diff --git a/README.md b/README.md index dd0e2ed..c88fb7a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,16 @@ Supported Stacks for now: - Winter CMS - Wordpress +It also detects if the repository uses nodeJS. If so, it detects node version (through .nvmrc or .node-version), node version requirements, and package manager. + +Detected package managers: + +- npm +- pnpm +- bun +- yarn +- yarn berry + ## Install ``` @@ -39,7 +49,7 @@ require_once __DIR__ . '/vendor/autoload.php'; use Einenlum\PhpStackDetector\Detector; use Einenlum\PhpStackDetector\Factory\FilesystemDetectorFactory; use Einenlum\PhpStackDetector\Factory\GithubDetectorFactory; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; // Local usage @@ -107,12 +117,20 @@ Required extensions: ctype, iconv, redis, sodium Detected stack: laravel Version: 10.19.0 +Detected Node.js version: 22.0 +Detected Node.js requirements: Unknown version +Package Manager: bun + php bin/detect-github.php 'symfony/demo' Detected PHP version: 8.4 Detected PHP requirements: ^8.3 Required extensions: ctype, iconv Detected stack: symfony Version: 6.3.0 + +Detected Node.js version: Unknown version +Detected Node.js requirements: Unknown version +Package Manager: npm ``` It is advised to use an access token for github parsing, to either access private repositories or avoid reaching Github API limit. @@ -121,6 +139,10 @@ It is advised to use an access token for github parsing, to either access privat GITHUB_ACCESS_TOKEN=my_token php bin/detect-github.php 'einenlum/private-repo' Detected stack: laravel Version: 10.19.0 + +Detected Node.js version: Unknown version +Detected Node.js requirements: Unknown version +Package Manager: npm ``` ### Usage with Symfony diff --git a/bin/detect-github.php b/bin/detect-github.php index 2eb25d4..12d4032 100644 --- a/bin/detect-github.php +++ b/bin/detect-github.php @@ -40,3 +40,10 @@ echo 'Detected stack: '.$stack->type->value."\n"; echo 'Version: '.($stack->version ?: 'Unknown version')."\n"; + +$nodeConfig = $config->nodeConfiguration; + +echo "\n"; +echo 'Detected Node.js version: '.($nodeConfig?->version ?: 'Unknown version')."\n"; +echo 'Detected Node.js requirements: '.($nodeConfig?->requirements ?: 'Unknown version')."\n"; +echo 'Package Manager: '.($nodeConfig?->packageManager?->value ?: 'Unknown')."\n"; diff --git a/bin/detect-local.php b/bin/detect-local.php index 26ac107..7d3f108 100644 --- a/bin/detect-local.php +++ b/bin/detect-local.php @@ -31,3 +31,10 @@ echo 'Detected stack: '.$stack->type->value."\n"; echo 'Version: '.($stack->version ?: 'Unknown version')."\n"; + +$nodeConfig = $config->nodeConfiguration; + +echo "\n"; +echo 'Detected Node.js version: '.($nodeConfig?->version ?: 'Unknown version')."\n"; +echo 'Detected Node.js requirements: '.($nodeConfig?->requirements ?: 'Unknown version')."\n"; +echo 'Package Manager: '.($nodeConfig?->packageManager?->value ?: 'Unknown')."\n"; diff --git a/lib/Composer/ComposerConfigProvider.php b/lib/Composer/ComposerConfigProvider.php index 1c4a22d..2b0c453 100644 --- a/lib/Composer/ComposerConfigProvider.php +++ b/lib/Composer/ComposerConfigProvider.php @@ -4,6 +4,8 @@ namespace Einenlum\PhpStackDetector\Composer; +use Einenlum\PhpStackDetector\DTO\Composer\ComposerConfig; +use Einenlum\PhpStackDetector\DTO\Enum\ComposerConfigType; use Einenlum\PhpStackDetector\DirectoryCrawler\AdapterInterface; use Einenlum\PhpStackDetector\Exception\CacheMissException; use Einenlum\PhpStackDetector\Exception\ResourceNotFoundException; @@ -22,10 +24,6 @@ public function __construct( ) { } - /** - * This returns the content of the composer lock file if it exists, - * otherwise the composer json file if it exists, otherwise null. - */ public function getComposerConfig( ComposerConfigType $type, string $baseUri, diff --git a/lib/Composer/PackageVersionProvider.php b/lib/Composer/PackageVersionProvider.php index b886897..75335b8 100644 --- a/lib/Composer/PackageVersionProvider.php +++ b/lib/Composer/PackageVersionProvider.php @@ -4,6 +4,9 @@ namespace Einenlum\PhpStackDetector\Composer; +use Einenlum\PhpStackDetector\DTO\Composer\PackageVersion; +use Einenlum\PhpStackDetector\DTO\Enum\ComposerConfigType; + readonly class PackageVersionProvider { public function __construct(private ComposerConfigProvider $configProvider) diff --git a/lib/Composer/ComposerConfig.php b/lib/DTO/Composer/ComposerConfig.php similarity index 66% rename from lib/Composer/ComposerConfig.php rename to lib/DTO/Composer/ComposerConfig.php index 6988106..761a2cc 100644 --- a/lib/Composer/ComposerConfig.php +++ b/lib/DTO/Composer/ComposerConfig.php @@ -2,7 +2,9 @@ declare(strict_types=1); -namespace Einenlum\PhpStackDetector\Composer; +namespace Einenlum\PhpStackDetector\DTO\Composer; + +use Einenlum\PhpStackDetector\DTO\Enum\ComposerConfigType; readonly class ComposerConfig { diff --git a/lib/Composer/PackageVersion.php b/lib/DTO/Composer/PackageVersion.php similarity index 93% rename from lib/Composer/PackageVersion.php rename to lib/DTO/Composer/PackageVersion.php index 1b57792..d2c07bc 100644 --- a/lib/Composer/PackageVersion.php +++ b/lib/DTO/Composer/PackageVersion.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Einenlum\PhpStackDetector\Composer; +namespace Einenlum\PhpStackDetector\DTO\Composer; use Einenlum\ComposerVersionParser\Parser; diff --git a/lib/DependencyTree.php b/lib/DTO/DependencyTree.php similarity index 95% rename from lib/DependencyTree.php rename to lib/DTO/DependencyTree.php index aa5e5b6..ee716f3 100644 --- a/lib/DependencyTree.php +++ b/lib/DTO/DependencyTree.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Einenlum\PhpStackDetector; +namespace Einenlum\PhpStackDetector\DTO; use Einenlum\PhpStackDetector\StackDetector\LunarDetector; use Einenlum\PhpStackDetector\StackDetector\OctoberCMSDetector; diff --git a/lib/Composer/ComposerConfigType.php b/lib/DTO/Enum/ComposerConfigType.php similarity index 71% rename from lib/Composer/ComposerConfigType.php rename to lib/DTO/Enum/ComposerConfigType.php index 79d3b2a..1b48f0c 100644 --- a/lib/Composer/ComposerConfigType.php +++ b/lib/DTO/Enum/ComposerConfigType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Einenlum\PhpStackDetector\Composer; +namespace Einenlum\PhpStackDetector\DTO\Enum; enum ComposerConfigType: string { diff --git a/lib/FullConfiguration.php b/lib/DTO/FullConfiguration.php similarity index 67% rename from lib/FullConfiguration.php rename to lib/DTO/FullConfiguration.php index 575e3e2..9a45c79 100644 --- a/lib/FullConfiguration.php +++ b/lib/DTO/FullConfiguration.php @@ -2,12 +2,13 @@ declare(strict_types=1); -namespace Einenlum\PhpStackDetector; +namespace Einenlum\PhpStackDetector\DTO; readonly class FullConfiguration { public function __construct( public PhpConfiguration $phpConfiguration, + public ?NodeConfiguration $nodeConfiguration, public ?Stack $stack, ) { } diff --git a/lib/DTO/NodeConfiguration.php b/lib/DTO/NodeConfiguration.php new file mode 100644 index 0000000..321b38c --- /dev/null +++ b/lib/DTO/NodeConfiguration.php @@ -0,0 +1,17 @@ +cleanSubFolder($subFolder); $phpConfiguration = $this->getPhpConfiguration($baseUri, $subFolder); + $nodeConfiguration = $this->getNodeConfiguration($baseUri, $subFolder); $stack = $this->getStack($baseUri, $subFolder); return new FullConfiguration( $phpConfiguration, + $nodeConfiguration, $stack, ); } @@ -31,6 +39,11 @@ private function getPhpConfiguration(string $baseUri, ?string $subFolder = null) return $this->phpConfigurationDetector->getPhpConfiguration($baseUri, $subFolder); } + private function getNodeConfiguration(string $baseUri, ?string $subFolder = null): ?NodeConfiguration + { + return $this->nodeConfigurationDetector->getNodeConfiguration($baseUri, $subFolder); + } + /** * @param string $baseUri The base URI of the project, e.g. * /some/path/to/local/project diff --git a/lib/DirectoryCrawler/AdapterInterface.php b/lib/DirectoryCrawler/AdapterInterface.php index 421aec3..4b67bc1 100644 --- a/lib/DirectoryCrawler/AdapterInterface.php +++ b/lib/DirectoryCrawler/AdapterInterface.php @@ -11,6 +11,8 @@ interface AdapterInterface /** @throws ResourceNotFoundException */ public function getFileContent(string $baseUri, ?string ...$pathTree): string; + public function fileExists(string $baseUri, ?string ...$pathTree): bool; + public function directoryExists(string $baseUri, ?string ...$pathTree): bool; /** @return array */ diff --git a/lib/DirectoryCrawler/FilesystemAdapter.php b/lib/DirectoryCrawler/FilesystemAdapter.php index 97972fb..41fe967 100644 --- a/lib/DirectoryCrawler/FilesystemAdapter.php +++ b/lib/DirectoryCrawler/FilesystemAdapter.php @@ -23,6 +23,13 @@ public function getFileContent(string $baseUri, ?string ...$pathTree): string return $content; } + public function fileExists(string $baseUri, ?string ...$pathTree): bool + { + $fullUri = $this->getFullUri($baseUri, $pathTree); + + return is_file($fullUri); + } + public function directoryExists(string $baseUri, ?string ...$pathTree): bool { $fullUri = $this->getFullUri($baseUri, $pathTree); diff --git a/lib/DirectoryCrawler/GithubAdapter.php b/lib/DirectoryCrawler/GithubAdapter.php index e953c36..a099a1b 100644 --- a/lib/DirectoryCrawler/GithubAdapter.php +++ b/lib/DirectoryCrawler/GithubAdapter.php @@ -37,6 +37,24 @@ public function getFileContent(string $baseUri, ?string ...$pathTree): string return base64_decode($content['content']); } + public function fileExists(string $baseUri, ?string ...$pathTree): bool + { + $config = $this->splitBaseUri($baseUri); + + try { + $this->client->repo()->contents()->show( + $config['organization'], + $config['repository'], + $this->getPathTreeAsString($pathTree), + $config['reference'] + ); + + return true; + } catch (RuntimeException $e) { + return false; + } + } + public function directoryExists(string $baseUri, ?string ...$pathTree): bool { $config = $this->splitBaseUri($baseUri); diff --git a/lib/Enum/NodePackageManagerType.php b/lib/Enum/NodePackageManagerType.php new file mode 100644 index 0000000..447b63a --- /dev/null +++ b/lib/Enum/NodePackageManagerType.php @@ -0,0 +1,14 @@ +getStackDetectors($composerConfigProvider, $adapter); - return new Detector($phpConfigurationDetector, $stackDetectors); + return new Detector( + $phpConfigurationDetector, + $nodeConfigurationDetector, + $stackDetectors + ); } } diff --git a/lib/Factory/GithubDetectorFactory.php b/lib/Factory/GithubDetectorFactory.php index ba4e8b4..03671b3 100644 --- a/lib/Factory/GithubDetectorFactory.php +++ b/lib/Factory/GithubDetectorFactory.php @@ -7,6 +7,8 @@ use Einenlum\PhpStackDetector\Composer\ComposerConfigProvider; use Einenlum\PhpStackDetector\Detector; use Einenlum\PhpStackDetector\DirectoryCrawler\GithubAdapter; +use Einenlum\PhpStackDetector\Node\PackageJsonProvider; +use Einenlum\PhpStackDetector\NodeConfigurationDetector; use Einenlum\PhpStackDetector\PhpConfigurationDetector; use Github\Client; @@ -21,8 +23,18 @@ public function create(?Client $client = null): Detector $composerConfigProvider = new ComposerConfigProvider($adapter); $phpConfigurationDetector = new PhpConfigurationDetector($composerConfigProvider); + $packageJsonProvider = new PackageJsonProvider($adapter); + $nodeConfigurationDetector = new NodeConfigurationDetector( + $packageJsonProvider, + $adapter + ); + $stackDetectors = $this->getStackDetectors($composerConfigProvider, $adapter); - return new Detector($phpConfigurationDetector, $stackDetectors); + return new Detector( + $phpConfigurationDetector, + $nodeConfigurationDetector, + $stackDetectors + ); } } diff --git a/lib/Node/PackageJsonProvider.php b/lib/Node/PackageJsonProvider.php new file mode 100644 index 0000000..cac7cdb --- /dev/null +++ b/lib/Node/PackageJsonProvider.php @@ -0,0 +1,103 @@ + */ + private array $cache = []; + + public function __construct( + private readonly AdapterInterface $adapter, + ) { + } + + /** @return array|null */ + public function getPackageJsonConfig( + string $baseUri, + ?string $subDirectory, + ): ?array { + try { + return $this->getFromCache($baseUri, $subDirectory); + } catch (CacheMissException) { + } + + $content = $this->getFileContent( + $baseUri, + $subDirectory, + ); + + $this->setToCache($baseUri, $subDirectory, $content); + + return $content; + } + + /** @return array|null */ + private function getFileContent( + string $baseUri, + ?string $subDirectory, + ): ?array { + if (!$this->adapter->directoryExists($baseUri, $subDirectory)) { + return null; + } + + try { + $fileContent = $this->adapter->getFileContent( + $baseUri, + $subDirectory, + 'package.json' + ); + } catch (ResourceNotFoundException $e) { + return null; + } + + $decoded = json_decode($fileContent, true); + if (null === $decoded) { + return null; + } + + return $decoded; + } + + /** @param array|null $config */ + private function setToCache( + string $baseUri, + ?string $subDirectory, + ?array $config, + ): void { + $cacheKey = $this->getCacheKey($baseUri, $subDirectory); + + $this->cache[$cacheKey] = $config; + } + + /** + * @return array|null + * + * @throws CacheMissException + */ + private function getFromCache( + string $baseUri, + ?string $subDirectory, + ): ?array { + $cacheKey = $this->getCacheKey($baseUri, $subDirectory); + + if (!array_key_exists($cacheKey, $this->cache)) { + throw new CacheMissException(); + } + + return $this->cache[$cacheKey]; + } + + private function getCacheKey( + string $baseUri, + ?string $subDirectory, + ): string { + return $baseUri.$subDirectory; + } +} diff --git a/lib/NodeConfigurationDetector.php b/lib/NodeConfigurationDetector.php new file mode 100644 index 0000000..7e7b358 --- /dev/null +++ b/lib/NodeConfigurationDetector.php @@ -0,0 +1,181 @@ +packageJsonProvider->getPackageJsonConfig( + $baseUri, + $subFolder, + ); + if (null === $packageJsonConfig) { + return null; + } + + return new NodeConfiguration( + $this->getNodeVersion($baseUri, $subFolder), + $this->getVersionRequirements($baseUri, $subFolder), + $this->getPackageManagerType($baseUri, $subFolder), + ); + } + + private function getNodeVersion(string $baseUri, ?string $subFolder = null): ?string + { + if (!$this->adapter->directoryExists($baseUri, $subFolder)) { + return null; + } + + $nvmrcContent = $this->getFileContent( + $baseUri, + $subFolder, + '.nvmrc' + ); + $nodeVersion = $this->extractNodeVersion($nvmrcContent); + + if (null !== $nodeVersion) { + return $nodeVersion; + } + + $nodeVersionContent = $this->getFileContent( + $baseUri, + $subFolder, + '.node-version' + ); + $nodeVersion = $this->extractNodeVersion($nodeVersionContent); + + return $nodeVersion; + } + + private function getVersionRequirements(string $baseUri, ?string $subFolder = null): ?string + { + $packageJsonContent = $this->packageJsonProvider->getPackageJsonConfig( + $baseUri, + $subFolder, + ); + + if (null === $packageJsonContent) { + return null; + } + + return $packageJsonContent['engines']['node'] ?? null; + } + + private function extractNodeVersion(?string $content): ?string + { + if (null === $content) { + return null; + } + + $lines = explode("\n", trim($content)); + $lines = array_filter( + $lines, + fn ($line) => '' !== $line && false === str_starts_with($line, '#') + ); + + $firstLine = $lines[0] ?? null; + + if (null === $firstLine) { + return null; + } + + $version = ltrim($firstLine, 'v'); + + return $version ?: null; + } + + private function getPackageManagerType( + string $baseUri, + ?string $subFolder = null, + ): NodePackageManagerType { + $lockFiles = [ + 'package-lock.json' => NodePackageManagerType::NPM, + 'pnpm-lock.yaml' => NodePackageManagerType::PNPM, + 'bun.lock' => NodePackageManagerType::BUN, + ]; + + foreach ($lockFiles as $filename => $type) { + if ($this->adapter->fileExists($baseUri, $subFolder, $filename)) { + return $type; + } + } + + $yarnType = $this->detectYarn($baseUri, $subFolder); + if (null !== $yarnType) { + return $yarnType; + } + + /** @var string $packageJsonContent */ + $packageJsonContent = $this->getFileContent( + $baseUri, + $subFolder, + 'package.json' + ); + + $packageData = json_decode( + $packageJsonContent, + true, + 512, + \JSON_THROW_ON_ERROR + ); + + $packageManager = $packageData['packageManager'] ?? null; + if (null !== $packageManager) { + $packageManagerParts = explode('@', $packageManager); + $managerName = $packageManagerParts[0]; + + $managerType = NodePackageManagerType::tryFrom($managerName); + + if (null !== $managerType) { + return $managerType; + } + } + + return NodePackageManagerType::NPM; // Default to NPM if no lock file or packageManager field is found + } + + private function detectYarn( + string $baseUri, + ?string $subFolder = null, + ): ?NodePackageManagerType { + if (!$this->adapter->fileExists($baseUri, $subFolder, 'yarn.lock')) { + return null; + } + + if ($this->adapter->fileExists($baseUri, $subFolder, '.yarnrc.yml')) { + return NodePackageManagerType::YARN_BERRY; + } + + return NodePackageManagerType::YARN; + } + + private function getFileContent(string $baseUri, ?string $subFolder, string $filename): ?string + { + try { + return $this->adapter->getFileContent( + $baseUri, + $subFolder, + $filename + ); + } catch (ResourceNotFoundException) { + return null; + } + } +} diff --git a/lib/PhpConfigurationDetector.php b/lib/PhpConfigurationDetector.php index e961cc0..7dceeaf 100644 --- a/lib/PhpConfigurationDetector.php +++ b/lib/PhpConfigurationDetector.php @@ -4,9 +4,11 @@ namespace Einenlum\PhpStackDetector; -use Einenlum\PhpStackDetector\Composer\ComposerConfig; +use Einenlum\PhpStackDetector\DTO\Composer\ComposerConfig; use Einenlum\PhpStackDetector\Composer\ComposerConfigProvider; -use Einenlum\PhpStackDetector\Composer\ComposerConfigType; +use Einenlum\PhpStackDetector\DTO\Enum\ComposerConfigType; +use Einenlum\PhpStackDetector\DTO\PhpConfiguration; +use Einenlum\PhpStackDetector\DTO\PhpVersion; class PhpConfigurationDetector { diff --git a/lib/StackDetector/BaseComposerTypeDetector.php b/lib/StackDetector/BaseComposerTypeDetector.php index 8bb7ee6..69457aa 100644 --- a/lib/StackDetector/BaseComposerTypeDetector.php +++ b/lib/StackDetector/BaseComposerTypeDetector.php @@ -5,8 +5,8 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\Composer\PackageVersionProvider; -use Einenlum\PhpStackDetector\Stack; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\DTO\Stack; +use Einenlum\PhpStackDetector\Enum\StackType; abstract class BaseComposerTypeDetector { diff --git a/lib/StackDetector/BoltCMSDetector.php b/lib/StackDetector/BoltCMSDetector.php index f40488b..8806f4d 100644 --- a/lib/StackDetector/BoltCMSDetector.php +++ b/lib/StackDetector/BoltCMSDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class BoltCMSDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/CakePhpDetector.php b/lib/StackDetector/CakePhpDetector.php index 32639eb..9a27406 100644 --- a/lib/StackDetector/CakePhpDetector.php +++ b/lib/StackDetector/CakePhpDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class CakePhpDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/CodeigniterDetector.php b/lib/StackDetector/CodeigniterDetector.php index 439ab8a..5dab56e 100644 --- a/lib/StackDetector/CodeigniterDetector.php +++ b/lib/StackDetector/CodeigniterDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class CodeigniterDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/CraftCMSDetector.php b/lib/StackDetector/CraftCMSDetector.php index f2e79c5..b6705d3 100644 --- a/lib/StackDetector/CraftCMSDetector.php +++ b/lib/StackDetector/CraftCMSDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class CraftCMSDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/DrupalDetector.php b/lib/StackDetector/DrupalDetector.php index 8c0cfdc..813445d 100644 --- a/lib/StackDetector/DrupalDetector.php +++ b/lib/StackDetector/DrupalDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class DrupalDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/GravCMSDetector.php b/lib/StackDetector/GravCMSDetector.php index 7afcde2..a7dc4ab 100644 --- a/lib/StackDetector/GravCMSDetector.php +++ b/lib/StackDetector/GravCMSDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class GravCMSDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/LaravelDetector.php b/lib/StackDetector/LaravelDetector.php index 4b17b8e..a8b0501 100644 --- a/lib/StackDetector/LaravelDetector.php +++ b/lib/StackDetector/LaravelDetector.php @@ -4,10 +4,10 @@ namespace Einenlum\PhpStackDetector\StackDetector; -use Einenlum\PhpStackDetector\DependencyTree; -use Einenlum\PhpStackDetector\Stack; +use Einenlum\PhpStackDetector\DTO\DependencyTree; +use Einenlum\PhpStackDetector\DTO\Stack; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class LaravelDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/LeafDetector.php b/lib/StackDetector/LeafDetector.php index 04c5749..daee646 100644 --- a/lib/StackDetector/LeafDetector.php +++ b/lib/StackDetector/LeafDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class LeafDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/LunarDetector.php b/lib/StackDetector/LunarDetector.php index 102fcc4..bbf42f6 100644 --- a/lib/StackDetector/LunarDetector.php +++ b/lib/StackDetector/LunarDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class LunarDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/OctoberCMSDetector.php b/lib/StackDetector/OctoberCMSDetector.php index a4d34b2..92ee78b 100644 --- a/lib/StackDetector/OctoberCMSDetector.php +++ b/lib/StackDetector/OctoberCMSDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class OctoberCMSDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/ShopwareDetector.php b/lib/StackDetector/ShopwareDetector.php index 1284bcd..e1fcef4 100644 --- a/lib/StackDetector/ShopwareDetector.php +++ b/lib/StackDetector/ShopwareDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class ShopwareDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/StatamicDetector.php b/lib/StackDetector/StatamicDetector.php index 172ce42..fc055dd 100644 --- a/lib/StackDetector/StatamicDetector.php +++ b/lib/StackDetector/StatamicDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class StatamicDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/SymfonyDetector.php b/lib/StackDetector/SymfonyDetector.php index 510b690..8c005bf 100644 --- a/lib/StackDetector/SymfonyDetector.php +++ b/lib/StackDetector/SymfonyDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class SymfonyDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/TempestDetector.php b/lib/StackDetector/TempestDetector.php index 622caee..9cab639 100644 --- a/lib/StackDetector/TempestDetector.php +++ b/lib/StackDetector/TempestDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class TempestDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/TwillDetector.php b/lib/StackDetector/TwillDetector.php index a6b1f8f..be53824 100644 --- a/lib/StackDetector/TwillDetector.php +++ b/lib/StackDetector/TwillDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class TwillDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/Typo3Detector.php b/lib/StackDetector/Typo3Detector.php index 086e90f..da412e5 100644 --- a/lib/StackDetector/Typo3Detector.php +++ b/lib/StackDetector/Typo3Detector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class Typo3Detector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/WinterCMSDetector.php b/lib/StackDetector/WinterCMSDetector.php index f297b09..209593f 100644 --- a/lib/StackDetector/WinterCMSDetector.php +++ b/lib/StackDetector/WinterCMSDetector.php @@ -5,7 +5,7 @@ namespace Einenlum\PhpStackDetector\StackDetector; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class WinterCMSDetector extends BaseComposerTypeDetector implements StackDetectorInterface { diff --git a/lib/StackDetector/WordpressDetector.php b/lib/StackDetector/WordpressDetector.php index 0a73d31..fe207d8 100644 --- a/lib/StackDetector/WordpressDetector.php +++ b/lib/StackDetector/WordpressDetector.php @@ -4,9 +4,9 @@ use Einenlum\PhpStackDetector\DirectoryCrawler\AdapterInterface; use Einenlum\PhpStackDetector\Exception\ResourceNotFoundException; -use Einenlum\PhpStackDetector\Stack; +use Einenlum\PhpStackDetector\DTO\Stack; use Einenlum\PhpStackDetector\StackDetectorInterface; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\StackType; class WordpressDetector implements StackDetectorInterface { diff --git a/lib/StackDetectorInterface.php b/lib/StackDetectorInterface.php index bfd7cd0..106c9b8 100644 --- a/lib/StackDetectorInterface.php +++ b/lib/StackDetectorInterface.php @@ -4,6 +4,8 @@ namespace Einenlum\PhpStackDetector; +use Einenlum\PhpStackDetector\DTO\Stack; + interface StackDetectorInterface { public function getStack(string $baseUri, ?string $subDirectory): ?Stack; diff --git a/tests/Unit/Composer/ComposerConfigProviderFilesystemTest.php b/tests/Unit/Composer/ComposerConfigProviderFilesystemTest.php index 38b16b7..432306f 100644 --- a/tests/Unit/Composer/ComposerConfigProviderFilesystemTest.php +++ b/tests/Unit/Composer/ComposerConfigProviderFilesystemTest.php @@ -4,9 +4,9 @@ namespace Einenlum\Tests\PhpStackDetector\Unit\Composer; -use Einenlum\PhpStackDetector\Composer\ComposerConfig; +use Einenlum\PhpStackDetector\DTO\Composer\ComposerConfig; use Einenlum\PhpStackDetector\Composer\ComposerConfigProvider; -use Einenlum\PhpStackDetector\Composer\ComposerConfigType; +use Einenlum\PhpStackDetector\DTO\Enum\ComposerConfigType; use Einenlum\PhpStackDetector\DirectoryCrawler\FilesystemAdapter; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/DetectorTest.php b/tests/Unit/DetectorTest.php index c8a1654..ba3a5a0 100644 --- a/tests/Unit/DetectorTest.php +++ b/tests/Unit/DetectorTest.php @@ -6,7 +6,8 @@ use Einenlum\PhpStackDetector\Detector; use Einenlum\PhpStackDetector\Factory\FilesystemDetectorFactory; -use Einenlum\PhpStackDetector\StackType; +use Einenlum\PhpStackDetector\Enum\NodePackageManagerType; +use Einenlum\PhpStackDetector\Enum\StackType; use PHPUnit\Framework\TestCase; class DetectorTest extends TestCase @@ -19,6 +20,195 @@ public function setUp(): void $this->sut = $factory->create(); } + /** + * @test + */ + public function it_detects_no_node_version(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/no-version') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertNull($fullConfig->nodeConfiguration->version); + } + + /** + * @test + */ + public function it_detects_node_version_from_nvmrc(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/nvmrc') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame('13.0.1', $fullConfig->nodeConfiguration->version); + } + + /** + * @test + */ + public function it_detects_node_version_from_commented_nvmrc(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/nvmrc-commented') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame(null, $fullConfig->nodeConfiguration->version); + } + + /** + * @test + */ + public function it_detects_node_version_from_node_version_file(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/node-version') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame('13.0.1', $fullConfig->nodeConfiguration->version); + } + + /** + * @test + */ + public function it_detects_no_node_version_from_commented_node_version_file(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/node-version-commented') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame(null, $fullConfig->nodeConfiguration->version); + } + + /** + * @test + */ + public function it_detects_requirements_from_package_json(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/package-json-requirements') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame('>=18 <20', $fullConfig->nodeConfiguration->requirements); + } + + /** + * @test + */ + public function it_detects_no_node_configuration(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/empty') + ); + + $this->assertNotNull($fullConfig); + + $this->assertNull($fullConfig->nodeConfiguration); + } + + /** + * @test + */ + public function it_detects_npm(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/npm-lock') + ); + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame( + NodePackageManagerType::NPM, + $fullConfig->nodeConfiguration->packageManager + ); + } + + /** + * @test + */ + public function it_detects_pnpm(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/pnpm-lock') + ); + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame( + NodePackageManagerType::PNPM, + $fullConfig->nodeConfiguration->packageManager + ); + } + + /** + * @test + */ + public function it_detects_bun(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/bun-lock') + ); + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame( + NodePackageManagerType::BUN, + $fullConfig->nodeConfiguration->packageManager + ); + } + + /** + * @test + */ + public function it_detects_yarn(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/yarn') + ); + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame( + NodePackageManagerType::YARN, + $fullConfig->nodeConfiguration->packageManager + ); + } + + /** + * @test + */ + public function it_detects_yarn_berry(): void + { + $fullConfig = $this->sut->getFullConfiguration( + sprintf('%s/../fixtures/%s', __DIR__, 'node-configuration/yarn-berry') + ); + $this->assertNotNull($fullConfig); + + $this->assertNotNull($fullConfig->nodeConfiguration); + $this->assertSame( + NodePackageManagerType::YARN_BERRY, + $fullConfig->nodeConfiguration->packageManager + ); + } + /** * @test * @@ -27,7 +217,7 @@ public function setUp(): void public function it_detects_stack(string $fixtureFolder, ?string $expectedVersion, StackType $expectedType): void { $fullConfig = $this->sut->getFullConfiguration( - sprintf('%s/../fixtures/%s', __DIR__, $fixtureFolder) + sprintf('%s/../fixtures/php-stack/%s', __DIR__, $fixtureFolder) ); $this->assertNotNull($fullConfig); @@ -201,7 +391,7 @@ public static function packagesDataProvider(): array 'Statamic 4' => ['statamic/4', '4', StackType::STATAMIC], 'Statamic unknown version' => ['statamic/unknown', null, StackType::STATAMIC], - 'Composer lock test' => ['composer-lock', '6.3.5', StackType::SYMFONY], + 'Composer lock test' => ['symfony-in-composer-lock', '6.3.5', StackType::SYMFONY], ]; } } diff --git a/tests/fixtures/node-configuration/bun-lock/bun.lock b/tests/fixtures/node-configuration/bun-lock/bun.lock new file mode 100644 index 0000000..cc41dd1 --- /dev/null +++ b/tests/fixtures/node-configuration/bun-lock/bun.lock @@ -0,0 +1,3 @@ +{ + "name": "bun-lock" +} diff --git a/tests/fixtures/node-configuration/bun-lock/package.json b/tests/fixtures/node-configuration/bun-lock/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/bun-lock/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/empty/.gitkeep b/tests/fixtures/node-configuration/empty/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures/node-configuration/no-version/package.json b/tests/fixtures/node-configuration/no-version/package.json new file mode 100644 index 0000000..0aafd5a --- /dev/null +++ b/tests/fixtures/node-configuration/no-version/package.json @@ -0,0 +1,3 @@ +{ + "name": "no-version-package" +} diff --git a/tests/fixtures/node-configuration/node-version-commented/.node-version b/tests/fixtures/node-configuration/node-version-commented/.node-version new file mode 100644 index 0000000..59b8172 --- /dev/null +++ b/tests/fixtures/node-configuration/node-version-commented/.node-version @@ -0,0 +1 @@ +# 13.0.1 diff --git a/tests/fixtures/node-configuration/node-version-commented/package.json b/tests/fixtures/node-configuration/node-version-commented/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/node-version-commented/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/node-version/.node-version b/tests/fixtures/node-configuration/node-version/.node-version new file mode 100644 index 0000000..5cb7d85 --- /dev/null +++ b/tests/fixtures/node-configuration/node-version/.node-version @@ -0,0 +1 @@ +13.0.1 diff --git a/tests/fixtures/node-configuration/node-version/package.json b/tests/fixtures/node-configuration/node-version/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/node-version/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/npm-lock/package-lock.json b/tests/fixtures/node-configuration/npm-lock/package-lock.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/npm-lock/package-lock.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/npm-lock/package.json b/tests/fixtures/node-configuration/npm-lock/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/npm-lock/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/nvmrc-commented/.nvmrc b/tests/fixtures/node-configuration/nvmrc-commented/.nvmrc new file mode 100644 index 0000000..23a5055 --- /dev/null +++ b/tests/fixtures/node-configuration/nvmrc-commented/.nvmrc @@ -0,0 +1 @@ +#v13.0.1 diff --git a/tests/fixtures/node-configuration/nvmrc-commented/package.json b/tests/fixtures/node-configuration/nvmrc-commented/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/nvmrc-commented/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/nvmrc/.nvmrc b/tests/fixtures/node-configuration/nvmrc/.nvmrc new file mode 100644 index 0000000..c67637c --- /dev/null +++ b/tests/fixtures/node-configuration/nvmrc/.nvmrc @@ -0,0 +1 @@ +v13.0.1 diff --git a/tests/fixtures/node-configuration/nvmrc/package.json b/tests/fixtures/node-configuration/nvmrc/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/nvmrc/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/package-json-requirements/package.json b/tests/fixtures/node-configuration/package-json-requirements/package.json new file mode 100644 index 0000000..cdc79c3 --- /dev/null +++ b/tests/fixtures/node-configuration/package-json-requirements/package.json @@ -0,0 +1,5 @@ +{ + "engines": { + "node": ">=18 <20" + } +} diff --git a/tests/fixtures/node-configuration/pnpm-lock/package.json b/tests/fixtures/node-configuration/pnpm-lock/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/pnpm-lock/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/pnpm-lock/pnpm-lock.yaml b/tests/fixtures/node-configuration/pnpm-lock/pnpm-lock.yaml new file mode 100644 index 0000000..4eddb87 --- /dev/null +++ b/tests/fixtures/node-configuration/pnpm-lock/pnpm-lock.yaml @@ -0,0 +1,2 @@ +foo: + bar diff --git a/tests/fixtures/node-configuration/yarn-berry/.yarnrc.yml b/tests/fixtures/node-configuration/yarn-berry/.yarnrc.yml new file mode 100644 index 0000000..4eddb87 --- /dev/null +++ b/tests/fixtures/node-configuration/yarn-berry/.yarnrc.yml @@ -0,0 +1,2 @@ +foo: + bar diff --git a/tests/fixtures/node-configuration/yarn-berry/package.json b/tests/fixtures/node-configuration/yarn-berry/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/yarn-berry/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/yarn-berry/yarn.lock b/tests/fixtures/node-configuration/yarn-berry/yarn.lock new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/yarn-berry/yarn.lock @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/yarn/package.json b/tests/fixtures/node-configuration/yarn/package.json new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/yarn/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/node-configuration/yarn/yarn.lock b/tests/fixtures/node-configuration/yarn/yarn.lock new file mode 100644 index 0000000..93a68a5 --- /dev/null +++ b/tests/fixtures/node-configuration/yarn/yarn.lock @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/tests/fixtures/bolt_cms/5/composer.json b/tests/fixtures/php-stack/bolt_cms/5/composer.json similarity index 100% rename from tests/fixtures/bolt_cms/5/composer.json rename to tests/fixtures/php-stack/bolt_cms/5/composer.json diff --git a/tests/fixtures/cakephp/5/composer.json b/tests/fixtures/php-stack/cakephp/5/composer.json similarity index 100% rename from tests/fixtures/cakephp/5/composer.json rename to tests/fixtures/php-stack/cakephp/5/composer.json diff --git a/tests/fixtures/codeigniter/4/composer.json b/tests/fixtures/php-stack/codeigniter/4/composer.json similarity index 100% rename from tests/fixtures/codeigniter/4/composer.json rename to tests/fixtures/php-stack/codeigniter/4/composer.json diff --git a/tests/fixtures/craft_cms/3/composer.json b/tests/fixtures/php-stack/craft_cms/3/composer.json similarity index 100% rename from tests/fixtures/craft_cms/3/composer.json rename to tests/fixtures/php-stack/craft_cms/3/composer.json diff --git a/tests/fixtures/craft_cms/4/composer.json b/tests/fixtures/php-stack/craft_cms/4/composer.json similarity index 100% rename from tests/fixtures/craft_cms/4/composer.json rename to tests/fixtures/php-stack/craft_cms/4/composer.json diff --git a/tests/fixtures/craft_cms/unknown/composer.json b/tests/fixtures/php-stack/craft_cms/unknown/composer.json similarity index 100% rename from tests/fixtures/craft_cms/unknown/composer.json rename to tests/fixtures/php-stack/craft_cms/unknown/composer.json diff --git a/tests/fixtures/drupal/11/composer.json b/tests/fixtures/php-stack/drupal/11/composer.json similarity index 100% rename from tests/fixtures/drupal/11/composer.json rename to tests/fixtures/php-stack/drupal/11/composer.json diff --git a/tests/fixtures/grav_cms/2/composer.json b/tests/fixtures/php-stack/grav_cms/2/composer.json similarity index 100% rename from tests/fixtures/grav_cms/2/composer.json rename to tests/fixtures/php-stack/grav_cms/2/composer.json diff --git a/tests/fixtures/laravel/10/composer.json b/tests/fixtures/php-stack/laravel/10/composer.json similarity index 100% rename from tests/fixtures/laravel/10/composer.json rename to tests/fixtures/php-stack/laravel/10/composer.json diff --git a/tests/fixtures/laravel/5/composer.json b/tests/fixtures/php-stack/laravel/5/composer.json similarity index 100% rename from tests/fixtures/laravel/5/composer.json rename to tests/fixtures/php-stack/laravel/5/composer.json diff --git a/tests/fixtures/laravel/6/composer.json b/tests/fixtures/php-stack/laravel/6/composer.json similarity index 100% rename from tests/fixtures/laravel/6/composer.json rename to tests/fixtures/php-stack/laravel/6/composer.json diff --git a/tests/fixtures/laravel/7/composer.json b/tests/fixtures/php-stack/laravel/7/composer.json similarity index 100% rename from tests/fixtures/laravel/7/composer.json rename to tests/fixtures/php-stack/laravel/7/composer.json diff --git a/tests/fixtures/laravel/8/composer.json b/tests/fixtures/php-stack/laravel/8/composer.json similarity index 100% rename from tests/fixtures/laravel/8/composer.json rename to tests/fixtures/php-stack/laravel/8/composer.json diff --git a/tests/fixtures/laravel/9/composer.json b/tests/fixtures/php-stack/laravel/9/composer.json similarity index 100% rename from tests/fixtures/laravel/9/composer.json rename to tests/fixtures/php-stack/laravel/9/composer.json diff --git a/tests/fixtures/laravel/star/composer.json b/tests/fixtures/php-stack/laravel/star/composer.json similarity index 100% rename from tests/fixtures/laravel/star/composer.json rename to tests/fixtures/php-stack/laravel/star/composer.json diff --git a/tests/fixtures/laravel/unknown/composer.json b/tests/fixtures/php-stack/laravel/unknown/composer.json similarity index 100% rename from tests/fixtures/laravel/unknown/composer.json rename to tests/fixtures/php-stack/laravel/unknown/composer.json diff --git a/tests/fixtures/leaf/3/composer.json b/tests/fixtures/php-stack/leaf/3/composer.json similarity index 100% rename from tests/fixtures/leaf/3/composer.json rename to tests/fixtures/php-stack/leaf/3/composer.json diff --git a/tests/fixtures/lunar/1/composer.json b/tests/fixtures/php-stack/lunar/1/composer.json similarity index 100% rename from tests/fixtures/lunar/1/composer.json rename to tests/fixtures/php-stack/lunar/1/composer.json diff --git a/tests/fixtures/october_cms/4/composer.json b/tests/fixtures/php-stack/october_cms/4/composer.json similarity index 100% rename from tests/fixtures/october_cms/4/composer.json rename to tests/fixtures/php-stack/october_cms/4/composer.json diff --git a/tests/fixtures/shopware/6/composer.json b/tests/fixtures/php-stack/shopware/6/composer.json similarity index 100% rename from tests/fixtures/shopware/6/composer.json rename to tests/fixtures/php-stack/shopware/6/composer.json diff --git a/tests/fixtures/statamic/4/composer.json b/tests/fixtures/php-stack/statamic/4/composer.json similarity index 100% rename from tests/fixtures/statamic/4/composer.json rename to tests/fixtures/php-stack/statamic/4/composer.json diff --git a/tests/fixtures/statamic/unknown/composer.json b/tests/fixtures/php-stack/statamic/unknown/composer.json similarity index 100% rename from tests/fixtures/statamic/unknown/composer.json rename to tests/fixtures/php-stack/statamic/unknown/composer.json diff --git a/tests/fixtures/php-stack/symfony-in-composer-lock/composer.json b/tests/fixtures/php-stack/symfony-in-composer-lock/composer.json new file mode 100644 index 0000000..0ac81ac --- /dev/null +++ b/tests/fixtures/php-stack/symfony-in-composer-lock/composer.json @@ -0,0 +1,66 @@ +{ + "type": "project", + "license": "proprietary", + "minimum-stability": "stable", + "prefer-stable": true, + "require": { + "symfony/framework-bundle": "6.3.*", + "symfony/runtime": "6.3.*", + "symfony/yaml": "6.3.*", + "lorem/ipsum": "2.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "symfony/browser-kit": "6.3.*", + "symfony/css-selector": "6.3.*", + "symfony/phpunit-bridge": "^6.3" + }, + "config": { + "allow-plugins": { + "php-http/discovery": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } + }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php73": "*", + "symfony/polyfill-php74": "*", + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*" + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ] + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "6.3.*" + } + } +} diff --git a/tests/fixtures/php-stack/symfony-in-composer-lock/composer.lock b/tests/fixtures/php-stack/symfony-in-composer-lock/composer.lock new file mode 100644 index 0000000..4b3dcbf --- /dev/null +++ b/tests/fixtures/php-stack/symfony-in-composer-lock/composer.lock @@ -0,0 +1,316 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "0ff5bf63dfe00c079888b47286b794c9", + "packages": [ + { + "name": "someframework/foo", + "version": "v2.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<5.4", + "symfony/service-contracts": "<2.5" + }, + "require-dev": { + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v6.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-19T20:22:16+00:00" + }, + { + "name": "symfony/config", + "version": "v6.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<5.4", + "symfony/service-contracts": "<2.5" + }, + "require-dev": { + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v6.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-19T20:22:16+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v6.3.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "567cafcfc08e3076b47290a7558b0ca17a98b0ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/567cafcfc08e3076b47290a7558b0ca17a98b0ce", + "reference": "567cafcfc08e3076b47290a7558b0ca17a98b0ce", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "ext-xml": "*", + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.3.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.1", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-foundation": "^6.3", + "symfony/http-kernel": "^6.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.4|^6.0" + }, + "conflict": { + "doctrine/annotations": "<1.13.1", + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/asset": "<5.4", + "symfony/clock": "<6.3", + "symfony/console": "<5.4", + "symfony/dom-crawler": "<6.3", + "symfony/dotenv": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<6.3", + "symfony/lock": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<6.3", + "symfony/mime": "<6.2", + "symfony/property-access": "<5.4", + "symfony/property-info": "<5.4", + "symfony/security-core": "<5.4", + "symfony/security-csrf": "<5.4", + "symfony/serializer": "<6.3", + "symfony/stopwatch": "<5.4", + "symfony/translation": "<6.2.8", + "symfony/twig-bridge": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/validator": "<6.3", + "symfony/web-profiler-bundle": "<5.4", + "symfony/workflow": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13.1|^2", + "doctrine/persistence": "^1.3|^2|^3", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^5.4|^6.0", + "symfony/asset-mapper": "^6.3", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/clock": "^6.2", + "symfony/console": "^5.4.9|^6.0.9", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dom-crawler": "^6.3", + "symfony/dotenv": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/form": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", + "symfony/http-client": "^6.3", + "symfony/lock": "^5.4|^6.0", + "symfony/mailer": "^5.4|^6.0", + "symfony/messenger": "^6.3", + "symfony/mime": "^6.2", + "symfony/notifier": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/rate-limiter": "^5.4|^6.0", + "symfony/scheduler": "^6.3", + "symfony/security-bundle": "^5.4|^6.0", + "symfony/semaphore": "^5.4|^6.0", + "symfony/serializer": "^6.3", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/string": "^5.4|^6.0", + "symfony/translation": "^6.2.8", + "symfony/twig-bundle": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^6.3", + "symfony/web-link": "^5.4|^6.0", + "symfony/workflow": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0", + "twig/twig": "^2.10|^3.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/framework-bundle/tree/v6.3.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-09-29T10:45:15+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=8.1", + "ext-ctype": "*", + "ext-iconv": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/tests/fixtures/symfony/2/composer.json b/tests/fixtures/php-stack/symfony/2/composer.json similarity index 100% rename from tests/fixtures/symfony/2/composer.json rename to tests/fixtures/php-stack/symfony/2/composer.json diff --git a/tests/fixtures/symfony/3/composer.json b/tests/fixtures/php-stack/symfony/3/composer.json similarity index 100% rename from tests/fixtures/symfony/3/composer.json rename to tests/fixtures/php-stack/symfony/3/composer.json diff --git a/tests/fixtures/symfony/4/composer.json b/tests/fixtures/php-stack/symfony/4/composer.json similarity index 100% rename from tests/fixtures/symfony/4/composer.json rename to tests/fixtures/php-stack/symfony/4/composer.json diff --git a/tests/fixtures/symfony/5/composer.json b/tests/fixtures/php-stack/symfony/5/composer.json similarity index 100% rename from tests/fixtures/symfony/5/composer.json rename to tests/fixtures/php-stack/symfony/5/composer.json diff --git a/tests/fixtures/symfony/6/composer.json b/tests/fixtures/php-stack/symfony/6/composer.json similarity index 100% rename from tests/fixtures/symfony/6/composer.json rename to tests/fixtures/php-stack/symfony/6/composer.json diff --git a/tests/fixtures/symfony/unknown/composer.json b/tests/fixtures/php-stack/symfony/unknown/composer.json similarity index 100% rename from tests/fixtures/symfony/unknown/composer.json rename to tests/fixtures/php-stack/symfony/unknown/composer.json diff --git a/tests/fixtures/tempest/1/composer.json b/tests/fixtures/php-stack/tempest/1/composer.json similarity index 100% rename from tests/fixtures/tempest/1/composer.json rename to tests/fixtures/php-stack/tempest/1/composer.json diff --git a/tests/fixtures/twill/3/composer.json b/tests/fixtures/php-stack/twill/3/composer.json similarity index 100% rename from tests/fixtures/twill/3/composer.json rename to tests/fixtures/php-stack/twill/3/composer.json diff --git a/tests/fixtures/typo3_cms/13/composer.json b/tests/fixtures/php-stack/typo3_cms/13/composer.json similarity index 100% rename from tests/fixtures/typo3_cms/13/composer.json rename to tests/fixtures/php-stack/typo3_cms/13/composer.json diff --git a/tests/fixtures/winter_cms/1/composer.json b/tests/fixtures/php-stack/winter_cms/1/composer.json similarity index 100% rename from tests/fixtures/winter_cms/1/composer.json rename to tests/fixtures/php-stack/winter_cms/1/composer.json diff --git a/tests/fixtures/wordpress/1/wp-includes/vars.php b/tests/fixtures/php-stack/wordpress/1/wp-includes/vars.php similarity index 100% rename from tests/fixtures/wordpress/1/wp-includes/vars.php rename to tests/fixtures/php-stack/wordpress/1/wp-includes/vars.php diff --git a/tests/fixtures/wordpress/2/wp-includes/version.php b/tests/fixtures/php-stack/wordpress/2/wp-includes/version.php similarity index 100% rename from tests/fixtures/wordpress/2/wp-includes/version.php rename to tests/fixtures/php-stack/wordpress/2/wp-includes/version.php diff --git a/tests/fixtures/wordpress/3/wp-includes/version.php b/tests/fixtures/php-stack/wordpress/3/wp-includes/version.php similarity index 100% rename from tests/fixtures/wordpress/3/wp-includes/version.php rename to tests/fixtures/php-stack/wordpress/3/wp-includes/version.php diff --git a/tests/fixtures/wordpress/4/wp-includes/version.php b/tests/fixtures/php-stack/wordpress/4/wp-includes/version.php similarity index 100% rename from tests/fixtures/wordpress/4/wp-includes/version.php rename to tests/fixtures/php-stack/wordpress/4/wp-includes/version.php diff --git a/tests/fixtures/wordpress/5/wp-includes/version.php b/tests/fixtures/php-stack/wordpress/5/wp-includes/version.php similarity index 100% rename from tests/fixtures/wordpress/5/wp-includes/version.php rename to tests/fixtures/php-stack/wordpress/5/wp-includes/version.php diff --git a/tests/fixtures/wordpress/6/wp-includes/version.php b/tests/fixtures/php-stack/wordpress/6/wp-includes/version.php similarity index 100% rename from tests/fixtures/wordpress/6/wp-includes/version.php rename to tests/fixtures/php-stack/wordpress/6/wp-includes/version.php