Completed
Push — master ( 34bc1a...41d5a5 )
by Thierry
02:48 queued 02:48
created

CallableClassPlugin::processRequest()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
c 0
b 0
f 0
nc 9
nop 1
dl 0
loc 37
rs 9.0111
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\ParameterReader;
28
use Jaxon\Request\Target;
29
use Jaxon\Request\Validator;
30
use Jaxon\Response\ResponseManager;
31
use Jaxon\Utils\Template\TemplateEngine;
32
use Jaxon\Utils\Translation\Translator;
33
use Jaxon\Exception\RequestException;
34
use Jaxon\Exception\SetupException;
35
use Psr\Http\Message\ServerRequestInterface;
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 string
53
     */
54
    protected $sPrefix;
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 parameter reader
58
     *
59
     * @var ParameterReader
60
     */
61
    protected $xParameterReader;
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
     * @var Target
103
     */
104
    protected $xTarget = null;
105
106
    /**
107
     * The methods that must not be exported to js
108
     *
109
     * @var array
110
     */
111
    protected $aProtectedMethods = [];
112
113
    /**
114
     * The class constructor
115
     *
116
     * @param string  $sPrefix
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...
117
     * @param ParameterReader $xParameterReader
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
118
     * @param ResponseManager $xResponseManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
119
     * @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...
120
     * @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...
121
     * @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; 1 found
Loading history...
122
     * @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...
123
     * @param Validator $xValidator
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...
124
     */
125
    public function __construct(string $sPrefix, ParameterReader $xParameterReader,
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
126
        ResponseManager $xResponseManager, CallableRegistry $xRegistry, CallableRepository $xRepository,
127
        TemplateEngine $xTemplateEngine, Translator $xTranslator, Validator $xValidator)
