diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2011-09-04 20:40:45 -0400 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2011-09-04 20:40:45 -0400 |
commit | 103332a30f8976fcc224c8f55dc23aba7b99e578 (patch) | |
tree | 32337915884fb6217007d569636f418130757df3 /src/lib/View.class.php | |
parent | bca1b20b4fc6dca04368f8c03b5e1faeec5af7d3 (diff) |
New router and view selector engine magic coolness.
Diffstat (limited to 'src/lib/View.class.php')
-rw-r--r-- | src/lib/View.class.php | 127 |
1 files changed, 127 insertions, 0 deletions
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 @@ +<?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; + 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(); + 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); + } +} |