Passed
Push — master ( 8eafb5...9551a9 )
by Thierry
02:09
created

ClassPlugin::getHash()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 0
dl 0
loc 17
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * ClassPlugin.php - Jaxon callable class plugin
5
 *
6
 * This class registers user defined callable classes, generates client side javascript code,
7
 * and calls their methods on user request
8
 *
9
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
10
 * @author Jared White
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
11
 * @author J. Max Wilson
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
12
 * @author Joseph Woolley
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
13
 * @author Steffen Konerow
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
14
 * @author Thierry Feuzeu <[email protected]>
15
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
16
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
17
 * @copyright 2016 Thierry Feuzeu <[email protected]>
18
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
19
 * @link https://github.com/jaxon-php/jaxon-core
20
 */
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...
21
22
namespace Jaxon\Request\Plugin\CallableClass;
23
24
use Jaxon\Jaxon;
25
use Jaxon\CallableClass;
26
use Jaxon\Plugin\Request as RequestPlugin;
27
use Jaxon\Request\Handler\Handler as RequestHandler;
28
use Jaxon\Request\Target;
29
use Jaxon\Request\Validator;
30
use Jaxon\Response\Manager as ResponseManager;
31
use Jaxon\Utils\Config\Config;
32
use Jaxon\Utils\Template\Engine as TemplateEngine;
33
use Jaxon\Utils\Translation\Translator;
34
use Jaxon\Exception\RequestException;
35
use Jaxon\Exception\SetupException;
36
37
use ReflectionException;
38
39
use function is_array;
40
use function is_string;
41
use function is_subclass_of;
42
use function md5;
43
use function strlen;
44
use function trim;
45
use function uksort;
46
47
class ClassPlugin extends RequestPlugin
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class ClassPlugin
Loading history...
48
{
49
    /**
50
     * @var Config
51
     */
52
    protected $xConfig;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
53
54
    /**
55
     * The request handler
56
     *
57
     * @var RequestHandler
58
     */
59
    protected $xRequestHandler;
60
61
    /**
62
     * The response manager
63
     *
64
     * @var ResponseManager
65
     */
66
    protected $xResponseManager;
67
68
    /**
69
     * The callable registry
70
     *
71
     * @var Registry
72
     */
73
    protected $xRegistry;
74
75
    /**
76
     * The callable repository
77
     *
78
     * @var Repository
79
     */
80
    protected $xRepository;
81
82
    /**
83
     * The request data validator
84
     *
85
     * @var Validator
86
     */
87
    protected $xValidator;
88
89
    /**
90
     * @var TemplateEngine
91
     */
92
    protected $xTemplateEngine;
93
94
    /**
95
     * @var Translator
96
     */
97
    protected $xTranslator;
98
99
    /**
100
     * The value of the class parameter of the incoming Jaxon request
101
     *
102
     * @var string
103
     */
104
    protected $sRequestedClass = '';
105
106
    /**
107
     * The value of the method parameter of the incoming Jaxon request
108
     *
109
     * @var string
110
     */
111
    protected $sRequestedMethod = '';
112
113
    /**
114
     * The methods that must not be exported to js
115
     *
116
     * @var array
117
     */
118
    protected $aProtectedMethods = [];
119
120
    /**
121
     * The class constructor
122
     *
123
     * @param Config  $xConfig
0 ignored issues
show
Coding Style introduced by
Expected 10 spaces after parameter type; 2 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
124
     * @param RequestHandler  $xRequestHandler
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
125
     * @param ResponseManager  $xResponseManager
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 2 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
126
     * @param Registry $xRegistry    The callable class registry
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
127
     * @param Repository $xRepository    The callable object repository
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter name; 4 found
Loading history...
128
     * @param TemplateEngine  $xTemplateEngine
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
129
     * @param Translator  $xTranslator
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter type; 2 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
130
     * @param Validator  $xValidator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 7 spaces after parameter type; 2 found
Loading history...
131
     */
132
    public function __construct(Config $xConfig, RequestHandler $xRequestHandler,
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
133
        ResponseManager $xResponseManager, Registry $xRegistry, Repository $xRepository,
134
        TemplateEngine  $xTemplateEngine, Translator $xTranslator, Validator $xValidator)
135
    {
136
        $this->xConfig = $xConfig;
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...
137
        $this->xRequestHandler = $xRequestHandler;
138
        $this->xResponseManager = $xResponseManager;
139
        $this->xRegistry = $xRegistry;
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...
140
        $this->xRepository = $xRepository;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 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...
141
        $this->xTemplateEngine = $xTemplateEngine;
142
        $this->xTranslator = $xTranslator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 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...
143
        $this->xValidator = $xValidator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 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...
144
145
        if(isset($_GET['jxncls']))
146
        {
147
            $this->sRequestedClass = trim($_GET['jxncls']);
148
        }
149
        if(isset($_GET['jxnmthd']))
150
        {
151
            $this->sRequestedMethod = trim($_GET['jxnmthd']);
152
        }
153
        if(isset($_POST['jxncls']))
154
        {
155
            $this->sRequestedClass = trim($_POST['jxncls']);
156
        }
157
        if(isset($_POST['jxnmthd']))
158
        {
159
            $this->sRequestedMethod = trim($_POST['jxnmthd']);
160
        }
161
162
        // The methods of the \Jaxon\ClassPlugin class must not be exported
163
        $xCallableClass = new \ReflectionClass(CallableClass::class);
164
        foreach($xCallableClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $xMethod)
165
        {
166
            $this->aProtectedMethods[] = $xMethod->getName();
167
        }
168
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
169
170
    /**
171
     * @inheritDoc
172
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
173
    public function getName(): string
174
    {
175
        return Jaxon::CALLABLE_CLASS;
176
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
177
178
    /**
179
     * @inheritDoc
180
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
181
    public function getTarget(): ?Target
182
    {
183
        if(!$this->sRequestedClass || !$this->sRequestedMethod)
184
        {
185
            return null;
186
        }
187
        return Target::makeClass($this->sRequestedClass, $this->sRequestedMethod);
188
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
189
190
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xOptions should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $sCallable should have a doc-comment as per coding-style.
Loading history...
191
     * @inheritDoc
192
     * @throws SetupException
193
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
194
    public function checkOptions(string $sCallable, $xOptions): array
195
    {
196
        if(!$this->xValidator->validateClass(trim($sCallable)))
197
        {
198
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
199
        }
200
        if(is_string($xOptions))
201
        {
202
            $xOptions = ['include' => $xOptions];
203
        }
204
        elseif(!is_array($xOptions))
205
        {
206
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
207
        }
208
        return $xOptions;
209
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
210
211
    /**
212
     * Register a callable class
213
     *
214
     * @param string $sType    The type of request handler being registered
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
215
     * @param string $sCallable    The name of the class being registered
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
216
     * @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 2 spaces after parameter name; 4 found
Loading history...
217
     *
218
     * @return bool
219
     */
220
    public function register(string $sType, string $sCallable, array $aOptions): bool
221
    {
222
        $sClassName = trim($sCallable);
223
        $this->xRepository->addClass($sClassName, $aOptions);
224
        return true;
225
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
226
227
    /**
228
     * @inheritDoc
229
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
230
    public function getHash(): string
231
    {
232
        $this->xRegistry->parseCallableClasses();
233
        $aNamespaces = $this->xRepository->getNamespaces();
234
        $aClasses = $this->xRepository->getClasses();
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...
235
        $sHash = '';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 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...
236
237
        foreach($aNamespaces as $sNamespace => $aOptions)
238
        {
239
            $sHash .= $sNamespace . $aOptions['separator'];
240
        }
241
        foreach($aClasses as $sClassName => $aOptions)
242
        {
243
            $sHash .= $sClassName . $aOptions['timestamp'];
244
        }
245
246
        return md5($sHash);
247
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
248
249
    /**
250
     * Generate client side javascript code for namespaces
251
     *
252
     * @return string
253
     */
254
    private function getNamespacesScript(): string
255
    {
256
        $sCode = '';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 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...
257
        $sPrefix = $this->xConfig->getOption('core.prefix.class');
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...
258
        $aJsClasses = [];
259
        $aNamespaces = array_keys($this->xRepository->getNamespaces());
260
        foreach($aNamespaces as $sNamespace)
261
        {
262
            $offset = 0;
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...
263
            $sJsNamespace = str_replace('\\', '.', $sNamespace);
264
            $sJsNamespace .= '.Null'; // This is a sentinel. The last token is not processed in the while loop.
265
            while(($dotPosition = strpos($sJsNamespace, '.', $offset)) !== false)
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
266
            {
267
                $sJsClass = substr($sJsNamespace, 0, $dotPosition);
268
                // Generate code for this object
269
                if(!isset($aJsClasses[$sJsClass]))
270
                {
271
                    $sCode .= "$sPrefix$sJsClass = {};\n";
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...
272
                    $aJsClasses[$sJsClass] = $sJsClass;
273
                }
274
                $offset = $dotPosition + 1;
275
            }
276
        }
277
        return $sCode;
278
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
279
280
    /**
281
     * Generate client side javascript code for a callable class
282
     *
283
     * @param string $sClassName
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...
284
     * @param CallableObject $xCallableObject The corresponding callable object
285
     *
286
     * @return string
287
     */
288
    private function getCallableScript(string $sClassName, CallableObject $xCallableObject): string
289
    {
290
        $aProtectedMethods = is_subclass_of($sClassName, CallableClass::class) ? $this->aProtectedMethods : [];
291
        return $this->xTemplateEngine->render('jaxon::support/object.js', [
292
            'sPrefix' => $this->xConfig->getOption('core.prefix.class'),
293
            'sClass' => $xCallableObject->getJsName(),
294
            'aMethods' => $xCallableObject->getMethods($aProtectedMethods),
295
        ]);
296
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
297
298
    /**
299
     * Generate client side javascript code for the registered callable objects
300
     *
301
     * @return string
302
     */
303
    public function getScript(): string
304
    {
305
        $this->xRegistry->registerCallableClasses();
306
307
        $sCode = $this->getNamespacesScript();
308
309
        $aClassNames = $this->xRepository->getClassNames();
310
        // Sort the options by key length asc
311
        uksort($aClassNames, function($name1, $name2) {
312
            return strlen($name1) - strlen($name2);
313
        });
314
        foreach($aClassNames as $sClassName)
315
        {
316
            $xCallableObject = $this->xRegistry->getCallableObject($sClassName);
317
            $sCode .= $this->getCallableScript($sClassName, $xCallableObject);
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...
318
        }
319
320
        return $sCode;
321
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
322
323
    /**
324
     * @inheritDoc
325
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
326
    public function canProcessRequest(): bool
327
    {
328
        // Check the validity of the class name
329
        if(($this->sRequestedClass !== null && !$this->xValidator->validateClass($this->sRequestedClass)) ||
330
            ($this->sRequestedMethod !== null && !$this->xValidator->validateMethod($this->sRequestedMethod)))
331
        {
332
            $this->sRequestedClass = null;
333
            $this->sRequestedMethod = null;
334
        }
335
        return ($this->sRequestedClass !== null && $this->sRequestedMethod !== null);
336
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
337
338
    /**
339
     * @inheritDoc
340
     * @throws RequestException
341
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
342
    public function processRequest(): bool
343
    {
344
        if(!$this->canProcessRequest())
345
        {
346
            return false;
347
        }
348
349
        // Find the requested method
350
        $xCallableObject = $this->xRegistry->getCallableObject($this->sRequestedClass);
351
        if(!$xCallableObject || !$xCallableObject->hasMethod($this->sRequestedMethod))
0 ignored issues
show
introduced by
$xCallableObject is of type Jaxon\Request\Plugin\CallableClass\CallableObject, thus it always evaluated to true.
Loading history...
352
        {
353
            // Unable to find the requested object or method
354
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
355
                ['class' => $this->sRequestedClass, 'method' => $this->sRequestedMethod]));
356
        }
357
358
        // Call the requested method
359
        $aArgs = $this->xRequestHandler->processArguments();
360
        try
361
        {
362
            $xResponse = $xCallableObject->call($this->sRequestedMethod, $aArgs);
363
            if(($xResponse))
364
            {
365
                $this->xResponseManager->append($xResponse);
366
            }
367
        }
368
        catch(ReflectionException $e)
369
        {
370
            // Unable to find the requested class
371
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
372
                ['class' => $this->sRequestedClass, 'method' => $this->sRequestedMethod]));
373
        }
374
        return true;
375
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
376
}
377