Skip to content

Commit

Permalink
Add support for Symfony 7 where able
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Schranz <[email protected]>
  • Loading branch information
mbabker and alexander-schranz committed Apr 3, 2024
1 parent 3fafc1e commit c893697
Show file tree
Hide file tree
Showing 47 changed files with 568 additions and 437 deletions.
40 changes: 31 additions & 9 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ jobs:
continue-on-error: ${{ matrix.can-fail }}

strategy:
fail-fast: false
matrix:
include:
- php-version: 7.2
composer-flags: "--prefer-lowest "
- php-version: 7.4
composer-flags: "--prefer-lowest"
symfony-require: "5.4.*"
can-fail: false
- php-version: 7.3
- php-version: 7.4
composer-flags: ""
can-fail: false
- php-version: 7.4
Expand All @@ -34,22 +36,32 @@ jobs:
- php-version: 8.0
composer-flags: ""
can-fail: false
symfony-require: "6.0.*"
symfony-require: "5.4.*"
- php-version: 8.1
composer-flags: ""
can-fail: false
symfony-require: "6.1.*"
symfony-require: "6.4.*"
- php-version: 8.2
composer-flags: ""
can-fail: false
symfony-require: "6.4.*"
- php-version: 8.2
composer-flags: ""
can-fail: false
symfony-require: "6.2.*"
symfony-require: "6.4.*"
remove-sensio-bundle: yes # Smoke test with SensioFrameworkExtraBundle removed on latest Symfony LTS
- php-version: 8.2
composer-flags: ""
can-fail: false
symfony-require: "6.3.*"
symfony-require: "7.0.*"
remove-sensio-bundle: yes # SensioFrameworkExtraBundle is not compatible with Symfony 7.0 or later
- php-version: 8.2
composer-flags: ""
can-fail: true # we don't want to fail the build if we are incompatible with the next (unstable) Symfony version
remove-sensio-bundle: yes # SensioFrameworkExtraBundle is not compatible with Symfony 7.0 or later

env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}

steps:
- name: "Checkout"
Expand Down Expand Up @@ -78,11 +90,17 @@ jobs:
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
restore-keys: "php-${{ matrix.php-version }}-composer-locked-"

- name: "Remove SensioFrameworkExtraBundle if required"
if: "${{ matrix.remove-sensio-bundle == 'yes' }}"
env:
SYMFONY_REQUIRE: "${{ matrix.symfony-require }}"
run: |
composer remove --no-update --dev sensio/framework-extra-bundle
- name: "Install dependencies with composer"
env:
SYMFONY_REQUIRE: "${{ matrix.symfony-require }}"
run: |
composer remove friendsofphp/php-cs-fixer --dev --no-update
composer update --no-interaction --no-progress ${{ matrix.composer-flags }}
- name: "Run PHPUnit"
Expand All @@ -93,5 +111,9 @@ jobs:
php ocular.phar code-coverage:upload --format=php-clover coverage.clover
- name: "Run PHPUnit"
if: "${{ matrix.coverage == '' }}"
if: "${{ matrix.coverage == '' }} && ${{ matrix.php-version != '8.0' }}"
run: "./phpunit"

- name: "Run PHPUnit (debug)"
if: "${{ matrix.coverage == '' }} && ${{ matrix.php-version == '8.0' }}"
run: "./phpunit --debug"
146 changes: 77 additions & 69 deletions Controller/Annotations/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,28 @@

namespace FOS\RestBundle\Controller\Annotations;

use Symfony\Component\Routing\Annotation\Route as BaseRoute;
use Symfony\Component\Routing\Annotation\Route as BaseAnnotationRoute;
use Symfony\Component\Routing\Attribute\Route as BaseAttributeRoute;

if (class_exists(BaseAttributeRoute::class)) {
/**
* Compatibility layer for Symfony 6.4 and later.
*
* @internal
*/
class CompatRoute extends BaseAttributeRoute
{
}
} else {
/**
* Compatibility layer for Symfony 6.3 and earlier.
*
* @internal
*/
class CompatRoute extends BaseAnnotationRoute
{
}
}