128
    {
129
        $this->sPrefix = $sPrefix;
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...
130
        $this->xParameterReader = $xParameterReader;
131
        $this->xResponseManager = $xResponseManager;
132
        $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...
133
        $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...
134
        $this->xTemplateEngine = $xTemplateEngine;
135
        $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...
136
        $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...
137
138
        // The methods of the CallableClass class must not be exported
139
        $xCallableClass = new ReflectionClass(CallableClass::class);
140
        foreach($xCallableClass->getMethods(ReflectionMethod::IS_PUBLIC) as $xMethod)
141
        {
142
            $this->aProtectedMethods[] = $xMethod->getName();
143
        }
144
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
145
146
    /**
147
     * @inheritDoc
148
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
149
    public function getName(): string
150
    {
151
        return Jaxon::CALLABLE_CLASS;
152
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
153
154
    /**
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...
155
     * @inheritDoc
156
     * @throws SetupException
157
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
158
    public function checkOptions(string $sCallable, $xOptions): array
159
    {
160
        if(!$this->xValidator->validateClass(trim($sCallable)))
161
        {
162
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
163
        }
164
        if(is_string($xOptions))
165
        {
166
            $xOptions = ['include' => $xOptions];
167
        }
168
        elseif(!is_array($xOptions))
169
        {
170
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
171
        }
172
        return $xOptions;
173
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
174
175
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $sType 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...
Coding Style introduced by
Parameter $aOptions should have a doc-comment as per coding-style.
Loading history...
176
     * @inheritDoc
177
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
178
    public function register(string $sType, string $sCallable, array $aOptions): bool
179
    {
180
        $sClassName = trim($sCallable);
181
        $this->xRepository->addClass($sClassName, $aOptions);
182
        return true;
183
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
184
185
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $sCallable should have a doc-comment as per coding-style.
Loading history...
186
     * @inheritDoc
187
     * @throws SetupException
188
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
189
    public function getCallable(string $sCallable)
190
    {
191
        return $this->xRegistry->getCallableObject($sCallable);
192
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
193
194
    /**
195
     * @inheritDoc
196
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
197
    public function getHash(): string
198
    {
199
        $this->xRegistry->parseCallableClasses();
200
        return md5($this->xRepository->getHash());
201
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
202
203
    /**
204
     * Generate client side javascript code for namespaces
205
     *
206
     * @return string
207
     */
208
    private function getNamespacesScript(): string
209
    {
210
        $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...
211
        $aJsClasses = [];
212
        $aNamespaces = $this->xRepository->getNamespaces();
213
        foreach($aNamespaces as $sNamespace)
214
        {
215
            $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...
216
            $sJsNamespace = str_replace('\\', '.', $sNamespace);
217
            $sJsNamespace .= '.Null'; // This is a sentinel. The last token is not processed in the while loop.
218
            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...
219
            {
220
                $sJsClass = substr($sJsNamespace, 0, $dotPosition);
221
                // Generate code for this object
222
                if(!isset($aJsClasses[$sJsClass]))
223
                {
224
                    $sCode .= $this->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...
225
                    $aJsClasses[$sJsClass] = $sJsClass;
226
                }
227
                $offset = $dotPosition + 1;
228
            }
229
        }
230
        return $sCode;
231
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
232
233
    /**
234
     * Generate client side javascript code for a callable class
235
     *
236
     * @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...
237
     * @param CallableObject $xCallableObject The corresponding callable object
238
     *
239
     * @return string
240
     */
241
    private function getCallableScript(string $sClassName, CallableObject $xCallableObject): string
242
    {
243
        $aProtectedMethods = is_subclass_of($sClassName, CallableClass::class) ? $this->aProtectedMethods : [];
244
        return $this->xTemplateEngine->render('jaxon::callables/object.js', [
245
            'sPrefix' => $this->sPrefix,
246
            'sClass' => $xCallableObject->getJsName(),
247
            'aMethods' => $xCallableObject->getMethods($aProtectedMethods),
248
        ]);
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 the registered callable objects
253
     *
254
     * @return string
255
     * @throws SetupException
256
     */
257
    public function getScript(): string
258
    {
259
        $this->xRegistry->parseCallableClasses();
260
        $aCallableObjects = $this->xRepository->getCallableObjects();
261
        // Sort the options by key length asc
262
        uksort($aCallableObjects, function($name1, $name2) {
263
            return strlen($name1) - strlen($name2);
264
        });
265
266
        $sCode = $this->getNamespacesScript();
267
        foreach($aCallableObjects as $sClassName => $xCallableObject)
268
        {
269
            $sCode .= $this->getCallableScript($sClassName, $xCallableObject);
270
        }
271
        return $sCode;
272
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
273
274
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xRequest should have a doc-comment as per coding-style.
Loading history...
275
     * @inheritDoc
276
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
277
    public static function canProcessRequest(ServerRequestInterface $xRequest): bool
278
    {
279
        $aBody = $xRequest->getParsedBody();
280
        if(is_array($aBody))
281
        {
282
            return isset($aBody['jxncls']) && isset($aBody['jxnmthd']);
283
        }
284
        $aParams = $xRequest->getQueryParams();
285
        return isset($aParams['jxncls']) && isset($aParams['jxnmthd']);
286
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
287
288
    /**
289
     * @inheritDoc
290
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
291
    public function getTarget(): ?Target
292
    {
293
        return $this->xTarget;
294
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
295
296
    /**
297
     * @param ServerRequestInterface $xRequest
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
298
     *
299
     * @return void
300
     */
301
    private function setTarget(ServerRequestInterface $xRequest)
302
    {
303
        $aBody = $xRequest->getParsedBody();
304
        if(is_array($aBody))
305
        {
306
            $this->xTarget = Target::makeClass(trim($aBody['jxncls']), trim($aBody['jxnmthd']));
307
            return;
308
        }
309
        $aParams = $xRequest->getQueryParams();
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...
310
        $this->xTarget = Target::makeClass(trim($aParams['jxncls']), trim($aParams['jxnmthd']));
311
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
312
313
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xRequest should have a doc-comment as per coding-style.
Loading history...
314
     * @inheritDoc
315
     * @throws RequestException
316
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
317
    public function processRequest(ServerRequestInterface $xRequest): bool
318
    {
319
        $this->setTarget($xRequest);
320
        $sRequestedClass = $this->xTarget->getClassName();
321
        $sRequestedMethod = $this->xTarget->getMethodName();
322
323
        if(!$this->xValidator->validateClass($sRequestedClass) ||
324
            !$this->xValidator->validateMethod($sRequestedMethod))
325
        {
326
            // Unable to find the requested object or method
327
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
328
                ['class' => $sRequestedClass, 'method' => $sRequestedMethod]));
329
        }
330
331
        // Call the requested method
332
        try
333
        {
334
            $xCallableObject = $this->xRegistry->getCallableObject($sRequestedClass);
335
            $xResponse = $xCallableObject->call($sRequestedMethod, $this->xParameterReader->args());
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...
336
            if(($xResponse))
337
            {
338
                $this->xResponseManager->append($xResponse);
339
            }
340
        }
341
        catch(ReflectionException $e)
342
        {
343
            // Unable to find the requested class or method
344
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
345
                ['class' => $sRequestedClass, 'method' => $sRequestedMethod]));
346
        }
347
        catch(SetupException $e)
348
        {
349
            // Unable to get the callable object
350
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
351
                ['class' => $sRequestedClass, 'method' => $sRequestedMethod]));
352
        }
353
        return true;
354
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
355
}
356