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

Use different PHP version information for PHPCS and PHPStan #23

Merged
merged 1 commit into from
Feb 13, 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
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
"ext-xml": "*",
"composer-runtime-api": "^2.0",
"bamarni/composer-bin-plugin": "^1.8",
"composer/semver": "^3.3",
"composer/semver": "^3.4",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
"nette/neon": "^3.3",
"nikic/php-parser": "^4.15",
"nikic/php-parser": "^4.18",
"php-di/php-di": "^7.0.1",
"slevomat/coding-standard": "^8.10.0",
"squizlabs/php_codesniffer": "^3.7.2",
Expand All @@ -47,10 +47,10 @@
"amphp/amp": "^v2.6.2",
"amphp/phpunit-util": "^2.0.0",
"amphp/process": "^v1.1.4",
"brianium/paratest": "^6.8.1",
"infection/infection": ">=0.26.16",
"mockery/mockery": "^1.5.1",
"phpunit/phpunit": "^9.5.28",
"brianium/paratest": "^6.11.0",
"infection/infection": ">=0.27.9",
"mockery/mockery": "^1.6.7",
"phpunit/phpunit": "^9.6.16",
"roave/security-advisories": "dev-latest",
"sebastianknott/hamcrest-object-accessor": "^3.0.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Extension\FileExtensionDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Fix\FixDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Multiprocess\MultiprocessDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\MinimalVersionDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\VersionDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Target\TargetDecorator;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Verbose\VerboseDecorator;
Expand All @@ -32,6 +33,7 @@ class EventDispatcherFactory
TargetDecorator::class,
VerboseDecorator::class,
MultiprocessDecorator::class,
MinimalVersionDecorator::class,
VersionDecorator::class,
];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use JsonException;
use Safe\Exceptions\FilesystemException;
use Zooroyal\CodingStandard\CommandLine\EnhancedFileInfo\EnhancedFileInfoFactory;
use Zooroyal\CodingStandard\CommandLine\Environment\Environment;

use function Safe\file_get_contents;

class ComposerInterpreter
{
public function __construct(
private readonly Environment $environment,
private readonly EnhancedFileInfoFactory $enhancedFileInfoFactory,
private readonly ConstraintToVersionConverter $constraintToVersionConverter,
) {
}

/**
* Get local php-version-constraints from root composer.json.
*
* @throws FilesystemException
* @throws JsonException
*/
public function getLocalPhpVersionConstraint(): string
{
$rootDirectory = $this->environment->getRootDirectory();
$path = $rootDirectory->getRealPath();
$composerFile = $this->enhancedFileInfoFactory->buildFromPath($path . '/composer.json');
$composerConfig = json_decode(
file_get_contents($composerFile->getRealPath()),
associative: true,
flags: JSON_THROW_ON_ERROR
);

$phpVersionConstraint = $composerConfig['config']['platform']['php']
?? $composerConfig['require']['php']
?? '*';

$phpVersionConstraintExtracted = $this->constraintToVersionConverter
->extractActualPhpVersion($phpVersionConstraint);

return $phpVersionConstraintExtracted;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use Composer\Semver\Semver;

use function Safe\preg_match;

class ConstraintToVersionConverter
{
/** @var array<string> */
private array $phpVersions = [];

public function __construct()
{
$phpVersionRanges = [
'7.4.' => '33',
'8.0.' => '27',
'8.1.' => '17',
'8.2.' => (explode('.', phpversion()))[2],
];

foreach ($phpVersionRanges as $phpVersionString => $phpMaxPatchVersion) {
$phpPatchLevels = range('0', $phpMaxPatchVersion);
foreach ($phpPatchLevels as $phpPatchLevel) {
$this->phpVersions[] = $phpVersionString . $phpPatchLevel;
}
}
}

/**
* Check if $phpVersionConstraint is a version number and return it or if we find a php version that satisfies
* the constraint.
*/
public function extractActualPhpVersion(string $phpVersionConstraint): string
{
if (preg_match('/^(\d+)(\.\d)?(\.\d)?$/', $phpVersionConstraint, $matches)) {
return $matches[1] . ($matches[2] ?? '.0') . ($matches[3] ?? '.0');
}

$minPhpVersion = '7.4.0';
foreach ($this->phpVersions as $phpVersion) {
if (SemVer::satisfies($phpVersion, $phpVersionConstraint)) {
$minPhpVersion = $phpVersion;
break;
}
}
return $minPhpVersion;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use Symfony\Component\Console\Output\OutputInterface;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\DecorateEvent;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\TerminalCommandDecorator;

class MinimalVersionDecorator extends TerminalCommandDecorator
{
private ?string $cachedMinPhpVersion = null;

public function __construct(
private readonly ConstraintToVersionConverter $constraintToVersionConverter,
private readonly ComposerInterpreter $composerInterpreter,
) {
}

public function decorate(DecorateEvent $event): void
{
$terminalCommand = $event->getTerminalCommand();

if (!$terminalCommand instanceof MinimalVersionDependantTerminalCommand) {
return;
}

if ($this->cachedMinPhpVersion === null) {
$phpVersionConstraint = $this->composerInterpreter->getLocalPhpVersionConstraint();

$this->cachedMinPhpVersion = $this->constraintToVersionConverter
->extractActualPhpVersion($phpVersionConstraint);
}

$terminalCommand->setMinimalPhpVersion($this->cachedMinPhpVersion);

$event->getOutput()->writeln(
'<info>Targeted minimal PHP version is ' . $this->cachedMinPhpVersion . '</info>' . PHP_EOL,
OutputInterface::VERBOSITY_VERBOSE,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\TerminalCommand;

interface MinimalVersionDependantTerminalCommand extends TerminalCommand
{
/**
* This method receives the minimal php version the source code to check is written in.
*/
public function setMinimalPhpVersion(string $phpVersion): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

trait MinimalVersionDependentTrait
{
protected string $minimalPhpVersion = '7.4';

/**
* {@inheritDoc}
*/
public function setMinimalPhpVersion(string $minimalPhpVersion): void
{
$this->minimalPhpVersion = $minimalPhpVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,25 @@

namespace Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion;

use Composer\Semver\Semver;
use Symfony\Component\Console\Output\OutputInterface;
use Zooroyal\CodingStandard\CommandLine\EnhancedFileInfo\EnhancedFileInfo;
use Zooroyal\CodingStandard\CommandLine\EnhancedFileInfo\EnhancedFileInfoFactory;
use Zooroyal\CodingStandard\CommandLine\Environment\Environment;
use Zooroyal\CodingStandard\CommandLine\FileSearch\FileSearchInterface;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\DecorateEvent;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\TerminalCommandDecorator;

use function Safe\file_get_contents;
use function Safe\preg_match;

class VersionDecorator extends TerminalCommandDecorator
{
/** @var array<string> */
private array $phpVersions = [];
private ?string $cachedMinPhpVersion = null;

public function __construct(
private readonly Environment $environment,
private readonly FileSearchInterface $fileSearchInterface,
private readonly EnhancedFileInfoFactory $enhancedFileInfoFactory,
private readonly ConstraintToVersionConverter $constraintToVersionConverter,
private readonly ComposerInterpreter $composerInterpreter,
) {
$phpVersionRanges = [
'7.4.' => '33',
'8.0.' => '27',
'8.1.' => '17',
'8.2.' => (explode('.', phpversion()))[2],
];

foreach ($phpVersionRanges as $phpVersionString => $phpMaxPatchVersion) {
$phpPatchLevels = range('0', $phpMaxPatchVersion);
foreach ($phpPatchLevels as $phpPatchLevel) {
$this->phpVersions[] = $phpVersionString . $phpPatchLevel;
}
}
}

public function decorate(DecorateEvent $event): void
Expand All @@ -63,26 +46,6 @@ public function decorate(DecorateEvent $event): void
);
}

/**
* Check if $phpVersionConstraint is a version number and return it or if we find a php version that satisfies
* the constraint.
*/
private function extractActualPhpVersion(string $phpVersionConstraint): string
{
if (preg_match('/^(\d+)(\.\d)?(\.\d)?$/', $phpVersionConstraint, $matches)) {
return $matches[1] . ($matches[2] ?? '.0') . ($matches[3] ?? '.0');
}

$minPhpVersion = '7.4.0';
foreach ($this->phpVersions as $phpVersion) {
if (SemVer::satisfies($phpVersion, $phpVersionConstraint)) {
$minPhpVersion = $phpVersion;
break;
}
}
return $minPhpVersion;
}

/**
* Finds all composer files in the project.
*
Expand All @@ -91,18 +54,15 @@ private function extractActualPhpVersion(string $phpVersionConstraint): string
private function gatherComposerFiles(): array
{
$rootDirectory = $this->environment->getRootDirectory();
$path = $rootDirectory->getRealPath();
$composerFiles[] = $this->enhancedFileInfoFactory->buildFromPath($path . '/composer.json');

$foundComposerFiles = $this->fileSearchInterface->listFolderFiles(
fileName: 'composer.json',
path: $rootDirectory,
minDepth: 1,
maxDepth: 4
maxDepth: 4,
);

$composerFiles = [...$composerFiles, ...$foundComposerFiles];
return $composerFiles;
return $foundComposerFiles;
}

/**
Expand All @@ -112,22 +72,15 @@ private function gatherComposerFiles(): array
*/
private function searchMinimalViablePhpVersion(array $composerFiles): string
{
$minPhpVersion = '7.4.0';
$minPhpVersion = $this->composerInterpreter->getLocalPhpVersionConstraint();

foreach ($composerFiles as $key => $composerFile) {
foreach ($composerFiles as $composerFile) {
$contents = file_get_contents($composerFile->getRealPath());
$composerConfig = json_decode($contents, true, 512, JSON_THROW_ON_ERROR);

// The first file is the root composer file, so we need to check the platform config.
if ($key === 0) {
$phpVersionConstraint = $composerConfig['config']['platform']['php']
?? $composerConfig['require']['php']
?? '*';
} else {
$phpVersionConstraint = $composerConfig['require']['php'] ?? '*';
}
$phpVersionConstraint = $composerConfig['require']['php'] ?? '*';

$minPhpVersionPackage = $this->extractActualPhpVersion($phpVersionConstraint);
$minPhpVersionPackage = $this->constraintToVersionConverter->extractActualPhpVersion($phpVersionConstraint);
$minPhpVersion = version_compare($minPhpVersion, $minPhpVersionPackage, '<')
? $minPhpVersionPackage
: $minPhpVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Fix\FixTrait;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Multiprocess\MultiprocessTerminalCommand;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Multiprocess\MultiprocessTrait;
// phpcs:ignore -- I did not find a way to either break this line or to make it shorter.
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\MinimalVersionDependantTerminalCommand;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be possible, but does not quite make it more readable I think 😅

use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\{
    MinimalVersionDependantTerminalCommand,
    MinimalVersionDependentTrait,
    PhpVersionConverter
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. thought about that but came to the same conclusion as you did. :/

use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\MinimalVersionDependentTrait;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\PhpVersionConverter;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\VersionDependentTerminalCommand;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\PhpVersion\VersionDependentTrait;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Target\TargetTerminalCommand;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Target\TargetTrait;
use Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\Verbose\VerboseTerminalCommand;
Expand All @@ -31,15 +32,15 @@ class TerminalCommand extends AbstractTerminalCommand implements
FileExtensionTerminalCommand,
VerboseTerminalCommand,
MultiprocessTerminalCommand,
VersionDependentTerminalCommand
MinimalVersionDependantTerminalCommand
{
use TargetTrait;
use FixTrait;
use ExclusionTrait;
use FileExtensionTrait;
use VerboseTrait;
use MultiprocessTrait;
use VersionDependentTrait;
use MinimalVersionDependentTrait;

private const TEMPLATE = 'php %1$s %5$s%6$s--parallel=%7$d -p --standard=%2$s%3$s%8$s%4$s';

Expand Down Expand Up @@ -148,7 +149,7 @@ private function buildTargetingString(): string
private function buildPhpVersionString(): string
{
$template = ' --runtime-set php_version %d';
$phpVersion = $this->phpVersionConverter->convertSemVerToPhpString($this->phpVersion);
$phpVersion = $this->phpVersionConverter->convertSemVerToPhpString($this->minimalPhpVersion);

$result = sprintf($template, $phpVersion);

Expand Down
Loading
Loading