From b387c4424a5d034b90e53afbd0390833b1ab7e2e Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 22 Oct 2012 15:10:18 +0200 Subject: [PATCH] Added AJAXInvokeAction for generic AJAX requests --- .../lib/action/AJAXInvokeAction.class.php | 212 ++++++++++++++++++ .../lib/action/AJAXProxyAction.class.php | 184 +-------------- 2 files changed, 219 insertions(+), 177 deletions(-) create mode 100644 wcfsetup/install/files/lib/action/AJAXInvokeAction.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 index 0000000000..65cdf728b5 --- /dev/null +++ b/wcfsetup/install/files/lib/action/AJAXInvokeAction.class.php @@ -0,0 +1,212 @@ +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; + } +} diff --git a/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php b/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php index 024c740429..de68bcf536 100644 --- a/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php +++ b/wcfsetup/install/files/lib/action/AJAXProxyAction.class.php @@ -1,16 +1,9 @@ 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; - } } -- 2.20.1