git-svn-id: https://msi/svn/firstRepo/Service/branches/Slim3@39 0f545695-f87b-41b6-9a03-7f16563b5454
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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())
|
||||
{
|
||||
$defaults = 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')
|
||||
);
|
||||
self::$environment = new self(array_merge($defaults, $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'];
|
||||
|
||||
// Server params
|
||||
$scriptName = $_SERVER['SCRIPT_NAME']; // <-- "/foo/index.php"
|
||||
$requestUri = $_SERVER['REQUEST_URI']; // <-- "/foo/bar?test=abc" or "/foo/index.php/bar?test=abc"
|
||||
$queryString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; // <-- "test=abc" or ""
|
||||
|
||||
// Physical path
|
||||
if (strpos($requestUri, $scriptName) !== false) {
|
||||
$physicalPath = $scriptName; // <-- Without rewriting
|
||||
} else {
|
||||
$physicalPath = str_replace('\\', '', dirname($scriptName)); // <-- With rewriting
|
||||
}
|
||||
$env['SCRIPT_NAME'] = rtrim($physicalPath, '/'); // <-- Remove trailing slashes
|
||||
|
||||
// Virtual path
|
||||
$env['PATH_INFO'] = substr_replace($requestUri, '', 0, strlen($physicalPath)); // <-- Remove physical path
|
||||
$env['PATH_INFO'] = str_replace('?' . $queryString, '', $env['PATH_INFO']); // <-- Remove query string
|
||||
$env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); // <-- Ensure leading slash
|
||||
|
||||
// Query string (without leading "?")
|
||||
$env['QUERY_STRING'] = $queryString;
|
||||
|
||||
//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 (retains HTTP_ prefix to match $_SERVER)
|
||||
$headers = \Slim\Http\Headers::extract($_SERVER);
|
||||
foreach ($headers as $key => $value) {
|
||||
$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 multipart/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,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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,246 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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\Helper;
|
||||
|
||||
class Set implements \ArrayAccess, \Countable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Key-value array of arbitrary data
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param array $items Pre-populate set with this key-value array
|
||||
*/
|
||||
public function __construct($items = array())
|
||||
{
|
||||
$this->replace($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize data key
|
||||
*
|
||||
* Used to transform data key into the necessary
|
||||
* key format for this set. Used in subclasses
|
||||
* like \Slim\Http\Headers.
|
||||
*
|
||||
* @param string $key The data key
|
||||
* @return mixed The transformed/normalized data key
|
||||
*/
|
||||
protected function normalizeKey($key)
|
||||
{
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data key to value
|
||||
* @param string $key The data key
|
||||
* @param mixed $value The data value
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->data[$this->normalizeKey($key)] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data value with key
|
||||
* @param string $key The data key
|
||||
* @param mixed $default The value to return if data key does not exist
|
||||
* @return mixed The data value, or the default value
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ($this->has($key)) {
|
||||
$isInvokable = is_object($this->data[$this->normalizeKey($key)]) && method_exists($this->data[$this->normalizeKey($key)], '__invoke');
|
||||
|
||||
return $isInvokable ? $this->data[$this->normalizeKey($key)]($this) : $this->data[$this->normalizeKey($key)];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to set
|
||||
* @param array $items Key-value array of data to append to this set
|
||||
*/
|
||||
public function replace($items)
|
||||
{
|
||||
foreach ($items as $key => $value) {
|
||||
$this->set($key, $value); // Ensure keys are normalized
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch set data
|
||||
* @return array This set's key-value data array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch set data keys
|
||||
* @return array This set's key-value data array keys
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this set contain a key?
|
||||
* @param string $key The data key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return array_key_exists($this->normalizeKey($key), $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove value with key from this set
|
||||
* @param string $key The data key
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
unset($this->data[$this->normalizeKey($key)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Property Overloading
|
||||
*/
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->set($key, $value);
|
||||
}
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->has($key);
|
||||
}
|
||||
|
||||
public function __unset($key)
|
||||
{
|
||||
return $this->remove($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all values
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Array Access
|
||||
*/
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Countable
|
||||
*/
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* IteratorAggregate
|
||||
*/
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a value or object will remain globally unique
|
||||
* @param string $key The value or object name
|
||||
* @param Closure The closure that defines the object
|
||||
* @return mixed
|
||||
*/
|
||||
public function singleton($key, $value)
|
||||
{
|
||||
$this->set($key, function ($c) use ($value) {
|
||||
static $object;
|
||||
|
||||
if (null === $object) {
|
||||
$object = $value($c);
|
||||
}
|
||||
|
||||
return $object;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Protect closure from being directly invoked
|
||||
* @param Closure $callable A closure to keep from being invoked and evaluated
|
||||
* @return Closure
|
||||
*/
|
||||
public function protect(\Closure $callable)
|
||||
{
|
||||
return function () use ($callable) {
|
||||
return $callable;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim Framework (http://slimframework.com)
|
||||
*
|
||||
* @link https://github.com/slimphp/Slim
|
||||
* @copyright Copyright (c) 2011-2015 Josh Lockhart
|
||||
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
namespace Slim\Http;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Slim\Interfaces\Http\CookiesInterface;
|
||||
|
||||
/**
|
||||
* Cookie helper
|
||||
*/
|
||||
class Cookies implements CookiesInterface
|
||||
{
|
||||
/**
|
||||
* Cookies from HTTP request
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requestCookies = [];
|
||||
|
||||
/**
|
||||
* Cookies for HTTP response
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $responseCookies = [];
|
||||
|
||||
/**
|
||||
* Default cookie properties
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $defaults = [
|
||||
'value' => '',
|
||||
'domain' => null,
|
||||
'path' => null,
|
||||
'expires' => null,
|
||||
'secure' => false,
|
||||
'httponly' => false
|
||||
];
|
||||
|
||||
/**
|
||||
* Create new cookies helper
|
||||
*
|
||||
* @param array $cookies
|
||||
*/
|
||||
public function __construct(array $cookies = [])
|
||||
{
|
||||
$this->requestCookies = $cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default cookie properties
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
public function setDefaults(array $settings)
|
||||
{
|
||||
$this->defaults = array_replace($this->defaults, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request cookie
|
||||
*
|
||||
* @param string $name Cookie name
|
||||
* @param mixed $default Cookie default value
|
||||
*
|
||||
* @return mixed Cookie value if present, else default
|
||||
*/
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set response cookie
|
||||
*
|
||||
* @param string $name Cookie name
|
||||
* @param string|array $value Cookie value, or cookie properties
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
$value = ['value' => (string)$value];
|
||||
}
|
||||
$this->responseCookies[$name] = array_replace($this->defaults, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to `Set-Cookie` headers
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toHeaders()
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($this->responseCookies as $name => $properties) {
|
||||
$headers[] = $this->toHeader($name, $properties);
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to `Set-Cookie` header
|
||||
*
|
||||
* @param string $name Cookie name
|
||||
* @param array $properties Cookie properties
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function toHeader($name, array $properties)
|
||||
{
|
||||
$result = urlencode($name) . '=' . urlencode($properties['value']);
|
||||
|
||||
if (isset($properties['domain'])) {
|
||||
$result .= '; domain=' . $properties['domain'];
|
||||
}
|
||||
|
||||
if (isset($properties['path'])) {
|
||||
$result .= '; path=' . $properties['path'];
|
||||
}
|
||||
|
||||
if (isset($properties['expires'])) {
|
||||
if (is_string($properties['expires'])) {
|
||||
$timestamp = strtotime($properties['expires']);
|
||||
} else {
|
||||
$timestamp = (int)$properties['expires'];
|
||||
}
|
||||
if ($timestamp !== 0) {
|
||||
$result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($properties['secure']) && $properties['secure']) {
|
||||
$result .= '; secure';
|
||||
}
|
||||
|
||||
if (isset($properties['httponly']) && $properties['httponly']) {
|
||||
$result .= '; HttpOnly';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse HTTP request `Cookie:` header and extract
|
||||
* into a PHP associative array.
|
||||
*
|
||||
* @param string $header The raw HTTP request `Cookie:` header
|
||||
*
|
||||
* @return array Associative array of cookie names and values
|
||||
*
|
||||
* @throws InvalidArgumentException if the cookie data cannot be parsed
|
||||
*/
|
||||
public static function parseHeader($header)
|
||||
{
|
||||
if (is_array($header) === true) {
|
||||
$header = isset($header[0]) ? $header[0] : '';
|
||||
}
|
||||
|
||||
if (is_string($header) === false) {
|
||||
throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.');
|
||||
}
|
||||
|
||||
$header = rtrim($header, "\r\n");
|
||||
$pieces = preg_split('@\s*[;,]\s*@', $header);
|
||||
$cookies = [];
|
||||
|
||||
foreach ($pieces as $cookie) {
|
||||
$cookie = explode('=', $cookie, 2);
|
||||
|
||||
if (count($cookie) === 2) {
|
||||
$key = urldecode($cookie[0]);
|
||||
$value = urldecode($cookie[1]);
|
||||
|
||||
if (!isset($cookies[$key])) {
|
||||
$cookies[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $cookies;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim Framework (http://slimframework.com)
|
||||
*
|
||||
* @link https://github.com/slimphp/Slim
|
||||
* @copyright Copyright (c) 2011-2015 Josh Lockhart
|
||||
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
namespace Slim\Http;
|
||||
|
||||
use Slim\Collection;
|
||||
use Slim\Interfaces\Http\HeadersInterface;
|
||||
|
||||
/**
|
||||
* Headers
|
||||
*
|
||||
* This class represents a collection of HTTP headers
|
||||
* that is used in both the HTTP request and response objects.
|
||||
* It also enables header name case-insensitivity when
|
||||
* getting or setting a header value.
|
||||
*
|
||||
* Each HTTP header can have multiple values. This class
|
||||
* stores values into an array for each header name. When
|
||||
* you request a header value, you receive an array of values
|
||||
* for that header.
|
||||
*/
|
||||
class Headers extends Collection implements HeadersInterface
|
||||
{
|
||||
/**
|
||||
* Special HTTP headers that do not have the "HTTP_" prefix
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $special = [
|
||||
'CONTENT_TYPE' => 1,
|
||||
'CONTENT_LENGTH' => 1,
|
||||
'PHP_AUTH_USER' => 1,
|
||||
'PHP_AUTH_PW' => 1,
|
||||
'PHP_AUTH_DIGEST' => 1,
|
||||
'AUTH_TYPE' => 1,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create new headers collection with data extracted from
|
||||
* the application Environment object
|
||||
*
|
||||
* @param Environment $environment The Slim application Environment
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function createFromEnvironment(Environment $environment)
|
||||
{
|
||||
$data = [];
|
||||
foreach ($environment as $key => $value) {
|
||||
$key = strtoupper($key);
|
||||
if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) {
|
||||
if ($key !== 'HTTP_CONTENT_LENGTH') {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new static($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of HTTP header names and values.
|
||||
* This method returns the _original_ header name
|
||||
* as specified by the end user.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
$all = parent::all();
|
||||
$out = [];
|
||||
foreach ($all as $key => $props) {
|
||||
$out[$props['originalKey']] = $props['value'];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTTP header value
|
||||
*
|
||||
* This method sets a header value. It replaces
|
||||
* any values that may already exist for the header name.
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
* @param string $value The header value
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
parent::set($this->normalizeKey($key), [
|
||||
'value' => $value,
|
||||
'originalKey' => $key
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTTP header value
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
* @param mixed $default The default value if key does not exist
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ($this->has($key)) {
|
||||
return parent::get($this->normalizeKey($key))['value'];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTTP header key as originally specified
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
* @param mixed $default The default value if key does not exist
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOriginalKey($key, $default = null)
|
||||
{
|
||||
if ($this->has($key)) {
|
||||
return parent::get($this->normalizeKey($key))['originalKey'];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add HTTP header value
|
||||
*
|
||||
* This method appends a header value. Unlike the set() method,
|
||||
* this method _appends_ this new value to any values
|
||||
* that already exist for this header name.
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
* @param array|string $value The new header value(s)
|
||||
*/
|
||||
public function add($key, $value)
|
||||
{
|
||||
$oldValues = $this->get($key, []);
|
||||
$newValues = is_array($value) ? $value : [$value];
|
||||
$this->set($key, array_merge($oldValues, array_values($newValues)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this collection have a given header?
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return parent::has($this->normalizeKey($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove header from collection
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
parent::remove($this->normalizeKey($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize header name
|
||||
*
|
||||
* This method transforms header names into a
|
||||
* normalized form. This is how we enable case-insensitive
|
||||
* header names in the other methods in this class.
|
||||
*
|
||||
* @param string $key The case-insensitive header name
|
||||
*
|
||||
* @return string Normalized header name
|
||||
*/
|
||||
public function normalizeKey($key)
|
||||
{
|
||||
$key = strtr(strtolower($key), '_', '-');
|
||||
if (strpos($key, 'http-') === 0) {
|
||||
$key = substr($key, 5);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,450 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim Framework (http://slimframework.com)
|
||||
*
|
||||
* @link https://github.com/slimphp/Slim
|
||||
* @copyright Copyright (c) 2011-2015 Josh Lockhart
|
||||
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
namespace Slim\Http;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Slim\Interfaces\Http\HeadersInterface;
|
||||
|
||||
/**
|
||||
* Response
|
||||
*
|
||||
* This class represents an HTTP response. It manages
|
||||
* the response status, headers, and body
|
||||
* according to the PSR-7 standard.
|
||||
*
|
||||
* @link https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
|
||||
* @link https://github.com/php-fig/http-message/blob/master/src/ResponseInterface.php
|
||||
*/
|
||||
class Response extends Message implements ResponseInterface
|
||||
{
|
||||
/**
|
||||
* Status code
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $status = 200;
|
||||
|
||||
/**
|
||||
* Reason phrase
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $reasonPhrase = '';
|
||||
|
||||
/**
|
||||
* Status codes and reason phrases
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $messages = [
|
||||
//Informational 1xx
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing',
|
||||
//Successful 2xx
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
207 => 'Multi-Status',
|
||||
208 => 'Already Reported',
|
||||
226 => 'IM Used',
|
||||
//Redirection 3xx
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
306 => '(Unused)',
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect',
|
||||
//Client Error 4xx
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => 'I\'m a teapot',
|
||||
422 => 'Unprocessable Entity',
|
||||
423 => 'Locked',
|
||||
424 => 'Failed Dependency',
|
||||
426 => 'Upgrade Required',
|
||||
428 => 'Precondition Required',
|
||||
429 => 'Too Many Requests',
|
||||
431 => 'Request Header Fields Too Large',
|
||||
//Server Error 5xx
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported',
|
||||
506 => 'Variant Also Negotiates',
|
||||
507 => 'Insufficient Storage',
|
||||
508 => 'Loop Detected',
|
||||
510 => 'Not Extended',
|
||||
511 => 'Network Authentication Required',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create new HTTP response.
|
||||
*
|
||||
* @param int $status The response status code.
|
||||
* @param HeadersInterface|null $headers The response headers.
|
||||
* @param StreamInterface|null $body The response body.
|
||||
*/
|
||||
public function __construct($status = 200, HeadersInterface $headers = null, StreamInterface $body = null)
|
||||
{
|
||||
$this->status = $this->filterStatus($status);
|
||||
$this->headers = $headers ? $headers : new Headers();
|
||||
$this->body = $body ? $body : new Body(fopen('php://temp', 'r+'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is applied to the cloned object
|
||||
* after PHP performs an initial shallow-copy. This
|
||||
* method completes a deep-copy by creating new objects
|
||||
* for the cloned object's internal reference pointers.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->headers = clone $this->headers;
|
||||
$this->body = clone $this->body;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Status
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets the response status code.
|
||||
*
|
||||
* The status code is a 3-digit integer result code of the server's attempt
|
||||
* to understand and satisfy the request.
|
||||
*
|
||||
* @return int Status code.
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified status code and, optionally, reason phrase.
|
||||
*
|
||||
* If no reason phrase is specified, implementations MAY choose to default
|
||||
* to the RFC 7231 or IANA recommended reason phrase for the response's
|
||||
* status code.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated status and reason phrase.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @param int $code The 3-digit integer result code to set.
|
||||
* @param string $reasonPhrase The reason phrase to use with the
|
||||
* provided status code; if none is provided, implementations MAY
|
||||
* use the defaults as suggested in the HTTP specification.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException For invalid status code arguments.
|
||||
*/
|
||||
public function withStatus($code, $reasonPhrase = '')
|
||||
{
|
||||
$code = $this->filterStatus($code);
|
||||
|
||||
if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) {
|
||||
throw new InvalidArgumentException('ReasonPhrase must be a string');
|
||||
}
|
||||
|
||||
$clone = clone $this;
|
||||
$clone->status = $code;
|
||||
if ($reasonPhrase === '' && isset(static::$messages[$code])) {
|
||||
$reasonPhrase = static::$messages[$code];
|
||||
}
|
||||
|
||||
if ($reasonPhrase === '') {
|
||||
throw new InvalidArgumentException('ReasonPhrase must be supplied for this code');
|
||||
}
|
||||
|
||||
$clone->reasonPhrase = $reasonPhrase;
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter HTTP status code.
|
||||
*
|
||||
* @param int $status HTTP status code.
|
||||
* @return int
|
||||
* @throws \InvalidArgumentException If an invalid HTTP status code is provided.
|
||||
*/
|
||||
protected function filterStatus($status)
|
||||
{
|
||||
if (!is_integer($status) || $status<100 || $status>599) {
|
||||
throw new InvalidArgumentException('Invalid HTTP status code');
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response reason phrase associated with the status code.
|
||||
*
|
||||
* Because a reason phrase is not a required element in a response
|
||||
* status line, the reason phrase value MAY be null. Implementations MAY
|
||||
* choose to return the default RFC 7231 recommended reason phrase (or those
|
||||
* listed in the IANA HTTP Status Code Registry) for the response's
|
||||
* status code.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @return string Reason phrase; must return an empty string if none present.
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
{
|
||||
if ($this->reasonPhrase) {
|
||||
return $this->reasonPhrase;
|
||||
}
|
||||
if (isset(static::$messages[$this->status])) {
|
||||
return static::$messages[$this->status];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Body
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Write data to the response body.
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* Proxies to the underlying stream and writes the provided data to it.
|
||||
*
|
||||
* @param string $data
|
||||
* @return self
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
$this->getBody()->write($data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Response Helpers
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Redirect.
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* This method prepares the response object to return an HTTP Redirect
|
||||
* response to the client.
|
||||
*
|
||||
* @param string|UriInterface $url The redirect destination.
|
||||
* @param int $status The redirect HTTP status code.
|
||||
* @return self
|
||||
*/
|
||||
public function withRedirect($url, $status = 302)
|
||||
{
|
||||
return $this->withStatus($status)->withHeader('Location', (string)$url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Json.
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* This method prepares the response object to return an HTTP Json
|
||||
* response to the client.
|
||||
*
|
||||
* @param mixed $data The data
|
||||
* @param int $status The HTTP status code.
|
||||
* @param int $encodingOptions Json encoding options
|
||||
* @return self
|
||||
*/
|
||||
public function withJson($data, $status = 200, $encodingOptions = 0)
|
||||
{
|
||||
$body = $this->getBody();
|
||||
$body->rewind();
|
||||
$body->write(json_encode($data, $encodingOptions));
|
||||
|
||||
return $this->withStatus($status)->withHeader('Content-Type', 'application/json;charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response empty?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return in_array($this->getStatusCode(), [204, 205, 304]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response informational?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInformational()
|
||||
{
|
||||
return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response OK?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isOk()
|
||||
{
|
||||
return $this->getStatusCode() === 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response successful?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccessful()
|
||||
{
|
||||
return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response a redirect?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirect()
|
||||
{
|
||||
return in_array($this->getStatusCode(), [301, 302, 303, 307]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response a redirection?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedirection()
|
||||
{
|
||||
return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response forbidden?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
* @api
|
||||
*/
|
||||
public function isForbidden()
|
||||
{
|
||||
return $this->getStatusCode() === 403;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response not Found?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotFound()
|
||||
{
|
||||
return $this->getStatusCode() === 404;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response a client error?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClientError()
|
||||
{
|
||||
return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this response a server error?
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isServerError()
|
||||
{
|
||||
return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert response to string.
|
||||
*
|
||||
* Note: This method is not part of the PSR-7 standard.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$output = sprintf(
|
||||
'HTTP/%s %s %s',
|
||||
$this->getProtocolVersion(),
|
||||
$this->getStatusCode(),
|
||||
$this->getReasonPhrase()
|
||||
);
|
||||
$output .= PHP_EOL;
|
||||
foreach ($this->getHeaders() as $name => $values) {
|
||||
$output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . PHP_EOL;
|
||||
}
|
||||
$output .= PHP_EOL;
|
||||
$output .= (string)$this->getBody();
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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.
|
||||
*
|
||||
* @param array|string $rawData
|
||||
* @param bool $overrideStripSlashes
|
||||
* @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
|
||||
$defaults = array(
|
||||
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||
'mode' => MCRYPT_MODE_CBC
|
||||
);
|
||||
$settings = array_merge($defaults, $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
|
||||
$defaults = array(
|
||||
'algorithm' => MCRYPT_RIJNDAEL_256,
|
||||
'mode' => MCRYPT_MODE_CBC
|
||||
);
|
||||
$settings = array_merge($defaults, $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 = rtrim($decryptedData, "\0");
|
||||
mcrypt_generic_deinit($module);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize Response cookies into raw HTTP header
|
||||
* @param \Slim\Http\Headers $headers The Response headers
|
||||
* @param \Slim\Http\Cookies $cookies The Response cookies
|
||||
* @param array $config The Slim app settings
|
||||
*/
|
||||
public static function serializeCookies(\Slim\Http\Headers &$headers, \Slim\Http\Cookies $cookies, array $config)
|
||||
{
|
||||
if ($config['cookies.encrypt']) {
|
||||
foreach ($cookies as $name => $settings) {
|
||||
if (is_string($settings['expires'])) {
|
||||
$expires = strtotime($settings['expires']);
|
||||
} else {
|
||||
$expires = (int) $settings['expires'];
|
||||
}
|
||||
|
||||
$settings['value'] = static::encodeSecureCookie(
|
||||
$settings['value'],
|
||||
$expires,
|
||||
$config['cookies.secret_key'],
|
||||
$config['cookies.cipher'],
|
||||
$config['cookies.cipher_mode']
|
||||
);
|
||||
static::setCookieHeader($headers, $name, $settings);
|
||||
}
|
||||
} else {
|
||||
foreach ($cookies as $name => $settings) {
|
||||
static::setCookieHeader($headers, $name, $settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 insecure 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
|
||||
* @return string
|
||||
*/
|
||||
public static function encodeSecureCookie($value, $expires, $secret, $algorithm, $mode)
|
||||
{
|
||||
$key = hash_hmac('sha1', (string) $expires, $secret);
|
||||
$iv = self::getIv($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 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
|
||||
* @return bool|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::getIv($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 array $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 request'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, 2);
|
||||
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 string Hash
|
||||
*/
|
||||
private static function getIv($expires, $secret)
|
||||
{
|
||||
$data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
|
||||
$data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
|
||||
|
||||
return pack("h*", $data1.$data2);
|
||||
}
|
||||
}
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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, array $context )
|
||||
* info( mixed $object, array $context )
|
||||
* notice( mixed $object, array $context )
|
||||
* warning( mixed $object, array $context )
|
||||
* error( mixed $object, array $context )
|
||||
* critical( mixed $object, array $context )
|
||||
* alert( mixed $object, array $context )
|
||||
* emergency( mixed $object, array $context )
|
||||
* log( mixed $level, mixed $object, array $context )
|
||||
*
|
||||
* 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 EMERGENCY = 1;
|
||||
const ALERT = 2;
|
||||
const CRITICAL = 3;
|
||||
const FATAL = 3; //DEPRECATED replace with CRITICAL
|
||||
const ERROR = 4;
|
||||
const WARN = 5;
|
||||
const NOTICE = 6;
|
||||
const INFO = 7;
|
||||
const DEBUG = 8;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $levels = array(
|
||||
self::EMERGENCY => 'EMERGENCY',
|
||||
self::ALERT => 'ALERT',
|
||||
self::CRITICAL => 'CRITICAL',
|
||||
self::ERROR => 'ERROR',
|
||||
self::WARN => 'WARNING',
|
||||
self::NOTICE => 'NOTICE',
|
||||
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
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function debug($object, $context = array())
|
||||
{
|
||||
return $this->log(self::DEBUG, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log info message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function info($object, $context = array())
|
||||
{
|
||||
return $this->log(self::INFO, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log notice message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function notice($object, $context = array())
|
||||
{
|
||||
return $this->log(self::NOTICE, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log warning message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function warning($object, $context = array())
|
||||
{
|
||||
return $this->log(self::WARN, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function warning
|
||||
* Log warning message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function warn($object, $context = array())
|
||||
{
|
||||
return $this->log(self::WARN, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function error($object, $context = array())
|
||||
{
|
||||
return $this->log(self::ERROR, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log critical message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function critical($object, $context = array())
|
||||
{
|
||||
return $this->log(self::CRITICAL, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function critical
|
||||
* Log fatal message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function fatal($object, $context = array())
|
||||
{
|
||||
return $this->log(self::CRITICAL, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log alert message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function alert($object, $context = array())
|
||||
{
|
||||
return $this->log(self::ALERT, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log emergency message
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
*/
|
||||
public function emergency($object, $context = array())
|
||||
{
|
||||
return $this->log(self::EMERGENCY, $object, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log message
|
||||
* @param mixed $level
|
||||
* @param mixed $object
|
||||
* @param array $context
|
||||
* @return mixed|bool What the Logger returns, or false if Logger not set or not enabled
|
||||
* @throws \InvalidArgumentException If invalid log level
|
||||
*/
|
||||
public function log($level, $object, $context = array())
|
||||
{
|
||||
if (!isset(self::$levels[$level])) {
|
||||
throw new \InvalidArgumentException('Invalid log level supplied to function');
|
||||
} else if ($this->enabled && $this->writer && $level <= $this->level) {
|
||||
$message = (string)$object;
|
||||
if (count($context) > 0) {
|
||||
if (isset($context['exception']) && $context['exception'] instanceof \Exception) {
|
||||
$message .= ' - ' . $context['exception'];
|
||||
unset($context['exception']);
|
||||
}
|
||||
$message = $this->interpolate($message, $context);
|
||||
}
|
||||
return $this->writer->write($message, $level);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED for function log
|
||||
* Log message
|
||||
* @param mixed $object The object to log
|
||||
* @param int $level The message level
|
||||
* @return int|bool
|
||||
*/
|
||||
protected function write($object, $level)
|
||||
{
|
||||
return $this->log($level, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate log message
|
||||
* @param mixed $message The log message
|
||||
* @param array $context An array of placeholder values
|
||||
* @return string The processed string
|
||||
*/
|
||||
protected function interpolate($message, $context = array())
|
||||
{
|
||||
$replace = array();
|
||||
foreach ($context as $key => $value) {
|
||||
$replace['{' . $key . '}'] = $value;
|
||||
}
|
||||
return strtr($message, $replace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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|bool
|
||||
*/
|
||||
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 <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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\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\Slim $application
|
||||
*/
|
||||
final public function setApplication($application)
|
||||
{
|
||||
$this->app = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application
|
||||
*
|
||||
* This method retrieves the application previously injected
|
||||
* into this middleware.
|
||||
*
|
||||
* @return \Slim\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|\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,174 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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())
|
||||
{
|
||||
$defaults = array(
|
||||
'application/json' => array($this, 'parseJson'),
|
||||
'application/xml' => array($this, 'parseXml'),
|
||||
'text/xml' => array($this, 'parseXml'),
|
||||
'text/csv' => array($this, 'parseCsv')
|
||||
);
|
||||
$this->contentTypes = array_merge($defaults, $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 {
|
||||
$backup = libxml_disable_entity_loader(true);
|
||||
$result = new \SimpleXMLElement($input);
|
||||
libxml_disable_entity_loader($backup);
|
||||
return $result;
|
||||
} 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,212 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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, \Countable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $messages;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Countable: Count
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->getMessages());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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 pseudo 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 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.
|
||||
*
|
||||
* @return array[status, header, body]
|
||||
*/
|
||||
public function call()
|
||||
{
|
||||
$env = $this->app->environment();
|
||||
if (isset($env['HTTP_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['HTTP_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,116 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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) {
|
||||
$log = $this->app->getLog(); // Force Slim to append log to env if not already
|
||||
$env = $this->app->environment();
|
||||
$env['slim.log'] = $log;
|
||||
$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 = str_replace(array('#', '\n'), array('<div>#', '</div>'), $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>';
|
||||
$html .= sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
|
||||
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,210 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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.
|
||||
*
|
||||
* You should NEVER store sensitive data in a client-side cookie
|
||||
* in any format, encrypted (with cookies.encrypt) 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 limited 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())
|
||||
{
|
||||
$defaults = array(
|
||||
'expires' => '20 minutes',
|
||||
'path' => '/',
|
||||
'domain' => null,
|
||||
'secure' => false,
|
||||
'httponly' => false,
|
||||
'name' => 'slim_session',
|
||||
);
|
||||
$this->settings = array_merge($defaults, $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
|
||||
*/
|
||||
protected function loadSession()
|
||||
{
|
||||
if (session_id() === '') {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$value = $this->app->getCookie($this->settings['name']);
|
||||
|
||||
if ($value) {
|
||||
try {
|
||||
$_SESSION = unserialize($value);
|
||||
} catch (\Exception $e) {
|
||||
$this->app->getLog()->error('Error unserializing session cookie value! ' . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$_SESSION = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save session
|
||||
*/
|
||||
protected function saveSession()
|
||||
{
|
||||
$value = serialize($_SESSION);
|
||||
|
||||
if (strlen($value) > 4096) {
|
||||
$this->app->getLog()->error('WARNING! Slim\Middleware\SessionCookie data size is larger than 4KB. Content save failed.');
|
||||
} else {
|
||||
$this->app->setCookie(
|
||||
$this->settings['name'],
|
||||
$value,
|
||||
$this->settings['expires'],
|
||||
$this->settings['path'],
|
||||
$this->settings['domain'],
|
||||
$this->settings['secure'],
|
||||
$this->settings['httponly']
|
||||
);
|
||||
}
|
||||
// session_destroy();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Session Handler
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function write($id, $data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim Framework (http://slimframework.com)
|
||||
*
|
||||
* @link https://github.com/slimphp/Slim
|
||||
* @copyright Copyright (c) 2011-2015 Josh Lockhart
|
||||
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
namespace Slim;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Handlers\Strategies\RequestResponse;
|
||||
use Slim\Interfaces\InvocationStrategyInterface;
|
||||
use Slim\Interfaces\RouteInterface;
|
||||
|
||||
/**
|
||||
* Route
|
||||
*/
|
||||
class Route extends Routable implements RouteInterface
|
||||
{
|
||||
use MiddlewareAwareTrait;
|
||||
|
||||
/**
|
||||
* HTTP methods supported by this route
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $methods = [];
|
||||
|
||||
/**
|
||||
* Route identifier
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* Route name
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Parent route groups
|
||||
*
|
||||
* @var RouteGroup[]
|
||||
*/
|
||||
protected $groups;
|
||||
|
||||
private $finalized = false;
|
||||
|
||||
/**
|
||||
* Output buffering mode
|
||||
*
|
||||
* One of: false, 'prepend' or 'append'
|
||||
*
|
||||
* @var boolean|string
|
||||
*/
|
||||
protected $outputBuffering = 'append';
|
||||
|
||||
/**
|
||||
* Route parameters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* Create new route
|
||||
*
|
||||
* @param string[] $methods The route HTTP methods
|
||||
* @param string $pattern The route pattern
|
||||
* @param callable $callable The route callable
|
||||
* @param int $identifier The route identifier
|
||||
* @param RouteGroup[] $groups The parent route groups
|
||||
*/
|
||||
public function __construct($methods, $pattern, $callable, $groups = [], $identifier = 0)
|
||||
{
|
||||
$this->methods = $methods;
|
||||
$this->pattern = $pattern;
|
||||
$this->callable = $callable;
|
||||
$this->groups = $groups;
|
||||
$this->identifier = 'route' . $identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize the route in preparation for dispatching
|
||||
*/
|
||||
public function finalize()
|
||||
{
|
||||
if ($this->finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
$groupMiddleware = [];
|
||||
foreach ($this->getGroups() as $group) {
|
||||
$groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware);
|
||||
}
|
||||
|
||||
$this->middleware = array_merge($this->middleware, $groupMiddleware);
|
||||
|
||||
foreach ($this->getMiddleware() as $middleware) {
|
||||
$this->addMiddleware($middleware);
|
||||
}
|
||||
|
||||
$this->finalized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route callable
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getCallable()
|
||||
{
|
||||
return $this->callable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route methods
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getMethods()
|
||||
{
|
||||
return $this->methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent route groups
|
||||
*
|
||||
* @return RouteGroup[]
|
||||
*/
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route name
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get output buffering mode
|
||||
*
|
||||
* @return boolean|string
|
||||
*/
|
||||
public function getOutputBuffering()
|
||||
{
|
||||
return $this->outputBuffering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set output buffering mode
|
||||
*
|
||||
* One of: false, 'prepend' or 'append'
|
||||
*
|
||||
* @param boolean|string $mode
|
||||
*
|
||||
* @throws InvalidArgumentException If an unknown buffering mode is specified
|
||||
*/
|
||||
public function setOutputBuffering($mode)
|
||||
{
|
||||
if (!in_array($mode, [false, 'prepend', 'append'], true)) {
|
||||
throw new InvalidArgumentException('Unknown output buffering mode');
|
||||
}
|
||||
$this->outputBuffering = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set route name
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws InvalidArgumentException if the route name is not a string
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
if (!is_string($name)) {
|
||||
throw new InvalidArgumentException('Route name must be a string');
|
||||
}
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a route argument
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setArgument($name, $value)
|
||||
{
|
||||
$this->arguments[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace route arguments
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve route arguments
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific route argument
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getArgument($name, $default = null)
|
||||
{
|
||||
if (array_key_exists($name, $this->arguments)) {
|
||||
return $this->arguments[$name];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Route Runner
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Prepare the route for use
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param array $arguments
|
||||
*/
|
||||
public function prepare(ServerRequestInterface $request, array $arguments)
|
||||
{
|
||||
// Add the arguments
|
||||
foreach ($arguments as $k => $v) {
|
||||
$this->setArgument($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run route
|
||||
*
|
||||
* This method traverses the middleware stack, including the route's callable
|
||||
* and captures the resultant HTTP response object. It then sends the response
|
||||
* back to the Application.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function run(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
// Finalise route now that we are about to run it
|
||||
$this->finalize();
|
||||
|
||||
// Traverse middleware stack and fetch updated response
|
||||
return $this->callMiddlewareStack($request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch route callable against current Request and Response objects
|
||||
*
|
||||
* This method invokes the route object's callable. If middleware is
|
||||
* registered for the route, each callable middleware is invoked in
|
||||
* the order specified.
|
||||
*
|
||||
* @param ServerRequestInterface $request The current Request object
|
||||
* @param ResponseInterface $response The current Response object
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
* @throws \Exception if the route callable throws an exception
|
||||
*/
|
||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$this->callable = $this->resolveCallable($this->callable);
|
||||
|
||||
/** @var InvocationStrategyInterface $handler */
|
||||
$handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse();
|
||||
|
||||
// invoke route callable
|
||||
if ($this->outputBuffering === false) {
|
||||
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
|
||||
} else {
|
||||
try {
|
||||
ob_start();
|
||||
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
|
||||
$output = ob_get_clean();
|
||||
} catch (Exception $e) {
|
||||
ob_end_clean();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if ($newResponse instanceof ResponseInterface) {
|
||||
// if route callback returns a ResponseInterface, then use it
|
||||
$response = $newResponse;
|
||||
} elseif (is_string($newResponse)) {
|
||||
// if route callback returns a string, then append it to the response
|
||||
if ($response->getBody()->isWritable()) {
|
||||
$response->getBody()->write($newResponse);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($output) && $response->getBody()->isWritable()) {
|
||||
if ($this->outputBuffering === 'prepend') {
|
||||
// prepend output buffer content
|
||||
$body = new Http\Body(fopen('php://temp', 'r+'));
|
||||
$body->write($output . $response->getBody());
|
||||
$response = $response->withBody($body);
|
||||
} elseif ($this->outputBuffering === 'append') {
|
||||
// append output buffer content
|
||||
$response->getBody()->write($output);
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
+383
@@ -0,0 +1,383 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim Framework (http://slimframework.com)
|
||||
*
|
||||
* @link https://github.com/slimphp/Slim
|
||||
* @copyright Copyright (c) 2011-2015 Josh Lockhart
|
||||
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
namespace Slim;
|
||||
|
||||
use FastRoute\Dispatcher;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use FastRoute\RouteCollector;
|
||||
use FastRoute\RouteParser;
|
||||
use FastRoute\RouteParser\Std as StdParser;
|
||||
use FastRoute\DataGenerator;
|
||||
use Slim\Interfaces\RouteGroupInterface;
|
||||
use Slim\Interfaces\RouterInterface;
|
||||
use Slim\Interfaces\RouteInterface;
|
||||
|
||||
/**
|
||||
* Router
|
||||
*
|
||||
* This class organizes Slim application route objects. It is responsible
|
||||
* for registering route objects, assigning names to route objects,
|
||||
* finding routes that match the current HTTP request, and creating
|
||||
* URLs for a named route.
|
||||
*/
|
||||
class Router implements RouterInterface
|
||||
{
|
||||
/**
|
||||
* Parser
|
||||
*
|
||||
* @var \FastRoute\RouteParser
|
||||
*/
|
||||
protected $routeParser;
|
||||
|
||||
/**
|
||||
* Base path used in pathFor()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $basePath = '';
|
||||
|
||||
/**
|
||||
* Routes
|
||||
*
|
||||
* @var Route[]
|
||||
*/
|
||||
protected $routes = [];
|
||||
|
||||
/**
|
||||
* Route counter incrementer
|
||||
* @var int
|
||||
*/
|
||||
protected $routeCounter = 0;
|
||||
|
||||
/**
|
||||
* Named routes
|
||||
*
|
||||
* @var null|Route[]
|
||||
*/
|
||||
protected $namedRoutes;
|
||||
|
||||
/**
|
||||
* Route groups
|
||||
*
|
||||
* @var RouteGroup[]
|
||||
*/
|
||||
protected $routeGroups = [];
|
||||
|
||||
/**
|
||||
* @var \FastRoute\Dispatcher
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* Create new router
|
||||
*
|
||||
* @param RouteParser $parser
|
||||
*/
|
||||
public function __construct(RouteParser $parser = null)
|
||||
{
|
||||
$this->routeParser = $parser ?: new StdParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base path used in pathFor()
|
||||
*
|
||||
* @param string $basePath
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setBasePath($basePath)
|
||||
{
|
||||
if (!is_string($basePath)) {
|
||||
throw new InvalidArgumentException('Router basePath must be a string');
|
||||
}
|
||||
|
||||
$this->basePath = $basePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add route
|
||||
*
|
||||
* @param string[] $methods Array of HTTP methods
|
||||
* @param string $pattern The route pattern
|
||||
* @param callable $handler The route callable
|
||||
*
|
||||
* @return RouteInterface
|
||||
*
|
||||
* @throws InvalidArgumentException if the route pattern isn't a string
|
||||
*/
|
||||
public function map($methods, $pattern, $handler)
|
||||
{
|
||||
if (!is_string($pattern)) {
|
||||
throw new InvalidArgumentException('Route pattern must be a string');
|
||||
}
|
||||
|
||||
// Prepend parent group pattern(s)
|
||||
if ($this->routeGroups) {
|
||||
$pattern = $this->processGroups() . $pattern;
|
||||
}
|
||||
|
||||
// According to RFC methods are defined in uppercase (See RFC 7231)
|
||||
$methods = array_map("strtoupper", $methods);
|
||||
|
||||
// Add route
|
||||
$route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter);
|
||||
$this->routes[$route->getIdentifier()] = $route;
|
||||
$this->routeCounter++;
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch router for HTTP request
|
||||
*
|
||||
* @param ServerRequestInterface $request The current HTTP request object
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
|
||||
*/
|
||||
public function dispatch(ServerRequestInterface $request)
|
||||
{
|
||||
$uri = '/' . ltrim($request->getUri()->getPath(), '/');
|
||||
|
||||
return $this->createDispatcher()->dispatch(
|
||||
$request->getMethod(),
|
||||
$uri
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \FastRoute\Dispatcher
|
||||
*/
|
||||
protected function createDispatcher()
|
||||
{
|
||||
return $this->dispatcher ?: \FastRoute\simpleDispatcher(function (RouteCollector $r) {
|
||||
foreach ($this->getRoutes() as $route) {
|
||||
$r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
|
||||
}
|
||||
}, [
|
||||
'routeParser' => $this->routeParser
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \FastRoute\Dispatcher $dispatcher
|
||||
*/
|
||||
public function setDispatcher(Dispatcher $dispatcher)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route objects
|
||||
*
|
||||
* @return Route[]
|
||||
*/
|
||||
public function getRoutes()
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get named route object
|
||||
*
|
||||
* @param string $name Route name
|
||||
*
|
||||
* @return Route
|
||||
*
|
||||
* @throws RuntimeException If named route does not exist
|
||||
*/
|
||||
public function getNamedRoute($name)
|
||||
{
|
||||
if (is_null($this->namedRoutes)) {
|
||||
$this->buildNameIndex();
|
||||
}
|
||||
if (!isset($this->namedRoutes[$name])) {
|
||||
throw new RuntimeException('Named route does not exist for name: ' . $name);
|
||||
}
|
||||
return $this->namedRoutes[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process route groups
|
||||
*
|
||||
* @return string A group pattern to prefix routes with
|
||||
*/
|
||||
protected function processGroups()
|
||||
{
|
||||
$pattern = "";
|
||||
foreach ($this->routeGroups as $group) {
|
||||
$pattern .= $group->getPattern();
|
||||
}
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route group to the array
|
||||
*
|
||||
* @param string $pattern
|
||||
* @param callable $callable
|
||||
*
|
||||
* @return RouteGroupInterface
|
||||
*/
|
||||
public function pushGroup($pattern, $callable)
|
||||
{
|
||||
$group = new RouteGroup($pattern, $callable);
|
||||
array_push($this->routeGroups, $group);
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last route group from the array
|
||||
*
|
||||
* @return RouteGroup|bool The RouteGroup if successful, else False
|
||||
*/
|
||||
public function popGroup()
|
||||
{
|
||||
$group = array_pop($this->routeGroups);
|
||||
return $group instanceof RouteGroup ? $group : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $identifier
|
||||
* @return \Slim\Interfaces\RouteInterface
|
||||
*/
|
||||
public function lookupRoute($identifier)
|
||||
{
|
||||
if (!isset($this->routes[$identifier])) {
|
||||
throw new RuntimeException('Route not found, looks like your route cache is stale.');
|
||||
}
|
||||
return $this->routes[$identifier];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the path for a named route excluding the base path
|
||||
*
|
||||
* @param string $name Route name
|
||||
* @param array $data Named argument replacement data
|
||||
* @param array $queryParams Optional query string parameters
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws RuntimeException If named route does not exist
|
||||
* @throws InvalidArgumentException If required data not provided
|
||||
*/
|
||||
public function relativePathFor($name, array $data = [], array $queryParams = [])
|
||||
{
|
||||
$route = $this->getNamedRoute($name);
|
||||
$pattern = $route->getPattern();
|
||||
|
||||
$routeDatas = $this->routeParser->parse($pattern);
|
||||
// $routeDatas is an array of all possible routes that can be made. There is
|
||||
// one routedata for each optional parameter plus one for no optional parameters.
|
||||
//
|
||||
// The most specific is last, so we look for that first.
|
||||
$routeDatas = array_reverse($routeDatas);
|
||||
|
||||
$segments = [];
|
||||
foreach ($routeDatas as $routeData) {
|
||||
foreach ($routeData as $item) {
|
||||
if (is_string($item)) {
|
||||
// this segment is a static string
|
||||
$segments[] = $item;
|
||||
continue;
|
||||
}
|
||||
|
||||
// This segment has a parameter: first element is the name
|
||||
if (!array_key_exists($item[0], $data)) {
|
||||
// we don't have a data element for this segment: cancel
|
||||
// testing this routeData item, so that we can try a less
|
||||
// specific routeData item.
|
||||
$segments = [];
|
||||
$segmentName = $item[0];
|
||||
break;
|
||||
}
|
||||
$segments[] = $data[$item[0]];
|
||||
}
|
||||
if (!empty($segments)) {
|
||||
// we found all the parameters for this route data, no need to check
|
||||
// less specific ones
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($segments)) {
|
||||
throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName);
|
||||
}
|
||||
$url = implode('', $segments);
|
||||
|
||||
if ($queryParams) {
|
||||
$url .= '?' . http_build_query($queryParams);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the path for a named route including the base path
|
||||
*
|
||||
* @param string $name Route name
|
||||
* @param array $data Named argument replacement data
|
||||
* @param array $queryParams Optional query string parameters
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws RuntimeException If named route does not exist
|
||||
* @throws InvalidArgumentException If required data not provided
|
||||
*/
|
||||
public function pathFor($name, array $data = [], array $queryParams = [])
|
||||
{
|
||||
$url = $this->relativePathFor($name, $data, $queryParams);
|
||||
|
||||
if ($this->basePath) {
|
||||
$url = $this->basePath . $url;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the path for a named route.
|
||||
*
|
||||
* This method is deprecated. Use pathFor() from now on.
|
||||
*
|
||||
* @param string $name Route name
|
||||
* @param array $data Named argument replacement data
|
||||
* @param array $queryParams Optional query string parameters
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws RuntimeException If named route does not exist
|
||||
* @throws InvalidArgumentException If required data not provided
|
||||
*/
|
||||
public function urlFor($name, array $data = [], array $queryParams = [])
|
||||
{
|
||||
trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED);
|
||||
return $this->pathFor($name, $data, $queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build index of named routes
|
||||
*/
|
||||
protected function buildNameIndex()
|
||||
{
|
||||
$this->namedRoutes = [];
|
||||
foreach ($this->routes as $route) {
|
||||
$name = $route->getName();
|
||||
if ($name) {
|
||||
$this->namedRoutes[$name] = $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1412
File diff suppressed because it is too large
Load Diff
+282
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
/**
|
||||
* Slim - a micro PHP 5 framework
|
||||
*
|
||||
* @author Josh Lockhart <[email protected]>
|
||||
* @copyright 2011 Josh Lockhart
|
||||
* @link http://www.slimframework.com
|
||||
* @license http://www.slimframework.com/license
|
||||
* @version 2.4.2
|
||||
* @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
|
||||
{
|
||||
/**
|
||||
* Data available to the view templates
|
||||
* @var \Slim\Helper\Set
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Path to templates base directory (without trailing slash)
|
||||
* @var string
|
||||
*/
|
||||
protected $templatesDirectory;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->data = new \Slim\Helper\Set();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Data methods
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Does view data have value with key?
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->data->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view data value with key
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->data->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set view data value with key
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->data->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set view data value as Closure with key
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function keep($key, Closure $value)
|
||||
{
|
||||
$this->data->keep($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view data
|
||||
* @return array
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->data->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace view data
|
||||
* @param array $data
|
||||
*/
|
||||
public function replace(array $data)
|
||||
{
|
||||
$this->data->replace($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear view data
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data->clear();
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Legacy data methods
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* Get data from view
|
||||
*/
|
||||
public function getData($key = null)
|
||||
{
|
||||
if (!is_null($key)) {
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
} else {
|
||||
return $this->data->all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* Set data for view
|
||||
*/
|
||||
public function setData()
|
||||
{
|
||||
$args = func_get_args();
|
||||
if (count($args) === 1 && is_array($args[0])) {
|
||||
$this->data->replace($args[0]);
|
||||
} elseif (count($args) === 2) {
|
||||
// Ensure original behavior is maintained. DO NOT invoke stored Closures.
|
||||
if (is_object($args[1]) && method_exists($args[1], '__invoke')) {
|
||||
$this->data->set($args[0], $this->data->protect($args[1]));
|
||||
} else {
|
||||
$this->data->set($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, ... ]);`');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* Append data to view
|
||||
* @param array $data
|
||||
*/
|
||||
public function appendData($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
throw new \InvalidArgumentException('Cannot append view data. Expected array argument.');
|
||||
}
|
||||
$this->data->replace($data);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Resolve template paths
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Set the base directory that contains view templates
|
||||
* @param string $directory
|
||||
* @throws \InvalidArgumentException If directory is not a directory
|
||||
*/
|
||||
public function setTemplatesDirectory($directory)
|
||||
{
|
||||
$this->templatesDirectory = rtrim($directory, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get templates base directory
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplatesDirectory()
|
||||
{
|
||||
return $this->templatesDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fully qualified path to template file using templates base directory
|
||||
* @param string $file The template file pathname relative to templates base directory
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplatePathname($file)
|
||||
{
|
||||
return $this->templatesDirectory . DIRECTORY_SEPARATOR . ltrim($file, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Rendering
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Display template
|
||||
*
|
||||
* This method echoes the rendered template to the current output buffer
|
||||
*
|
||||
* @param string $template Pathname of template file relative to templates directory
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
*/
|
||||
public function display($template, $data = null)
|
||||
{
|
||||
echo $this->fetch($template, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contents of a rendered template file
|
||||
*
|
||||
* @param string $template The template pathname, relative to the template base directory
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
* @return string The rendered template
|
||||
*/
|
||||
public function fetch($template, $data = null)
|
||||
{
|
||||
return $this->render($template, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a template file
|
||||
*
|
||||
* NOTE: This method should be overridden by custom view subclasses
|
||||
*
|
||||
* @param string $template The template pathname, relative to the template base directory
|
||||
* @param array $data Any additonal data to be passed to the template.
|
||||
* @return string The rendered template
|
||||
* @throws \RuntimeException If resolved template pathname is not a valid file
|
||||
*/
|
||||
protected function render($template, $data = null)
|
||||
{
|
||||
$templatePathname = $this->getTemplatePathname($template);
|
||||
if (!is_file($templatePathname)) {
|
||||
throw new \RuntimeException("View cannot render `$template` because the template does not exist");
|
||||
}
|
||||
|
||||
$data = array_merge($this->data->all(), (array) $data);
|
||||
extract($data);
|
||||
ob_start();
|
||||
require $templatePathname;
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user