1: <?php
2: /*
3: File: xajaxResponse.inc.php
4:
5: Contains the response class.
6:
7: Title: xajax response class
8:
9: Please see <copyright.inc.php> for a detailed description, copyright
10: and license information.
11: */
12:
13: /*
14: @package xajax
15: @version $Id: xajaxResponse.inc.php 361 2007-05-24 12:48:14Z calltoconstruct $
16: @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
17: @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson
18: @license http://www.xajaxproject.org/bsd_license.txt BSD License
19: */
20:
21: /*
22: Class: xajaxResponse
23:
24: Collect commands to be sent back to the browser in response to a xajax
25: request. Commands are encoded and packaged in a format that is acceptable
26: to the response handler from the javascript library running on the client
27: side.
28:
29: Common commands include:
30: - <xajaxResponse->assign>: Assign a value to an elements property.
31: - <xajaxResponse->append>: Append a value on to an elements property.
32: - <xajaxResponse->script>: Execute a portion of javascript code.
33: - <xajaxResponse->call>: Execute an existing javascript function.
34: - <xajaxResponse->alert>: Display an alert dialog to the user.
35:
36: Elements are identified by the value of the HTML id attribute. If you do
37: not see your updates occuring on the browser side, ensure that you are
38: using the correct id in your response.
39: */
40: class xajaxResponse
41: {
42: /*
43: Array: aCommands
44:
45: Stores the commands that will be sent to the browser in the response.
46: */
47: public $aCommands;
48:
49: /*
50: String: sCharacterEncoding
51:
52: The name of the encoding method you wish to use when dealing with
53: special characters. See <xajax->setEncoding> for more information.
54: */
55: private $sCharacterEncoding;
56:
57: /*
58: Boolean: bOutputEntities
59:
60: Convert special characters to the HTML equivellent. See also
61: <xajax->bOutputEntities> and <xajax->configure>.
62: */
63: private $bOutputEntities;
64:
65: /*
66: Mixed: returnValue
67:
68: A string, array or integer value to be returned to the caller when
69: using 'synchronous' mode requests. See <xajax->setMode> for details.
70: */
71: private $returnValue;
72:
73: /*
74: Object: objPluginManager
75:
76: A reference to the global plugin manager.
77: */
78: private $objPluginManager;
79:
80: // sorry but this config is static atm
81: private $sContentType = 'application/json'; //'text/xml';
82:
83: /*
84: Constructor: xajaxResponse
85:
86: Create and initialize a xajaxResponse object.
87: */
88: public function __construct()
89: {
90: //SkipDebug
91: if (0 < func_num_args()) {
92: $objLanguageManager = xajaxLanguageManager::getInstance();
93: trigger_error(
94: $objLanguageManager->getText('XJXRSP:EDERR:01')
95: , E_USER_ERROR
96: );
97: }
98: //EndSkipDebug
99:
100: $this->aCommands = array();
101:
102: $objResponseManager = xajaxResponseManager::getInstance();
103:
104: $this->sCharacterEncoding = $objResponseManager->getCharacterEncoding();
105: $this->bOutputEntities = $objResponseManager->getOutputEntities();
106: $this->setResponseType($objResponseManager->getConfiguration('responseType'));
107:
108: $this->objPluginManager = xajaxPluginManager::getInstance();
109: }
110:
111: function getResponseType()
112: {
113: return $this->sResponseType;
114: }
115:
116: function setResponseType($sResponseType) {
117:
118: if (NULL == $sResponseType) return;
119:
120: $this->sResponseType = $sResponseType ;
121:
122: if ('XML' == $sResponseType) {
123: $this->setContentType('text/xml');
124: }
125: elseif ('JSON' == $sResponseType) {
126: $this->setContentType('application/json');
127: }
128: }
129:
130:
131: /*
132: Function: setCharacterEncoding
133:
134: Overrides the default character encoding (or the one specified in the
135: constructor) to the specified character encoding.
136:
137: Parameters:
138:
139: sCharacterEncoding - (string): The encoding method to use for this response.
140:
141: See also, <xajaxResponse->xajaxResponse>()
142:
143: Returns:
144:
145: object - The xajaxResponse object.
146: */
147: public function setCharacterEncoding($sCharacterEncoding)
148: {
149: $this->sCharacterEncoding = $sCharacterEncoding;
150: return $this;
151: }
152:
153:
154: /*
155: Function: setOutputEntities
156:
157: Convert special characters to their HTML equivellent automatically
158: (only works if the mb_string extension is available).
159:
160: Parameters:
161:
162: bOption - (boolean): Convert special characters
163:
164: Returns:
165:
166: object - The xajaxResponse object.
167: */
168: public function setOutputEntities($bOutputEntities)
169: {
170: $this->bOutputEntities = (boolean)$bOutputEntities;
171: return $this;
172: }
173:
174: /*
175: Function: plugin
176:
177: Provides access to registered response plugins. If you are using PHP
178: 4 or 5, pass the plugin name as the first argument, the plugin method
179: name as the second argument and subsequent arguments (if any) to be
180: passed along to the plugin.
181:
182: Optionally, if you use PHP 5, you can pass just the plugin name as the
183: first argument and the plugin object will be returned. You can then
184: access the methods of the plugin directly.
185:
186: Parameters:
187:
188: sName - (string): Name of the plugin.
189: sFunction - (string, optional): The name of the method to call.
190: arg1...argn - (mixed, optional): Additional arguments to pass on to
191: the plugin function.
192:
193: Returns:
194:
195: object - The plugin specified by sName.
196: */
197: public function plugin()
198: {
199: $aArgs = func_get_args();
200: $nArgs = func_num_args();
201:
202: //SkipDebug
203: if (false == (0 < $nArgs)) {
204: $objLanguageManager = xajaxLanguageManager::getInstance();
205: trigger_error(
206: $objLanguageManager->getText('XJXRSP:MPERR:01')
207: , E_USER_ERROR
208: );
209: }
210: //EndSkipDebug
211:
212: $sName = array_shift($aArgs);
213:
214: $objPlugin = $this->objPluginManager->getResponsePlugin($sName);
215:
216: if (false === $objPlugin)
217: {
218: $bReturn = false;
219: return $bReturn;
220: }
221:
222: $objPlugin->setResponse($this);
223:
224: if (0 < count($aArgs))
225: {
226: $sMethod = array_shift($aArgs);
227:
228: $aFunction = array($objPlugin, $sMethod);
229: call_user_func_array($aFunction, $aArgs);
230: }
231:
232: return $objPlugin;
233: }
234:
235: /*
236: Function: __get
237:
238: Magic function for PHP 5. Used to permit plugins to be called as if they
239: where native members of the xajaxResponse instance.
240:
241: Parameters:
242:
243: sPluginName - (string): The name of the plugin.
244:
245: Returns:
246:
247: object - The plugin specified by sPluginName.
248: */
249: public function __get($sPluginName)
250: {
251: $objPlugin = $this->plugin($sPluginName);
252: return $objPlugin;
253: }
254:
255: /*
256: Function: confirmCommands
257:
258: Response command that prompts user with [ok] [cancel] style
259: message box. If the user clicks cancel, the specified
260: number of response commands following this one, will be
261: skipped.
262:
263: Parameters:
264:
265: iCmdNumber - (integer): The number of commands to skip upon cancel.
266: sMessage - (string): The message to display to the user.
267:
268: Returns:
269:
270: object : The xajaxResponse object.
271: */
272: public function confirmCommands($iCmdNumber, $sMessage)
273: {
274: return $this->addCommand(
275: array(
276: 'cmd'=>'cc',
277: 'id'=>$iCmdNumber
278: ),
279: $sMessage
280: );
281: }
282:
283: /*
284: Function: assign
285:
286: Response command indicating that the specified value should be
287: assigned to the given element's attribute.
288:
289: Parameters:
290:
291: sTarget - (string): The id of the html element on the browser.
292: sAttribute - (string): The property to be assigned.
293: sData - (string): The value to be assigned to the property.
294:
295: Returns:
296:
297: object : The <xajaxResponse> object.
298:
299: */
300: public function assign($sTarget,$sAttribute,$sData)
301: {
302: return $this->addCommand(
303: array(
304: 'cmd'=>'as',
305: 'id'=>$sTarget,
306: 'prop'=>$sAttribute
307: ),
308: $sData
309: );
310: }
311:
312: /*
313: Function: append
314:
315: Response command that indicates the specified data should be appended
316: to the given element's property.
317:
318: Parameters:
319:
320: sTarget - (string): The id of the element to be updated.
321: sAttribute - (string): The name of the property to be appended to.
322: sData - (string): The data to be appended to the property.
323:
324: Returns:
325:
326: object : The <xajaxResponse> object.
327: */
328: public function append($sTarget,$sAttribute,$sData)
329: {
330: return $this->addCommand(
331: array(
332: 'cmd'=>'ap',
333: 'id'=>$sTarget,
334: 'prop'=>$sAttribute
335: ),
336: $sData
337: );
338: }
339:
340: /*
341: Function: prepend
342:
343: Response command to prepend the specified value onto the given
344: element's property.
345:
346: Parameters:
347:
348: sTarget - (string): The id of the element to be updated.
349: sAttribute - (string): The property to be updated.
350: sData - (string): The value to be prepended.
351:
352: Returns:
353:
354: object : The <xajaxResponse> object.
355: */
356: public function prepend($sTarget,$sAttribute,$sData)
357: {
358: return $this->addCommand(
359: array(
360: 'cmd'=>'pp',
361: 'id'=>$sTarget,
362: 'prop'=>$sAttribute
363: ),
364: $sData
365: );
366: }
367:
368: /*
369: Function: replace
370:
371: Replace a specified value with another value within the given
372: element's property.
373:
374: Parameters:
375:
376: sTarget - (string): The id of the element to update.
377: sAttribute - (string): The property to be updated.
378: sSearch - (string): The needle to search for.
379: sData - (string): The data to use in place of the needle.
380: */
381: public function replace($sTarget,$sAttribute,$sSearch,$sData)
382: {
383: return $this->addCommand(
384: array(
385: 'cmd'=>'rp',
386: 'id'=>$sTarget,
387: 'prop'=>$sAttribute
388: ),
389: array(
390: 's' => $sSearch,
391: 'r' => $sData
392: )
393: );
394: }
395:
396: /*
397: Function: clear
398:
399: Response command used to clear the specified property of the
400: given element.
401:
402: Parameters:
403:
404: sTarget - (string): The id of the element to be updated.
405: sAttribute - (string): The property to be clared.
406:
407: Returns:
408:
409: object - The <xajaxResponse> object.
410: */
411: public function clear($sTarget,$sAttribute)
412: {
413: return $this->assign(
414: $sTarget,
415: $sAttribute,
416: ''
417: );
418: }
419:
420: /*
421: Function: contextAssign
422:
423: Response command used to assign a value to a member of a
424: javascript object (or element) that is specified by the context
425: member of the request. The object is referenced using the 'this' keyword
426: in the sAttribute parameter.
427:
428: Parameters:
429:
430: sAttribute - (string): The property to be updated.
431: sData - (string): The value to assign.
432:
433: Returns:
434:
435: object : The <xajaxResponse> object.
436: */
437: public function contextAssign($sAttribute, $sData)
438: {
439: return $this->addCommand(
440: array(
441: 'cmd'=>'c:as',
442: 'prop'=>$sAttribute
443: ),
444: $sData
445: );
446: }
447:
448: /*
449: Function: contextAppend
450:
451: Response command used to append a value onto the specified member
452: of the javascript context object (or element) specified by the context
453: member of the request. The object is referenced using the 'this' keyword
454: in the sAttribute parameter.
455:
456: Parameters:
457:
458: sAttribute - (string): The member to be appended to.
459: sData - (string): The value to append.
460:
461: Returns:
462:
463: object : The <xajaxResponse> object.
464: */
465: public function contextAppend($sAttribute, $sData)
466: {
467: return $this->addCommand(
468: array(
469: 'cmd'=>'c:ap',
470: 'prop'=>$sAttribute
471: ),
472: $sData
473: );
474: }
475:
476: /*
477: Function: contextPrepend
478:
479: Response command used to prepend the speicified data to the given
480: member of the current javascript object specified by context in the
481: current request. The object is access via the 'this' keyword in the
482: sAttribute parameter.
483:
484: Parameters:
485:
486: sAttribute - (string): The member to be updated.
487: sData - (string): The value to be prepended.
488:
489: Returns:
490:
491: object : The <xajaxResponse> object.
492: */
493: public function contextPrepend($sAttribute, $sData)
494: {
495: return $this->addCommand(
496: array(
497: 'cmd'=>'c:pp',
498: 'prop'=>$sAttribute
499: ),
500: $sData
501: );
502: }
503:
504: /*
505: Function: contextClear
506:
507: Response command used to clear the value of the property specified
508: in the sAttribute parameter. The member is access via the 'this'
509: keyword and can be used to update a javascript object specified
510: by context in the request parameters.
511:
512: Parameters:
513:
514: sAttribute - (string): The member to be cleared.
515:
516: Returns:
517:
518: object : The <xajaxResponse> object.
519: */
520: public function contextClear($sAttribute)
521: {
522: return $this->contextAssign(
523: $sAttribute,
524: ''
525: );
526: }
527:
528: /*
529: Function: alert
530:
531: Response command that is used to display an alert message to the user.
532:
533: Parameters:
534:
535: sMsg - (string): The message to be displayed.
536:
537: Returns:
538:
539: object : The <xajaxResponse> object.
540: */
541: public function alert($sMsg)
542: {
543: return $this->addCommand(
544: array(
545: 'cmd'=>'al'
546: ),
547: $sMsg
548: );
549: }
550:
551: public function debug($sMessage)
552: {
553: return $this->addCommand(
554: array(
555: 'cmd'=>'dbg'
556: ),
557: $sMessage
558: );
559: }
560:
561: /*
562: Function: redirect
563:
564: Response command that causes the browser to navigate to the specified
565: URL.
566:
567: Parameters:
568:
569: sURL - (string): The relative or fully qualified URL.
570: iDelay - (integer, optional): Number of seconds to delay before
571: the redirect occurs.
572:
573: Returns:
574:
575: object : The <xajaxResponse> object.
576: */
577: public function redirect($sURL, $iDelay=0)
578: {
579: //we need to parse the query part so that the values are rawurlencode()'ed
580: //can't just use parse_url() cos we could be dealing with a relative URL which
581: // parse_url() can't deal with.
582: $queryStart = strpos($sURL, '?', strrpos($sURL, '/'));
583: if ($queryStart !== FALSE)
584: {
585: $queryStart++;
586: $queryEnd = strpos($sURL, '#', $queryStart);
587: if ($queryEnd === FALSE)
588: $queryEnd = strlen($sURL);
589: $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart);
590: parse_str($queryPart, $queryParts);
591: $newQueryPart = "";
592: if ($queryParts)
593: {
594: $first = true;
595: foreach($queryParts as $key => $value)
596: {
597: if ($first)
598: $first = false;
599: else
600: $newQueryPart .= '&';
601: $newQueryPart .= rawurlencode($key).'='.rawurlencode($value);
602: }
603: } else if ($_SERVER['QUERY_STRING']) {
604: //couldn't break up the query, but there's one there
605: //possibly "http://url/page.html?query1234" type of query?
606: //just encode it and hope it works
607: $newQueryPart = rawurlencode($_SERVER['QUERY_STRING']);
608: }
609: $sURL = str_replace($queryPart, $newQueryPart, $sURL);
610: }
611: if ($iDelay)
612: $this->script(
613: 'window.setTimeout("window.location = \''
614: . $sURL
615: . '\';",'
616: . ($iDelay*1000)
617: . ');'
618: );
619: else
620: $this->script(
621: 'window.location = "'
622: . $sURL
623: . '";'
624: );
625: return $this;
626: }
627:
628: /*
629: Function: script
630:
631: Response command that is used to execute a portion of javascript on
632: the browser. The script runs in it's own context, so variables declared
633: locally, using the 'var' keyword, will no longer be available after the
634: call. To construct a variable that will be accessable globally, even
635: after the script has executed, leave off the 'var' keyword.
636:
637: Parameters:
638:
639: sJS - (string): The script to execute.
640:
641: Returns:
642:
643: object : The <xajaxResponse> object.
644: */
645: public function script($sJS)
646: {
647: return $this->addCommand(
648: array(
649: 'cmd'=>'js'
650: ),
651: $sJS
652: );
653: }
654:
655: /*
656: Function: call
657:
658: Response command that indicates that the specified javascript
659: function should be called with the given (optional) parameters.
660:
661: Parameters:
662:
663: arg1 - (string): The name of the function to call.
664: arg2 .. argn : arguments to be passed to the function.
665:
666: Returns:
667:
668: object : The <xajaxResponse> object.
669: */
670: public function call() {
671: $aArgs = func_get_args();
672: $sFunc = array_shift($aArgs);
673: return $this->addCommand(
674: array(
675: 'cmd'=>'jc',
676: 'func'=>$sFunc
677: ),
678: $aArgs
679: );
680: }
681:
682: /*
683: Function: remove
684:
685: Response command used to remove an element from the document.
686:
687: Parameters:
688:
689: sTarget - (string): The id of the element to be removed.
690:
691: Returns:
692:
693: object : The <xajaxResponse> object.
694: */
695: public function remove($sTarget)
696: {
697: return $this->addCommand(
698: array(
699: 'cmd'=>'rm',
700: 'id'=>$sTarget),
701: ''
702: );
703: }
704:
705: /*
706: Function: create
707:
708: Response command used to create a new element on the browser.
709:
710: Parameters:
711:
712: sParent - (string): The id of the parent element.
713: sTag - (string): The tag name to be used for the new element.
714: sId - (string): The id to assign to the new element.
715:
716:
717: Returns:
718:
719: object : The <xajaxResponse> object.
720: */
721:
722: public function create($sParent, $sTag, $sId)
723: {
724:
725:
726: return $this->addCommand(
727: array(
728: 'cmd'=>'ce',
729: 'id'=>$sParent,
730: 'prop'=>$sId
731: ),
732: $sTag
733: );
734: }
735:
736: /*
737: Function: insert
738:
739: Response command used to insert a new element just prior to the specified
740: element.
741:
742: Parameters:
743:
744: sBefore - (string): The element used as a reference point for the
745: insertion.
746: sTag - (string): The tag to be used for the new element.
747: sId - (string): The id to be used for the new element.
748:
749: Returns:
750:
751: object : The <xajaxResponse> object.
752: */
753: public function insert($sBefore, $sTag, $sId)
754: {
755: return $this->addCommand(
756: array(
757: 'cmd'=>'ie',
758: 'id'=>$sBefore,
759: 'prop'=>$sId
760: ),
761: $sTag
762: );
763: }
764:
765: /*
766: Function: insertAfter
767:
768: Response command used to insert a new element after the specified
769: one.
770:
771: Parameters:
772:
773: sAfter - (string): The id of the element that will be used as a reference
774: for the insertion.
775: sTag - (string): The tag name to be used for the new element.
776: sId - (string): The id to be used for the new element.
777:
778: Returns:
779:
780: object : The <xajaxResponse> object.
781: */
782: public function insertAfter($sAfter, $sTag, $sId)
783: {
784: return $this->addCommand(
785: array(
786: 'cmd'=>'ia',
787: 'id'=>$sAfter,
788: 'prop'=>$sId
789: ),
790: $sTag
791: );
792: }
793:
794: /*
795: Function: createInput
796:
797: Response command used to create an input element on the browser.
798:
799: Parameters:
800:
801: sParent - (string): The id of the parent element.
802: sType - (string): The type of the new input element.
803: sName - (string): The name of the new input element.
804: sId - (string): The id of the new element.
805:
806: Returns:
807:
808: object : The <xajaxResponse> object.
809: */
810: public function createInput($sParent, $sType, $sName, $sId)
811: {
812: return $this->addCommand(
813: array(
814: 'cmd'=>'ci',
815: 'id'=>$sParent,
816: 'prop'=>$sId,
817: 'type'=>$sType
818: ),
819: $sName
820: );
821: }
822:
823: /*
824: Function: insertInput
825:
826: Response command used to insert a new input element preceeding the
827: specified element.
828:
829: Parameters:
830:
831: sBefore - (string): The id of the element to be used as the reference
832: point for the insertion.
833: sType - (string): The type of the new input element.
834: sName - (string): The name of the new input element.
835: sId - (string): The id of the new input element.
836:
837: Returns:
838:
839: object : The <xajaxResponse> object.
840: */
841: public function insertInput($sBefore, $sType, $sName, $sId)
842: {
843: return $this->addCommand(
844: array(
845: 'cmd'=>'ii',
846: 'id'=>$sBefore,
847: 'prop'=>$sId,
848: 'type'=>$sType
849: ),
850: $sName
851: );
852: }
853:
854: /*
855: Function: insertInputAfter
856:
857: Response command used to insert a new input element after the
858: specified element.
859:
860: Parameters:
861:
862: sAfter - (string): The id of the element that is to be used
863: as the insertion point for the new element.
864: sType - (string): The type of the new input element.
865: sName - (string): The name of the new input element.
866: sId - (string): The id of the new input element.
867:
868: Returns:
869:
870: object : The <xajaxResponse> object.
871: */
872: public function insertInputAfter($sAfter, $sType, $sName, $sId)
873: {
874: return $this->addCommand(
875: array(
876: 'cmd'=>'iia',
877: 'id'=>$sAfter,
878: 'prop'=>$sId,
879: 'type'=>$sType
880: ),
881: $sName
882: );
883: }
884:
885: /*
886: Function: setEvent
887:
888: Response command used to set an event handler on the browser.
889:
890: Parameters:
891:
892: sTarget - (string): The id of the element that contains the event.
893: sEvent - (string): The name of the event.
894: sScript - (string): The javascript to execute when the event is fired.
895:
896: Returns:
897:
898: object : The <xajaxResponse> object.
899: */
900: public function setEvent($sTarget,$sEvent,$sScript)
901: {
902: return $this->addCommand(
903: array(
904: 'cmd'=>'ev',
905: 'id'=>$sTarget,
906: 'prop'=>$sEvent
907: ),
908: $sScript
909: );
910: }
911:
912:
913: /*
914: Function: addEvent
915:
916: Response command used to set an event handler on the browser.
917:
918: Parameters:
919:
920: sTarget - (string): The id of the element that contains the event.
921: sEvent - (string): The name of the event.
922: sScript - (string): The javascript to execute when the event is fired.
923:
924: Returns:
925:
926: object : The <xajaxResponse> object.
927:
928: Note:
929:
930: This function is depreciated and will be removed in a future version.
931: Use <setEvent> instead.
932: */
933: public function addEvent($sTarget,$sEvent,$sScript)
934: {
935: return $this->setEvent(
936: $sTarget,
937: $sEvent,
938: $sScript
939: );
940: }
941:
942: /*
943: Function: addHandler
944:
945: Response command used to install an event handler on the specified element.
946:
947: Parameters:
948:
949: sTarget - (string): The id of the element.
950: sEvent - (string): The name of the event to add the handler to.
951: sHandler - (string): The javascript function to call when the event is fired.
952:
953: You can add more than one event handler to an element's event using this method.
954:
955: Returns:
956:
957: object - The <xajaxResponse> object.
958: */
959: public function addHandler($sTarget,$sEvent,$sHandler)
960: {
961: return $this->addCommand(
962: array(
963: 'cmd'=>'ah',
964: 'id'=>$sTarget,
965: 'prop'=>$sEvent
966: ),
967: $sHandler
968: );
969: }
970:
971: /*
972: Function: removeHandler
973:
974: Response command used to remove an event handler from an element.
975:
976: Parameters:
977:
978: sTarget - (string): The id of the element.
979: sEvent - (string): The name of the event.
980: sHandler - (string): The javascript function that is called when the
981: event is fired.
982:
983: Returns:
984:
985: object : The <xajaxResponse> object.
986: */
987: public function removeHandler($sTarget,$sEvent,$sHandler)
988: {
989: return $this->addCommand(
990: array(
991: 'cmd'=>'rh',
992: 'id'=>$sTarget,
993: 'prop'=>$sEvent
994: ),
995: $sHandler);
996: }
997:
998: /*
999: Function: setFunction
1000:
1001: Response command used to construct a javascript function on the browser.
1002:
1003: Parameters:
1004:
1005: sFunction - (string): The name of the function to construct.
1006: sArgs - (string): Comma separated list of parameter names.
1007: sScript - (string): The javascript code that will become the body of the
1008: function.
1009:
1010: Returns:
1011:
1012: object : The <xajaxResponse> object.
1013: */
1014: public function setFunction($sFunction, $sArgs, $sScript)
1015: {
1016: return $this->addCommand(
1017: array(
1018: 'cmd'=>'sf',
1019: 'func'=>$sFunction,
1020: 'prop'=>$sArgs
1021: ),
1022: $sScript
1023: );
1024: }
1025:
1026: /*
1027: Function: wrapFunction
1028:
1029: Response command used to construct a wrapper function around
1030: and existing javascript function on the browser.
1031:
1032: Parameters:
1033:
1034: sFunction - (string): The name of the existing function to wrap.
1035: sArgs - (string): The comma separated list of parameters for the function.
1036: aScripts - (array): An array of javascript code snippets that will
1037: be used to build the body of the function. The first piece of code
1038: specified in the array will occur before the call to the original
1039: function, the second will occur after the original function is called.
1040: sReturnValueVariable - (string): The name of the variable that will
1041: retain the return value from the call to the original function.
1042:
1043: Returns:
1044:
1045: object : The <xajaxResponse> object.
1046: */
1047: public function wrapFunction($sFunction, $sArgs, $aScripts, $sReturnValueVariable)
1048: {
1049: return $this->addCommand(
1050: array(
1051: 'cmd'=>'wpf',
1052: 'func'=>$sFunction,
1053: 'prop'=>$sArgs,
1054: 'type'=>$sReturnValueVariable
1055: ),
1056: $aScripts
1057: );
1058: }
1059:
1060: /*
1061: Function: includeScript
1062:
1063: Response command used to load a javascript file on the browser.
1064:
1065: Parameters:
1066:
1067: sFileName - (string): The relative or fully qualified URI of the
1068: javascript file.
1069:
1070: sType - (string): Determines the script type . Defaults to 'text/javascript'.
1071:
1072:
1073: Returns:
1074:
1075: object : The <xajaxResponse> object.
1076: */
1077: public function includeScript($sFileName, $sType = null, $sId = null)
1078: {
1079: $command = array('cmd' => 'in');
1080:
1081: if (false === (null === $sType))
1082: $command['type'] = $sType;
1083:
1084: if (false === (null === $sId))
1085: $command['elm_id'] = $sId;
1086:
1087: return $this->addCommand(
1088: $command,
1089: $sFileName
1090: );
1091: }
1092:
1093: /*
1094: Function: includeScriptOnce
1095:
1096: Response command used to include a javascript file on the browser
1097: if it has not already been loaded.
1098:
1099: Parameters:
1100:
1101: sFileName - (string): The relative for fully qualified URI of the
1102: javascript file.
1103:
1104: sType - (string): Determines the script type . Defaults to 'text/javascript'.
1105:
1106: Returns:
1107:
1108: object : The <xajaxResponse> object.
1109: */
1110: public function includeScriptOnce($sFileName, $sType = null, $sId = null)
1111: {
1112: $command = array('cmd' => 'ino');
1113:
1114: if (false === (null === $sType))
1115: $command['type'] = $sType;
1116:
1117: if (false === (null === $sId))
1118: $command['elm_id'] = $sId;
1119:
1120: return $this->addCommand(
1121: $command,
1122: $sFileName
1123: );
1124: }
1125:
1126: /*
1127: Function: removeScript
1128:
1129: Response command used to remove a SCRIPT reference to a javascript
1130: file on the browser. Optionally, you can call a javascript function
1131: just prior to the file being unloaded (for cleanup).
1132:
1133: Parameters:
1134:
1135: sFileName - (string): The relative or fully qualified URI of the
1136: javascript file.
1137: sUnload - (string): Name of a javascript function to call prior
1138: to unlaoding the file.
1139:
1140: Returns:
1141:
1142: object : The <xajaxResponse> object.
1143: */
1144: public function removeScript($sFileName, $sUnload = '') {
1145: $this->addCommand(
1146: array(
1147: 'cmd'=>'rjs',
1148: 'unld'=>$sUnload
1149: ),
1150: $sFileName
1151: );
1152: return $this;
1153: }
1154:
1155: /*
1156: Function: includeCSS
1157:
1158: Response command used to include a LINK reference to
1159: the specified CSS file on the browser. This will cause the
1160: browser to load and apply the style sheet.
1161:
1162: Parameters:
1163:
1164: sFileName - (string): The relative or fully qualified URI of
1165: the css file.
1166:
1167: sMedia - (string): Determines the media type of the CSS file. Defaults to 'screen'.
1168:
1169: Returns:
1170:
1171: object : The <xajaxResponse> object.
1172: */
1173: public function includeCSS($sFileName, $sMedia = null)
1174: {
1175: $command = array('cmd' => 'css');
1176:
1177: if (false === (null === $sMedia))
1178: $command['media'] = $sMedia;
1179:
1180: return $this->addCommand(
1181: $command,
1182: $sFileName
1183: );
1184: }
1185:
1186: /*
1187: Function: removeCSS
1188:
1189: Response command used to remove a LINK reference to
1190: a CSS file on the browser. This causes the browser to
1191: unload the style sheet, effectively removing the style
1192: changes it caused.
1193:
1194: Parameters:
1195:
1196: sFileName - (string): The relative or fully qualified URI
1197: of the css file.
1198:
1199: Returns:
1200:
1201: object : The <xajaxResponse> object.
1202: */
1203: public function removeCSS($sFileName, $sMedia = null)
1204: {
1205: $command = array('cmd'=>'rcss');
1206:
1207: if (false === (null === $sMedia))
1208: $command['media'] = $sMedia;
1209:
1210: return $this->addCommand(
1211: $command,
1212: $sFileName
1213: );
1214: }
1215:
1216: /*
1217: Function: waitForCSS
1218:
1219: Response command instructing xajax to pause while the CSS
1220: files are loaded. The browser is not typically a multi-threading
1221: application, with regards to javascript code. Therefore, the
1222: CSS files included or removed with <xajaxResponse->includeCSS> and
1223: <xajaxResponse->removeCSS> respectively, will not be loaded or
1224: removed until the browser regains control from the script. This
1225: command returns control back to the browser and pauses the execution
1226: of the response until the CSS files, included previously, are
1227: loaded.
1228:
1229: Parameters:
1230:
1231: iTimeout - (integer): The number of 1/10ths of a second to pause
1232: before timing out and continuing with the execution of the
1233: response commands.
1234:
1235: Returns:
1236:
1237: object : The <xajaxResponse> object.
1238: */
1239: public function waitForCSS($iTimeout = 600) {
1240: $sData = "";
1241: $this->addCommand(
1242: array(
1243: 'cmd'=>'wcss',
1244: 'prop'=>$iTimeout
1245: ),
1246: $sData
1247: );
1248: return $this;
1249: }
1250:
1251: /*
1252: Function: waitFor
1253:
1254: Response command instructing xajax to delay execution of the response
1255: commands until a specified condition is met. Note, this returns control
1256: to the browser, so that other script operations can execute. xajax
1257: will continue to monitor the specified condition and, when it evaulates
1258: to true, will continue processing response commands.
1259:
1260: Parameters:
1261:
1262: script - (string): A piece of javascript code that evaulates to true
1263: or false.
1264: tenths - (integer): The number of 1/10ths of a second to wait before
1265: timing out and continuing with the execution of the response
1266: commands.
1267:
1268: Returns:
1269:
1270: object : The <xajaxResponse> object.
1271: */
1272: public function waitFor($script, $tenths) {
1273: return $this->addCommand(
1274: array(
1275: 'cmd'=>'wf',
1276: 'prop'=>$tenths
1277: ),
1278: $script
1279: );
1280: }
1281:
1282: /*
1283: Function: sleep
1284:
1285: Response command which instructs xajax to pause execution
1286: of the response commands, returning control to the browser
1287: so it can perform other commands asynchronously. After
1288: the specified delay, xajax will continue execution of the
1289: response commands.
1290:
1291: Parameters:
1292:
1293: tenths - (integer): The number of 1/10ths of a second to
1294: sleep.
1295:
1296: Returns:
1297:
1298: object : The <xajaxResponse> object.
1299: */
1300: public function sleep($tenths) {
1301: $this->addCommand(
1302: array(
1303: 'cmd'=>'s',
1304: 'prop'=>$tenths
1305: ),
1306: ''
1307: );
1308: return $this;
1309: }
1310:
1311: public function domStartResponse()
1312: {
1313: $this->script('xjxElm = []');
1314: }
1315:
1316: public function domCreateElement($variable, $tag)
1317: {
1318: return $this->addCommand(
1319: array(
1320: 'cmd' => 'DCE',
1321: 'tgt' => $variable
1322: ),
1323: $tag
1324: );
1325: }
1326:
1327: public function domSetAttribute($variable, $key, $value)
1328: {
1329: return $this->addCommand(
1330: array(
1331: 'cmd' => 'DSA',
1332: 'tgt' => $variable,
1333: 'key' => $key
1334: ),
1335: $value
1336: );
1337: }
1338:
1339: public function domRemoveChildren($parent, $skip=null, $remove=null)
1340: {
1341: $command = array(
1342: 'cmd' => 'DRC'
1343: );
1344:
1345: if ($skip != null)
1346: $command['skip'] = $skip;
1347:
1348: if ($remove != null)
1349: $command['remove'] = $remove;
1350:
1351: return $this->addCommand(
1352: $command,
1353: $parent
1354: );
1355: }
1356:
1357: public function domAppendChild($parent, $variable)
1358: {
1359: return $this->addCommand(
1360: array(
1361: 'cmd' => 'DAC',
1362: 'par' => $parent
1363: ),
1364: $variable
1365: );
1366: }
1367:
1368: public function domInsertBefore($target, $variable)
1369: {
1370: return $this->addCommand(
1371: array(
1372: 'cmd' => 'DIB',
1373: 'tgt' => $target
1374: ),
1375: $variable
1376: );
1377: }
1378:
1379: public function domInsertAfter($target, $variable)
1380: {
1381: return $this->addCommand(
1382: array(
1383: 'cmd' => 'DIA',
1384: 'tgt' => $target
1385: ),
1386: $variable
1387: );
1388: }
1389:
1390: public function domAppendText($parent, $text)
1391: {
1392: return $this->addCommand(
1393: array(
1394: 'cmd' => 'DAT',
1395: 'par' => $parent
1396: ),
1397: $text
1398: );
1399: }
1400:
1401: public function domEndResponse()
1402: {
1403: $this->script('xjxElm = []');
1404: }
1405:
1406: /*
1407: Function: setReturnValue
1408:
1409: Stores a value that will be passed back as part of the response.
1410: When making synchronous requests, the calling javascript can
1411: obtain this value immediately as the return value of the
1412: <xajax.call> function.
1413:
1414: Parameters:
1415:
1416: value - (mixed): Any value.
1417:
1418: Returns:
1419:
1420: object : The <xajaxResponse> object.
1421: */
1422: public function setReturnValue($value) {
1423:
1424:
1425: $this->returnValue = 'JSON' == $this->sResponseType ? $value : $this->_encodeArray($value) ;
1426: return $this;
1427: }
1428:
1429: /*
1430: Function: getContentType
1431:
1432: Returns the current content type that will be used for the
1433: response packet. (typically: "text/xml")
1434:
1435: Returns:
1436:
1437: string : The content type.
1438: */
1439: public function getContentType()
1440: {
1441: return $this->sContentType;
1442: }
1443:
1444: public function setContentType($sContentType)
1445: {
1446: $this->sContentType = $sContentType ;
1447: }
1448:
1449: /*
1450: Function: getOutput
1451: */
1452: public function getOutput()
1453: {
1454: ob_start();
1455: if ('text/xml' == $this->getContentType() ) {
1456: $this->_printHeader_XML();
1457: $this->_printResponse_XML();
1458: } elseif ('application/json' == $this->getContentType() ) {
1459: $this->_printResponse_JSON();
1460:
1461: } else {
1462: //todo: trigger Error
1463: };
1464: return ob_get_clean();
1465: }
1466:
1467: /*
1468: Function: printOutput
1469:
1470: Prints the output, generated from the commands added to the response,
1471: that will be sent to the browser.
1472:
1473: Returns:
1474:
1475: string : The textual representation of the response commands.
1476: */
1477: public function printOutput()
1478: {
1479: $this->_sendHeaders();
1480: if ('text/xml' == $this->getContentType() ) {
1481: $this->_printHeader_XML();
1482: $this->_printResponse_XML();
1483: } elseif ('application/json' == $this->getContentType() ) {
1484: $this->_printResponse_JSON();
1485:
1486: } else {
1487: //todo: trigger Error
1488: }
1489: }
1490:
1491: /*
1492: Function: _sendHeaders
1493:
1494: Used internally to generate the response headers.
1495: */
1496: public function _sendHeaders()
1497: {
1498: $objArgumentManager = xajaxArgumentManager::getInstance();
1499: if (XAJAX_METHOD_GET == $objArgumentManager->getRequestMethod())
1500: {
1501: header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1502: header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
1503: header ("Cache-Control: no-cache, must-revalidate");
1504: header ("Pragma: no-cache");
1505: }
1506:
1507: $sCharacterSet = '';
1508: if ($this->sCharacterEncoding && 0 < strlen(trim($this->sCharacterEncoding))) {
1509: $sCharacterSet = '; charset="' . trim($this->sCharacterEncoding) . '"';
1510: }
1511:
1512: $sContentType = $this->getContentType();
1513:
1514: header('content-type: ' . $sContentType . ' ' . $sCharacterSet);
1515: }
1516:
1517: /*
1518: Function: getCommandCount
1519:
1520: Returns:
1521:
1522: integer : The number of commands in the response.
1523: */
1524: public function getCommandCount()
1525: {
1526: return count($this->aCommands);
1527: }
1528:
1529: /*
1530: Function: appendResponse
1531:
1532: Merges the response commands from the specified <xajaxResponse>
1533: object with the response commands in this <xajaxResponse> object.
1534:
1535: Parameters:
1536:
1537: mCommands - (object): <xajaxResponse> object.
1538: bBefore - (boolean): Add the new commands to the beginning
1539: of the list.
1540:
1541: */
1542: public function appendResponse($mCommands, $bBefore=false)
1543: {
1544: if ( $mCommands instanceof xajaxResponse ) {
1545: $this->returnValue = $mCommands->returnValue;
1546:
1547: if ($bBefore) {
1548: $this->aCommands = array_merge($mCommands->aCommands, $this->aCommands);
1549: }
1550: else {
1551: $this->aCommands = array_merge($this->aCommands, $mCommands->aCommands);
1552: }
1553: }
1554: else if (is_array($mCommands)) {
1555: if ($bBefore) {
1556: $this->aCommands = array_merge($mCommands, $this->aCommands);
1557: }
1558: else {
1559: $this->aCommands = array_merge($this->aCommands, $mCommands);
1560: }
1561: }
1562: else {
1563: //SkipDebug
1564: if (!empty($mCommands)) {
1565: $objLanguageManager = xajaxLanguageManager::getInstance();
1566: trigger_error(
1567: $objLanguageManager->getText('XJXRSP:LCERR:01')
1568: , E_USER_ERROR
1569: );
1570: }
1571: //EndSkipDebug
1572: }
1573: }
1574:
1575: /*
1576: Function: addPluginCommand
1577:
1578: Adds a response command that is generated by a plugin.
1579:
1580: Parameters:
1581:
1582: objPlugin - (object): A reference to a plugin object.
1583: aAttributes - (array): Array containing the attributes for this
1584: response command.
1585: mData - (mixed): The data to be sent with this command.
1586:
1587: Returns:
1588:
1589: object : The <xajaxResponse> object.
1590: */
1591: public function addPluginCommand($objPlugin, $aAttributes, $mData)
1592: {
1593: $aAttributes['plg'] = $objPlugin->getName();
1594: return $this->addCommand($aAttributes, $mData);
1595: }
1596:
1597: /*
1598: Function: addCommand
1599:
1600: Add a response command to the array of commands that will
1601: be sent to the browser.
1602:
1603: Parameters:
1604:
1605: aAttributes - (array): Associative array of attributes that
1606: will describe the command.
1607: mData - (mixed): The data to be associated with this command.
1608:
1609: Returns:
1610:
1611: object : The <xajaxResponse> command.
1612: */
1613: public function addCommand($aAttributes, $mData)
1614: {
1615: if ('text/xml' == $this->getContentType()) $mData = $this->_encodeArray($mData);;
1616:
1617: /* merge commands if possible */
1618: if ( in_array($aAttributes['cmd'],array('js','ap') ) )
1619: {
1620: if ($aLastCommand = array_pop($this->aCommands))
1621: {
1622: if ($aLastCommand['cmd'] == $aAttributes['cmd'])
1623: {
1624: if ('js' == $aLastCommand['cmd'])
1625: {
1626: $mData = $aLastCommand['data'].'; '.$mData;
1627: }
1628: elseif('ap' == $aLastCommand['cmd'] && $aLastCommand['id'] == $aAttributes['id'] && $aLastCommand['prop'] == $aAttributes['prop'])
1629: {
1630: $mData = $aLastCommand['data'].' '.$mData;
1631: }
1632: else
1633: {
1634: $this->aCommands[] = $aLastCommand;
1635: }
1636: } else {
1637: $this->aCommands[] = $aLastCommand;
1638: }
1639: }
1640: }
1641: $aAttributes['data'] = $mData;
1642: $this->aCommands[] = $aAttributes;
1643:
1644: return $this;
1645: }
1646:
1647:
1648: private function _printResponse_JSON()
1649: {
1650: $response = array();
1651:
1652: if (null !== $this->returnValue)
1653: $response['xjxrv'] = $this->returnValue;
1654:
1655: $response['xjxobj'] = array();
1656:
1657: foreach(array_keys($this->aCommands) as $sKey)
1658: $response['xjxobj'][] = $this->aCommands[$sKey];
1659:
1660: print json_encode($response);
1661: }
1662:
1663: /*
1664: Function: _printHeader_XML
1665:
1666: Used internally to print XML start tag.
1667: */
1668: private function _printHeader_XML()
1669: {
1670: echo '<';
1671: echo '?';
1672: echo 'xml version="1.0"';
1673:
1674: $sEncoding = trim($this->sCharacterEncoding);
1675: if ($this->sCharacterEncoding && 0 < strlen($sEncoding)) {
1676: echo ' encoding="';
1677: echo $sEncoding;
1678: echo '"';
1679: }
1680:
1681: echo ' ?';
1682: echo '>';
1683: }
1684:
1685: /*
1686: Function: _printResponse_XML
1687:
1688: Used internally to generate the command output.
1689: */
1690: public function _printResponse_XML()
1691: {
1692: echo '<';
1693: echo 'xjx>';
1694:
1695: if (null !== $this->returnValue)
1696: {
1697: echo '<';
1698: echo 'xjxrv>';
1699:
1700: $this->_printArray_XML($this->returnValue);
1701:
1702: echo '<';
1703: echo '/xjxrv>';
1704: }
1705:
1706: foreach(array_keys($this->aCommands) as $sKey)
1707: $this->_printCommand_XML($this->aCommands[$sKey]);
1708:
1709: echo '<';
1710: echo '/xjx>';
1711: }
1712:
1713: /*
1714: Function: _printCommand_XML
1715:
1716: Prints an XML representation of the command.
1717:
1718: Parameters:
1719:
1720: aAttributes - (array): Associative array of attributes for this
1721: command.
1722: */
1723: private function _printCommand_XML($aAttributes)
1724: {
1725: echo '<';
1726: echo 'cmd';
1727:
1728: $mData = '';
1729:
1730: foreach (array_keys($aAttributes) as $sKey) {
1731: if ($sKey) {
1732: if ('data' != $sKey) {
1733: echo ' ';
1734: echo $sKey;
1735: echo '="';
1736: echo $aAttributes[$sKey];
1737: echo '"';
1738: } else
1739: $mData = $aAttributes[$sKey];
1740: }
1741: }
1742:
1743: echo '>';
1744:
1745: $this->_printArray_XML($mData);
1746:
1747: echo '<';
1748: echo '/cmd>';
1749: }
1750:
1751: /*
1752: Function: _printArray_XML
1753:
1754: Prints an XML representation of a php array suitable
1755: for inclusion in the response to the browser. Arrays
1756: sent via this method will be converted into a javascript
1757: array on the browser.
1758:
1759: Parameters:
1760:
1761: mArray - (array): Array to be converted.
1762: */
1763: private function _printArray_XML($mArray) {
1764: if ('object' == gettype($mArray))
1765: $mArray = get_object_vars($mArray);
1766:
1767: if (false == is_array($mArray)) {
1768: $this->_printEscapedString_XML($mArray);
1769: return;
1770: }
1771:
1772: echo '<';
1773: echo 'xjxobj>';
1774:
1775: foreach (array_keys($mArray) as $sKey) {
1776: if (is_array($mArray[$sKey])) {
1777: echo '<';
1778: echo 'e>';
1779:
1780: foreach (array_keys($mArray[$sKey]) as $sInnerKey) {
1781: //SkipDebug
1782: if (htmlspecialchars($sInnerKey, ENT_COMPAT, 'UTF-8') != $sInnerKey) {
1783: $objLanguageManager = xajaxLanguageManager::getInstance();
1784: trigger_error(
1785: $objLanguageManager->getText('XJXRSP:AKERR:01')
1786: , E_USER_ERROR
1787: );
1788: }
1789: //EndSkipDebug
1790:
1791: if ('k' == $sInnerKey || 'v' == $sInnerKey) {
1792: echo '<';
1793: echo $sInnerKey;
1794: echo '>';
1795: $this->_printArray_XML($mArray[$sKey][$sInnerKey]);
1796: echo '<';
1797: echo '/';
1798: echo $sInnerKey;
1799: echo '>';
1800: } else {
1801: //SkipDebug
1802: $objLanguageManager = xajaxLanguageManager::getInstance();
1803: trigger_error(
1804: $objLanguageManager->getText('XJXRSP:IEAERR:01')
1805: , E_USER_ERROR
1806: );
1807: //EndSkipDebug
1808: }
1809: }
1810:
1811: echo '<';
1812: echo '/e>';
1813: } else {
1814: //SkipDebug
1815: $objLanguageManager = xajaxLanguageManager::getInstance();
1816: trigger_error(
1817: $objLanguageManager->getText('XJXRSP:NEAERR:01')
1818: , E_USER_ERROR
1819: );
1820: //EndSkipDebug
1821: }
1822: }
1823:
1824: echo '<';
1825: echo '/xjxobj>';
1826: }
1827:
1828: /*
1829: Function: _printEscapedString_XML
1830:
1831: Escape the specified data if necessary, so special characters in the
1832: command data does not interfere with the structure of the response.
1833:
1834: This could be overridden to allow for transport encodings other than
1835: XML.
1836:
1837: Parameters:
1838:
1839: sData - (string): The data to be escaped.
1840:
1841: Returns:
1842:
1843: string : The escaped data.
1844: */
1845: private function _printEscapedString_XML($sData)
1846: {
1847: if (is_null($sData) || false == isset($sData)) {
1848: echo '*';
1849: return;
1850: }
1851:
1852: if ($this->bOutputEntities) {
1853: //SkipDebug
1854: if (false === function_exists('mb_convert_encoding')) {
1855: $objLanguageManager = xajaxLanguageManager::getInstance();
1856: trigger_error(
1857: $objLanguageManager->getText('XJXRSP:MBEERR:01')
1858: , E_USER_NOTICE
1859: );
1860: }
1861: //EndSkipDebug
1862:
1863: echo call_user_func_array(
1864: 'mb_convert_encoding',
1865: array($sData, 'HTML-ENTITIES', $this->sCharacterEncoding)
1866: );
1867: return;
1868: }
1869:
1870: $nCDATA = 0;
1871:
1872: $bNoOpenCDATA = (false === strpos($sData, '<'.'![CDATA['));
1873: if ($bNoOpenCDATA) {
1874: $bNoCloseCDATA = (false === strpos($sData, ']]>'));
1875: if ($bNoCloseCDATA) {
1876: $bSpecialChars = (htmlspecialchars($sData, ENT_COMPAT, 'UTF-8') != $sData);
1877: if ($bSpecialChars)
1878: $nCDATA = 1;
1879: } else
1880: $nCDATA = 2;
1881: } else
1882: $nCDATA = 2;
1883:
1884: if (0 < $nCDATA) {
1885: echo '<';
1886: echo '![CDATA[';
1887:
1888: // PHP defines numeric values as integer or float (double and real are aliases of float)
1889: if (is_string($sData)) {
1890: echo 'S';
1891: } else if (is_int($sData) || is_float($sData)) {
1892: echo 'N';
1893: } else if (is_bool($sData)) {
1894: echo 'B';
1895: }
1896:
1897: if (1 < $nCDATA) {
1898: $aSegments = explode('<'.'![CDATA[', $sData);
1899: $aOutput = array();
1900: $nOutput = 0;
1901: foreach (array_keys($aSegments) as $keySegment) {
1902: $aFragments = explode(']]>', $aSegments[$keySegment]);
1903: $aStack = array();
1904: $nStack = 0;
1905: foreach (array_keys($aFragments) as $keyFragment) {
1906: if (0 < $nStack)
1907: array_push($aStack, ']]]]><', '![CDATA[>', $aFragments[$keyFragment]);
1908: else
1909: $aStack[] = $aFragments[$keyFragment];
1910: ++$nStack;
1911: }
1912: if (0 < $nOutput)
1913: array_push($aOutput, '<', '![]]><', '![CDATA[CDATA[', implode('', $aStack));
1914: else
1915: $aOutput[] = implode('', $aStack);
1916: ++$nOutput;
1917: }
1918: echo implode('', $aOutput);
1919: } else
1920: echo $sData;
1921:
1922: echo ']]>';
1923: } else {
1924: if (is_string($sData)) {
1925: echo 'S';
1926: } else if (is_int($sData) || is_float($sData)) {
1927: echo 'N';
1928: } else if (is_bool($sData)) {
1929: echo 'B';
1930: }
1931: echo $sData;
1932: }
1933: }
1934:
1935: /*
1936: Function: _encodeArray
1937:
1938: Recursively serializes a data structure in an array so that it can
1939: be sent to the browser. This can be thought of as the opposite of
1940: <xajaxRequestProcessorPlugin->_parseObjXml>.
1941:
1942: Parameters:
1943:
1944: mData - (mixed): The data to be evaluated.
1945:
1946: Returns:
1947:
1948: mixed : The object constructed from the data.
1949: */
1950: private function _encodeArray($mData) {
1951: if ('object' === gettype($mData))
1952: $mData = get_object_vars($mData);
1953:
1954: if (false === is_array($mData))
1955: return $mData;
1956:
1957: $aData = array();
1958: foreach (array_keys($mData) as $sKey)
1959: $aData[] = array(
1960: // key does not need to be encoded
1961: 'k'=>$sKey,
1962: 'v'=>$this->_encodeArray($mData[$sKey])
1963: );
1964: return $aData;
1965: }
1966:
1967: }// end class xajaxResponse
1968:
1969: class xajaxCustomResponse
1970: {
1971: protected $sOutput;
1972: protected $sContentType;
1973:
1974: protected $sCharacterEncoding;
1975: protected $bOutputEntities;
1976:
1977: function xajaxCustomResponse($sContentType)
1978: {
1979: $this->sOutput = '';
1980: $this->sContentType = $sContentType;
1981:
1982: $objResponseManager = xajaxResponseManager::getInstance();
1983:
1984: $this->sCharacterEncoding = $objResponseManager->getCharacterEncoding();
1985: $this->bOutputEntities = $objResponseManager->getOutputEntities();
1986: }
1987:
1988: public function setCharacterEncoding($sCharacterEncoding)
1989: {
1990: $this->sCharacterEncoding = $sCharacterEncoding;
1991: }
1992:
1993: public function setOutputEntities($bOutputEntities)
1994: {
1995: $this->bOutputEntities = $bOutputEntities;
1996: }
1997:
1998: public function clear()
1999: {
2000: $this->sOutput = '';
2001: }
2002:
2003: public function append($sOutput)
2004: {
2005: $this->sOutput .= $sOutput;
2006: }
2007:
2008: public function appendResponse($objResponse)
2009: {
2010: //SkipDebug
2011: if (false == ($objResponse instanceof xajaxCustomResponse )) {
2012: $objLanguageManager = xajaxLanguageManager::getInstance();
2013: trigger_error(
2014: $objLanguageManager->getText('XJXRSP:MXRTERR')
2015: , E_USER_ERROR
2016: );
2017: }
2018:
2019: if ($objResponse->getContentType() != $this->getContentType()) {
2020: $objLanguageManager = xajaxLanguageManager::getInstance();
2021: trigger_error(
2022: $objLanguageManager->getText('XJXRSP:MXCTERR')
2023: , E_USER_ERROR
2024: );
2025: }
2026:
2027: if ($objResponse->getCharacterEncoding() != $this->getCharacterEncoding()) {
2028: $objLanguageManager = xajaxLanguageManager::getInstance();
2029: trigger_error(
2030: $objLanguageManager->getText('XJXRSP:MXCEERR')
2031: , E_USER_ERROR
2032: );
2033: }
2034:
2035: if ($objResponse->getOutputEntities() != $this->getOutputEntities()) {
2036: $objLanguageManager = xajaxLanguageManager::getInstance();
2037: trigger_error(
2038: $objLanguageManager->getText('XJXRSP:MXOEERR')
2039: , E_USER_ERROR
2040: );
2041: }
2042: //EndSkipDebug
2043:
2044: $this->sOutput .= $objResponse->getOutput();
2045: }
2046:
2047: public function getContentType()
2048: {
2049: return $this->sContentType;
2050: }
2051:
2052: public function getCharacterEncoding()
2053: {
2054: return $this->sCharacterEncoding;
2055: }
2056:
2057: public function getOutputEntities()
2058: {
2059: return $this->bOutputEntities;
2060: }
2061:
2062: public function getOutput()
2063: {
2064: return $this->sOutput;
2065: }
2066:
2067: public function printOutput()
2068: {
2069: $sContentType = $this->sContentType;
2070: $sCharacterSet = $this->sCharacterEncoding;
2071:
2072: header("content-type: {$sContentType}; charset={$sCharacterSet}");
2073:
2074: echo $this->sOutput;
2075: }
2076: }
2077: