1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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);
}
}
|