Passed
Push — master ( dc0218...f79a4b )
by Thierry
02:43
created

Response   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 326
Duplicated Lines 0 %

Importance

Changes 21
Bugs 1 Features 0
Metric Value
eloc 74
c 21
b 1
f 0
dl 0
loc 326
rs 9.44
wmc 37

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __get() 0 3 1
A clearCommands() 0 4 1
A jQuery() 0 3 1
A addCommand() 0 15 3
A jq() 0 3 1
A appendResponse() 0 19 4
A getCommandCount() 0 3 1
A addPluginCommand() 0 4 1
B getCommandData() 0 29 11
A setReturnValue() 0 4 1
A _addCommand() 0 19 5
A getContentType() 0 3 1
A getOutput() 0 15 3
A getCommands() 0 3 1
A plugin() 0 3 1
A __construct() 0 5 1
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 constructor
73
     *
74
     * @param Config $xConfig
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
75
     * @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...
76
     * @param PluginManager $xPluginManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
77
     */
78
    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...
79
    {
80
        $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...
81
        $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...
82
        $this->xPluginManager = $xPluginManager;
83
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
84
85
    /**
86
     * The commands that will be sent to the browser in the response
87
     *
88
     * @var array
89
     */
90
    protected $aCommands = [];
91
92
    /**
93
     * A string, array or integer value to be returned to the caller when using 'synchronous' mode requests.
94
     * See <jaxon->setMode> for details.
95
     *
96
     * @var mixed
97
     */
98
    protected $xReturnValue;
99
100
    /**
101
     * Get the content type, which is always set to 'application/json'
102
     *
103
     * @return string
104
     */
105
    public function getContentType(): string
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
106
    {
107
        return 'application/json';
108
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
109
110
    /**
111
     * Provides access to registered response plugins
112
     *
113
     * Pass the plugin name as the first argument and the plugin object will be returned.
114
     *
115
     * @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...
116
     *
117
     * @return null|ResponsePlugin
118
     */
119
    public function plugin(string $sName): ?ResponsePlugin
120
    {
121
        return $this->xPluginManager->getResponsePlugin($sName, $this);
122
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
123
124
    /**
125
     * Magic PHP function
126
     *
127
     * Used to permit plugins to be called as if they where native members of the Response instance.
128
     *
129
     * @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...
130
     *
131
     * @return null|ResponsePlugin
132
     */
133
    public function __get(string $sPluginName)
134
    {
135
        return $this->plugin($sPluginName);
136
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
137
138
    /**
139
     * Create a JQuery Element with a given selector, and link it to the current response.
140
     *
141
     * This is a shortcut to the JQuery plugin.
142
     *
143
     * @param string $sSelector    The jQuery selector
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
144
     * @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...
145
     *
146
     * @return Element
147
     */
148
    public function jq(string $sSelector = '', string $sContext = ''): Element
149
    {
150
        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

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