Completed
Push — dev ( 5c06f5...dcd39b )
by Arnaud
09:19
created

RoutingLoader::load()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 26
ccs 0
cts 19
cp 0
rs 8.5806
cc 4
eloc 14
nc 4
nop 2
crap 20
1
<?php
2
3
namespace LAG\AdminBundle\Routing;
4
5
use LAG\AdminBundle\Admin\Action;
6
use LAG\AdminBundle\Admin\ActionInterface;
7
use LAG\AdminBundle\Admin\AdminInterface;
8
use Exception;
9
use LAG\AdminBundle\Admin\Factory\AdminFactory;
10
use RuntimeException;
11
use Symfony\Component\Config\Loader\LoaderInterface;
12
use Symfony\Component\Config\Loader\LoaderResolverInterface;
13
use Symfony\Component\Routing\Route;
14
use Symfony\Component\Routing\RouteCollection;
15
16
/**
17
 * RoutingLoader.
18
 *
19
 * Creates routing for configured entities
20
 */
21
class RoutingLoader implements LoaderInterface
22
{
23
    protected $loaded = false;
24
25
    /**
26
     * @var AdminFactory
27
     */
28
    protected $adminFactory;
29
30
    public function __construct(AdminFactory $adminFactory)
31
    {
32
        $this->adminFactory = $adminFactory;
33
    }
34
35
    public function load($resource, $type = null)
36
    {
37
        if (true === $this->loaded) {
38
            throw new RuntimeException('Do not add the "extra" loader twice');
39
        }
40
        $routes = new RouteCollection();
41
        $this->adminFactory->init();
42
        $admins = $this
43
            ->adminFactory
44
            ->getAdmins();
45
        // creating a route by admin and action
46
        /** @var AdminInterface $admin */
47
        foreach ($admins as $admin) {
48
            $actions = $admin->getActions();
49
            // by default, actions are create, edit, delete, list
50
            /** @var Action $action */
51
            foreach ($actions as $action) {
52
                // load route into collection
53
                $this->loadRouteForAction($admin, $action, $routes);
54
            }
55
        }
56
        // loader is loaded
57
        $this->loaded = true;
58
59
        return $routes;
60
    }
61
62
    public function supports($resource, $type = null)
63
    {
64
        return 'extra' === $type;
65
    }
66
67
    public function getResolver()
68
    {
69
    }
70
71
    public function setResolver(LoaderResolverInterface $resolver)
72
    {
73
    }
74
75
    /**
76
     * Add a Route to the RouteCollection according to an Admin an an Action.
77
     *
78
     * @param AdminInterface  $admin
79
     * @param ActionInterface $action
80
     * @param RouteCollection $routeCollection
81
     *
82
     * @throws Exception
83
     */
84
    protected function loadRouteForAction(AdminInterface $admin, ActionInterface $action, RouteCollection $routeCollection)
85
    {
86
        $routingUrlPattern = $admin->getConfiguration()->getRoutingUrlPattern();
87
        // routing pattern should contains {admin} and {action}
88
        if (strpos($routingUrlPattern, '{admin}') == -1 || strpos($routingUrlPattern, '{action}') == -1) {
89
            throw new Exception('Admin routing pattern should contains {admin} and {action} placeholder');
90
        }
91
        // route path by entity name and action name
92
        $path = str_replace('{admin}', $admin->getName(), $routingUrlPattern);
93
        $path = str_replace('{action}', $action->getName(), $path);
94
        // by default, generic controller
95
        $defaults = [
96
            '_controller' => $admin->getConfiguration()->getControllerName().':'.$action->getName(),
97
            '_admin' => $admin->getName(),
98
            '_action' => $action->getName(),
99
        ];
100
        // by default, no requirements
101
        $requirements = [];
102
        // for delete and edit action, an id is required
103
        if (in_array($action->getName(), ['delete', 'edit'])) {
104
            $path .= '/{id}';
105
            $requirements = [
106
                'id' => '\d+',
107
            ];
108
        }
109
        // creating new route
110
        $route = new Route($path, $defaults, $requirements);
111
        $routeName = $admin->generateRouteName($action->getName());
112
        // set route to action
113
        $action->getConfiguration()->setRoute($routeName);
114
        $action->getConfiguration()->setParameters($requirements);
115
        // adding route to symfony collection
116
        $routeCollection->add($routeName, $route);
117
    }
118
119
    protected function replaceInRoute($pattern, $adminName, $actionName)
120
    {
121
        $pattern = str_replace('{admin}', $adminName, $pattern);
122
        $pattern = str_replace('{action}', $actionName, $pattern);
123
124
        return $pattern;
125
    }
126
127
    /**
128
     * Return entity path for routing (for example, MyNamespace\EntityName => entityName).
129
     *
130
     * @param $namespace
131
     *
132
     * @return string
133
     */
134
    protected function getEntityPath($namespace)
135
    {
136
        $array = explode('\\', $namespace);
137
        $path = array_pop($array);
138
        $path = strtolower(substr($path, 0, 1)).substr($path, 1);
139
140
        return $path;
141
    }
142
}
143