×

Welcome to TagMyCode

Please login or create account to add a snippet.
0
0
 
0
Language: PHP
Posted by: Jing Tai Piao
Added: May 14, 2013 3:29 AM
Views: 28
Tags: no tags
  1. <?php
  2. /**
  3.  * AjaxActionsResponse V3.0
  4.  * @author Joel Cox
  5.  * @date 16-04-2011
  6.  */
  7.  
  8. class AjaxResponse extends AjaxActionList {
  9.        
  10.         // Set-up / Initialization
  11.        
  12.         public static $autoOutputOnShutdown = true;
  13.         private static $_isShutdownFunctionSet = false;
  14.         private static $_autoOutputInstance = null;
  15.         private static $_instances = array();
  16.         private static $_errorHandlerInstance = null;
  17.         protected $_namespace = null;
  18.         protected $_previousErrorHandler = null;
  19.         protected $_previousExceptionHandler = null;
  20.         protected $_previousErrorReporting = null;
  21.         protected static $_iframeSubmit = false;
  22.        
  23.         /**
  24.          * Initialize an instance of AjaxActionsResponse object.
  25.          * @param string $namespace Response Namespace. all calls to init() function with the same namespace specified will return the same object.
  26.          * @param boolean $setErrorHandler whether or not to set the ajax actions error handler. defaults to true only with the default namespace, and no other instance has already set an error handler.
  27.          * @return AjaxActionList
  28.          */
  29.         public static function init($namespace = null, $setErrorHandler = null) {
  30.                 $iframeSubmitIndicator = 'ajax-actions-iframe-submit-indicator';
  31.                 if (isset($_REQUEST[$iframeSubmitIndicator])) {
  32.                         self::$_iframeSubmit = true;
  33.                         unset($_REQUEST[$iframeSubmitIndicator]);
  34.                         if (isset($_GET[$iframeSubmitIndicator])) unset($_GET[$iframeSubmitIndicator]);
  35.                         if (isset($_POST[$iframeSubmitIndicator])) unset($_POST[$iframeSubmitIndicator]);
  36.                 }
  37.                 $setErrorHandler = is_null($setErrorHandler) && is_null($namespace) ? true : false;
  38.                 $namespace = is_null($namespace) ? 'global' : $namespace;
  39.                 if (!isset(self::$_instances[$namespace])) {
  40.                         self::$_instances[$namespace] = new self();
  41.                 }
  42.                 if ($setErrorHandler && self::$_errorHandlerInstance == null) {
  43.                         self::$_instances[$namespace]->setPhpErrorHandler();
  44.                 }
  45.                 return self::$_instances[$namespace];
  46.         }
  47.        
  48.         public static function isIframeSubmit() {
  49.                 return self::$_iframeSubmit;
  50.         }
  51.        
  52.         public static function isAjaxActionsRequest() {
  53.                 if (self::$_iframeSubmit) return true;
  54.                 if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
  55.                         return true;
  56.                 }
  57.                 return false;
  58.         }
  59.        
  60.         /**
  61.          * Sets PHP error and exception handlers - so errors will be output as valid
  62.          * ajax actions responses in order to give useful feedback to the user
  63.          */
  64.         public function setPhpErrorHandler() {
  65.                 self::$_errorHandlerInstance = $this;
  66.                 $this->_previousErrorHandler = set_error_handler(array($this, '__phpErrorHandler'), error_reporting());
  67.                 $this->_previousExceptionHandler = set_exception_handler(array($this, '__phpExceptionHandler'));
  68.                 $this->_previousErrorReporting = ini_get('error_reporting');
  69.                 ini_set('error_reporting', 0);
  70.         }
  71.        
  72.         /**
  73.          * Restore previous PHP error and exception handlers.
  74.          */
  75.         public function unsetPhpErrorHandler() {
  76.                 if (!is_null($this->_previousErrorHandler)) set_error_handler($this->_previousErrorHandler);
  77.                 if (!is_null($this->_previousExceptionHandler)) set_exception_handler($this->_previousExceptionHandler);
  78.                 $this->_previousErrorHandler = null;
  79.                 $this->_previousExceptionHandler = null;
  80.                 ini_set('error_reporting', $this->_previousErrorReporting);
  81.         }
  82.        
  83.         public function __phpErrorHandler($errno, $errstr, $errfile, $errline) {
  84.                 self::$_errorHandlerInstance->alert("Error $errno\n$errstr\n\nOccurred in $errfile on line $errline");
  85.                 die;
  86.         }
  87.        
  88.         public function __phpExceptionHandler(Exception $e) {
  89.                 self::$_errorHandlerInstance->alert('An error occurred: '.$e->getMessage());
  90.                 die;
  91.         }
  92.        
  93.         public static function __phpShutdownFunction() {
  94.                 if (!self::isAjaxActionsRequest()) return;
  95.                 if (self::$autoOutputOnShutdown) {
  96.                         // NOTE: OB_INITIAL_LEVEL is C5 SPECIFIC - and will
  97.                         // need updating if moving this class to another framework!
  98.                         if (!defined('OB_INITIAL_LEVEL')) {
  99.                                 echo 'AjaxActionsError - Please see comments in __phpShutdownFunction for more details.';
  100.                                 return;
  101.                         }
  102.                         $lastError = error_get_last();
  103.                         if ($lastError['type'] === E_ERROR) {
  104.                                 $ajax = self::init();
  105.                                 $ajax->jQuery->ajaxActions->loading_start();
  106.                                 $ajax->jQuery->ajaxActions->error("PHP Fatal Error\n\n".
  107.                                         $lastError['message'].' in '.$lastError['file'].' on line '.$lastError['line']
  108.                                         , array(
  109.                                                 'width' => '1000px',
  110.                                                 'margin-left' => '-500px',
  111.                                                 'text-align' => 'left',
  112.                                                 'font-size' => '12pt'
  113.                                         ));
  114.                                         // On fatal error, clear all output buffers
  115.                                         while (ob_get_level()) ob_get_clean();
  116.                         }
  117.                         if (!headers_sent()) {
  118.                                 if (!is_null(self::$_autoOutputInstance)) {
  119.                                         $response = self::$_autoOutputInstance;
  120.                                 } else {
  121.                                         $response = self::init();
  122.                                 }
  123. //                              var_export($response);
  124.                                 $response->output();
  125.                         }
  126.                 }
  127.         }
  128.        
  129.         public function __construct() {
  130.                 if (!self::$_isShutdownFunctionSet) {
  131.                         register_shutdown_function(get_class($this).'::__phpShutdownFunction');
  132.                         self::$_isShutdownFunctionSet = true;
  133.                 }
  134.         }
  135.        
  136.         public function getOutput() {
  137. //              return print_r($this->toArray(), true);
  138.                 return json_encode($this->utf8encodestrings(array('ajaxActions' => $this->toArray())));
  139. //              return json_encode(array('ajaxActions' => $this->toArray()));
  140.         }
  141.        
  142.         private function utf8encodestrings($data) {
  143.                 if (is_array($data)) {
  144.                         foreach ($data as $k => &$v) $v = $this->utf8encodestrings($v);
  145.                 } else if (is_string($data)) {
  146.                         $data = utf8_encode($data);
  147. //                      $data = iconv(mb_detect_encoding($data, 'auto'), 'UTF-8//TRANSLIT', $data);
  148. //                      $data = utf8_encode(iconv(mb_detect_encoding($data, 'auto'), 'UTF-8//TRANSLIT', $data));
  149.                 }
  150.                 return $data;
  151.         }
  152.        
  153. }
  154.  
  155. /**
  156.  * Ajax Actions Action List
  157.  *
  158.  * @method alert($text) will show a javascript alert.
  159.  */
  160. class AjaxActionList {
  161.        
  162.         protected $_actions = array();
  163.         protected $_isExecuteChain = false;
  164.         protected $_parent = null;
  165.         protected $_single = false;
  166.         protected $_return = null;
  167.        
  168.         /**
  169.          *
  170.          * @return type
  171.          */
  172.         public function getOutput() {
  173.                 return json_encode($this->toArray());
  174.         }
  175.        
  176.         protected static $_outputCount = 0;
  177.         public function output($reset = true) {
  178.                 if (AjaxResponse::isIframeSubmit()) {
  179.                         if (self::$_outputCount++ == 0) {
  180.                                 echo '<script>window.parent.$.ajaxActions.loading_complete();</script>';
  181.                         }
  182.                         echo '<script>window.parent.$.ajaxActions.processResponse('.$this->getOutput().');</script>';
  183.                 } else if (!headers_sent()) {
  184.                         header('content-type: application/json; charset=utf-8');
  185.                         echo $this->getOutput();
  186.                 }
  187.                 flush();
  188.                 if ($reset) $this->_actions = array();
  189.         }
  190.        
  191.         public function _addAction($method, $params, $startExecuteChain = false) {
  192.                 foreach ($params as &$param) {
  193.                         if ($param instanceof self) if ($param->_isExecuteChain) {
  194.                                 $param = $param->_getParent();
  195.                         }
  196.                 }
  197.                 $action = array(
  198.                         'method' => $method,
  199.                         'params' => $params
  200.                 );
  201.                 if ($this->_isExecuteChain || $startExecuteChain) {
  202.                         $chain = new self();
  203.                         $chain->_isExecuteChain = true;
  204.                         $chain->_parent = $this;
  205.                         $action['chain'] = $chain;
  206.                 }
  207.                 $this->_actions[] = $action;
  208.                 return ($this->_isExecuteChain || $startExecuteChain) ? $chain : $this;
  209.         }
  210.        
  211.         public function _addGet($name) {
  212.                 $chain = new self();
  213.                 $chain->_isExecuteChain = true;
  214.                 $chain->_parent = $this;
  215.                 $this->_actions[] = array(
  216.                         '__get__' => $name,
  217.                         'chain' => $chain
  218.                 );
  219.                 return $chain;
  220.         }
  221.        
  222.         public static function callback($return = null) {
  223.                 $callback = new self();
  224.                 if ($return !== null) $callback->_return = $return;
  225.                 return $callback;
  226.         }
  227.        
  228.         protected function _getParent() {
  229.                 return is_null($this->_parent) ? $this : $this->_parent->_getParent();
  230.         }
  231.        
  232.         // -------------------------------------------------------------------------
  233.        
  234.         public function jQuery() {
  235.                 //return $this->_addAction('jQuery', func_get_args(), true);
  236.                 $data = func_get_args();
  237.                 return $this->_addAction('jQuery', $data, true);
  238.         }
  239.        
  240.         public function __call($name, $arguments) {
  241.                 return $this->_addAction($name, $arguments);
  242.         }
  243.        
  244.         public function __get($name) {
  245.                 return $this->_addGet($name);
  246.         }
  247.        
  248.         public function __set($name, $value) {
  249.                 $this->_actions[] = array(
  250.                         '__set__' => $name,
  251.                         'value' => $value
  252.                 );
  253.                 return $this;
  254.         }
  255.        
  256.         public function toArray() {
  257.                 foreach ($this->_actions as &$action) {
  258.                         if (isset($action['chain'])) if ($action['chain'] instanceof self) {
  259.                                 $action['chain'] = $action['chain']->toArray();
  260.                                 if (count($action['chain']) == 0) {
  261.                                         unset($action['chain']);
  262.                                 }
  263.                         }
  264.                         if (isset($action['__get__']) || isset($action['__set__'])) {
  265.                                
  266.                         } else foreach ($action['params'] as &$param) {
  267.                                 if (is_array($param)) {
  268.                                         foreach ($param as &$p) {
  269.                                                 if ($p instanceof self) {
  270.                                                         $p = $p->_getParent()->toArray();
  271.                                                         $p['isAjaxActionChainObject'] = true;
  272.                                                 }
  273.                                         }
  274.                                 } else if ($param instanceof self) {
  275.                                         $param = $param->toArray();
  276.                                         $param['isAjaxActionChainObject'] = true;
  277.                                 }
  278.                         }
  279.                 }
  280.                 if ($this->_return !== null) $this->_actions['__return__'] = $this->_return;
  281.                 return $this->_actions;
  282.         }
  283.        
  284.         public function _ajaxLoadScript($url, $multiple = false, $async = true) {
  285.                 if ($async) {
  286.                         $callback = self::callback();
  287.                         $this->jQuery->ajaxActions->ajaxLoadScript($url, $multiple, $callback);
  288.                         return $callback;
  289.                 } else {
  290.                         $this->jQuery->ajaxActions->ajaxLoadScript($url, $multiple);
  291.                         return $this;
  292.                 }
  293.         }
  294.        
  295.         public function _ajaxLoadCss($url) {
  296.                 $this->jQuery->ajaxActions->ajaxLoadCss($url);
  297.                 return $this;
  298.         }
  299.        
  300.         /* @method alert($text) */
  301.        
  302. }
  303.