Completed
Push — master ( 30af4a...256b3e )
by Łukasz
18:25 queued 05:11
created

RoutingExtension::getPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
declare(strict_types=1);
8
9
namespace eZ\Publish\Core\MVC\Symfony\Templating\Twig\Extension;
10
11
use eZ\Publish\API\Repository\Values\Content\Content;
12
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
13
use eZ\Publish\API\Repository\Values\Content\Location;
14
use eZ\Publish\Core\MVC\Symfony\Routing\Generator\RouteReferenceGeneratorInterface;
15
use eZ\Publish\Core\MVC\Symfony\Routing\RouteReference;
16
use eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter;
17
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
18
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
19
use Twig\Extension\AbstractExtension;
20
use Twig\Node\Expression\ArrayExpression;
21
use Twig\Node\Expression\ConstantExpression;
22
use Twig\Node\Node;
23
use Twig\TwigFunction;
24
25
class RoutingExtension extends AbstractExtension
26
{
27
    /** @var \eZ\Publish\Core\MVC\Symfony\Routing\Generator\RouteReferenceGeneratorInterface */
28
    private $routeReferenceGenerator;
29
30
    /** @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface */
31
    private $urlGenerator;
32
33
    public function __construct(
34
        RouteReferenceGeneratorInterface $routeReferenceGenerator,
35
        UrlGeneratorInterface $urlGenerator
36
    ) {
37
        $this->routeReferenceGenerator = $routeReferenceGenerator;
38
        $this->urlGenerator = $urlGenerator;
39
    }
40
41
    public function getFunctions(): array
42
    {
43
        return [
44
            new TwigFunction(
45
                'ez_route',
46
                [$this, 'getRouteReference']
47
            ),
48
            new TwigFunction(
49
                'ez_path',
50
                [$this, 'getPath'],
51
                ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]
52
            ),
53
            new TwigFunction(
54
                'ez_url',
55
                [$this, 'getUrl'],
56
                ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]
57
            ),
58
        ];
59
    }
60
61
    public function getName(): string
62
    {
63
        return 'ezpublish.routing';
64
    }
65
66
    /**
67
     * @param mixed $resource
68
     * @param array $params
69
     *
70
     * @return \eZ\Publish\Core\MVC\Symfony\Routing\RouteReference
71
     */
72
    public function getRouteReference($resource = null, $params = []): RouteReference
73
    {
74
        return $this->routeReferenceGenerator->generate($resource, $params);
75
    }
76
77
    public function getPath(object $name, array $parameters = [], bool $relative = false): string
78
    {
79
        $referenceType = $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH;
80
81
        return $this->generateUrlForObject($name, $parameters, $referenceType);
82
    }
83
84
    public function getUrl(object $name, array $parameters = [], bool $schemeRelative = false): string
85
    {
86
        $referenceType = $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL;
87
88
        return $this->generateUrlForObject($name, $parameters, $referenceType);
89
    }
90
91
    private function generateUrlForObject(object $object, array $parameters, int $referenceType): string
92
    {
93
        if ($object instanceof Location) {
94
            $routeName = UrlAliasRouter::URL_ALIAS_ROUTE_NAME;
95
            $parameters += [
96
                'locationId' => $object->id,
97
            ];
98
        } elseif ($object instanceof Content || $object instanceof ContentInfo) {
99
            $routeName = UrlAliasRouter::URL_ALIAS_ROUTE_NAME;
100
            $parameters += [
101
                'contentId' => $object->id,
102
            ];
103
        } elseif ($object instanceof RouteReference) {
104
            $routeName = $object->getRoute();
105
            $parameters += $object->getParams();
106
        } else {
107
            $routeName = '';
108
            $parameters += [
109
                RouteObjectInterface::ROUTE_OBJECT => $object,
110
            ];
111
        }
112
113
        return $this->urlGenerator->generate($routeName, $parameters, $referenceType);
114
    }
115
116
    /**
117
     * Determines at compile time whether the generated URL will be safe and thus
118
     * saving the unneeded automatic escaping for performance reasons.
119
     *
120
     * @see \Symfony\Bridge\Twig\Extension\RoutingExtension::isUrlGenerationSafe
121
     */
122
    public function isUrlGenerationSafe(Node $argsNode): array
123
    {
124
        // support named arguments
125
        $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : (
126
            $argsNode->hasNode('1') ? $argsNode->getNode('1') : null
127
        );
128
129
        if (null === $paramsNode || $paramsNode instanceof ArrayExpression && \count($paramsNode) <= 2 &&
130
            (!$paramsNode->hasNode('1') || $paramsNode->getNode('1') instanceof ConstantExpression)
131
        ) {
132
            return ['html'];
133
        }
134
135
        return [];
136
    }
137
}
138