diff --git a/src/classes/Controller.php b/src/classes/Controller.php
deleted file mode 100644
index 015df27..0000000
--- a/src/classes/Controller.php
+++ /dev/null
@@ -1,206 +0,0 @@
-
- * @copyright Copyright 2007-2014, Josh Sherman
- * @license http://www.opensource.org/licenses/mit-license.html
- * @package PICKLES
- * @link https://github.com/joshtronic/pickles
- */
-
-/**
- * Controller Class
- *
- * The heavy lifter of PICKLES, makes the calls to get the session and
- * configuration loaded. Loads modules, serves up user authentication when the
- * module asks for it, and loads the viewer that the module requested. Default
- * values are present to make things easier on the user.
- *
- * @usage new Controller();
- */
-class Controller extends Object
-{
- /**
- * Constructor
- *
- * To save a few keystrokes, the Controller is executed as part of the
- * constructor instead of via a method. You either want the Controller or
- * you don't.
- */
- public function __construct()
- {
- parent::__construct();
-
- try
- {
- // Catches requests that aren't lowercase
- $lowercase_request = strtolower($_REQUEST['request']);
-
- if ($_REQUEST['request'] != $lowercase_request)
- {
- // @todo Rework the Browser class to handle the 301 (perhaps redirect301()) to not break other code
- header('Location: ' . substr_replace($_SERVER['REQUEST_URI'], $lowercase_request, 1, strlen($lowercase_request)), true, 301);
- throw new Exception();
- }
-
- // Grabs the requested page
- $request = $_REQUEST['request'];
-
- // Loads the module's information
- $module_class = strtr($request, '/', '_');
- $module_filename = SITE_MODULE_PATH . $request . '.php';
- $module_exists = file_exists($module_filename);
-
- // Attempts to instantiate the requested module
- if ($module_exists)
- {
- if (class_exists($module_class))
- {
- $module = new $module_class;
- }
- }
-
- // No module instantiated, load up a generic Module
- if (!isset($module))
- {
- $module = new Module();
- }
-
- // Determines if we need to serve over HTTP or HTTPS
- if ($module->secure == false && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'])
- {
- header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
- throw new Exception();
- }
- elseif ($module->secure == true && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false))
- {
- header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
- throw new Exception();
- }
-
- // Gets the profiler status
- $profiler = $this->config->pickles['profiler'];
- $profiler = $profiler === true || stripos($profiler, 'timers') !== false;
-
- $default_method = '__default';
- $role_method = null;
-
- // Attempts to execute the default method
- // @todo Seems a bit redundant, refactor
- if ($default_method == $role_method || method_exists($module, $default_method))
- {
- // Starts a timer before the module is executed
- if ($profiler)
- {
- Profiler::timer('module ' . $default_method);
- }
-
- $valid_request = false;
- $error_message = 'An unexpected error has occurred.';
-
- // Determines if the request method is valid for this request
- if ($module->method)
- {
- if (!is_array($module->method))
- {
- $module->method = [$module->method];
- }
-
- foreach ($module->method as $method)
- {
- if ($_SERVER['REQUEST_METHOD'] == $method)
- {
- $valid_request = true;
- break;
- }
- }
-
- if (!$valid_request)
- {
- // @todo Should probably utilize that AJAX flag to determine the type of return
- $error_message = 'There was a problem with your request method.';
- }
- }
- else
- {
- $valid_request = true;
- }
-
- $valid_form_input = true;
-
- if ($valid_request && $module->validate)
- {
- $validation_errors = $module->__validate();
-
- if ($validation_errors)
- {
- $error_message = implode(' ', $validation_errors);
- $valid_form_input = false;
- }
- }
-
- /**
- * Note to Self: When building in caching will need to let the
- * module know to use the cache, either passing in a variable
- * or setting it on the object
- */
- if ($valid_request && $valid_form_input)
- {
- $module_return = $module->$default_method();
-
- if (!is_array($module_return))
- {
- $module_return = $module->response;
- }
- else
- {
- $module_return = array_merge($module_return, $module->response);
- }
- }
-
- // Stops the module timer
- if ($profiler)
- {
- Profiler::timer('module ' . $default_method);
- }
-
- $display = new Display($module);
- }
-
- // Starts a timer for the display rendering
- if ($profiler)
- {
- Profiler::timer('display render');
- }
-
- // Renders the content
- $output = $display->render();
-
- // Stops the display timer
- if ($profiler)
- {
- Profiler::timer('display render');
- }
- }
- catch (Exception $e)
- {
- $output = $e->getMessage();
- }
-
- echo $output;
-
- // Display the Profiler's report if the stars are aligned
- if ($this->config->pickles['profiler'])
- {
- Profiler::report();
- }
- }
-}
-
diff --git a/src/classes/Display.php b/src/classes/Display.php
deleted file mode 100644
index be82a21..0000000
--- a/src/classes/Display.php
+++ /dev/null
@@ -1,96 +0,0 @@
-
- * @copyright Copyright 2007-2014, Josh Sherman
- * @license http://www.opensource.org/licenses/mit-license.html
- * @package PICKLES
- * @link https://github.com/joshtronic/pickles
- */
-
-/**
- * Display Class
- *
- * If you can see it then it probably happened in here.
- */
-class Display extends Object
-{
- /**
- * Module
- *
- * This is the module we are attempting to display output for.
- */
- public $module = null;
-
- public function __construct($module = null)
- {
- if ($module && $module instanceof Module)
- {
- $this->module = $module;
- }
- }
-
- public function render()
- {
- try
- {
- // Starts up the buffer so we can capture it
- ob_start();
-
- if (!is_array($this->module->response))
- {
- $this->module->response = [$this->module->response];
- }
-
- // Checks for the PHPSESSID in the query string
- if (stripos($_SERVER['REQUEST_URI'], '?PHPSESSID=') === false)
- {
- // XHTML compliancy stuff
- // @todo Wonder if this could be yanked now that we're in HTML5 land
- ini_set('arg_separator.output', '&');
- ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,input=src,fieldset=');
-
- header('Content-type: text/html; charset=UTF-8');
- }
- else
- {
- // Redirect so Google knows to index the page without the session ID
- list($request_uri, $phpsessid) = explode('?PHPSESSID=', $_SERVER['REQUEST_URI'], 2);
- header('HTTP/1.1 301 Moved Permanently');
- header('Location: ' . $request_uri);
-
- throw new Exception('Requested URI contains PHPSESSID, redirecting.');
- }
-
- $response = [
- 'meta' => [
- 'status' => $this->module->status,
- 'message' => $this->module->message,
- ],
- ];
-
- if ($this->module->response)
- {
- $response['response'] = $this->module->response;
- }
-
- header('Content-type: application/json');
- $pretty = isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false;
- echo json_encode($response, $pretty);
-
- return ob_get_clean();
- }
- catch (Exception $e)
- {
- return $e->getMessage();
- }
- }
-}
-
diff --git a/src/classes/Module.php b/src/classes/Module.php
index 78ec6af..b3c1917 100644
--- a/src/classes/Module.php
+++ b/src/classes/Module.php
@@ -27,41 +27,6 @@
*/
abstract class Module extends Object
{
- /**
- * Page Title
- *
- * @var string, null by default
- * @todo Abandon for $this->meta
- */
- public $title = null;
-
- /**
- * Meta Description
- *
- * @var string, null by default
- * @todo Abandon for $this->meta
- */
- public $description = null;
-
- /**
- * Meta Keywords (comma separated)
- *
- * @var string, null by default
- * @todo Abandon for $this->meta
- */
- public $keywords = null;
-
- /**
- * Meta Data
- *
- * @var array
- */
- public $meta = [
- 'title' => '',
- 'description' => '',
- 'keywords' => '',
- ];
-
/**
* Secure
*
@@ -72,20 +37,13 @@ abstract class Module extends Object
public $secure = false;
/**
- * Security Settings
+ * Filter
*
- * @var boolean, null by default
+ * Variables to filter.
+ *
+ * @var array
*/
- public $security = null;
-
- /**
- * Method
- *
- * Request methods that are allowed to access the module.
- *
- * @var string or array, null by default
- */
- public $method = null;
+ public $filter = [];
/**
* Validate
@@ -96,46 +54,13 @@ abstract class Module extends Object
*/
public $validate = [];
- /**
- * Template
- *
- * This is the parent template that will be loaded if you are using the
- * 'template' return type in the Display class. Parent templates are found
- * in ./templates/__shared and use the phtml extension.
- *
- * @var string, 'index' by default
- */
- public $template = 'index';
-
- /**
- * Response
- *
- * Array of data that will be rendered as part of the display. This is
- * somewhat of a one way trip as you cannot get the variable unless you
- * reference the response array explicitly, $this->response['variable']
- *
- * @var array
- */
- public $response = [];
-
- /**
- * Output
- *
- * What should the class render as output? This can be a string or an array
- * containing either 'json', 'rss', 'template' or 'xml'. Default is to use
- * templates and if the template is not present, fall back to JSON.
- *
- * @var mixed string or array
- */
- public $output = ['template', 'json'];
-
// @todo
public $status = 200;
public $message = 'OK';
- public $echo = false;
- public $limit = false;
- public $offset = false;
- public $errors = [];
+ public $echo = false;
+ public $limit = false;
+ public $offset = false;
+ public $errors = [];
// @todo if $status != 200 && $message == 'OK' ...
@@ -146,81 +71,10 @@ abstract class Module extends Object
* variable to tell it to automatically run the __default() method. This is
* typically used when a module is called outside of the scope of the
* controller (the registration page calls the login page in this manner.
- *
- * @param boolean $autorun optional flag to autorun __default()
- @ @param boolean $filter optional flag to disable autorun filtering
- * @param boolean $valiate optional flag to disable autorun validation
*/
- public function __construct($autorun = false, $filter = true, $validate = true)
+ public function __construct()
{
parent::__construct(['cache', 'db']);
-
- if ($autorun)
- {
- if ($filter)
- {
- // @todo
- //$this->__filter();
- }
-
- if ($validate)
- {
- $errors = $this->__validate();
-
- if (!$errors)
- {
- // @todo Fatal error perhaps?
- exit('Errors encountered, this is a @todo for form validation when calling modules from inside of modules');
- }
- }
-
- $this->__default();
- }
- }
-
- /**
- * Default "Magic" Method
- *
- * The __default() method is where you want to place any code that needs to
- * be executed at runtime.
- *
- * @abstract
- */
- abstract public function __default();
-
- /**
- * Magic Setter Method
- *
- * Places undefined properties into the response array as part of the
- * module's payload.
- *
- * @param string $variable name of the variable to be set
- * @param mixed $value value of the variable to be set
- */
- public function __set($variable, $value)
- {
- $this->response[$variable] = $value;
- }
-
- /**
- * Magic Getter Method
- *
- * Any variables not defined in this class are set in the response array
- * and default to false if not defined there.
- *
- * @param string $name name of the variable requested
- * @return mixed value of the variable or boolean false
- */
- public function __get($name)
- {
- if (!isset($this->response[$name]))
- {
- return false;
- }
- else
- {
- return $this->response[$name];
- }
}
/**
diff --git a/src/classes/Response.php b/src/classes/Response.php
new file mode 100644
index 0000000..cea8f56
--- /dev/null
+++ b/src/classes/Response.php
@@ -0,0 +1,46 @@
+ $this->status,
+ 'message' => $this->message,
+ ];
+
+ foreach (['echo', 'limit', 'offset', 'errors'] as $variable)
+ {
+ if ($this->$variable)
+ {
+ $meta[$variable] = $this->$variable;
+ }
+ }
+
+ $response = ['meta' => $meta];
+
+ foreach (['response', 'profiler'] as $variable)
+ {
+ if ($this->$variable)
+ {
+ $response[$variable] = $this->$variable;
+ }
+ }
+
+ $pretty = isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false;
+
+ exit(json_encode($response, $pretty));
+ }
+}
+
diff --git a/src/classes/Router.php b/src/classes/Router.php
new file mode 100644
index 0000000..e2519a8
--- /dev/null
+++ b/src/classes/Router.php
@@ -0,0 +1,190 @@
+
+ * @copyright Copyright 2007-2014, Josh Sherman
+ * @license http://www.opensource.org/licenses/mit-license.html
+ * @package PICKLES
+ * @link https://github.com/joshtronic/pickles
+ */
+
+/**
+ * Router Class
+ *
+ * The heavy lifter of PICKLES, makes the calls to get the session and
+ * configuration loaded. Loads modules, serves up user authentication when the
+ * module asks for it, and loads the viewer that the module requested. Default
+ * values are present to make things easier on the user.
+ *
+ * @usage new Router();
+ */
+class Router extends Object
+{
+ /**
+ * Constructor
+ *
+ * To save a few keystrokes, the Controller is executed as part of the
+ * constructor instead of via a method. You either want the Controller or
+ * you don't.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ try
+ {
+ // Catches requests that aren't lowercase
+ $lowercase_request = strtolower($_REQUEST['request']);
+
+ if ($_REQUEST['request'] != $lowercase_request)
+ {
+ // @todo Rework the Browser class to handle the 301 (perhaps redirect301()) to not break other code
+ header('Location: ' . substr_replace($_SERVER['REQUEST_URI'], $lowercase_request, 1, strlen($lowercase_request)), true, 301);
+ throw new Exception();
+ }
+
+ // Grabs the requested page
+ $request = $_REQUEST['request'];
+ $components = explode('/', $request);
+ $version = array_shift($components);
+ $nouns = [];
+ $uids = [];
+
+ // Loops through the components to determine nouns and IDs
+ foreach ($components as $index => $component)
+ {
+ if ($index % 2)
+ {
+ $uids[end($nouns)] = $component;
+ }
+ else
+ {
+ $nouns[] = $component;
+ }
+ }
+
+ array_unshift($nouns, $version);
+
+ $class = implode('_', $nouns);
+
+ array_unshift($nouns, SITE_MODULE_PATH);
+
+ $filename = implode('/', $nouns) . '.php';
+
+ if (file_exists($filename))
+ {
+ if (class_exists($class))
+ {
+ $resource = new $class($uids);
+
+ // Determines if we need to serve over HTTP or HTTPS
+ if ($resource->secure == false && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'])
+ {
+ header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
+ throw new Exception();
+ }
+ elseif ($resource->secure == true && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == false))
+ {
+ header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
+ throw new Exception();
+ }
+
+ // Checks for the PHPSESSID in the query string
+ if (stripos($_SERVER['REQUEST_URI'], '?PHPSESSID=') === false)
+ {
+ // XHTML compliancy stuff
+ // @todo Wonder if this could be yanked now that we're in HTML5 land
+ ini_set('arg_separator.output', '&');
+ ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,input=src,fieldset=');
+
+ // @todo Will want to generate the header based on if we're pushing documentation or API
+ header('Content-type: text/html; charset=UTF-8');
+ // header('Content-type: application/json');
+ //header('Content-type: application/json; charset=UTF-8');
+ }
+ else
+ {
+ // Redirect so Google knows to index the page without the session ID
+ list($request_uri, $phpsessid) = explode('?PHPSESSID=', $_SERVER['REQUEST_URI'], 2);
+ header('HTTP/1.1 301 Moved Permanently');
+ header('Location: ' . $request_uri);
+
+ throw new Exception('Requested URI contains PHPSESSID, redirecting.');
+ }
+
+ // Gets the profiler status
+ $profiler = $this->config->pickles['profiler'];
+ $profiler = $profiler === true || stripos($profiler, 'timers') !== false;
+
+ $method = strtolower($_SERVER['REQUEST_METHOD']);
+
+ if (method_exists($resource, $method))
+ {
+ // Starts a timer before the resource is executed
+ if ($profiler)
+ {
+ Profiler::timer('resource ' . $method);
+ }
+
+ $response = new Response();
+
+ if ($resource->validate)
+ {
+ $validation_errors = $resource->__validate();
+
+ if ($validation_errors)
+ {
+ $response->status = 400;
+ $response->message = implode(' ', $validation_errors);
+ }
+ }
+
+ if ($response->status == 200)
+ {
+ $resource_return = $resource->$method();
+
+ if ($resource_return)
+ {
+ $response->response = $resource_return;
+ }
+ }
+
+ // Stops the resource timer
+ if ($profiler)
+ {
+ Profiler::timer('resource ' . $method);
+ }
+
+ $response->respond();
+ }
+ else
+ {
+ throw new Exception('Missing method');
+ }
+ }
+ else
+ {
+ throw new Exception('Missing class');
+ }
+ }
+ else
+ {
+ throw new Exception('Missing file');
+ }
+ }
+ catch (Exception $e)
+ {
+ // @todo
+ exit('fuuuu');
+ $output = $e->getMessage();
+ }
+ }
+}
+