Passed
Push — master ( 27d45a...b61896 )
by Thierry
02:21
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\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