From 103332a30f8976fcc224c8f55dc23aba7b99e578 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 4 Sep 2011 20:40:45 -0400 Subject: New router and view selector engine magic coolness. --- index.php | 24 +++++--- src/lib/Controller.class.php | 61 +++------------------ src/lib/Mime.class.php | 10 ++-- src/lib/Router.class.php | 4 +- src/lib/View.class.php | 127 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 69 deletions(-) create mode 100644 src/lib/View.class.php diff --git a/index.php b/index.php index c8f72a6..3a3a646 100644 --- a/index.php +++ b/index.php @@ -7,28 +7,34 @@ define('LIBPATH', BASEPATH.'/src/lib'.PATH_SEPARATOR.BASEPATH.'/src/ext') define('MODELPATH', BASEPATH.'/src/models'); define('VIEWPATH', BASEPATH.'/src/views');// views are not objects define('CONTROLLERPATH', BASEPATH.'/src/controllers'); +define('PLUGINPATH', BASEPATH.'/src/plugins'); // Modify our include path to catch our class files. set_include_path(get_include_path() .PATH_SEPARATOR.LIBPATH .PATH_SEPARATOR.MODELPATH .PATH_SEPARATOR.CONTROLLERPATH + .PATH_SEPARATOR.PLUGINPATH ); // Figure what page is trying to be loaded. Don't worry if we're // looking for a real file, if the requested page exists as a real // file, .htaccess won't even let us load this file. @$PAGE_RAW = $_GET['p']; -preg_match('@(.*)(\.([^./]))?@', $PAGE_RAW, $matches); -@$PAGE = $matches[1]; -@$EXT = $matches[3]; -@$ACCEPT = $_SERVER['HTTP_ACCEPT']; -if ($PAGE=='') - $PAGE = 'index'; -if ($EXT!='') - $ACCEPT = "$EXT, $ACCEPT"; +$PAGE_PARTS = explode('/', $PAGE_RAW); +$FILE = array_pop($PAGE_PARTS); +$regex = '@([^.]*)\\.(.*)@'; +if (preg_match($regex, $FILE, $matches)) { + @$FILE = $matches[1]; + @$EXT = $matches[2]; + array_push($PAGE_PARTS, $FILE); + $PAGE = implode('/', $PAGE_PARTS); +} else { + $PAGE = $PAGE_RAW; +} +if ($PAGE=='') $PAGE = 'index'; define('PAGE', $PAGE); unset($PAGE); -define('ACCEPT', $ACCEPT); unset($ACCEPT); +define('PAGE_EXT', $EXT); unset($EXT); // Get ready require_once('Model.class.php'); diff --git a/src/lib/Controller.class.php b/src/lib/Controller.class.php index 592ea2c..f9ed59d 100644 --- a/src/lib/Controller.class.php +++ b/src/lib/Controller.class.php @@ -1,65 +1,20 @@ getQuality($mime); - if (isset($final[$ext])) { - $quality = max($final[$ext], $quality); - } - $prefs[$ext] = $quality; - } - } - - // Sort $prefs such that the entry with the highest value will - // appear first. - arsort($prefs); - - // Return the first entry in $prefs. - foreach ($prefs as $ext => $quality) { - return VIEWPATH."/pages/$view.$ext.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) { - global $VARS, $mm; + global $mm; + if ($vars===null) { $vars = array(); } - $VARS = $vars; - $VARS['template'] = $mm->template(); - include($this->_resolveView($view)); - unset($VARS); + $vars['template'] = $mm->template(); + + $obj = new View($view); + $obj->show($vars); } // Here be default handlers //////////////////////////////////////////// diff --git a/src/lib/Mime.class.php b/src/lib/Mime.class.php index 40562b4..f37c1eb 100644 --- a/src/lib/Mime.class.php +++ b/src/lib/Mime.class.php @@ -2,13 +2,14 @@ class Mime { public static $mimes = array( - 'csv' => array('text/x-comma-separated-values', + 'csv' => array( + 'text/csv', 'text/x-csv', + 'text/x-comma-separated-values', 'text/comma-separated-values', - 'application/octet-stream', - 'application/vnd.ms-excel', - 'text/x-csv', 'text/csv', 'application/csv', + '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'), @@ -18,7 +19,6 @@ class Mime { 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'css' => 'text/css', - 'html' => 'text/html', 'htm' => 'text/html', 'txt' => 'text/plain', 'json' => array('application/json', 'text/json') diff --git a/src/lib/Router.class.php b/src/lib/Router.class.php index 459034d..238e3f8 100644 --- a/src/lib/Router.class.php +++ b/src/lib/Router.class.php @@ -27,8 +27,8 @@ class Router { $dirs = explode(PATH_SEPARATOR, $controllerpath); foreach ($dirs as $dir) { // Find all files in $dir with the ext `.class.php' - $controllerfiles = glob($dir.'/*.class.php'); - foreach ($controllerfiles as $file) { + $files = glob($dir.'/*.class.php'); + foreach ($files as $file) { // and include them require_once($file); } diff --git a/src/lib/View.class.php b/src/lib/View.class.php new file mode 100644 index 0000000..ea5ad60 --- /dev/null +++ b/src/lib/View.class.php @@ -0,0 +1,127 @@ +extensions = array(); + foreach ($files as $file) { + $ext = preg_replace('@[^.]*\.(.*)\.php$@','$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]); + + global $VARS; + $VARS = $vars; + include($file); + unset($VARS); + } +} -- cgit v1.2.3