SelectorFactory::nullOrException()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
3
/**
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace Cubiche\Core\Selector;
12
13
/**
14
 * Selector Factory Class.
15
 *
16
 * @author Karel Osorio Ramírez <[email protected]>
17
 */
18
class SelectorFactory implements SelectorFactoryInterface
19
{
20
    /**
21
     * @var \ReflectionClass[]
22
     */
23
    private $selectorClass;
24
25
    /**
26
     * @var string[]
27
     */
28
    private $namespaces;
29
30
    /**
31
     * @param string $defaultNamespace
32
     */
33
    public function __construct($defaultNamespace = null)
34
    {
35
        $this->selectorClass = array();
36
        $this->namespaces = array();
37
38
        if (!empty($defaultNamespace)) {
39
            $this->addNamespace($defaultNamespace);
40
        }
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function addSelector($selectorClass, $selectorName = null)
47
    {
48
        $reflection = $this->validateSelectorClass($selectorClass);
49
50
        if (empty($selectorName)) {
51
            $selectorName = \lcfirst($reflection->getShortName());
52
        }
53
54
        if ($this->findSelector($selectorName) !== null) {
55
            throw new \InvalidArgumentException(\sprintf('There is already a selector with name %s', $selectorName));
56
        }
57
58
        $this->selectorClass[$selectorName] = $reflection;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function addNamespace($namespace)
65
    {
66
        if (empty($namespace)) {
67
            throw new \InvalidArgumentException('The namespace name must be non-empty');
68
        }
69
70
        if (!isset($this->namespaces[$namespace])) {
71
            $this->namespaces[] = $namespace;
72
        }
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function create($selectorName, array $arguments = array())
79
    {
80
        $reflection = $this->findSelector($selectorName);
81
82
        if ($reflection !== null) {
83
            return $reflection->newInstanceArgs($arguments);
84
        }
85
86
        throw new \InvalidArgumentException(\sprintf('There is not a selector with name "%s"', $selectorName));
87
    }
88
89
    /**
90
     * @param string $selectorName
91
     *
92
     * @return \ReflectionClass
93
     */
94
    private function findSelector($selectorName)
95
    {
96
        if (isset($this->selectorClass[$selectorName])) {
97
            return $this->selectorClass[$selectorName];
98
        }
99
100
        foreach ($this->namespaces as $namespace) {
101
            $className = $namespace.'\\'.\ucfirst($selectorName);
102
            $reflection = $this->validateSelectorClass($className, false);
103
            if ($reflection !== null) {
104
                $this->selectorClass[$selectorName] = $reflection;
105
106
                return $reflection;
107
            }
108
        }
109
110
        return;
111
    }
112
113
    /**
114
     * @param string $selectorClass
115
     * @param bool   $strict
116
     */
117
    private function validateSelectorClass($selectorClass, $strict = true)
118
    {
119
        if (!\class_exists($selectorClass)) {
120
            return $this->nullOrException(
121
                new \InvalidArgumentException(\sprintf('There is not a class with name %s', $selectorClass)),
122
                $strict
123
            );
124
        }
125
126
        $reflection = new \ReflectionClass($selectorClass);
127
        if (!$reflection->isSubclassOf(SelectorInterface::class)) {
128
            return $this->nullOrException(
129
                new \InvalidArgumentException(
130
                    \sprintf('%s must be implement %s interface', $selectorClass, SelectorInterface::class)
131
                ),
132
                $strict
133
            );
134
        }
135
136
        return $reflection;
137
    }
138
139
    /**
140
     * @param \Exception $exception
141
     * @param bool       $strict
142
     *
143
     * @throws \Exception
144
     */
145
    private function nullOrException(\Exception $exception, $strict = true)
146
    {
147
        if ($strict) {
148
            throw $exception;
149
        }
150
151
        return;
152
    }
153
}
154