Passed
Push — master ( 1d699e...0f9ddd )
by Thierry
04:26 queued 02:06
created

CallableClassPlugin::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 8
dl 0
loc 18
rs 9.9
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
     * The value of the class parameter of the incoming Jaxon request
103
     *
104
     * @var string
105
     */
106
    protected static $sRequestedClass = '';
107
108
    /**
109
     * The value of the method parameter of the incoming Jaxon request
110
     *
111
     * @var string
112
     */
113
    protected static $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 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...
126
     * @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...
127
     * @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...
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; 1 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; 1 found
Loading history...
132
     * @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...
133
     */
134
    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...
135
        ResponseManager $xResponseManager, CallableRegistry $xRegistry, CallableRepository $xRepository,
136
        TemplateEngine $xTemplateEngine, Translator $xTranslator, Validator $xValidator)
137
    {
138
        $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...
139
        $this->xParameterReader = $xParameterReader;
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
        // The methods of the CallableClass class must not be exported
148
        $xCallableClass = new ReflectionClass(CallableClass::class);
149
        foreach($xCallableClass->getMethods(ReflectionMethod::IS_PUBLIC) as $xMethod)
150
        {
151
            $this->aProtectedMethods[] = $xMethod->getName();
152
        }
153
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
154
155
    /**
156
     * @inheritDoc
157
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
158
    public function getName(): string
159
    {
160
        return Jaxon::CALLABLE_CLASS;
161
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
162
163
    /**
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...
164
     * @inheritDoc
165
     * @throws SetupException
166
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
167
    public function checkOptions(string $sCallable, $xOptions): array
168
    {
169
        if(!$this->xValidator->validateClass(trim($sCallable)))
170
        {
171
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
172
        }
173
        if(is_string($xOptions))
174
        {
175
            $xOptions = ['include' => $xOptions];
176
        }
177
        elseif(!is_array($xOptions))
178
        {
179
            throw new SetupException($this->xTranslator->trans('errors.objects.invalid-declaration'));
180
        }
181
        return $xOptions;
182
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
183
184
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $aOptions 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 $sType should have a doc-comment as per coding-style.
Loading history...
185
     * @inheritDoc
186
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
187
    public function register(string $sType, string $sCallable, array $aOptions): bool
188
    {
189
        $sClassName = trim($sCallable);
190
        $this->xRepository->addClass($sClassName, $aOptions);
191
        return true;
192
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
193
194
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $sCallable should have a doc-comment as per coding-style.
Loading history...
195
     * @inheritDoc
196
     * @throws SetupException
197
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
198
    public function getCallable(string $sCallable)
199
    {
200
        return $this->xRegistry->getCallableObject($sCallable);
201
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
202
203
    /**
204
     * @inheritDoc
205
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
206
    public function getHash(): string
207
    {
208
        $this->xRegistry->parseCallableClasses();
209
        $aNamespaces = $this->xRepository->getNamespaces();
210
        $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...
211
        $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...
212
213
        foreach($aNamespaces as $sNamespace => $aOptions)
214
        {
215
            $sHash .= $sNamespace . $aOptions['separator'];
216
        }
217
        foreach($aClasses as $sClassName => $aOptions)
218
        {
219
            $sHash .= $sClassName . $aOptions['timestamp'];
220
        }
221
222
        return md5($sHash);
223
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
224
225
    /**
226
     * Generate client side javascript code for namespaces
227
     *
228
     * @return string
229
     */
230
    private function getNamespacesScript(): string
231
    {
232
        $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...
233
        $aJsClasses = [];
234
        $aNamespaces = array_keys($this->xRepository->getNamespaces());
235
        foreach($aNamespaces as $sNamespace)
236
        {
237
            $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...
238
            $sJsNamespace = str_replace('\\', '.', $sNamespace);
239
            $sJsNamespace .= '.Null'; // This is a sentinel. The last token is not processed in the while loop.
240
            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...
241
            {
242
                $sJsClass = substr($sJsNamespace, 0, $dotPosition);
243
                // Generate code for this object
244
                if(!isset($aJsClasses[$sJsClass]))
245
                {
246
                    $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...
247
                    $aJsClasses[$sJsClass] = $sJsClass;
248
                }
249
                $offset = $dotPosition + 1;
250
            }
251
        }
252
        return $sCode;
253
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
254
255
    /**
256
     * Generate client side javascript code for a callable class
257
     *
258
     * @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...
259
     * @param CallableObject $xCallableObject The corresponding callable object
260
     *
261
     * @return string
262
     */
263
    private function getCallableScript(string $sClassName, CallableObject $xCallableObject): string
264
    {
265
        $aProtectedMethods = is_subclass_of($sClassName, CallableClass::class) ? $this->aProtectedMethods : [];
266
        return $this->xTemplateEngine->render('jaxon::callables/object.js', [
267
            'sPrefix' => $this->sPrefix,
268
            'sClass' => $xCallableObject->getJsName(),
269
            'aMethods' => $xCallableObject->getMethods($aProtectedMethods),
270
        ]);
271
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
272
273
    /**
274
     * Generate client side javascript code for the registered callable objects
275
     *
276
     * @return string
277
     * @throws SetupException
278
     */
279
    public function getScript(): string
280
    {
281
        $this->xRegistry->registerCallableClasses();
282
283
        $sCode = $this->getNamespacesScript();
284
285
        $aClassNames = $this->xRepository->getClassNames();
286
        // Sort the options by key length asc
287
        uksort($aClassNames, function($name1, $name2) {
288
            return strlen($name1) - strlen($name2);
289
        });
290
        foreach($aClassNames as $sClassName)
291
        {
292
            $xCallableObject = $this->xRegistry->getCallableObject($sClassName);
293
            $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...
294
        }
295
296
        return $sCode;
297
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
298
299
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xRequest should have a doc-comment as per coding-style.
Loading history...
300
     * @inheritDoc
301
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
302
    public static function canProcessRequest(ServerRequestInterface $xRequest): bool
303
    {
304
        self::$sRequestedClass = '';
305
        self::$sRequestedMethod = '';
306
        $aBody = $xRequest->getParsedBody();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 18 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...
307
        if(is_array($aBody))
308
        {
309
            if(isset($aBody['jxncls']))
310
            {
311
                self::$sRequestedClass = trim($aBody['jxncls']);
312
            }
313
            if(isset($aBody['jxnmthd']))
314
            {
315
                self::$sRequestedMethod = trim($aBody['jxnmthd']);
316
            }
317
        }
318
        else
319
        {
320
            $aParams = $xRequest->getQueryParams();
321
            if(isset($aParams['jxncls']))
322
            {
323
                self::$sRequestedClass = trim($aParams['jxncls']);
324
            }
325
            if(isset($aParams['jxnmthd']))
326
            {
327
                self::$sRequestedMethod = trim($aParams['jxnmthd']);
328
            }
329
        }
330
        return (self::$sRequestedClass !== '' && self::$sRequestedMethod !== '');
331
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
332
333
    /**
334
     * @inheritDoc
335
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
336
    public function getTarget(): ?Target
337
    {
338
        if(!self::$sRequestedClass || !self::$sRequestedMethod)
339
        {
340
            return null;
341
        }
342
        return Target::makeClass(self::$sRequestedClass, self::$sRequestedMethod);
343
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
344
345
    /**
346
     * @inheritDoc
347
     * @throws RequestException
348
     * @throws SetupException
349
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
350
    public function processRequest(): bool
351
    {
352
        if(!$this->xValidator->validateClass(self::$sRequestedClass) ||
353
            !$this->xValidator->validateMethod(self::$sRequestedMethod))
354
        {
355
            // Unable to find the requested object or method
356
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
357
                ['class' => self::$sRequestedClass, 'method' => self::$sRequestedMethod]));
358
        }
359
        // Find the requested method
360
        $xCallableObject = $this->xRegistry->getCallableObject(self::$sRequestedClass);
361
        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...
362
        {
363
            // Unable to find the requested object or method
364
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
365
                ['class' => self::$sRequestedClass, 'method' => self::$sRequestedMethod]));
366
        }
367
368
        // Call the requested method
369
        try
370
        {
371
            $xResponse = $xCallableObject->call(self::$sRequestedMethod, $this->xParameterReader->args());
372
            if(($xResponse))
373
            {
374
                $this->xResponseManager->append($xResponse);
375
            }
376
        }
377
        catch(ReflectionException $e)
378
        {
379
            // Unable to find the requested class
380
            throw new RequestException($this->xTranslator->trans('errors.objects.invalid',
381
                ['class' => self::$sRequestedClass, 'method' => self::$sRequestedMethod]));
382
        }
383
        return true;
384
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
385
}
386