Completed
Push — master ( 2478d5...a209a4 )
by Thierry
01:46
created

src/Response/Response.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 a format that is acceptable to the response handler
8
 * from the javascript library running on the client side.
9
 *
10
 * Common commands include:
11
 * - <Response->assign>: Assign a value to an element's attribute.
12
 * - <Response->append>: Append a value on to an element's attribute.
13
 * - <Response->script>: Execute a portion of javascript code.
14
 * - <Response->call>: Execute an existing javascript function.
15
 * - <Response->alert>: Display an alert dialog to the user.
16
 *
17
 * Elements are identified by the value of the HTML id attribute.
18
 * If you do not see your updates occuring on the browser side, ensure that you are using
19
 * the correct id in your response.
20
 *
21
 * @package jaxon-core
22
 * @author Jared White
23
 * @author J. Max Wilson
24
 * @author Joseph Woolley
25
 * @author Steffen Konerow
26
 * @author Thierry Feuzeu <[email protected]>
27
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
28
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
29
 * @copyright 2016 Thierry Feuzeu <[email protected]>
30
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
31
 * @link https://github.com/jaxon-php/jaxon-core
32
 */
33
34
namespace Jaxon\Response;
35
36
use Jaxon\Jaxon;
37
38
class Response
39
{
40
    use \Jaxon\Utils\Traits\Config;
41
    use \Jaxon\Utils\Traits\Manager;
42
    use \Jaxon\Utils\Traits\Translator;
43
44
    /**
45
     * The response type
46
     *
47
     * @var string
48
     */
49
    public $sContentType = 'application/json';
50
51
    /**
52
     * The commands that will be sent to the browser in the response
53
     *
54
     * @var array
55
     */
56
    public $aCommands;
57
58
    /**
59
     * A string, array or integer value to be returned to the caller when using 'synchronous' mode requests.
60
     * See <jaxon->setMode> for details.
61
     *
62
     * @var mixed
63
     */
64
    private $returnValue;
65
66
    public function __construct()
67
    {
68
        $this->aCommands = [];
69
    }
70
71
    /**
72
     * Get the content type, which is always set to 'application/json'
73
     *
74
     * @return string
75
     */
76
    public function getContentType()
77
    {
78
        return $this->sContentType;
79
    }
80
81
    /**
82
     * Get the configured character encoding
83
     *
84
     * @return string
85
     */
86
    public function getCharacterEncoding()
87
    {
88
        return $this->getOption('core.encoding');
89
    }
90
91
    /**
92
     * Provides access to registered response plugins
93
     *
94
     * Pass the plugin name as the first argument and the plugin object will be returned.
95
     * You can then access the methods of the plugin directly.
96
     *
97
     * @param string        $sName                The name of the plugin
98
     *
99
     * @return null|\Jaxon\Plugin\Response
100
     */
101
    public function plugin($sName)
102
    {
103
        $xPlugin = $this->getPluginManager()->getResponsePlugin($sName);
104
        if(!$xPlugin)
105
        {
106
            return null;
107
        }
108
        $xPlugin->setResponse($this);
109
        return $xPlugin;
110
    }
111
112
    /**
113
     * Create a JQuery Element with a given selector, and link it to the current response.
114
     *
115
     * This is a shortcut to the JQuery plugin.
116
     *
117
     * @param string        $sSelector            The jQuery selector
118
     * @param string        $sContext             A context associated to the selector
119
     *
120
     * @return Jaxon\Response\Plugin\JQuery\Dom\Element
121
     */
122
    public function jq($sSelector = '', $sContext = '')
123
    {
124
        return $this->plugin('jquery')->element($sSelector, $sContext);
125
    }
126
127
    /**
128
     * Create a JQuery Element with a given selector, and link it to the current response.
129
     *
130
     * This is a shortcut to the JQuery plugin.
131
     *
132
     * @param string        $sSelector            The jQuery selector
133
     * @param string        $sContext             A context associated to the selector
134
     *
135
     * @return Jaxon\Response\Plugin\JQuery\Dom\Element
136
     */
137
    public function jQuery($sSelector = '', $sContext = '')
138
    {
139
        return $this->jq($sSelector, $sContext);
140
    }
141
142
    /**
143
     * Magic PHP function
144
     *
145
     * Used to permit plugins to be called as if they where native members of the Response instance.
146
     *
147
     * @param string        $sPluginName        The name of the plugin
148
     *
149
     * @return \Jaxon\Plugin\Response
150
     */
151
    public function __get($sPluginName)
152
    {
153
        return $this->plugin($sPluginName);
154
    }
155
156
    /**
157
     * Add a response command to the array of commands that will be sent to the browser
158
     *
159
     * @param array         $aAttributes        Associative array of attributes that will describe the command
160
     * @param mixed            $mData                The data to be associated with this command
161
     *
162
     * @return \Jaxon\Plugin\Response
163
     */
164
    public function addCommand($aAttributes, $mData)
165
    {
166
        /* merge commands if possible */
167
        if(in_array($aAttributes['cmd'], array('js', 'ap')))
168
        {
169
            if(($aLastCommand = array_pop($this->aCommands)))
170
            {
171
                if($aLastCommand['cmd'] == $aAttributes['cmd'])
172
                {
173
                    if($this->getOption('core.response.merge.js') &&
174
                            $aLastCommand['cmd'] == 'js')
175
                    {
176
                        $mData = $aLastCommand['data'].'; '.$mData;
177
                    }
178
                    elseif($this->getOption('core.response.merge.ap') &&
179
                            $aLastCommand['cmd'] == 'ap' &&
180
                            $aLastCommand['id'] == $aAttributes['id'] &&
181
                            $aLastCommand['prop'] == $aAttributes['prop'])
182
                    {
183
                        $mData = $aLastCommand['data'].' '.$mData;
184
                    }
185
                    else
186
                    {
187
                        $this->aCommands[] = $aLastCommand;
188
                    }
189
                }
190
                else
191
                {
192
                    $this->aCommands[] = $aLastCommand;
193
                }
194
            }
195
        }
196
        $aAttributes['data'] = $mData;
197
        $this->aCommands[] = $aAttributes;
198
199
        return $this;
200
    }
201
202
    /**
203
     * Clear all the commands already added to the response
204
     *
205
     * @return \Jaxon\Plugin\Response
206
     */
207
    public function clearCommands()
208
    {
209
        $this->aCommands[] = [];
210
211
        return $this;
212
    }
213
214
    /**
215
     * Add a response command that is generated by a plugin
216
     *
217
     * @param \Jaxon\Plugin\Plugin  $xPlugin            The plugin object
218
     * @param array                 $aAttributes        The attributes for this response command
219
     * @param mixed                 $mData              The data to be sent with this command
220
     *
221
     * @return \Jaxon\Plugin\Response
222
     */
223
    public function addPluginCommand($xPlugin, $aAttributes, $mData)
224
    {
225
        $aAttributes['plg'] = $xPlugin->getName();
226
        return $this->addCommand($aAttributes, $mData);
227
    }
228
229
    /**
230
     * Merge the response commands from the specified <Response> object with
231
     * the response commands in this <Response> object
232
     *
233
     * @param Response        $mCommands            The <Response> object
234
     * @param boolean        $bBefore            Add the new commands to the beginning of the list
235
     *
236
     * @return void
237
     */
238
    public function appendResponse($mCommands, $bBefore = false)
239
    {
240
        if($mCommands instanceof Response)
241
        {
242
            $this->returnValue = $mCommands->returnValue;
243
244 View Code Duplication
            if($bBefore)
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
            {
246
                $this->aCommands = array_merge($mCommands->aCommands, $this->aCommands);
247
            }
248
            else
249
            {
250
                $this->aCommands = array_merge($this->aCommands, $mCommands->aCommands);
251
            }
252
        }
253 View Code Duplication
        elseif(is_array($mCommands))
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
254
        {
255
            if($bBefore)
256
            {
257
                $this->aCommands = array_merge($mCommands, $this->aCommands);
258
            }
259
            else
260
            {
261
                $this->aCommands = array_merge($this->aCommands, $mCommands);
262
            }
263
        }
264
        else
265
        {
266
            if(!empty($mCommands))
267
            {
268
                throw new \Jaxon\Exception\Error($this->trans('errors.response.data.invalid'));
269
            }
270
        }
271
    }
272
273
    /**
274
     * Response command that prompts user with [ok] [cancel] style message box
275
     *
276
     * If the user clicks cancel, the specified number of response commands
277
     * following this one, will be skipped.
278
     *
279
     * @param integer        $iCmdNumber            The number of commands to skip upon cancel
280
     * @param string        $sMessage            The message to display to the user
281
     *
282
     * @return \Jaxon\Plugin\Response
283
     */
284
    public function confirmCommands($iCmdNumber, $sMessage)
285
    {
286
        return $this->addCommand(
287
            array(
288
                'cmd' => 'cc',
289
                'id' => $iCmdNumber
290
            ),
291
            trim((string)$sMessage, " \t\n")
292
        );
293
    }
294
295
    /**
296
     * Add a command to assign the specified value to the given element's attribute
297
     *
298
     * @param string        $sTarget              The id of the html element on the browser
299
     * @param string        $sAttribute           The attribute to be assigned
300
     * @param string        $sData                The value to be assigned to the attribute
301
     *
302
     * @return \Jaxon\Plugin\Response
303
     */
304 View Code Duplication
    public function assign($sTarget, $sAttribute, $sData)
305
    {
306
        return $this->addCommand(
307
            array(
308
                'cmd' => 'as',
309
                'id' => trim((string)$sTarget, " \t"),
310
                'prop' => trim((string)$sAttribute, " \t")
311
            ),
312
            trim((string)$sData, " \t\n")
313
        );
314
    }
315
316
    /**
317
     * Add a command to assign the specified HTML content to the given element
318
     *
319
     * This is a shortcut for assign() on the innerHTML attribute.
320
     *
321
     * @param string        $sTarget              The id of the html element on the browser
322
     * @param string        $sData                The value to be assigned to the attribute
323
     *
324
     * @return \Jaxon\Plugin\Response
325
     */
326
    public function html($sTarget, $sData)
327
    {
328
        return $this->assign($sTarget, 'innerHTML', $sData);
329
    }
330
331
    /**
332
     * Add a command to append the specified data to the given element's attribute
333
     *
334
     * @param string        $sTarget            The id of the element to be updated
335
     * @param string        $sAttribute            The name of the attribute to be appended to
336
     * @param string        $sData                The data to be appended to the attribute
337
     *
338
     * @return \Jaxon\Plugin\Response
339
     */
340 View Code Duplication
    public function append($sTarget, $sAttribute, $sData)
341
    {
342
        return $this->addCommand(
343
            array(
344
                'cmd' => 'ap',
345
                'id' => trim((string)$sTarget, " \t"),
346
                'prop' => trim((string)$sAttribute, " \t")
347
            ),
348
            trim((string)$sData, " \t\n")
349
        );
350
    }
351
352
    /**
353
     * Add a command to prepend the specified data to the given element's attribute
354
     *
355
     * @param string        $sTarget            The id of the element to be updated
356
     * @param string        $sAttribute            The name of the attribute to be prepended to
357
     * @param string        $sData                The value to be prepended to the attribute
358
     *
359
     * @return \Jaxon\Plugin\Response
360
     */
361 View Code Duplication
    public function prepend($sTarget, $sAttribute, $sData)
362
    {
363
        return $this->addCommand(
364
            array(
365
                'cmd' => 'pp',
366
                'id' => trim((string)$sTarget, " \t"),
367
                'prop' => trim((string)$sAttribute, " \t")
368
            ),
369
            trim((string)$sData, " \t\n")
370
        );
371
    }
372
373
    /**
374
     * Add a command to replace a specified value with another value within the given element's attribute
375
     *
376
     * @param string        $sTarget            The id of the element to update
377
     * @param string        $sAttribute            The attribute to be updated
378
     * @param string        $sSearch            The needle to search for
379
     * @param string        $sData                The data to use in place of the needle
380
     *
381
     * @return \Jaxon\Plugin\Response
382
     */
383
    public function replace($sTarget, $sAttribute, $sSearch, $sData)
384
    {
385
        return $this->addCommand(
386
            array(
387
                'cmd' => 'rp',
388
                'id' => trim((string)$sTarget, " \t"),
389
                'prop' => trim((string)$sAttribute, " \t")
390
            ),
391
            array(
392
                's' => trim((string)$sSearch, " \t\n"),
393
                'r' => trim((string)$sData, " \t\n")
394
            )
395
        );
396
    }
397
398
    /**
399
     * Add a command to clear the specified attribute of the given element
400
     *
401
     * @param string        $sTarget            The id of the element to be updated.
402
     * @param string        $sAttribute            The attribute to be cleared
403
     *
404
     * @return \Jaxon\Plugin\Response
405
     */
406
    public function clear($sTarget, $sAttribute)
407
    {
408
        return $this->assign(trim((string)$sTarget, " \t"), trim((string)$sAttribute, " \t"), '');
409
    }
410
411
    /**
412
     * Add a command to assign a value to a member of a javascript object (or element)
413
     * that is specified by the context member of the request
414
     *
415
     * The object is referenced using the 'this' keyword in the sAttribute parameter.
416
     *
417
     * @param string        $sAttribute            The attribute to be updated
418
     * @param string        $sData                The value to assign
419
     *
420
     * @return \Jaxon\Plugin\Response
421
     */
422 View Code Duplication
    public function contextAssign($sAttribute, $sData)
423
    {
424
        return $this->addCommand(
425
            array(
426
                'cmd' => 'c:as',
427
                'prop' => trim((string)$sAttribute, " \t")
428
            ),
429
            trim((string)$sData, " \t\n")
430
        );
431
    }
432
433
    /**
434
     * Add a command to append a value onto the specified member of the javascript
435
     * context object (or element) specified by the context member of the request
436
     *
437
     * The object is referenced using the 'this' keyword in the sAttribute parameter.
438
     *
439
     * @param string        $sAttribute            The attribute to be appended to
440
     * @param string        $sData                The value to append
441
     *
442
     * @return \Jaxon\Plugin\Response
443
     */
444 View Code Duplication
    public function contextAppend($sAttribute, $sData)
445
    {
446
        return $this->addCommand(
447
            array(
448
                'cmd' => 'c:ap',
449
                'prop' => trim((string)$sAttribute, " \t")
450
            ),
451
            trim((string)$sData, " \t\n")
452
        );
453
    }
454
455
    /**
456
     * Add a command to prepend the speicified data to the given member of the current
457
     * javascript object specified by context in the current request
458
     *
459
     * The object is access via the 'this' keyword in the sAttribute parameter.
460
     *
461
     * @param string        $sAttribute            The attribute to be updated
462
     * @param string        $sData                The value to be prepended
463
     *
464
     * @return \Jaxon\Plugin\Response
465
     */
466 View Code Duplication
    public function contextPrepend($sAttribute, $sData)
467
    {
468
        return $this->addCommand(
469
            array(
470
                'cmd' => 'c:pp',
471
                'prop' => trim((string)$sAttribute, " \t")
472
            ),
473
            trim((string)$sData, " \t\n")
474
        );
475
    }
476
477
    /**
478
     * Add a command to to clear the value of the attribute specified in the sAttribute parameter
479
     *
480
     * The member is access via the 'this' keyword and can be used to update a javascript
481
     * object specified by context in the request parameters.
482
     *
483
     * @param string        $sAttribute            The attribute to be cleared
484
     *
485
     * @return \Jaxon\Plugin\Response
486
     */
487
    public function contextClear($sAttribute)
488
    {
489
        return $this->contextAssign(trim((string)$sAttribute, " \t"), '');
490
    }
491
492
    /**
493
     * Add a command to display an alert message to the user
494
     *
495
     * @param string        $sMessage            The message to be displayed
496
     *
497
     * @return \Jaxon\Plugin\Response
498
     */
499
    public function alert($sMessage)
500
    {
501
        return $this->addCommand(
502
            array(
503
                'cmd' => 'al'
504
            ),
505
            trim((string)$sMessage, " \t\n")
506
        );
507
    }
508
509
    /**
510
     * Add a command to display a debug message to the user
511
     *
512
     * @param string        $sMessage            The message to be displayed
513
     *
514
     * @return \Jaxon\Plugin\Response
515
     */
516
    public function debug($sMessage)
517
    {
518
        return $this->addCommand(
519
            array(
520
                'cmd' => 'dbg'
521
            ),
522
            trim((string)$sMessage, " \t\n")
523
        );
524
    }
525
526
    /**
527
     * Add a command to ask the browser to navigate to the specified URL
528
     *
529
     * @param string        $sURL                The relative or fully qualified URL
530
     * @param integer        $iDelay                Number of seconds to delay before the redirect occurs
531
     *
532
     * @return \Jaxon\Plugin\Response
533
     */
534
    public function redirect($sURL, $iDelay=0)
535
    {
536
        // we need to parse the query part so that the values are rawurlencode()'ed
537
        // can't just use parse_url() cos we could be dealing with a relative URL which
538
        // parse_url() can't deal with.
539
        $queryStart = strpos($sURL, '?', strrpos($sURL, '/'));
540
        if($queryStart !== false)
541
        {
542
            $queryStart++;
543
            $queryEnd = strpos($sURL, '#', $queryStart);
544
            if($queryEnd === false)
545
                $queryEnd = strlen($sURL);
546
            $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart);
547
            parse_str($queryPart, $queryParts);
548
            $newQueryPart = "";
549
            if($queryParts)
550
            {
551
                $first = true;
552
                foreach($queryParts as $key => $value)
553
                {
554
                    if($first)
555
                        $first = false;
556
                    else
557
                        $newQueryPart .= '&';
558
                    $newQueryPart .= rawurlencode($key).'='.rawurlencode($value);
559
                }
560
            } elseif($_SERVER['QUERY_STRING']) {
561
                    //couldn't break up the query, but there's one there
562
                    //possibly "http://url/page.html?query1234" type of query?
563
                    //just encode it and hope it works
564
                    $newQueryPart = rawurlencode($_SERVER['QUERY_STRING']);
565
                }
566
            $sURL = str_replace($queryPart, $newQueryPart, $sURL);
567
        }
568
        if($iDelay)
569
            $this->script('window.setTimeout("window.location = \'' . $sURL . '\';",' . ($iDelay*1000) . ');');
570
        else
571
            $this->script('window.location = "' . $sURL . '";');
572
        return $this;
573
    }
574
575
    /**
576
     * Add a command to execute a portion of javascript on the browser
577
     *
578
     * The script runs in it's own context, so variables declared locally, using the 'var' keyword,
579
     * will no longer be available after the call.
580
     * To construct a variable that will be accessable globally, even after the script has executed,
581
     * leave off the 'var' keyword.
582
     *
583
     * @param string        $sJS                The script to execute
584
     *
585
     * @return \Jaxon\Plugin\Response
586
     */
587
    public function script($sJS)
588
    {
589
        return $this->addCommand(
590
            array(
591
                'cmd' => 'js'
592
            ),
593
            trim((string)$sJS, " \t\n")
594
        );
595
    }
596
597
    /**
598
     * Add a command to call the specified javascript function with the given (optional) parameters
599
     *
600
     * @param string        $sFunc                The name of the function to call
601
     *
602
     * @return \Jaxon\Plugin\Response
603
     */
604
    public function call($sFunc)
605
    {
606
        $aArgs = func_get_args();
607
        array_shift($aArgs);
608
        return $this->addCommand(
609
            array(
610
                'cmd' => 'jc',
611
                'func' => $sFunc
612
            ),
613
            $aArgs
614
        );
615
    }
616
617
    /**
618
     * Add a command to remove an element from the document
619
     *
620
     * @param string        $sTarget            The id of the element to be removed
621
     *
622
     * @return \Jaxon\Plugin\Response
623
     */
