BlazeManager   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 5.71%

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 3
dl 0
loc 222
ccs 4
cts 70
cp 0.0571
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getRoute() 0 18 3
A getUrl() 0 4 1
A getPath() 0 24 5
B getRouteParams() 0 39 5
A getSingleRouteParam() 0 19 4
A callObjectFunction() 0 14 4
B getClass() 0 24 6
1
<?php
2
3
namespace Happyr\BlazeBundle\Service;
4
5
use Happyr\BlazeBundle\Exception\BlazeException;
6
use Happyr\BlazeBundle\Model\ConfigurationInterface;
7
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
8
use Symfony\Component\Routing\RouterInterface;
9
10
/**
11
 * @author Tobias Nyholm <[email protected]>
12
 */
13
class BlazeManager implements BlazeManagerInterface
14
{
15
    /**
16
     * @var RouterInterface router
17
     */
18
    protected $router;
19
20
    /**
21
     * @var \Happyr\BlazeBundle\Model\ConfigurationInterface config
22
     */
23
    protected $config;
24
25
    /**
26
     * @param ConfigurationInterface $config
27
     * @param RouterInterface        $router
28
     */
29 1
    public function __construct(ConfigurationInterface $config, RouterInterface $router)
30
    {
31 1
        $this->config = $config;
32 1
        $this->router = $router;
33 1
    }
34
35
    /**
36
     * Get the route and the params.
37
     *
38
     * @param object $object
39
     * @param string $action
40
     *
41
     * @return array array($route, $params, $cmpObj)
42
     *
43
     * @throws BlazeException
44
     */
45
    protected function getRoute($object, $action)
46
    {
47
        if (null == $object) {
48
            throw new BlazeException(sprintf('Blaze: Cant find route for non-object.'));
49
        }
50
51
        $class = $this->getClass($object);
52
53
        if (!$this->config->actionExist($class, $action)) {
54
            throw new BlazeException(sprintf('Action "%s" for class %s does not exist in Blaze config.', $action, $class));
55
        }
56
57
        $route = $this->config->getRoute($class, $action);
58
        $params = $this->config->getParameters($class, $action);
59
        $cmpObj = $this->config->getComplementaryObjects($class, $action);
60
61
        return [$route, $params, $cmpObj];
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function getUrl($object, $action, array $cmpObj = [])
68
    {
69
        return $this->getPath($object, $action, $cmpObj, true);
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function getPath($object, $action, array $cmpObj = [], $absolute = false)
76
    {
77
        list($route, $params, $confCmpObj) = $this->getRoute($object, $action);
78
79
        // make sure that $confCmpObj and $cmpObj is matching
80
        foreach ($confCmpObj as $key => $class) {
81
            if (!isset($cmpObj[$key])) {
82
                throw new BlazeException(sprintf('The %d parameter of complementary objects was expected to be %s but you gave me nothing!', $key, $class));
83
            }
84
85
            if ($this->getClass($cmpObj[$key]) != $class) {
86
                throw new BlazeException(sprintf('The %d parameter of complementary objects was expected to be %s but instance of %s was given', $key, $class, get_class($cmpObj[$key])));
87
            }
88
        }
89
90
        $routeParams = $this->getRouteParams($object, $params, $cmpObj);
91
92
        $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH;
93
        if ($absolute) {
94
            $referenceType = UrlGeneratorInterface::ABSOLUTE_URL;
95
        }
96
97
        return $this->router->generate($route, $routeParams, $referenceType);
98
    }
99
100
    /**
101
     * Get the parameters to send to the @router.
102
     *
103
     * @param object $object
104
     * @param array  $params
105
     * @param array  $cmpObj
106
     *
107
     * @return array
108
     */
109
    protected function getRouteParams($object, array $params, array $cmpObj = [])
110
    {
111
        /*
112
         * Assert: I know for sure that $object is not null
113
         */
114
        $routeParams = [];
115
        foreach ($params as $key => $func) {
116
            //if there is complementary objects
117
            if (is_array($func)) {
118
                /*
119
                 * the first element should use the $object
120
                 * other elements should use objects in the $cmpObj.
121
                 */
122
                if (0 == $key) {
123
                    //make sure that the size of $params is equal to $cmpObj + the $obejct
124
                    if (count($params) != count($cmpObj) + 1) {
125
                        throw new BlazeException(sprintf('There is a mismatch in the number of route params and the number of objects. This is '.'usually cased by a configuration error or that you forgotten to send the complementary'.' objects to the Blaze service. We found %s parameter arrays but %d objects', count($params), count($cmpObj) + 1));
126
                    }
127
128
                    $routeParams = array_merge($routeParams, $this->getRouteParams($object, $func));
129
130
                    continue;
131
                } else {
132
                    /*
133
                     * We know for sure that $cmpObj[$key-1] and is of type like the config says
134
                     */
135
136
                    //get the route params with the complementary object
137
                    $routeParams = array_merge($routeParams, $this->getRouteParams($cmpObj[$key - 1], $func));
138
139
                    continue;
140
                }
141
            }
142
143
            $routeParams[$key] = $this->getSingleRouteParam($object, $func);
144
        }
145
146
        return $routeParams;
147
    }
148
149
    /**
150
     * Get a route param.
151
     *
152
     * @param object $object
153
     * @param string $function
154
     *
155
     * @return mixed
156
     *
157
     * @throws BlazeException
158
     */
159
    protected function getSingleRouteParam($object, $function)
160
    {
161
        //if there is a chain of functions
162
        if (strstr($function, '.')) {
163
            $funcs = explode('.', $function);
164
            $returnValue = $object;
165
            foreach ($funcs as $f) {
166
                $returnValue = $this->callObjectFunction($returnValue, $f);
167
168
                if (null === $returnValue) {
169
                    throw new BlazeException(sprintf('Function "%s" ended up with returning non-object (null) after "%s".', $function, $f));
170
                }
171
            }
172
173
            return $returnValue;
174
        } else {
175
            return $this->callObjectFunction($object, $function);
176
        }
177
    }
178
179
    /**
180
     * Call a $function on the object.
181
     *
182
     * @param object $object
183
     * @param string $function
184
     *
185
     * @return mixed
186
     */
187
    private function callObjectFunction($object, $function)
188
    {
189
        try {
190
            return $object->$function();
191
        } catch (\Exception $e) {
192
            if (null === $object) {
193
                throw new BlazeException(sprintf('Called "%s" on a non-object', $function));
194
            }
195
196
            if (!method_exists($object, $function)) {
197
                throw new BlazeException(sprintf('Method %s does not exits on object %s', $function, get_class($object)));
198
            }
199
        }
200
    }
201
202
    /**
203
     * Get the class in the config.
204
     * If the class of $object is not found, try the parent of $object.
205
     *
206
     * @param object $object
207
     *
208
     * @return string
209
     */
210
    protected function getClass($object)
211
    {
212
        if (!is_object($object)) {
213
            //we assume that $object is a string and namespace
214
            if (class_exists($object)) {
215
                return $object;
216
            }
217
218
            //class not loaded
219
            throw new BlazeException(sprintf('Blaze must receive an object or a fully qualified name of a loaded class. We got "%s"', $object));
220
        }
221
222
        $class = get_class($object);
223
224
        //Do max 3 times
225
        for ($i = 0; $i < 3 && $class; ++$i) {
226
            if ($this->config->classExist($class)) {
227
                return $class;
228
            }
229
            $class = get_parent_class($class);
230
        }
231
232
        throw new BlazeException(sprintf('Class %s does not exist in Blaze config.', get_class($object)));
233
    }
234
}
235