Added the Slim PHP Framework
This commit is contained in:
parent
5aacf17bca
commit
6f14b71386
|
@ -0,0 +1,237 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment
|
||||||
|
*
|
||||||
|
* This class creates and returns a key/value array of common
|
||||||
|
* environment variables for the current HTTP request.
|
||||||
|
*
|
||||||
|
* This is a singleton class; derived environment variables will
|
||||||
|
* be common across multiple Slim applications.
|
||||||
|
*
|
||||||
|
* This class matches the Rack (Ruby) specification as closely
|
||||||
|
* as possible. More information available below.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class Environment implements \ArrayAccess, \IteratorAggregate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Slim\Environment
|
||||||
|
*/
|
||||||
|
protected static $environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get environment instance (singleton)
|
||||||
|
*
|
||||||
|
* This creates and/or returns an environment instance (singleton)
|
||||||
|
* derived from $_SERVER variables. You may override the global server
|
||||||
|
* variables by using `\Slim\Environment::mock()` instead.
|
||||||
|
*
|
||||||
|
* @param bool $refresh Refresh properties using global server variables?
|
||||||
|
* @return \Slim\Environment
|
||||||
|
*/
|
||||||
|
public static function getInstance($refresh = false)
|
||||||
|
{
|
||||||
|
if (is_null(self::$environment) || $refresh) {
|
||||||
|
self::$environment = new self();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mock environment instance
|
||||||
|
*
|
||||||
|
* @param array $userSettings
|
||||||
|
* @return \Slim\Environment
|
||||||
|
*/
|
||||||
|
public static function mock($userSettings = array())
|
||||||
|
{
|
||||||
|
self::$environment = new self(array_merge(array(
|
||||||
|
'REQUEST_METHOD' => 'GET',
|
||||||
|
'SCRIPT_NAME' => '',
|
||||||
|
'PATH_INFO' => '',
|
||||||
|
'QUERY_STRING' => '',
|
||||||
|
'SERVER_NAME' => 'localhost',
|
||||||
|
'SERVER_PORT' => 80,
|
||||||
|
'ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||||
|
'ACCEPT_LANGUAGE' => 'en-US,en;q=0.8',
|
||||||
|
'ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
|
||||||
|
'USER_AGENT' => 'Slim Framework',
|
||||||
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
|
'slim.url_scheme' => 'http',
|
||||||
|
'slim.input' => '',
|
||||||
|
'slim.errors' => @fopen('php://stderr', 'w')
|
||||||
|
), $userSettings));
|
||||||
|
|
||||||
|
return self::$environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor (private access)
|
||||||
|
*
|
||||||
|
* @param array|null $settings If present, these are used instead of global server variables
|
||||||
|
*/
|
||||||
|
private function __construct($settings = null)
|
||||||
|
{
|
||||||
|
if ($settings) {
|
||||||
|
$this->properties = $settings;
|
||||||
|
} else {
|
||||||
|
$env = array();
|
||||||
|
|
||||||
|
//The HTTP request method
|
||||||
|
$env['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD'];
|
||||||
|
|
||||||
|
//The IP
|
||||||
|
$env['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application paths
|
||||||
|
*
|
||||||
|
* This derives two paths: SCRIPT_NAME and PATH_INFO. The SCRIPT_NAME
|
||||||
|
* is the real, physical path to the application, be it in the root
|
||||||
|
* directory or a subdirectory of the public document root. The PATH_INFO is the
|
||||||
|
* virtual path to the requested resource within the application context.
|
||||||
|
*
|
||||||
|
* With htaccess, the SCRIPT_NAME will be an absolute path (without file name);
|
||||||
|
* if not using htaccess, it will also include the file name. If it is "/",
|
||||||
|
* it is set to an empty string (since it cannot have a trailing slash).
|
||||||
|
*
|
||||||
|
* The PATH_INFO will be an absolute path with a leading slash; this will be
|
||||||
|
* used for application routing.
|
||||||
|
*/
|
||||||
|
if (strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0) {
|
||||||
|
$env['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME']; //Without URL rewrite
|
||||||
|
} else {
|
||||||
|
$env['SCRIPT_NAME'] = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']) ); //With URL rewrite
|
||||||
|
}
|
||||||
|
$env['PATH_INFO'] = substr_replace($_SERVER['REQUEST_URI'], '', 0, strlen($env['SCRIPT_NAME']));
|
||||||
|
if (strpos($env['PATH_INFO'], '?') !== false) {
|
||||||
|
$env['PATH_INFO'] = substr_replace($env['PATH_INFO'], '', strpos($env['PATH_INFO'], '?')); //query string is not removed automatically
|
||||||
|
}
|
||||||
|
$env['SCRIPT_NAME'] = rtrim($env['SCRIPT_NAME'], '/');
|
||||||
|
$env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/');
|
||||||
|
|
||||||
|
//The portion of the request URI following the '?'
|
||||||
|
$env['QUERY_STRING'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
|
||||||
|
|
||||||
|
//Name of server host that is running the script
|
||||||
|
$env['SERVER_NAME'] = $_SERVER['SERVER_NAME'];
|
||||||
|
|
||||||
|
//Number of server port that is running the script
|
||||||
|
$env['SERVER_PORT'] = $_SERVER['SERVER_PORT'];
|
||||||
|
|
||||||
|
//HTTP request headers
|
||||||
|
$specialHeaders = array('CONTENT_TYPE', 'CONTENT_LENGTH', 'PHP_AUTH_USER', 'PHP_AUTH_PW', 'PHP_AUTH_DIGEST', 'AUTH_TYPE');
|
||||||
|
foreach ($_SERVER as $key => $value) {
|
||||||
|
$value = is_string($value) ? trim($value) : $value;
|
||||||
|
if (strpos($key, 'HTTP_') === 0) {
|
||||||
|
$env[substr($key, 5)] = $value;
|
||||||
|
} elseif (strpos($key, 'X_') === 0 || in_array($key, $specialHeaders)) {
|
||||||
|
$env[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Is the application running under HTTPS or HTTP protocol?
|
||||||
|
$env['slim.url_scheme'] = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https';
|
||||||
|
|
||||||
|
//Input stream (readable one time only; not available for mutipart/form-data requests)
|
||||||
|
$rawInput = @file_get_contents('php://input');
|
||||||
|
if (!$rawInput) {
|
||||||
|
$rawInput = '';
|
||||||
|
}
|
||||||
|
$env['slim.input'] = $rawInput;
|
||||||
|
|
||||||
|
//Error stream
|
||||||
|
$env['slim.errors'] = fopen('php://stderr', 'w');
|
||||||
|
|
||||||
|
$this->properties = $env;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Exists
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return isset($this->properties[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Get
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
if (isset($this->properties[$offset])) {
|
||||||
|
return $this->properties[$offset];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Set
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->properties[$offset] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Unset
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
unset($this->properties[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IteratorAggregate
|
||||||
|
*
|
||||||
|
* @return \ArrayIterator
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new \ArrayIterator($this->properties);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass Exception
|
||||||
|
*
|
||||||
|
* This Exception will cause the Router::dispatch method
|
||||||
|
* to skip the current matching route and continue to the next
|
||||||
|
* matching route. If no subsequent routes are found, a
|
||||||
|
* HTTP 404 Not Found response will be sent to the client.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Pass extends \Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request Slash Exception
|
||||||
|
*
|
||||||
|
* This Exception is thrown when Slim detects a matching route
|
||||||
|
* (defined with a trailing slash) and the HTTP request
|
||||||
|
* matches the route but does not have a trailing slash. This
|
||||||
|
* exception will be caught in `Slim::run` and trigger a 301 redirect
|
||||||
|
* to the same resource URI with a trailing slash.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class RequestSlash extends \Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop Exception
|
||||||
|
*
|
||||||
|
* This Exception is thrown when the Slim application needs to abort
|
||||||
|
* processing and return control flow to the outer PHP script.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Stop extends \Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Headers
|
||||||
|
*
|
||||||
|
* This class is an abstraction of the HTTP response headers and
|
||||||
|
* provides array access to the header list while automatically
|
||||||
|
* stores and retrieves headers with lowercase canonical keys regardless
|
||||||
|
* of the input format.
|
||||||
|
*
|
||||||
|
* This class also implements the `Iterator` and `Countable`
|
||||||
|
* interfaces for even more convenient usage.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class Headers implements \ArrayAccess, \Iterator, \Countable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array HTTP headers
|
||||||
|
*/
|
||||||
|
protected $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Map canonical header name to original header name
|
||||||
|
*/
|
||||||
|
protected $map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param array $headers
|
||||||
|
*/
|
||||||
|
public function __construct($headers = array())
|
||||||
|
{
|
||||||
|
$this->merge($headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge Headers
|
||||||
|
* @param array $headers
|
||||||
|
*/
|
||||||
|
public function merge($headers)
|
||||||
|
{
|
||||||
|
foreach ($headers as $name => $value) {
|
||||||
|
$this[$name] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform header name into canonical form
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function canonical($name)
|
||||||
|
{
|
||||||
|
return strtolower(trim($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Exists
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return isset($this->headers[$this->canonical($offset)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Get
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
$canonical = $this->canonical($offset);
|
||||||
|
if (isset($this->headers[$canonical])) {
|
||||||
|
return $this->headers[$canonical];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Set
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$canonical = $this->canonical($offset);
|
||||||
|
$this->headers[$canonical] = $value;
|
||||||
|
$this->map[$canonical] = $offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Unset
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
$canonical = $this->canonical($offset);
|
||||||
|
unset($this->headers[$canonical], $this->map[$canonical]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Countable: Count
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator: Rewind
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
reset($this->headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator: Current
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return current($this->headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator: Key
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
$key = key($this->headers);
|
||||||
|
|
||||||
|
return $this->map[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator: Next
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
return next($this->headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator: Valid
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return current($this->headers) !== false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,585 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slim HTTP Request
|
||||||
|
*
|
||||||
|
* This class provides a human-friendly interface to the Slim environment variables;
|
||||||
|
* environment variables are passed by reference and will be modified directly.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Request
|
||||||
|
{
|
||||||
|
const METHOD_HEAD = 'HEAD';
|
||||||
|
const METHOD_GET = 'GET';
|
||||||
|
const METHOD_POST = 'POST';
|
||||||
|
const METHOD_PUT = 'PUT';
|
||||||
|
const METHOD_DELETE = 'DELETE';
|
||||||
|
const METHOD_OPTIONS = 'OPTIONS';
|
||||||
|
const METHOD_OVERRIDE = '_METHOD';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $formDataMediaTypes = array('application/x-www-form-urlencoded');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $env;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param array $env
|
||||||
|
* @see \Slim\Environment
|
||||||
|
*/
|
||||||
|
public function __construct($env)
|
||||||
|
{
|
||||||
|
$this->env = $env;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get HTTP method
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMethod()
|
||||||
|
{
|
||||||
|
return $this->env['REQUEST_METHOD'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a GET request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isGet()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_GET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a POST request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPost()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a PUT request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPut()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_PUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a DELETE request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isDelete()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a HEAD request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isHead()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a OPTIONS request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isOptions()
|
||||||
|
{
|
||||||
|
return $this->getMethod() === self::METHOD_OPTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this an AJAX request?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isAjax()
|
||||||
|
{
|
||||||
|
if ($this->params('isajax')) {
|
||||||
|
return true;
|
||||||
|
} elseif (isset($this->env['X_REQUESTED_WITH']) && $this->env['X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this an XHR request? (alias of Slim_Http_Request::isAjax)
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isXhr()
|
||||||
|
{
|
||||||
|
return $this->isAjax();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch GET and POST data
|
||||||
|
*
|
||||||
|
* This method returns a union of GET and POST data as a key-value array, or the value
|
||||||
|
* of the array key if requested; if the array key does not exist, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return array|mixed|null
|
||||||
|
*/
|
||||||
|
public function params($key = null)
|
||||||
|
{
|
||||||
|
$union = array_merge($this->get(), $this->post());
|
||||||
|
if ($key) {
|
||||||
|
if (isset($union[$key])) {
|
||||||
|
return $union[$key];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $union;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch GET data
|
||||||
|
*
|
||||||
|
* This method returns a key-value array of data sent in the HTTP request query string, or
|
||||||
|
* the value of the array key if requested; if the array key does not exist, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return array|mixed|null
|
||||||
|
*/
|
||||||
|
public function get($key = null)
|
||||||
|
{
|
||||||
|
if (!isset($this->env['slim.request.query_hash'])) {
|
||||||
|
$output = array();
|
||||||
|
if (function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte'])) {
|
||||||
|
mb_parse_str($this->env['QUERY_STRING'], $output);
|
||||||
|
} else {
|
||||||
|
parse_str($this->env['QUERY_STRING'], $output);
|
||||||
|
}
|
||||||
|
$this->env['slim.request.query_hash'] = Util::stripSlashesIfMagicQuotes($output);
|
||||||
|
}
|
||||||
|
if ($key) {
|
||||||
|
if (isset($this->env['slim.request.query_hash'][$key])) {
|
||||||
|
return $this->env['slim.request.query_hash'][$key];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->env['slim.request.query_hash'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch POST data
|
||||||
|
*
|
||||||
|
* This method returns a key-value array of data sent in the HTTP request body, or
|
||||||
|
* the value of a hash key if requested; if the array key does not exist, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return array|mixed|null
|
||||||
|
* @throws \RuntimeException If environment input is not available
|
||||||
|
*/
|
||||||
|
public function post($key = null)
|
||||||
|
{
|
||||||
|
if (!isset($this->env['slim.input'])) {
|
||||||
|
throw new \RuntimeException('Missing slim.input in environment variables');
|
||||||
|
}
|
||||||
|
if (!isset($this->env['slim.request.form_hash'])) {
|
||||||
|
$this->env['slim.request.form_hash'] = array();
|
||||||
|
if ($this->isFormData() && is_string($this->env['slim.input'])) {
|
||||||
|
$output = array();
|
||||||
|
if (function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte'])) {
|
||||||
|
mb_parse_str($this->env['slim.input'], $output);
|
||||||
|
} else {
|
||||||
|
parse_str($this->env['slim.input'], $output);
|
||||||
|
}
|
||||||
|
$this->env['slim.request.form_hash'] = Util::stripSlashesIfMagicQuotes($output);
|
||||||
|
} else {
|
||||||
|
$this->env['slim.request.form_hash'] = Util::stripSlashesIfMagicQuotes($_POST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($key) {
|
||||||
|
if (isset($this->env['slim.request.form_hash'][$key])) {
|
||||||
|
return $this->env['slim.request.form_hash'][$key];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->env['slim.request.form_hash'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch PUT data (alias for \Slim\Http\Request::post)
|
||||||
|
* @param string $key
|
||||||
|
* @return array|mixed|null
|
||||||
|
*/
|
||||||
|
public function put($key = null)
|
||||||
|
{
|
||||||
|
return $this->post($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch DELETE data (alias for \Slim\Http\Request::post)
|
||||||
|
* @param string $key
|
||||||
|
* @return array|mixed|null
|
||||||
|
*/
|
||||||
|
public function delete($key = null)
|
||||||
|
{
|
||||||
|
return $this->post($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch COOKIE data
|
||||||
|
*
|
||||||
|
* This method returns a key-value array of Cookie data sent in the HTTP request, or
|
||||||
|
* the value of a array key if requested; if the array key does not exist, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return array|string|null
|
||||||
|
*/
|
||||||
|
public function cookies($key = null)
|
||||||
|
{
|
||||||
|
if (!isset($this->env['slim.request.cookie_hash'])) {
|
||||||
|
$cookieHeader = isset($this->env['COOKIE']) ? $this->env['COOKIE'] : '';
|
||||||
|
$this->env['slim.request.cookie_hash'] = Util::parseCookieHeader($cookieHeader);
|
||||||
|
}
|
||||||
|
if ($key) {
|
||||||
|
if (isset($this->env['slim.request.cookie_hash'][$key])) {
|
||||||
|
return $this->env['slim.request.cookie_hash'][$key];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->env['slim.request.cookie_hash'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the Request body contain parseable form data?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isFormData()
|
||||||
|
{
|
||||||
|
$method = isset($this->env['slim.method_override.original_method']) ? $this->env['slim.method_override.original_method'] : $this->getMethod();
|
||||||
|
|
||||||
|
return ($method === self::METHOD_POST && is_null($this->getContentType())) || in_array($this->getMediaType(), self::$formDataMediaTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Headers
|
||||||
|
*
|
||||||
|
* This method returns a key-value array of headers sent in the HTTP request, or
|
||||||
|
* the value of a hash key if requested; if the array key does not exist, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param mixed $default The default value returned if the requested header is not available
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function headers($key = null, $default = null)
|
||||||
|
{
|
||||||
|
if ($key) {
|
||||||
|
$key = strtoupper($key);
|
||||||
|
$key = str_replace('-', '_', $key);
|
||||||
|
$key = preg_replace('@^HTTP_@', '', $key);
|
||||||
|
if (isset($this->env[$key])) {
|
||||||
|
return $this->env[$key];
|
||||||
|
} else {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$headers = array();
|
||||||
|
foreach ($this->env as $key => $value) {
|
||||||
|
if (strpos($key, 'slim.') !== 0) {
|
||||||
|
$headers[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Body
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBody()
|
||||||
|
{
|
||||||
|
return $this->env['slim.input'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Content Type
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getContentType()
|
||||||
|
{
|
||||||
|
if (isset($this->env['CONTENT_TYPE'])) {
|
||||||
|
return $this->env['CONTENT_TYPE'];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Media Type (type/subtype within Content Type header)
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getMediaType()
|
||||||
|
{
|
||||||
|
$contentType = $this->getContentType();
|
||||||
|
if ($contentType) {
|
||||||
|
$contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
|
||||||
|
|
||||||
|
return strtolower($contentTypeParts[0]);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Media Type Params
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMediaTypeParams()
|
||||||
|
{
|
||||||
|
$contentType = $this->getContentType();
|
||||||
|
$contentTypeParams = array();
|
||||||
|
if ($contentType) {
|
||||||
|
$contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
|
||||||
|
$contentTypePartsLength = count($contentTypeParts);
|
||||||
|
for ($i = 1; $i < $contentTypePartsLength; $i++) {
|
||||||
|
$paramParts = explode('=', $contentTypeParts[$i]);
|
||||||
|
$contentTypeParams[strtolower($paramParts[0])] = $paramParts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $contentTypeParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Content Charset
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getContentCharset()
|
||||||
|
{
|
||||||
|
$mediaTypeParams = $this->getMediaTypeParams();
|
||||||
|
if (isset($mediaTypeParams['charset'])) {
|
||||||
|
return $mediaTypeParams['charset'];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Content-Length
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getContentLength()
|
||||||
|
{
|
||||||
|
if (isset($this->env['CONTENT_LENGTH'])) {
|
||||||
|
return (int) $this->env['CONTENT_LENGTH'];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Host
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHost()
|
||||||
|
{
|
||||||
|
if (isset($this->env['HOST'])) {
|
||||||
|
if (strpos($this->env['HOST'], ':') !== false) {
|
||||||
|
$hostParts = explode(':', $this->env['HOST']);
|
||||||
|
|
||||||
|
return $hostParts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->env['HOST'];
|
||||||
|
} else {
|
||||||
|
return $this->env['SERVER_NAME'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Host with Port
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHostWithPort()
|
||||||
|
{
|
||||||
|
return sprintf('%s:%s', $this->getHost(), $this->getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Port
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPort()
|
||||||
|
{
|
||||||
|
return (int) $this->env['SERVER_PORT'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Scheme (https or http)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getScheme()
|
||||||
|
{
|
||||||
|
return $this->env['slim.url_scheme'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Script Name (physical path)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getScriptName()
|
||||||
|
{
|
||||||
|
return $this->env['SCRIPT_NAME'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LEGACY: Get Root URI (alias for Slim_Http_Request::getScriptName)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRootUri()
|
||||||
|
{
|
||||||
|
return $this->getScriptName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Path (physical path + virtual path)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPath()
|
||||||
|
{
|
||||||
|
return $this->getScriptName() . $this->getPathInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Path Info (virtual path)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPathInfo()
|
||||||
|
{
|
||||||
|
return $this->env['PATH_INFO'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LEGACY: Get Resource URI (alias for Slim_Http_Request::getPathInfo)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResourceUri()
|
||||||
|
{
|
||||||
|
return $this->getPathInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get URL (scheme + host [ + port if non-standard ])
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl()
|
||||||
|
{
|
||||||
|
$url = $this->getScheme() . '://' . $this->getHost();
|
||||||
|
if (($this->getScheme() === 'https' && $this->getPort() !== 443) || ($this->getScheme() === 'http' && $this->getPort() !== 80)) {
|
||||||
|
$url .= sprintf(':%s', $this->getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get IP
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getIp()
|
||||||
|
{
|
||||||
|
if (isset($this->env['X_FORWARDED_FOR'])) {
|
||||||
|
return $this->env['X_FORWARDED_FOR'];
|
||||||
|
} elseif (isset($this->env['CLIENT_IP'])) {
|
||||||
|
return $this->env['CLIENT_IP'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->env['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Referrer
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getReferrer()
|
||||||
|
{
|
||||||
|
if (isset($this->env['REFERER'])) {
|
||||||
|
return $this->env['REFERER'];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Referer (for those who can't spell)
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getReferer()
|
||||||
|
{
|
||||||
|
return $this->getReferrer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get User Agent
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getUserAgent()
|
||||||
|
{
|
||||||
|
if (isset($this->env['USER_AGENT'])) {
|
||||||
|
return $this->env['USER_AGENT'];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,459 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response
|
||||||
|
*
|
||||||
|
* This is a simple abstraction over top an HTTP response. This
|
||||||
|
* provides methods to set the HTTP status, the HTTP headers,
|
||||||
|
* and the HTTP body.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Response implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int HTTP status code
|
||||||
|
*/
|
||||||
|
protected $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Slim\Http\Headers List of HTTP response headers
|
||||||
|
*/
|
||||||
|
protected $header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string HTTP response body
|
||||||
|
*/
|
||||||
|
protected $body;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Length of HTTP response body
|
||||||
|
*/
|
||||||
|
protected $length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array HTTP response codes and messages
|
||||||
|
*/
|
||||||
|
protected static $messages = array(
|
||||||
|
//Informational 1xx
|
||||||
|
100 => '100 Continue',
|
||||||
|
101 => '101 Switching Protocols',
|
||||||
|
//Successful 2xx
|
||||||
|
200 => '200 OK',
|
||||||
|
201 => '201 Created',
|
||||||
|
202 => '202 Accepted',
|
||||||
|
203 => '203 Non-Authoritative Information',
|
||||||
|
204 => '204 No Content',
|
||||||
|
205 => '205 Reset Content',
|
||||||
|
206 => '206 Partial Content',
|
||||||
|
//Redirection 3xx
|
||||||
|
300 => '300 Multiple Choices',
|
||||||
|
301 => '301 Moved Permanently',
|
||||||
|
302 => '302 Found',
|
||||||
|
303 => '303 See Other',
|
||||||
|
304 => '304 Not Modified',
|
||||||
|
305 => '305 Use Proxy',
|
||||||
|
306 => '306 (Unused)',
|
||||||
|
307 => '307 Temporary Redirect',
|
||||||
|
//Client Error 4xx
|
||||||
|
400 => '400 Bad Request',
|
||||||
|
401 => '401 Unauthorized',
|
||||||
|
402 => '402 Payment Required',
|
||||||
|
403 => '403 Forbidden',
|
||||||
|
404 => '404 Not Found',
|
||||||
|
405 => '405 Method Not Allowed',
|
||||||
|
406 => '406 Not Acceptable',
|
||||||
|
407 => '407 Proxy Authentication Required',
|
||||||
|
408 => '408 Request Timeout',
|
||||||
|
409 => '409 Conflict',
|
||||||
|
410 => '410 Gone',
|
||||||
|
411 => '411 Length Required',
|
||||||
|
412 => '412 Precondition Failed',
|
||||||
|
413 => '413 Request Entity Too Large',
|
||||||
|
414 => '414 Request-URI Too Long',
|
||||||
|
415 => '415 Unsupported Media Type',
|
||||||
|
416 => '416 Requested Range Not Satisfiable',
|
||||||
|
417 => '417 Expectation Failed',
|
||||||
|
422 => '422 Unprocessable Entity',
|
||||||
|
423 => '423 Locked',
|
||||||
|
//Server Error 5xx
|
||||||
|
500 => '500 Internal Server Error',
|
||||||
|
501 => '501 Not Implemented',
|
||||||
|
502 => '502 Bad Gateway',
|
||||||
|
503 => '503 Service Unavailable',
|
||||||
|
504 => '504 Gateway Timeout',
|
||||||
|
505 => '505 HTTP Version Not Supported'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param string $body The HTTP response body
|
||||||
|
* @param int $status The HTTP response status
|
||||||
|
* @param \Slim\Http\Headers|array $header The HTTP response headers
|
||||||
|
*/
|
||||||
|
public function __construct($body = '', $status = 200, $header = array())
|
||||||
|
{
|
||||||
|
$this->status = (int) $status;
|
||||||
|
$headers = array();
|
||||||
|
foreach ($header as $key => $value) {
|
||||||
|
$headers[$key] = $value;
|
||||||
|
}
|
||||||
|
$this->header = new Headers(array_merge(array('Content-Type' => 'text/html'), $headers));
|
||||||
|
$this->body = '';
|
||||||
|
$this->write($body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and set status
|
||||||
|
* @param int|null $status
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function status($status = null)
|
||||||
|
{
|
||||||
|
if (!is_null($status)) {
|
||||||
|
$this->status = (int) $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and set header
|
||||||
|
* @param string $name Header name
|
||||||
|
* @param string|null $value Header value
|
||||||
|
* @return string Header value
|
||||||
|
*/
|
||||||
|
public function header($name, $value = null)
|
||||||
|
{
|
||||||
|
if (!is_null($value)) {
|
||||||
|
$this[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get headers
|
||||||
|
* @return \Slim\Http\Headers
|
||||||
|
*/
|
||||||
|
public function headers()
|
||||||
|
{
|
||||||
|
return $this->header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and set body
|
||||||
|
* @param string|null $body Content of HTTP response body
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function body($body = null)
|
||||||
|
{
|
||||||
|
if (!is_null($body)) {
|
||||||
|
$this->write($body, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and set length
|
||||||
|
* @param int|null $length
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function length($length = null)
|
||||||
|
{
|
||||||
|
if (!is_null($length)) {
|
||||||
|
$this->length = (int) $length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append HTTP response body
|
||||||
|
* @param string $body Content to append to the current HTTP response body
|
||||||
|
* @param bool $replace Overwrite existing response body?
|
||||||
|
* @return string The updated HTTP response body
|
||||||
|
*/
|
||||||
|
public function write($body, $replace = false)
|
||||||
|
{
|
||||||
|
if ($replace) {
|
||||||
|
$this->body = $body;
|
||||||
|
} else {
|
||||||
|
$this->body .= (string) $body;
|
||||||
|
}
|
||||||
|
$this->length = strlen($this->body);
|
||||||
|
|
||||||
|
return $this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize
|
||||||
|
*
|
||||||
|
* This prepares this response and returns an array
|
||||||
|
* of [status, headers, body]. This array is passed to outer middleware
|
||||||
|
* if available or directly to the Slim run method.
|
||||||
|
*
|
||||||
|
* @return array[int status, array headers, string body]
|
||||||
|
*/
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
if (in_array($this->status, array(204, 304))) {
|
||||||
|
unset($this['Content-Type'], $this['Content-Length']);
|
||||||
|
|
||||||
|
return array($this->status, $this->header, '');
|
||||||
|
} else {
|
||||||
|
return array($this->status, $this->header, $this->body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cookie
|
||||||
|
*
|
||||||
|
* Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
|
||||||
|
* header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
|
||||||
|
* response's header is passed by reference to the utility class and is directly modified. By not
|
||||||
|
* relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
|
||||||
|
* analyze the raw header before the response is ultimately delivered to the HTTP client.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie
|
||||||
|
* @param string|array $value If string, the value of cookie; if array, properties for
|
||||||
|
* cookie including: value, expire, path, domain, secure, httponly
|
||||||
|
*/
|
||||||
|
public function setCookie($name, $value)
|
||||||
|
{
|
||||||
|
Util::setCookieHeader($this->header, $name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete cookie
|
||||||
|
*
|
||||||
|
* Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
|
||||||
|
* header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
|
||||||
|
* response's header is passed by reference to the utility class and is directly modified. By not
|
||||||
|
* relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
|
||||||
|
* analyze the raw header before the response is ultimately delivered to the HTTP client.
|
||||||
|
*
|
||||||
|
* This method will set a cookie with the given name that has an expiration time in the past; this will
|
||||||
|
* prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may
|
||||||
|
* also pass a key/value array as the second argument. If the "domain" key is present in this
|
||||||
|
* array, only the Cookie with the given name AND domain will be removed. The invalidating cookie
|
||||||
|
* sent with this response will adopt all properties of the second argument.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie
|
||||||
|
* @param array $value Properties for cookie including: value, expire, path, domain, secure, httponly
|
||||||
|
*/
|
||||||
|
public function deleteCookie($name, $value = array())
|
||||||
|
{
|
||||||
|
Util::deleteCookieHeader($this->header, $name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect
|
||||||
|
*
|
||||||
|
* This method prepares this response to return an HTTP Redirect response
|
||||||
|
* to the HTTP client.
|
||||||
|
*
|
||||||
|
* @param string $url The redirect destination
|
||||||
|
* @param int $status The redirect HTTP status code
|
||||||
|
*/
|
||||||
|
public function redirect ($url, $status = 302)
|
||||||
|
{
|
||||||
|
$this->status = $status;
|
||||||
|
$this['Location'] = $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Empty?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return in_array($this->status, array(201, 204, 304));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Informational?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isInformational()
|
||||||
|
{
|
||||||
|
return $this->status >= 100 && $this->status < 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: OK?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isOk()
|
||||||
|
{
|
||||||
|
return $this->status === 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Successful?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isSuccessful()
|
||||||
|
{
|
||||||
|
return $this->status >= 200 && $this->status < 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Redirect?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isRedirect()
|
||||||
|
{
|
||||||
|
return in_array($this->status, array(301, 302, 303, 307));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Redirection?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isRedirection()
|
||||||
|
{
|
||||||
|
return $this->status >= 300 && $this->status < 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Forbidden?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isForbidden()
|
||||||
|
{
|
||||||
|
return $this->status === 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Not Found?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isNotFound()
|
||||||
|
{
|
||||||
|
return $this->status === 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Client error?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClientError()
|
||||||
|
{
|
||||||
|
return $this->status >= 400 && $this->status < 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers: Server Error?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isServerError()
|
||||||
|
{
|
||||||
|
return $this->status >= 500 && $this->status < 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Exists
|
||||||
|
*/
|
||||||
|
public function offsetExists( $offset )
|
||||||
|
{
|
||||||
|
return isset($this->header[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Get
|
||||||
|
*/
|
||||||
|
public function offsetGet( $offset )
|
||||||
|
{
|
||||||
|
if (isset($this->header[$offset])) {
|
||||||
|
return $this->header[$offset];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Set
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->header[$offset] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Unset
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
unset($this->header[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Countable: Count
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Iterator
|
||||||
|
*
|
||||||
|
* This returns the contained `\Slim\Http\Headers` instance which
|
||||||
|
* is itself iterable.
|
||||||
|
*
|
||||||
|
* @return \Slim\Http\Headers
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return $this->header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get message for HTTP status code
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public static function getMessageForCode($status)
|
||||||
|
{
|
||||||
|
if (isset(self::$messages[$status])) {
|
||||||
|
return self::$messages[$status];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,389 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slim HTTP Utilities
|
||||||
|
*
|
||||||
|
* This class provides useful methods for handling HTTP requests.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Strip slashes from string or array
|
||||||
|
*
|
||||||
|
* This method strips slashes from its input. By default, this method will only
|
||||||
|
* strip slashes from its input if magic quotes are enabled. Otherwise, you may
|
||||||
|
* override the magic quotes setting with either TRUE or FALSE as the send argument
|
||||||
|
* to force this method to strip or not strip slashes from its input.
|
||||||
|
*
|
||||||
|
* @var array|string $rawData
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
public static function stripSlashesIfMagicQuotes($rawData, $overrideStripSlashes = null)
|
||||||
|
{
|
||||||
|
$strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
|
||||||
|
if ($strip) {
|
||||||
|
return self::_stripSlashes($rawData);
|
||||||
|
} else {
|
||||||
|
return $rawData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip slashes from string or array
|
||||||
|
* @param array|string $rawData
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
protected static function _stripSlashes($rawData)
|
||||||
|
{
|
||||||
|
return is_array($rawData) ? array_map(array('self', '_stripSlashes'), $rawData) : stripslashes($rawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt data
|
||||||
|
*
|
||||||
|
* This method will encrypt data using a given key, vector, and cipher.
|
||||||
|
* By default, this will encrypt data using the RIJNDAEL/AES 256 bit cipher. You
|
||||||
|
* may override the default cipher and cipher mode by passing your own desired
|
||||||
|
* cipher and cipher mode as the final key-value array argument.
|
||||||
|
*
|
||||||
|
* @param string $data The unencrypted data
|
||||||
|
* @param string $key The encryption key
|
||||||
|
* @param string $iv The encryption initialization vector
|
||||||
|
* @param array $settings Optional key-value array with custom algorithm and mode
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function encrypt($data, $key, $iv, $settings = array())
|
||||||
|
{
|
||||||
|
if ($data === '' || !extension_loaded('mcrypt')) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Merge settings with defaults
|
||||||
|
$settings = array_merge(array(
|
||||||
|
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||||
|
'mode' => MCRYPT_MODE_CBC
|
||||||
|
), $settings);
|
||||||
|
|
||||||
|
//Get module
|
||||||
|
$module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
|
||||||
|
|
||||||
|
//Validate IV
|
||||||
|
$ivSize = mcrypt_enc_get_iv_size($module);
|
||||||
|
if (strlen($iv) > $ivSize) {
|
||||||
|
$iv = substr($iv, 0, $ivSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate key
|
||||||
|
$keySize = mcrypt_enc_get_key_size($module);
|
||||||
|
if (strlen($key) > $keySize) {
|
||||||
|
$key = substr($key, 0, $keySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Encrypt value
|
||||||
|
mcrypt_generic_init($module, $key, $iv);
|
||||||
|
$res = @mcrypt_generic($module, $data);
|
||||||
|
mcrypt_generic_deinit($module);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt data
|
||||||
|
*
|
||||||
|
* This method will decrypt data using a given key, vector, and cipher.
|
||||||
|
* By default, this will decrypt data using the RIJNDAEL/AES 256 bit cipher. You
|
||||||
|
* may override the default cipher and cipher mode by passing your own desired
|
||||||
|
* cipher and cipher mode as the final key-value array argument.
|
||||||
|
*
|
||||||
|
* @param string $data The encrypted data
|
||||||
|
* @param string $key The encryption key
|
||||||
|
* @param string $iv The encryption initialization vector
|
||||||
|
* @param array $settings Optional key-value array with custom algorithm and mode
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function decrypt($data, $key, $iv, $settings = array())
|
||||||
|
{
|
||||||
|
if ($data === '' || !extension_loaded('mcrypt')) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Merge settings with defaults
|
||||||
|
$settings = array_merge(array(
|
||||||
|
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||||
|
'mode' => MCRYPT_MODE_CBC
|
||||||
|
), $settings);
|
||||||
|
|
||||||
|
//Get module
|
||||||
|
$module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
|
||||||
|
|
||||||
|
//Validate IV
|
||||||
|
$ivSize = mcrypt_enc_get_iv_size($module);
|
||||||
|
if (strlen($iv) > $ivSize) {
|
||||||
|
$iv = substr($iv, 0, $ivSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate key
|
||||||
|
$keySize = mcrypt_enc_get_key_size($module);
|
||||||
|
if (strlen($key) > $keySize) {
|
||||||
|
$key = substr($key, 0, $keySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrypt value
|
||||||
|
mcrypt_generic_init($module, $key, $iv);
|
||||||
|
$decryptedData = @mdecrypt_generic($module, $data);
|
||||||
|
$res = str_replace("\x0", '', $decryptedData);
|
||||||
|
mcrypt_generic_deinit($module);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode secure cookie value
|
||||||
|
*
|
||||||
|
* This method will create the secure value of an HTTP cookie. The
|
||||||
|
* cookie value is encrypted and hashed so that its value is
|
||||||
|
* secure and checked for integrity when read in subsequent requests.
|
||||||
|
*
|
||||||
|
* @param string $value The unsecure HTTP cookie value
|
||||||
|
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||||
|
* @param string $secret The secret key used to hash the cookie value
|
||||||
|
* @param int $algorithm The algorithm to use for encryption
|
||||||
|
* @param int $mode The algorithm mode to use for encryption
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public static function encodeSecureCookie($value, $expires, $secret, $algorithm, $mode)
|
||||||
|
{
|
||||||
|
$key = hash_hmac('sha1', $expires, $secret);
|
||||||
|
$iv = self::get_iv($expires, $secret);
|
||||||
|
$secureString = base64_encode(self::encrypt($value, $key, $iv, array(
|
||||||
|
'algorithm' => $algorithm,
|
||||||
|
'mode' => $mode
|
||||||
|
)));
|
||||||
|
$verificationString = hash_hmac('sha1', $expires . $value, $key);
|
||||||
|
|
||||||
|
return implode('|', array($expires, $secureString, $verificationString));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode secure cookie value
|
||||||
|
*
|
||||||
|
* This method will decode the secure value of an HTTP cookie. The
|
||||||
|
* cookie value is encrypted and hashed so that its value is
|
||||||
|
* secure and checked for integrity when read in subsequent requests.
|
||||||
|
*
|
||||||
|
* @param string $value The secure HTTP cookie value
|
||||||
|
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||||
|
* @param string $secret The secret key used to hash the cookie value
|
||||||
|
* @param int $algorithm The algorithm to use for encryption
|
||||||
|
* @param int $mode The algorithm mode to use for encryption
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public static function decodeSecureCookie($value, $secret, $algorithm, $mode)
|
||||||
|
{
|
||||||
|
if ($value) {
|
||||||
|
$value = explode('|', $value);
|
||||||
|
if (count($value) === 3 && ((int) $value[0] === 0 || (int) $value[0] > time())) {
|
||||||
|
$key = hash_hmac('sha1', $value[0], $secret);
|
||||||
|
$iv = self::get_iv($value[0], $secret);
|
||||||
|
$data = self::decrypt(base64_decode($value[1]), $key, $iv, array(
|
||||||
|
'algorithm' => $algorithm,
|
||||||
|
'mode' => $mode
|
||||||
|
));
|
||||||
|
$verificationString = hash_hmac('sha1', $value[0] . $data, $key);
|
||||||
|
if ($verificationString === $value[2]) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set HTTP cookie header
|
||||||
|
*
|
||||||
|
* This method will construct and set the HTTP `Set-Cookie` header. Slim
|
||||||
|
* uses this method instead of PHP's native `setcookie` method. This allows
|
||||||
|
* more control of the HTTP header irrespective of the native implementation's
|
||||||
|
* dependency on PHP versions.
|
||||||
|
*
|
||||||
|
* This method accepts the Slim_Http_Headers object by reference as its
|
||||||
|
* first argument; this method directly modifies this object instead of
|
||||||
|
* returning a value.
|
||||||
|
*
|
||||||
|
* @param array $header
|
||||||
|
* @param string $name
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public static function setCookieHeader(&$header, $name, $value)
|
||||||
|
{
|
||||||
|
//Build cookie header
|
||||||
|
if (is_array($value)) {
|
||||||
|
$domain = '';
|
||||||
|
$path = '';
|
||||||
|
$expires = '';
|
||||||
|
$secure = '';
|
||||||
|
$httponly = '';
|
||||||
|
if (isset($value['domain']) && $value['domain']) {
|
||||||
|
$domain = '; domain=' . $value['domain'];
|
||||||
|
}
|
||||||
|
if (isset($value['path']) && $value['path']) {
|
||||||
|
$path = '; path=' . $value['path'];
|
||||||
|
}
|
||||||
|
if (isset($value['expires'])) {
|
||||||
|
if (is_string($value['expires'])) {
|
||||||
|
$timestamp = strtotime($value['expires']);
|
||||||
|
} else {
|
||||||
|
$timestamp = (int) $value['expires'];
|
||||||
|
}
|
||||||
|
if ($timestamp !== 0) {
|
||||||
|
$expires = '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($value['secure']) && $value['secure']) {
|
||||||
|
$secure = '; secure';
|
||||||
|
}
|
||||||
|
if (isset($value['httponly']) && $value['httponly']) {
|
||||||
|
$httponly = '; HttpOnly';
|
||||||
|
}
|
||||||
|
$cookie = sprintf('%s=%s%s', urlencode($name), urlencode((string) $value['value']), $domain . $path . $expires . $secure . $httponly);
|
||||||
|
} else {
|
||||||
|
$cookie = sprintf('%s=%s', urlencode($name), urlencode((string) $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set cookie header
|
||||||
|
if (!isset($header['Set-Cookie']) || $header['Set-Cookie'] === '') {
|
||||||
|
$header['Set-Cookie'] = $cookie;
|
||||||
|
} else {
|
||||||
|
$header['Set-Cookie'] = implode("\n", array($header['Set-Cookie'], $cookie));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete HTTP cookie header
|
||||||
|
*
|
||||||
|
* This method will construct and set the HTTP `Set-Cookie` header to invalidate
|
||||||
|
* a client-side HTTP cookie. If a cookie with the same name (and, optionally, domain)
|
||||||
|
* is already set in the HTTP response, it will also be removed. Slim uses this method
|
||||||
|
* instead of PHP's native `setcookie` method. This allows more control of the HTTP header
|
||||||
|
* irrespective of PHP's native implementation's dependency on PHP versions.
|
||||||
|
*
|
||||||
|
* This method accepts the Slim_Http_Headers object by reference as its
|
||||||
|
* first argument; this method directly modifies this object instead of
|
||||||
|
* returning a value.
|
||||||
|
*
|
||||||
|
* @param array $header
|
||||||
|
* @param string $name
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public static function deleteCookieHeader(&$header, $name, $value = array())
|
||||||
|
{
|
||||||
|
//Remove affected cookies from current response header
|
||||||
|
$cookiesOld = array();
|
||||||
|
$cookiesNew = array();
|
||||||
|
if (isset($header['Set-Cookie'])) {
|
||||||
|
$cookiesOld = explode("\n", $header['Set-Cookie']);
|
||||||
|
}
|
||||||
|
foreach ($cookiesOld as $c) {
|
||||||
|
if (isset($value['domain']) && $value['domain']) {
|
||||||
|
$regex = sprintf('@%s=.*domain=%s@', urlencode($name), preg_quote($value['domain']));
|
||||||
|
} else {
|
||||||
|
$regex = sprintf('@%s=@', urlencode($name));
|
||||||
|
}
|
||||||
|
if (preg_match($regex, $c) === 0) {
|
||||||
|
$cookiesNew[] = $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($cookiesNew) {
|
||||||
|
$header['Set-Cookie'] = implode("\n", $cookiesNew);
|
||||||
|
} else {
|
||||||
|
unset($header['Set-Cookie']);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set invalidating cookie to clear client-side cookie
|
||||||
|
self::setCookieHeader($header, $name, array_merge(array('value' => '', 'path' => null, 'domain' => null, 'expires' => time() - 100), $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse cookie header
|
||||||
|
*
|
||||||
|
* This method will parse the HTTP requst's `Cookie` header
|
||||||
|
* and extract cookies into an associative array.
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function parseCookieHeader($header)
|
||||||
|
{
|
||||||
|
$cookies = array();
|
||||||
|
$header = rtrim($header, "\r\n");
|
||||||
|
$headerPieces = preg_split('@\s*[;,]\s*@', $header);
|
||||||
|
foreach ($headerPieces as $c) {
|
||||||
|
$cParts = explode('=', $c);
|
||||||
|
if (count($cParts) === 2) {
|
||||||
|
$key = urldecode($cParts[0]);
|
||||||
|
$value = urldecode($cParts[1]);
|
||||||
|
if (!isset($cookies[$key])) {
|
||||||
|
$cookies[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cookies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random IV
|
||||||
|
*
|
||||||
|
* This method will generate a non-predictable IV for use with
|
||||||
|
* the cookie encryption
|
||||||
|
*
|
||||||
|
* @param int $expires The UNIX timestamp at which this cookie will expire
|
||||||
|
* @param string $secret The secret key used to hash the cookie value
|
||||||
|
* @return binary string with length 40
|
||||||
|
*/
|
||||||
|
private static function get_iv($expires, $secret)
|
||||||
|
{
|
||||||
|
$data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
|
||||||
|
$data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
|
||||||
|
|
||||||
|
return pack("h*", $data1.$data2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log
|
||||||
|
*
|
||||||
|
* This is the primary logger for a Slim application. You may provide
|
||||||
|
* a Log Writer in conjunction with this Log to write to various output
|
||||||
|
* destinations (e.g. a file). This class provides this interface:
|
||||||
|
*
|
||||||
|
* debug( mixed $object )
|
||||||
|
* info( mixed $object )
|
||||||
|
* warn( mixed $object )
|
||||||
|
* error( mixed $object )
|
||||||
|
* fatal( mixed $object )
|
||||||
|
*
|
||||||
|
* This class assumes only that your Log Writer has a public `write()` method
|
||||||
|
* that accepts any object as its one and only argument. The Log Writer
|
||||||
|
* class may write or send its argument anywhere: a file, STDERR,
|
||||||
|
* a remote web API, etc. The possibilities are endless.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Log
|
||||||
|
{
|
||||||
|
const FATAL = 0;
|
||||||
|
const ERROR = 1;
|
||||||
|
const WARN = 2;
|
||||||
|
const INFO = 3;
|
||||||
|
const DEBUG = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $levels = array(
|
||||||
|
self::FATAL => 'FATAL',
|
||||||
|
self::ERROR => 'ERROR',
|
||||||
|
self::WARN => 'WARN',
|
||||||
|
self::INFO => 'INFO',
|
||||||
|
self::DEBUG => 'DEBUG'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected $writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param mixed $writer
|
||||||
|
*/
|
||||||
|
public function __construct($writer)
|
||||||
|
{
|
||||||
|
$this->writer = $writer;
|
||||||
|
$this->enabled = true;
|
||||||
|
$this->level = self::DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is logging enabled?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getEnabled()
|
||||||
|
{
|
||||||
|
return $this->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable logging
|
||||||
|
* @param bool $enabled
|
||||||
|
*/
|
||||||
|
public function setEnabled($enabled)
|
||||||
|
{
|
||||||
|
if ($enabled) {
|
||||||
|
$this->enabled = true;
|
||||||
|
} else {
|
||||||
|
$this->enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set level
|
||||||
|
* @param int $level
|
||||||
|
* @throws \InvalidArgumentException If invalid log level specified
|
||||||
|
*/
|
||||||
|
public function setLevel($level)
|
||||||
|
{
|
||||||
|
if (!isset(self::$levels[$level])) {
|
||||||
|
throw new \InvalidArgumentException('Invalid log level');
|
||||||
|
}
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get level
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLevel()
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set writer
|
||||||
|
* @param mixed $writer
|
||||||
|
*/
|
||||||
|
public function setWriter($writer)
|
||||||
|
{
|
||||||
|
$this->writer = $writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get writer
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getWriter()
|
||||||
|
{
|
||||||
|
return $this->writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is logging enabled?
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEnabled()
|
||||||
|
{
|
||||||
|
return $this->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log debug message
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||||
|
*/
|
||||||
|
public function debug($object)
|
||||||
|
{
|
||||||
|
return $this->log($object, self::DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log info message
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||||
|
*/
|
||||||
|
public function info($object)
|
||||||
|
{
|
||||||
|
return $this->log($object, self::INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log warn message
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||||
|
*/
|
||||||
|
public function warn($object)
|
||||||
|
{
|
||||||
|
return $this->log($object, self::WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log error message
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||||
|
*/
|
||||||
|
public function error($object)
|
||||||
|
{
|
||||||
|
return $this->log($object, self::ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log fatal message
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed|false What the Logger returns, or false if Logger not set or not enabled
|
||||||
|
*/
|
||||||
|
public function fatal($object)
|
||||||
|
{
|
||||||
|
return $this->log($object, self::FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log message
|
||||||
|
* @param mixed The object to log
|
||||||
|
* @param int The message level
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
|
protected function log($object, $level)
|
||||||
|
{
|
||||||
|
if ($this->enabled && $this->writer && $level <= $this->level) {
|
||||||
|
return $this->writer->write($object, $level);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log Writer
|
||||||
|
*
|
||||||
|
* This class is used by Slim_Log to write log messages to a valid, writable
|
||||||
|
* resource handle (e.g. a file or STDERR).
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class LogWriter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
protected $resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param resource $resource
|
||||||
|
* @throws \InvalidArgumentException If invalid resource
|
||||||
|
*/
|
||||||
|
public function __construct($resource)
|
||||||
|
{
|
||||||
|
if (!is_resource($resource)) {
|
||||||
|
throw new \InvalidArgumentException('Cannot create LogWriter. Invalid resource handle.');
|
||||||
|
}
|
||||||
|
$this->resource = $resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write message
|
||||||
|
* @param mixed $message
|
||||||
|
* @param int $level
|
||||||
|
* @return int|false
|
||||||
|
*/
|
||||||
|
public function write($message, $level = null)
|
||||||
|
{
|
||||||
|
return fwrite($this->resource, (string) $message . PHP_EOL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
abstract class Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Slim Reference to the primary application instance
|
||||||
|
*/
|
||||||
|
protected $app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed Reference to the next downstream middleware
|
||||||
|
*/
|
||||||
|
protected $next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set application
|
||||||
|
*
|
||||||
|
* This method injects the primary Slim application instance into
|
||||||
|
* this middleware.
|
||||||
|
*
|
||||||
|
* @param \Slim $application
|
||||||
|
*/
|
||||||
|
final public function setApplication($application)
|
||||||
|
{
|
||||||
|
$this->app = $application;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get application
|
||||||
|
*
|
||||||
|
* This method retrieves the application previously injected
|
||||||
|
* into this middleware.
|
||||||
|
*
|
||||||
|
* @return \Slim
|
||||||
|
*/
|
||||||
|
final public function getApplication()
|
||||||
|
{
|
||||||
|
return $this->app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set next middleware
|
||||||
|
*
|
||||||
|
* This method injects the next downstream middleware into
|
||||||
|
* this middleware so that it may optionally be called
|
||||||
|
* when appropriate.
|
||||||
|
*
|
||||||
|
* @param \Slim|\Slim\Middleware
|
||||||
|
*/
|
||||||
|
final public function setNextMiddleware($nextMiddleware)
|
||||||
|
{
|
||||||
|
$this->next = $nextMiddleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get next middleware
|
||||||
|
*
|
||||||
|
* This method retrieves the next downstream middleware
|
||||||
|
* previously injected into this middleware.
|
||||||
|
*
|
||||||
|
* @return \Slim|\Slim\Middleware
|
||||||
|
*/
|
||||||
|
final public function getNextMiddleware()
|
||||||
|
{
|
||||||
|
return $this->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*
|
||||||
|
* Perform actions specific to this middleware and optionally
|
||||||
|
* call the next downstream middleware.
|
||||||
|
*/
|
||||||
|
abstract public function call();
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Middleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content Types
|
||||||
|
*
|
||||||
|
* This is middleware for a Slim application that intercepts
|
||||||
|
* the HTTP request body and parses it into the appropriate
|
||||||
|
* PHP data structure if possible; else it returns the HTTP
|
||||||
|
* request body unchanged. This is particularly useful
|
||||||
|
* for preparing the HTTP request body for an XML or JSON API.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class ContentTypes extends \Slim\Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $contentTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param array $settings
|
||||||
|
*/
|
||||||
|
public function __construct($settings = array())
|
||||||
|
{
|
||||||
|
$this->contentTypes = array_merge(array(
|
||||||
|
'application/json' => array($this, 'parseJson'),
|
||||||
|
'application/xml' => array($this, 'parseXml'),
|
||||||
|
'text/xml' => array($this, 'parseXml'),
|
||||||
|
'text/csv' => array($this, 'parseCsv')
|
||||||
|
), $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*/
|
||||||
|
public function call()
|
||||||
|
{
|
||||||
|
$mediaType = $this->app->request()->getMediaType();
|
||||||
|
if ($mediaType) {
|
||||||
|
$env = $this->app->environment();
|
||||||
|
$env['slim.input_original'] = $env['slim.input'];
|
||||||
|
$env['slim.input'] = $this->parse($env['slim.input'], $mediaType);
|
||||||
|
}
|
||||||
|
$this->next->call();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse input
|
||||||
|
*
|
||||||
|
* This method will attempt to parse the request body
|
||||||
|
* based on its content type if available.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param string $contentType
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function parse ($input, $contentType)
|
||||||
|
{
|
||||||
|
if (isset($this->contentTypes[$contentType]) && is_callable($this->contentTypes[$contentType])) {
|
||||||
|
$result = call_user_func($this->contentTypes[$contentType], $input);
|
||||||
|
if ($result) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse JSON
|
||||||
|
*
|
||||||
|
* This method converts the raw JSON input
|
||||||
|
* into an associative array.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
protected function parseJson($input)
|
||||||
|
{
|
||||||
|
if (function_exists('json_decode')) {
|
||||||
|
$result = json_decode($input, true);
|
||||||
|
if ($result) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse XML
|
||||||
|
*
|
||||||
|
* This method creates a SimpleXMLElement
|
||||||
|
* based upon the XML input. If the SimpleXML
|
||||||
|
* extension is not available, the raw input
|
||||||
|
* will be returned unchanged.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @return \SimpleXMLElement|string
|
||||||
|
*/
|
||||||
|
protected function parseXml($input)
|
||||||
|
{
|
||||||
|
if (class_exists('SimpleXMLElement')) {
|
||||||
|
try {
|
||||||
|
return new \SimpleXMLElement($input);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse CSV
|
||||||
|
*
|
||||||
|
* This method parses CSV content into a numeric array
|
||||||
|
* containing an array of data for each CSV line.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function parseCsv($input)
|
||||||
|
{
|
||||||
|
$temp = fopen('php://memory', 'rw');
|
||||||
|
fwrite($temp, $input);
|
||||||
|
fseek($temp, 0);
|
||||||
|
$res = array();
|
||||||
|
while (($data = fgetcsv($temp)) !== false) {
|
||||||
|
$res[] = $data;
|
||||||
|
}
|
||||||
|
fclose($temp);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Middleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flash
|
||||||
|
*
|
||||||
|
* This is middleware for a Slim application that enables
|
||||||
|
* Flash messaging between HTTP requests. This allows you
|
||||||
|
* set Flash messages for the current request, for the next request,
|
||||||
|
* or to retain messages from the previous request through to
|
||||||
|
* the next request.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class Flash extends \Slim\Middleware implements \ArrayAccess, \IteratorAggregate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $messages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param \Slim $app
|
||||||
|
* @param array $settings
|
||||||
|
*/
|
||||||
|
public function __construct($settings = array())
|
||||||
|
{
|
||||||
|
$this->settings = array_merge(array('key' => 'slim.flash'), $settings);
|
||||||
|
$this->messages = array(
|
||||||
|
'prev' => array(), //flash messages from prev request (loaded when middleware called)
|
||||||
|
'next' => array(), //flash messages for next request
|
||||||
|
'now' => array() //flash messages for current request
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*/
|
||||||
|
public function call()
|
||||||
|
{
|
||||||
|
//Read flash messaging from previous request if available
|
||||||
|
$this->loadMessages();
|
||||||
|
|
||||||
|
//Prepare flash messaging for current request
|
||||||
|
$env = $this->app->environment();
|
||||||
|
$env['slim.flash'] = $this;
|
||||||
|
$this->next->call();
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Now
|
||||||
|
*
|
||||||
|
* Specify a flash message for a given key to be shown for the current request
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function now($key, $value)
|
||||||
|
{
|
||||||
|
$this->messages['now'][(string) $key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set
|
||||||
|
*
|
||||||
|
* Specify a flash message for a given key to be shown for the next request
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function set($key, $value)
|
||||||
|
{
|
||||||
|
$this->messages['next'][(string) $key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep
|
||||||
|
*
|
||||||
|
* Retain flash messages from the previous request for the next request
|
||||||
|
*/
|
||||||
|
public function keep()
|
||||||
|
{
|
||||||
|
foreach ($this->messages['prev'] as $key => $val) {
|
||||||
|
$this->messages['next'][$key] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$_SESSION[$this->settings['key']] = $this->messages['next'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load messages from previous request if available
|
||||||
|
*/
|
||||||
|
public function loadMessages()
|
||||||
|
{
|
||||||
|
if (isset($_SESSION[$this->settings['key']])) {
|
||||||
|
$this->messages['prev'] = $_SESSION[$this->settings['key']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return array of flash messages to be shown for the current request
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMessages()
|
||||||
|
{
|
||||||
|
return array_merge($this->messages['prev'], $this->messages['now']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Exists
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
$messages = $this->getMessages();
|
||||||
|
|
||||||
|
return isset($messages[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Get
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
$messages = $this->getMessages();
|
||||||
|
|
||||||
|
return isset($messages[$offset]) ? $messages[$offset] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Set
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->now($offset, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array Access: Offset Unset
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
unset($this->messages['prev'][$offset], $this->messages['now'][$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Aggregate: Get Iterator
|
||||||
|
* @return \ArrayIterator
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
$messages = $this->getMessages();
|
||||||
|
|
||||||
|
return new \ArrayIterator($messages);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Middleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Method Override
|
||||||
|
*
|
||||||
|
* This is middleware for a Slim application that allows traditional
|
||||||
|
* desktop browsers to submit psuedo PUT and DELETE requests by relying
|
||||||
|
* on a pre-determined request parameter. Without this middleware,
|
||||||
|
* desktop browsers are only able to submit GET and POST requests.
|
||||||
|
*
|
||||||
|
* This middleware is included automatically!
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class MethodOverride extends \Slim\Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param \Slim $app
|
||||||
|
* @param array $settings
|
||||||
|
*/
|
||||||
|
public function __construct($settings = array())
|
||||||
|
{
|
||||||
|
$this->settings = array_merge(array('key' => '_METHOD'), $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*
|
||||||
|
* Implements Slim middleware interface. This method is invoked and passed
|
||||||
|
* an array of environment variables. This middleware inspects the environment
|
||||||
|
* variables for the HTTP method override parameter; if found, this middleware
|
||||||
|
* modifies the environment settings so downstream middleware and/or the Slim
|
||||||
|
* application will treat the request with the desired HTTP method.
|
||||||
|
*
|
||||||
|
* @param array $env
|
||||||
|
* @return array[status, header, body]
|
||||||
|
*/
|
||||||
|
public function call()
|
||||||
|
{
|
||||||
|
$env = $this->app->environment();
|
||||||
|
if (isset($env['X_HTTP_METHOD_OVERRIDE'])) {
|
||||||
|
// Header commonly used by Backbone.js and others
|
||||||
|
$env['slim.method_override.original_method'] = $env['REQUEST_METHOD'];
|
||||||
|
$env['REQUEST_METHOD'] = strtoupper($env['X_HTTP_METHOD_OVERRIDE']);
|
||||||
|
} elseif (isset($env['REQUEST_METHOD']) && $env['REQUEST_METHOD'] === 'POST') {
|
||||||
|
// HTML Form Override
|
||||||
|
$req = new \Slim\Http\Request($env);
|
||||||
|
$method = $req->post($this->settings['key']);
|
||||||
|
if ($method) {
|
||||||
|
$env['slim.method_override.original_method'] = $env['REQUEST_METHOD'];
|
||||||
|
$env['REQUEST_METHOD'] = strtoupper($method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->next->call();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Middleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pretty Exceptions
|
||||||
|
*
|
||||||
|
* This middleware catches any Exception thrown by the surrounded
|
||||||
|
* application and displays a developer-friendly diagnostic screen.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class PrettyExceptions extends \Slim\Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param array $settings
|
||||||
|
*/
|
||||||
|
public function __construct($settings = array())
|
||||||
|
{
|
||||||
|
$this->settings = $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*/
|
||||||
|
public function call()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->next->call();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$env = $this->app->environment();
|
||||||
|
$env['slim.log']->error($e);
|
||||||
|
$this->app->contentType('text/html');
|
||||||
|
$this->app->response()->status(500);
|
||||||
|
$this->app->response()->body($this->renderBody($env, $e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render response body
|
||||||
|
* @param array $env
|
||||||
|
* @param \Exception $exception
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function renderBody(&$env, $exception)
|
||||||
|
{
|
||||||
|
$title = 'Slim Application Error';
|
||||||
|
$code = $exception->getCode();
|
||||||
|
$message = $exception->getMessage();
|
||||||
|
$file = $exception->getFile();
|
||||||
|
$line = $exception->getLine();
|
||||||
|
$trace = $exception->getTraceAsString();
|
||||||
|
$html = sprintf('<h1>%s</h1>', $title);
|
||||||
|
$html .= '<p>The application could not run because of the following error:</p>';
|
||||||
|
$html .= '<h2>Details</h2>';
|
||||||
|
if ($code) {
|
||||||
|
$html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
|
||||||
|
}
|
||||||
|
if ($message) {
|
||||||
|
$html .= sprintf('<div><strong>Message:</strong> %s</div>', $message);
|
||||||
|
}
|
||||||
|
if ($file) {
|
||||||
|
$html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
|
||||||
|
}
|
||||||
|
if ($line) {
|
||||||
|
$html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
|
||||||
|
}
|
||||||
|
if ($trace) {
|
||||||
|
$html .= '<h2>Trace</h2>';
|
||||||
|
$html .= sprintf('<pre>%s</pre>', $trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf("<html><head><title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}</style></head><body>%s</body></html>", $title, $html);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim\Middleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session Cookie
|
||||||
|
*
|
||||||
|
* This class provides an HTTP cookie storage mechanism
|
||||||
|
* for session data. This class avoids using a PHP session
|
||||||
|
* and instead serializes/unserializes the $_SESSION global
|
||||||
|
* variable to/from an HTTP cookie.
|
||||||
|
*
|
||||||
|
* If a secret key is provided with this middleware, the HTTP
|
||||||
|
* cookie will be checked for integrity to ensure the client-side
|
||||||
|
* cookie is not changed.
|
||||||
|
*
|
||||||
|
* You should NEVER store sensitive data in a client-side cookie
|
||||||
|
* in any format, encrypted or not. If you need to store sensitive
|
||||||
|
* user information in a session, you should rely on PHP's native
|
||||||
|
* session implementation, or use other middleware to store
|
||||||
|
* session data in a database or alternative server-side cache.
|
||||||
|
*
|
||||||
|
* Because this class stores serialized session data in an HTTP cookie,
|
||||||
|
* you are inherently limtied to 4 Kb. If you attempt to store
|
||||||
|
* more than this amount, serialization will fail.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
class SessionCookie extends \Slim\Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param array $settings
|
||||||
|
*/
|
||||||
|
public function __construct($settings = array())
|
||||||
|
{
|
||||||
|
$this->settings = array_merge(array(
|
||||||
|
'expires' => '20 minutes',
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => null,
|
||||||
|
'secure' => false,
|
||||||
|
'httponly' => false,
|
||||||
|
'name' => 'slim_session',
|
||||||
|
'secret' => 'CHANGE_ME',
|
||||||
|
'cipher' => MCRYPT_RIJNDAEL_256,
|
||||||
|
'cipher_mode' => MCRYPT_MODE_CBC
|
||||||
|
), $settings);
|
||||||
|
if (is_string($this->settings['expires'])) {
|
||||||
|
$this->settings['expires'] = strtotime($this->settings['expires']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session
|
||||||
|
*
|
||||||
|
* We must start a native PHP session to initialize the $_SESSION superglobal.
|
||||||
|
* However, we won't be using the native session store for persistence, so we
|
||||||
|
* disable the session cookie and cache limiter. We also set the session
|
||||||
|
* handler to this class instance to avoid PHP's native session file locking.
|
||||||
|
*/
|
||||||
|
ini_set('session.use_cookies', 0);
|
||||||
|
session_cache_limiter(false);
|
||||||
|
session_set_save_handler(
|
||||||
|
array($this, 'open'),
|
||||||
|
array($this, 'close'),
|
||||||
|
array($this, 'read'),
|
||||||
|
array($this, 'write'),
|
||||||
|
array($this, 'destroy'),
|
||||||
|
array($this, 'gc')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call
|
||||||
|
*/
|
||||||
|
public function call()
|
||||||
|
{
|
||||||
|
$this->loadSession();
|
||||||
|
$this->next->call();
|
||||||
|
$this->saveSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load session
|
||||||
|
* @param array $env
|
||||||
|
*/
|
||||||
|
protected function loadSession()
|
||||||
|
{
|
||||||
|
if (session_id() === '') {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = \Slim\Http\Util::decodeSecureCookie(
|
||||||
|
$this->app->request()->cookies($this->settings['name']),
|
||||||
|
$this->settings['secret'],
|
||||||
|
$this->settings['cipher'],
|
||||||
|
$this->settings['cipher_mode']
|
||||||
|
);
|
||||||
|
if ($value) {
|
||||||
|
$_SESSION = unserialize($value);
|
||||||
|
} else {
|
||||||
|
$_SESSION = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save session
|
||||||
|
*/
|
||||||
|
protected function saveSession()
|
||||||
|
{
|
||||||
|
$value = \Slim\Http\Util::encodeSecureCookie(
|
||||||
|
serialize($_SESSION),
|
||||||
|
$this->settings['expires'],
|
||||||
|
$this->settings['secret'],
|
||||||
|
$this->settings['cipher'],
|
||||||
|
$this->settings['cipher_mode']
|
||||||
|
);
|
||||||
|
if (strlen($value) > 4096) {
|
||||||
|
$this->app->getLog()->error('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.');
|
||||||
|
} else {
|
||||||
|
$this->app->response()->setCookie($this->settings['name'], array(
|
||||||
|
'value' => $value,
|
||||||
|
'domain' => $this->settings['domain'],
|
||||||
|
'path' => $this->settings['path'],
|
||||||
|
'expires' => $this->settings['expires'],
|
||||||
|
'secure' => $this->settings['secure'],
|
||||||
|
'httponly' => $this->settings['httponly']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Session Handler
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
public function open($savePath, $sessionName)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read($id)
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($id, $data)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function gc($maxlifetime)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,407 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart, Thomas Bley
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Route
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string The route pattern (e.g. "/books/:id")
|
||||||
|
*/
|
||||||
|
protected $pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed The route callable
|
||||||
|
*/
|
||||||
|
protected $callable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Conditions for this route's URL parameters
|
||||||
|
*/
|
||||||
|
protected $conditions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Default conditions applied to all route instances
|
||||||
|
*/
|
||||||
|
protected static $defaultConditions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string The name of this route (optional)
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Key-value array of URL parameters
|
||||||
|
*/
|
||||||
|
protected $params = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array value array of URL parameter names
|
||||||
|
*/
|
||||||
|
protected $paramNames = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array key array of URL parameter names with + at the end
|
||||||
|
*/
|
||||||
|
protected $paramNamesPath = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array HTTP methods supported by this Route
|
||||||
|
*/
|
||||||
|
protected $methods = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[Callable] Middleware to be run before only this route instance
|
||||||
|
*/
|
||||||
|
protected $middleware = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param string $pattern The URL pattern (e.g. "/books/:id")
|
||||||
|
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||||
|
*/
|
||||||
|
public function __construct($pattern, $callable)
|
||||||
|
{
|
||||||
|
$this->setPattern($pattern);
|
||||||
|
$this->setCallable($callable);
|
||||||
|
$this->setConditions(self::getDefaultConditions());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default route conditions for all instances
|
||||||
|
* @param array $defaultConditions
|
||||||
|
*/
|
||||||
|
public static function setDefaultConditions(array $defaultConditions)
|
||||||
|
{
|
||||||
|
self::$defaultConditions = $defaultConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default route conditions for all instances
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getDefaultConditions()
|
||||||
|
{
|
||||||
|
return self::$defaultConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route pattern
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPattern()
|
||||||
|
{
|
||||||
|
return $this->pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route pattern
|
||||||
|
* @param string $pattern
|
||||||
|
*/
|
||||||
|
public function setPattern($pattern)
|
||||||
|
{
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route callable
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getCallable()
|
||||||
|
{
|
||||||
|
return $this->callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route callable
|
||||||
|
* @param mixed $callable
|
||||||
|
*/
|
||||||
|
public function setCallable($callable)
|
||||||
|
{
|
||||||
|
$this->callable = $callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route conditions
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConditions()
|
||||||
|
{
|
||||||
|
return $this->conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route conditions
|
||||||
|
* @param array $conditions
|
||||||
|
*/
|
||||||
|
public function setConditions(array $conditions)
|
||||||
|
{
|
||||||
|
$this->conditions = $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route name
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route name
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = (string) $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route parameters
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getParams()
|
||||||
|
{
|
||||||
|
return $this->params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route parameters
|
||||||
|
* @param array $params
|
||||||
|
*/
|
||||||
|
public function setParams($params)
|
||||||
|
{
|
||||||
|
$this->params = $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route parameter value
|
||||||
|
* @param string $index Name of URL parameter
|
||||||
|
* @return string
|
||||||
|
* @throws \InvalidArgumentException If route parameter does not exist at index
|
||||||
|
*/
|
||||||
|
public function getParam($index)
|
||||||
|
{
|
||||||
|
if (!isset($this->params[$index])) {
|
||||||
|
throw new \InvalidArgumentException('Route parameter does not exist at specified index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->params[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route parameter value
|
||||||
|
* @param string $index Name of URL parameter
|
||||||
|
* @param mixed $value The new parameter value
|
||||||
|
* @throws \InvalidArgumentException If route parameter does not exist at index
|
||||||
|
*/
|
||||||
|
public function setParam($index, $value)
|
||||||
|
{
|
||||||
|
if (!isset($this->params[$index])) {
|
||||||
|
throw new \InvalidArgumentException('Route parameter does not exist at specified index');
|
||||||
|
}
|
||||||
|
$this->params[$index] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add supported HTTP method(s)
|
||||||
|
*/
|
||||||
|
public function setHttpMethods()
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$this->methods = $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get supported HTTP methods
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getHttpMethods()
|
||||||
|
{
|
||||||
|
return $this->methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append supported HTTP methods
|
||||||
|
*/
|
||||||
|
public function appendHttpMethods()
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$this->methods = array_merge($this->methods, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append supported HTTP methods (alias for Route::appendHttpMethods)
|
||||||
|
* @return \Slim\Route
|
||||||
|
*/
|
||||||
|
public function via()
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
$this->methods = array_merge($this->methods, $args);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect support for an HTTP method
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function supportsHttpMethod($method)
|
||||||
|
{
|
||||||
|
return in_array($method, $this->methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get middleware
|
||||||
|
* @return array[Callable]
|
||||||
|
*/
|
||||||
|
public function getMiddleware()
|
||||||
|
{
|
||||||
|
return $this->middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set middleware
|
||||||
|
*
|
||||||
|
* This method allows middleware to be assigned to a specific Route.
|
||||||
|
* If the method argument `is_callable` (including callable arrays!),
|
||||||
|
* we directly append the argument to `$this->middleware`. Else, we
|
||||||
|
* assume the argument is an array of callables and merge the array
|
||||||
|
* with `$this->middleware`. Even if non-callables are included in the
|
||||||
|
* argument array, we still merge them; we lazily check each item
|
||||||
|
* against `is_callable` during Router::dispatch().
|
||||||
|
*
|
||||||
|
* @param Callable|array[Callable]
|
||||||
|
* @return \Slim\Route
|
||||||
|
* @throws \InvalidArgumentException If argument is not callable or not an array
|
||||||
|
*/
|
||||||
|
public function setMiddleware($middleware)
|
||||||
|
{
|
||||||
|
if (is_callable($middleware)) {
|
||||||
|
$this->middleware[] = $middleware;
|
||||||
|
} elseif (is_array($middleware)) {
|
||||||
|
$this->middleware = array_merge($this->middleware, $middleware);
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException('Route middleware must be callable or an array of callables');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches URI?
|
||||||
|
*
|
||||||
|
* Parse this route's pattern, and then compare it to an HTTP resource URI
|
||||||
|
* This method was modeled after the techniques demonstrated by Dan Sosedoff at:
|
||||||
|
*
|
||||||
|
* http://blog.sosedoff.com/2009/09/20/rails-like-php-url-router/
|
||||||
|
*
|
||||||
|
* @param string $resourceUri A Request URI
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function matches($resourceUri)
|
||||||
|
{
|
||||||
|
//Convert URL params into regex patterns, construct a regex for this route, init params
|
||||||
|
$patternAsRegex = preg_replace_callback('#:([\w]+)\+?#', array($this, 'matchesCallback'),
|
||||||
|
str_replace(')', ')?', (string) $this->pattern));
|
||||||
|
if (substr($this->pattern, -1) === '/') {
|
||||||
|
$patternAsRegex .= '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
//Cache URL params' names and values if this route matches the current HTTP request
|
||||||
|
if (!preg_match('#^' . $patternAsRegex . '$#', $resourceUri, $paramValues)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($this->paramNames as $name) {
|
||||||
|
if (isset($paramValues[$name])) {
|
||||||
|
if (isset($this->paramNamesPath[ $name ])) {
|
||||||
|
$this->params[$name] = explode('/', urldecode($paramValues[$name]));
|
||||||
|
} else {
|
||||||
|
$this->params[$name] = urldecode($paramValues[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a URL parameter (e.g. ":id", ":id+") into a regular expression
|
||||||
|
* @param array URL parameters
|
||||||
|
* @return string Regular expression for URL parameter
|
||||||
|
*/
|
||||||
|
protected function matchesCallback($m)
|
||||||
|
{
|
||||||
|
$this->paramNames[] = $m[1];
|
||||||
|
if (isset($this->conditions[ $m[1] ])) {
|
||||||
|
return '(?P<' . $m[1] . '>' . $this->conditions[ $m[1] ] . ')';
|
||||||
|
}
|
||||||
|
if (substr($m[0], -1) === '+') {
|
||||||
|
$this->paramNamesPath[ $m[1] ] = 1;
|
||||||
|
|
||||||
|
return '(?P<' . $m[1] . '>.+)';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '(?P<' . $m[1] . '>[^/]+)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set route name
|
||||||
|
* @param string $name The name of the route
|
||||||
|
* @return \Slim\Route
|
||||||
|
*/
|
||||||
|
public function name($name)
|
||||||
|
{
|
||||||
|
$this->setName($name);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge route conditions
|
||||||
|
* @param array $conditions Key-value array of URL parameter conditions
|
||||||
|
* @return \Slim\Route
|
||||||
|
*/
|
||||||
|
public function conditions(array $conditions)
|
||||||
|
{
|
||||||
|
$this->conditions = array_merge($this->conditions, $conditions);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,337 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Router
|
||||||
|
*
|
||||||
|
* This class organizes, iterates, and dispatches \Slim\Route objects.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Router implements \Iterator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string Request URI
|
||||||
|
*/
|
||||||
|
protected $resourceUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Lookup hash of all route objects
|
||||||
|
*/
|
||||||
|
protected $routes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Lookup hash of named route objects, keyed by route name (lazy-loaded)
|
||||||
|
*/
|
||||||
|
protected $namedRoutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Array of route objects that match the request URI (lazy-loaded)
|
||||||
|
*/
|
||||||
|
protected $matchedRoutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed Callable to be invoked if no matching route objects are found
|
||||||
|
*/
|
||||||
|
protected $notFound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed Callable to be invoked if application error
|
||||||
|
*/
|
||||||
|
protected $error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->routes = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Resource URI
|
||||||
|
*
|
||||||
|
* This method injects the current request's resource URI. This method should be invoked
|
||||||
|
* only immediately before router iteration.
|
||||||
|
*
|
||||||
|
* @param string $uri The request URI
|
||||||
|
*/
|
||||||
|
public function setResourceUri($uri)
|
||||||
|
{
|
||||||
|
$this->resourceUri = $uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Current Route object
|
||||||
|
* @return \Slim\Route|false
|
||||||
|
*/
|
||||||
|
public function getCurrentRoute()
|
||||||
|
{
|
||||||
|
$this->getMatchedRoutes(); // <-- Parse if not already parsed
|
||||||
|
|
||||||
|
return $this->current();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return route objects that match the current request URI
|
||||||
|
* @param bool $reload Should matching routes be re-parsed?
|
||||||
|
* @return array[\Slim\Route]
|
||||||
|
*/
|
||||||
|
public function getMatchedRoutes($reload = false)
|
||||||
|
{
|
||||||
|
if ($reload || is_null($this->matchedRoutes)) {
|
||||||
|
$this->matchedRoutes = array();
|
||||||
|
foreach ($this->routes as $route) {
|
||||||
|
if ($route->matches($this->resourceUri)) {
|
||||||
|
$this->matchedRoutes[] = $route;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->matchedRoutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a route object to a callback function
|
||||||
|
* @param string $pattern The URL pattern (ie. "/books/:id")
|
||||||
|
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||||
|
* @return \Slim\Route
|
||||||
|
*/
|
||||||
|
public function map($pattern, $callable)
|
||||||
|
{
|
||||||
|
$route = new \Slim\Route($pattern, $callable);
|
||||||
|
$this->routes[] = $route;
|
||||||
|
|
||||||
|
return $route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get URL for named route
|
||||||
|
* @param string $name The name of the route
|
||||||
|
* @param array Associative array of URL parameter names and replacement values
|
||||||
|
* @throws RuntimeException If named route not found
|
||||||
|
* @return string The URL for the given route populated with provided replacement values
|
||||||
|
*/
|
||||||
|
public function urlFor($name, $params = array())
|
||||||
|
{
|
||||||
|
if (!$this->hasNamedRoute($name)) {
|
||||||
|
throw new \RuntimeException('Named route not found for name: ' . $name);
|
||||||
|
}
|
||||||
|
$search = array();
|
||||||
|
foreach (array_keys($params) as $key) {
|
||||||
|
$search[] = '#:' . $key . '\+?(?!\w)#';
|
||||||
|
}
|
||||||
|
$pattern = preg_replace($search, $params, $this->getNamedRoute($name)->getPattern());
|
||||||
|
|
||||||
|
//Remove remnants of unpopulated, trailing optional pattern segments
|
||||||
|
return preg_replace('#\(/?:.+\)|\(|\)#', '', $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch route
|
||||||
|
*
|
||||||
|
* This method invokes the route object's callable. If middleware is
|
||||||
|
* registered for the route, each callable middleware is invoked in
|
||||||
|
* the order specified.
|
||||||
|
*
|
||||||
|
* This method is smart about trailing slashes on the route pattern.
|
||||||
|
* If the route's pattern is defined with a trailing slash, and if the
|
||||||
|
* current request URI does not have a trailing slash but otherwise
|
||||||
|
* matches the route's pattern, a Slim_Exception_RequestSlash
|
||||||
|
* will be thrown triggering an HTTP 301 Permanent Redirect to the same
|
||||||
|
* URI _with_ a trailing slash. This Exception is caught in the
|
||||||
|
* `Slim::call` loop. If the route's pattern is defined without a
|
||||||
|
* trailing slash, and if the current request URI does have a trailing
|
||||||
|
* slash, the route will not be matched and a 404 Not Found
|
||||||
|
* response will be sent if no subsequent matching routes are found.
|
||||||
|
*
|
||||||
|
* @param \Slim\Route $route The route object
|
||||||
|
* @return bool Was route callable invoked successfully?
|
||||||
|
* @throws \Slim\Exception\RequestSlash
|
||||||
|
*/
|
||||||
|
public function dispatch(\Slim\Route $route)
|
||||||
|
{
|
||||||
|
if (substr($route->getPattern(), -1) === '/' && substr($this->resourceUri, -1) !== '/') {
|
||||||
|
throw new Exception\RequestSlash();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Invoke middleware
|
||||||
|
foreach ($route->getMiddleware() as $mw) {
|
||||||
|
if (is_callable($mw)) {
|
||||||
|
call_user_func_array($mw, array($route));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Invoke callable
|
||||||
|
if (is_callable($route->getCallable())) {
|
||||||
|
call_user_func_array($route->getCallable(), array_values($route->getParams()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add named route
|
||||||
|
* @param string $name The route name
|
||||||
|
* @param \Slim\Route $route The route object
|
||||||
|
* @throws \RuntimeException If a named route already exists with the same name
|
||||||
|
*/
|
||||||
|
public function addNamedRoute($name, \Slim\Route $route)
|
||||||
|
{
|
||||||
|
if ($this->hasNamedRoute($name)) {
|
||||||
|
throw new \RuntimeException('Named route already exists with name: ' . $name);
|
||||||
|
}
|
||||||
|
$this->namedRoutes[(string) $name] = $route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has named route
|
||||||
|
* @param string $name The route name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasNamedRoute($name)
|
||||||
|
{
|
||||||
|
$this->getNamedRoutes();
|
||||||
|
|
||||||
|
return isset($this->namedRoutes[(string) $name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get named route
|
||||||
|
* @param string $name
|
||||||
|
* @return \Slim\Route|null
|
||||||
|
*/
|
||||||
|
public function getNamedRoute($name)
|
||||||
|
{
|
||||||
|
$this->getNamedRoutes();
|
||||||
|
if ($this->hasNamedRoute($name)) {
|
||||||
|
return $this->namedRoutes[(string) $name];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get named routes
|
||||||
|
* @return \ArrayIterator
|
||||||
|
*/
|
||||||
|
public function getNamedRoutes()
|
||||||
|
{
|
||||||
|
if (is_null($this->namedRoutes)) {
|
||||||
|
$this->namedRoutes = array();
|
||||||
|
foreach ($this->routes as $route) {
|
||||||
|
if ($route->getName() !== null) {
|
||||||
|
$this->addNamedRoute($route->getName(), $route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new \ArrayIterator($this->namedRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a 404 Not Found callback
|
||||||
|
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function notFound($callable = null)
|
||||||
|
{
|
||||||
|
if (is_callable($callable)) {
|
||||||
|
$this->notFound = $callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->notFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a 500 Error callback
|
||||||
|
* @param mixed $callable Anything that returns TRUE for is_callable()
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function error($callable = null)
|
||||||
|
{
|
||||||
|
if (is_callable($callable)) {
|
||||||
|
$this->error = $callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Interface: Rewind
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
reset($this->matchedRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Interface: Current
|
||||||
|
* @return \Slim\Route|false
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return current($this->matchedRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Interface: Key
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
return key($this->matchedRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Interface: Next
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
next($this->matchedRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator Interface: Valid
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
return $this->current();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Slim - a micro PHP 5 framework
|
||||||
|
*
|
||||||
|
* @author Josh Lockhart <info@slimframework.com>
|
||||||
|
* @copyright 2011 Josh Lockhart
|
||||||
|
* @link http://www.slimframework.com
|
||||||
|
* @license http://www.slimframework.com/license
|
||||||
|
* @version 2.0.0
|
||||||
|
* @package Slim
|
||||||
|
*
|
||||||
|
* MIT LICENSE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
namespace Slim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View
|
||||||
|
*
|
||||||
|
* The view is responsible for rendering a template. The view
|
||||||
|
* should subclass \Slim\View and implement this interface:
|
||||||
|
*
|
||||||
|
* public render(string $template);
|
||||||
|
*
|
||||||
|
* This method should render the specified template and return
|
||||||
|
* the resultant string.
|
||||||
|
*
|
||||||
|
* @package Slim
|
||||||
|
* @author Josh Lockhart
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class View
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string Absolute or relative filesystem path to a specific template
|
||||||
|
*
|
||||||
|
* DEPRECATION WARNING!
|
||||||
|
* This variable will be removed in the near future
|
||||||
|
*/
|
||||||
|
protected $templatePath = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Associative array of template variables
|
||||||
|
*/
|
||||||
|
protected $data = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Absolute or relative path to the application's templates directory
|
||||||
|
*/
|
||||||
|
protected $templatesDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* This is empty but may be implemented in a subclass
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get data
|
||||||
|
* @param string|null $key
|
||||||
|
* @return mixed If key is null, array of template data;
|
||||||
|
* If key exists, value of datum with key;
|
||||||
|
* If key does not exist, null;
|
||||||
|
*/
|
||||||
|
public function getData($key = null)
|
||||||
|
{
|
||||||
|
if (!is_null($key)) {
|
||||||
|
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||||
|
} else {
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set data
|
||||||
|
*
|
||||||
|
* If two arguments:
|
||||||
|
* A single datum with key is assigned value;
|
||||||
|
*
|
||||||
|
* $view->setData('color', 'red');
|
||||||
|
*
|
||||||
|
* If one argument:
|
||||||
|
* Replace all data with provided array keys and values;
|
||||||
|
*
|
||||||
|
* $view->setData(array('color' => 'red', 'number' => 1));
|
||||||
|
*
|
||||||
|
* @param mixed
|
||||||
|
* @param mixed
|
||||||
|
* @throws InvalidArgumentException If incorrect method signature
|
||||||
|
*/
|
||||||
|
public function setData()
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
if (count($args) === 1 && is_array($args[0])) {
|
||||||
|
$this->data = $args[0];
|
||||||
|
} elseif (count($args) === 2) {
|
||||||
|
$this->data[(string) $args[0]] = $args[1];
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append new data to existing template data
|
||||||
|
* @param array
|
||||||
|
* @throws InvalidArgumentException If not given an array argument
|
||||||
|
*/
|
||||||
|
public function appendData($data)
|
||||||
|
{
|
||||||
|
if (!is_array($data)) {
|
||||||
|
throw new \InvalidArgumentException('Cannot append view data. Expected array argument.');
|
||||||
|
}
|
||||||
|
$this->data = array_merge($this->data, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get templates directory
|
||||||
|
* @return string|null Path to templates directory without trailing slash;
|
||||||
|
* Returns null if templates directory not set;
|
||||||
|
*/
|
||||||
|
public function getTemplatesDirectory()
|
||||||
|
{
|
||||||
|
return $this->templatesDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set templates directory
|
||||||
|
* @param string $dir
|
||||||
|
*/
|
||||||
|
public function setTemplatesDirectory($dir)
|
||||||
|
{
|
||||||
|
$this->templatesDirectory = rtrim($dir, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set template
|
||||||
|
* @param string $template
|
||||||
|
* @throws RuntimeException If template file does not exist
|
||||||
|
*
|
||||||
|
* DEPRECATION WARNING!
|
||||||
|
* This method will be removed in the near future.
|
||||||
|
*/
|
||||||
|
public function setTemplate($template)
|
||||||
|
{
|
||||||
|
$this->templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/');
|
||||||
|
if (!file_exists($this->templatePath)) {
|
||||||
|
throw new \RuntimeException('View cannot render template `' . $this->templatePath . '`. Template does not exist.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display template
|
||||||
|
*
|
||||||
|
* This method echoes the rendered template to the current output buffer
|
||||||
|
*
|
||||||
|
* @param string $template Pathname of template file relative to templates directoy
|
||||||
|
*/
|
||||||
|
public function display($template)
|
||||||
|
{
|
||||||
|
echo $this->fetch($template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch rendered template
|
||||||
|
*
|
||||||
|
* This method returns the rendered template
|
||||||
|
*
|
||||||
|
* @param string $template Pathname of template file relative to templates directory
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function fetch($template)
|
||||||
|
{
|
||||||
|
return $this->render($template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render template
|
||||||
|
*
|
||||||
|
* @param string $template Pathname of template file relative to templates directory
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* DEPRECATION WARNING!
|
||||||
|
* Use `\Slim\View::fetch` to return a rendered template instead of `\Slim\View::render`.
|
||||||
|
*/
|
||||||
|
public function render($template)
|
||||||
|
{
|
||||||
|
$this->setTemplate($template);
|
||||||
|
extract($this->data);
|
||||||
|
ob_start();
|
||||||
|
require $this->templatePath;
|
||||||
|
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue