Commit 8a7b4321 authored by Fabien Potencier's avatar Fabien Potencier

changed Application to extend Pimple (this makes everything configurable)

You can now use the app instance to store objects or parameters:

$app = new Application();
$app['twig'] = new \Twig_Environment(...);
$app['debug'] = true;

$app->get('/', function() use ($app) {
    return $app['twig']->load('index.html')->render(array());
});

For sercices, you can even make them lazy loaded and/or shared:

$app['twig'] = $app->asShared(function ()
{
    return \Twig_Environment(...);
});
parent 36bef409
...@@ -25,3 +25,6 @@ ...@@ -25,3 +25,6 @@
[submodule "vendor/Symfony/Component/CssSelector"] [submodule "vendor/Symfony/Component/CssSelector"]
path = vendor/Symfony/Component/CssSelector path = vendor/Symfony/Component/CssSelector
url = https://github.com/symfony/CssSelector url = https://github.com/symfony/CssSelector
[submodule "vendor/pimple"]
path = vendor/pimple
url = https://github.com/fabpot/Pimple
...@@ -9,4 +9,7 @@ $loader->registerNamespaces(array( ...@@ -9,4 +9,7 @@ $loader->registerNamespaces(array(
'Symfony' => __DIR__.'/vendor', 'Symfony' => __DIR__.'/vendor',
'Silex' => __DIR__.'/src', 'Silex' => __DIR__.'/src',
)); ));
$loader->registerPrefixes(array(
'Pimple' => __DIR__.'/vendor/pimple/lib',
));
$loader->register(); $loader->register();
...@@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; ...@@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Events as HttpKernelEvents;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcher;
...@@ -34,49 +35,37 @@ use Symfony\Component\Routing\Matcher\Exception\NotFoundException; ...@@ -34,49 +35,37 @@ use Symfony\Component\Routing\Matcher\Exception\NotFoundException;
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class Application implements HttpKernelInterface, EventSubscriberInterface class Application extends \Pimple implements HttpKernelInterface, EventSubscriberInterface
{ {
private $dispatcher;
private $routes;
private $controllers;
private $request;
private $kernel;
/** /**
* Constructor. * Constructor.
*/ */
public function __construct() public function __construct()
{ {
$this->routes = new RouteCollection(); $sc = $this;
$this->controllers = new ControllerCollection($this->routes);
$this->dispatcher = new EventDispatcher(); $this['routes'] = $this->asShared(function () {
$this->dispatcher->addSubscriber($this); return new RouteCollection();
$this->dispatcher->addListener(\Symfony\Component\HttpKernel\Events::onCoreView, $this, -10); });
$this['controllers'] = $this->asShared(function () use ($sc) {
return new ControllerCollection($sc['routes']);
});
$resolver = new ControllerResolver(); $this['dispatcher'] = $this->asShared(function () use ($sc) {
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber($sc);
$dispatcher->addListener(HttpKernelEvents::onCoreView, $sc, -10);
$this->kernel = new HttpKernel($this->dispatcher, $resolver); return $dispatcher;
} });
/** $this['resolver'] = $this->asShared(function () {
* Gets the current request. return new ControllerResolver();
* });
* @return Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
return $this->request;
}
/** $this['kernel'] = $this->asShared(function () use ($sc) {
* Gets the collection of routes. return new HttpKernel($sc['dispatcher'], $sc['resolver']);
* });
* @return Symfony\Component\Routing\RouteCollection
*/
public function getRoutes()
{
return $this->routes;
} }
/** /**
...@@ -101,7 +90,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -101,7 +90,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
$route = new Route($pattern, array('_controller' => $to), $requirements); $route = new Route($pattern, array('_controller' => $to), $requirements);
$controller = new Controller($route); $controller = new Controller($route);
$this->controllers->add($controller); $this['controllers']->add($controller);
return $controller; return $controller;
} }
...@@ -171,7 +160,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -171,7 +160,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function before($callback) public function before($callback)
{ {
$this->dispatcher->addListener(Events::onSilexBefore, $callback); $this['dispatcher']->addListener(Events::onSilexBefore, $callback);
return $this; return $this;
} }
...@@ -189,7 +178,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -189,7 +178,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function after($callback) public function after($callback)
{ {
$this->dispatcher->addListener(Events::onSilexAfter, $callback); $this['dispatcher']->addListener(Events::onSilexAfter, $callback);
return $this; return $this;
} }
...@@ -215,7 +204,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -215,7 +204,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function error($callback) public function error($callback)
{ {
$this->dispatcher->addListener(Events::onSilexError, function(GetResponseForErrorEvent $event) use ($callback) { $this['dispatcher']->addListener(Events::onSilexError, function(GetResponseForErrorEvent $event) use ($callback) {
$exception = $event->getException(); $exception = $event->getException();
$result = $callback->__invoke($exception); $result = $callback->__invoke($exception);
...@@ -232,7 +221,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -232,7 +221,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function flush() public function flush()
{ {
$this->controllers->flush(); $this['controllers']->flush();
} }
/** /**
...@@ -251,7 +240,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -251,7 +240,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{ {
return $this->kernel->handle($request, $type, $catch); return $this['kernel']->handle($request, $type, $catch);
} }
/** /**
...@@ -259,31 +248,31 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -259,31 +248,31 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function onCoreRequest(KernelEvent $event) public function onCoreRequest(KernelEvent $event)
{ {
$this->request = $event->getRequest(); $this['request'] = $event->getRequest();
$this->controllers->flush(); $this['controllers']->flush();
$matcher = new UrlMatcher($this->routes, array( $matcher = new UrlMatcher($this['routes'], array(
'base_url' => $this->request->getBaseUrl(), 'base_url' => $this['request']->getBaseUrl(),
'method' => $this->request->getMethod(), 'method' => $this['request']->getMethod(),
'host' => $this->request->getHost(), 'host' => $this['request']->getHost(),
'port' => $this->request->getPort(), 'port' => $this['request']->getPort(),
'is_secure' => $this->request->isSecure(), 'is_secure' => $this['request']->isSecure(),
)); ));
try { try {
$attributes = $matcher->match($this->request->getPathInfo()); $attributes = $matcher->match($this['request']->getPathInfo());
$this->request->attributes->add($attributes); $this['request']->attributes->add($attributes);
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
$message = sprintf('No route found for "%s %s"', $this->request->getMethod(), $this->request->getPathInfo()); $message = sprintf('No route found for "%s %s"', $this['request']->getMethod(), $this['request']->getPathInfo());
throw new NotFoundHttpException('Not Found', $message, 0, $e); throw new NotFoundHttpException('Not Found', $message, 0, $e);
} catch (MethodNotAllowedException $e) { } catch (MethodNotAllowedException $e) {
$message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $this->request->getMethod(), $this->request->getPathInfo(), strtoupper(implode(', ', $e->getAllowedMethods()))); $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $this['request']->getMethod(), $this['request']->getPathInfo(), strtoupper(implode(', ', $e->getAllowedMethods())));
throw new MethodNotAllowedHttpException($e->getAllowedMethods(), 'Method Not Allowed', $message, 0, $e); throw new MethodNotAllowedHttpException($e->getAllowedMethods(), 'Method Not Allowed', $message, 0, $e);
} }
$this->dispatcher->dispatch(Events::onSilexBefore); $this['dispatcher']->dispatch(Events::onSilexBefore);
} }
/** /**
...@@ -305,7 +294,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -305,7 +294,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
*/ */
public function onCoreResponse(Event $event) public function onCoreResponse(Event $event)
{ {
$this->dispatcher->dispatch(Events::onSilexAfter); $this['dispatcher']->dispatch(Events::onSilexAfter);
} }
/** /**
...@@ -319,7 +308,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -319,7 +308,7 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
public function onCoreException(GetResponseForExceptionEvent $event) public function onCoreException(GetResponseForExceptionEvent $event)
{ {
$errorEvent = new GetResponseForErrorEvent($this, $event->getRequest(), $event->getRequestType(), $event->getException()); $errorEvent = new GetResponseForErrorEvent($this, $event->getRequest(), $event->getRequestType(), $event->getException());
$this->dispatcher->dispatch(Events::onSilexError, $errorEvent); $this['dispatcher']->dispatch(Events::onSilexError, $errorEvent);
if ($errorEvent->hasResponse()) { if ($errorEvent->hasResponse()) {
$event->setResponse($errorEvent->getResponse()); $event->setResponse($errorEvent->getResponse());
...@@ -334,9 +323,9 @@ class Application implements HttpKernelInterface, EventSubscriberInterface ...@@ -334,9 +323,9 @@ class Application implements HttpKernelInterface, EventSubscriberInterface
// onCoreView listener is added manually because it has lower priority // onCoreView listener is added manually because it has lower priority
return array( return array(
\Symfony\Component\HttpKernel\Events::onCoreRequest, HttpKernelEvents::onCoreRequest,
\Symfony\Component\HttpKernel\Events::onCoreResponse, HttpKernelEvents::onCoreResponse,
\Symfony\Component\HttpKernel\Events::onCoreException, HttpKernelEvents::onCoreException,
); );
} }
} }
...@@ -37,6 +37,7 @@ class Compiler ...@@ -37,6 +37,7 @@ class Compiler
->ignoreVCS(true) ->ignoreVCS(true)
->name('*.php') ->name('*.php')
->in(__DIR__.'/..') ->in(__DIR__.'/..')
->in(__DIR__.'/../../vendor/pimple')
->in(__DIR__.'/../../vendor/Symfony/Component/ClassLoader') ->in(__DIR__.'/../../vendor/Symfony/Component/ClassLoader')
->in(__DIR__.'/../../vendor/Symfony/Component/EventDispatcher') ->in(__DIR__.'/../../vendor/Symfony/Component/EventDispatcher')
->in(__DIR__.'/../../vendor/Symfony/Component/HttpFoundation') ->in(__DIR__.'/../../vendor/Symfony/Component/HttpFoundation')
......
...@@ -67,14 +67,14 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase ...@@ -67,14 +67,14 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$application->handle($request); $application->handle($request);
$this->assertEquals($request, $application->getRequest()); $this->assertEquals($request, $application['request']);
} }
public function testgetRoutesWithNoRoutes() public function testgetRoutesWithNoRoutes()
{ {
$application = new Application(); $application = new Application();
$routes = $application->getRoutes(); $routes = $application['routes'];
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes); $this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes);
$this->assertEquals(0, count($routes->all())); $this->assertEquals(0, count($routes->all()));
} }
...@@ -91,7 +91,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase ...@@ -91,7 +91,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
return 'bar'; return 'bar';
}); });
$routes = $application->getRoutes(); $routes = $application['routes'];
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes); $this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $routes);
$this->assertEquals(0, count($routes->all())); $this->assertEquals(0, count($routes->all()));
$application->flush(); $application->flush();
......
...@@ -35,7 +35,7 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase ...@@ -35,7 +35,7 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
->setRouteName('foo_abc'); ->setRouteName('foo_abc');
$application->flush(); $application->flush();
$routes = $application->getRoutes(); $routes = $application['routes'];
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('homepage')); $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('homepage'));
$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('foo_abc')); $this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('foo_abc'));
} }
......
...@@ -139,10 +139,10 @@ class RouterTest extends \PHPUnit_Framework_TestCase ...@@ -139,10 +139,10 @@ class RouterTest extends \PHPUnit_Framework_TestCase
public function testRequestShouldBeStoredRegardlessOfRouting() { public function testRequestShouldBeStoredRegardlessOfRouting() {
$application = new Application(); $application = new Application();
$application->get('/foo', function() use ($application) { $application->get('/foo', function() use ($application) {
return new Response($application->getRequest()->getRequestUri()); return new Response($application['request']->getRequestUri());
}); });
$application->error(function($e) use ($application) { $application->error(function($e) use ($application) {
return new Response($application->getRequest()->getRequestUri()); return new Response($application['request']->getRequestUri());
}); });
foreach(array('/foo', '/bar') as $path) { foreach(array('/foo', '/bar') as $path) {
$request = Request::create($path); $request = Request::create($path);
......
Subproject commit 0f20b9db3f19898a39fb0e751cd6ec1274696da8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment