if (isset($arr[0]) && is_array($arr[0])) // test the first array item, continue if it's another array, if it's NOT an array, then it's a single route path processed below, this $arr[0] will be null or a string like 'GET' in the `single route/path` version
{
foreach ($arr as $route)
{
if ( ! isset($route[0]) || strpos($route[0], $method) !== false)
. $this->expandRoutePattern($arr[1]))) . '$~'; // by default if we leave the route/command null, we use /login instead of /login/ like `/admin/...` basically this works differently to the array (sub-folder) version for arrays, where we append /name/ but here we only do /name
else if (($pos = strpos($controller, '->')) !== false) // controller is an instantiatable object, usually an object extending the base Controller class
// Check matching number of opening & closing brackets ... disabled only for performance reasons, the preg_match() will also throw an exception!?!? wtf?
// In order to support Restful API's on browsers that only support GET and POST, ...
// Notes taken from Slim: https://www.slimframework.com/docs/objects/request.html
// `It is possible to fake or override the HTTP request method. This is useful if, for example, you need to mimic a PUT request using a traditional web browser that only supports GET or POST requests.`
// `There are two ways to override the HTTP request method. You can include a _METHOD parameter in a POST request’s body. The HTTP request must use the application/x-www-form-urlencoded content type.`
// eg. request::build_url(array('path' => '/login')) == http://host/login (NOTE: Any `default` (request::$query) query string will be ignored when `path` is specified!)
(isset($parts['query']) ? (empty($parts['query']) ? null : '?' . $parts['query']) : (empty($parts['path']) && _::request('query') ? '?' . _::request('query') : null)); // NO FRAGMENT! We can append it if we really need it!
// Function competely re-written and added to the request class on 21 May 2017
function redirect( /* mixed */ )
{
/*
Taken from: http://www.php.net/manual/en/function.header.php#78470
// 301 Moved Permanently
header("Location: /foo.php",TRUE,301);
// 302 Found
header("Location: /foo.php",TRUE,302);
header("Location: /foo.php");
// 303 See Other
header("Location: /foo.php",TRUE,303);
// 307 Temporary Redirect
header("Location: /foo.php",TRUE,307);
"The HTTP status code changes the way browsers and robots handle redirects, so if you are using header(Location:) it's a good idea to set the status code at the same time. Browsers typically re-request a 307 page every time, cache a 302 page for the session, and cache a 301 page for longer, or even indefinitely. Search engines typically transfer "page rank" to the new location for 301 redirects, but not for 302, 303 or 307."
"If the status code is not specified, header('Location:') defaults to 302."
throw new \Exception('Request section not implemented/RE-written yet!');
/*
// Note: This is not necessary because the redirect header accepts a path based address; eg. / ... so the scheme & host are NOT always required! IOW we don't need to build a FULL / fully qualified URL like the `build_url()` function!
switch (substr($arg, 0, 1)) // pseudo: if $arg = '' then $arg[0] == `Notice: Uninitialized string offset: 0` ... IOW: We cannot use `switch($arg[0])` because we could get a PHP notice message!
{
case '/':
if (substr($arg, 0, 2) === '//') // `//` eg. '//www.google.com/' ... ie. same protocol!
$location = parse_url($arg);
else // `/` eg. '/login' ... ie. relative URL
{
$qmark = strpos($arg, '?');
if ($qmark === false) // eg. request::redirect('https', '/login') ... ie. the `https` will set scheme, host, path and query. We only want scheme, host and path! NOT the query string!
$location['query'] = (empty($location['query']) ? substr($arg, 1) : $location['query'] . $arg); // append to existing query string OR create new query string if it doesn't exist
break;
case '#':
// if ( ! isset($location['path'])) // optional
// $location['path'] = self::$path;
$location['fragment'] = substr($arg, 1); // should it be possible to just set the fragment without anything else?
break;
case 'h':
if ($arg === 'http' || $arg === 'https')
{
$location = [ 'scheme' => $arg,
'host' => _::request('host'),
'path' => _::request('path'),
'query' => _::request('query')
];
break;
}
// Alternative version below would have checked the prefix value of $arg for a `http:/` or `https:` value in the beginning to `semi-validate` the parse_url() value.
//$substr = substr($arg, 0, 6); // `optional` alternative
die('Invalid value in request::redirect(): ' . print_r($arg, true));
/*
if (strpos($arg, '=') !== false) // eg. 'test=123' == append to query string
{
$location = [ 'scheme' => $arg,
'host' => self::$host,
'path' => self::$path,
'query' => self::$query
];
}
*/
}
}
else if (is_int($arg))
$http_response_code = $arg;
else if (is_array($arg))
{
if (is_array($location))
{
if (isset($location['query']) && isset($arg['path']) && ! isset($arg['query'])) // eg. request::redirect('?id=123', ['path' => '/']) ... result = '/' ... because the '/' is a PATH without query string! The new `arg` value has a PATH but NOT a query string! path = query string = request_uri ... they go hand-in-hand!
unset($location['query']);
$location = array_merge($location, $arg);
}
else
$location = $arg;
}
else
die('Invalid value in request::redirect(): ' . print_r($arg, true));
}
if (is_array($location))
{
7 years ago
throw new \Exception('Request section not implemented or re-written yet!');
die('Invalid value in request::redirect(): ' . print_r($args, true));
}
// ob_get_length() will return "FALSE if no buffering is active." ... so all we want to know is if buffering IS active AND there was already data sent to the buffer ... then we need to die()!
if (ob_get_length()) die(ob_get_clean() . '<p><spanstyle="color: red;">Errors on Redirect to: <ahref="' . $location . '">' . $location . '</a></span></p>');