Skip to content

Commit f77c307

Browse files
authored
Merge pull request #54 from mvorisek/fix_53
Fix plugin config must be kept after upgrade/downgrade
2 parents 2adeb2a + a762400 commit f77c307

7 files changed

Lines changed: 62 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,16 @@ jobs:
116116
cd test-composer/vendor/roundcube/roundcubemail
117117
ls -lah plugins/acl/config.*
118118
if [ ! -f plugins/acl/config.inc.php ]; then echo 'Config file was not created' && exit 1; fi
119+
120+
- name: Test update - install plugin
121+
run: |
122+
cd test-composer
123+
echo '// xxx no config update xxx' >> vendor/roundcube/roundcubemail/plugins/carddav/config.inc.php
124+
composer update -v --prefer-dist --no-interaction --no-progress roundcube/carddav --prefer-lowest
125+
126+
- name: Test update - verify install
127+
run: |
128+
cd test-composer
129+
ls -lah vendor/roundcube/roundcubemail/plugins/carddav/config.*
130+
if [ ! -f vendor/roundcube/roundcubemail/plugins/carddav/config.inc.php ]; then echo 'Config file was deleted' && exit 1; fi
131+
if ! grep -Fq 'xxx no config update xxx' vendor/roundcube/roundcubemail/plugins/carddav/config.inc.php; then echo 'Config file was replaced' && exit 1; fi

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
],
2020
"require": {
2121
"php": ">=7.3 <8.4",
22-
"composer-plugin-api": "^1.0 || ^2.0",
22+
"composer-plugin-api": "^2.1",
2323
"roundcube/roundcubemail": "*"
2424
},
2525
"require-dev": {
26-
"composer/composer": "^2.0",
26+
"composer/composer": "^2.1",
2727
"ergebnis/composer-normalize": "^2.13",
2828
"friendsofphp/php-cs-fixer": "^3.0",
2929
"phpstan/extension-installer": "^1.1",

phpstan.neon.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ includes:
33

44
parameters:
55
level: 4
6+
checkMissingOverrideMethodAttribute: true
67
paths:
78
- .
89
excludePaths:

src/ExtensionInstaller.php

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Roundcube\Composer;
44

5+
use Composer\Installer\InstallationManager;
56
use Composer\Installer\LibraryInstaller;
67
use Composer\Package\PackageInterface;
78
use Composer\Package\Version\VersionParser;
@@ -35,23 +36,41 @@ protected function setRoundcubemailInstallPath(InstalledRepositoryInterface $ins
3536

3637
if ($roundcubemailPackage === $rootPackage) { // $this->getInstallPath($package) does not work for root package
3738
$this->initializeVendorDir();
38-
$this->roundcubemailInstallPath = dirname($this->vendorDir);
39+
$installPath = dirname($this->vendorDir);
3940
} else {
40-
$this->roundcubemailInstallPath = $this->getInstallPath($roundcubemailPackage);
41+
$installPath = $this->getInstallPath($roundcubemailPackage);
42+
}
43+
44+
if ($this->roundcubemailInstallPath === null) {
45+
$this->roundcubemailInstallPath = $installPath;
46+
} elseif ($this->roundcubemailInstallPath !== $installPath) {
47+
throw new \Exception('Install path of "roundcube/roundcubemail" package has unexpectedly changed');
4148
}
4249
}
4350

4451
protected function getRoundcubemailInstallPath(): string
4552
{
53+
// install path is not set at composer download phase
54+
// never assume any path, but for this known composer behaviour get it from backtrace instead
55+
if ($this->roundcubemailInstallPath === null) {
56+
$backtrace = debug_backtrace();
57+
foreach ($backtrace as $frame) {
58+
// relies on https://github.com/composer/composer/blob/2.7.4/src/Composer/Installer/InstallationManager.php#L243
59+
if (($frame['object'] ?? null) instanceof InstallationManager
60+
&& $frame['function'] === 'downloadAndExecuteBatch'
61+
) {
62+
$this->setRoundcubemailInstallPath($frame['args'][0]);
63+
}
64+
}
65+
}
66+
4667
return $this->roundcubemailInstallPath;
4768
}
4869

70+
#[\Override]
4971
public function getInstallPath(PackageInterface $package)
5072
{
51-
if (
52-
!$this->supports($package->getType())
53-
|| $this->roundcubemailInstallPath === null // install path is not known at download phase
54-
) {
73+
if (!$this->supports($package->getType())) {
5574
return parent::getInstallPath($package);
5675
}
5776

@@ -63,13 +82,21 @@ public function getInstallPath(PackageInterface $package)
6382

6483
private function initializeRoundcubemailEnvironment(): void
6584
{
66-
// initialize Roundcube environment
6785
if (!defined('INSTALL_PATH')) {
6886
define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
6987
}
7088
require_once INSTALL_PATH . 'program/include/iniset.php';
7189
}
7290

91+
#[\Override]
92+
public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
93+
{
94+
$this->setRoundcubemailInstallPath($repo);
95+
96+
return parent::isInstalled($repo, $package);
97+
}
98+
99+
#[\Override]
73100
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
74101
{
75102
$this->setRoundcubemailInstallPath($repo);
@@ -131,6 +158,7 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
131158
return null;
132159
}
133160

161+
#[\Override]
134162
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
135163
{
136164
$this->setRoundcubemailInstallPath($repo);
@@ -196,6 +224,7 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
196224
return null;
197225
}
198226

227+
#[\Override]
199228
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
200229
{
201230
$this->setRoundcubemailInstallPath($repo);
@@ -237,6 +266,7 @@ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $
237266
return null;
238267
}
239268

269+
#[\Override]
240270
public function supports($packageType)
241271
{
242272
return $packageType === $this->composer_type;

src/PluginInstaller.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ class PluginInstaller extends ExtensionInstaller
66
{
77
protected $composer_type = 'roundcube-plugin';
88

9+
#[\Override]
910
public function getVendorDir()
1011
{
1112
return $this->getRoundcubemailInstallPath() . \DIRECTORY_SEPARATOR . 'plugins';
1213
}
1314

15+
#[\Override]
1416
protected function confirmInstall($package_name)
1517
{
1618
$config = $this->composer->getConfig()->get('roundcube');
@@ -24,6 +26,7 @@ protected function confirmInstall($package_name)
2426
return $answer;
2527
}
2628

29+
#[\Override]
2730
protected function getConfig($package_name, $config, $add)
2831
{
2932
$cur_config = !empty($config['plugins'])

src/RoundcubeInstaller.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class RoundcubeInstaller implements PluginInterface
1111
private $extentions = [PluginInstaller::class, SkinInstaller::class];
1212
private $installers = [];
1313

14+
#[\Override]
1415
public function activate(Composer $composer, IOInterface $io)
1516
{
1617
foreach ($this->extentions as $extension) {
@@ -20,12 +21,14 @@ public function activate(Composer $composer, IOInterface $io)
2021
}
2122
}
2223

24+
#[\Override]
2325
public function deactivate(Composer $composer, IOInterface $io)
2426
{
2527
foreach ($this->installers as $installer) {
2628
$composer->getInstallationManager()->removeInstaller($installer);
2729
}
2830
}
2931

32+
#[\Override]
3033
public function uninstall(Composer $composer, IOInterface $io) {}
3134
}

src/SkinInstaller.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ class SkinInstaller extends ExtensionInstaller
66
{
77
protected $composer_type = 'roundcube-skin';
88

9+
#[\Override]
910
public function getVendorDir()
1011
{
1112
return $this->getRoundcubemailInstallPath() . \DIRECTORY_SEPARATOR . 'skins';
1213
}
1314

15+
#[\Override]
1416
protected function confirmInstall($package_name)
1517
{
1618
$config = $this->composer->getConfig()->get('roundcube');
@@ -24,6 +26,7 @@ protected function confirmInstall($package_name)
2426
return $answer;
2527
}
2628

29+
#[\Override]
2730
protected function getConfig($package_name, $config, $add)
2831
{
2932
$cur_config = !empty($config['skin'])

0 commit comments

Comments
 (0)