Passed
Push — main ( dd4c4b...a0525b )
by Loïc
03:44
created

RoutingExtension::getAttributeIf()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Twig\Extension;
6
7
use Symfony\Component\Routing\RouterInterface;
8
use Twig\Extension\AbstractExtension;
9
use Twig\TwigFunction;
10
11
use function Symfony\Component\String\u;
12
13
/**
14
 * Routing related stuff.
15
 *
16
 * @see RoutingExtensionTest
17
 */
18
final class RoutingExtension extends AbstractExtension
19
{
20
    /**
21
     * @var array<int, string>|null
22
     */
23
    private ?array $controllers = null;
24
25 11
    public function __construct(
26
        private readonly RouterInterface $router,
27
    ) {
28 11
    }
29
30 4
    public function getFunctions(): array
31
    {
32 4
        return [
33 4
            new TwigFunction('ctrl_fqcn', $this->getControllerFqcn(...)),
34 4
            new TwigFunction('attr_if', $this->getAttributeIf(...)),
35 4
        ];
36
    }
37
38
    /**
39
     * This function returns a complete controller FQCN from a short name.
40
     * If you have multiple controllers/actions with the same name, you can include
41
     * the parent namespace to select the good one like the last examples below.
42
     *
43
     * @example ComposerAction      --> App\Controller\ComposerAction
44
     * @example Product\ListAction  --> App\Controller\Product\ListAction
45
     * @example Category\ListAction --> App\Controller\Category\ListAction
46
     *
47
     * @return class-string
48
     */
49 8
    public function getControllerFqcn(string $ctrlShortname): string
50
    {
51 8
        if ($this->controllers === null) {
52 8
            $this->controllers = array_unique(array_map(
53 8
                static fn ($value) => u($value)->trimSuffix('::__invoke')->toString(),
54 8
                array_keys($this->router->getRouteCollection()->getAliases())
55 8
            ));
56
        }
57
58 8
        foreach ($this->controllers as $controller) {
59
            /** @var class-string $controller */
60 8
            if (u($controller)->endsWith($ctrlShortname)) {
61 7
                return $controller;
62
            }
63
        }
64
65
        // If all your ADR controllers live in the "App\Controller\" namespace,
66
        // then you probably don't need all the code above, just use:
67
        //
68
        // return  'App\\Controller\\'. $ctrlShortname;
69
        //
70
        // If the route is not found, then Twig raises a "RouteNotFoundException".
71
72 1
        throw new \InvalidArgumentException('No controller found for the "'.$ctrlShortname.'" shortname.');
73
    }
74
75
    /**
76
     * Returns an HTML attribute with a given value only if a condition is met.
77
     *
78
     * @see templates/base.html.twig
79
     */
80 7
    public function getAttributeIf(bool $condition, string $attribute, string $value): string
81
    {
82 7
        if (!$condition) {
83 7
            return '';
84
        }
85
86 7
        return \sprintf(' %s="%s"', $attribute, $value);
87
    }
88
}
89