Completed
Push — master ( 34bc1a...41d5a5 )
by Thierry
02:48 queued 02:48
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
     * @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