CallableRepository::setDirectoryOptions()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
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\Plugin\Request\CallableClass;
16
17
use Jaxon\App\CallableClass;
18
use Jaxon\App\I18n\Translator;
19
use Jaxon\Di\Container;
20
use Jaxon\Exception\SetupException;
21
22
use ReflectionClass;
23
use ReflectionMethod;
24
25
use function array_merge;
26
use function is_string;
27
use function is_subclass_of;
28
use function strlen;
29
use function strncmp;
30
31
class CallableRepository
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class CallableRepository
Loading history...
32
{
33
    /**
34
     * The DI container
35
     *
36
     * @var Container
37
     */
38
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
39
40
    /**
41
     * @var Translator
42
     */
43
    protected $xTranslator;
44
45
    /**
46
     * The namespace options
47
     *
48
     * These are the options of the registered namespaces.
49
     *
50
     * @var array
51
     */
52
    protected $aNamespaceOptions = [];
53
54
    /**
55
     * The directory options
56
     *
57
     * These are the options of the registered directories.
58
     *
59
     * @var array
60
     */
61
    protected $aDirectoryOptions = [];
62
63
    /**
64
     * The classes
65
     *
66
     * These are all the classes, both registered and found in registered directories.
67
     *
68
     * @var array
69
     */
70
    protected $aClasses = [];
71
72
    /**
73
     * The namespaces
74
     *
75
     * These are all the namespaces found in registered directories.
76
     *
77
     * @var array
78
     */
79
    protected $aNamespaces = [];
80
81
    /**
82
     * The string that will be used to compute the js file hash
83
     *
84
     * @var string
85
     */
86
    protected $sHash = '';
87
88
    /**
89
     * @var array
90
     */
91
    private $aDefaultClassOptions = ['separator' => '.', 'protected' => [], 'functions' => [], 'timestamp' => 0];
92
93
    /**
94
     * The methods that must not be exported to js
95
     *
96
     * @var array
97
     */
98
    private $aProtectedMethods = [];
99
100
    /**
101
     * The constructor
102
     *
103
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
104
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
105
     */
106
    public function __construct(Container $di, Translator $xTranslator)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
107
    {
108
        $this->di = $di;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 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...
109
        $this->xTranslator = $xTranslator;
110
111
        // The methods of the CallableClass class must not be exported
112
        $xCallableClass = new ReflectionClass(CallableClass::class);
113
        foreach($xCallableClass->getMethods(ReflectionMethod::IS_PUBLIC) as $xMethod)
114
        {
115
            $this->aProtectedMethods[] = $xMethod->getName();
116
        }
117
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
118
119
    /**
120
     * @return array
121
     */
122
    public function getDirectoryOptions(): array
123
    {
124
        return $this->aDirectoryOptions;
125
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
126
127
    /**
128
     * @param string $sDirectory
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
129
     * @param array $aOptions
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
130
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
131
    public function setDirectoryOptions(string $sDirectory, array $aOptions): void
132
    {
133
        $this->aDirectoryOptions[$sDirectory] = $aOptions;
134
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
135
136
    /**
137
     * @return array
138
     */
139
    public function getNamespaceOptions(): array
140
    {
141
        return $this->aNamespaceOptions;
142
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
143
144
    /**
145
     * @param string $sNamespace
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
146
     * @param array $aOptions
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
147
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
148
    public function setNamespaceOptions(string $sNamespace, array $aOptions): void
149
    {
150
        $this->aNamespaceOptions[$sNamespace] = $aOptions;
151
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
152
153
    /**
154
     * Get all registered namespaces
155
     *
156
     * @return array
157
     */
158
    public function getNamespaces(): array
159
    {
160
        return $this->aNamespaces;
161
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
162
163
    /**
164
     * Get the hash
165
     *
166
     * @return string
167
     */
168
    public function getHash(): string
169
    {
170
        return $this->sHash;
171
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
172
173
    /**
174
     * Get a given class options from specified directory options
175
     *
176
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
177
     * @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...
178
     * @param array $aDirectoryOptions    The directory options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
179
     *
180
     * @return array
181
     */
182
    public function makeClassOptions(string $sClassName, array $aClassOptions, array $aDirectoryOptions): array
183
    {
184
        foreach($this->aDefaultClassOptions as $sOption => $xValue)
185
        {
186
            if(!isset($aClassOptions[$sOption]))
187
            {
188
                $aClassOptions[$sOption] = $xValue;
189
            }
190
        }
191
        $aClassOptions['excluded'] = (bool)($aClassOptions['excluded'] ?? false); // Convert to bool.
192
        if(is_string($aClassOptions['protected']))
193
        {
194
            $aClassOptions['protected'] = [$aClassOptions['protected']]; // Convert to array.
195
        }
196
197
        $aDirectoryOptions['functions'] = []; // The 'functions' section is not allowed here.
198
        $aOptionGroups = [
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 18 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...
199
            $aDirectoryOptions, // Options at directory level
200
            $aDirectoryOptions['classes']['*'] ?? [], // Options for all classes
201
            $aDirectoryOptions['classes'][$sClassName] ?? [], // Options for this specific class
202
        ];
203
        foreach($aOptionGroups as $aOptionGroup)
204
        {
205
            if(isset($aOptionGroup['separator']))
206
            {
207
                $aClassOptions['separator'] = (string)$aOptionGroup['separator'];
208
            }
209
            if(isset($aOptionGroup['excluded']))
210
            {
211
                $aClassOptions['excluded'] = (bool)$aOptionGroup['excluded'];
212
            }
213
            if(isset($aOptionGroup['protected']))
214
            {
215
                if(is_string($aOptionGroup['protected']))
216
                {
217
                    $aOptionGroup['protected'] = [$aOptionGroup['protected']]; // Convert to array.
218
                }
219
                $aClassOptions['protected'] = array_merge($aClassOptions['protected'], $aOptionGroup['protected']);
220
            }
221
            if(isset($aOptionGroup['functions']))
222
            {
223
                $aClassOptions['functions'] = array_merge($aClassOptions['functions'], $aOptionGroup['functions']);
224
            }
225
        }
226
227
        return $aClassOptions;
228
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
229
230
    /**
231
     *
232
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
233
     * @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...
234
     * @param array $aDirectoryOptions    The directory options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
235
     *
236
     * @return void
237
     */
238
    public function addClass(string $sClassName, array $aClassOptions, array $aDirectoryOptions = [])
239
    {
240
        $this->aClasses[$sClassName] = $this->makeClassOptions($sClassName, $aClassOptions, $aDirectoryOptions);
241
        $this->sHash .= $sClassName . $this->aClasses[$sClassName]['timestamp'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 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...
242
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
243
244
    /**
245
     *
246
     * @param string $sNamespace    The namespace
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
247
     * @param array $aOptions    The associated options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
248
     *
249
     * @return void
250
     */
251
    public function addNamespace(string $sNamespace, array $aOptions)
252
    {
253
        $this->aNamespaces[] = $sNamespace;
254
        $this->sHash .= $sNamespace . $aOptions['separator'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 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...
255
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
256
257
    /**
258
     * Find options for a class which is registered with namespace
259
     *
260
     * @param string $sClassName    The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
261
     *
262
     * @return void
263
     */
264
    private function getNamespaceClassOptions(string $sClassName)
265
    {
266
        // Find the corresponding namespace
267
        foreach($this->aNamespaceOptions as $sNamespace => $aOptions)
268
        {
269
            // Check if the namespace matches the class.
270
            if(strncmp($sClassName, $sNamespace . '\\', strlen($sNamespace) + 1) === 0)
271
            {
272
                // Save the class options
273
                $this->aClasses[$sClassName] = $this->makeClassOptions($sClassName,
274
                    ['namespace' => $sNamespace], $aOptions);
275
                return;
276
            }
277
        }
278
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
279
280
    /**
281
     * Find the options associated with a registered class name
282
     *
283
     * @param string $sClassName The class name
284
     *
285
     * @return array
286
     * @throws SetupException
287
     */
288
    public function getClassOptions(string $sClassName): array
289
    {
290
        // Find options for a class registered with namespace.
291
        if(!isset($this->aClasses[$sClassName]))
292
        {
293
            $this->getNamespaceClassOptions($sClassName);
294
            if(!isset($this->aClasses[$sClassName]))
295
            {
296
                // Find options for a class registered without namespace.
297
                // We then need to parse all classes to be able to find one.
298
                $this->di->getCallableRegistry()->parseDirectories();
299
            }
300
        }
301
        if(isset($this->aClasses[$sClassName]))
302
        {
303
            return $this->aClasses[$sClassName];
304
        }
305
        $sMessage = $this->xTranslator->trans('errors.class.invalid', ['name' => $sClassName]);
306
        throw new SetupException($sMessage);
307
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
308
309
    /**
310
     * Find the options associated with a registered class name
311
     *
312
     * @param string $sClassName The class name
313
     *
314
     * @return array
315
     */
316
    public function getProtectedMethods(string $sClassName): array
317
    {
318
        return is_subclass_of($sClassName, CallableClass::class) ? $this->aProtectedMethods : [];
319
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
320
321
    /**
322
     * Get callable objects for known classes
323
     *
324
     * @return array
325
     * @throws SetupException
326
     */
327
    public function getCallableObjects(): array
328
    {
329
        $aCallableObjects = [];
330
        foreach($this->aClasses as $sClassName => $aOptions)
331
        {
332
            $this->di->registerCallableClass($sClassName, $aOptions);
333
            $aCallableObjects[$sClassName] = $this->di->getCallableObject($sClassName);
334
        }
335
        return $aCallableObjects;
336
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
337
}
338