File indexing completed on 2025-03-09 05:22:13
0001 <?php 0002 0003 /** 0004 * Flooer Framework 0005 * 0006 * LICENSE: BSD License (2 Clause) 0007 * 0008 * @category Flooer 0009 * @package Flooer_Http 0010 * @subpackage Request 0011 * @author Akira Ohgaki <akiraohgaki@gmail.com> 0012 * @copyright Akira Ohgaki 0013 * @license https://opensource.org/licenses/BSD-2-Clause BSD License (2 Clause) 0014 * @link https://github.com/akiraohgaki/flooer 0015 */ 0016 0017 /** 0018 * Usage 0019 * 0020 * $request = new Flooer_Http_Request(); 0021 * $request->addUriMapRule( 0022 * '^tags/(.+)/(.*)', 0023 * 'key=$1¶ms=$2', 0024 * 'params' 0025 * ); 0026 * $request->addUriMapRule( 0027 * array('^TAGS/(.+)/(.*)', '#', 'i'), 0028 * 'key=$1¶ms=$2', 0029 * array('params', '/') 0030 * ); 0031 * $request->mapUri(); 0032 * $value = $request->key; 0033 */ 0034 0035 /** 0036 * HTTP request class 0037 * 0038 * @category Flooer 0039 * @package Flooer_Http 0040 * @subpackage Request 0041 * @author Akira Ohgaki <akiraohgaki@gmail.com> 0042 */ 0043 class Flooer_Http_Request 0044 { 0045 0046 /** 0047 * Configuration options 0048 * 0049 * @var array 0050 */ 0051 protected $_config = array( 0052 'importPredefinedVars' => true, 0053 'mapUri' => false, 0054 'uriMapRules' => array() 0055 ); 0056 0057 /** 0058 * Overloaded properties 0059 * 0060 * @var array 0061 */ 0062 protected $_properties = array(); 0063 0064 /** 0065 * Constructor 0066 * 0067 * @param array $config 0068 * @return void 0069 */ 0070 public function __construct(array $config = null) 0071 { 0072 if ($config) { 0073 $this->_config = $config + $this->_config; 0074 } 0075 if ($this->_config['importPredefinedVars']) { 0076 $this->importPredefinedVars(); 0077 } 0078 if ($this->_config['mapUri']) { 0079 $this->mapUri(); 0080 } 0081 } 0082 0083 /** 0084 * Magic method to set a property 0085 * 0086 * @param string $key 0087 * @param mixed $value 0088 * @return void 0089 */ 0090 public function __set($key, $value) 0091 { 0092 $this->_properties[$key] = $value; 0093 } 0094 0095 /** 0096 * Magic method to get a property 0097 * 0098 * @param string $key 0099 * @return mixed 0100 */ 0101 public function __get($key) 0102 { 0103 if (isset($this->_properties[$key])) { 0104 return $this->_properties[$key]; 0105 } 0106 return null; 0107 } 0108 0109 /** 0110 * Magic method to check a property 0111 * 0112 * @param string $key 0113 * @return bool 0114 */ 0115 public function __isset($key) 0116 { 0117 return isset($this->_properties[$key]); 0118 } 0119 0120 /** 0121 * Magic method to unset a property 0122 * 0123 * @param string $key 0124 * @return void 0125 */ 0126 public function __unset($key) 0127 { 0128 unset($this->_properties[$key]); 0129 } 0130 0131 /** 0132 * Import a predefined variables 0133 * 0134 * @return void 0135 */ 0136 public function importPredefinedVars() 0137 { 0138 switch ($_SERVER['REQUEST_METHOD']) { 0139 case 'GET': 0140 if (!empty($_GET)) { 0141 $this->_properties += $_GET; 0142 } 0143 break; 0144 case 'POST': 0145 if (!empty($_POST)) { 0146 $this->_properties += $_POST; 0147 } 0148 break; 0149 case 'PUT': 0150 $contentType = $this->getHeader('Content-Type'); 0151 if (!empty($contentType) 0152 && strpos(strtolower($contentType), 'application/x-www-form-urlencoded') !== false 0153 ) { 0154 parse_str($this->getRawBody(), $put); 0155 if (!empty($put)) { 0156 $this->_properties += $put; 0157 } 0158 } 0159 break; 0160 case 'DELETE': 0161 // Continue to default 0162 default: 0163 if (!empty($_SERVER['QUERY_STRING'])) { 0164 parse_str($_SERVER['QUERY_STRING'], $params); 0165 if (!empty($params)) { 0166 $this->_properties += $params; 0167 } 0168 } 0169 break; 0170 } 0171 } 0172 0173 /** 0174 * URI mapping 0175 * 0176 * @return void 0177 */ 0178 public function mapUri() 0179 { 0180 $uri = $this->getUri(); 0181 if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) { 0182 $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME'])); 0183 } 0184 else if (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0) { 0185 $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); 0186 } 0187 $uri = trim(preg_replace("/^([^\?]*).*/", "$1", $uri), '/'); 0188 if ($uri !== '' && $this->_config['uriMapRules']) { 0189 foreach ($this->_config['uriMapRules'] as $rule) { 0190 $pattern = null; 0191 $patternDelimiter = '#'; 0192 $patternModifiers = null; 0193 $replacement = null; 0194 $addition = null; 0195 $additionDelimiter = '/'; 0196 if (!empty($rule[0])) { 0197 if (is_array($rule[0])) { 0198 if (!empty($rule[0][0])) { 0199 $pattern = $rule[0][0]; 0200 } 0201 if (!empty($rule[0][1])) { 0202 $patternDelimiter = $rule[0][1]; 0203 } 0204 if (!empty($rule[0][2])) { 0205 $patternModifiers = $rule[0][2]; 0206 } 0207 } 0208 else { 0209 $pattern = $rule[0]; 0210 } 0211 $pattern = $patternDelimiter 0212 . $pattern 0213 . $patternDelimiter 0214 . $patternModifiers; 0215 } 0216 if (!empty($rule[1])) { 0217 $replacement = $rule[1]; 0218 } 0219 if (!empty($rule[2])) { 0220 if (is_array($rule[2])) { 0221 if (!empty($rule[2][0])) { 0222 $addition = $rule[2][0]; 0223 } 0224 if (!empty($rule[2][1])) { 0225 $additionDelimiter = $rule[2][1]; 0226 } 0227 } 0228 else { 0229 $addition = $rule[2]; 0230 } 0231 } 0232 if ($pattern && $replacement && preg_match($pattern, $uri)) { 0233 $query = preg_replace($pattern, $replacement, $uri); 0234 parse_str($query, $params); 0235 if ($addition && !empty($params[$addition])) { 0236 $kvPairs = explode( 0237 $additionDelimiter, 0238 trim($params[$addition], $additionDelimiter) 0239 ); 0240 for ($i = 0; $i < count($kvPairs); $i++) { 0241 $n = $i + 1; 0242 if (isset($kvPairs[$n])) { 0243 $params[$kvPairs[$i]] = $kvPairs[$n]; 0244 $i = $n; 0245 } 0246 else { 0247 $params[$kvPairs[$i]] = null; 0248 } 0249 } 0250 } 0251 $this->_properties = $params + $this->_properties; 0252 break; 0253 } 0254 } 0255 } 0256 } 0257 0258 /** 0259 * Set a URI mapping rules 0260 * 0261 * @param array $uriMapRules 0262 * @return void 0263 */ 0264 public function setUriMapRules(array $uriMapRules) 0265 { 0266 $this->_config['uriMapRules'] = $uriMapRules; 0267 } 0268 0269 /** 0270 * Get a URI mapping rules 0271 * 0272 * @return array 0273 */ 0274 public function getUriMapRules() 0275 { 0276 return $this->_config['uriMapRules']; 0277 } 0278 0279 /** 0280 * Add a URI mapping rule 0281 * 0282 * @param array|string $pattern Regex 0283 * @param string $replacement Query string 0284 * @param array|string $addition Needle to parse as a key-value pairs 0285 * @return void 0286 */ 0287 public function addUriMapRule($pattern, $replacement, $addition = null) 0288 { 0289 $this->_config['uriMapRules'][] = array($pattern, $replacement, $addition); 0290 } 0291 0292 /** 0293 * Check for a secure connection 0294 * 0295 * @return bool 0296 */ 0297 public function isSecure() 0298 { 0299 if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { 0300 return true; 0301 } 0302 return false; 0303 } 0304 0305 /** 0306 * Check for a XML HTTP request 0307 * 0308 * @return bool 0309 */ 0310 public function isXmlHttpRequest() 0311 { 0312 if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) 0313 && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' 0314 ) { 0315 return true; 0316 } 0317 return false; 0318 } 0319 0320 /** 0321 * Get a request method 0322 * 0323 * @param bool $override 0324 * @return string 0325 */ 0326 public function getMethod($override = false) 0327 { 0328 $method = $_SERVER['REQUEST_METHOD']; 0329 if ($override 0330 && !empty($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) 0331 ) { 0332 $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); 0333 } 0334 return $method; 0335 } 0336 0337 /** 0338 * Get a request URI 0339 * 0340 * @return string|null 0341 */ 0342 public function getUri() 0343 { 0344 $uri = null; 0345 // IIS Mod-Rewrite module 0346 if (!empty($_SERVER['HTTP_X_ORIGINAL_URL'])) { 0347 $uri = $_SERVER['HTTP_X_ORIGINAL_URL']; 0348 } 0349 // IIS Isapi_Rewrite module 0350 else if (!empty($_SERVER['HTTP_X_REWRITE_URL'])) { 0351 $uri = $_SERVER['HTTP_X_REWRITE_URL']; 0352 } 0353 // Common 0354 else if (!empty($_SERVER['REQUEST_URI'])) { 0355 $uri = $_SERVER['REQUEST_URI']; 0356 } 0357 // IIS and PHP-CGI 0358 else if (!empty($_SERVER['PATH_INFO'])) { 0359 if ($_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME']) { 0360 $uri = $_SERVER['PATH_INFO']; 0361 } 0362 else { 0363 $uri = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO']; 0364 } 0365 if (!empty($_SERVER['QUERY_STRING'])) { 0366 $uri .= '?' . $_SERVER['QUERY_STRING']; 0367 } 0368 } 0369 else if (!empty($_SERVER['ORIG_PATH_INFO'])) { 0370 if ($_SERVER['ORIG_PATH_INFO'] == $_SERVER['SCRIPT_NAME']) { 0371 $uri = $_SERVER['ORIG_PATH_INFO']; 0372 } 0373 else { 0374 $uri = $_SERVER['SCRIPT_NAME'] . $_SERVER['ORIG_PATH_INFO']; 0375 } 0376 if (!empty($_SERVER['QUERY_STRING'])) { 0377 $uri .= '?' . $_SERVER['QUERY_STRING']; 0378 } 0379 } 0380 return $uri; 0381 } 0382 0383 /** 0384 * Get a request header 0385 * 0386 * @param string $name 0387 * @return string|null 0388 */ 0389 public function getHeader($name) 0390 { 0391 $header = null; 0392 $key = 'HTTP_' . str_replace('-', '_', strtoupper($name)); 0393 if (!empty($_SERVER[$key])) { 0394 $header = $_SERVER[$key]; 0395 } 0396 else if (function_exists('apache_request_headers')) { 0397 $headers = array_change_key_case(apache_request_headers(), CASE_LOWER); 0398 $key = strtolower($name); 0399 if (!empty($headers[$key])) { 0400 $header = $headers[$key]; 0401 } 0402 } 0403 return $header; 0404 } 0405 0406 /** 0407 * Get an accept language 0408 * 0409 * @param bool $subset 0410 * @return string|null 0411 */ 0412 public function getAcceptLanguage($subset = true) 0413 { 0414 $language = null; 0415 if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { 0416 preg_match( 0417 "/^([a-z]{2})(\-|\_)?([a-z]{2})?\,?/i", 0418 $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0419 $matches 0420 ); 0421 if ($subset && !empty($matches[1]) && !empty($matches[3])) { 0422 $language = strtolower($matches[1]) . '-' . strtoupper($matches[3]); 0423 } 0424 else if (!empty($matches[1])) { 0425 $language = strtolower($matches[1]); 0426 } 0427 } 0428 return $language; 0429 } 0430 0431 /** 0432 * Get a raw body data 0433 * 0434 * @return mixed 0435 */ 0436 public function getRawBody() 0437 { 0438 return file_get_contents('php://input'); 0439 } 0440 0441 }