Added AJAXInvokeAction for generic AJAX requests
authorAlexander Ebert <ebert@woltlab.com>
Mon, 22 Oct 2012 13:10:18 +0000 (15:10 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 22 Oct 2012 13:10:18 +0000 (15:10 +0200)
wcfsetup/install/files/lib/action/AJAXInvokeAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/action/AJAXProxyAction.class.php

diff --git a/wcfsetup/install/files/lib/action/AJAXInvokeAction.class.php b/wcfsetup/install/files/lib/action/AJAXInvokeAction.class.php
new file mode 100644 (file)
index 0000000..65cdf72
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+namespace wcf\action;
+use wcf\system\exception\AJAXException;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\exception\SystemException;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\ClassUtil;
+use wcf\util\JSON;
+use wcf\util\StringUtil;
+
+class AJAXInvokeAction extends AbstractSecureAction {
+       /**
+        * method name
+        * @var string
+        */
+       public $actionName = '';
+       
+       /**
+        * action object
+        * @var wcf\system\SingletonFactory
+        */
+       public $actionObject = null;
+       
+       /**
+        * class name
+        * @var string
+        */
+       public $className = '';
+       
+       /**
+        * enables debug mode
+        * @var boolean
+        */
+       public $inDebugMode = false;
+       
+
+       /**
+        * results of the executed action
+        * @var mixed
+        */
+       protected $response = null;
+       
+       /**
+        * @see wcf\action\IAction::__run()
+        */
+       public function __run() {
+               try {
+                       parent::__run();
+               }
+               catch (\Exception $e) {
+                       if ($e instanceof AJAXException) {
+                               throw $e;
+                       }
+                       else {
+                               $this->throwException($e);
+                       }
+               }
+       }
+       
+       /**
+        * @see wcf\action\IAction::readParameters()
+        */
+       public function readParameters() {
+               parent::readParameters();
+               
+               if (isset($_POST['actionName'])) $this->actionName = StringUtil::trim($_POST['actionName']);
+               if (isset($_POST['className'])) $this->className = StringUtil::trim($_POST['className']);
+               if (empty($this->className) || !class_exists($this->className)) {
+                       throw new UserInputException('className');
+               }
+       }
+       
+       /**
+        * @see wcf\action\IAction::execute()
+        */
+       public function execute() {
+               parent::execute();
+               
+               // execute action
+               try {
+                       $this->invoke();
+               }
+               catch (\Exception $e) {
+                       $this->throwException($e);
+               }
+               $this->executed();
+               
+               // send JSON-encoded response
+               if (!$this->inDebugMode) {
+                       header('Content-type: application/json');
+                       echo JSON::encode($this->response);
+                       exit;
+               }
+       }
+       
+       /**
+        * Invokes action method.
+        */
+       protected function invoke() {
+               // check for interface and inheritance of SingletonFactory
+               if (!ClassUtil::isInstanceOf($this->className, 'wcf\system\SingletonFactory')) {
+                       throw new SystemException("'".$this->className."' should extend 'wcf\system\SingletonFactory'");
+               }
+               
+               $this->actionObject = call_user_func(array($this->className, 'getInstance'));
+               
+               // validate action name
+               if (empty($this->actionName) || !method_exists($this->actionObject, $this->actionName)) {
+                       throw new UserInputException('actionName');
+               }
+               
+               $this->response = $this->actionObject->{$this->actionName}();
+       }
+       
+       /**
+        * Throws an previously catched exception while maintaing the propriate stacktrace.
+        *
+        * @param       \Exception      $e
+        */
+       protected function throwException(\Exception $e) {
+               if ($this->inDebugMode) {
+                       throw $e;
+               }
+       
+               if ($e instanceof IllegalLinkException) {
+                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.ajax.error.sessionExpired'), AJAXException::SESSION_EXPIRED, $e->getTraceAsString());
+               }
+               else if ($e instanceof PermissionDeniedException) {
+                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.ajax.error.permissionDenied'), AJAXException::INSUFFICIENT_PERMISSIONS, $e->getTraceAsString());
+               }
+               else if ($e instanceof SystemException) {
+                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->__getTraceAsString());
+               }
+               else if ($e instanceof UserInputException) {
+                       throw new AJAXException($e->getMessage(), AJAXException::BAD_PARAMETERS, $e->getTraceAsString());
+               }
+               else {
+                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->getTraceAsString());
+               }
+       }
+       
+       /**
+        * Returns action response.
+        *
+        * @return      mixed
+        */
+       public function getResponse() {
+               return $this->response;
+       }
+       
+       /**
+        * Enables debug mode.
+        */
+       public function enableDebugMode() {
+               $this->inDebugMode = true;
+       }
+       
+       /**
+        * Performs a debug call to AJAXInvokeAction, allowing testing without relying on JavaScript.
+        * The $data-array should be build like within WCF.Action.Proxy, look below for an example:
+        *
+        * $data = array(
+        *      'actionName' => 'foo',
+        *      'className' => 'wcf\foo\bar\FooBarAction',
+        *      'objectIDs' => array(1, 2, 3, 4, 5), // optional
+        *      'parameters' => array( // optional
+        *              'foo' => 'bar',
+        *              'data' => array(
+        *                      'baz' => 'foobar'
+        *              )
+        *      )
+        * )
+        *
+        * @param       array           $data
+        * @param       string          $className
+        * @param       string          $actionName
+        * @return      wcf\action\AJAXInvokeAction
+        */
+       public static function debugCall(array $data) {
+               // validate $data array
+               if (!isset($data['actionName'])) {
+                       throw new SystemException("Could not execute debug call, 'actionName' is missing.");
+               }
+               else if (!isset($data['className'])) {
+                       throw new SystemException("Could not execute debug call, 'className' is missing.");
+               }
+               
+               // set security token
+               $_REQUEST['t'] = WCF::getSession()->getSecurityToken();
+               
+               // save $_POST variables
+               $postVars = $_POST;
+               
+               // fake request
+               foreach ($data as $key => $value) {
+                       $_POST[$key] = $value;
+               }
+               
+               // execute request
+               $className = get_called_class();
+               $actionObject = new $className();
+               $actionObject->enableDebugMode();
+               $actionObject->__run();
+               
+               // restore $_POST variables
+               $_POST = $postVars;
+               
+               return $actionObject;
+       }
+}
index 024c7404297c0a3597e053ee6e818952136979c1..de68bcf53677ab4f2dfae1dbc583db0178767f47 100644 (file)
@@ -1,16 +1,9 @@
 <?php
 namespace wcf\action;
 use wcf\data\IStorableObject;
-use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\AJAXException;
-use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\SystemException;
-use wcf\system\exception\UserInputException;
-use wcf\system\exception\ValidateActionException;
-use wcf\system\WCF;
 use wcf\util\ArrayUtil;
 use wcf\util\ClassUtil;
-use wcf\util\JSON;
 use wcf\util\StringUtil;
 
 /**
@@ -23,31 +16,13 @@ use wcf\util\StringUtil;
  * @subpackage action
  * @category   Community Framework
  */
-class AJAXProxyAction extends AbstractSecureAction {
-       /**
-        * action name
-        * @var string
-        */
-       protected $actionName = '';
-       
-       /**
-        * class name
-        * @var string
-        */
-       protected $className = '';
-       
+class AJAXProxyAction extends AJAXInvokeAction {
        /**
         * interface name
         * @var string
         */
        protected $interfaceName = '';
        
-       /**
-        * debug mode
-        * @var boolean
-        */
-       protected $inDebugMode = false;
-       
        /**
         * object action
         * @var wcf\data\IDatabaseObjectAction
@@ -66,37 +41,12 @@ class AJAXProxyAction extends AbstractSecureAction {
         */
        protected $parameters = array();
        
-       /**
-        * results of the executed action
-        * @var mixed
-        */
-       protected $response = null;
-       
-       /**
-        * @see wcf\action\IAction::__run()
-        */
-       public function __run() {
-               try {
-                       parent::__run();
-               }
-               catch (\Exception $e) {
-                       if ($e instanceof AJAXException) {
-                               throw $e;
-                       }
-                       else {
-                               $this->throwException($e);
-                       }
-               }
-       }
-       
        /**
         * @see wcf\action\IAction::readParameters()
         */
        public function readParameters() {
                parent::readParameters();
                
-               if (isset($_POST['actionName'])) $this->actionName = StringUtil::trim($_POST['actionName']);
-               if (isset($_POST['className'])) $this->className = StringUtil::trim($_POST['className']);
                if (isset($_POST['interfaceName'])) $this->interfaceName = StringUtil::trim($_POST['interfaceName']);
                if (isset($_POST['objectIDs']) && is_array($_POST['objectIDs'])) $this->objectIDs = ArrayUtil::toIntegerArray($_POST['objectIDs']);
                if (isset($_POST['parameters']) && is_array($_POST['parameters'])) $this->parameters = $_POST['parameters'];
@@ -105,15 +55,9 @@ class AJAXProxyAction extends AbstractSecureAction {
        /**
         * @see wcf\action\IAction::execute()
         */
-       public function execute() {
-               parent::execute();
-               
-               // validate class name
-               if (!class_exists($this->className)) {
-                       throw new SystemException("unknown class '".$this->className."'");
-               }
+       protected function invoke() {
                if (!ClassUtil::isInstanceOf($this->className, 'wcf\data\IDatabaseObjectAction')) {
-                       throw new SystemException("'".$this->className."' should implement 'wcf\system\IDatabaseObjectAction'");
+                       throw new SystemException("'".$this->className."' should implement 'wcf\data\IDatabaseObjectAction'");
                }
                
                if (!empty($this->interfaceName)) {
@@ -126,33 +70,12 @@ class AJAXProxyAction extends AbstractSecureAction {
                $this->objectAction = new $this->className($this->objectIDs, $this->actionName, $this->parameters);
                
                // validate action
-               try {
-                       $this->objectAction->validateAction();
-               }
-               catch (UserInputException $e) {
-                       $this->throwException($e);
-               }
-               catch (ValidateActionException $e) {
-                       $this->throwException($e);
-               }
+               $this->objectAction->validateAction();
                
                // execute action
-               try {
-                       $this->response = $this->objectAction->executeAction();
-                       if (isset($this->response['returnValues'])) {
-                               $this->response['returnValues'] = $this->getData($this->response['returnValues']);
-                       }
-               }
-               catch (\Exception $e) {
-                       $this->throwException($e);
-               }
-               $this->executed();
-               
-               // send JSON-encoded response
-               if (!$this->inDebugMode) {
-                       header('Content-type: application/json');
-                       echo JSON::encode($this->response);
-                       exit;
+               $this->response = $this->objectAction->executeAction();
+               if (isset($this->response['returnValues'])) {
+                       $this->response['returnValues'] = $this->getData($this->response['returnValues']);
                }
        }
        
@@ -174,97 +97,4 @@ class AJAXProxyAction extends AbstractSecureAction {
                }
                return $response;
        }
-       
-       /**
-        * Throws an previously catched exception while maintaing the propriate stacktrace.
-        * 
-        * @param       \Exception      $e
-        */
-       protected function throwException(\Exception $e) {
-               if ($this->inDebugMode) {
-                       throw $e;
-               }
-               
-               if ($e instanceof IllegalLinkException) {
-                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.ajax.error.sessionExpired'), AJAXException::SESSION_EXPIRED, $e->getTraceAsString());
-               }
-               else if ($e instanceof PermissionDeniedException) {
-                       throw new AJAXException(WCF::getLanguage()->get('wcf.global.ajax.error.permissionDenied'), AJAXException::INSUFFICIENT_PERMISSIONS, $e->getTraceAsString());
-               }
-               else if ($e instanceof SystemException) {
-                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->__getTraceAsString());
-               }
-               else if ($e instanceof UserInputException) {
-                       throw new AJAXException($e->getMessage(), AJAXException::BAD_PARAMETERS, $e->getTraceAsString());
-               }
-               else {
-                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->getTraceAsString());
-               }
-       }
-       
-       /**
-        * Returns action response.
-        * 
-        * @return      mixed
-        */
-       public function getResponse() {
-               return $this->response;
-       }
-       
-       /**
-        * Enables debug mode.
-        */
-       public function enableDebugMode() {
-               $this->inDebugMode = true;
-       }
-       
-       /**
-        * Performs a debug call to AJAXProxyAction, allowing testing without relying on JavaScript.
-        * The $data-array should be build like within WCF.Action.Proxy, look below for an example:
-        * 
-        * $data = array(
-        *      'actionName' => 'foo',
-        *      'className' => 'wcf\foo\bar\FooBarAction',
-        *      'objectIDs' => array(1, 2, 3, 4, 5), // optional
-        *      'parameters' => array( // optional
-        *              'foo' => 'bar',
-        *              'data' => array(
-        *                      'baz' => 'foobar'
-        *              )
-        *      )
-        * )
-        * 
-        * @param       array           $data
-        * @param       string          $className
-        * @param       string          $actionName
-        * @return      wcf\action\AJAXProxyAction
-        */
-       public static function debugCall(array $data) {
-               // validate $data array
-               if (!isset($data['actionName'])) {
-                       throw new SystemException("Could not execute debug call, 'actionName' is missing.");
-               }
-               else if (!isset($data['className'])) {
-                       throw new SystemException("Could not execute debug call, 'className' is missing.");
-               }
-               
-               // save $_POST variables
-               $postVars = $_POST;
-               
-               // fake request
-               foreach ($data as $key => $value) {
-                       $_POST[$key] = $value;
-               }
-               
-               // execute request
-               $className = get_called_class();
-               $actionObject = new $className();
-               $actionObject->enableDebugMode();
-               $actionObject->__run();
-               
-               // restore $_POST variables
-               $_POST = $postVars;
-               
-               return $actionObject;
-       }
 }