Skip to content

Commit

Permalink
Wip on fixing no-layout issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierstoval committed May 25, 2020
1 parent 10d3f53 commit 703601b
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 9 deletions.
37 changes: 32 additions & 5 deletions EventListener/LayoutsListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

namespace Orbitale\Bundle\CmsBundle\EventListener;

use Orbitale\Bundle\CmsBundle\Controller\CategoryController;
use Orbitale\Bundle\CmsBundle\Controller\PageController;
use Orbitale\Bundle\CmsBundle\Controller\PostsController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
Expand Down Expand Up @@ -82,21 +85,45 @@ public function setRequestLayout(RequestEvent $event): void
$layouts = $this->layouts;
do {
$finalLayout = array_shift($layouts);
if (!$finalLayout) {
continue;
}
if ($finalLayout['host'] || $finalLayout['pattern']) {
$finalLayout = null;
}
} while (null === $finalLayout && count($layouts));
}

if (null === $finalLayout || !$this->twig->getLoader()->exists($finalLayout['resource'])) {
$source = new Source('', $finalLayout['resource']);
if (null === $finalLayout) {
// Means that there is no fall-back to "default layout".

$controller = $request->attributes->get('_controller');

if (
!is_a($controller, PageController::class, true)
&& !is_a($controller, CategoryController::class, true)
&& !is_a($controller, PostsController::class, true)
) {
// Don't do anything if there's no layout and the controller isn't supposed to use it.
// If the user still wants to use a layout "outside" the built-in controllers,
// they will have to add a layout config for it anyway.
return;
}

throw new \RuntimeException(sprintf(
'Unable to find layout for url "%s://%s%s". Did you forget to add a layout configuration for this path?',
$request->getScheme(), $host, $path
));
}

throw new LoaderError(sprintf(
if (!$this->twig->getLoader()->exists($finalLayout['resource'])) {
throw new \RuntimeException(sprintf(
'Unable to find template %s for layout %s. The "layout" parameter must be a valid twig view to be used as a layout.',
$finalLayout['resource'], $finalLayout['name']
), 0, $source);
$finalLayout['resource'] ?? '', $finalLayout['name'] ?? ''
));
}


$event->getRequest()->attributes->set('_orbitale_cms_layout', $finalLayout);
}
}
68 changes: 66 additions & 2 deletions Tests/EventListener/LayoutsListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@
namespace Orbitale\Bundle\CmsBundle\Tests\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Orbitale\Bundle\CmsBundle\Controller\CategoryController;
use Orbitale\Bundle\CmsBundle\Controller\PageController;
use Orbitale\Bundle\CmsBundle\Controller\PostsController;
use Orbitale\Bundle\CmsBundle\EventListener\LayoutsListener;
use Orbitale\Bundle\CmsBundle\Tests\AbstractTestCase;
use Orbitale\Bundle\CmsBundle\Tests\Fixtures\TestBundle\Entity\Page;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Twig\Environment;
use Twig\Error\LoaderError;

Expand Down Expand Up @@ -44,11 +50,64 @@ public function testHostLayout(): void

public function testLayoutWrong(): void
{
$this->expectException(LoaderError::class);
$this->expectExceptionMessage('Unable to find template this_layout_does_not_exist.html.twig for layout front. The "layout" parameter must be a valid twig view to be used as a layout in "this_layout_does_not_exist.html.twig".');
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unable to find template this_layout_does_not_exist.html.twig for layout front. The "layout" parameter must be a valid twig view to be used as a layout.');
static::createClient(['environment' => 'layout_wrong'])->request('GET', '/page/');
}

public function testNoLayoutsDoesNotSetRequestAttribute()
{
$kernel = static::bootKernel();
$request = Request::create('/');
$listener = new LayoutsListener([], $this->getTwig());
$listener->setRequestLayout(new RequestEvent($kernel, $request, $kernel::MASTER_REQUEST));
static::assertFalse($request->attributes->has('_orbitale_cms_layout'));
}

public function testNoMatchingLayoutDoesNotSetRequestAttribute()
{
$kernel = static::bootKernel();

$listener = new LayoutsListener([
[
'pattern' => '/noop',
'host' => '',
'resource' => '.',
],
], $this->getTwig());
$request = Request::create('/');
$listener->setRequestLayout(new RequestEvent($kernel, $request, $kernel::MASTER_REQUEST));

static::assertFalse($request->attributes->has('_orbitale_cms_layout'));
}

/** @dataProvider provideBundleControllerClasses */
public function testNoMatchingLayoutWithBundleControllerThrowsException(string $controller)
{
$kernel = static::bootKernel();

$listener = new LayoutsListener([
[
'pattern' => '/noop',
'host' => '',
'resource' => '.',
],
], $this->getTwig());
$request = Request::create('/no-way');
$request->attributes->set('_controller', $controller);

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unable to find layout for url "http://localhost/no-way". Did you forget to add a layout configuration for this path?');
$listener->setRequestLayout(new RequestEvent($kernel, $request, $kernel::MASTER_REQUEST));
}

public function provideBundleControllerClasses(): \Generator
{
yield [PageController::class];
yield [CategoryController::class];
yield [PostsController::class];
}

/**
* {@inheritdoc}
*/
Expand All @@ -71,4 +130,9 @@ protected static function createClient(array $options = [], array $server = [])

return $client;
}

private function getTwig(): Environment
{
return $this->createMock(Environment::class);
}
}
4 changes: 2 additions & 2 deletions Tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@

$application = new Application($kernel);
$application->setAutoExit(false);
$application->run(new ArrayInput(['command' => 'doctrine:database:create']));
$application->run(new ArrayInput(['command' => 'doctrine:schema:create']));
$application->run(new ArrayInput(['command' => 'doctrine:database:create']), new NullOutput());
$application->run(new ArrayInput(['command' => 'doctrine:schema:create']), new NullOutput());

$kernel->shutdown();
})();

0 comments on commit 703601b

Please sign in to comment.