diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2012-01-07 08:21:00 -0800 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2012-01-07 10:20:28 -0800 |
commit | 464f4d3497617fadb9d7752868f1175849cfa6d2 (patch) | |
tree | 0771bd935b30971bf2c244b6f158ed7496b644e5 /lpf/lib | |
parent | 3d64793a1ee45857856be1cd71c3a0a040a3e869 (diff) |
Refactor to separate the framework from the app; drop message stuff, this app is just user management. Add a json view for individual usersHEADmaster
Diffstat (limited to 'lpf/lib')
-rw-r--r-- | lpf/lib/Controller.class.php | 30 | ||||
-rw-r--r-- | lpf/lib/Mime.class.php | 45 | ||||
-rw-r--r-- | lpf/lib/Model.class.php | 9 | ||||
-rw-r--r-- | lpf/lib/Router.class.php | 110 | ||||
-rw-r--r-- | lpf/lib/View.class.php | 135 |
5 files changed, 329 insertions, 0 deletions
diff --git a/lpf/lib/Controller.class.php b/lpf/lib/Controller.class.php new file mode 100644 index 0000000..05736ee --- /dev/null +++ b/lpf/lib/Controller.class.php @@ -0,0 +1,30 @@ +<?php + +class Controller { + /** + * Show a $view, in the most appropriate format (according to file + * extension and HTTP Accept header). Pass the array $vars to the view. + */ + protected function showView($view, $vars=null) { + if ($vars===null) { $vars = array(); } + + $obj = new View($view); + $obj->show($vars); + } + + // Here be default handlers //////////////////////////////////////////// + + public function index($routed, $remainder) { + header('Content-type: text/plain'); + echo " == Generic Controller Index == \n\n"; + $routed_str = implode('/', $routed); + $remainder_str = implode('/', $remainder); + echo "Full path: $routed_str/$remainder_str\n"; + echo "Controller path: $routed_str\n"; + echo "Remainder path: $remainder_str\n"; + } + public function http404($routed, $remainder) { + $this->showView('http404', array('routed'=>$routed, + 'remainder'=>$remainder)); + } +} diff --git a/lpf/lib/Mime.class.php b/lpf/lib/Mime.class.php new file mode 100644 index 0000000..f37c1eb --- /dev/null +++ b/lpf/lib/Mime.class.php @@ -0,0 +1,45 @@ +<?php + +class Mime { + public static $mimes = array( + 'csv' => array( + 'text/csv', 'text/x-csv', + 'text/x-comma-separated-values', + 'text/comma-separated-values', + 'application/csv', + 'application/excel', 'application/vnd.msexcel'), + 'xhtml' => array('text/html', 'application/xhtml+xml'), + 'html' => array('text/html', 'application/xhtml+xml'), + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => array('image/jpeg', 'image/pjpeg'), + 'jpg' => array('image/jpeg', 'image/pjpeg'), + 'jpe' => array('image/jpeg', 'image/pjpeg'), + 'png' => array('image/png', 'image/x-png'), + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'css' => 'text/css', + 'htm' => 'text/html', + 'txt' => 'text/plain', + 'json' => array('application/json', 'text/json') + ); + + public static function ext2mime($ext) { + $mimes = self::$mimes; + $mime = $mimes[$ext]; + if (!is_array($mime)) $mime = array($mime); + return $mime; + } + public static function mime2ext($my_mime) { + $ret = array(); + foreach (self::mimes as $ext => $mime) { + if (is_array($mime)) { + $match = in_array($my_mime, $mime); + } else { + $match = $my_mime==$mime; + } + if ($match) $ret[] = $ext; + } + return $ret; + } +}
\ No newline at end of file diff --git a/lpf/lib/Model.class.php b/lpf/lib/Model.class.php new file mode 100644 index 0000000..0cce525 --- /dev/null +++ b/lpf/lib/Model.class.php @@ -0,0 +1,9 @@ +<?php +require_once('Database.class.php'); + +abstract class Model { + protected $db; + public function __construct() { + $this->db = Database::getInstance(); + } +} diff --git a/lpf/lib/Router.class.php b/lpf/lib/Router.class.php new file mode 100644 index 0000000..238e3f8 --- /dev/null +++ b/lpf/lib/Router.class.php @@ -0,0 +1,110 @@ +<?php + +require_once('Controller.class.php'); + +class Router { + /** + * Array mapping URIs to controllers. + * A controller may register itself either by using + * Router::register($URI, $controller[, $function]); + * or by adding itself to the $ROUTER global. + * + * The default here just gives us a 404 handler. + */ + private $routes = array('/*' => 'Http404'); + + /** + * Instantiate a router that looks for controllers in $controllerpath. + */ + public function Router($controllerpath) { + // create a $ROUTES global that can be used to set up our + // $this->routes. + global $ROUTES; + $ROUTES = $this->routes; + + // Split $controllerpath into directories, and load the + // controllers in each. + $dirs = explode(PATH_SEPARATOR, $controllerpath); + foreach ($dirs as $dir) { + // Find all files in $dir with the ext `.class.php' + $files = glob($dir.'/*.class.php'); + foreach ($files as $file) { + // and include them + require_once($file); + } + } + + $this->routes = $ROUTES; + unset($ROUTES); + } + + /** + * Route the page at the relative URL $page to the appropriate + * controller, and call the appropriate function. + */ + public function route($page) { + $parts = explode('/', $page); + $length = count($parts); // the # of segments in $controllerpart + + // if $page ends in "/", strip that off + if ($parts[$length-1]=='') { + array_pop($parts); + $length--; + } + + $controllerpart = implode('/', $parts); + + // Keep shortening $controllerpart until it matches something in + // $this->routes. The shortest it will ever become is '/*'. + // If no key exists for '/*', that's an infinite loop. + // Fortunately, the default value of $this->routes directs '/*' + // to the Http404 controller. + while(!isset($this->routes[$controllerpart])) { + $some_parts = array_slice($parts, 0, $length); + $controllerpart = implode('/', $some_parts).'/*'; + $length--; + } + $length++; + + // Figure what function to call on what controller + // Grammar Nazi Warning: `what' or `which'? + $controller = $this->routes[$controllerpart]; + if (strpos($controller, '->')===false) { + // imply function + $function = $parts[$length]; + } else { + preg_match('/(.*)->(.*)/', $controller, $matches); + $controller = $matches[1]; + $function = $matches[2]; + } + + // Default to the `index' function, provided by all controllers + if ($function=='') { + $function = 'index'; + } + + // We will pass these arrays to the function. + $routed = array_slice($parts, 0, $length); + $remainder = array_slice($parts, $length); + + // Finally, run the controller + $obj = new $controller(); + if (in_array($function, get_class_methods($obj))) { + call_user_func(array($obj, $function), + $routed, $remainder); + } else { + $obj->http404($routed, $remainder); + } + } + + /** + * This is to allow controllers to register themselves to the router. + * If $function=='', then the function will be determined by the segment + * to the right of the last segment in $path + */ + public static function register($path, $controller, $function='') { + $str = $controller.(($function=='')?'':'->'.$function); + global $ROUTES; + $ROUTES[$path] = $str; + } +}
\ No newline at end of file diff --git a/lpf/lib/View.class.php b/lpf/lib/View.class.php new file mode 100644 index 0000000..d7a21d3 --- /dev/null +++ b/lpf/lib/View.class.php @@ -0,0 +1,135 @@ +<?php + +require_once('Mime.class.php'); +require_once('HTTP_Accept.class.php'); + +/** + * A class to handle loading and evaluating the appropriateness of different + * views. + * + * Depends on the state of the following variables/constants: + * PAGE_EXT + * VIEWPATH + * $_SERVER['HTTP_ACCEPT'] + */ +class View { + private $extensions = array(); + private $ext = ''; + private $view = ''; + + /** + * Return the filename of the view file with extension $ext + */ + private static function filename($view, $ext) { + return VIEWPATH."/pages/$view.$ext.php"; + } + + /** + * Choose between $extensions, which all have equal quality. + */ + private function chooseBetweenEquals($extensions) { + if (count($extensions)<1) return false; + $pref = array('html'); + foreach ($pref as $ext) { + if (in_array($ext, $extensions)) return $ext; + } + return $extensions[0]; // XXX: Worst. Solution. Ever. + } + + /** + * Find the best available extension to use, based on file extension and + * HTTP 'Accept' headers. + */ + private function chooseExtension($view) { + // Make a list of candidate extensions for this view. + $files = glob(self::filename($view, '*')); + $this->extensions = array(); + $regex = '@'.preg_quote(VIEWPATH,'@').'[^.]*\.(.*)\.php$@'; + foreach ($files as $file) { + $ext = preg_replace($regex, '$1', $file); + $this->extensions[] = $ext; + } + if (count($this->extensions)<1) return false; + + if (PAGE_EXT != '') { + // First, do a check if we can just return requested + // file extension: + if (in_array(PAGE_EXT, $this->extensions)) { + return PAGE_EXT; + } + + // Check for other extensions with the same mime type as + // the requested: + $accept_str = implode(', ', Mime::ext2mime(PAGE_EXT)); + $extensions = $this->parseAccept($view, $accept_str); + if ($ext = $this->chooseBetweenEquals($extensions)) return $ext; + } + + // Check for other extensions based on HTTP 'Accept' headers: + $accept_str = $_SERVER['HTTP_ACCEPT']; + $extensions = $this->parseAccept($view, $accept_str); + if ($ext = $this->chooseBetweenEquals($extensions)) return $ext; + + // Well, all the good options failed, so let's see what we've + // got left: + $extensions = $this->extensions; + return $this->chooseBetweenEquals($extensions); + + } + + private function parseAccept($view, $accept_str) { + // $prefs is a associative array where the key is the file + // extension, and the value is how much we like that extension. + // Higher numbers are better. + $prefs = array(); + + $accept = new HTTP_Accept($accept_str); + + // Loop through the candidate views, and record how much we + // like each. + foreach ($this->extensions as $ext) { + $mimes = Mime::ext2mime($ext); + foreach ($mimes as $mime) { + $quality = $accept->getQuality($mime); + if (isset($prefs[$ext])) { + $quality = max($prefs[$ext], $quality); + } + $prefs[$ext] = $quality; + } + } + + // Create an array of all extensions tied for the top quality. + $ret = array(); + $top_quality = 0.001;// minimum acceptable according to RFC 2616 + foreach ($prefs as $ext => $quality) { + if ($quality > $top_quality) { + $top_quality = $quality; + $ret = array(); + } + if ($quality == $top_quality) { + $ret[] = $ext; + } + } + return $ret; + } + + public function __construct($view) { + $this->ext = $this->chooseExtension($view); + $this->view = $view; + } + + public function show($vars) { + $file = self::filename($this->view, $this->ext); + $mimes = Mime::ext2mime($this->ext); + + header('Content-type: '.$mimes[0]); + + require_once(VIEWPATH.'/Template.class.php'); + $vars['template'] = new Template(); + + global $VARS; + $VARS = $vars; + include($file); + unset($VARS); + } +} |