Skip to content

Commit

Permalink
Add validator verifying if the template exists
Browse files Browse the repository at this point in the history
  • Loading branch information
marekkalnik committed Dec 3, 2012
1 parent d6f0822 commit 04bb36d
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions DependencyInjection/TheodoRogerCmsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ public function load(array $configs, ContainerBuilder $container)

// Load the services.yml file
$loader->load('services.xml');
$loader->load('validator.xml');
}
}
3 changes: 3 additions & 0 deletions Entity/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

use Theodo\RogerCmsBundle\Repository\PageRepository;
use Theodo\RogerCmsBundle\Validator\Constraints\ExistingLayout;
use Theodo\RogerCmsBundle\Validator\TwigSyntax;

/**
Expand Down Expand Up @@ -388,6 +389,7 @@ public static function loadValidatorMetadata(ClassMetadata $metadata)
$metadata->addConstraint(new UniqueEntity(array('fields' => array('slug'))));

// Content validator: not null
$metadata->addPropertyConstraint('content', new ExistingLayout());
$metadata->addPropertyConstraint('content', new NotBlank());
$metadata->addPropertyConstraint('content', new TwigSyntax());

Expand All @@ -396,6 +398,7 @@ public static function loadValidatorMetadata(ClassMetadata $metadata)
$metadata->addPropertyConstraint('status', new Choice(array(
'choices' => PageRepository::getAvailableStatus())
));

}

/**
Expand Down
2 changes: 2 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<parameter key="gedmo.timestampable.listener.class">Gedmo\Timestampable\TimestampableListener</parameter>
<parameter key="doctrine.orm.validator.unique.class">Theodo\RogerCmsBundle\Validator\Constraints\RogerUniqueEntityValidator</parameter>
<parameter key="roger.twig.extension.helper.class">Theodo\RogerCmsBundle\Extensions\Twig\Extension\RogerHelperExtension</parameter>
<parameter key="theodo_roger_cms.extractor.layout.class">Theodo\RogerCmsBundle\Form\DataTransformer\LayoutExtractor</parameter>
</parameters>

<services>
Expand Down Expand Up @@ -71,5 +72,6 @@
<service id="form.type.roger_cms_page_layout" class="Theodo\RogerCmsBundle\Form\Page\LayoutType">
<tag name="form.type" alias="roger_cms_page_layout" />
</service>
<service id="theodo_roger_cms.extractor.layout" class="%theodo_roger_cms.extractor.layout.class%" />
</services>
</container>
17 changes: 17 additions & 0 deletions Resources/config/validator.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<container
xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="theodo_roger_cms.validator.existing_layout.class">Theodo\RogerCmsBundle\Validator\Constraints\ExistingLayoutValidator</parameter>
</parameters>

<services>
<service id="theodo_roger_cms.validator.existing_layout" class="%theodo_roger_cms.validator.existing_layout.class%">
<argument type="service" id="roger.twig.loader_chain" />
<argument type="service" id="theodo_roger_cms.extractor.layout" />
<tag name="validator.constraint_validator" alias="theodo_roger_cms.validator.existing_layout" />
</service>
</services>
</container>
20 changes: 20 additions & 0 deletions Tests/Validator/Constraints/ExistingLayoutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Theodo\RogerCmsBundle\Tests\Validator\Constraints;

use Theodo\RogerCmsBundle\Validator\Constraints\ExistingLayout;

class ExistingLayoutTest extends \PHPUnit_Framework_TestCase
{
public function testIsValidationConstraint()
{
$constraint = new ExistingLayout();
$this->assertInstanceOf('\Symfony\Component\Validator\Constraint', $constraint);
}

public function testHasNotStandardValidator()
{
$constraint = new ExistingLayout();
$this->assertNotEquals(get_class($constraint) . 'Validator', $constraint->validatedBy());
}
}
76 changes: 76 additions & 0 deletions Tests/Validator/Constraints/ExistingLayoutValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Theodo\RogerCmsBundle\Tests\Validator\Constraints;

use Theodo\RogerCmsBundle\Validator\Constraints\ExistingLayoutValidator;
use Phake;

/**
* @author Marek Kalnik <[email protected]>
*/
class ExistingLayoutValidatorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Twig_LoaderInterface
*/
public $loader;

