HostnameIdentifiedLoader   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 36
c 1
b 0
f 0
dl 0
loc 83
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A load() 0 20 3
A resolveHostnames() 0 10 2
A supports() 0 3 2
A configureRoute() 0 26 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FH\Bundle\MultiSiteBundle\Router;
6
7
use FH\Bundle\MultiSiteBundle\Site\IdentifierMappingInterface;
8
use Symfony\Component\Config\Loader\Loader;
9
use Symfony\Component\Routing\Route;
10
use Symfony\Component\Routing\RouteCollection;
11
12
/**
13
 * @author Joris van de Sande <[email protected]>
14
 */
15
final class HostnameIdentifiedLoader extends Loader
16
{
17
    public const TYPE = 'hostname_identified';
18
19
    /**
20
     * Resource stack to prevent loading loops.
21
     *
22
     * @var mixed[]
23
     */
24
    private $resourceStack = [];
25
26
    private $identifierMapping;
27
28
    public function __construct(IdentifierMappingInterface $identifierMapping)
29
    {
30
        $this->identifierMapping = $identifierMapping;
31
    }
32
33
    public function load($resource, ?string $type = null): RouteCollection
34
    {
35
        $this->resourceStack[] = $resource;
36
37
        $importedCollection = $this->import($resource);
38
39
        array_pop($this->resourceStack);
40
41
        if (\count($importedCollection) <= 0) {
42
            return $importedCollection;
43
        }
44
45
        $collection = new RouteCollection();
46
47
        foreach ($importedCollection as $name => $route) {
48
            $configuredRoute = $this->configureRoute($route);
49
            $collection->add($name, $configuredRoute);
50
        }
51
52
        return $collection;
53
    }
54
55
    public function supports($resource, ?string $type = null): bool
56
    {
57
        return null === $type && !\in_array($resource, $this->resourceStack, true);
58
    }
59
60
    private function configureRoute(Route $route): Route
61
    {
62
        if (!$route->hasOption('hostname_identifiers')) {
63
            return $route;
64
        }
65
66
        $newRoute = clone $route;
67
        $identifiers = (array) $newRoute->getOption('hostname_identifiers');
68
        $locale = $newRoute->hasDefault('_canonical_route') ? $newRoute->getDefault('_locale') : null;
69
        $hostnames = $this->resolveHostnames($identifiers, $locale);
70
71
        if (0 === \count($hostnames)) {
72
            throw new \RuntimeException(sprintf('No hostnames resolved for path "%s" and host identifiers %s', $route->getPath(), implode(', ', $identifiers)));
73
        }
74
75
        $regex = implode('|', array_map('preg_quote', $hostnames));
76
77
        $newRoute
78
            ->setHost('{site_hostname}')
79
            ->setRequirement('site_hostname', $regex);
80
81
        if (1 === \count($hostnames)) {
82
            $newRoute->setDefault('site_hostname', reset($hostnames));
83
        }
84
85
        return $newRoute;
86
    }
87
88
    private function resolveHostnames(array $identifiers, ?string $locale): array
89
    {
90
        $hostnames = [];
91
92
        foreach ($identifiers as $identifier) {
93
            $mappedHostnames = $this->identifierMapping->findHostnamesByIdentifier($identifier, $locale);
94
            $hostnames = array_merge($hostnames, $mappedHostnames);
95
        }
96
97
        return $hostnames;
98
    }
99
}
100