Passed
Push — master ( b34d93...aea763 )
by Thierry
03:02 queued 24s
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
eloc 11
c 0
b 0
f 0
dl 0
loc 18
rs 9.9
cc 2
nc 2
nop 8

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