624
    public function remove($sTarget)
625
    {
626
        return $this->addCommand(
627
            array(
628
                'cmd' => 'rm',
629
                'id' => trim((string)$sTarget, " \t")
630
            ),
631
            ''
632
        );
633
    }
634
635
    /**
636
     * Add a command to create a new element on the browser
637
     *
638
     * @param string        $sParent            The id of the parent element
639
     * @param string        $sTag                The tag name to be used for the new element
640
     * @param string        $sId                The id to assign to the new element
641
     *
642
     * @return \Jaxon\Plugin\Response
643
     */
644
    public function create($sParent, $sTag, $sId)
645
    {
646
        return $this->addCommand(
647
            array(
648
                'cmd' => 'ce',
649
                'id' => trim((string)$sParent, " \t"),
650
                'prop' => trim((string)$sId, " \t")
651
            ),
652
            trim((string)$sTag, " \t\n")
653
        );
654
    }
655
656
    /**
657
     * Add a command to insert a new element just prior to the specified element
658
     *
659
     * @param string        $sBefore            The id of the element used as a reference point for the insertion
660
     * @param string        $sTag               The tag name to be used for the new element
661
     * @param string        $sId                The id to assign to the new element
662
     *
663
     * @return \Jaxon\Plugin\Response
664
     */
