Skip to content

Commit

Permalink
Merge pull request #51 from mvorisek/honor_composer_replace
Browse files Browse the repository at this point in the history
Use composer InstalledRepository to determine install dir
  • Loading branch information
alecpl authored Apr 21, 2024
2 parents da8b3a7 + d66380f commit 5916d6e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 49 deletions.
2 changes: 1 addition & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ parameters:
-
message: '~^Constant RCMAIL_VERSION not found\.$~'
path: 'src/ExtensionInstaller.php'
count: 3
count: 1
97 changes: 53 additions & 44 deletions src/ExtensionInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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("<info>Running database initialization script for {$package_name}</info>");

$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);
}
}

Expand All @@ -113,31 +133,28 @@ 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)
$fs->copy($package_dir, $temp_dir);

$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)) {
Expand All @@ -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("<info>Updating database schema for {$package_name}</info>");

$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);
}
}

Expand All @@ -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);

Expand Down Expand Up @@ -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)) {
Expand All @@ -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
{
Expand Down
8 changes: 6 additions & 2 deletions src/PluginInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions src/SkinInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand Down

0 comments on commit 5916d6e

Please sign in to comment.