Файл: onlinepoisk.wm-scripts.ru/vendor/silex/silex/silex/src/Silex/Application.php
Строк: 746
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Silex;
use SymfonyComponentHttpFoundationBinaryFileResponse;
use SymfonyComponentHttpKernelHttpKernel;
use SymfonyComponentHttpKernelHttpKernelInterface;
use SymfonyComponentHttpKernelTerminableInterface;
use SymfonyComponentHttpKernelEventFilterResponseEvent;
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentHttpKernelEventPostResponseEvent;
use SymfonyComponentHttpKernelEventListenerResponseListener;
use SymfonyComponentHttpKernelEventListenerRouterListener;
use SymfonyComponentHttpKernelExceptionHttpException;
use SymfonyComponentHttpKernelKernelEvents;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationStreamedResponse;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentRoutingRouteCollection;
use SymfonyComponentRoutingRequestContext;
use SilexRedirectableUrlMatcher;
use SilexControllerResolver;
use SilexEventListenerLocaleListener;
use SilexEventListenerMiddlewareListener;
use SilexEventListenerConverterListener;
use SilexEventListenerStringToResponseListener;
/**
* The Silex framework class.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Application extends Pimple implements HttpKernelInterface, TerminableInterface
{
const VERSION = '1.0-DEV';
const EARLY_EVENT = 512;
const LATE_EVENT = -512;
private $providers = array();
private $booted = false;
/**
* Instantiate a new Application.
*
* Objects and parameters can be passed as argument to the constructor.
*
* @param array $values The parameters or objects.
*/
public function __construct(array $values = array())
{
parent::__construct();
$app = $this;
$this['logger'] = null;
$this['routes'] = $this->share(function () {
return new RouteCollection();
});
$this['controllers'] = $this->share(function () use ($app) {
return $app['controllers_factory'];
});
$this['controllers_factory'] = function () use ($app) {
return new ControllerCollection($app['route_factory']);
};
$this['route_class'] = 'Silex\Route';
$this['route_factory'] = function () use ($app) {
return new $app['route_class']();
};
$this['exception_handler'] = $this->share(function () use ($app) {
return new ExceptionHandler($app['debug']);
});
$this['dispatcher_class'] = 'Symfony\Component\EventDispatcher\EventDispatcher';
$this['dispatcher'] = $this->share(function () use ($app) {
$dispatcher = new $app['dispatcher_class']();
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
});
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $app['request_context'], $app['logger']));
$dispatcher->addSubscriber(new LocaleListener($app, $urlMatcher));
if (isset($app['exception_handler'])) {
$dispatcher->addSubscriber($app['exception_handler']);
}
$dispatcher->addSubscriber(new ResponseListener($app['charset']));
$dispatcher->addSubscriber(new MiddlewareListener($app));
$dispatcher->addSubscriber(new ConverterListener($app['routes']));
$dispatcher->addSubscriber(new StringToResponseListener());
return $dispatcher;
});
$this['resolver'] = $this->share(function () use ($app) {
return new ControllerResolver($app, $app['logger']);
});
$this['kernel'] = $this->share(function () use ($app) {
return new HttpKernel($app['dispatcher'], $app['resolver']);
});
$this['request_context'] = $this->share(function () use ($app) {
$context = new RequestContext();
$context->setHttpPort($app['request.http_port']);
$context->setHttpsPort($app['request.https_port']);
return $context;
});
$this['url_matcher'] = $this->share(function () use ($app) {
// Inject the query string into the RequestContext for Symfony versions <= 2.2
if ($app['request']->server->get('QUERY_STRING') !== '' && !method_exists($app['request_context'], 'getQueryString')) {
$app['request_context']->setParameter('QUERY_STRING', $app['request']->server->get('QUERY_STRING'));
}
return new RedirectableUrlMatcher($app['routes'], $app['request_context']);
});
$this['request_error'] = $this->protect(function () {
throw new RuntimeException('Accessed request service outside of request scope. Try moving that call to a before handler or controller.');
});
$this['request'] = $this['request_error'];
$this['request.http_port'] = 80;
$this['request.https_port'] = 443;
$this['debug'] = false;
$this['charset'] = 'UTF-8';
$this['locale'] = 'en';
foreach ($values as $key => $value) {
$this[$key] = $value;
}
}
/**
* Registers a service provider.
*
* @param ServiceProviderInterface $provider A ServiceProviderInterface instance
* @param array $values An array of values that customizes the provider
*
* @return Application
*/
public function register(ServiceProviderInterface $provider, array $values = array())
{
$this->providers[] = $provider;
$provider->register($this);
foreach ($values as $key => $value) {
$this[$key] = $value;
}
return $this;
}
/**
* Boots all service providers.
*
* This method is automatically called by handle(), but you can use it
* to boot all service providers when not handling a request.
*/
public function boot()
{
if (!$this->booted) {
foreach ($this->providers as $provider) {
$provider->boot($this);
}
$this->booted = true;
}
}
/**
* Maps a pattern to a callable.
*
* You can optionally specify HTTP methods that should be matched.
*
* @param string $pattern Matched route pattern
* @param mixed $to Callback that returns the response when matched
*
* @return Controller
*/
public function match($pattern, $to)
{
return $this['controllers']->match($pattern, $to);
}
/**
* Maps a GET request to a callable.
*
* @param string $pattern Matched route pattern
* @param mixed $to Callback that returns the response when matched
*
* @return Controller
*/
public function get($pattern, $to)
{
return $this['controllers']->get($pattern, $to);
}
/**
* Maps a POST request to a callable.
*
* @param string $pattern Matched route pattern
* @param mixed $to Callback that returns the response when matched
*
* @return Controller
*/
public function post($pattern, $to)
{
return $this['controllers']->post($pattern, $to);
}
/**
* Maps a PUT request to a callable.
*
* @param string $pattern Matched route pattern
* @param mixed $to Callback that returns the response when matched
*
* @return Controller
*/
public function put($pattern, $to)
{
return $this['controllers']->put($pattern, $to);
}
/**
* Maps a DELETE request to a callable.
*
* @param string $pattern Matched route pattern
* @param mixed $to Callback that returns the response when matched
*
* @return Controller
*/
public function delete($pattern, $to)
{
return $this['controllers']->delete($pattern, $to);
}
/**
* Adds an event listener that listens on the specified events.
*
* @param string $eventName The event to listen on
* @param callable $callback The listener
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function on($eventName, $callback, $priority = 0)
{
$this['dispatcher']->addListener($eventName, $callback, $priority);
}
/**
* Registers a before filter.
*
* Before filters are run before any route has been matched.
*
* @param mixed $callback Before filter callback
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function before($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$ret = call_user_func($callback, $event->getRequest());
if ($ret instanceof Response) {
$event->setResponse($ret);
}
}, $priority);
}
/**
* Registers an after filter.
*
* After filters are run after the controller has been executed.
*
* @param mixed $callback After filter callback
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function after($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
call_user_func($callback, $event->getRequest(), $event->getResponse());
}, $priority);
}
/**
* Registers a finish filter.
*
* Finish filters are run after the response has been sent.
*
* @param mixed $callback Finish filter callback
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function finish($callback, $priority = 0)
{
$this['dispatcher']->addListener(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {
call_user_func($callback, $event->getRequest(), $event->getResponse());
}, $priority);
}
/**
* Aborts the current request by sending a proper HTTP error.
*
* @param integer $statusCode The HTTP status code
* @param string $message The status message
* @param array $headers An array of HTTP headers
*/
public function abort($statusCode, $message = '', array $headers = array())
{
throw new HttpException($statusCode, $message, null, $headers);
}
/**
* Registers an error handler.
*
* Error handlers are simple callables which take a single Exception
* as an argument. If a controller throws an exception, an error handler
* can return a specific response.
*
* When an exception occurs, all handlers will be called, until one returns
* something (a string or a Response object), at which point that will be
* returned to the client.
*
* For this reason you should add logging handlers before output handlers.
*
* @param mixed $callback Error handler callback, takes an Exception argument
* @param integer $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to -8)
*/
public function error($callback, $priority = -8)
{
$this['dispatcher']->addListener(KernelEvents::EXCEPTION, new ExceptionListenerWrapper($this, $callback), $priority);
}
/**
* Flushes the controller collection.
*
* @param string $prefix The route prefix
*/
public function flush($prefix = '')
{
$this['routes']->addCollection($this['controllers']->flush($prefix));
}
/**
* Redirects the user to another URL.
*
* @param string $url The URL to redirect to
* @param integer $status The status code (302 by default)
*
* @return RedirectResponse
*/
public function redirect($url, $status = 302)
{
return new RedirectResponse($url, $status);
}
/**
* Creates a streaming response.
*
* @param mixed $callback A valid PHP callback
* @param integer $status The response status code
* @param array $headers An array of response headers
*
* @return StreamedResponse
*/
public function stream($callback = null, $status = 200, $headers = array())
{
return new StreamedResponse($callback, $status, $headers);
}
/**
* Escapes a text for HTML.
*
* @param string $text The input text to be escaped
* @param integer $flags The flags (@see htmlspecialchars)
* @param string $charset The charset
* @param Boolean $doubleEncode Whether to try to avoid double escaping or not
*
* @return string Escaped text
*/
public function escape($text, $flags = ENT_COMPAT, $charset = null, $doubleEncode = true)
{
return htmlspecialchars($text, $flags, $charset ?: $this['charset'], $doubleEncode);
}
/**
* Convert some data into a JSON response.
*
* @param mixed $data The response data
* @param integer $status The response status code
* @param array $headers An array of response headers
*
* @return JsonResponse
*/
public function json($data = array(), $status = 200, $headers = array())
{
return new JsonResponse($data, $status, $headers);
}
/**
* Sends a file.
*
* @param SplFileInfo|string $file The file to stream
* @param integer $status The response status code
* @param array $headers An array of response headers
* @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename
*
* @return BinaryFileResponse
*
* @throws RuntimeException When the feature is not supported, before http-foundation v2.2
*/
public function sendFile($file, $status = 200, $headers = array(), $contentDisposition = null)
{
if (!class_exists('SymfonyComponentHttpFoundationBinaryFileResponse')) {
throw new RuntimeException('The "sendFile" method is only supported as of Http Foundation 2.2.');
}
return new BinaryFileResponse($file, $status, $headers, true, $contentDisposition);
}
/**
* Mounts controllers under the given route prefix.
*
* @param string $prefix The route prefix
* @param ControllerCollection|ControllerProviderInterface $controllers A ControllerCollection or a ControllerProviderInterface instance
*
* @return Application
*/
public function mount($prefix, $controllers)
{
if ($controllers instanceof ControllerProviderInterface) {
$controllers = $controllers->connect($this);
}
if (!$controllers instanceof ControllerCollection) {
throw new LogicException('The "mount" method takes either a ControllerCollection or a ControllerProviderInterface instance.');
}
$this['routes']->addCollection($controllers->flush($prefix));
return $this;
}
/**
* Handles the request and delivers the response.
*
* @param Request $request Request to process
*/
public function run(Request $request = null)
{
if (null === $request) {
$request = Request::createFromGlobals();
}
$response = $this->handle($request);
$response->send();
$this->terminate($request, $response);
}
/**
* {@inheritdoc}
*
* If you call this method directly instead of run(), you must call the
* terminate() method yourself if you want the finish filters to be run.
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
if (!$this->booted) {
$this->boot();
}
$current = HttpKernelInterface::SUB_REQUEST === $type ? $this['request'] : $this['request_error'];
$this['request'] = $request;
$this->flush();
$response = $this['kernel']->handle($request, $type, $catch);
$this['request'] = $current;
return $response;
}
/**
* {@inheritdoc}
*/
public function terminate(Request $request, Response $response)
{
$this['kernel']->terminate($request, $response);
}
}