diff options
Diffstat (limited to 'lpf/lib/View.class.php')
-rw-r--r-- | lpf/lib/View.class.php | 135 |
1 files changed, 135 insertions, 0 deletions
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); + } +} |