Passed
Push — master ( 27d45a...b61896 )
by Thierry
02:21
created

CallableClassPlugin::getCallable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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