Skip to content

Commit

Permalink
chore: components dependencies (#6113)
Browse files Browse the repository at this point in the history
* chore: components dependencies

* test
  • Loading branch information
soyuka committed Jan 19, 2024
1 parent ce9ab82 commit 93fab65
Show file tree
Hide file tree
Showing 238 changed files with 6,157 additions and 877 deletions.
20 changes: 5 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ jobs:
ini-values: memory_limit=-1
tools: pecl, composer
coverage: none
- name: Download PHPArkitect PHAR
run: |
wget -q https://github.com/phparkitect/arkitect/releases/latest/download/phparkitect.phar
chmod +x phparkitect.phar
- name: Get composer cache directory
id: composercache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
Expand All @@ -68,8 +64,7 @@ jobs:
- name: Update project dependencies
run: |
composer update --no-interaction --no-progress --ansi
- name: Run PHPArkitect
run: ./phparkitect.phar check
- run: php components.php

php-cs-fixer:
name: PHP CS Fixer (PHP ${{ matrix.php }})
Expand Down Expand Up @@ -145,8 +140,6 @@ jobs:
rm -Rf tests/Fixtures/app/var/cache/*
tests/Fixtures/app/console cache:warmup
- name: Run PHPStan analysis
env:
SYMFONY_PHPUNIT_VERSION: '9.5'
run: |
./vendor/bin/phpstan --version
./vendor/bin/phpstan analyse --no-interaction --no-progress --ansi
Expand Down Expand Up @@ -244,6 +237,9 @@ jobs:
- GraphQl
- Serializer
- Symfony
- Doctrine/Common
- Doctrine/Orm
- Doctrine/Odm
include:
- php: '8.1'
coverage: true
Expand Down Expand Up @@ -768,8 +764,6 @@ jobs:
restore-keys: ${{ runner.os }}-composer-
- name: Update project dependencies
run: composer update --prefer-lowest --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Run Behat tests
Expand Down Expand Up @@ -1033,12 +1027,10 @@ jobs:
run: rm -Rf tests/Fixtures/app/var/cache/*
- name: Update project dependencies
run: composer update --prefer-lowest --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Run PHPUnit tests
run: vendor/bin/simple-phpunit
run: vendor/bin/phpunit
env:
SYMFONY_DEPRECATIONS_HELPER: max[self]=0&ignoreFile=./tests/.ignored-deprecations

Expand Down Expand Up @@ -1077,8 +1069,6 @@ jobs:
run: rm -Rf tests/Fixtures/app/var/cache/*
- name: Update project dependencies
run: composer update --prefer-lowest --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Run Behat tests
Expand Down
3 changes: 2 additions & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
'tests/Fixtures/app/var',
'docs/guides',
'docs/var',
'**vendor**'
'src/Doctrine/Orm/Tests/var',
'src/Doctrine/Odm/Tests/var'
])
->notPath('src/Symfony/Bundle/DependencyInjection/Configuration.php')
->notPath('src/Annotation/ApiFilter.php') // temporary
Expand Down
168 changes: 168 additions & 0 deletions components.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

/*
* This script checks for dependencies between our components
* and fails if a component has a wrong dependency.
*/
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Finder\Finder;

$loader = require './vendor/autoload.php';
$namespace = 'ApiPlatform';
$prefix = 'api-platform';
$ignoreList = ['ApiPlatform\\Api', 'ApiPlatform\\Exception', 'ApiPlatform\\Util'];
$stopOnFailure = in_array('--stop-on-failure', $_SERVER['argv'], true);
$skipPaths = [__DIR__.'/src/GraphQl/Resolver/Stage'];

/**
* Reads the beginning of a PHP class and returns "use" instructions matching our namespace.
*/
$class_uses_namespaces = function (ReflectionClass $r) use ($namespace): \Generator {
$fp = fopen($r->getFileName(), 'r');
$u = 'use';
$c = false;
while (($buffer = fgets($fp, 4096)) !== false) {
if ($c && \PHP_EOL === $buffer) {
break;
}

if (!str_starts_with($buffer, $u)) {
continue;
}

$c = true;
$buffer = substr($buffer, 4, -2);
if (str_starts_with($buffer, $namespace)) {
yield substr($buffer, 0, strpos($buffer, ' ') ?: null);
}
}

fclose($fp);
};

// Creates and require the map of dependencies
$directories = [];
$map = [];
foreach (Finder::create()->in('src')->notPath('vendor')->name('composer.json') as $f) {
if (null === ($component = json_decode($f->getContents(), true))) {
continue;
}

$filter = fn ($v) => str_starts_with($v, $prefix);
$dependencies =
array_merge(
array_filter(array_keys((array) $component['require']), $filter),
array_filter(array_keys((array) $component['require-dev'] ?? []), $filter)
);

$map[$component['name']] = ['namespace' => substr(key($component['autoload']['psr-4']), 0, -1), 'dependencies' => $dependencies];
$directories[] = substr($f->getRealPath(), 0, -14);

foreach (Finder::create()->in($f->getPath())->notPath('vendor')->notPath('var')->name('*.php')->notName('*.tpl.php')->notName('bootstrap.php') as $f) {
require_once $f->getRealPath();
}
}

// create a PSR map of dependencies
$psrMap = [];
foreach ($map as $component) {
$depsPsr = [];
foreach ($component['dependencies'] as $d) {
$depsPsr[] = $map[$d]['namespace'];
}

$psrMap[$component['namespace']] = $depsPsr;
}

$warned = [];
$getComponentNamespace = function (ReflectionClass $r, ReflectionClass $inside = null) use ($psrMap, $warned, $ignoreList, $namespace) {
$ns = $r->getNamespaceName();
// Find this components namespace
$nsParts = explode('\\', $ns);
$n = count($nsParts);
$componentNs = $nsParts[0].'\\'.$nsParts[1];
$i = 2;

while (!isset($psrMap[$componentNs]) && $i < $n) {
if ($part = ($nsParts[$i++] ?? null)) {
$componentNs .= '\\'.$part;
}
}

if (!isset($psrMap[$componentNs])) {
if (in_array($componentNs, $ignoreList, true)) {
return null;
}

$guess = $nsParts[0].'\\'.$nsParts[1];
if ($warned[$guess] ?? true) {
echo sprintf('"%s" is not an %s component at "%s" %s', $guess, $namespace, ($inside ?? $r)->getFileName(), \PHP_EOL);
$warned[$guess] = false;
}

return null;
}

return $componentNs;
};

$exitCode = 0;
$lnamespace = strlen($namespace);
foreach (array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()) as $className) {
$r = new ReflectionClass($className);
$ns = $r->getNamespaceName();

foreach ($skipPaths as $base) {
if (!($fileName = $r->getFileName())) {
continue;
}

if (Path::isBasePath($skipPaths[0], $fileName)) {
continue 2;
}
}

if (!str_starts_with($ns, $namespace)) {
continue;
}

$componentNs = $getComponentNamespace($r);

if (!$componentNs) {
continue;
}

foreach ($class_uses_namespaces($r) as $u) {
if (str_starts_with($u, $componentNs)) {
continue;
}

$useNs = $getComponentNamespace(new ReflectionClass($u), $r);

if (!$useNs || $useNs === $componentNs) {
continue;
}

if (!in_array($useNs, $psrMap[$componentNs], true)) {
echo sprintf('"%s" uses "%s" although "%s" is not one of its dependencies %s', $className, $u, $useNs, \PHP_EOL);
$exitCode = 1;

if ($stopOnFailure) {
exit($exitCode);
}
}
}
}

exit($exitCode);
74 changes: 37 additions & 37 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
"psr/cache": "^1.0 || ^2.0 || ^3.0",
"psr/container": "^1.0 || ^2.0",
"symfony/deprecation-contracts": "^3.1",
"symfony/http-foundation": "^6.1 || ^7.0",
"symfony/http-kernel": "^6.1 || ^7.0",
"symfony/property-access": "^6.1 || ^7.0",
"symfony/property-info": "^6.1 || ^7.0",
"symfony/serializer": "^6.1 || ^7.0",
"symfony/http-foundation": "^6.4 || ^7.0",
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/property-access": "^6.4 || ^7.0",
"symfony/property-info": "^6.4 || ^7.0",
"symfony/serializer": "^6.4 || ^7.0",
"symfony/translation-contracts": "^3.3",
"symfony/web-link": "^6.1 || ^7.0",
"symfony/web-link": "^6.4 || ^7.0",
"willdurand/negotiation": "^3.0"
},
"require-dev": {
Expand All @@ -57,47 +57,47 @@
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpdoc-parser": "^1.13",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-doctrine": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-symfony": "^1.0",
"phpunit/phpunit": "^9.5",
"phpunit/phpunit": "^9.6",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"ramsey/uuid": "^3.9.7 || ^4.0",
"ramsey/uuid-doctrine": "^1.4 || ^2.0",
"sebastian/comparator": "<5.0",
"soyuka/contexts": "v3.3.9",
"soyuka/stubs-mongodb": "^1.0",
"symfony/asset": "^6.1 || ^7.0",
"symfony/browser-kit": "^6.1 || ^7.0",
"symfony/cache": "^6.1 || ^7.0",
"symfony/config": "^6.1 || ^7.0",
"symfony/console": "^6.1 || ^7.0",
"symfony/css-selector": "^6.1 || ^7.0",
"symfony/dependency-injection": "^6.1 || ^7.0.12",
"symfony/doctrine-bridge": "^6.1 || ^7.0",
"symfony/dom-crawler": "^6.1 || ^7.0",
"symfony/error-handler": "^6.1 || ^7.0",
"symfony/event-dispatcher": "^6.1 || ^7.0",
"symfony/expression-language": "^6.1 || ^7.0",
"symfony/finder": "^6.1 || ^7.0",
"symfony/form": "^6.1 || ^7.0",
"symfony/framework-bundle": "^6.1 || ^7.0",
"symfony/http-client": "^6.1 || ^7.0",
"symfony/intl": "^6.1 || ^7.0",
"symfony/asset": "^6.4 || ^7.0",
"symfony/browser-kit": "^6.4 || ^7.0",
"symfony/cache": "^6.4 || ^7.0",
"symfony/config": "^6.4 || ^7.0",
"symfony/console": "^6.4 || ^7.0",
"symfony/css-selector": "^6.4 || ^7.0",
"symfony/dependency-injection": "^6.4 || ^7.0.12",
"symfony/doctrine-bridge": "^6.4 || ^7.0",
"symfony/dom-crawler": "^6.4 || ^7.0",
"symfony/error-handler": "^6.4 || ^7.0",
"symfony/event-dispatcher": "^6.4 || ^7.0",
"symfony/expression-language": "^6.4 || ^7.0",
"symfony/finder": "^6.4 || ^7.0",
"symfony/form": "^6.4 || ^7.0",
"symfony/framework-bundle": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"symfony/intl": "^6.4 || ^7.0",
"symfony/maker-bundle": "^1.24",
"symfony/mercure-bundle": "*",
"symfony/messenger": "^6.1 || ^7.0",
"symfony/phpunit-bridge": "^6.1 || ^7.0",
"symfony/routing": "^6.1 || ^7.0",
"symfony/security-bundle": "^6.1 || ^7.0",
"symfony/security-core": "^6.1 || ^7.0",
"symfony/stopwatch": "^6.1 || ^7.0",
"symfony/twig-bundle": "^6.1 || ^7.0",
"symfony/uid": "^6.1 || ^7.0",
"symfony/validator": "^6.1 || ^7.0",
"symfony/web-profiler-bundle": "^6.1 || ^7.0",
"symfony/yaml": "^6.1 || ^7.0",
"symfony/messenger": "^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4 || ^7.0",
"symfony/routing": "^6.4 || ^7.0",
"symfony/security-bundle": "^6.4 || ^7.0",
"symfony/security-core": "^6.4 || ^7.0",
"symfony/stopwatch": "^6.4 || ^7.0",
"symfony/twig-bundle": "^6.4 || ^7.0",
"symfony/uid": "^6.4 || ^7.0",
"symfony/validator": "^6.4 || ^7.0",
"symfony/web-profiler-bundle": "^6.4 || ^7.0",
"symfony/yaml": "^6.4 || ^7.0",
"twig/twig": "^1.42.3 || ^2.12 || ^3.0",
"webonyx/graphql-php": "^14.0 || ^15.0"
},
Expand Down Expand Up @@ -157,7 +157,7 @@
"dev-main": "3.3.x-dev"
},
"symfony": {
"require": "^6.1 || ^7.0"
"require": "^6.4 || ^7.0"
}
}
}
5 changes: 0 additions & 5 deletions phparkitect-baseline.json

This file was deleted.

0 comments on commit 93fab65

Please sign in to comment.