665
    public function insert($sBefore, $sTag, $sId)
666
    {
667
        return $this->addCommand(
668
            array(
669
                'cmd' => 'ie',
670
                'id' => trim((string)$sBefore, " \t"),
671
                'prop' => trim((string)$sId, " \t")
672
            ),
673
            trim((string)$sTag, " \t\n")
674
        );
675
    }
676
677
    /**
678
     * Add a command to insert a new element after the specified
679
     *
680
     * @param string        $sAfter             The id of the element used as a reference point for the insertion
681
     * @param string        $sTag               The tag name to be used for the new element
682
     * @param string        $sId                The id to assign to the new element
683
     *
684
     * @return \Jaxon\Plugin\Response
685
     */
686
    public function insertAfter($sAfter, $sTag, $sId)
687
    {
688
        return $this->addCommand(
689
            array(
690
                'cmd' => 'ia',
691
                'id' => trim((string)$sAfter, " \t"),
692
                'prop' => trim((string)$sId, " \t")
693
            ),
694
            trim((string)$sTag, " \t\n")
695
        );
696
    }
697
698
    /**
699
     * Add a command to create an input element on the browser
700
     *
701
     * @param string        $sParent            The id of the parent element
702
     * @param string        $sType                The type of the new input element
703
     * @param string        $sName                The name of the new input element
704
     * @param string        $sId                The id of the new element
705
     *
706
     * @return \Jaxon\Plugin\Response
707
     */
