Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to min PHP 8 and Symfony 5.4, drop doctrine/annotations dependency. #22

Merged
merged 1 commit into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
strategy:
matrix:
php-version:
- "7.3"
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"

steps:
- name: "Checkout"
Expand Down
50 changes: 13 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class AppKernel extends Kernel

### 2. Define breadcrumbs

There are three ways to create a breadcrumb: via code (1), via attributes (2) (PHP 8.0+) or via annotations (3).
There are two ways to create a breadcrumb: via code (1) or via attributes (2).

*Via code*: you can inject the breadcrumb builder in your controller and add breadcrumb items:

Expand Down Expand Up @@ -77,7 +77,7 @@ class CoolController extends Controller
```php
<?php

use SlopeIt\BreadcrumbBundle\Annotation\Breadcrumb;
use SlopeIt\BreadcrumbBundle\Attribute\Breadcrumb;

#[Breadcrumb([
'label' => 'home',
Expand All @@ -98,32 +98,6 @@ class CoolController extends Controller
}
```

*Via annotations*: just use the `@Breadcrumb` annotation at the class and/or method level. They will be merged (class comes first).

*NOTE:* The annotation can take either a single item (in the example it's done at the class level) or multiple items (in the example, at the method level).

```php
<?php

use SlopeIt\BreadcrumbBundle\Annotation\Breadcrumb;

/**
* @Breadcrumb({"label" = "home", "route" = "home_route", "params" = {"p" = "val"}, "translationDomain" = "domain" })
*/
class CoolController extends Controller
{
/**
* @Breadcrumb({
* { "label" = "$entity.property", "route" = "entity_route" },
* { "label" = "cool_stuff" }
* })
*/
public function coolStuffAction()
{
// ...
}
```

### 3. Render breadcrumb

The last step is to use the following Twig function wherever you want the breadcrumb printed in your template:
Expand Down Expand Up @@ -173,15 +147,17 @@ child_edit | { parent_id: 12345, child_id: 67890 } | /parents/12345/children/
If you are in the action for route `children_edit` and you want to generate a breadcrumb including all the above steps, you will be able to use the following annotation:

```php
/**
* @Breadcrumb({
* { "label" = "parents", "route" = "parent_list" },
* { "label" = "$parent.name", "route" = "parent_view" },
* { "label" = "children", "route" = "children_list" },
* { "label" = "$child.name", "route" = "child_view" },
* { "label" = "edit" }
* })
*/
<?php

use SlopeIt\BreadcrumbBundle\Attribute\Breadcrumb;

#[Breadcrumb([
['label' => 'parents', 'route' => 'parent_list'],
['label' => '$parent.name', 'route' => 'parent_view'],
['label' => 'children', 'route' => 'children_list'],
['label' => '$child.name', 'route' => 'child_view'],
['label' => 'edit'],
])]
public function childrenEditAction($parentID, $childrenID)
{
// ...
Expand Down
23 changes: 23 additions & 0 deletions UPGRADE-2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# UPGRADE FROM 1.x to 2.0

- Removed annotations in favor of attributes. Migration should be straightforward, here's a quick example:

Before:
```php
use SlopeIt\BreadcrumbBundle\Annotation\Breadcrumb;

/**
* @Breadcrumb({
* { "label" = "home", "route" = "home_route" },
* })
*/
class CoolController extends Controller
```

After:
```php
use SlopeIt\BreadcrumbBundle\Attribute\Breadcrumb;

#[Breadcrumb(['label' => 'home', 'route' => 'home_route'])]
class CoolController extends Controller
```
13 changes: 6 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,17 @@
}
],
"require": {
"php": ">=7.3.0",
"doctrine/annotations": "^1.0",
"symfony/framework-bundle": "^4.0|^5.0|^6.0",
"symfony/property-access": "^4.0|^5.0|^6.0",
"symfony/translation": "^4.0|^5.0|^6.0",
"symfony/yaml": "^4.0|^5.0|^6.0",
"php": ">=8.0.0",
"symfony/framework-bundle": "^5.4|^6.3|^7.0",
"symfony/property-access": "^5.4|^6.3|^7.0",
"symfony/translation": "^5.4|^6.3|^7.0",
"symfony/yaml": "^5.4|^6.3|^7.0",
"twig/twig": "^2.10|^3.0"
},
"require-dev": {
"mockery/mockery": "^1.3",
"phpunit/phpunit": "8.5.15",
"symfony/dependency-injection": "^4.0|^5.0",
"symfony/dependency-injection": "^5.4|^6.3|^7.0",
"symfony/monolog-bundle": "^3.7"
},
"autoload": {
Expand Down
15 changes: 2 additions & 13 deletions src/Annotation/Breadcrumb.php → src/Attribute/Breadcrumb.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
<?php

namespace SlopeIt\BreadcrumbBundle\Annotation;
namespace SlopeIt\BreadcrumbBundle\Attribute;

/**
* @Annotation
* @Target({"CLASS","METHOD"})
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
class Breadcrumb
{
Expand All @@ -21,21 +17,14 @@ class Breadcrumb
* - params: optional, if provided must be an array of key-value parameters needed to generate the route. Parameter
* values can be provided either statically or using the same $variable.property.path syntax used by "label".
* See note above regarding the "route" key to know when you need to provide route params explicitly.
*
* @var array
*/
public $items;
public array $items;

/**
* @param array $items An array of items or a single item.
*/
public function __construct(array $items)
{
// 'value' is present in case this class is used as annotation.
if (array_key_exists('value', $items)) {
$items = $items['value'];
}

// $items can be either a single item or an array of items, for convenience. Normalize it to an array of items.
if (array_key_exists('label', $items)) {
$items = [$items];
Expand Down
3 changes: 0 additions & 3 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder(): TreeBuilder
{
$builder = new TreeBuilder('slope_it_breadcrumb');
Expand Down
6 changes: 0 additions & 6 deletions src/DependencyInjection/SlopeItBreadcrumbExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,11 @@

class SlopeItBreadcrumbExtension extends Extension
{
/**
* {@inheritdoc}
*/
public function getAlias(): string
{
return 'slope_it_breadcrumb';
}

/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container): void
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
Expand Down
26 changes: 5 additions & 21 deletions src/EventListener/BreadcrumbListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,17 @@

namespace SlopeIt\BreadcrumbBundle\EventListener;

use SlopeIt\BreadcrumbBundle\Annotation\Breadcrumb;
use SlopeIt\BreadcrumbBundle\Attribute\Breadcrumb;
use SlopeIt\BreadcrumbBundle\Service\BreadcrumbBuilder;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpKernel\Event\ControllerEvent;

class BreadcrumbListener
{
/**
* @var Reader
*/
private $annotationReader;
private BreadcrumbBuilder $breadcrumbBuilder;

/**
* @var BreadcrumbBuilder
*/
private $breadcrumbBuilder;

public function __construct(BreadcrumbBuilder $breadcrumbBuilder, Reader $annotationReader)
public function __construct(BreadcrumbBuilder $breadcrumbBuilder)
{
$this->breadcrumbBuilder = $breadcrumbBuilder;
$this->annotationReader = $annotationReader;
}

public function onKernelController(ControllerEvent $event): void
Expand All @@ -38,16 +28,10 @@ public function onKernelController(ControllerEvent $event): void
$method = new \ReflectionMethod($controller, $action);

$breadcrumbs = [];
if (($classAnnotation = $this->annotationReader->getClassAnnotation($class, Breadcrumb::class))) {
$breadcrumbs[] = $classAnnotation;
}
if (\PHP_VERSION_ID >= 80000 && ($classAttribute = $class->getAttributes(Breadcrumb::class)[0] ?? null)) {
if (($classAttribute = $class->getAttributes(Breadcrumb::class)[0] ?? null)) {
$breadcrumbs[] = $classAttribute->newInstance();
}
if (($methodAnnotation = $this->annotationReader->getMethodAnnotation($method, Breadcrumb::class))) {
$breadcrumbs[] = $methodAnnotation;
}
if (\PHP_VERSION_ID >= 80000 && ($methodAttribute = $method->getAttributes(Breadcrumb::class)[0] ?? null)) {
if (($methodAttribute = $method->getAttributes(Breadcrumb::class)[0] ?? null)) {
$breadcrumbs[] = $methodAttribute->newInstance();
}

Expand Down
26 changes: 6 additions & 20 deletions src/Model/BreadcrumbItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,14 @@
*/
class BreadcrumbItem
{
/**
* @var string|null
*/
private $label;
private ?string $label;

/**
* @var string|null
*/
private $route;
private ?string $route;

/**
* @var array|null
*/
private $routeParams;
private ?array $routeParams;

/**
* @var string|null|false - Null uses the default transation domain, passing "false" avoids translation altogether.
*/
private $translationDomain;
/** Null uses the default transation domain, passing "false" avoids translation altogether. */
private string|null|false $translationDomain;

public function __construct(
?string $label = null,
Expand Down Expand Up @@ -55,10 +44,7 @@ public function getRouteParams(): ?array
return $this->routeParams;
}

/**
* @return false|string|null
*/
public function getTranslationDomain()
public function getTranslationDomain(): string|null|false
{
return $this->translationDomain;
}
Expand Down
10 changes: 2 additions & 8 deletions src/Model/ProcessedBreadcrumbItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@
*/
class ProcessedBreadcrumbItem
{
/**
* @var string|null
*/
private $translatedLabel;
private ?string $translatedLabel;

/**
* @var string|null
*/
private $url;
private ?string $url;

public function __construct(?string $translatedLabel = null, ?string $url = null)
{
Expand Down
1 change: 0 additions & 1 deletion src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ services:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
arguments:
- '@slope_it.breadcrumb.builder'
- '@annotation_reader'

slope_it.breadcrumb.builder:
class: SlopeIt\BreadcrumbBundle\Service\BreadcrumbBuilder
Expand Down
21 changes: 4 additions & 17 deletions src/Service/BreadcrumbBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,21 @@
use SlopeIt\BreadcrumbBundle\Model\BreadcrumbItem;

/**
* Provides a minimal interface to create a breadcrumb. This is used by the event listener if annotation are used, but
* Provides a minimal interface to create a breadcrumb. This is used by the event listener if attributes are used, but
* can also be used straight from controllers which want to customize their breadcrumb.
*/
class BreadcrumbBuilder
{
/**
* @var BreadcrumbItemFactory
*/
private $itemFactory;
private BreadcrumbItemFactory $itemFactory;

/**
* @var BreadcrumbItem[]
*/
private $items = [];
/** @var BreadcrumbItem[] */
private array $items = [];

public function __construct(BreadcrumbItemFactory $itemFactory)
{
$this->itemFactory = $itemFactory;
}

/**
* Adds a new breadcrumb item.
*/
public function addItem(
?string $label = null,
?string $route = null,
Expand All @@ -38,11 +30,6 @@ public function addItem(
return $this;
}

/**
* Returns the current breadcrumb items.
*
* @return BreadcrumbItem[]
*/
public function getItems(): array
{
return $this->items;
Expand Down
Loading
Loading