Skip to content

Commit

Permalink
Add a dedicated AttributeDriver, deprecate annotations (#9)
Browse files Browse the repository at this point in the history
This PR prepares the removal of annotations support, which helps to prepare https://github.com/webfactory/BGObjectRoutingBundle for Symfony 7. 

symfony/framework-bundle 7.x does not ship the `annotation_reader` anymore, and instead of wiring up an annotation reader ourselves, I'd prefer to go down the attributes path.
  • Loading branch information
mpdude authored Apr 4, 2024
1 parent 1178380 commit aab21ab
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 27 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }})
Expand Down
10 changes: 6 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
18 changes: 4 additions & 14 deletions src/JMS/ObjectRouting/Annotation/ObjectRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
40 changes: 40 additions & 0 deletions src/JMS/ObjectRouting/Attribute/ObjectRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/*
* Copyright 2013 Johannes M. Schmitt <[email protected]>
*
* 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;
}
}
16 changes: 11 additions & 5 deletions src/JMS/ObjectRouting/Metadata/Driver/AnnotationDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}
}
50 changes: 50 additions & 0 deletions src/JMS/ObjectRouting/Metadata/Driver/AttributeDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/*
* Copyright 2013 Johannes M. Schmitt <[email protected]>
*
* 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace JMS\Tests\ObjectRouting\Metadata\Driver;

use JMS\ObjectRouting\Metadata\Driver\AttributeDriver;
use JMS\Tests\ObjectRouting\Metadata\Driver\Fixture\BlogPostWithAttributes;
use PHPUnit\Framework\TestCase;

class AttributeDriverTest extends TestCase
{
private readonly AttributeDriver $driver;

public function testLoad()
{
$metadata = $this->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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace JMS\Tests\ObjectRouting\Metadata\Driver\Fixture;

use JMS\ObjectRouting\Attribute\ObjectRoute;

#[ObjectRoute(type: "view", name: "blog_post_view", params: ['slug' => '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;
}
}

0 comments on commit aab21ab

Please sign in to comment.