Merge branch 'maint/7.0'
[ninja.git] / system / helpers / request.php
blob4a4643872898c93d768f72e14b10101f56fe4f37
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * Request helper class.
5 * $Id: request.php 3917 2009-01-21 03:06:22Z zombor $
7 * @package Core
8 * @author Kohana Team
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
12 class request {
14 // Possible HTTP methods
15 protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
17 // Content types from client's HTTP Accept request header (array)
18 protected static $accept_types;
20 /**
21 * Returns the HTTP referrer, or the default if the referrer is not set.
23 * @param mixed default to return
24 * @return string
26 public static function referrer($default = FALSE)
28 if ( ! empty($_SERVER['HTTP_REFERER']))
30 // Set referrer
31 $ref = $_SERVER['HTTP_REFERER'];
33 if (strpos($ref, url::base(FALSE)) === 0)
35 // Remove the base URL from the referrer
36 $ref = substr($ref, strlen(url::base(TRUE)));
40 return isset($ref) ? $ref : $default;
43 /**
44 * Returns the current request protocol, based on $_SERVER['https']. In CLI
45 * mode, NULL will be returned.
47 * @return string
49 public static function protocol()
51 if (PHP_SAPI === 'cli')
53 return NULL;
55 elseif ( ! empty($_SERVER['HTTPS']) AND $_SERVER['HTTPS'] === 'on')
57 return 'https';
59 else
61 return 'http';
65 /**
66 * Tests if the current request is an AJAX request by checking the X-Requested-With HTTP
67 * request header that most popular JS frameworks now set for AJAX calls.
69 * @return boolean
71 public static function is_ajax()
73 return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
76 /**
77 * Returns current request method.
79 * @throws Kohana_Exception in case of an unknown request method
80 * @return string
82 public static function method()
84 $method = strtolower($_SERVER['REQUEST_METHOD']);
86 if ( ! in_array($method, self::$http_methods))
87 throw new Kohana_Exception('request.unknown_method', $method);
89 return $method;
92 /**
93 * Returns boolean of whether client accepts content type.
95 * @param string content type
96 * @param boolean set to TRUE to disable wildcard checking
97 * @return boolean
99 public static function accepts($type = NULL, $explicit_check = FALSE)
101 request::parse_accept_header();
103 if ($type === NULL)
104 return self::$accept_types;
106 return (request::accepts_at_quality($type, $explicit_check) > 0);
110 * Compare the q values for given array of content types and return the one with the highest value.
111 * If items are found to have the same q value, the first one encountered in the given array wins.
112 * If all items in the given array have a q value of 0, FALSE is returned.
114 * @param array content types
115 * @param boolean set to TRUE to disable wildcard checking
116 * @return mixed string mime type with highest q value, FALSE if none of the given types are accepted
118 public static function preferred_accept($types, $explicit_check = FALSE)
120 // Initialize
121 $mime_types = array();
122 $max_q = 0;
123 $preferred = FALSE;
125 // Load q values for all given content types
126 foreach (array_unique($types) as $type)
128 $mime_types[$type] = request::accepts_at_quality($type, $explicit_check);
131 // Look for the highest q value
132 foreach ($mime_types as $type => $q)
134 if ($q > $max_q)
136 $max_q = $q;
137 $preferred = $type;
141 return $preferred;
145 * Returns quality factor at which the client accepts content type.
147 * @param string content type (e.g. "image/jpg", "jpg")
148 * @param boolean set to TRUE to disable wildcard checking
149 * @return integer|float
151 public static function accepts_at_quality($type = NULL, $explicit_check = FALSE)
153 request::parse_accept_header();
155 // Normalize type
156 $type = strtolower((string) $type);
158 // General content type (e.g. "jpg")
159 if (strpos($type, '/') === FALSE)
161 // Don't accept anything by default
162 $q = 0;
164 // Look up relevant mime types
165 foreach ((array) Kohana::config('mimes.'.$type) as $type)
167 $q2 = request::accepts_at_quality($type, $explicit_check);
168 $q = ($q2 > $q) ? $q2 : $q;
171 return $q;
174 // Content type with subtype given (e.g. "image/jpg")
175 $type = explode('/', $type, 2);
177 // Exact match
178 if (isset(self::$accept_types[$type[0]][$type[1]]))
179 return self::$accept_types[$type[0]][$type[1]];
181 // Wildcard match (if not checking explicitly)
182 if ($explicit_check === FALSE AND isset(self::$accept_types[$type[0]]['*']))
183 return self::$accept_types[$type[0]]['*'];
185 // Catch-all wildcard match (if not checking explicitly)
186 if ($explicit_check === FALSE AND isset(self::$accept_types['*']['*']))
187 return self::$accept_types['*']['*'];
189 // Content type not accepted
190 return 0;
194 * Parses client's HTTP Accept request header, and builds array structure representing it.
196 * @return void
198 protected static function parse_accept_header()
200 // Run this function just once
201 if (self::$accept_types !== NULL)
202 return;
204 // Initialize accept_types array
205 self::$accept_types = array();
207 // No HTTP Accept header found
208 if (empty($_SERVER['HTTP_ACCEPT']))
210 // Accept everything
211 self::$accept_types['*']['*'] = 1;
212 return;
215 // Remove linebreaks and parse the HTTP Accept header
216 foreach (explode(',', str_replace(array("\r", "\n"), '', $_SERVER['HTTP_ACCEPT'])) as $accept_entry)
218 // Explode each entry in content type and possible quality factor
219 $accept_entry = explode(';', trim($accept_entry), 2);
221 // Explode each content type (e.g. "text/html")
222 $type = explode('/', $accept_entry[0], 2);
224 // Skip invalid content types
225 if ( ! isset($type[1]))
226 continue;
228 // Assume a default quality factor of 1 if no custom q value found
229 $q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1;
231 // Populate accept_types array
232 if ( ! isset(self::$accept_types[$type[0]][$type[1]]) OR $q > self::$accept_types[$type[0]][$type[1]])
234 self::$accept_types[$type[0]][$type[1]] = $q;
239 } // End request