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

CallableClassPlugin::processRequest()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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