Passed
Push — v5.x ( fe38d4...6ac3c7 )
by Thierry
10:27
created

CallableRegistry::getRequestFactory()   A

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 1
1
<?php
2
3
/**
4
 * CallableRegistry.php - Jaxon callable class registry
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\Plugin\Request\CallableClass;
16
17
use Jaxon\App\I18n\Translator;
18
use Jaxon\Di\Container;
19
use Jaxon\Exception\SetupException;
20
use Jaxon\Request\Factory\JsCallFactory;
21
22
use Composer\Autoload\ClassLoader;
23
use RecursiveDirectoryIterator;
24
use RecursiveIteratorIterator;
25
26
use function file_exists;
27
use function in_array;
28
use function str_replace;
29
use function strlen;
30
use function substr;
31
use function trim;
32
33
class CallableRegistry
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class CallableRegistry
Loading history...
34
{
35
    /**
36
     * The DI container
37
     *
38
     * @var Container
39
     */
40
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
41
42
    /**
43
     * The callable repository
44
     *
45
     * @var CallableRepository
46
     */
47
    protected $xRepository;
48
49
    /**
50
     * @var Translator
51
     */
52
    protected $xTranslator;
53
54
    /**
55
     * @var bool
0 ignored issues
show
Bug introduced by
Expected "boolean" but found "bool" for @var tag in member variable comment
Loading history...
56
     */
57
    protected $bDirectoriesParsed = false;
58
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 $bNamespacesParsed = false;
63
64
    /**
65
     * If the underscore is used as separator in js class names.
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 $bUsingUnderscore = false;
70
71
    /**
72
     * The Composer autoloader
73
     *
74
     * @var ClassLoader
75
     */
76
    private $xAutoloader = null;
77
78
    /**
79
     * The class constructor
80
     *
81
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
82
     * @param CallableRepository $xRepository
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
83
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 9 spaces after parameter type; 1 found
Loading history...
84
     */
85
    public function __construct(Container $di, CallableRepository $xRepository, Translator $xTranslator)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
86
    {
87
        $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...
88
        $this->xTranslator = $xTranslator;
89
        $this->xRepository = $xRepository;
90
91
        // Set the composer autoloader
92
        if(file_exists(($sAutoloadFile = __DIR__ . '/../../../../../../autoload.php')) ||
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
93
            file_exists(($sAutoloadFile = __DIR__ . '/../../../../vendor/autoload.php')))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
94
        {
95
            $this->xAutoloader = require($sAutoloadFile);
96
        }
97
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
98
99
    /**
100
     *
101
     * @param string $sDirectory    The directory being registered
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
102
     * @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...
103
     *
104
     * @return void
105
     */
106
    public function addDirectory(string $sDirectory, array $aOptions)
107
    {
108
        // Set the autoload option default value
109
        if(!isset($aOptions['autoload']))
110
        {
111
            $aOptions['autoload'] = true;
112
        }
113
        $this->xRepository->setDirectoryOptions($sDirectory, $aOptions);
114
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
115
116
    /**
117
     *
118
     * @param string $sNamespace    The namespace of the directory being registered
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
119
     * @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...
120
     *
121
     * @return void
122
     */
123
    public function addNamespace(string $sNamespace, array $aOptions)
124
    {
125
        // Separator default value
126
        if(!isset($aOptions['separator']))
127
        {
128
            $aOptions['separator'] = '.';
129
        }
130
        $aOptions['separator'] = trim($aOptions['separator']);
131
        if(!in_array($aOptions['separator'], ['.', '_']))
132
        {
133
            $aOptions['separator'] = '.';
134
        }
135
        if($aOptions['separator'] === '_')
136
        {
137
            $this->bUsingUnderscore = true;
138
        }
139
        // Set the autoload option default value
140
        if(!isset($aOptions['autoload']))
141
        {
142
            $aOptions['autoload'] = true;
143
        }
144
        // Register the dir with PSR4 autoloading
145
        if(($aOptions['autoload']) && $this->xAutoloader != null)
146
        {
147
            $this->xAutoloader->setPsr4($sNamespace . '\\', $aOptions['directory']);
148
        }
149
        $this->xRepository->setNamespaceOptions($sNamespace, $aOptions);
150
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
151
152
    /**
153
     * Read classes from directories registered without namespaces
154
     *
155
     * @return void
156
     */
157
    public function parseDirectories()
158
    {
159
        // This is to be done only once.
160
        if($this->bDirectoriesParsed)
161
        {
162
            return;
163
        }
164
        $this->bDirectoriesParsed = true;
165
166
        // Browse directories without namespaces and read all the files.
167
        $aClassMap = [];
168
        foreach($this->xRepository->getDirectoryOptions() as $sDirectory => $aOptions)
169
        {
170
            $itFile = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sDirectory));
171
            // Iterate on dir content
172
            foreach($itFile as $xFile)
173
            {
174
                // Skip everything except PHP files
175
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
176
                {
177
                    continue;
178
                }
179
180
                $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...
181
                $aClassOptions = ['timestamp' => $xFile->getMTime()];
182
                // No more custom classmap autoloading. The file will be included when needed.
183
                if(($aOptions['autoload']))
184
                {
185
                    $aClassMap[$sClassName] = $xFile->getPathname();
186
                }
187
                $this->xRepository->addClass($sClassName, $aClassOptions, $aOptions);
188
            }
189
        }
190
        // Set classmap autoloading
191
        if(($aClassMap) && $this->xAutoloader !== null)
192
        {
193
            $this->xAutoloader->addClassMap($aClassMap);
194
        }
195
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
196
197
    /**
198
     * Read classes from directories registered with namespaces
199
     *
200
     * @return void
201
     */
202
    public function parseNamespaces()
203
    {
204
        // This is to be done only once.
205
        if($this->bNamespacesParsed)
206
        {
207
            return;
208
        }
209
        $this->bNamespacesParsed = true;
210
211
        // Browse directories with namespaces and read all the files.
212
        $sDS = DIRECTORY_SEPARATOR;
213
        foreach($this->xRepository->getNamespaceOptions() as $sNamespace => $aOptions)
214
        {
215
            $this->xRepository->addNamespace($sNamespace, ['separator' => $aOptions['separator']]);
216
217
            // Iterate on dir content
218
            $sDirectory = $aOptions['directory'];
219
            $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...
220
            foreach($itFile as $xFile)
221
            {
222
                // skip everything except PHP files
223
                if(!$xFile->isFile() || $xFile->getExtension() != 'php')
224
                {
225
                    continue;
226
                }
227
228
                // Find the class path (the same as the class namespace)
229
                $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...
230
                $sRelativePath = substr($xFile->getPath(), strlen($sDirectory));
231
                $sRelativePath = trim(str_replace($sDS, '\\', $sRelativePath), '\\');
232
                if($sRelativePath !== '')
233
                {
234
                    $sClassPath .= '\\' . $sRelativePath;
235
                }
236
237
                $this->xRepository->addNamespace($sClassPath, ['separator' => $aOptions['separator']]);
238
239
                $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...
240
                $aClassOptions = ['namespace' => $sNamespace, 'timestamp' => $xFile->getMTime()];
241
                $this->xRepository->addClass($sClassName, $aClassOptions, $aOptions);
242
            }
243
        }
244
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
245
246
    /**
247
     * Check if a callable object is already in the DI, and register if not
248
     *
249
     * @param string $sClassName The class name of the callable object
250
     *
251
     * @return string
252
     * @throws SetupException
253
     */
254
    private function checkCallableObject(string $sClassName): string
255
    {
256
        // Replace all separators ('.' and '_') with antislashes, and remove the antislashes
257
        // at the beginning and the end of the class name.
258
        $sClassName = trim(str_replace('.', '\\', $sClassName), '\\');
259
        if($this->bUsingUnderscore)
260
        {
261
            $sClassName = trim(str_replace('_', '\\', $sClassName), '\\');
262
        }
263
        // Register the class.
264
        $this->di->registerCallableClass($sClassName, $this->xRepository->getClassOptions($sClassName));
265
        return $sClassName;
266
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
267
268
    /**
269
     * Get the callable object for a given class
270
     *
271
     * @param string $sClassName The class name of the callable object
272
     *
273
     * @return CallableObject|null
274
     * @throws SetupException
275
     */
276
    public function getCallableObject(string $sClassName): ?CallableObject
277
    {
278
        return $this->di->getCallableObject($this->checkCallableObject($sClassName));
279
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
280
281
    /**
282
     * Get the js call factory for a given class
283
     *
284
     * @param string $sClassName The class name of the callable object
285
     *
286
     * @return JsCallFactory|null
287
     * @throws SetupException
288
     */
289
    public function getJsCallFactory(string $sClassName): ?JsCallFactory
290
    {
291
        return $this->di->getJsCallFactory($this->checkCallableObject($sClassName));
292
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
293
294
    /**
295
     * Register all the callable classes
296
     *
297
     * @return void
298
     */
299
    public function parseCallableClasses()
300
    {
301
        $this->parseDirectories();
302
        $this->parseNamespaces();
303
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
304
}
305