708 View Code Duplication
    public function createInput($sParent, $sType, $sName, $sId)
709
    {
710
        return $this->addCommand(
711
            array(
712
                'cmd' => 'ci',
713
                'id' => trim((string)$sParent, " \t"),
714
                'prop' => trim((string)$sId, " \t"),
715
                'type' => trim((string)$sType, " \t")
716
            ),
717
            trim((string)$sName, " \t\n")
718
        );
719
    }
720
721
    /**
722
     * Add a command to insert a new input element preceding the specified element
723
     *
724
     * @param string        $sBefore            The id of the element to be used as the reference point for the insertion
725
     * @param string        $sType                The type of the new input element
726
     * @param string        $sName                The name of the new input element
727
     * @param string        $sId                The id of the new element
728
     *
729
     * @return \Jaxon\Plugin\Response
730
     */
731 View Code Duplication
    public function insertInput($sBefore, $sType, $sName, $sId)
732
    {
733
        return $this->addCommand(
734
            array(
735
                'cmd' => 'ii',
736
                'id' => trim((string)$sBefore, " \t"),
737
                'prop' => trim((string)$sId, " \t"),
738
                'type' => trim((string)$sType, " \t")
739
            ),
740
            trim((string)$sName, " \t\n")
741
        );
742
    }
743
744
    /**
745
     * Add a command to insert a new input element after the specified element
746
     *
747
     * @param string        $sAfter                The id of the element to be used as the reference point for the insertion
748
     * @param string        $sType                The type of the new input element
749
     * @param string        $sName                The name of the new input element
750
     * @param string        $sId                The id of the new element
751
     *
752
     * @return \Jaxon\Plugin\Response
753
     */
754 View Code Duplication
    public function insertInputAfter($sAfter, $sType, $sName, $sId)
755
    {
756
        return $this->addCommand(
757
            array(
758
                'cmd' => 'iia',
759
                'id' => trim((string)$sAfter, " \t"),
760
                'prop' => trim((string)$sId, " \t"),
761
                'type' => trim((string)$sType, " \t")
762
            ),
763
            trim((string)$sName, " \t\n")
764
        );
765
    }
766
767
    /**
768
     * Add a command to set an event handler on the browser
769
     *
770
     * @param string        $sTarget            The id of the element that contains the event
771
     * @param string        $sEvent                The name of the event
772
     * @param string        $sScript            The javascript to execute when the event is fired
773
     *
774
     * @return \Jaxon\Plugin\Response
775
     */
776 View Code Duplication
    public function setEvent($sTarget, $sEvent, $sScript)
777
    {
778
        return $this->addCommand(
779
            array(
780
                'cmd' => 'ev',
781
                'id' => trim((string)$sTarget, " \t"),
782
                'prop' => trim((string)$sEvent, " \t")
783
            ),
784
            trim((string)$sScript, " \t\n")
785
        );
786
    }
787
788
    /**
789
     * Add a command to set a click handler on the browser
790
     *
791
     * @param string        $sTarget            The id of the element that contains the event
792
     * @param string        $sScript            The javascript to execute when the event is fired
793
     *
794
     * @return \Jaxon\Plugin\Response
795
     */
796
    public function onClick($sTarget, $sScript)
797
    {
798
        return $this->setEvent($sTarget, 'onclick', $sScript);
799
    }
800
801
    /**
802
     * Add a command to install an event handler on the specified element
803
     *
804
     * You can add more than one event handler to an element's event using this method.
805
     *
806
     * @param string        $sTarget             The id of the element
807
     * @param string        $sEvent              The name of the event
808
     * @param string        $sHandler            The name of the javascript function to call when the event is fired
809
     *
810
     * @return \Jaxon\Plugin\Response
811
     */
812 View Code Duplication
    public function addHandler($sTarget, $sEvent, $sHandler)
813
    {
814
        return $this->addCommand(
815
            array(
816
                'cmd' => 'ah',
817
                'id' => trim((string)$sTarget, " \t"),
818
                'prop' => trim((string)$sEvent, " \t")
819
            ),
820
            trim((string)$sHandler, " \t\n")
821
        );
822
    }