/**
* @var Theodo\RogerCmsBundle\Validator\Constraints\ExistingLayoutValidator
*/
public $validator;

/**
* @var Theodo\RogerCmsBundle\Form\DataTransformer\LayoutExtractor;
*/
public $extractor;

public function setUp()
{
$this->loader = Phake::mock('Twig_LoaderInterface');
$this->extractor = Phake::mock('Theodo\RogerCmsBundle\Form\DataTransformer\LayoutExtractor');
$this->validator = new ExistingLayoutValidator($this->loader, $this->extractor);
}

public function testIsConstraintValidator()
{
$this->assertInstanceOf('Symfony\Component\Validator\ConstraintValidatorInterface', $this->validator);
}

public function testValidatesIfLayoutExists()
{
Phake::when($this->extractor)->getLayout(Phake::anyParameters())
->thenReturn('blabla');
Phake::when($this->loader)->getSource(Phake::anyParameters())
->thenReturn('blabla');

$context = Phake::mock('Symfony\Component\Validator\ExecutionContext');
$this->validator->initialize($context);

$this->validator->validate('blabla', Phake::mock('Symfony\Component\Validator\Constraint'));

Phake::verify($this->extractor, Phake::times(1))
->getLayout(Phake::anyParameters());
Phake::verify($this->loader, Phake::times(1))
->getSource(Phake::anyParameters());
Phake::verify($context, Phake::never())
->addViolation(Phake::anyParameters());
}

public function testFailsIfLayoutDoesNotExist()
{
Phake::when($this->extractor)->getLayout(Phake::anyParameters())
->thenReturn('blabla');
Phake::when($this->loader)->getSource(Phake::anyParameters())
->thenThrow(new \Twig_Error_Loader('Template not found'));

$context = Phake::mock('Symfony\Component\Validator\ExecutionContext');
$this->validator->initialize($context);
$this->validator->validate('blabla', Phake::mock('Symfony\Component\Validator\Constraint'));

Phake::verify($this->loader, Phake::times(1))
->getSource(Phake::anyParameters());
Phake::verify($context, Phake::times(1))
->addViolation(Phake::anyParameters());
}
}
18 changes: 18 additions & 0 deletions Validator/Constraints/ExistingLayout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Theodo\RogerCmsBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
* @author Marek Kalnik <[email protected]>
*/
class ExistingLayout extends Constraint
{
public $validationService = 'theodo_roger_cms.validator.existing_layout';

public function validatedBy()
{
return $this->validationService;
}
}
48 changes: 48 additions & 0 deletions Validator/Constraints/ExistingLayoutValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Theodo\RogerCmsBundle\Validator\Constraints;

use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Constraint;

use Theodo\RogerCmsBundle\Extractor\LayoutExtractorInterface;

/**
* @todo This validator should we able to work on content as it is used on the object rathern
* that the form. Maybe the Content property should be replaced by an object, to do it in
* a more elegant way?
*
* @author Marek Kalnik <[email protected]>
*/
class ExistingLayoutValidator extends ConstraintValidator
{
private $loader;

private $extractor;

/**
* @param \Twig_LoaderInterface $load The loader used to find the template
* @param LayoutExtractor $extractor Used to extract the template name form template
*/
public function __construct(\Twig_LoaderInterface $loader, LayoutExtractorInterface $extractor)
{
$this->loader = $loader;
$this->extractor = $extractor;
}

/**
* {@inheritdoc}
*/
public function validate($content, Constraint $constraint)
{
$layout = $this->extractor->getLayout($content);

if ($layout) {
try {
$this->loader->getSource($layout);
} catch (\Twig_Error_Loader $e) {
$this->context->addViolation('Template not found.');
}
}
}
}

0 comments on commit 04bb36d

Please sign in to comment.