Skip to content

Commit 5916d6e

Browse files
authored
Merge pull request #51 from mvorisek/honor_composer_replace
Use composer InstalledRepository to determine install dir
2 parents da8b3a7 + d66380f commit 5916d6e

4 files changed

Lines changed: 66 additions & 49 deletions

File tree

phpstan.neon.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ parameters:
1616
-
1717
message: '~^Constant RCMAIL_VERSION not found\.$~'
1818
path: 'src/ExtensionInstaller.php'
19-
count: 3
19+
count: 1

src/ExtensionInstaller.php

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,81 @@
55
use Composer\Installer\LibraryInstaller;
66
use Composer\Package\PackageInterface;
77
use Composer\Package\Version\VersionParser;
8+
use Composer\Repository\InstalledRepository;
89
use Composer\Repository\InstalledRepositoryInterface;
10+
use Composer\Repository\RootPackageRepository;
911
use Composer\Util\Filesystem;
1012
use Composer\Util\ProcessExecutor;
1113
use React\Promise\PromiseInterface;
1214

1315
abstract class ExtensionInstaller extends LibraryInstaller
1416
{
17+
/** @var string|null */
18+
private $roundcubemailInstallPath;
19+
20+
/** @var string */
1521
protected $composer_type;
1622

17-
protected function getRoundcubemailInstallPath(): string
23+
protected function setRoundcubemailInstallPath(InstalledRepositoryInterface $installedRepo): void
1824
{
19-
$rootPackage = $this->composer->getPackage();
20-
if ($rootPackage->getName() === 'roundcube/roundcubemail') {
25+
// https://github.com/composer/composer/discussions/11927#discussioncomment-9116893
26+
$rootPackage = clone $this->composer->getPackage();
27+
$installedRepo = new InstalledRepository([
28+
$installedRepo,
29+
new RootPackageRepository($rootPackage),
30+
]);
31+
32+
$roundcubemailPackages = $installedRepo->findPackagesWithReplacersAndProviders('roundcube/roundcubemail');
33+
assert(count($roundcubemailPackages) === 1);
34+
$roundcubemailPackage = $roundcubemailPackages[0];
35+
36+
if ($roundcubemailPackage === $rootPackage) { // $this->getInstallPath($package) does not work for root package
2137
$this->initializeVendorDir();
22-
23-
return dirname($this->vendorDir);
38+
$this->roundcubemailInstallPath = dirname($this->vendorDir);
39+
} else {
40+
$this->roundcubemailInstallPath = $this->getInstallPath($roundcubemailPackage);
2441
}
42+
}
2543

26-
$roundcubemailPackage = $this->composer
27-
->getRepositoryManager()
28-
->findPackage('roundcube/roundcubemail', '*');
29-
30-
return $this->getInstallPath($roundcubemailPackage);
44+
protected function getRoundcubemailInstallPath(): string
45+
{
46+
return $this->roundcubemailInstallPath;
3147
}
3248

3349
public function getInstallPath(PackageInterface $package)
3450
{
35-
if (!$this->supports($package->getType())) {
51+
if (
52+
!$this->supports($package->getType())
53+
|| $this->roundcubemailInstallPath === null // install path is not known at download phase
54+
) {
3655
return parent::getInstallPath($package);
3756
}
3857

3958
$vendorDir = $this->getVendorDir();
4059

41-
return sprintf('%s/%s', $vendorDir, $this->getPackageName($package));
60+
return $vendorDir . \DIRECTORY_SEPARATOR
61+
. str_replace('/', \DIRECTORY_SEPARATOR, $this->getPackageName($package));
4262
}
4363

44-
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
64+
private function initializeRoundcubemailEnvironment(): void
4565
{
4666
// initialize Roundcube environment
4767
if (!defined('INSTALL_PATH')) {
4868
define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
4969
}
5070
require_once INSTALL_PATH . 'program/include/iniset.php';
71+
}
5172

73+
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
74+
{
75+
$this->setRoundcubemailInstallPath($repo);
76+
$this->initializeRoundcubemailEnvironment();
5277
$this->rcubeVersionCheck($package);
5378

5479
$postInstall = function () use ($package) {
5580
$config_file = $this->rcubeConfigFile();
5681
$package_name = $this->getPackageName($package);
57-
$package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
82+
$package_dir = $this->getInstallPath($package);
5883
$extra = $package->getExtra();
5984

6085
if (is_writable($config_file) && \PHP_SAPI === 'cli' && $this->confirmInstall($package_name)) {
@@ -83,12 +108,7 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
83108
if ($sqldir = realpath($package_dir . \DIRECTORY_SEPARATOR . $extra['roundcube']['sql-dir'])) {
84109
$this->io->write("<info>Running database initialization script for {$package_name}</info>");
85110

86-
$roundcube_version = self::versionNormalize(RCMAIL_VERSION);
87-
if (self::versionCompare($roundcube_version, '1.2.0', '>=')) {
88-
\rcmail_utils::db_init($sqldir);
89-
} else {
90-
throw new \Exception('Database initialization failed. Roundcube 1.2.0 or above required.');
91-
}
111+
\rcmail_utils::db_init($sqldir);
92112
}
93113
}
94114

@@ -113,31 +133,28 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa
113133

114134
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
115135
{
116-
// initialize Roundcube environment
117-
if (!defined('INSTALL_PATH')) {
118-
define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
119-
}
120-
require_once INSTALL_PATH . 'program/include/iniset.php';
121-
136+
$this->setRoundcubemailInstallPath($repo);
137+
$this->initializeRoundcubemailEnvironment();
122138
$this->rcubeVersionCheck($target);
123139

124140
$extra = $target->getExtra();
125141
$fs = new Filesystem();
126142

127143
// backup persistent files e.g. config.inc.php
128-
$package_name = $this->getPackageName($initial);
129-
$package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
144+
$package_dir = $this->getInstallPath($initial);
130145
$temp_dir = $package_dir . '-' . sprintf('%010d%010d', mt_rand(), mt_rand());
131146

132147
// make a backup of existing files (for restoring persistent files)
133148
$fs->copy($package_dir, $temp_dir);
134149

135150
$postUpdate = function () use ($target, $extra, $fs, $temp_dir) {
136151
$package_name = $this->getPackageName($target);
137-
$package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
152+
$package_dir = $this->getInstallPath($target);
138153

139154
// restore persistent files
140-
$persistent_files = !empty($extra['roundcube']['persistent-files']) ? $extra['roundcube']['persistent-files'] : ['config.inc.php'];
155+
$persistent_files = !empty($extra['roundcube']['persistent-files'])
156+
? $extra['roundcube']['persistent-files']
157+
: ['config.inc.php'];
141158
foreach ($persistent_files as $file) {
142159
$path = $temp_dir . \DIRECTORY_SEPARATOR . $file;
143160
if (is_readable($path)) {
@@ -156,12 +173,7 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
156173
if ($sqldir = realpath($package_dir . \DIRECTORY_SEPARATOR . $extra['roundcube']['sql-dir'])) {
157174
$this->io->write("<info>Updating database schema for {$package_name}</info>");
158175

159-
$roundcube_version = self::versionNormalize(RCMAIL_VERSION);
160-
if (self::versionCompare($roundcube_version, '1.2.0', '>=')) {
161-
\rcmail_utils::db_update($sqldir, $package_name);
162-
} else {
163-
throw new \Exception('Database update failed. Roundcube 1.2.0 or above required.');
164-
}
176+
\rcmail_utils::db_update($sqldir, $package_name);
165177
}
166178
}
167179

@@ -186,18 +198,15 @@ public function update(InstalledRepositoryInterface $repo, PackageInterface $ini
186198

187199
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
188200
{
189-
// initialize Roundcube environment
190-
if (!defined('INSTALL_PATH')) {
191-
define('INSTALL_PATH', $this->getRoundcubemailInstallPath() . '/');
192-
}
193-
require_once INSTALL_PATH . 'program/include/iniset.php';
201+
$this->setRoundcubemailInstallPath($repo);
202+
$this->initializeRoundcubemailEnvironment();
194203

195204
$config = $this->composer->getConfig()->get('roundcube');
196205

197206
$postUninstall = function () use ($package, $config) {
198207
// post-uninstall: deactivate package
199208
$package_name = $this->getPackageName($package);
200-
$package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
209+
$package_dir = $this->getInstallPath($package);
201210

202211
$this->rcubeAlterConfig($package_name, false);
203212

@@ -380,7 +389,7 @@ private function rcubeRunScript($script, PackageInterface $package)
380389
{
381390
$package_name = $this->getPackageName($package);
382391
$package_type = $package->getType();
383-
$package_dir = $this->getVendorDir() . \DIRECTORY_SEPARATOR . $package_name;
392+
$package_dir = $this->getInstallPath($package);
384393

385394
// check for executable shell script
386395
if (($scriptfile = realpath($package_dir . \DIRECTORY_SEPARATOR . $script)) && is_executable($scriptfile)) {
@@ -404,7 +413,7 @@ private function rcubeRunScript($script, PackageInterface $package)
404413
}
405414

406415
/**
407-
* normalize Roundcube version string.
416+
* Normalize Roundcube version string.
408417
*/
409418
private static function versionNormalize(string $version): string
410419
{

src/PluginInstaller.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ protected function confirmInstall($package_name)
2626

2727
protected function getConfig($package_name, $config, $add)
2828
{
29-
$cur_config = !empty($config['plugins']) ? ((array) $config['plugins']) : [];
29+
$cur_config = !empty($config['plugins'])
30+
? ((array) $config['plugins'])
31+
: [];
3032
$new_config = $cur_config;
3133

3234
if ($add && !in_array($package_name, $new_config, true)) {
@@ -36,7 +38,9 @@ protected function getConfig($package_name, $config, $add)
3638
}
3739

3840
if ($new_config !== $cur_config) {
39-
$config_val = count($new_config) > 0 ? "[\n\t'" . implode("',\n\t'", $new_config) . "',\n];" : '[];';
41+
$config_val = count($new_config) > 0
42+
? "[\n\t'" . implode("',\n\t'", $new_config) . "',\n];"
43+
: '[];';
4044
$result = ['plugins', $config_val];
4145
} else {
4246
$result = false;

src/SkinInstaller.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ protected function confirmInstall($package_name)
2626

2727
protected function getConfig($package_name, $config, $add)
2828
{
29-
$cur_config = !empty($config['skin']) ? $config['skin'] : null;
29+
$cur_config = !empty($config['skin'])
30+
? $config['skin']
31+
: null;
3032
$new_config = $cur_config;
3133

3234
if ($add && $new_config !== $package_name) {
@@ -36,7 +38,9 @@ protected function getConfig($package_name, $config, $add)
3638
}
3739

3840
if ($new_config !== $cur_config) {
39-
$config_val = !empty($new_config) ? "'{$new_config}';" : null;
41+
$config_val = !empty($new_config)
42+
? "'{$new_config}';"
43+
: null;
4044
$result = ['skin', $config_val];
4145
} else {
4246
$result = false;

0 commit comments

Comments
 (0)