summaryrefslogtreecommitdiff
path: root/src/lib/View.class.php
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2011-09-04 20:40:45 -0400
committerLuke Shumaker <LukeShu@sbcglobal.net>2011-09-04 20:40:45 -0400
commit103332a30f8976fcc224c8f55dc23aba7b99e578 (patch)
tree32337915884fb6217007d569636f418130757df3 /src/lib/View.class.php
parentbca1b20b4fc6dca04368f8c03b5e1faeec5af7d3 (diff)
New router and view selector engine magic coolness.
Diffstat (limited to 'src/lib/View.class.php')
-rw-r--r--src/lib/View.class.php127
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);
+ }
+}