Passed
Push — master ( f79a4b...8eafb5 )
by Thierry
02:11
created

Response::addPluginCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 3
1
<?php
2
3
/**
4
 * Response.php - The Jaxon Response
5
 *
6
 * This class collects commands to be sent back to the browser in response to a jaxon request.
7
 * Commands are encoded and packaged in json format.
8
 *
9
 * Common commands include:
10
 * - <Response->assign>: Assign a value to an element's attribute.
11
 * - <Response->append>: Append a value on to an element's attribute.
12
 * - <Response->script>: Execute a portion of javascript code.
13
 * - <Response->call>: Execute an existing javascript function.
14
 * - <Response->alert>: Display an alert dialog to the user.
15
 *
16
 * Elements are identified by the value of the HTML id attribute.
17
 *
18
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
19
 * @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...
20
 * @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...
21
 * @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...
22
 * @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...
23
 * @author Thierry Feuzeu <[email protected]>
24
 * @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...
25
 * @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...
26
 * @copyright 2016 Thierry Feuzeu <[email protected]>
27
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
28
 * @link https://github.com/jaxon-php/jaxon-core
29
 */
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...
30
31
namespace Jaxon\Response;
32
33
use Jaxon\Plugin\Manager as PluginManager;
34
use Jaxon\Plugin\Response as ResponsePlugin;
35
use Jaxon\Response\Plugin\JQuery\Dom\Element;
36
use Jaxon\Utils\Config\Config;
37
use Jaxon\Utils\Translation\Translator;
38
use Jaxon\Exception\RequestException;
39
40
use function json_encode;
41
use function array_merge;
42
use function array_map;
43
use function array_pop;
44
use function is_integer;
45
use function trim;
46
use function is_array;
47
use function array_keys;
48
use function count;
49
50
class Response extends AbstractResponse
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class Response
Loading history...
51
{
52
    use Features\DomCommands;
53
    use Features\JsCommands;
54
    use Features\DomTreeCommands;
55
56
    /**
57
     * @var Config
58
     */
59
    protected $xConfig;
60
61
    /**
62
     * @var Translator
63
     */
64
    protected $xTranslator;
65
66
    /**
67
     * @var PluginManager
68
     */
69
    protected $xPluginManager;
70
71
    /**
72
     * The commands that will be sent to the browser in the response
73
     *
74
     * @var array
75
     */
76
    protected $aCommands = [];
77
78
    /**
79
     * A string, array or integer value to be returned to the caller when using 'synchronous' mode requests.
80
     * See <jaxon->setMode> for details.
81
     *
82
     * @var mixed
83
     */
84
    protected $xReturnValue;
85
86
    /**
87
     * The constructor
88
     *
89
     * @param Config $xConfig
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
90
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
91
     * @param PluginManager $xPluginManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
92
     */
93
    public function __construct(Config $xConfig, Translator $xTranslator, PluginManager $xPluginManager)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
94
    {
95
        $this->xConfig = $xConfig;
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...
96
        $this->xTranslator = $xTranslator;
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...
97
        $this->xPluginManager = $xPluginManager;
98
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
99
100
    /**
101
     * Create a new Jaxon response object
102
     *
103
     * @return Response
104
     */
105
    public function newResponse(): Response
106
    {
107
        return new Response($this->xConfig, $this->xTranslator, $this->xPluginManager);
108
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
109
110
    /**
111
     * Get the content type, which is always set to 'application/json'
112
     *
113
     * @return string
114
     */
115
    public function getContentType(): string
116
    {
117
        return 'application/json';
118
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
119
120
    /**
121
     * Provides access to registered response plugins
122
     *
123
     * Pass the plugin name as the first argument and the plugin object will be returned.
124
     *
125
     * @param string $sName    The name of the plugin
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
126
     *
127
     * @return null|ResponsePlugin
128
     */
129
    public function plugin(string $sName): ?ResponsePlugin
130
    {
131
        return $this->xPluginManager->getResponsePlugin($sName, $this);
132
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
133
134
    /**
135
     * Magic PHP function
136
     *
137
     * Used to permit plugins to be called as if they where native members of the Response instance.
138
     *
139
     * @param string $sPluginName    The name of the plugin
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
140
     *
141
     * @return null|ResponsePlugin
142
     */
143
    public function __get(string $sPluginName)
144
    {
145
        return $this->plugin($sPluginName);
146
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
147
148
    /**
149
     * Create a JQuery Element with a given selector, and link it to the current response.
150
     *
151
     * This is a shortcut to the JQuery plugin.
152
     *
153
     * @param string $sSelector    The jQuery selector
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
154
     * @param string $sContext    A context associated to the selector
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
155
     *
156
     * @return Element
157
     */
158
    public function jq(string $sSelector = '', string $sContext = ''): Element
159
    {
160
        return $this->plugin('jquery')->element($sSelector, $sContext);
0 ignored issues
show
Bug introduced by
The method element() does not exist on Jaxon\Plugin\Response. It seems like you code against a sub-type of Jaxon\Plugin\Response such as Jaxon\Response\Plugin\JQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

160
        return $this->plugin('jquery')->/** @scrutinizer ignore-call */ element($sSelector, $sContext);
Loading history...
161
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
162
163
    /**
164
     * Create a JQuery Element with a given selector, and link it to the current response.
165
     *
166
     * This is a shortcut to the JQuery plugin.
167
     *
168
     * @param string $sSelector    The jQuery selector
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
169
     * @param string $sContext    A context associated to the selector
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
170
     *
171
     * @return Element
172
     */
173
    public function jQuery(string $sSelector = '', string $sContext = ''): Element
174
    {
175
        return $this->jq($sSelector, $sContext);
176
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
177
178
    /**
179
     * Get the command data, merged with the last one if possible.
180
     *
181
     * @param array $aAttributes    Associative array of attributes that will describe the command
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
182
     * @param mixed $mData    The data to be associated with this command
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 4 found
Loading history...
183
     *
184
     * @return array
185
     */
186
    private function getCommandData(array $aAttributes, $mData): array
187
    {
188
        if(!$this->xConfig->getOption('core.response.merge') ||
189
            !in_array($aAttributes['cmd'], ['js', 'ap']) || ($count = count($this->aCommands)) === 0)
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
190
        {
191
            return [false, $mData];
192
        }
193
        $aLastCommand = $this->aCommands[$count - 1];
194
        if($aLastCommand['cmd'] !== $aAttributes['cmd'])
195
        {
196
            return [false, $mData];
197
        }
198
        if($aLastCommand['cmd'] === 'js')
199
        {
200
            if($this->xConfig->getOption('core.response.merge.js'))
201
            {
202
                return [true, $aLastCommand['data'] . '; ' . $mData];
203
            }
204
        }
205
        elseif($aLastCommand['cmd'] === 'ap')
206
        {
207
            if($this->xConfig->getOption('core.response.merge.ap') &&
208
                $aLastCommand['id'] === $aAttributes['id'] &&
209
                $aLastCommand['prop'] === $aAttributes['prop'])
210
            {
211
                return [true, $aLastCommand['data'] . ' ' . $mData];
212
            }
213
        }
214
        return [false, $mData];
215
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
216
217
    /**
218
     * Add a response command to the array of commands that will be sent to the browser
219
     *
220
     * @param array $aAttributes    Associative array of attributes that will describe the command
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
221
     * @param mixed $mData    The data to be associated with this command
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 4 found
Loading history...
222
     *
223
     * @return Response
224
     */
225
    public function addCommand(array $aAttributes, $mData): Response
226
    {
227
        $aAttributes = array_map(function($xAttribute) {
228
            return is_integer($xAttribute) ? $xAttribute : trim((string)$xAttribute, " \t");
229
        }, $aAttributes);
230
231
        [$bMerged, $mData] = $this->getCommandData($aAttributes, $mData);
232
        if($bMerged)
233
        {
234
            array_pop($this->aCommands);
235
        }
236
        $aAttributes['data'] = $mData;
237
        $this->aCommands[] = $aAttributes;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 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
239
        return $this;
240
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
241
242
    /**
243
     * Add a response command to the array of commands that will be sent to the browser
244
     *
245
     * @param string $sName    The command name
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
246
     * @param array $aAttributes    Associative array of attributes that will describe the command
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
247
     * @param mixed $mData    The data to be associated with this command
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
248
     * @param bool $bRemoveEmpty    If true, remove empty attributes
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
249
     *
250
     * @return Response
251
     */
252
    protected function _addCommand(string $sName, array $aAttributes, $mData, bool $bRemoveEmpty = false): Response
253
    {
254
        $mData = is_array($mData) ? array_map(function($sData) {
255
            return trim((string)$sData, " \t\n");
256
        }, $mData) : trim((string)$mData, " \t\n");
257
258
        if($bRemoveEmpty)
259
        {
260
            foreach(array_keys($aAttributes) as $sAttr)
261
            {
262
                if($aAttributes[$sAttr] === '')
263
                {
264
                    unset($aAttributes[$sAttr]);
265
                }
266
            }
267
        }
268
269
        $aAttributes['cmd'] = $sName;
270
        return $this->addCommand($aAttributes, $mData);
271
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
272
273
    /**
274
     * Clear all the commands already added to the response
275
     *
276
     * @return Response
277
     */
278
    public function clearCommands(): Response
279
    {
280
        $this->aCommands = [];
281
        return $this;
282
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
283
284
    /**
285
     * Add a response command that is generated by a plugin
286
     *
287
     * @param ResponsePlugin $xPlugin    The plugin object
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
288
     * @param array $aAttributes    The attributes for this response command
0 ignored issues
show
Coding Style introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
289
     * @param mixed $mData    The data to be sent with this command
0 ignored issues
show
Coding Style introduced by
Expected 7 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
290
     *
291
     * @return Response
292
     */
293
    public function addPluginCommand(ResponsePlugin $xPlugin, array $aAttributes, $mData): Response
294
    {
295
        $aAttributes['plg'] = $xPlugin->getName();
296
        return $this->addCommand($aAttributes, $mData);
297
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
298
299
    /**
300
     * Merge the response commands from the specified <Response> object with
301
     * the response commands in this <Response> object
302
     *
303
     * @param Response|array $mCommands    The <Response> object
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
304
     * @param bool $bBefore    Add the new commands to the beginning of the list
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 11 spaces after parameter type; 1 found
Loading history...
305
     *
306
     * @return void
307
     * @throws RequestException
308
     */
309
    public function appendResponse($mCommands, bool $bBefore = false)
310
    {
311
        if($mCommands instanceof Response)
312
        {
313
            $this->xReturnValue = $mCommands->xReturnValue;
314
            $aCommands = $mCommands->aCommands;
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...
315
        }
316
        elseif(is_array($mCommands))
0 ignored issues
show
introduced by
The condition is_array($mCommands) is always true.
Loading history...
317
        {
318
            $aCommands = $mCommands;
319
        }
320
        else
321
        {
322
            throw new RequestException($this->xTranslator->trans('errors.response.data.invalid'));
323
        }
324
325
        $this->aCommands = ($bBefore) ?
0 ignored issues
show
Coding Style introduced by
Expected 1 space after "?"; newline found
Loading history...
326
            array_merge($aCommands, $this->aCommands) :
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ":"; newline found
Loading history...
327
            array_merge($this->aCommands, $aCommands);
328
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
329
330
    /**
331
     * Get the commands in the response
332
     *
333
     * @return array
334
     */
335
    public function getCommands(): array
336
    {
337
        return $this->aCommands;
338
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
339
340
    /**
341
     * Get the number of commands in the response
342
     *
343
     * @return int
344
     */
345
    public function getCommandCount(): int
346
    {
347
        return count($this->aCommands);
348
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
349
350
    /**
351
     * Stores a value that will be passed back as part of the response
352
     *
353
     * When making synchronous requests, the calling javascript can obtain this value
354
     * immediately as the return value of the <jaxon.call> javascript function
355
     *
356
     * @param mixed $value    Any value
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
357
     *
358
     * @return Response
359
     */
360
    public function setReturnValue($value): Response
361
    {
362
        $this->xReturnValue = $value;
363
        return $this;
364
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
365
366
    /**
367
     * Return the output, generated from the commands added to the response, that will be sent to the browser
368
     *
369
     * @return string
370
     */
371
    public function getOutput(): string
372
    {
373
        $aResponse = [
374
            'jxnobj' => [],
375
        ];
376
        if(($this->xReturnValue))
377
        {
378
            $aResponse['jxnrv'] = $this->xReturnValue;
379
        }
380
        foreach($this->aCommands as $xCommand)
381
        {
382
            $aResponse['jxnobj'][] = $xCommand;
383
        }
384
385
        return json_encode($aResponse);
386
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
387
}
388