Passed
Push — v5.x ( 6ac3c7...223ede )
by Thierry
02:17
created

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