diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index f27b06b..3812e72 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -16,4 +16,4 @@ parameters:
-
message: '~^Constant RCMAIL_VERSION not found\.$~'
path: 'src/ExtensionInstaller.php'
- count: 3
+ count: 1
diff --git a/src/ExtensionInstaller.php b/src/ExtensionInstaller.php
index 33fff66..8cfbd61 100644
--- a/src/ExtensionInstaller.php
+++ b/src/ExtensionInstaller.php
@@ -5,56 +5,81 @@
use Composer\Installer\LibraryInstaller;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
+use Composer\Repository\InstalledRepository;
use Composer\Repository\InstalledRepositoryInterface;
+use Composer\Repository\RootPackageRepository;
use Composer\Util\Filesystem;
use Composer\Util\ProcessExecutor;
use React\Promise\PromiseInterface;
abstract class ExtensionInstaller extends LibraryInstaller
{
+ /** @var string|null */
+ private $roundcubemailInstallPath;
+
+ /** @var string */
protected $composer_type;
- protected function getRoundcubemailInstallPath(): string
+ protected function setRoundcubemailInstallPath(InstalledRepositoryInterface $installedRepo): void
{
- $rootPackage = $this->composer->getPackage();
- if ($rootPackage->getName() === 'roundcube/roundcubemail') {
+ // https://github.com/composer/composer/discussions/11927#discussioncomment-9116893
+ $rootPackage = clone $this->composer->getPackage();
+ $installedRepo = new InstalledRepository([
+ $installedRepo,
+ new RootPackageRepository($rootPackage),
+ ]);
+
+ $roundcubemailPackages = $installedRepo->findPackagesWithReplacersAndProviders('roundcube/roundcubemail');
+ assert(count($roundcubemailPackages) === 1);
+ $roundcubemailPackage = $roundcubemailPackages[0];
+
+ if ($roundcubemailPackage === $rootPackage) { // $this->getInstallPath($package) does not work for root package
$this->initializeVendorDir();
-
- return dirname($this->vendorDir);
+ $this->roundcubemailInstallPath = dirname($this->vendorDir);
+ } else {
+ $this->roundcubemailInstallPath = $this->getInstallPath($roundcubemailPackage);
}
+ }
- $roundcubemailPackage = $this->composer
- ->getRepositoryManager()
- ->findPackage('roundcube/roundcubemail', '*');
-
- return $this->getInstallPath($roundcubemailPackage);
+ protected function getRoundcubemailInstallPath(): string
+ {
+ return $this->roundcubemailInstallPath;
}
public function getInstallPath(PackageInterface $package)
{
- if (!$this->supports($package->getType())) {
+ if (
+ !$this->supports($package->getType())
+ || $this->roundcubemailInstallPath === null // install path is not known at download phase
+ ) {
return parent::getInstallPath($package);
}
$vendorDir = $this->getVendorDir();
- return sprintf('%s/%s', $vendorDir, $this->getPackageName($package));
+ return $vendorDir . \DIRECTORY_SEPARATOR
+ . str_replace('/', \DIRECTORY_SEPARATOR, $this->getPackageName($package));
}
- public function install(InstalledRepositoryInterface $repo, 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';
+ }
+ public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
+ {
+ $this->setRoundcubemailInstallPath($repo);
+ $this->initializeRoundcubemailEnvironment();
$this->rcubeVersionCheck($package);
$postInstall = function () use ($package) {
$config_file = $this->rcubeConfigFile();
$package_name = $this->getPackageName($package);
- $package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
+ $package_dir = $this->getInstallPath($package);
$extra = $package->getExtra();
if (is_writable($config_file) && \PHP_SAPI === 'cli' && $this->confirmInstall($package_name)) {
@@ -83,12 +108,7 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
if ($sqldir = realpath($package_dir . \DIRECTORY_SEPARATOR . $extra['roundcube']['sql-dir'])) {
$this->io->write("Running database initialization script for {$package_name}");
- $roundcube_version = self::versionNormalize(RCMAIL_VERSION);
- if (self::versionCompare($roundcube_version, '1.2.0', '>=')) {
- \rcmail_utils::db_init($sqldir);
- } else {
- throw new \Exception('Database initialization failed. Roundcube 1.2.0 or above required.');
- }
+ \rcmail_utils::db_init($sqldir);
}
}
@@ -113,20 +133,15 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
{
- // initialize Roundcube environment
- if (!defined('INSTALL_PATH')) {
- define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
- }
- require_once INSTALL_PATH . 'program/include/iniset.php';
-
+ $this->setRoundcubemailInstallPath($repo);
+ $this->initializeRoundcubemailEnvironment();
$this->rcubeVersionCheck($target);
$extra = $target->getExtra();
$fs = new Filesystem();
// backup persistent files e.g. config.inc.php
- $package_name = $this->getPackageName($initial);
- $package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
+ $package_dir = $this->getInstallPath($initial);
$temp_dir = $package_dir . '-' . sprintf('%010d%010d', mt_rand(), mt_rand());
// make a backup of existing files (for restoring persistent files)
@@ -134,10 +149,12 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
$postUpdate = function () use ($target, $extra, $fs, $temp_dir) {
$package_name = $this->getPackageName($target);
- $package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
+ $package_dir = $this->getInstallPath($target);
// restore persistent files
- $persistent_files = !empty($extra['roundcube']['persistent-files']) ? $extra['roundcube']['persistent-files'] : ['config.inc.php'];
+ $persistent_files = !empty($extra['roundcube']['persistent-files'])
+ ? $extra['roundcube']['persistent-files']
+ : ['config.inc.php'];
foreach ($persistent_files as $file) {
$path = $temp_dir . \DIRECTORY_SEPARATOR . $file;
if (is_readable($path)) {
@@ -156,12 +173,7 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
if ($sqldir = realpath($package_dir . \DIRECTORY_SEPARATOR . $extra['roundcube']['sql-dir'])) {
$this->io->write("Updating database schema for {$package_name}");
- $roundcube_version = self::versionNormalize(RCMAIL_VERSION);
- if (self::versionCompare($roundcube_version, '1.2.0', '>=')) {
- \rcmail_utils::db_update($sqldir, $package_name);
- } else {
- throw new \Exception('Database update failed. Roundcube 1.2.0 or above required.');
- }
+ \rcmail_utils::db_update($sqldir, $package_name);
}
}
@@ -186,18 +198,15 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{
- // initialize Roundcube environment
- if (!defined('INSTALL_PATH')) {
- define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
- }
- require_once INSTALL_PATH . 'program/include/iniset.php';
+ $this->setRoundcubemailInstallPath($repo);
+ $this->initializeRoundcubemailEnvironment();
$config = $this->composer->getConfig()->get('roundcube');
$postUninstall = function () use ($package, $config) {
// post-uninstall: deactivate package
$package_name = $this->getPackageName($package);
- $package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
+ $package_dir = $this->getInstallPath($package);
$this->rcubeAlterConfig($package_name, false);
@@ -380,7 +389,7 @@ private function rcubeRunScript($script, PackageInterface $package)
{
$package_name = $this->getPackageName($package);
$package_type = $package->getType();
- $package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
+ $package_dir = $this->getInstallPath($package);
// check for executable shell script
if (($scriptfile = realpath($package_dir . \DIRECTORY_SEPARATOR . $script)) && is_executable($scriptfile)) {
@@ -404,7 +413,7 @@ private function rcubeRunScript($script, PackageInterface $package)
}
/**
- * normalize Roundcube version string.
+ * Normalize Roundcube version string.
*/
private static function versionNormalize(string $version): string
{
diff --git a/src/PluginInstaller.php b/src/PluginInstaller.php
index 6bd2c9f..e09fbe4 100644
--- a/src/PluginInstaller.php
+++ b/src/PluginInstaller.php
@@ -26,7 +26,9 @@ protected function confirmInstall($package_name)
protected function getConfig($package_name, $config, $add)
{
- $cur_config = !empty($config['plugins']) ? ((array) $config['plugins']) : [];
+ $cur_config = !empty($config['plugins'])
+ ? ((array) $config['plugins'])
+ : [];
$new_config = $cur_config;
if ($add && !in_array($package_name, $new_config, true)) {
@@ -36,7 +38,9 @@ protected function getConfig($package_name, $config, $add)
}
if ($new_config !== $cur_config) {
- $config_val = count($new_config) > 0 ? "[\n\t'" . implode("',\n\t'", $new_config) . "',\n];" : '[];';
+ $config_val = count($new_config) > 0
+ ? "[\n\t'" . implode("',\n\t'", $new_config) . "',\n];"
+ : '[];';
$result = ['plugins', $config_val];
} else {
$result = false;
diff --git a/src/SkinInstaller.php b/src/SkinInstaller.php
index 5854bf9..4d9cee5 100644
--- a/src/SkinInstaller.php
+++ b/src/SkinInstaller.php
@@ -26,7 +26,9 @@ protected function confirmInstall($package_name)
protected function getConfig($package_name, $config, $add)
{
- $cur_config = !empty($config['skin']) ? $config['skin'] : null;
+ $cur_config = !empty($config['skin'])
+ ? $config['skin']
+ : null;
$new_config = $cur_config;
if ($add && $new_config !== $package_name) {
@@ -36,7 +38,9 @@ protected function getConfig($package_name, $config, $add)
}
if ($new_config !== $cur_config) {
- $config_val = !empty($new_config) ? "'{$new_config}';" : null;
+ $config_val = !empty($new_config)
+ ? "'{$new_config}';"
+ : null;
$result = ['skin', $config_val];
} else {
$result = false;