Completed
Pull Request — master (#58)
by Tim
06:23
created

ActionDescriptor::getMappedRequestMethods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * AppserverIo\Routlt\Description\ActionDescriptor
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author     Tim Wagner <[email protected]>
15
 * @copyright  2015 TechDivision GmbH <[email protected]>
16
 * @license    http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link       http://github.com/appserver-io/routlt
18
 * @link       http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Routlt\Description;
22
23
use AppserverIo\Http\HttpProtocol;
24
use AppserverIo\Routlt\Annotations\Action;
25
use AppserverIo\Routlt\Annotations\Connect;
26
use AppserverIo\Routlt\Annotations\Delete;
27
use AppserverIo\Routlt\Annotations\Get;
28
use AppserverIo\Routlt\Annotations\Head;
29
use AppserverIo\Routlt\Annotations\Options;
30
use AppserverIo\Routlt\Annotations\Patch;
31
use AppserverIo\Routlt\Annotations\Post;
32
use AppserverIo\Routlt\Annotations\Put;
33
use AppserverIo\Routlt\Annotations\Trace;
34
use AppserverIo\Lang\Reflection\MethodInterface;
35
use AppserverIo\Configuration\Interfaces\NodeInterface;
36
use AppserverIo\Description\AbstractNameAwareDescriptor;
37
38
/**
39
 * Annotation to map a request path info to an action method.
40
 *
41
 * @author     Tim Wagner <[email protected]>
42
 * @copyright  2015 TechDivision GmbH <[email protected]>
43
 * @license    http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
44
 * @link       http://github.com/appserver-io/routlt
45
 * @link       http://www.appserver.io
46
 */
47
class ActionDescriptor extends AbstractNameAwareDescriptor implements ActionDescriptorInterface
48
{
49
50
    /**
51
     * The action method name.
52
     *
53
     * @var string
54
     */
55
    protected $methodName;
56
57
    /**
58
     * The request methods the action is listening to.
59
     *
60
     * @var array
61
     */
62
    protected $requestMethods = array();
63
64
    protected $mappedRequestMethods = array(
65
        HttpProtocol::METHOD_CONNECT => Connect::class,
66
        HttpProtocol::METHOD_DELETE  => Delete::class,
67
        HttpProtocol::METHOD_GET     => Get::class,
68
        HttpProtocol::METHOD_HEAD    => Head::class,
69
        HttpProtocol::METHOD_OPTIONS => Options::class,
70
        HttpProtocol::METHOD_POST    => Post::class,
71
        HttpProtocol::METHOD_PUT     => Put::class,
72
        HttpProtocol::METHOD_TRACE   => Trace::class,
73
        HttpProtocol::METHOD_PATCH   => Patch::class
74 9
    );
75
76
    /**
77
     * The restrictions for the route placeholders.
78 9
     *
79 9
     * @var array
80
     */
81
    protected $restrictions;
82 9
83 9
    /**
84 9
     * The defaults for the route placeholders.
85 9
     *
86 9
     * @var array
87 9
     */
88 9
    protected $defaults;
89 9
90 9
    /**
91
     * Initializes the descriptor with the default
92 9
     * request methods the action is listening to.
93 9
     */
94
    public function __construct()
95
    {
96
97
        // initialize restrictions and defaults
98
        $this->defaults = array();
99
        $this->restrictions = array();
100
101
        // initialize the request methods
102 8
        $this->requestMethods = array_keys($this->getMappedRequestMethods());
103
    }
104 8
105 8
    /**
106
     * Sets the action method name.
107
     *
108
     * @param string $methodName The action method name
109
     *
110
     * @return void
111
     */
112 3
    public function setMethodName($methodName)
113
    {
114 3
        $this->methodName = $methodName;
115
    }
116
117
    /**
118
     * Returns the action method name.
119
     *
120
     * @return string The action method name
121
     */
122
    public function getMethodName()
123
    {
124 3
        return $this->methodName;
125
    }
126 3
127 3
    /**
128
     * Sets the request methods the action is listening to.
129
     *
130
     * @param array $requestMethods The request methods
131
     *
132
     * @return void
133
     */
134 8
    public function setRequestMethods(array $requestMethods)
135
    {
136 8
        $this->requestMethods = $requestMethods;
137
    }
138
139
    /**
140
     * Returns the request methods the action is listening to.
141
     *
142
     * @return array The request methods
143
     */
144
    public function getRequestMethods()
145
    {
146
        return $this->requestMethods;
147
    }
148
149
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
150
     * Add's the passed key => value pair as restriction.
151
     *
152
     * @param string $key   The parameter name to add the restriction for
0 ignored issues
show
Bug introduced by
There is no parameter named $key. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
Coding Style introduced by
Doc comment for parameter $key does not match actual variable name $name
Loading history...
153
     * @param string $value The restriction value itself
154
     *
155
     * @return void
156
     */
157
    public function addRestriction($name, $value)
158
    {
159
        $this->restrictions[$name] = $value;
160
    }
161
162
    /**
163
     * Sets the restrictions for the route placeholders.
164
     *
165
     * @param array $restrictions The restrictions for the route placeholders
166
     *
167
     * @return void
168
     */
169
    public function setRestrictions(array $restrictions)
170
    {
171
        $this->restrictions = $restrictions;
172
    }
173
174
    /**
175
     * Returns the restrictions for the route placeholders.
176
     *
177
     * @return array The restrictions for the route placeholders
178
     */
179
    public function getRestrictions()
180
    {
181
        return $this->restrictions;
182
    }
183
184
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
185
     * Add's the passed key => value pair as default.
186
     *
187
     * @param string $key   The parameter name to add the default for
0 ignored issues
show
Bug introduced by
There is no parameter named $key. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
Coding Style introduced by
Doc comment for parameter $key does not match actual variable name $name
Loading history...
188 4
     * @param string $value The default value itself
189
     *
190 4
     * @return void
191
     */
192
    public function addDefault($name, $value)
193
    {
194
        $this->defaults[$name] = $value;
195
    }
196
197
    /**
198
     * Sets the defaults for the route placeholders.
199
     *
200 7
     * @param array $defaults The defaults for the route placeholders
201
     *
202 7
     * @return void
203
     */
204
    public function setDefaults(array $defaults)
205
    {
206
        $this->defaults = $defaults;
207
    }
208
209
    /**
210
     * Returns the defaults for the route placeholders.
211
     *
212 8
     * @return array The defaults for the route placeholders
213
     */
214
    public function getDefaults()
215
    {
216 8
        return $this->defaults;
217
    }
218
219 8
    /**
220 8
     * Returns a new descriptor instance.
221
     *
222 4
     * @return \AppserverIo\Routlt\Description\ActionDescriptorInterface The descriptor instance
223
     */
224
    public static function newDescriptorInstance()
225 8
    {
226 8
        return new ActionDescriptor();
227
    }
228 4
229
    /**
230 4
     * Return's the array with the reqeust method => annotation class mapping.
231
     *
232 7
     * @return array The mapping
233
     */
234
    protected function getMappedRequestMethods()
235
    {
236 8
        return $this->mappedRequestMethods;
237
    }
238
239 8
    /**
240 8
     * Initializes the action configuration instance from the passed reflection method instance.
241 8
     *
242 8
     * @param \AppserverIo\Lang\Reflection\MethodInterface $reflectionMethod The reflection method with the action configuration
243
     *
244
     * @return \AppserverIo\Routlt\Description\ActionDescriptorInterface The initialized descriptor
245 8
     */
246 6
    public function fromReflectionMethod(MethodInterface $reflectionMethod)
247 6
    {
248
249 5
        // create a new annotation instance
250
        $annotationInstance = $this->getMethodAnnotation($reflectionMethod, Action::class);
251
252
        // query if we've a method with a @Action annotation
253 8
        if ($annotationInstance === null && $reflectionMethod->getMethodName() !== 'perform') {
254
            // if not, do nothing
255
            return;
256 8
        }
257
258 8
        // query whether we've the default perform() method WITHOUT an @Action annotation
259
        if ($annotationInstance === null && $reflectionMethod->getMethodName() === 'perform') {
260
            // create a new annotation instance
261 8
            $annotationInstance = new Action(array('name' => $reflectionMethod->getMethodName()));
262 3
        }
263 3
264 8
        // load method name
265
        $this->setMethodName($reflectionMethod->getMethodName());
266
267 8
        // load the default name to register in naming directory
268
        if (($nameAttribute = $annotationInstance->getName()) || $nameAttribute === '') {
269 3
            $this->setName($nameAttribute);
270 3
        } else {
271
            // if @Annotation(name=****) is NOT SET, we use the method name by default
272
            $this->setName('/' . lcfirst(str_replace('Action', '', $reflectionMethod->getMethodName())));
273 8
        }
274
275
        // initialize the array for the annotated request methods
276
        $annotatedRequestMethods = array();
277
278
        // parse the method for annotated request methods
279
        foreach ($this->getMappedRequestMethods() as $requestMethod => $annotationName) {
280
            // query whether the reflection method has been annotated
281 8
            if ($this->getMethodAnnotation($reflectionMethod, $annotationName)) {
282
                array_push($annotatedRequestMethods, $requestMethod);
283
            }
284
        }
285
286
        // query whether at least one annotated request method has been found
287
        if (sizeof($annotatedRequestMethods) > 0) {
288
            // if yes, override the default request methods
289 8
            $this->setRequestMethods($annotatedRequestMethods);
290
        }
291
292
        // initialize the restrictions for the route placeholders
293
        if (is_array($restrictions = $annotationInstance->getRestrictions())) {
294
            foreach ($restrictions as $restriction) {
295
                list($name, $value) = $restriction;
296
                $this->addRestriction($name, $value);
297
            }
298
        }
299 1
300
        // initialize the defaults for the route placeholders
301 1
        if (is_array($defaults = $annotationInstance->getDefaults())) {
302
            foreach ($defaults as $default) {
303
                list($name, $value) = $default;
304
                $this->addDefault($name, $value);
305
            }
306
        }
307
308
        // return the instance
309
        return $this;
310
    }
311
312
    /**
313
     * Initializes a action configuration instance from the passed deployment descriptor node.
314
     *
315
     * @param \SimpleXmlElement $node The deployment node with the action configuration
316
     *
317
     * @return \AppserverIo\Routlt\Description\ActionDescriptorInterface The initialized descriptor
318
     */
319
    public function fromDeploymentDescriptor(\SimpleXmlElement $node)
0 ignored issues
show
Unused Code introduced by
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
320
    {
321
    }
322
323 2
    /**
324
     * Initializes a action configuration instance from the passed configuration node.
325
     *
326
     * @param \AppserverIo\Configuration\Interfaces\NodeInterface $node The configuration node with the action configuration
327 2
     *
328 1
     * @return \AppserverIo\Routlt\Description\ActionDescriptorInterface The initialized descriptor
329 1
     */
330 1
    public function fromConfiguration(NodeInterface $node)
0 ignored issues
show
Unused Code introduced by
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
331
    {
332
    }
333
334 1
    /**
335 1
     * Merges the passed configuration into this one. Configuration values
336 1
     * of the passed configuration will overwrite this one.
337 1
     *
338
     * @param \AppserverIo\Routlt\Description\ActionDescriptorInterface $actionDescriptor The configuration to merge
339
     *
340
     * @return void
341
     * @throws \AppserverIo\Routlt\Description\DescriptorException Is thrown if the passed descriptor has a different method name
342
     */
343
    public function merge(ActionDescriptorInterface $actionDescriptor)
344
    {
345
346
        // check if the classes are equal
347
        if ($this->getMethodName() !== $actionDescriptor->getMethodName()) {
348
            throw new DescriptorException(
349
                sprintf('You try to merge a action configuration for %s with %s', $actionDescriptor->getMethodName(), $this->getMethodName())
350
            );
351
        }
352
353
        // merge the name
354
        if ($name = $actionDescriptor->getName()) {
355
            $this->setName($name);
356
        }
357
    }
358
}
359