composer update

This commit is contained in:
Marcel Kapfer (mmk2410) 2016-12-30 00:04:12 +01:00
parent 9ac51e0523
commit 623395064f
279 changed files with 4458 additions and 16328 deletions

View file

@ -1,20 +0,0 @@
# How to Contribute
## Pull Requests
1. Fork the Slim Framework repository
2. Create a new branch for each feature or improvement
3. Send a pull request from each feature branch to the **develop** branch
It is very important to separate new features or improvements into separate feature branches, and to send a
pull request for each branch. This allows me to review and pull in new features or improvements individually.
## Style Guide
All pull requests must adhere to the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md).
## Unit Testing
All pull requests must be accompanied by passing unit tests and complete code coverage. The Slim Framework uses phpunit for testing.
[Learn about PHPUnit](https://github.com/sebastianbergmann/phpunit/)

View file

@ -1,84 +0,0 @@
# Slim Framework
[![Build Status](https://travis-ci.org/slimphp/Slim.svg?branch=develop)](https://travis-ci.org/slimphp/Slim)
[![Coverage Status](https://coveralls.io/repos/slimphp/Slim/badge.svg?branch=develop)](https://coveralls.io/r/slimphp/Slim?branch=develop)
[![Total Downloads](https://poser.pugx.org/slim/slim/downloads)](https://packagist.org/packages/slim/slim)
[![License](https://poser.pugx.org/slim/slim/license)](https://packagist.org/packages/slim/slim)
Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs.
## Installation
It's recommended that you use [Composer](https://getcomposer.org/) to install Slim.
```bash
$ composer require slim/slim "^3.0"
```
This will install Slim and all required dependencies. Slim requires PHP 5.5.0 or newer.
## Usage
Create an index.php file with the following contents:
```php
<?php
require 'vendor/autoload.php';
$app = new Slim\App();
$app->get('/hello/{name}', function ($request, $response, $args) {
$response->write("Hello, " . $args['name']);
return $response;
});
$app->run();
```
You may quickly test this using the built-in PHP server:
```bash
$ php -S localhost:8000
```
Going to http://localhost:8000/hello/world will now display "Hello, world".
For more information on how to configure your web server, see the [Documentation](http://www.slimframework.com/docs/start/web-servers.html).
## Tests
To execute the test suite, you'll need phpunit.
```bash
$ phpunit
```
## Contributing
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
## Learn More
Learn more at these links:
- [Website](http://www.slimframework.com)
- [Documentation](http://www.slimframework.com/docs/start/installation.html)
- [Support Forum](http://help.slimframework.com)
- [Twitter](https://twitter.com/slimphp)
- [Resources](https://github.com/xssc/awesome-slim)
## Security
If you discover security related issues, please email security@slimframework.com instead of using the issue tracker.
## Credits
- [Josh Lockhart](https://github.com/codeguy)
- [Andrew Smith](https://github.com/silentworks)
- [Rob Allen](https://github.com/akrabat)
- [Gabriel Manricks](https://github.com/gmanricks)
- [All Contributors](../../contributors)
## License
The Slim Framework is licensed under the MIT license. See [License File](LICENSE.md) for more information.

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -36,11 +36,6 @@ use Slim\Interfaces\RouterInterface;
* configure, and run a Slim Framework application.
* The \Slim\App class also accepts Slim Framework middleware.
*
* @property-read array $settings App settings
* @property-read EnvironmentInterface $environment
* @property-read RequestInterface $request
* @property-read ResponseInterface $response
* @property-read RouterInterface $router
* @property-read callable $errorHandler
* @property-read callable $phpErrorHandler
* @property-read callable $notFoundHandler function($request, $response)
@ -55,7 +50,7 @@ class App
*
* @var string
*/
const VERSION = '3.0.0';
const VERSION = '3.7.0';
/**
* Container
@ -111,7 +106,7 @@ class App
/**
* Calling a non-existant method on App checks to see if there's an item
* in the container than is callable and if so, calls it.
* in the container that is callable and if so, calls it.
*
* @param string $method
* @param array $args
@ -379,19 +374,21 @@ class App
}
$settings = $this->container->get('settings');
$chunkSize = $settings['responseChunkSize'];
$contentLength = $response->getHeaderLine('Content-Length');
if (!$contentLength) {
$contentLength = $body->getSize();
}
if (isset($contentLength)) {
$totalChunks = ceil($contentLength / $chunkSize);
$lastChunkSize = $contentLength % $chunkSize;
$currentChunk = 0;
while (!$body->eof() && $currentChunk < $totalChunks) {
if (++$currentChunk == $totalChunks && $lastChunkSize > 0) {
$chunkSize = $lastChunkSize;
}
echo $body->read($chunkSize);
$amountToRead = $contentLength;
while ($amountToRead > 0 && !$body->eof()) {
$data = $body->read(min($chunkSize, $amountToRead));
echo $data;
$amountToRead -= strlen($data);
if (connection_status() != CONNECTION_NORMAL) {
break;
}
@ -543,9 +540,17 @@ class App
return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length');
}
$size = $response->getBody()->getSize();
if ($size !== null && !$response->hasHeader('Content-Length')) {
$response = $response->withHeader('Content-Length', (string) $size);
// Add Content-Length header if `addContentLengthHeader` setting is set
if (isset($this->container->get('settings')['addContentLengthHeader']) &&
$this->container->get('settings')['addContentLengthHeader'] == true) {
if (ob_get_length() > 0) {
throw new \RuntimeException("Unexpected data in output buffer. " .
"Maybe you have characters before an opening <?php tag?");
}
$size = $response->getBody()->getSize();
if ($size !== null && !$response->hasHeader('Content-Length')) {
$response = $response->withHeader('Content-Length', (string) $size);
}
}
return $response;
@ -587,7 +592,7 @@ class App
$params = [$e->getRequest(), $e->getResponse(), $e->getAllowedMethods()];
} elseif ($e instanceof NotFoundException) {
$handler = 'notFoundHandler';
$params = [$e->getRequest(), $e->getResponse()];
$params = [$e->getRequest(), $e->getResponse(), $e];
} elseif ($e instanceof SlimException) {
// This is a Stop exception and contains the response
return $e->getResponse();
@ -614,9 +619,8 @@ class App
* @param Throwable $e
* @param ServerRequestInterface $request
* @param ResponseInterface $response
*
* @return ResponseInterface
* @throws Exception if a handler is needed and not found
* @throws Throwable
*/
protected function handlePhpError(Throwable $e, ServerRequestInterface $request, ResponseInterface $response)
{

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -79,7 +79,10 @@ final class CallableResolver implements CallableResolverInterface
}
if (!is_callable($resolved)) {
throw new RuntimeException(sprintf('%s is not resolvable', $toResolve));
throw new RuntimeException(sprintf(
'%s is not resolvable',
is_array($toResolve) || is_object($toResolve) ? json_encode($toResolve) : $toResolve
));
}
return $resolved;

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -34,9 +34,7 @@ class Collection implements CollectionInterface
*/
public function __construct(array $items = [])
{
foreach ($items as $key => $value) {
$this->set($key, $value);
}
$this->replace($items);
}
/********************************************************************************
@ -68,7 +66,7 @@ class Collection implements CollectionInterface
}
/**
* Add item to collection
* Add item to collection, replacing existing items with the same data key
*
* @param array $items Key-value array of data to append to this collection
*/

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -11,9 +11,8 @@ namespace Slim;
use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Pimple\Container as PimpleContainer;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\ContainerValueNotFoundException;
use Slim\Exception\ContainerException as SlimContainerException;
/**
* Slim's default DI container is Pimple.
@ -30,7 +29,7 @@ use Slim\Exception\ContainerValueNotFoundException;
* - errorHandler: a callable with the signature: function($request, $response, $exception)
* - notFoundHandler: a callable with the signature: function($request, $response)
* - notAllowedHandler: a callable with the signature: function($request, $response, $allowedHttpMethods)
* - callableResolver: an instance of callableResolver
* - callableResolver: an instance of \Slim\Interfaces\CallableResolverInterface
*
* @property-read array settings
* @property-read \Slim\Interfaces\Http\EnvironmentInterface environment
@ -56,6 +55,8 @@ class Container extends PimpleContainer implements ContainerInterface
'outputBuffering' => 'append',
'determineRouteBeforeAppMiddleware' => false,
'displayErrorDetails' => false,
'addContentLengthHeader' => true,
'routerCacheFile' => false,
];
/**
@ -94,7 +95,7 @@ class Container extends PimpleContainer implements ContainerInterface
$this['settings'] = function () use ($userSettings, $defaultSettings) {
return new Collection(array_merge($defaultSettings, $userSettings));
};
$defaultProvider = new DefaultServicesProvider();
$defaultProvider->register($this);
}
@ -118,7 +119,34 @@ class Container extends PimpleContainer implements ContainerInterface
if (!$this->offsetExists($id)) {
throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id));
}
return $this->offsetGet($id);
try {
return $this->offsetGet($id);
} catch (\InvalidArgumentException $exception) {
if ($this->exceptionThrownByContainer($exception)) {
throw new SlimContainerException(
sprintf('Container error while retrieving "%s"', $id),
null,
$exception
);
} else {
throw $exception;
}
}
}
/**
* Tests whether an exception needs to be recast for compliance with Container-Interop. This will be if the
* exception was thrown by Pimple.
*
* @param \InvalidArgumentException $exception
*
* @return bool
*/
private function exceptionThrownByContainer(\InvalidArgumentException $exception)
{
$trace = $exception->getTrace()[0];
return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet';
}
/**

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -10,7 +10,6 @@ namespace Slim;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\ContainerValueNotFoundException;
use Slim\Handlers\PhpError;
use Slim\Handlers\Error;
use Slim\Handlers\NotFound;
@ -83,10 +82,23 @@ class DefaultServicesProvider
* This service MUST return a SHARED instance
* of \Slim\Interfaces\RouterInterface.
*
* @param Container $container
*
* @return RouterInterface
*/
$container['router'] = function () {
return new Router;
$container['router'] = function ($container) {
$routerCacheFile = false;
if (isset($container->get('settings')['routerCacheFile'])) {
$routerCacheFile = $container->get('settings')['routerCacheFile'];
}
$router = (new Router)->setCacheFile($routerCacheFile);
if (method_exists($router, 'setContainer')) {
$router->setContainer($container);
}
return $router;
};
}

View file

@ -1,5 +1,11 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;

View file

@ -0,0 +1,20 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
* @license https://github.com/codeguy/Slim/blob/master/LICENSE (MIT License)
*/
namespace Slim\Exception;
use InvalidArgumentException;
use Interop\Container\Exception\ContainerException as InteropContainerException;
/**
* Container Exception
*/
class ContainerException extends InvalidArgumentException implements InteropContainerException
{
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/codeguy/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -0,0 +1,99 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers;
/**
* Abstract Slim application error handler
*/
abstract class AbstractError extends AbstractHandler
{
/**
* @var bool
*/
protected $displayErrorDetails;
/**
* Constructor
*
* @param bool $displayErrorDetails Set to true to display full details
*/
public function __construct($displayErrorDetails = false)
{
$this->displayErrorDetails = (bool) $displayErrorDetails;
}
/**
* Write to the error log if displayErrorDetails is false
*
* @param \Exception|\Throwable $throwable
*
* @return void
*/
protected function writeToErrorLog($throwable)
{
if ($this->displayErrorDetails) {
return;
}
$message = 'Slim Application Error:' . PHP_EOL;
$message .= $this->renderThrowableAsText($throwable);
while ($throwable = $throwable->getPrevious()) {
$message .= PHP_EOL . 'Previous error:' . PHP_EOL;
$message .= $this->renderThrowableAsText($throwable);
}
$message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL;
$this->logError($message);
}
/**
* Render error as Text.
*
* @param \Exception|\Throwable $throwable
*
* @return string
*/
protected function renderThrowableAsText($throwable)
{
$text = sprintf('Type: %s' . PHP_EOL, get_class($throwable));
if ($code = $throwable->getCode()) {
$text .= sprintf('Code: %s' . PHP_EOL, $code);
}
if ($message = $throwable->getMessage()) {
$text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message));
}
if ($file = $throwable->getFile()) {
$text .= sprintf('File: %s' . PHP_EOL, $file);
}
if ($line = $throwable->getLine()) {
$text .= sprintf('Line: %s' . PHP_EOL, $line);
}
if ($trace = $throwable->getTraceAsString()) {
$text .= sprintf('Trace: %s', $trace);
}
return $text;
}
/**
* Wraps the error_log function so that this can be easily tested
*
* @param $message
*/
protected function logError($message)
{
error_log($message);
}
}

View file

@ -0,0 +1,59 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface;
/**
* Abstract Slim application handler
*/
abstract class AbstractHandler
{
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Determine which content type we know about is wanted using Accept header
*
* Note: This method is a bare-bones implementation designed specifically for
* Slim's error handling requirements. Consider a fully-feature solution such
* as willdurand/negotiation for any other situation.
*
* @param ServerRequestInterface $request
* @return string
*/
protected function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return current($selectedContentTypes);
}
// handle +json and +xml specially
if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) {
$mediaType = 'application/' . $matches[1];
if (in_array($mediaType, $this->knownContentTypes)) {
return $mediaType;
}
}
return 'text/html';
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -8,10 +8,10 @@
*/
namespace Slim\Handlers;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Http\Body;
use UnexpectedValueException;
/**
* Default Slim application error handler
@ -19,42 +19,19 @@ use Slim\Http\Body;
* It outputs the error message and diagnostic information in either JSON, XML,
* or HTML based on the Accept header.
*/
class Error
class Error extends AbstractError
{
protected $displayErrorDetails;
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Constructor
*
* @param boolean $displayErrorDetails Set to true to display full details
*/
public function __construct($displayErrorDetails = false)
{
$this->displayErrorDetails = (bool)$displayErrorDetails;
}
/**
* Invoke error handler
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
* @param Exception $exception The caught Exception object
* @param \Exception $exception The caught Exception object
*
* @return ResponseInterface
* @throws UnexpectedValueException
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Exception $exception)
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception)
{
$contentType = $this->determineContentType($request);
switch ($contentType) {
@ -70,6 +47,9 @@ class Error
case 'text/html':
$output = $this->renderHtmlErrorMessage($exception);
break;
default:
throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType);
}
$this->writeToErrorLog($exception);
@ -83,72 +63,14 @@ class Error
->withBody($body);
}
/**
* Write to the error log if displayErrorDetails is false
*
* @param Exception $exception
* @return void
*/
protected function writeToErrorLog($exception)
{
if ($this->displayErrorDetails) {
return;
}
$message = 'Slim Application Error:' . PHP_EOL;
$message .= $this->renderTextException($exception);
while ($exception = $exception->getPrevious()) {
$message .= PHP_EOL . 'Previous exception:' . PHP_EOL;
$message .= $this->renderTextException($exception);
}
$message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL;
error_log($message);
}
/**
* Render exception as Text.
*
* @param Exception $exception
*
* @return string
*/
protected function renderTextException(Exception $exception)
{
$text = sprintf('Type: %s' . PHP_EOL, get_class($exception));
if (($code = $exception->getCode())) {
$text .= sprintf('Code: %s' . PHP_EOL, $code);
}
if (($message = $exception->getMessage())) {
$text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message));
}
if (($file = $exception->getFile())) {
$text .= sprintf('File: %s' . PHP_EOL, $file);
}
if (($line = $exception->getLine())) {
$text .= sprintf('Line: %s' . PHP_EOL, $line);
}
if (($trace = $exception->getTraceAsString())) {
$text .= sprintf('Trace: %s', $trace);
}
return $text;
}
/**
* Render HTML error page
*
* @param Exception $exception
* @param \Exception $exception
*
* @return string
*/
protected function renderHtmlErrorMessage(Exception $exception)
protected function renderHtmlErrorMessage(\Exception $exception)
{
$title = 'Slim Application Error';
@ -181,11 +103,11 @@ class Error
/**
* Render exception as HTML.
*
* @param Exception $exception
* @param \Exception $exception
*
* @return string
*/
protected function renderHtmlException(Exception $exception)
protected function renderHtmlException(\Exception $exception)
{
$html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
@ -216,10 +138,11 @@ class Error
/**
* Render JSON error
*
* @param Exception $exception
* @param \Exception $exception
*
* @return string
*/
protected function renderJsonErrorMessage(Exception $exception)
protected function renderJsonErrorMessage(\Exception $exception)
{
$error = [
'message' => 'Slim Application Error',
@ -246,10 +169,11 @@ class Error
/**
* Render XML error
*
* @param Exception $exception
* @param \Exception $exception
*
* @return string
*/
protected function renderXmlErrorMessage(Exception $exception)
protected function renderXmlErrorMessage(\Exception $exception)
{
$xml = "<error>\n <message>Slim Application Error</message>\n";
if ($this->displayErrorDetails) {
@ -279,22 +203,4 @@ class Error
{
return sprintf('<![CDATA[%s]]>', str_replace(']]>', ']]]]><![CDATA[>', $content));
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -11,6 +11,7 @@ namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Body;
use UnexpectedValueException;
/**
* Default Slim application not allowed handler
@ -18,20 +19,8 @@ use Slim\Http\Body;
* It outputs a simple message in either JSON, XML or HTML based on the
* Accept header.
*/
class NotAllowed
class NotAllowed extends AbstractHandler
{
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Invoke error handler
*
@ -40,6 +29,7 @@ class NotAllowed
* @param string[] $methods Allowed HTTP methods
*
* @return ResponseInterface
* @throws UnexpectedValueException
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, array $methods)
{
@ -63,6 +53,8 @@ class NotAllowed
case 'text/html':
$output = $this->renderHtmlNotAllowedMessage($methods);
break;
default:
throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType);
}
}
@ -77,24 +69,6 @@ class NotAllowed
->withBody($body);
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
/**
* Render PLAIN not allowed message
*

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -11,6 +11,7 @@ namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Body;
use UnexpectedValueException;
/**
* Default Slim application not found handler.
@ -18,20 +19,8 @@ use Slim\Http\Body;
* It outputs a simple message in either JSON, XML or HTML based on the
* Accept header.
*/
class NotFound
class NotFound extends AbstractHandler
{
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Invoke not found handler
*
@ -39,22 +28,27 @@ class NotFound
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
* @throws UnexpectedValueException
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
{
$contentType = $this->determineContentType($request);
switch ($contentType) {
case 'application/json':
$output = $this->renderJsonNotFoundOutput($request, $response);
$output = $this->renderJsonNotFoundOutput();
break;
case 'text/xml':
case 'application/xml':
$output = $this->renderXmlNotFoundOutput($request, $response);
$output = $this->renderXmlNotFoundOutput();
break;
case 'text/html':
$output = $this->renderHtmlNotFoundOutput($request, $response);
$output = $this->renderHtmlNotFoundOutput($request);
break;
default:
throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType);
}
$body = new Body(fopen('php://temp', 'r+'));
@ -65,33 +59,12 @@ class NotFound
->withBody($body);
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
/**
* Return a response for application/json content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderJsonNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
protected function renderJsonNotFoundOutput()
{
return '{"message":"Not found"}';
}
@ -99,12 +72,9 @@ class NotFound
/**
* Return a response for xml content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderXmlNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
protected function renderXmlNotFoundOutput()
{
return '<root><message>Not found</message></root>';
}
@ -113,11 +83,10 @@ class NotFound
* Return a response for text/html content not found
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
*
* @return ResponseInterface
*/
protected function renderHtmlNotFoundOutput(ServerRequestInterface $request, ResponseInterface $response)
protected function renderHtmlNotFoundOutput(ServerRequestInterface $request)
{
$homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment(''));
return <<<END

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -8,10 +8,10 @@
*/
namespace Slim\Handlers;
use Throwable;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Http\Body;
use UnexpectedValueException;
/**
* Default Slim application error handler for PHP 7+ Throwables
@ -19,42 +19,19 @@ use Slim\Http\Body;
* It outputs the error message and diagnostic information in either JSON, XML,
* or HTML based on the Accept header.
*/
class PhpError
class PhpError extends AbstractError
{
protected $displayErrorDetails;
/**
* Known handled content types
*
* @var array
*/
protected $knownContentTypes = [
'application/json',
'application/xml',
'text/xml',
'text/html',
];
/**
* Constructor
*
* @param boolean $displayErrorDetails Set to true to display full details
*/
public function __construct($displayErrorDetails = false)
{
$this->displayErrorDetails = (bool)$displayErrorDetails;
}
/**
* Invoke error handler
*
* @param ServerRequestInterface $request The most recent Request object
* @param ResponseInterface $response The most recent Response object
* @param Throwable $error The caught Throwable object
* @param \Throwable $error The caught Throwable object
*
* @return ResponseInterface
* @throws UnexpectedValueException
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Throwable $error)
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Throwable $error)
{
$contentType = $this->determineContentType($request);
switch ($contentType) {
@ -70,6 +47,8 @@ class PhpError
case 'text/html':
$output = $this->renderHtmlErrorMessage($error);
break;
default:
throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType);
}
$this->writeToErrorLog($error);
@ -83,74 +62,14 @@ class PhpError
->withBody($body);
}
/**
* Write to the error log if displayErrorDetails is false
*
* @param Throwable $error
*
* @return void
*/
protected function writeToErrorLog($error)
{
if ($this->displayErrorDetails) {
return;
}
$message = 'Slim Application Error:' . PHP_EOL;
$message .= $this->renderTextError($error);
while ($error = $error->getPrevious()) {
$message .= PHP_EOL . 'Previous error:' . PHP_EOL;
$message .= $this->renderTextError($error);
}
$message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL;
error_log($message);
}
/**
* Render error as Text.
*
* @param Throwable $error
*
* @return string
*/
protected function renderTextError(Throwable $error)
{
$text = sprintf('Type: %s' . PHP_EOL, get_class($error));
if (($code = $error->getCode())) {
$text .= sprintf('Code: %s' . PHP_EOL, $code);
}
if (($message = $error->getMessage())) {
$text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message));
}
if (($file = $error->getFile())) {
$text .= sprintf('File: %s' . PHP_EOL, $file);
}
if (($line = $error->getLine())) {
$text .= sprintf('Line: %s' . PHP_EOL, $line);
}
if (($trace = $error->getTraceAsString())) {
$text .= sprintf('Trace: %s', $trace);
}
return $text;
}
/**
* Render HTML error page
*
* @param Throwable $error
* @param \Throwable $error
*
* @return string
*/
protected function renderHtmlErrorMessage(Throwable $error)
protected function renderHtmlErrorMessage(\Throwable $error)
{
$title = 'Slim Application Error';
@ -183,11 +102,11 @@ class PhpError
/**
* Render error as HTML.
*
* @param Throwable $error
* @param \Throwable $error
*
* @return string
*/
protected function renderHtmlError(Throwable $error)
protected function renderHtmlError(\Throwable $error)
{
$html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($error));
@ -218,11 +137,11 @@ class PhpError
/**
* Render JSON error
*
* @param Throwable $error
* @param \Throwable $error
*
* @return string
*/
protected function renderJsonErrorMessage(Throwable $error)
protected function renderJsonErrorMessage(\Throwable $error)
{
$json = [
'message' => 'Slim Application Error',
@ -249,10 +168,11 @@ class PhpError
/**
* Render XML error
*
* @param Throwable $error
* @param \Throwable $error
*
* @return string
*/
protected function renderXmlErrorMessage(Throwable $error)
protected function renderXmlErrorMessage(\Throwable $error)
{
$xml = "<error>\n <message>Slim Application Error</message>\n";
if ($this->displayErrorDetails) {
@ -282,22 +202,4 @@ class PhpError
{
return sprintf('<![CDATA[%s]]>', str_replace(']]>', ']]]]><![CDATA[>', $content));
}
/**
* Determine which content type we know about is wanted using Accept header
*
* @param ServerRequestInterface $request
* @return string
*/
private function determineContentType(ServerRequestInterface $request)
{
$acceptHeader = $request->getHeaderLine('Accept');
$selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
if (count($selectedContentTypes)) {
return $selectedContentTypes[0];
}
return 'text/html';
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -141,7 +141,7 @@ class Cookies implements CookiesInterface
if (isset($properties['secure']) && $properties['secure']) {
$result .= '; secure';
}
if (isset($properties['hostonly']) && $properties['hostonly']) {
$result .= '; HostOnly';
}
@ -174,7 +174,7 @@ class Cookies implements CookiesInterface
}
$header = rtrim($header, "\r\n");
$pieces = preg_split('@\s*[;,]\s*@', $header);
$pieces = preg_split('@[;]\s*@', $header);
$cookies = [];
foreach ($pieces as $cookie) {

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -51,6 +51,7 @@ class Headers extends Collection implements HeadersInterface
public static function createFromEnvironment(Environment $environment)
{
$data = [];
$environment = self::determineAuthorization($environment);
foreach ($environment as $key => $value) {
$key = strtoupper($key);
if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) {
@ -63,6 +64,30 @@ class Headers extends Collection implements HeadersInterface
return new static($data);
}
/**
* If HTTP_AUTHORIZATION does not exist tries to get it from
* getallheaders() when available.
*
* @param Environment $environment The Slim application Environment
*
* @return Environment
*/
public static function determineAuthorization(Environment $environment)
{
$authorization = $environment->get('HTTP_AUTHORIZATION');
if (null === $authorization && is_callable('getallheaders')) {
$headers = getallheaders();
$headers = array_change_key_case($headers, CASE_LOWER);
if (isset($headers['authorization'])) {
$environment->set('HTTP_AUTHORIZATION', $headers['authorization']);
}
}
return $environment;
}
/**
* Return array of HTTP header names and values.
* This method returns the _original_ header name

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -31,6 +31,17 @@ abstract class Message implements MessageInterface
*/
protected $protocolVersion = '1.1';
/**
* A map of valid protocol versions
*
* @var array
*/
protected static $validProtocolVersions = [
'1.0' => true,
'1.1' => true,
'2.0' => true,
];
/**
* Headers
*
@ -86,13 +97,11 @@ abstract class Message implements MessageInterface
*/
public function withProtocolVersion($version)
{
static $valid = [
'1.0' => true,
'1.1' => true,
'2.0' => true,
];
if (!isset($valid[$version])) {
throw new InvalidArgumentException('Invalid HTTP version. Must be one of: 1.0, 1.1, 2.0');
if (!isset(self::$validProtocolVersions[$version])) {
throw new InvalidArgumentException(
'Invalid HTTP version. Must be one of: '
. implode(', ', array_keys(self::$validProtocolVersions))
);
}
$clone = clone $this;
$clone->protocolVersion = $version;

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -248,12 +248,9 @@ class Request extends Message implements ServerRequestInterface
if ($customMethod) {
$this->method = $this->filterMethod($customMethod);
} elseif ($this->originalMethod === 'POST') {
$body = $this->getParsedBody();
if (is_object($body) && property_exists($body, '_METHOD')) {
$this->method = $this->filterMethod((string)$body->_METHOD);
} elseif (is_array($body) && isset($body['_METHOD'])) {
$this->method = $this->filterMethod((string)$body['_METHOD']);
$overrideMethod = $this->filterMethod($this->getParsedBodyParam('_METHOD'));
if ($overrideMethod !== null) {
$this->method = $overrideMethod;
}
if ($this->getBody()->eof()) {
@ -684,6 +681,27 @@ class Request extends Message implements ServerRequestInterface
return $this->cookies;
}
/**
* Fetch cookie value from cookies sent by the client to the server.
*
* Note: This method is not part of the PSR-7 standard.
*
* @param string $key The attribute name.
* @param mixed $default Default value to return if the attribute does not exist.
*
* @return mixed
*/
public function getCookieParam($key, $default = null)
{
$cookies = $this->getCookieParams();
$result = $default;
if (isset($cookies[$key])) {
$result = $cookies[$key];
}
return $result;
}
/**
* Return an instance with the specified cookies.
*
@ -828,6 +846,22 @@ class Request extends Message implements ServerRequestInterface
return $this->serverParams;
}
/**
* Retrieve a server parameter.
*
* Note: This method is not part of the PSR-7 standard.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function getServerParam($key, $default = null)
{
$serverParams = $this->getServerParams();
return isset($serverParams[$key]) ? $serverParams[$key] : $default;
}
/*******************************************************************************
* Attributes
******************************************************************************/
@ -967,9 +1001,15 @@ class Request extends Message implements ServerRequestInterface
}
$mediaType = $this->getMediaType();
$body = (string)$this->getBody();
// look for a media type with a structured syntax suffix (RFC 6839)
$parts = explode('+', $mediaType);
if (count($parts) >= 2) {
$mediaType = 'application/' . $parts[count($parts)-1];
}
if (isset($this->bodyParsers[$mediaType]) === true) {
$body = (string)$this->getBody();
$parsed = $this->bodyParsers[$mediaType]($body);
if (!is_null($parsed) && !is_object($parsed) && !is_array($parsed)) {
@ -1091,10 +1131,10 @@ class Request extends Message implements ServerRequestInterface
*
* Note: This method is not part of the PSR-7 standard.
*
* @param $key
* @param null $default
* @param string $key
* @param mixed $default
*
* @return null
* @return mixed
*/
public function getParsedBodyParam($key, $default = null)
{
@ -1114,10 +1154,10 @@ class Request extends Message implements ServerRequestInterface
*
* Note: This method is not part of the PSR-7 standard.
*
* @param $key
* @param null $default
* @param string $key
* @param mixed $default
*
* @return null
* @return mixed
*/
public function getQueryParam($key, $default = null)
{

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -91,6 +91,7 @@ class Response extends Message implements ResponseInterface
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot',
421 => 'Misdirected Request',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
@ -98,7 +99,9 @@ class Response extends Message implements ResponseInterface
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
444 => 'Connection Closed Without Response',
451 => 'Unavailable For Legal Reasons',
499 => 'Client Closed Request',
//Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
@ -111,6 +114,7 @@ class Response extends Message implements ResponseInterface
508 => 'Loop Detected',
510 => 'Not Extended',
511 => 'Network Authentication Required',
599 => 'Network Connect Timeout Error',
];
/**
@ -136,7 +140,6 @@ class Response extends Message implements ResponseInterface
public function __clone()
{
$this->headers = clone $this->headers;
$this->body = clone $this->body;
}
/*******************************************************************************
@ -273,12 +276,22 @@ class Response extends Message implements ResponseInterface
* response to the client.
*
* @param string|UriInterface $url The redirect destination.
* @param int $status The redirect HTTP status code.
* @param int|null $status The redirect HTTP status code.
* @return self
*/
public function withRedirect($url, $status = 302)
public function withRedirect($url, $status = null)
{
return $this->withStatus($status)->withHeader('Location', (string)$url);
$responseWithRedirect = $this->withHeader('Location', (string)$url);
if (is_null($status) && $this->getStatusCode() === 200) {
$status = 302;
}
if (!is_null($status)) {
return $responseWithRedirect->withStatus($status);
}
return $responseWithRedirect;
}
/**
@ -297,16 +310,15 @@ class Response extends Message implements ResponseInterface
*/
public function withJson($data, $status = null, $encodingOptions = 0)
{
$body = $this->getBody();
$body->rewind();
$body->write($json = json_encode($data, $encodingOptions));
$response = $this->withBody(new Body(fopen('php://temp', 'r+')));
$response->body->write($json = json_encode($data, $encodingOptions));
// Ensure that the json encoding passed successfully
if ($json === false) {
throw new \RuntimeException(json_last_error_msg(), json_last_error());
}
$responseWithJson = $this->withHeader('Content-Type', 'application/json;charset=utf-8');
$responseWithJson = $response->withHeader('Content-Type', 'application/json;charset=utf-8');
if (isset($status)) {
return $responseWithJson->withStatus($status);
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -19,6 +19,13 @@ use RuntimeException;
*/
class Stream implements StreamInterface
{
/**
* Bit mask to determine if the stream is a pipe
*
* This is octal as per header stat.h
*/
const FSTAT_MODE_S_IFIFO = 0010000;
/**
* Resource modes
*
@ -72,6 +79,13 @@ class Stream implements StreamInterface
*/
protected $size;
/**
* Is this stream a pipe?
*
* @var bool
*/
protected $isPipe;
/**
* Create a new Stream.
*
@ -158,6 +172,7 @@ class Stream implements StreamInterface
$this->writable = null;
$this->seekable = null;
$this->size = null;
$this->isPipe = null;
return $oldResource;
}
@ -196,7 +211,11 @@ class Stream implements StreamInterface
public function close()
{
if ($this->isAttached() === true) {
fclose($this->stream);
if ($this->isPipe()) {
pclose($this->stream);
} else {
fclose($this->stream);
}
}
$this->detach();
@ -211,7 +230,7 @@ class Stream implements StreamInterface
{
if (!$this->size && $this->isAttached() === true) {
$stats = fstat($this->stream);
$this->size = isset($stats['size']) ? $stats['size'] : null;
$this->size = isset($stats['size']) && !$this->isPipe() ? $stats['size'] : null;
}
return $this->size;
@ -226,7 +245,7 @@ class Stream implements StreamInterface
*/
public function tell()
{
if (!$this->isAttached() || ($position = ftell($this->stream)) === false) {
if (!$this->isAttached() || ($position = ftell($this->stream)) === false || $this->isPipe()) {
throw new RuntimeException('Could not get the position of the pointer in stream');
}
@ -251,13 +270,17 @@ class Stream implements StreamInterface
public function isReadable()
{
if ($this->readable === null) {
$this->readable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
foreach (self::$modes['readable'] as $mode) {
if (strpos($meta['mode'], $mode) === 0) {
$this->readable = true;
break;
if ($this->isPipe()) {
$this->readable = true;
} else {
$this->readable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
foreach (self::$modes['readable'] as $mode) {
if (strpos($meta['mode'], $mode) === 0) {
$this->readable = true;
break;
}
}
}
}
@ -300,7 +323,7 @@ class Stream implements StreamInterface
$this->seekable = false;
if ($this->isAttached()) {
$meta = $this->getMetadata();
$this->seekable = $meta['seekable'];
$this->seekable = !$this->isPipe() && $meta['seekable'];
}
}
@ -406,4 +429,22 @@ class Stream implements StreamInterface
return $contents;
}
/**
* Returns whether or not the stream is a pipe.
*
* @return bool
*/
public function isPipe()
{
if ($this->isPipe === null) {
$this->isPipe = false;
if ($this->isAttached()) {
$mode = fstat($this->stream)['mode'];
$this->isPipe = ($mode & self::FSTAT_MODE_S_IFIFO) !== 0;
}
}
return $this->isPipe;
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -226,11 +226,11 @@ class UploadedFile implements UploadedFileInterface
throw new RuntimeException('Uploaded file already moved');
}
if (!is_writable(dirname($targetPath))) {
$targetIsStream = strpos($targetPath, '://') > 0;
if (!$targetIsStream && !is_writable(dirname($targetPath))) {
throw new InvalidArgumentException('Upload target path is not writable');
}
$targetIsStream = strpos($targetPath, '://') > 0;
if ($targetIsStream) {
if (!copy($this->file, $targetPath)) {
throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath));

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -218,6 +218,9 @@ class Uri implements UriInterface
// Query string
$queryString = $env->get('QUERY_STRING', '');
if ($queryString === '') {
$queryString = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_QUERY);
}
// Fragment
$fragment = '';

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -19,7 +19,7 @@ use Interop\Container\ContainerInterface;
abstract class Routable
{
use CallableResolverAwareTrait;
/**
* Route callable
*
@ -93,4 +93,14 @@ abstract class Routable
$this->middleware[] = new DeferredCallable($callable, $this->container);
return $this;
}
/**
* Set the route pattern
*
* @set string
*/
public function setPattern($newPattern)
{
$this->pattern = $newPattern;
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -9,9 +9,11 @@
namespace Slim;
use Exception;
use Throwable;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Exception\SlimException;
use Slim\Handlers\Strategies\RequestResponse;
use Slim\Interfaces\InvocationStrategyInterface;
use Slim\Interfaces\RouteInterface;
@ -69,18 +71,25 @@ class Route extends Routable implements RouteInterface
*/
protected $arguments = [];
/**
* The callable payload
*
* @var callable
*/
protected $callable;
/**
* 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
* @param string|string[] $methods The route HTTP methods
* @param string $pattern The route pattern
* @param callable $callable The route callable
* @param RouteGroup[] $groups The parent route groups
* @param int $identifier The route identifier
*/
public function __construct($methods, $pattern, $callable, $groups = [], $identifier = 0)
{
$this->methods = $methods;
$this->methods = is_string($methods) ? [$methods] : $methods;
$this->pattern = $pattern;
$this->callable = $callable;
$this->groups = $groups;
@ -120,6 +129,16 @@ class Route extends Routable implements RouteInterface
return $this->callable;
}
/**
* This method enables you to override the Route's callable
*
* @param string|\Closure $callable
*/
public function setCallable($callable)
{
$this->callable = $callable;
}
/**
* Get route methods
*
@ -324,6 +343,11 @@ class Route extends Routable implements RouteInterface
ob_start();
$newResponse = $handler($this->callable, $request, $response, $this->arguments);
$output = ob_get_clean();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
ob_end_clean();
throw $e;
// @codeCoverageIgnoreEnd
} catch (Exception $e) {
ob_end_clean();
throw $e;

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart

View file

@ -1,6 +1,6 @@
<?php
/**
* Slim Framework (http://slimframework.com)
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2016 Josh Lockhart
@ -9,13 +9,13 @@
namespace Slim;
use FastRoute\Dispatcher;
use Interop\Container\ContainerInterface;
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;
@ -30,6 +30,13 @@ use Slim\Interfaces\RouteInterface;
*/
class Router implements RouterInterface
{
/**
* Container Interface
*
* @var ContainerInterface
*/
protected $container;
/**
* Parser
*
@ -44,6 +51,13 @@ class Router implements RouterInterface
*/
protected $basePath = '';
/**
* Path to fast route cache file. Set to false to disable route caching
*
* @var string|False
*/
protected $cacheFile = false;
/**
* Routes
*
@ -97,6 +111,37 @@ class Router implements RouterInterface
return $this;
}
/**
* Set path to fast route cache file. If this is false then route caching is disabled.
*
* @param string|false $cacheFile
*
* @return self
*/
public function setCacheFile($cacheFile)
{
if (!is_string($cacheFile) && $cacheFile !== false) {
throw new InvalidArgumentException('Router cacheFile must be a string or false');
}
$this->cacheFile = $cacheFile;
if ($cacheFile !== false && !is_writable(dirname($cacheFile))) {
throw new RuntimeException('Router cacheFile directory must be writable');
}
return $this;
}
/**
* @param ContainerInterface $container
*/
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Add route
*
@ -123,7 +168,7 @@ class Router implements RouterInterface
$methods = array_map("strtoupper", $methods);
// Add route
$route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter);
$route = $this->createRoute($methods, $pattern, $handler);
$this->routes[$route->getIdentifier()] = $route;
$this->routeCounter++;
@ -142,25 +187,59 @@ class Router implements RouterInterface
public function dispatch(ServerRequestInterface $request)
{
$uri = '/' . ltrim($request->getUri()->getPath(), '/');
return $this->createDispatcher()->dispatch(
$request->getMethod(),
$uri
);
}
/**
* Create a new Route object
*
* @param string[] $methods Array of HTTP methods
* @param string $pattern The route pattern
* @param callable $handler The route callable
*
* @return \Slim\Interfaces\RouteInterface
*/
protected function createRoute($methods, $pattern, $callable)
{
$route = new Route($methods, $pattern, $callable, $this->routeGroups, $this->routeCounter);
if (!empty($this->container)) {
$route->setContainer($this->container);
}
return $route;
}
/**
* @return \FastRoute\Dispatcher
*/
protected function createDispatcher()
{
return $this->dispatcher ?: \FastRoute\simpleDispatcher(function (RouteCollector $r) {
if ($this->dispatcher) {
return $this->dispatcher;
}
$routeDefinitionCallback = function (RouteCollector $r) {
foreach ($this->getRoutes() as $route) {
$r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
}
}, [
'routeParser' => $this->routeParser
]);
};
if ($this->cacheFile) {
$this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [
'routeParser' => $this->routeParser,
'cacheFile' => $this->cacheFile,
]);
} else {
$this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [
'routeParser' => $this->routeParser,
]);
}
return $this->dispatcher;
}
/**
@ -200,6 +279,21 @@ class Router implements RouterInterface
throw new RuntimeException('Named route does not exist for name: ' . $name);
}
/**
* Remove named route
*
* @param string $name Route name
*
* @throws RuntimeException If named route does not exist
*/
public function removeNamedRoute($name)
{
$route = $this->getNamedRoute($name);
// no exception, route exists, now remove by id
unset($this->routes[$route->getIdentifier()]);
}
/**
* Process route groups
*

View file

@ -3,7 +3,7 @@
"type": "library",
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
"keywords": ["framework","micro","api","router"],
"homepage": "http://slimframework.com",
"homepage": "https://slimframework.com",
"license": "MIT",
"authors": [
{
@ -31,13 +31,16 @@
"php": ">=5.5.0",
"pimple/pimple": "^3.0",
"psr/http-message": "^1.0",
"nikic/fast-route": "^0.6",
"nikic/fast-route": "^1.0",
"container-interop/container-interop": "^1.1"
},
"require-dev": {
"squizlabs/php_codesniffer": "^2.5",
"phpunit/phpunit": "^4.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"autoload": {
"psr-4": {
"Slim\\": "Slim"
@ -45,8 +48,8 @@
},
"scripts": {
"test": [
"php vendor/bin/phpcs",
"php vendor/bin/phpunit"
"@phpunit",
"@phpcs"
],
"phpunit": "php vendor/bin/phpunit",
"phpcs": "php vendor/bin/phpcs"

View file

@ -1,12 +0,0 @@
# Note: see https://httpd.apache.org/docs/current/howto/htaccess.html:
#
# "You should avoid using .htaccess files completely if you have access to
# httpd main server config file. Using .htaccess files slows down your Apache
# http server. Any directive that you can include in a .htaccess file is
# better set in a Directory block, as it will have the same effect with
# better performance."
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

View file

@ -1,45 +0,0 @@
<?php
/**
* Step 1: Require the Slim Framework using Composer's autoloader
*
* If you are not using Composer, you need to load Slim Framework with your own
* PSR-4 autoloader.
*/
require 'vendor/autoload.php';
/**
* Step 2: Instantiate a Slim application
*
* This example instantiates a Slim application using
* its default settings. However, you will usually configure
* your Slim application now by passing an associative array
* of setting names and values into the application constructor.
*/
$app = new Slim\App();
/**
* Step 3: Define the Slim application routes
*
* Here we define several Slim application routes that respond
* to appropriate HTTP request methods. In this example, the second
* argument for `Slim::get`, `Slim::post`, `Slim::put`, `Slim::patch`, and `Slim::delete`
* is an anonymous function.
*/
$app->get('/', function ($request, $response, $args) {
$response->write("Welcome to Slim!");
return $response;
});
$app->get('/hello[/{name}]', function ($request, $response, $args) {
$response->write("Hello, " . $args['name']);
return $response;
})->setArgument('name', 'World!');
/**
* Step 4: Run the Slim application
*
* This method should be called last. This executes the Slim application
* and returns the HTTP response to the HTTP client.
*/
$app->run();