-
-
Notifications
You must be signed in to change notification settings - Fork 46
Unable to retrieve the good alias for PHP_CodeSniffer package by API #458
Description
Hello @theseer
Perharps you can help me to confirm or not that the Phive API calls are on right sequence !
Hope it will be enough ? Tell me if you need more info !
Current Context
As author of package https://github.com/llaville/captainhook-bin-plugin (a CaptainHook Plugin), before to release officially the first version on Composer, I wanted to add support for PHIVE too !
Actually if a Composer package is not installed the action is skipped by my plugin (auto-detection).
I wanted to have the same feature with PHIVE.
I've tried many solutions, and found a possible good one, but I'm not sure (if I used the good API calls): Could you check the sequence please ?
Source Code is provide at end of report.
Expected behaviour
Package is auto-detected (see my solution at end of this report with source code provided), respect version constraint, and command ./tools/phpcs is run !
Note
PHP_CodeSniffer is well detected and run as expected (I've put a var_dump not well indented that raise the error)
Current behaviour
Without my "patch", the Package is not detected as installed (even if it's TRUE : see phive status), and action is skipped (my plugin goal).
Caution
PHP_CodeSniffer is not detected because the first alias retrieved by \PharIo\Phive\SourcesList::getAliasForComposerAlias is phpcbf (and not phpcs)
See https://github.com/phar-io/phive/blob/0.16.0/src/shared/sources/SourcesList.php#L66 only the first alias as provided
PHIVE installation
I've locally installed the PHP_CodeSniffer as follow :
phive install --target ./tools phpcs@^4.0The local .phive/phars.xml file contents is :
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpcs" version="^4.0" installed="4.0.1" location="././tools/phpcs" copy="false"/>
</phive>Important
Here the alias (phpcs) is the one that expected !
Confirmed by phive status command :
Phive 0.16.0 - Copyright (C) 2015-2026 by Arne Blankerts, Sebastian Heuer and Contributors
PHARs configured in project:
Alias/URL Version Constraint Installed Location Key Ids
phpcs ^4.0 4.0.1 /shared/backups/bartlett/captainhook-bin-plugin/tools/phpcs 97B02DD8E5071466
Source Code
Now, after a long introduction (sorry, but I want to be clear as much as possible), the code (PHIVE API calls , I used to auto-detect that the tool is correctly installed).
As for Composer Condition the key to check is the package identifier. For example : squizlabs/php_codesniffer for PHPCS
Tip
My Solution to by-pass the not found alias name candidate :
if (in_array('phpcbf', $aliases, true)) {
// "squizlabs/php_codesniffer" is the only Composer package that provide two aliases (for current Phive v0.16)
// but only the first one is retrieved by \PharIo\Phive\SourcesList::getAliasForComposerAlias
// @see https://github.com/phar-io/phive/blob/0.16.0/src/shared/sources/SourcesList.php#L66
$aliases[] = 'phpcs';
}Source Code
<?php
declare(strict_types=1);
namespace Bartlett\CaptainHookBinPlugin\Condition;
use CaptainHook\App\Console\IO;
use CaptainHook\App\Hook\Condition;
use Composer\InstalledVersions;
use Composer\Semver\Semver;
use PharIo\Phive\Cli\Request;
use PharIo\Phive\ComposerAlias;
use PharIo\Phive\EnvironmentLocator;
use PharIo\Phive\Factory;
use PharIo\Phive\LocalPhiveXmlConfig;
use PharIo\Phive\PhiveXmlConfigFileLocator;
use PharIo\Phive\StatusCommandConfig;
use PharIo\Phive\XmlFile;
use PharIo\Version\VersionConstraintParser;
use SebastianFeldmann\Git\Repository;
use Throwable;
use function in_array;
use const PHP_OS;
class PharInstalled implements Condition
{
public function __construct(private string $packageName, private string $constraint = '*')
{
}
public function isTrue(IO $io, Repository $repository): bool
{
$isPhiveAvailable = InstalledVersions::isInstalled('phar-io/phive');
if (!$isPhiveAvailable) {
$io->write(
' <fg=cyan>Applied: PHIVE is not installed</>',
true,
IO::VERBOSE,
);
return false;
}
$request = new Request([]);
$factory = new Factory($request);
// \PharIo\Phive\Factory::getEnvironment
$environment = (new EnvironmentLocator())->getEnvironment(PHP_OS);
// \PharIo\Phive\Factory::getConfig
$config = $factory->getConfig();
// \PharIo\Phive\Factory::getOutput
$output = $factory->getOutput();
// \PharIo\Phive\Factory::getPhiveXmlConfigFileLocator
$xmlConfigFileLocator = new PhiveXmlConfigFileLocator(
$environment,
$config,
$output
);
$xmlConfig = new LocalPhiveXmlConfig(
new XmlFile(
$xmlConfigFileLocator->getFile(),
'https://phar.io/phive',
'phive'
),
new VersionConstraintParser(),
$environment
);
$pharRegistry = $factory->getPharRegistry();
$statusCommandConfig = new StatusCommandConfig(
$request->getOptions(),
$xmlConfig,
$pharRegistry
);
// \PharIo\Phive\Factory::getSourcesList
$sourcesList = $factory->getRemoteSourcesListFileLoader()->load();
$isApplied = false;
$aliases = [];
try {
$aliases[] = $sourcesList->getAliasForComposerAlias(new ComposerAlias($this->packageName));
if (in_array('phpcbf', $aliases, true)) {
// "squizlabs/php_codesniffer" is the only Composer package that provide two aliases (for current Phive v0.16)
// but only the first one is retrieved by \PharIo\Phive\SourcesList::getAliasForComposerAlias
// @see https://github.com/phar-io/phive/blob/0.16.0/src/shared/sources/SourcesList.php#L66
//$aliases[] = 'phpcs';
}
foreach ($statusCommandConfig->getPhars() as $phar) {
if (!in_array($phar->getName(), $aliases, true)) {
continue;
}
if (!$phar->isInstalled()) {
continue;
}
$versionInstalled = $phar->getInstalledVersion();
\var_dump($versionInstalled->getOriginalString(), $phar->getVersionConstraint()->asString());
$isApplied = Semver::satisfies($versionInstalled->getOriginalString(), $phar->getVersionConstraint()->asString());
if ($isApplied) {
break;
}
}
} catch (Throwable $exception) {
}
$io->write(
sprintf(
' <fg=cyan>Applied: Package %s</> %s (with constraint "%s")',
$isApplied ? 'installed' : 'not installed',
$this->packageName,
$this->constraint
),
true,
IO::VERBOSE,
);
return $isApplied;
}
}