diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 895a2ce..d1d49a1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,14 +11,12 @@ env: jobs: PHPUnit: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - - { php-version: 7.4, dependency-version: prefer-lowest } - - { php-version: 7.4, dependency-version: prefer-stable } - - { php-version: 8.1, dependency-version: prefer-stable } + - { php-version: 8.1, dependency-version: prefer-lowest } - { php-version: 8.2, dependency-version: prefer-stable } - { php-version: 8.3, dependency-version: prefer-stable } name: PHPUnit (PHP ${{matrix.php-version}}, ${{ matrix.dependency-version }}) diff --git a/composer.json b/composer.json index 7803dce..733362c 100644 --- a/composer.json +++ b/composer.json @@ -8,18 +8,20 @@ }, "require": { - "php": ">= 7.4, < 8.4", + "php": ">= 8.1", "doctrine/annotations": "^1.12", "jms/metadata": "^2.6.1", - "symfony/property-access": "^3.4|^4.0|^5.0|^6.0|^7.0" + "symfony/property-access": "^3.4|^4.0|^5.0|^6.0|^7.0", + "symfony/deprecation-contracts": "^3.4" }, "require-dev": { "doctrine/common": "^2.2", - "phpunit/phpunit": "^8.5.26|^9.0", + "phpunit/phpunit": "^9.6", "symfony/routing": "^2.2|^3.0|^4.0", "symfony/yaml": "^3.0|^4.0|^5.0", - "twig/twig": "^2.0|^3.0" + "twig/twig": "^2.0|^3.0", + "symfony/phpunit-bridge": ">5.0" }, "conflict": { diff --git a/src/JMS/ObjectRouting/Annotation/ObjectRoute.php b/src/JMS/ObjectRouting/Annotation/ObjectRoute.php index f579623..7c86ae5 100644 --- a/src/JMS/ObjectRouting/Annotation/ObjectRoute.php +++ b/src/JMS/ObjectRouting/Annotation/ObjectRoute.php @@ -19,26 +19,16 @@ namespace JMS\ObjectRouting\Annotation; /** + * @deprecated * @Annotation * @NamedArgumentConstructor * @Target("CLASS") */ -#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)] -final class ObjectRoute +final class ObjectRoute extends \JMS\ObjectRouting\Attribute\ObjectRoute { - /** @var string @Required */ - public $type; - - /** @var string @Required */ - public $name; - - /** @var array */ - public $params = array(); - public function __construct(string $type, string $name, array $params = []) { - $this->type = $type; - $this->name = $name; - $this->params = $params; + trigger_deprecation('webfactory/object-routing', '1.7.0', 'Using annotations to configure object routes is deprecated. Use the %s attribute instead', \JMS\ObjectRouting\Attribute\ObjectRoute::class); + parent::__construct($type, $name, $params); } } diff --git a/src/JMS/ObjectRouting/Attribute/ObjectRoute.php b/src/JMS/ObjectRouting/Attribute/ObjectRoute.php new file mode 100644 index 0000000..433c5cb --- /dev/null +++ b/src/JMS/ObjectRouting/Attribute/ObjectRoute.php @@ -0,0 +1,40 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace JMS\ObjectRouting\Attribute; + +/** @final */ +#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)] +class ObjectRoute +{ + /** @var string @Required */ + public $type; + + /** @var string @Required */ + public $name; + + /** @var array */ + public $params = array(); + + public function __construct(string $type, string $name, array $params = []) + { + $this->type = $type; + $this->name = $name; + $this->params = $params; + } +} diff --git a/src/JMS/ObjectRouting/Metadata/Driver/AnnotationDriver.php b/src/JMS/ObjectRouting/Metadata/Driver/AnnotationDriver.php index 9ca01c7..803e501 100644 --- a/src/JMS/ObjectRouting/Metadata/Driver/AnnotationDriver.php +++ b/src/JMS/ObjectRouting/Metadata/Driver/AnnotationDriver.php @@ -23,12 +23,16 @@ use JMS\ObjectRouting\Metadata\ClassMetadata; use Metadata\Driver\DriverInterface; +/** + * @deprecated + */ class AnnotationDriver implements DriverInterface { private $reader; public function __construct(Reader $reader) { + trigger_deprecation('webfactory/object-routing', '1.7.0', 'The %s driver is deprecated. Use another configuration mechanism, or switch from annotations to PHP 8 attributes.', self::class); $this->reader = $reader; } @@ -51,14 +55,16 @@ private function buildAnnotations(\ReflectionClass $class): array { $annots = []; - if (PHP_MAJOR_VERSION >= 8) { - foreach ($class->getAttributes() as $attr) { - if (str_starts_with($attr->getName(), 'JMS\\ObjectRouting\\Annotation\\')) { - $annots[] = $attr->newInstance(); - } + foreach ($class->getAttributes() as $attr) { + if (str_starts_with($attr->getName(), 'JMS\\ObjectRouting\\Annotation\\')) { + $annots[] = $attr->newInstance(); } } + if ($annots) { + trigger_deprecation('webfactory/object-routing', '1.7.0', 'Discovering object route attributes through the %s driver is deprecated. Make sure the %s driver is used with a higher priority.', self::class, AttributeDriver::class); + } + return $annots; } } diff --git a/src/JMS/ObjectRouting/Metadata/Driver/AttributeDriver.php b/src/JMS/ObjectRouting/Metadata/Driver/AttributeDriver.php new file mode 100644 index 0000000..3a74288 --- /dev/null +++ b/src/JMS/ObjectRouting/Metadata/Driver/AttributeDriver.php @@ -0,0 +1,50 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace JMS\ObjectRouting\Metadata\Driver; + +use JMS\ObjectRouting\Attribute\ObjectRoute; +use JMS\ObjectRouting\Metadata\ClassMetadata; +use Metadata\Driver\DriverInterface; + +class AttributeDriver implements DriverInterface +{ + public function loadMetadataForClass(\ReflectionClass $class): ?ClassMetadata + { + $metadata = new ClassMetadata($class->name); + + $hasMetadata = false; + foreach ($this->fetchAttributes($class) as $attribute) { + $hasMetadata = true; + $metadata->addRoute($attribute->type, $attribute->name, $attribute->params); + } + + return $hasMetadata ? $metadata : null; + } + + private function fetchAttributes(\ReflectionClass $class): array + { + $attributes = []; + + foreach ($class->getAttributes(ObjectRoute::class) as $attr) { + $attributes[] = $attr->newInstance(); + } + + return $attributes; + } +} diff --git a/tests/JMS/Tests/ObjectRouting/Metadata/Driver/AttributeDriverTest.php b/tests/JMS/Tests/ObjectRouting/Metadata/Driver/AttributeDriverTest.php new file mode 100644 index 0000000..7755b0a --- /dev/null +++ b/tests/JMS/Tests/ObjectRouting/Metadata/Driver/AttributeDriverTest.php @@ -0,0 +1,34 @@ +driver->loadMetadataForClass(new \ReflectionClass(BlogPostWithAttributes::class)); + $this->assertCount(2, $metadata->routes); + + $routes = [ + 'view' => ['name' => 'blog_post_view', 'params' => ['slug' => 'slug']], + 'edit' => ['name' => 'blog_post_edit', 'params' => ['slug' => 'slug']], + ]; + $this->assertEquals($routes, $metadata->routes); + } + + public function testLoadReturnsNullWhenNoRoutes() + { + $this->assertNull($this->driver->loadMetadataForClass(new \ReflectionClass('stdClass'))); + } + + protected function setUp(): void + { + $this->driver = new AttributeDriver(); + } +} diff --git a/tests/JMS/Tests/ObjectRouting/Metadata/Driver/Fixture/BlogPostWithAttributes.php b/tests/JMS/Tests/ObjectRouting/Metadata/Driver/Fixture/BlogPostWithAttributes.php new file mode 100644 index 0000000..90c61be --- /dev/null +++ b/tests/JMS/Tests/ObjectRouting/Metadata/Driver/Fixture/BlogPostWithAttributes.php @@ -0,0 +1,22 @@ + 'slug'])] +#[ObjectRoute(type: "edit", name: "blog_post_edit", params: ['slug' => 'slug'])] +class BlogPostWithAttributes +{ + private $slug; + + public function __construct($slug) + { + $this->slug = $slug; + } + + public function getSlug() + { + return $this->slug; + } +}