Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix plugin config must be kept after upgrade/downgrade #54

Merged
merged 4 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,16 @@ jobs:
cd test-composer/vendor/roundcube/roundcubemail
ls -lah plugins/acl/config.*
if [ ! -f plugins/acl/config.inc.php ]; then echo 'Config file was not created' && exit 1; fi

- name: Test update - install plugin
run: |
cd test-composer
echo '// xxx no config update xxx' >> vendor/roundcube/roundcubemail/plugins/carddav/config.inc.php
composer update -v --prefer-dist --no-interaction --no-progress roundcube/carddav --prefer-lowest

- name: Test update - verify install
run: |
cd test-composer
ls -lah vendor/roundcube/roundcubemail/plugins/carddav/config.*
if [ ! -f vendor/roundcube/roundcubemail/plugins/carddav/config.inc.php ]; then echo 'Config file was deleted' && exit 1; fi
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
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
],
"require": {
"php": ">=7.3 <8.4",
"composer-plugin-api": "^1.0 || ^2.0",
"composer-plugin-api": "^2.1",
"roundcube/roundcubemail": "*"
},
"require-dev": {
"composer/composer": "^2.0",
"composer/composer": "^2.1",
"ergebnis/composer-normalize": "^2.13",
"friendsofphp/php-cs-fixer": "^3.0",
"phpstan/extension-installer": "^1.1",
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ includes:

parameters:
level: 4
checkMissingOverrideMethodAttribute: true
paths:
- .
excludePaths:
Expand Down
44 changes: 37 additions & 7 deletions src/ExtensionInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Roundcube\Composer;

use Composer\Installer\InstallationManager;
use Composer\Installer\LibraryInstaller;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
Expand Down Expand Up @@ -35,23 +36,41 @@ protected function setRoundcubemailInstallPath(InstalledRepositoryInterface $ins

if ($roundcubemailPackage === $rootPackage) { // $this->getInstallPath($package) does not work for root package
$this->initializeVendorDir();
$this->roundcubemailInstallPath = dirname($this->vendorDir);
$installPath = dirname($this->vendorDir);
} else {
$this->roundcubemailInstallPath = $this->getInstallPath($roundcubemailPackage);
$installPath = $this->getInstallPath($roundcubemailPackage);
}

if ($this->roundcubemailInstallPath === null) {
$this->roundcubemailInstallPath = $installPath;
} elseif ($this->roundcubemailInstallPath !== $installPath) {
throw new \Exception('Install path of "roundcube/roundcubemail" package has unexpectedly changed');
}
}

protected function getRoundcubemailInstallPath(): string
{
// install path is not set at composer download phase
// never assume any path, but for this known composer behaviour get it from backtrace instead
if ($this->roundcubemailInstallPath === null) {
$backtrace = debug_backtrace();
foreach ($backtrace as $frame) {
// relies on https://github.com/composer/composer/blob/2.7.4/src/Composer/Installer/InstallationManager.php#L243
if (($frame['object'] ?? null) instanceof InstallationManager
&& $frame['function'] === 'downloadAndExecuteBatch'
) {
$this->setRoundcubemailInstallPath($frame['args'][0]);
}
}
}

return $this->roundcubemailInstallPath;
}

#[\Override]
public function getInstallPath(PackageInterface $package)
{
if (
!$this->supports($package->getType())
|| $this->roundcubemailInstallPath === null // install path is not known at download phase
) {
if (!$this->supports($package->getType())) {
return parent::getInstallPath($package);
}

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

private function initializeRoundcubemailEnvironment(): void
{
// initialize Roundcube environment
if (!defined('INSTALL_PATH')) {
define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
}
require_once INSTALL_PATH . 'program/include/iniset.php';
}

#[\Override]
public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
{
$this->setRoundcubemailInstallPath($repo);

return parent::isInstalled($repo, $package);
}

#[\Override]
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
{
$this->setRoundcubemailInstallPath($repo);
Expand Down Expand Up @@ -131,6 +158,7 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
return null;
}

#[\Override]
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
{
$this->setRoundcubemailInstallPath($repo);
Expand Down Expand Up @@ -196,6 +224,7 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
return null;
}

#[\Override]
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{
$this->setRoundcubemailInstallPath($repo);
Expand Down Expand Up @@ -237,6 +266,7 @@ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $
return null;
}

#[\Override]
public function supports($packageType)
{
return $packageType === $this->composer_type;
Expand Down
3 changes: 3 additions & 0 deletions src/PluginInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ class PluginInstaller extends ExtensionInstaller
{
protected $composer_type = 'roundcube-plugin';

#[\Override]
public function getVendorDir()
{
return $this->getRoundcubemailInstallPath() . \DIRECTORY_SEPARATOR . 'plugins';
}

#[\Override]
protected function confirmInstall($package_name)
{
$config = $this->composer->getConfig()->get('roundcube');
Expand All @@ -24,6 +26,7 @@ protected function confirmInstall($package_name)
return $answer;
}

#[\Override]
protected function getConfig($package_name, $config, $add)
{
$cur_config = !empty($config['plugins'])
Expand Down
3 changes: 3 additions & 0 deletions src/RoundcubeInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class RoundcubeInstaller implements PluginInterface
private $extentions = [PluginInstaller::class, SkinInstaller::class];
private $installers = [];

#[\Override]
public function activate(Composer $composer, IOInterface $io)
{
foreach ($this->extentions as $extension) {
Expand All @@ -20,12 +21,14 @@ public function activate(Composer $composer, IOInterface $io)
}
}

#[\Override]
public function deactivate(Composer $composer, IOInterface $io)
{
foreach ($this->installers as $installer) {
$composer->getInstallationManager()->removeInstaller($installer);
}
}

#[\Override]
public function uninstall(Composer $composer, IOInterface $io) {}
}
3 changes: 3 additions & 0 deletions src/SkinInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ class SkinInstaller extends ExtensionInstaller
{
protected $composer_type = 'roundcube-skin';

#[\Override]
public function getVendorDir()
{
return $this->getRoundcubemailInstallPath() . \DIRECTORY_SEPARATOR . 'skins';
}

#[\Override]
protected function confirmInstall($package_name)
{
$config = $this->composer->getConfig()->get('roundcube');
Expand All @@ -24,6 +26,7 @@ protected function confirmInstall($package_name)
return $answer;
}

#[\Override]
protected function getConfig($package_name, $config, $add)
{
$cur_config = !empty($config['skin'])
Expand Down