/**
* Route annotation class.
Expand All @@ -21,8 +42,17 @@
* @Target({"CLASS", "METHOD"})
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
class Route extends BaseRoute
class Route extends CompatRoute
{
/**
* @param array|string $data
* @param array|string|null $path
* @param string[] $requirements
* @param string[]|string $methods
* @param string[]|string $schemes
*
* @throws \TypeError if the $data argument is an unsupported type
*/
public function __construct(
$data = [],
$path = null,
Expand All @@ -41,78 +71,56 @@ public function __construct(
bool $stateless = null,
string $env = null
) {
// BC layer for symfony < 5.2
// Before symfony/routing 5.2 the constructor only had one parameter
$method = new \ReflectionMethod(BaseRoute::class, '__construct');
if (1 === $method->getNumberOfParameters()) {
// Use Reflection to get the constructor from the parent class two levels up (accounting for our compat definition)
$method = (new \ReflectionClass($this))->getParentClass()->getParentClass()->getMethod('__construct');

// The $data constructor parameter was removed in Symfony 6.0 in favor of named arguments
if ('data' === $method->getParameters()[0]->getName()) {
parent::__construct(
$data,
$path,
$name,
$requirements,
$options,
$defaults,
$host,
$methods,
$schemes,
$condition,
$priority,
$locale,
$format,
$utf8,
$stateless,
$env
);
} else {
if (\is_string($data)) {
$path = $data;
$data = [];
$data = ['path' => $data];
} elseif (!\is_array($data)) {
throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data)));
} elseif (0 !== count($data) && [] === \array_intersect(\array_keys($data), ['path', 'name', 'requirements', 'options', 'defaults', 'host', 'methods', 'schemes', 'condition', 'priority', 'locale', 'format', 'utf8', 'stateless', 'env'])) {
$localizedPaths = $data;
$data = ['path' => $localizedPaths];
}

$data['path'] = $path;
$data['name'] = $name;
$data['requirements'] = $requirements;
$data['options'] = $options;
$data['defaults'] = $defaults;
$data['host'] = $host;
$data['methods'] = $methods;
$data['schemes'] = $schemes;
$data['condition'] = $condition;

parent::__construct($data);
} else {
// BC layer for symfony < 6.0
// The constructor parameter $data has been removed since symfony 6.0
if ('data' === $method->getParameters()[0]->getName()) {
parent::__construct(
$data,
$path,
$name,
$requirements,
$options,
$defaults,
$host,
$methods,
$schemes,
$condition,
$priority,
$locale,
$format,
$utf8,
$stateless,
$env
);
} else {
if (\is_string($data)) {
$data = ['path' => $data];
} elseif (!\is_array($data)) {
throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data)));
} elseif (0 !== count($data) && [] === \array_intersect(\array_keys($data), ['path', 'name', 'requirements', 'options', 'defaults', 'host', 'methods', 'schemes', 'condition', 'priority', 'locale', 'format', 'utf8', 'stateless', 'env'])) {
$localizedPaths = $data;
$data = ['path' => $localizedPaths];
}

parent::__construct(
$data['path'] ?? $path,
$data['name'] ?? $name,
$data['requirements'] ?? $requirements,
$data['options'] ?? $options,
$data['defaults'] ?? $defaults,
$data['host'] ?? $host,
$data['methods'] ?? $methods,
$data['schemes'] ?? $schemes,
$data['condition'] ?? $condition,
$data['priority'] ?? $priority,
$data['locale'] ?? $locale,
$data['format'] ?? $format,
$data['utf8'] ?? $utf8,
$data['stateless'] ?? $stateless,
$data['env'] ?? $env
);
}
parent::__construct(
$data['path'] ?? $path,
$data['name'] ?? $name,
$data['requirements'] ?? $requirements,
$data['options'] ?? $options,
$data['defaults'] ?? $defaults,
$data['host'] ?? $host,
$data['methods'] ?? $methods,
$data['schemes'] ?? $schemes,
$data['condition'] ?? $condition,
$data['priority'] ?? $priority,
$data['locale'] ?? $locale,
$data['format'] ?? $format,
$data['utf8'] ?? $utf8,
$data['stateless'] ?? $stateless,
$data['env'] ?? $env
);
}

if (!$this->getMethods()) {
Expand Down
Loading

0 comments on commit c893697

Please sign in to comment.