use Douche\Interactor\AuctionViewResponse; use Douche\Interactor\BidRequest; use Douche\Exception\Exception as DoucheException; use Mustache\Silex\Provider\MustacheServiceProvider; use Silex\Application; use Silex\Provider\DoctrineServiceProvider; use Silex\Provider\MonologServiceProvider; use Silex\Provider\ServiceControllerServiceProvider; use Silex\Provider\SessionServiceProvider; use Silex\ExceptionListenerWrapper; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; use Money\Money; use Money\Currency; $app = new Application(); $app->register(new MonologServiceProvider()); $app->register(new DoctrineServiceProvider()); $app->register(new MustacheServiceProvider(), [ 'mustache.options' => [ 'helpers' => [ 'format_money' => function ($money) { return $money->getCurrency().' '.($money->getAmount() / 100); }, 'format_date' => function (\DateTime $date) { return $date->format("Y-m-d H:i:s"); }, ], ], ]); $app->register(new ServiceControllerServiceProvider()); $app->register(new SessionServiceProvider()); $app->register(new ServiceProvider()); $app->get('/', 'interactor.auction_list') ->value('controller', 'auction_list'); $app->get('/auction/{id}', 'interactor.auction_view') ->value('controller', 'auction_view') ->convert('request', function ($_, Request $request) { return new AuctionViewRequest($request->attributes->get('id')); }); $app->post('/auction/{id}/bids', 'interactor.bid') ->before(function (Request $request, Application $app) { if (!$request->getSession()->has('current_user')) { return $app->abort(401, 'Authenitcation Required'); } }) ->value('controller', 'bid') ->value('success_handler', function ($view, $request) { return new RedirectResponse("/auction/" . $request->attributes->get('id')); }) ->value('error_handlers', [ "Douche\Exception\BidTooLowException" => function ($e, $code, $request) { $request->getSession()->getFlashBag()->set('errors', [ 'The provided bid was too low.', ]); return new RedirectResponse("/auction/" . $request->attributes->get('id')); }, ]) ->convert('request', function ($_, Request $request) { return new BidRequest( $request->attributes->get('id'), $request->getSession()->get('current_user')->id, new Money((int) $request->request->get('amount') * 100, new Currency($request->request->get('currency'))) ); }); $app->post('/login', 'interactor.user_login') ->value('controller', 'login') ->value('success_handler', function ($view, $request) { $request->getSession()->set('current_user', $view->user); return new RedirectResponse("/"); }) ->value('error_handlers', [ "Douche\Exception\UserNotFoundException" => function ($e) { return [ 'errors' => ['Incorrect email provided.'], 'email' => $e->email, ]; }, "Douche\Exception\IncorrectPasswordException" => function ($e) { return [ 'errors' => ['Invalid credentials provided.'], 'email' => $e->email, ]; }, ]) ->convert('request', function ($_, Request $request) { return new UserLoginRequest($request->request->all()); }); $app->get('/login', function(Request $request, Application $app) { $view = [ 'errors' => [], ]; return $app['mustache']->render('login.html.mustache', $view); }); $app->get('/logout', function(Request $request, Application $app) { $request->getSession()->start(); $request->getSession()->invalidate(); return $app->redirect("/"); }); $app['resolver'] = $app->share($app->extend('resolver', function ($resolver, $app) { $resolver = new ControllerResolver($resolver, $app); return $resolver; })); // TODO change to ->error once fabpot/silex#705 is merged $app['dispatcher'] = $app->share($app->extend('dispatcher', function ($dispatcher, $app) { $dispatcher->addListener(KernelEvents::EXCEPTION, new ExceptionListenerWrapper($app, function (DoucheException $e, $code) use ($app) { $app['request']->attributes->set('failed', true); $errorHandlers = $app['request']->attributes->get('error_handlers', []); foreach ($errorHandlers as $type => $handler) { if ($e instanceof $type) { return $handler($e, $code, $app['request']); } } }), -8); return $dispatcher; })); // TODO change to ->on once fabpot/silex#705 is merged $app['dispatcher'] = $app->share($app->extend('dispatcher', function ($dispatcher, $app) { $dispatcher->addListener(KernelEvents::VIEW, function ($event) use ($app) { $view = $event->getControllerResult(); if (is_null($view) || is_string($view)) { return; } $request = $event->getRequest(); if (!$request->attributes->get('failed') && $request->attributes->has('success_handler')) { $handler = $request->attributes->get('success_handler'); $view = $handler($view, $request); if ($view instanceof Response) { $event->setResponse($view); return; } } $controller = $request->attributes->get('controller'); $template = "$controller.html"; $view = (object) $view; $view->current_user = $request->getSession()->get('current_user'); $view->form_errors = $request->getSession()->getFlashBag()->get('errors'); $body = $app['mustache']->render($template, $view); $response = new Response($body); $event->setResponse($response); }); return $dispatcher; })); // TODO change to ->after once fabpot/silex#705 is merged $app['dispatcher'] = $app->share($app->extend('dispatcher', function ($dispatcher, $app) { $dispatcher->addListener(KernelEvents::RESPONSE, function () use ($app) { $app['douche.auction_repo']->save(); }); return $dispatcher; })); return $app; service providers routes listeners