823
824
    /**
825
     * Add a command to remove an event handler from an element
826
     *
827
     * @param string        $sTarget             The id of the element
828
     * @param string        $sEvent              The name of the event
829
     * @param string        $sHandler            The name of the javascript function called when the event is fired
830
     *
831
     * @return \Jaxon\Plugin\Response
832
     */
833 View Code Duplication
    public function removeHandler($sTarget, $sEvent, $sHandler)
834
    {
835
        return $this->addCommand(
836
            array(
837
                'cmd' => 'rh',
838
                'id' => trim((string)$sTarget, " \t"),
839
                'prop' => trim((string)$sEvent, " \t")
840
            ),
841
            trim((string)$sHandler, " \t\n")
842
        );
843
    }
844
845
    /**
846
     * Add a command to construct a javascript function on the browser
847
     *
848
     * @param string        $sFunction            The name of the function to construct
849
     * @param string        $sArgs                Comma separated list of parameter names
850
     * @param string        $sScript            The javascript code that will become the body of the function
851
     *
852
     * @return \Jaxon\Plugin\Response
853
     */
854 View Code Duplication
    public function setFunction($sFunction, $sArgs, $sScript)
855
    {
856
        return $this->addCommand(
857
            array(
858
                'cmd' => 'sf',
859
                'func' => trim((string)$sFunction, " \t"),
860
                'prop' => trim((string)$sArgs, " \t")
861
            ),
862
            trim((string)$sScript, " \t\n")
863
        );
864
    }
865
866
    /**
867
     * Add a command to construct a wrapper function around an existing javascript function on the browser
868
     *
869
     * @param string        $sFunction            The name of the existing function to wrap
870
     * @param string        $sArgs                The comma separated list of parameters for the function
871
     * @param array            $aScripts            An array of javascript code snippets that will be used to build
872
     *                                             the body of the function
873
     *                                             The first piece of code specified in the array will occur before
874
     *                                             the call to the original function, the second will occur after
875
     *                                             the original function is called.
876
     * @param string        $sReturnValueVar    The name of the variable that will retain the return value
877
     *                                             from the call to the original function
878
     *
879
     * @return \Jaxon\Plugin\Response
880
     */
881 View Code Duplication
    public function wrapFunction($sFunction, $sArgs, $aScripts, $sReturnValueVar)
882
    {
883
        return $this->addCommand(
884
            array(
885
                'cmd' => 'wpf',
886
                'func' => trim((string)$sFunction, " \t"),
887
                'prop' => trim((string)$sArgs, " \t"),
888
                'type' => trim((string)$sReturnValueVar, " \t")
889
            ),
890
            $aScripts
891
        );
892
    }
893
894
    /**
895
     * Add a command to load a javascript file on the browser
896
     *
897
     * @param string        $sFileName            The relative or fully qualified URI of the javascript file
898
     * @param string        $sType                Determines the script type. Defaults to 'text/javascript'
899
     *
900
     * @return \Jaxon\Plugin\Response
901
     */
902 View Code Duplication
    public function includeScript($sFileName, $sType = null, $sId = null)
903
    {
904
        $command = array('cmd'  =>  'in');
905
906
        if(($sType))
907
            $command['type'] = trim((string)$sType, " \t");
908
909
        if(($sId))
910
            $command['elm_id'] = trim((string)$sId, " \t");
911
912
        return $this->addCommand($command, trim((string)$sFileName, " \t"));
913
    }
914
915
    /**
916
     * Add a command to include a javascript file on the browser if it has not already been loaded
917
     *
918
     * @param string        $sFileName            The relative or fully qualified URI of the javascript file
919
     * @param string        $sType                Determines the script type. Defaults to 'text/javascript'
920
     *
921
     * @return \Jaxon\Plugin\Response
922
     */
923 View Code Duplication
    public function includeScriptOnce($sFileName, $sType = null, $sId = null)
924
    {
925
        $command = array('cmd' => 'ino');
926
927
        if(($sType))
928
            $command['type'] = trim((string)$sType, " \t");
929
930
        if(($sId))
931
            $command['elm_id'] = trim((string)$sId, " \t");
932
933
        return $this->addCommand($command, trim((string)$sFileName, " \t"));
934
    }
935
936
    /**
937
     * Add a command to remove a SCRIPT reference to a javascript file on the browser
938
     *
939
     * Optionally, you can call a javascript function just prior to the file being unloaded (for cleanup).
940
     *
941
     * @param string        $sFileName            The relative or fully qualified URI of the javascript file
942
     * @param string        $sUnload            Name of a javascript function to call prior to unlaoding the file
943
     *
944
     * @return \Jaxon\Plugin\Response
945
     */
946
    public function removeScript($sFileName, $sUnload = '')
947
    {
948
        return $this->addCommand(
949
            array(
950
                'cmd' => 'rjs',
951
                'unld' => trim((string)$sUnload, " \t")
952
            ),
953
            trim((string)$sFileName, " \t")
954
        );
955
    }
956
957
    /**
958
     * Add a command to include a LINK reference to the specified CSS file on the browser.
959
     *
960
     * This will cause the browser to load and apply the style sheet.
961
     *
962
     * @param string        $sFileName            The relative or fully qualified URI of the css file
963
     * @param string        $sMedia                The media type of the CSS file. Defaults to 'screen'
964
     *
965
     * @return \Jaxon\Plugin\Response
966
     */
967 View Code Duplication
    public function includeCSS($sFileName, $sMedia = null)
968
    {
969
        $command = array('cmd' => 'css');
970
971
        if(($sMedia))
972
            $command['media'] = trim((string)$sMedia, " \t");
973
974
        return $this->addCommand($command, trim((string)$sFileName, " \t"));
975
    }
976
977
    /**
978
     * Add a command to remove a LINK reference to a CSS file on the browser
979
     *
980
     * This causes the browser to unload the style sheet, effectively removing the style changes it caused.
981
     *
982
     * @param string        $sFileName            The relative or fully qualified URI of the css file
983
     *
984
     * @return \Jaxon\Plugin\Response
985
     */
986 View Code Duplication
    public function removeCSS($sFileName, $sMedia = null)
987
    {
988
        $command = array('cmd' => 'rcss');
989
990
        if(($sMedia))
991
            $command['media'] = trim((string)$sMedia, " \t");
992
993
        return $this->addCommand($command, trim((string)$sFileName, " \t"));
994
    }
995
996
    /**
997
     * Add a command to make Jaxon pause while the CSS files are loaded
998
     *
999
     * The browser is not typically a multi-threading application, with regards to javascript code.
1000
     * Therefore, the CSS files included or removed with <Response->includeCSS> and
1001
     * <Response->removeCSS> respectively, will not be loaded or removed until the browser regains
1002
     * control from the script.
1003
     * This command returns control back to the browser and pauses the execution of the response
1004
     * until the CSS files, included previously, are loaded.
1005
     *
1006
     * @param integer        $iTimeout            The number of 1/10ths of a second to pause before timing out
1007
     *                                             and continuing with the execution of the response commands
1008
     *
1009
     * @return \Jaxon\Plugin\Response
1010
     */
1011
    public function waitForCSS($iTimeout = 600)
1012
    {
1013
        $sData = "";
1014
        return $this->addCommand(
1015
            array(
1016
                'cmd' => 'wcss',
1017
                'prop' => $iTimeout
1018
            ),
1019
            $sData
1020
        );
1021
    }
1022
1023
    /**
1024
     * Add a command to make Jaxon to delay execution of the response commands until a specified condition is met
1025
     *
1026
     * Note, this returns control to the browser, so that other script operations can execute.
1027
     * Jaxon will continue to monitor the specified condition and, when it evaulates to true,
1028
     * will continue processing response commands.
1029
     *
1030
     * @param string        $script                A piece of javascript code that evaulates to true or false
1031
     * @param integer        $tenths                The number of 1/10ths of a second to wait before timing out
1032
     *                                             and continuing with the execution of the response commands.
1033
     *
1034
     * @return \Jaxon\Plugin\Response
1035
     */
1036
    public function waitFor($script, $tenths)
1037
    {
1038
        return $this->addCommand(
1039
            array(
1040
                'cmd' => 'wf',
1041
                'prop' => $tenths
1042
            ),
1043
            trim((string)$script, " \t\n")
1044
        );
1045
    }
1046
1047
    /**
1048
     * Add a command to make Jaxon to pause execution of the response commands,
1049
     * returning control to the browser so it can perform other commands asynchronously.
1050
     *
1051
     * After the specified delay, Jaxon will continue execution of the response commands.
1052
     *
1053
     * @param integer        $tenths                The number of 1/10ths of a second to sleep
1054
     *
1055
     * @return \Jaxon\Plugin\Response
1056
     */
1057
    public function sleep($tenths)
1058
    {
1059
        return $this->addCommand(
1060
            array(
1061
                'cmd' => 's',
1062
                'prop' => $tenths
1063
            ),
1064
            ''
1065
        );
1066
    }
1067
1068
    /**
1069
     * Add a command to start a DOM response
1070
     *
1071
     * @return \Jaxon\Plugin\Response
1072
     */
1073
    public function domStartResponse()
1074
    {
1075
        $this->script('jxnElm = []');
1076
    }
1077
1078
    /**
1079
     * Add a command to create a DOM element
1080
     *
1081
     * @param string        $variable            The DOM element name (id or class)
1082
     * @param string        $tag                The HTML tag of the new DOM element
1083
     *
1084
     * @return \Jaxon\Plugin\Response
1085
     */
1086
    public function domCreateElement($variable, $tag)
1087
    {
1088
        return $this->addCommand(
1089
            array(
1090
                'cmd' => 'DCE',
1091
                'tgt' => $variable
1092
            ),
1093
            $tag
1094
        );
1095
    }
1096
1097
    /**
1098
     * Add a command to set an attribute on a DOM element
1099
     *
1100
     * @param string        $variable            The DOM element name (id or class)
1101
     * @param string        $key                The name of the attribute
1102
     * @param string        $value                The value of the attribute
1103
     *
1104
     * @return \Jaxon\Plugin\Response
1105
     */
1106
    public function domSetAttribute($variable, $key, $value)
1107
    {
1108
        return $this->addCommand(
1109
            array(
1110
                'cmd' => 'DSA',
1111
                'tgt' => $variable,
1112
                'key' => $key
1113
            ),
1114
            $value
1115
        );
1116
    }
1117
1118
    /**
1119
     * Add a command to remove children from a DOM element
1120
     *
1121
     * @param string        $parent                The DOM parent element
1122
     * @param string        $skip                The ??
1123
     * @param string        $remove                The ??
1124
     *
1125
     * @return \Jaxon\Plugin\Response
1126
     */
