LICENSE 0000666 00000002067 13436753515 0005576 0 ustar 00 The MIT License (MIT) Copyright (c) 2015 Oscar Otero 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. README.md 0000666 00000056663 13436753515 0006063 0 ustar 00 # psr7-middlewares [![Build Status](https://travis-ci.org/oscarotero/psr7-middlewares.svg)](https://travis-ci.org/oscarotero/psr7-middlewares) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/oscarotero/psr7-middlewares/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/oscarotero/psr7-middlewares/?branch=master) Collection of [PSR-7](http://www.php-fig.org/psr/psr-7/) middlewares. It is installable and autoloadable via Composer as oscarotero/psr7-middlewares. ## Requirements * PHP >= 5.5 * A PSR-7 HTTP Message implementation, for example [zend-diactoros](https://github.com/zendframework/zend-diactoros) * A PSR-7 middleware dispatcher. For example [Relay](https://github.com/relayphp/Relay.Relay) or any other compatible with the following signature: ```php use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; function (RequestInterface $request, ResponseInterface $response, callable $next) { // ... } ``` ## Usage example: ```php use Psr7Middlewares\Middleware; use Relay\RelayBuilder; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequestFactory; use Zend\Diactoros\Stream; //Set a stream factory used by some middlewares //(Required only if Zend\Diactoros\Stream is not detected) Middleware::setStreamFactory(function ($file, $mode) { return new Stream($file, $mode); }); //Create a relay dispatcher and add some middlewares: $relay = new RelayBuilder(); $dispatcher = $relay->newInstance([ //Calculate the response time Middleware::responseTime(), //Add an Uuid to request Middleware::uuid(), //Handle errors Middleware::errorHandler('error_handler_function')->catchExceptions(true), //Override the method using X-Http-Method-Override header Middleware::methodOverride(), //Removes www subdomain Middleware::www(false)->redirect(301), //Block search engines robots indexing Middleware::robots(), //Geolocation Middleware::geolocate(), //Detect client device Middleware::detectDevice(), //Parse the request payload Middleware::payload(), //Remove the path prefix Middleware::basePath('/my-site/web'), //Remove the trailing slash Middleware::trailingSlash(), //Digest authentication Middleware::digestAuthentication(['username' => 'password']), //Get the client ip Middleware::clientIp(), //Allow only some ips Middleware::firewall(['127.0.0.*']), //Detects the user preferred language Middleware::languageNegotiator(['gl', 'es', 'en']), //Detects the format Middleware::formatNegotiator(), //Adds the php debug bar Middleware::debugBar($app->get('debugbar')), //Execute fast route Middleware::fastRoute($app->get('dispatcher')), //Minify the result Middleware::minify() //Saves the response in a file Middleware::saveResponse('app/public') ]); $response = $dispatcher(ServerRequestFactory::fromGlobals(), new Response()); ``` ## Available middlewares * [AuraRouter](#aurarouter) * [AuraSession](#aurasession) * [BasePath](#basepath) * [BasicAuthentication](#basicauthentication) * [Cache](#cache) * [ClientIp](#clientip) * [Cors](#cors) * [DebugBar](#debugbar) * [DetectDevice](#detectdevice) * [DigestAuthentication](#digestauthentication) * [ErrorHandler](#errorhandler) * [FastRoute](#fastroute) * [FormTimestamp](#formtimestamp) * [Firewall](#firewall) * [FormatNegotiation](#formatnegotiation) * [Geolocate](#geolocate) * [Honeypot](#honeypot) * [LanguageNegotiation](#languagenegotiation) * [MethodOverride](#methodoverride) * [Minify](#minify) * [Payload](#payload) * [ReadResponse](#readresponse) * [ResponseTime](#responseTime) * [Robots](#robots) * [SaveResponse](#saveresponse) * [Shutdown](#shutdown) * [TrailingSlash](#trailingslash) * [Uuid](#uuid) * [When](#when) * [Www](#www) ### AuraRouter To use [Aura.Router](https://github.com/auraphp/Aura.Router) as a middleware. You need the 3.x version, compatible with psr-7: ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\AuraRouter; use Aura\Router\RouterContainer; //Create the router $routerContainer = new RouterContainer(); $map = $routerContainer->getMap(); $map->get('hello', '/hello/{name}', function ($request, $response, $myApp) { //The route parameters are stored as attributes $name = $request->getAttribute('name'); //You can get also the route instance $route = AuraRouter::getRoute($request); //Write directly in the response's body $response->getBody()->write('Hello '.$name); //or echo the output (it will be captured and writted into body) echo 'Hello world'; //or return a string return 'Hello world'; //or return a new response return $response->withStatus(200); }); //Add to the dispatcher $dispatcher = $relay->getInstance([ Middleware::AuraRouter() ->router($routerContainer) //Instance of Aura\Router\RouterContainer ->arguments($myApp) //(optional) append more arguments to the controller ]); ``` ### AuraSession Creates a new [Aura.Session](https://github.com/auraphp/Aura.Session) instance with the request. ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\AuraSession; $dispatcher = $relay->getInstance([ Middleware::AuraSession(), ->factory($sessionFactory) //(optional) Intance of Aura\Session\SessionFactory ->name('my-session-name'), //(optional) custom session name function ($request, $reponse, $next) { //Get the session instance $session = AuraSession::getSession($request); } ]); ``` ### BasePath Strip off the prefix from the uri path of the request. This is useful to combine with routers if the root of the website is in a subdirectory. For example, if the root of your website is `/web/public`, a request with the uri `/web/public/post/34` will be converted to `/post/34`. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::BasePath('/web/public'), ]); ``` ### BasicAuthentication Implements the [basic http authentication](http://php.net/manual/en/features.http-auth.php). You have to provide an array with all users and password: ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::BasicAuthentication() ->users([ 'username1' => 'password1', 'username2' => 'password2' ]) ->realm('My realm') //(optional) change the realm value ]); ``` ### Cache To save and reuse responses based in the Cache-Control: max-age directive and Expires header. You need a cache library compatible with psr-6 ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::Cache() ->cache(new Psr6CachePool()) //the psr-6 cache implementation function($request, $response, $next) { //Cache the response 1 hour return $response->withHeader('Cache-Control', 'max-age=3600'); } ]); ``` ### ClientIp Detects the client ip(s). ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\ClientIp; $dispatcher = $relay->getInstance([ Middleware::ClientIp() ->headers([ 'Client-Ip', 'X-Forwarded-For', 'X-Forwarded' ]), //(optional) to change the trusted headers function ($request, $response, $next) { //Get the user ip $ip = ClientIp::getIp($request); //Get all ips found in the headers $all_ips = ClientIp::getIps($request); return $next($request, $response); } ]); ``` ### Cors To use the [neomerx/cors-psr7](https://github.com/neomerx/cors-psr7) library: ```php use Neomerx\Cors\Strategies\Settings $relay = new RelayBuilder(); $settings = (new Settings()) ->setServerOrigin([ 'scheme' => 'http', 'host' => 'example.com', 'port' => '123', ]); $dispatcher = $relay->getInstance([ Middleware::Cors() ->settings($settings) ]); ``` ### DebugBar Inserts the [PHP debug bar](http://phpdebugbar.com/) in the html body. This middleware requires `Middleware::formatNegotiator` executed before, to insert the debug bar only in Html responses. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::FormatNegotiator(), Middleware::DebugBar() ->debugBar(new DebugBar\StandardDebugBar()) ]); ``` ### DetectDevice Uses [Mobile-Detect](https://github.com/serbanghita/Mobile-Detect) library to detect the client device. ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\DetectDevice; $dispatcher = $relay->getInstance([ Middleware::DetectDevice(), function ($request, $response, $next) { //Get the device info $device = DetectDevice::getDevice($request); if ($device->isMobile()) { //mobile stuff } elseif ($device->isTablet()) { //tablet stuff } elseif ($device->is('bot')) { //bot stuff } return $next($request, $response); }, ]); ``` ### DigestAuthentication Implements the [digest http authentication](http://php.net/manual/en/features.http-auth.php). You have to provide an array with the users and password: ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::DigestAuthentication() ->users([ 'username1' => 'password1', 'username2' => 'password2' ]) ->realm('My realm') //(optional) custom realm value ->nonce(uniqid()) //(optional) custom nonce value ]); ``` ### ErrorHandler Executes a handler if the response returned by the next middlewares has any error (status code 400-599). You can catch also the exceptions throwed or even use [whoops](https://github.com/filp/whoops) as error handler. ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\ErrorHandler; function errorHandler($request, $response, $myApp) { switch ($response->getStatusCode()) { case 404: return 'Page not found'; case 500: //you can get the exception catched $exception = ErrorHandler::getException($request); return 'Server error: '.$exception->getMessage(); default: return 'There was an error' } } $whoops = new Whoops\Run(); $dispatcher = $relay->getInstance([ Middleware::ErrorHandler() ->handler('errorHandler') //The error handler ->arguments($myApp) //(optional) extra arguments to the handler ->whoops($whoops) //(optional) provide a whoops instance to capture errors and exceptions ->catchExceptions() //(optional) to catch exceptions if you don't use an external library for that ]); ``` ### FastRoute To use [FastRoute](https://github.com/nikic/FastRoute) as a middleware. ```php use Psr7Middlewares\Middleware; $router = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $r) { $r->addRoute('GET', '/blog/{id:[0-9]+}', function ($request, $response, $app) { return 'This is the post number'.$request->getAttribute('id'); }); }); $dispatcher = $relay->getInstance([ Middleware::FastRoute() ->router($router) //Instance of FastRoute\Dispatcher ->argument($myApp) //(optional) arguments appended to the controller ]); ``` ### Firewall Uses [M6Web/Firewall](https://github.com/M6Web/Firewall) to provide a IP filtering. This middleware deppends of **ClientIp** (to extract the ips from the headers). [See the ip formats allowed](https://github.com/M6Web/Firewall#entries-formats) for trusted/untrusted options: ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ //required to capture the user ips before Middleware::ClientIp(), //set the firewall Middleware::Firewall() ->trusted(['123.0.0.*']) //(optional) ips allowed ->untrusted(['123.0.0.1']) //(optional) ips not allowed ]); ``` ### FormatNegotiation Uses [willdurand/Negotiation (2.x)](https://github.com/willdurand/Negotiation) to detect and negotiate the format of the document using the url extension and/or the `Accept` http header. It also adds the `Content-Type` header to the response if it's missing. ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\FormatNegotiator; $dispatcher = $relay->getInstance([ Middleware::FormatNegotiator() ->defaultFormat('html') //(optional) default format if it's unable to detect. (by default is "html") ->addFormat('pdf', ['application/pdf', 'application/x-download']), //(optional) add new formats and mimetypes function ($request, $response, $next) { //get the format (for example: html) $format = FormatNegotiator::getFormat($request); return $next($request, $response); } ]); ``` ### FormTimestamp Simple spam protection based in injecting a hidden input in all post forms with the current timestamp. On submit the form, check the time value. If it's less than (for example) 3 seconds ago, assumes it's a bot, so returns a 403 response. You can also set a max number of seconds before the form expires. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ //required to get the format of the request (only executed in html requests) Middleware::FormatNegotiator(), Middleware::FormTimestamp() ->min(5) //(optional) Minimum seconds needed to validate the request (default: 3) ->max(3600) //(optional) Life of the form in second. Default is 0 (no limit) ->inputName('time-token') //(optional) Name of the input (default: hpt_time) ->key('my-secret-key'), //(optional but recomended) Key used to encrypt/decrypt the input value. If it's not defined, the value won't be encrypted ]); ``` ### Geolocate Uses [Geocoder library](https://github.com/geocoder-php/Geocoder) to geolocate the client using the ip. This middleware deppends of **ClientIp** (to extract the ips from the headers). ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\Geolocate; $dispatcher = $relay->getInstance([ //required to capture the user ips before Middleware::ClientIp(), Middleware::Geolocate() ->geocoder($geocoder), //(optional) To provide a custom Geocoder instance function ($request, $response, $next) { //get the location $addresses = Geolocate::getLocation($request); //get the country $country = $addresses->first()->getCountry(); $response->getBody()->write('Hello to '.$country); return $next($request, $response); } ]); ``` ### Honeypot Implements a honeypot span prevention. This technique is based on creating a input field that should be invisible and left empty by real users but filled by most spam bots. The middleware scan the html code and insert this inputs in all forms with method `post` and check in the incoming requests whether this value exists and is empty (is a real user) or doesn't exist or has a value (is a bot) returning a 403 response. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ //required to get the format of the request (only executed in html requests) Middleware::formatNegotiator(), Middleware::Honeypot() ->inputName('my_name') //(optional) The name of the input field (by default "hpt_name") ->inputClass('hidden') //(optional) The class of the input field (by default "hpt_input") } ]); ``` ### LanguageNegotiation Uses [willdurand/Negotiation](https://github.com/willdurand/Negotiation) to detect and negotiate the client language. You must provide an array with all available languages: ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\LanguageNegotiator; $dispatcher = $relay->getInstance([ Middleware::LanguageNegotiator() ->languages(['gl', 'en', 'es']), //Available languages function ($request, $response, $next) { //Get the preferred language $language = LanguageNegotiator::getLanguage($request); return $next($request, $response); } ]); ``` ### MethodOverride Overrides the request method using the `X-Http-Method-Override` header. This is useful for clients unable to send other methods than GET and POST: ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::MethodOverride() ->get(['HEAD', 'CONNECT', 'TRACE', 'OPTIONS']), //(optional) to customize the allowed GET overrided methods ->post(['PATCH', 'PUT', 'DELETE', 'COPY', 'LOCK', 'UNLOCK']), //(optional) to customize the allowed POST overrided methods ]); ``` ### Minify Uses [mrclay/minify](https://github.com/mrclay/minify) to minify the html, css and js code from the responses. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ //needed to get the format of the response Middleware::formatNegotiator(), Middleware::Minify() ->forCache(true) //(optional) only minify cacheable responses ->inlineCss(false) //(optional) enable/disable inline css minification ->inlineJs(false) //(optional) enable/disable inline js minification ]); ``` ### Payload Parses the body of the request if it's not parsed and the method is POST, PUT or DELETE. It has support for json, csv and url encoded format. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::Payload() ->associative(true) //(optional) To generate associative arrays with json objects function ($request, $response, $next) { //Get the parsed body $content = $request->getParsedBody(); return $next($request, $response); } ]); ``` ### ReadResponse Read the response content from a file. It's the opposite of [SaveResponse](#saveresponse) ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::ReadResponse() ->storage('path/to/document/root') //Path where the files are stored ->basePath('public') //(optional) basepath ignored from the request uri ]); ``` ### ResponseTime Calculates the response time (in miliseconds) and saves it into `X-Response-Time` header: ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::ResponseTime() ]); ``` ### Robots Disables the robots of the search engines for non-production environment. Adds automatically the header `X-Robots-Tag: noindex, nofollow, noarchive` in all responses and returns a default body for `/robots.txt` request. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::Robots() ]); ``` ### SaveResponse Saves the response content into a file if all of the following conditions are met: * The method is `GET` * The status code is `200` * The `Cache-Control` header does not contain `no-cache` value * The request has not query parameters. This is useful for cache purposes ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::SaveResponse() ->storage('path/to/document/root') //Path directory where save the responses ->basePath('public') //(optional) basepath ignored from the request uri ]); ``` ### Shutdown Useful to display a 503 maintenance page. You need to specify a handler. ```php use Psr7Middlewares\Middleware; function shutdownHandler ($request, $response, $app) { $response->getBody()->write('Service unavailable'); } $dispatcher = $relay->getInstance([ Middleware::Shutdown() ->handler('shutdownHandler') //Callable that generate the response ->arguments($app) //(optional) to add extra arguments to the handler ]); ``` ### TrailingSlash Removes (or adds) the trailing slash of the path. For example, `/post/23/` will be converted to `/post/23`. If the path is `/` it won't be converted. Useful if you have problems with the router. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::TrailingSlash() ->addSlash(true) //(optional) to add the trailing slash instead remove ->redirect(301) //(optional) to return a 301 (seo friendly) or 302 response to the new path ->basePath('public') //(optional) basepath ]); ``` ### Uuid Uses [ramsey/uuid](https://github.com/ramsey/uuid) to generate an Uuid (Universally Unique Identifiers) for each request (compatible with [RFC 4122](http://tools.ietf.org/html/rfc4122) versions 1, 3, 4 and 5). It's usefull for debugging purposes. ```php use Psr7Middlewares\Middleware; use Psr7Middlewares\Middleware\Uuid; $dispatcher = $relay->getInstance([ Middleware::Uuid() ->version(4) //(optional) version of the identifier (1 by default). Versions 3 and 5 need more arguments (see https://github.com/ramsey/uuid#examples) ->header(false), //(optional) Name of the header to store the identifier (X-Uuid by default). Set false to don't save header function ($request, $response, $next) { //Get the X-Uuid header $id = $request->getHeaderLine('X-Uuid'); //Get the Uuid instance $uuid = Uuid::getUuid($request); echo $uuid->toString(); return $next($request, $response); } ]); ``` ### When Execute a middleware only if a condition is evaluated as true. This is useful to add middleware only under some circunstances or environments. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::When() ->condition(getenv('ENV') === 'production') //The condition to be evaluated ->middleware(Middleware::minify()), //The middleware to be executed when the condition is true //You can use also callables: Middleware::when() ->condition(function ($request, $response) { return $request->hasHeader('X-Foo') }) ->middleware(function ($request, $response, $next) { //your code return $next($request, $response); }) ]); ``` ### Www Adds or removes the `www` subdomain in the host uri and, optionally, returns a redirect response. The following types of host values wont be changed: * The one word hosts, for example: `http://localhost`. * The ip based hosts, for example: `http://0.0.0.0`. * The multi domain hosts, for example: `http://subdomain.example.com`. ```php use Psr7Middlewares\Middleware; $dispatcher = $relay->getInstance([ Middleware::Www() ->addWww(true) //(optional) Add www instead remove it ->redirect(301) //(optional) to return a 301 (seo friendly) or 302 response to the new host ]); ``` ## Combine with container interop If you're using any container compatible with the [Container Interoperability Project](https://github.com/container-interop/container-interop) you can use it to provide instances to some middlewares (routers, debugbar, psr6 cache, etc). To do that, there's the method `->from($container, $id)` available in the following middlewares: ```php $container = new MyContainerInterop(); $dispatcher = $relay->getInstance([ Middleware::Cache()->from($container, 'cache'), Middleware::Cors()->from($container, 'cors-settings'), Middleware::DebugBar()->from($container, 'debug-bar'), Middleware::AuraSession()->from($container, 'session-factory'), Middleware::FastRouter()->from($container, 'fast-router'), Middleware::Geolocate()->from($container, 'geocoder'), ]); ``` By using containers instead creating and passing the instances directly, these instances will be created (for example `$container->get('fast-router')`) only if the middleware is executed. ## Contribution New middlewares are appreciated. Just create a pull request. src/Middleware.php 0000666 00000005617 13436753515 0010152 0 ustar 00 newInstanceArgs($args); } return new $class(); } throw new RuntimeException("The middleware {$name} does not exits"); } /** * Store an attribute in the request. * * @param ServerRequestInterface $request * @param string $name * @param mixed $value * * @return ServerRequestInterface */ public static function setAttribute(ServerRequestInterface $request, $name, $value) { $attributes = $request->getAttribute(self::KEY, []); $attributes[$name] = $value; return $request->withAttribute(self::KEY, $attributes); } /** * Retrieves an attribute from the request. * * @param ServerRequestInterface $request * @param string $name * * @return mixed */ public static function getAttribute(ServerRequestInterface $request, $name) { $attributes = $request->getAttribute(self::KEY); if (isset($attributes[$name])) { return $attributes[$name]; } } /** * Check whether an attribute exists. * * @param ServerRequestInterface $request * @param string $name * * @return bool */ public static function hasAttribute(ServerRequestInterface $request, $name) { $attributes = $request->getAttribute(self::KEY); if (empty($attributes)) { return false; } return array_key_exists($name, $attributes); } } src/Utils/FileTrait.php 0000666 00000002164 13436753515 0011052 0 ustar 00 getBasePath($request->getUri()->getPath()); $parts = pathinfo($path); $path = '/'.(isset($parts['dirname']) ? $parts['dirname'] : ''); $filename = isset($parts['basename']) ? $parts['basename'] : ''; //if it's a directory, append "/index.html" if (empty($parts['extension'])) { if ($path === '/') { $path .= $filename; } else { $path .= "/{$filename}"; } $extension = strtolower(pathinfo($request->getUri()->getPath(), PATHINFO_EXTENSION)) ?: 'html'; $filename = "index.{$extension}"; } return "{$this->storage}{$path}/{$filename}"; } } src/Utils/CallableTrait.php 0000666 00000005021 13436753515 0011665 0 ustar 00 arguments); $target = static::getCallable($target, $arguments); $return = call_user_func_array($target, $arguments); if ($return instanceof ResponseInterface) { $response = $return; $return = ''; } $return = ob_get_contents().$return; $body = $response->getBody(); if ($return !== '' && $body->isWritable()) { $body->write($return); } return $response; } catch (\Exception $exception) { throw $exception; } finally { if (ob_get_level() > 0) { ob_end_clean(); } } } /** * Resolves the target of the route and returns a callable. * * @param mixed $target * @param array $construct_args * * @throws RuntimeException If the target is not callable * * @return callable */ protected static function getCallable($target, array $construct_args) { //if it's callable as is if (is_callable($target)) { return $target; } if (is_string($target)) { //is a class "classname::method" if (strpos($target, '::') === false) { $class = $target; $method = '__invoke'; } else { list($class, $method) = explode('::', $target, 2); } if (!class_exists($class)) { throw new RuntimeException("The class {$class} does not exists"); } $class = new \ReflectionClass($class); $instance = $class->hasMethod('__construct') ? $class->newInstanceArgs($construct_args) : $class->newInstance(); $target = [$instance, $method]; } throw new RuntimeException('The route target is not callable'); } } src/Utils/ContainerTrait.php 0000666 00000002671 13436753515 0012120 0 ustar 00 container = $container; $this->containerId = $id; return $this; } /** * Returns the service from the container. * * @param string $type * @param bool $required * * @return null|mixed */ protected function getFromContainer($type = null, $required = true) { if (isset($this->container)) { $item = $this->container->get($this->containerId); if ($type !== null && !is_a($item, $type)) { throw new InvalidArgumentException("Invalid argument, it's not of type '{$type}'"); } return $item; } if ($required) { $class = get_class($this); throw new RuntimeException("Missing required '{$type}' in the middleware '{$class}'"); } } } src/Utils/ArgumentsTrait.php 0000666 00000000557 13436753515 0012144 0 ustar 00 arguments = func_get_args(); return $this; } } src/Utils/CryptTrait.php 0000666 00000001775 13436753515 0011303 0 ustar 00 cipher = new AES(); $this->cipher->setKey($key); return $this; } /** * Encrypt the given value. * * @param string $value * * @return string */ protected function encrypt($value) { if ($this->cipher) { return bin2hex($this->cipher->encrypt($value)); } return $value; } /** * Decrypt the given value. * * @param string $value * * @return string */ protected function decrypt($value) { if ($this->cipher) { return $this->cipher->decrypt(hex2bin($value)); } return $value; } } src/Utils/HandlerTrait.php 0000666 00000002151 13436753515 0011544 0 ustar 00 handler($handler); } } /** * Set the handler. * * @param string|callable $handler * * @return self */ public function handler($handler) { $this->handler = $handler; return $this; } /** * Execute the target. * * @param RequestInterface $request * @param ResponseInterface $response * * @return ResponseInterface */ protected function executeHandler(RequestInterface $request, ResponseInterface $response) { return $this->executeCallable($this->handler, $request, $response); } } src/Utils/StorageTrait.php 0000666 00000001061 13436753515 0011572 0 ustar 00 storage($storage); } /** * Configure the storage. * * @param string $storage * * @return self */ public function storage($storage) { $this->storage = $storage; return $this; } } src/Utils/AuthenticationTrait.php 0000666 00000001604 13436753515 0013150 0 ustar 00 password] */ public function __construct(array $users = null) { if ($users !== null) { $this->users($users); } } /** * Configure the users and passwords. * * @param array $users [username => password] * * @return self */ public function users(array $users) { $this->users = $users; return $this; } /** * Set the realm value. * * @param string $realm * * @return self */ public function realm($realm) { $this->realm = $realm; return $this; } } src/Utils/RedirectTrait.php 0000666 00000002420 13436753515 0011727 0 ustar 00 redirectStatus = $redirectStatus; return $this; } /** * Returns a redirect response. * * @param int $redirectStatus * @param UriInterface $uri * @param ResponseInterface $response */ protected static function getRedirectResponse($redirectStatus, UriInterface $uri, ResponseInterface $response) { return $response ->withStatus($redirectStatus) ->withHeader('Location', (string) $uri) ->withBody(Middleware::createStream()); } } src/Utils/FormTrait.php 0000666 00000002721 13436753515 0011075 0 ustar 00 getBody(); $html = preg_replace_callback( '/(