Added:
trunk/Lux/Controller/Rest.php (contents, props changed)
Log:
Initial commit for a (still very rough) REST page controller.
Added: trunk/Lux/Controller/Rest.php
==============================================================================
--- (empty file)
+++ trunk/Lux/Controller/Rest.php Tue Sep 30 14:35:48 2008
@@ -0,0 +1,334 @@
+<?php
+/**
+ *
+ * A specialized version of Solar_Controller_Page for RESTful apps.
+ *
+ * @category Lux
+ *
+ * @package Lux_Controller
+ *
+ * @author Rodrigo Moraes <rodrigo...@gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+class Lux_Controller_Rest extends Solar_Controller_Page
+{
+ /**
+ *
+ * HTTP request method.
+ *
+ * @var string
+ *
+ */
+ protected $_request_method;
+
+ /**
+ *
+ * A list of supported HTTP request methods for each action,
+ * keyed by the dashed action name. Example:
+ *
+ * {{code: php
+ *
+ * $_action_http = array(
+ * // actionList supports only GET
+ * 'list' => 'GET',
+ * // actionItem suppports GET, POST and PUT
+ * 'item' => array(
+ * 'GET', 'POST', 'PUT'
+ * ),
+ * );
+ *
+ * }}
+ *
+ * @var array
+ *
+ */
+ protected $_action_http = array();
+
+ /**
+ *
+ * A list of actions to be mapped based on the HTTP request method,
+ * keyed by the dashed action name. Example:
+ *
+ * {{code: php
+ *
+ * $_action_map = array(
+ * 'item' => array(
+ * // if HTTP method is POST, use 'actionItemUpdate'
instead
+ * 'POST' => 'item-update',
+ * // if HTTP method is PUT, use 'actionItemInsert' instead
+ * 'PUT' => 'item-insert',
+ * ),
+ * );
+ *
+ * }}
+ *
+ * @var array
+ *
+ */
+ protected $_action_map = array();
+
+ /**
+ *
+ * Content data to be converted depending on the current format
+ *
+ * @var array
+ *
+ */
+ protected $_content;
+
+ /**
+ *
+ * Sets the response content based on the format.
+ *
+ * @return void
+ *
+ */
+ protected function _render()
+ {
+ $this->_preRender();
+
+ // make sure we have xml or json
+ if ($this->_format != 'xml') {
+ $this->_format = 'json';
+ }
+
+ if ($this->_format == 'xml') {
+ $this->_renderXml();
+ } else {
+ $this->_renderJson();
+ }
+
+ $this->_postRender();
+ }
+
+ /**
+ *
+ * Sets the response content for JSON.
+ *
+ * @return void
+ *
+ */
+ protected function _renderJson()
+ {
+ // convert content to JSON
+ $json = Solar::factory('Solar_Json');
+ $this->_response->content = $json->encode($this->_content);
+ }
+
+ /**
+ *
+ * Sets the response content for XML.
+ *
+ * @return void
+ *
+ */
+ protected function _renderXml()
+ {
+ // @todo: convert content to XML
+ $this->_response->content = '';
+ }
+
+ /**
+ *
+ * Sets the value of $_content and defines as status code for the
response.
+ *
+ * @param array $content Content data to be converted to JSON or XML,
+ * depending on the current format.
+ *
+ * @param int $code Response status code.
+ *
+ * @return void
+ *
+ */
+ protected function _setContent($content, $code = 200)
+ {
+ $this->_content = (array) $content;
+ $this->_response->setStatusCode($code);
+ }
+
+ // -----------------------------------------------------------------
+ //
+ // Validation and error handling.
+ //
+ // -----------------------------------------------------------------
+
+ /**
+ *
+ * Validates that the HTTP method is supported by the current action.
+ *
+ * @return bool True if the current action supports the request method,
+ * false otherwise.
+ *
+ */
+ protected function _validateRequestMethod()
+ {
+ $action = $this->_action;
+ $method = $this->_request_method;
+
+ if (isset($this->_action_http[$action]) &&
+ in_array($method, $this->_action_http[$action])) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ * Renders a error code and message and terminates the current script.
+ *
+ * @param string Error message.
+ *
+ * @param int $code Status code.
+ *
+ */
+ protected function _error($message, $code = 500)
+ {
+ $this->_setContent($message, $code);
+ $this->_render();
+ $this->_setContentType();
+
+ echo $this->_response;
+ exit((int) $code);
+ }
+
+ /**
+ *
+ * Renders an exception message and terminates the current script.
+ *
+ * @param Exception $e The exception encountered during fetch().
+ *
+ * @return void;
+ *
+ */
+ protected function _exceptionDuringFetch(Exception $e)
+ {
+ $this->_error($e->getMessage());
+ }
+
+ // -----------------------------------------------------------------
+ //
+ // Behavior hooks.
+ //
+ // -----------------------------------------------------------------
+
+ /**
+ *
+ * Executes after construction.
+ *
+ * @return void
+ *
+ */
+ protected function _setup()
+ {
+ // set the request method
+ switch (true) {
+ case $this->_request->isGet():
+ $this->_request_method = 'GET';
+ break;
+ case $this->_request->isPut():
+ $this->_request_method = 'PUT';
+ break;
+ case $this->_request->isPost():
+ $this->_request_method = 'POST';
+ break;
+ case $this->_request->isDelete():
+ $this->_request_method = 'DELETE';
+ break;
+ default:
+ $this->_error('ERR_INVALID_REQUEST_METHOD');
+ }
+ }
+
+ /**
+ *
+ * Executes before the first action.
+ *
+ * @return void
+ *
+ */
+ protected function _preRun()
+ {
+ $action = $this->_action;
+ $method = $this->_request_method;
+
+ // rename action according to the request method, if defined
+ if (isset($this->_action_map[$action][$method])) {
+ $this->_action = $this->_action_map[$action][$method];
+ }
+ }
+
+ /**
+ *
+ * Executes before each action.
+ *
+ * @return void
+ *
+ */
+ protected function _preAction()
+ {
+ // checks if the current action supports the request method
+ if (! $this->_validateRequestMethod()) {
+ $info = array(
+ 'action' => $this->_action,
+ 'method' => $this->_request_method,
+ );
+
+ if (isset($this->_action_http[$this->_action])) {
+ $info['valid_methods'] =
$this->_action_http[$this->_action];
+ }
+
+ throw $this->_exception('ERR_INVALID_REQUEST_METHOD', $info);
+ }
+
+ // extend this to add auth/access checkings
+ }
+
+ /**
+ *
+ * Executes after each action.
+ *
+ * @return void
+ *
+ */
+ protected function _postAction()
+ {
+ }
+
+ /**
+ *
+ * Executes after the last action.
+ *
+ * @return void
+ *
+ */
+ protected function _postRun()
+ {
+ }
+
+ /**
+ *
+ * Executes before formatting the response content.
+ *
+ * @return void
+ *
+ */
+ protected function _preRender()
+ {
+ }
+
+ /**
+ *
+ * Executes after formatting the response content.
+ *
+ * @return void
+ *
+ */
+ protected function _postRender()
+ {
+ }
+}