1127
    public function domRemoveChildren($parent, $skip = null, $remove = null)
1128
    {
1129
        $command = array('cmd' => 'DRC');
1130
1131
        if(($skip))
1132
            $command['skip'] = $skip;
1133
1134
        if(($remove))
1135
            $command['remove'] = $remove;
1136
1137
        return $this->addCommand($command, $parent);
1138
    }
1139
1140
    /**
1141
     * Add a command to append a child to a DOM element
1142
     *
1143
     * @param string        $parent                The DOM parent element
1144
     * @param string        $variable            The DOM element name (id or class)
1145
     *
1146
     * @return \Jaxon\Plugin\Response
1147
     */
1148
    public function domAppendChild($parent, $variable)
1149
    {
1150
        return $this->addCommand(
1151
            array(
1152
                'cmd' => 'DAC',
1153
                'par' => $parent
1154
            ),
1155
            $variable
1156
        );
1157
    }
1158
1159
    /**
1160
     * Add a command to insert a DOM element before another
1161
     *
1162
     * @param string        $target                The DOM target element
1163
     * @param string        $variable            The DOM element name (id or class)
1164
     *
1165
     * @return \Jaxon\Plugin\Response
1166
     */
1167
    public function domInsertBefore($target, $variable)
1168
    {
1169
        return $this->addCommand(
1170
            array(
1171
                'cmd' => 'DIB',
1172
                'tgt' => $target
1173
            ),
1174
            $variable
1175
        );
1176
    }
1177
1178
    /**
1179
     * Add a command to insert a DOM element after another
1180
     *
1181
     * @param string        $target                The DOM target element
1182
     * @param string        $variable            The DOM element name (id or class)
1183
     *
1184
     * @return \Jaxon\Plugin\Response
1185
     */
1186
    public function domInsertAfter($target, $variable)
1187
    {
1188
        return $this->addCommand(
1189
            array(
1190
                'cmd' => 'DIA',
1191
                'tgt' => $target
1192
            ),
1193
            $variable
1194
        );
1195
    }
1196
1197
    /**
1198
     * Add a command to append a text to a DOM element
1199
     *
1200
     * @param string        $parent                The DOM parent element
1201
     * @param string        $text                The HTML text to append
1202
     *
1203
     * @return \Jaxon\Plugin\Response
1204
     */
1205
    public function domAppendText($parent, $text)
1206
    {
1207
        return $this->addCommand(
1208
            array(
1209
                'cmd' => 'DAT',
1210
                'par' => $parent
1211
            ),
1212
            $text
1213
        );
1214
    }
1215
1216
    /**
1217
     * Add a command to end a DOM response
1218
     *
1219
     * @return \Jaxon\Plugin\Response
1220
     */
1221
    public function domEndResponse()
1222
    {
1223
        $this->script('jxnElm = []');
1224
    }
1225
1226
    /**
1227
     * Get the number of commands in the response
1228
     *
1229
     * @return integer
1230
     */
1231
    public function getCommandCount()
1232
    {
1233
        return count($this->aCommands);
1234
    }
1235
1236
    /**
1237
     * Stores a value that will be passed back as part of the response
1238
     *
1239
     * When making synchronous requests, the calling javascript can obtain this value
1240
     * immediately as the return value of the <jaxon.call> javascript function
1241
     *
1242
     * @param mixed        $value                Any value
1243
     *
1244
     * @return \Jaxon\Plugin\Response
1245
     */
1246
    public function setReturnValue($value)
1247
    {
1248
        $this->returnValue = $value;
1249
        return $this;
1250
    }
1251
1252
    /**
1253
     * Used internally to generate the response headers
1254
     *
1255
     * @return void
1256
     */
1257
    public function sendHeaders()
1258
    {
1259
        if($this->getRequesthandler()->getRequestMethod() == Jaxon::METHOD_GET)
1260
        {
1261
            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1262
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
1263
            header("Cache-Control: no-cache, must-revalidate");
1264
            header("Pragma: no-cache");
1265
        }
1266
1267
        $sCharacterSet = '';
1268
        $sCharacterEncoding = trim($this->getOption('core.encoding'));
1269
        if(($sCharacterEncoding) && strlen($sCharacterEncoding) > 0)
1270
        {
1271
            $sCharacterSet = '; charset="' . trim($sCharacterEncoding) . '"';
1272
        }
1273
1274
        header('content-type: ' . $this->sContentType . ' ' . $sCharacterSet);
1275
    }
1276
1277
    /**
1278
     * Return the output, generated from the commands added to the response, that will be sent to the browser
1279
     *
1280
     * @return string
1281
     */
1282
    public function getOutput()
1283
    {
1284
        $response = [];
1285
1286
        if(($this->returnValue))
1287
        {
1288
            $response['jxnrv'] = $this->returnValue;
1289
        }
1290
        $response['jxnobj'] = [];
1291
1292
        foreach($this->aCommands as $xCommand)
1293
        {
1294
            $response['jxnobj'][] = $xCommand;
1295
        }
1296
1297
        return json_encode($response);
1298
    }
1299
1300
    /**
1301
     * Print the output, generated from the commands added to the response, that will be sent to the browser
1302
     *
1303
     * @return void
1304
     */
1305
    public function printOutput()
1306
    {
1307
        print $this->getOutput();
1308
    }
1309
}
1310