Passed
Push — master ( a07882...2b8759 )
by Thierry
02:21
created

CallableRepository::parseNamespaces()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 6
nop 1
dl 0
loc 40
rs 8.6666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * CallableRepository.php - Jaxon callable object repository
5
 *
6
 * This class stores all the callable object already created.
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\Plugin\CallableClass;
16
17
use Jaxon\Container\Container;
18
use Jaxon\Exception\SetupException;
19
20
use RecursiveDirectoryIterator;
21
use RecursiveIteratorIterator;
22
23
use function array_merge;
24
use function str_replace;
25
use function strlen;
26
use function strncmp;
27
use function substr;
28
use function trim;
29
30
class CallableRepository
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class CallableRepository
Loading history...
31
{
32
    /**
33
     * The DI container
34
     *
35
     * @var Container
36
     */
37
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
38
39
    /**
40
     * The classes
41
     *
42
     * These are all the registered classes.
43
     *
44
     * @var array
45
     */
46
    protected $aClasses = [];
47
48
    /**
49
     * The namespaces
50
     *
51
     * These are all the namespaces found in registered directories.
52
     *
53
     * @var array
54
     */
55
    protected $aNamespaces = [];
56
57
    /**
58
     * Indicate if the registered directories are already parsed
59
     *
60
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
61
     */
62
    protected $bParsedDirectories = false;
63
64
    /**
65
     * Indicate if the registered namespaces are already parsed
66
     *
67
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
68
     */
69
    protected $bParsedNamespaces = false;
70
71
    /**
72
     * The constructor
73
     *
74
     * @param Container  $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 2 found
Loading history...
75
     */
76
    public function __construct(Container $di)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
77
    {
78
        $this->di = $di;
79
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
80
81
    /**
82
     * Get a given class options from specified directory options
83
     *
84
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
85
     * @param array $aClassOptions    The default class options
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
86
     * @param array $aDirectoryOptions    The directory options
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
87
     *
88
     * @return array
89
     */
90
    public function makeClassOptions(string $sClassName, array $aClassOptions, array $aDirectoryOptions): array
91
    {
92
        if(!isset($aClassOptions['functions']))
93
        {
94
            $aClassOptions['functions'] = [];
95
        }
96
        foreach(['separator', 'protected'] as $sName)
97
        {
98
            if(isset($aDirectoryOptions[$sName]))
99
            {
100
                $aClassOptions[$sName] = $aDirectoryOptions[$sName];
101
            }
102
        }
103
104
        $aFunctionOptions = $aDirectoryOptions['classes'] ?? [];
105
        foreach($aFunctionOptions as $sName => $xValue)
106
        {
107
            if($sName === '*' || strncmp($sClassName, $sName, strlen($sName)) === 0)
108
            {
109
                $aClassOptions['functions'] = array_merge($aClassOptions['functions'], $xValue);
110
            }
111
        }
112
113
        // This value will be used to compute hash
114
        if(!isset($aClassOptions['timestamp']))
115
        {
116
            $aClassOptions['timestamp'] = 0;
117
        }
118
119
        return $aClassOptions;
120
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
121
122
    /**
123
     * Get all registered classes
124
     *
125
     * @return array
126
     */
127
    public function getClasses(): array
128
    {
129
        return $this->aClasses;
130
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
131
132
    /**
133
     * Get all registered namespaces
134
     *
135
     * @return array
136
     */
137
    public function getNamespaces(): array
138
    {
139
        return $this->aNamespaces;
140
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
141
142
    /**
143
     * Get the names of all registered classess
144
     *
145
     * @return array
146
     */
147
    public function getClassNames(): array
148
    {
149
        return array_keys($this->aClasses);
150
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
151
152
    /**
153
     *
154
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
155
     * @param array $aClassOptions    The default class options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
156
     * @param array $aDirectoryOptions    The directory options
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
157
     *
158
     * @return void
159
     */
160
    public function addClass(string $sClassName, array $aClassOptions, array $aDirectoryOptions = [])
161
    {
162
        $this->aClasses[$sClassName] = $this->makeClassOptions($sClassName, $aClassOptions, $aDirectoryOptions);
163
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
164
165
    /**
166
     *
167
     * @param string $sNamespace    The namespace
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
168
     * @param array|string $aOptions    The associated options
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
169
     *
170
     * @return void
171
     */
172
    public function addNamespace(string $sNamespace, $aOptions)
173
    {
174
        $this->aNamespaces[$sNamespace] = $aOptions;
175
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
176
177
    /**
178
     * Find the options associated with a registered class name
179
     *
180
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
181
     *
182
     * @return array|null
183
     */
184
    public function getClassOptions(string $sClassName): ?array
185
    {
186
        if(!isset($this->aClasses[$sClassName]))
187
        {
188
            // Class not found
189
            return null;
190
        }
191
        return $this->aClasses[$sClassName];
192
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
193
194
    /**
195
     * Read classes from directories registered without namespaces
196
     *
197
     * @param array $aDirectories    The directories
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
198
     *
199
     * @return void
200
     */
201
    public function parseDirectories(array $aDirectories)
202
    {
203
        // Browse directories without namespaces and read all the files.
204
        // This is to be done only once.
205
        if($this->bParsedDirectories)
206
        {
207
            return;
208
        }
209
        $this->bParsedDirectories = true;
210
211
        // Browse directories without namespaces and read all the files.
212
        foreach($aDirectories as $sDirectory => $aOptions)
213
        {
214
            $itFile = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sDirectory));
215
            // Iterate on dir content
216
            foreach($itFile as $xFile)
217
            {
218
                // skip everything except PHP files
219
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
220
                {
221
                    continue;
222
                }
223
224
                $sClassName = $xFile->getBasename('.php');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 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...
225
                $aClassOptions = ['timestamp' => $xFile->getMTime()];
226
                // No more classmap autoloading. The file will be included when needed.
227
                if(($aOptions['autoload']))
228
                {
229
                    $aClassOptions['include'] = $xFile->getPathname();
230
                }
231
                $this->addClass($sClassName, $aClassOptions, $aOptions);
232
            }
233
        }
234
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
235
236
    /**
237
     * Read classes from directories registered with namespaces
238
     *
239
     * @param array $aNamespaces    The namespaces
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
240
     *
241
     * @return void
242
     */
243
    public function parseNamespaces(array $aNamespaces)
244
    {
245
        // This is to be done only once.
246
        if($this->bParsedNamespaces)
247
        {
248
            return;
249
        }
250
        $this->bParsedNamespaces = true;
251
252
        // Browse directories with namespaces and read all the files.
253
        $sDS = DIRECTORY_SEPARATOR;
254
        foreach($aNamespaces as $sNamespace => $aOptions)
255
        {
256
            $this->addNamespace($sNamespace, ['separator' => $aOptions['separator']]);
257
258
            // Iterate on dir content
259
            $sDirectory = $aOptions['directory'];
260
            $itFile = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sDirectory));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 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...
261
            foreach($itFile as $xFile)
262
            {
263
                // skip everything except PHP files
264
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
265
                {
266
                    continue;
267
                }
268
269
                // Find the class path (the same as the class namespace)
270
                $sClassPath = $sNamespace;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 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...
271
                $sRelativePath = substr($xFile->getPath(), strlen($sDirectory));
272
                $sRelativePath = trim(str_replace($sDS, '\\', $sRelativePath), '\\');
273
                if($sRelativePath !== '')
274
                {
275
                    $sClassPath .= '\\' . $sRelativePath;
276
                }
277
278
                $this->addNamespace($sClassPath, ['separator' => $aOptions['separator']]);
279
280
                $sClassName = $sClassPath . '\\' . $xFile->getBasename('.php');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 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...
281
                $aClassOptions = ['namespace' => $sNamespace, 'timestamp' => $xFile->getMTime()];
282
                $this->addClass($sClassName, $aClassOptions, $aOptions);
283
            }
284
        }
285
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
286
287
    /**
288
     * Register a callable class
289
     *
290
     * @param string $sClassName The class name of the callable object
291
     * @param array $aOptions The callable object options
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
292
     *
293
     * @return void
294
     * @throws SetupException
295
     */
296
    public function registerCallableClass(string $sClassName, array $aOptions)
297
    {
298
        // Make sure we create each callable object only once.
299
        if($this->di->h($sClassName))
300
        {
301
            return;
302
        }
303
        // Make sure the registered class exists
304
        if(isset($aOptions['include']))
305
        {
306
            require_once($aOptions['include']);
307
        }
308
        // Register the callable object
309
        $this->di->registerCallableClass($sClassName, $aOptions);
310
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
311
}
312