Passed
Push — master ( 0602c9...8f96ba )
by Thierry
02:02
created

CallableRegistry::parseNamespaces()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
dl 0
loc 10
rs 10
c 1
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
/**
4
 * CallableRegistry.php - Jaxon callable object registrar
5
 *
6
 * This class is the entry point for class, directory and namespace registration.
7
 *
8
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2019 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
14
15
namespace Jaxon\Request\Support;
16
17
class CallableRegistry
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class CallableRegistry
Loading history...
18
{
19
    /**
20
     * The callable repository
21
     *
22
     * @var CallableRepository
23
     */
24
    public $xRepository;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
25
26
    /**
27
     * The registered directories
28
     *
29
     * These are directories registered without a namespace.
30
     *
31
     * @var array
32
     */
33
    protected $aDirectories = [];
34
35
    /**
36
     * Indicate if the registered directories are already parsed
37
     *
38
     * @var boolean
39
     */
40
    protected $bParsedDirectories = false;
41
42
    /**
43
     * The registered namespaces
44
     *
45
     * These are the namespaces specified when registering directories.
46
     *
47
     * @var array
48
     */
49
    protected $aNamespaces = [];
50
51
    /**
52
     * Indicate if the registered namespaces are already parsed
53
     *
54
     * @var boolean
55
     */
56
    protected $bParsedNamespaces = false;
57
58
    /**
59
     * If the underscore is used as separator in js class names.
60
     *
61
     * @var boolean
62
     */
63
    protected $bUsingUnderscore = false;
64
65
    /**
66
     * The Composer autoloader
67
     *
68
     * @var Autoloader
0 ignored issues
show
Bug introduced by
The type Jaxon\Request\Support\Autoloader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
69
     */
70
    private $xAutoloader = null;
71
72
    /**
73
     * The class constructor
74
     *
75
     * @param CallableRepository        $xRepository
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
76
     */
77
    public function __construct(CallableRepository $xRepository)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
78
    {
79
        $this->xRepository = $xRepository;
80
81
        // Set the composer autoloader
82
        $sAutoloadFile = __DIR__ . '/../../../../../autoload.php';
83
        if(file_exists($sAutoloadFile))
84
        {
85
            $this->xAutoloader = require($sAutoloadFile);
86
        }
87
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
88
89
    /**
90
     *
91
     * @param string        $sDirectory     The directory being registered
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
92
     * @param array         $aOptions       The associated options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 9 found
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter name; 7 found
Loading history...
93
     *
94
     * @return void
95
     */
96
    public function addDirectory($sDirectory, array $aOptions)
97
    {
98
        // Set the autoload option default value
99
        if(!key_exists('autoload', $aOptions))
100
        {
101
            $aOptions['autoload'] = true;
102
        }
103
104
        $this->aDirectories[$sDirectory] = $aOptions;
105
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
106
107
    /**
108
     *
109
     * @param string        $sNamespace     The namespace of the directory being registered
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
110
     * @param array         $aOptions       The associated options
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 7 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 9 found
Loading history...
111
     *
112
     * @return void
113
     */
114
    public function addNamespace($sNamespace, array $aOptions)
115
    {
116
        // Separator default value
117
        if(!key_exists('separator', $aOptions))
118
        {
119
            $aOptions['separator'] = '.';
120
        }
121
        $aOptions['separator'] = trim($aOptions['separator']);
122
        if(!in_array($aOptions['separator'], ['.', '_']))
123
        {
124
            $aOptions['separator'] = '.';
125
        }
126
        if($aOptions['separator'] == '_')
127
        {
128
            $this->bUsingUnderscore = true;
129
        }
130
        // Set the autoload option default value
131
        if(!key_exists('autoload', $aOptions))
132
        {
133
            $aOptions['autoload'] = true;
134
        }
135
        // Register the dir with PSR4 autoloading
136
        if(($aOptions['autoload']) && $this->xAutoloader != null)
137
        {
138
            $this->xAutoloader->setPsr4($sNamespace . '\\', $aOptions['directory']);
139
        }
140
141
        $this->aNamespaces[$sNamespace] = $aOptions;
142
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
143
144
    /**
145
     * Read classes from directories registered without namespaces
146
     *
147
     * @return void
148
     */
149
    protected function parseDirectories()
150
    {
151
        // Browse directories without namespaces and read all the files.
152
        // This is to be done only once.
153
        if($this->bParsedDirectories)
154
        {
155
            return;
156
        }
157
        $this->bParsedDirectories = true;
158
159
        $this->xRepository->parseDirectories($this->aDirectories);
160
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
161
162
    /**
163
     * Read classes from directories registered with namespaces
164
     *
165
     * @return void
166
     */
167
    protected function parseNamespaces()
168
    {
169
        // This is to be done only once.
170
        if($this->bParsedNamespaces)
171
        {
172
            return;
173
        }
174
        $this->bParsedNamespaces = true;
175
176
        $this->xRepository->parseNamespaces($this->aNamespaces);
177
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
178
179
    /**
180
     * Find options for a class which is registered with namespace
181
     *
182
     * @param string        $sClassName            The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 12 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
183
     *
184
     * @return array|null
185
     */
186
    protected function getClassOptionsFromNamespaces($sClassName)
187
    {
188
        // Find the corresponding namespace
189
        $sNamespace = null;
190
        $aOptions = null;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
191
        foreach($this->aNamespaces as $_sNamespace => $_aOptions)
192
        {
193
            // Check if the namespace matches the class.
194
            if(strncmp($sClassName, $_sNamespace . '\\', strlen($_sNamespace) + 1) === 0)
195
            {
196
                $sNamespace = $_sNamespace;
197
                $aOptions = $_aOptions;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
198
                break;
199
            }
200
        }
201
        if($sNamespace === null)
202
        {
203
            return null; // Class not registered
204
        }
205
206
        // Get the class options
207
        $aClassOptions = ['namespace' => $sNamespace];
208
        return $this->xRepository->makeClassOptions($sClassName, $aClassOptions, $aOptions);
209
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
210
211
    /**
212
     * Find the options associated with a registered class name
213
     *
214
     * @param string        $sClassName            The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 12 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
215
     *
216
     * @return array|null
217
     */
218
    protected function getClassOptions($sClassName)
219
    {
220
        // Find options for a class registered with namespace.
221
        $aOptions = $this->getClassOptionsFromNamespaces($sClassName);
222
        if($aOptions !== null)
223
        {
224
            return $aOptions;
225
        }
226
227
        // Without a namespace, we need to parse all classes to be able to find one.
228
        $this->parseDirectories();
229
230
        // Find options for a class registered without namespace.
231
        return $this->xRepository->getClassOptions($sClassName);
232
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
233
234
    /**
235
     * Find a callable object by class name
236
     *
237
     * @param string        $sClassName            The class name of the callable object
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 12 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
238
     *
239
     * @return CallableObject|null
240
     */
241
    public function getCallableObject($sClassName)
242
    {
243
        // Replace all separators ('.' and '_') with antislashes, and remove the antislashes
244
        // at the beginning and the end of the class name.
245
        $sClassName = (string)$sClassName;
246
        $sClassName = trim(str_replace('.', '\\', $sClassName), '\\');
247
        if($this->bUsingUnderscore)
248
        {
249
            $sClassName = trim(str_replace('_', '\\', $sClassName), '\\');
250
        }
251
252
        // Check if the callable object was already created.
253
        if(!$this->xRepository->hasCallableObject($sClassName))
254
        {
255
            $aOptions = $this->getClassOptions($sClassName);
256
            if($aOptions === null)
257
            {
258
                return null;
259
            }
260
            $this->xRepository->registerCallableObject($sClassName, $aOptions);
261
        }
262
263
        return $this->xRepository->getCallableObject($sClassName);
264
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
265
266
    /**
267
     * Register all the callable classes
268
     *
269
     * @return void
270
     */
271
    public function parseCallableClasses()
272
    {
273
        $this->parseDirectories();
274
        $this->parseNamespaces();
275
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
276
277
    /**
278
     * Create callable objects for all registered classes
279
     *
280
     * @return void
281
     */
282
    public function registerCallableObjects()
283
    {
284
        $this->parseCallableClasses();
285
286
        $aClasses = $this->xRepository->getClasses();
287
        foreach($aClasses as $sClassName => $aClassOptions)
288
        {
289
            // Make sure we create each callable object only once.
290
            if(!$this->xRepository->hasCallableObject($sClassName))
291
            {
292
                $this->xRepository->registerCallableObject($sClassName, $aClassOptions);
293
            }
294
        }
295
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
296
}
297