diff --git a/.gitignore b/.gitignore index 73124a0..5414c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ composer.lock phpunit.xml -Tests/autoload.php - -vendor/* +vendor/ diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..d3e500e --- /dev/null +++ b/.php_cs @@ -0,0 +1,20 @@ +level(Symfony\CS\FixerInterface::SYMFONY_LEVEL) + ->fixers([ + 'ordered_use', + 'phpdoc_order', + 'short_array_syntax', + ]); + +if (null === $input->getArgument('path')) { + $config + ->finder( + Symfony\CS\Finder\DefaultFinder::create() + ->exclude('Resources') + ->in(__DIR__) + ); +} + +return $config; diff --git a/.travis.yml b/.travis.yml index 7f08b35..b09f6ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,8 @@ cache: matrix: include: - - php: 5.4 + - php: 5.5 + env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest"' - php: 5.5 - php: 5.6 - php: 7.0 @@ -23,10 +24,11 @@ before_install: - 'if [[ -n "$GH_TOKEN" ]]; then composer config github-oauth.github.com ${GH_TOKEN}; fi;' - 'if [[ -n "$GH_TOKEN" ]]; then composer config preferred-install dist; fi;' -install: composer install --no-interaction --no-progress +install: 'composer update ${COMPOSER_FLAGS} --no-progress' script: - - phpunit -v + - ./vendor/bin/php-cs-fixer fix --diff --dry-run + - ./vendor/bin/phpunit -v - 'if [[ $TRAVIS_PULL_REQUEST == "false" && $TRAVIS_BRANCH == "master" && $TRAVIS_PHP_VERSION == "5.6" ]]; then sh generate-api.sh; fi;' notifications: diff --git a/Admin/FeatureAdmin.php b/Admin/FeatureAdmin.php index d6b09df..5fdba83 100644 --- a/Admin/FeatureAdmin.php +++ b/Admin/FeatureAdmin.php @@ -2,25 +2,30 @@ namespace Ae\FeatureBundle\Admin; +use Ae\FeatureBundle\Entity\FeatureManager; use Sonata\AdminBundle\Admin\Admin; -use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; +use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Form\FormMapper; -use Ae\FeatureBundle\Entity\FeatureManager; /** * @author Carlo Forghieri */ class FeatureAdmin extends Admin { + /** + * {@inheritdoc} + */ protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper - ->add('name') - ->add('enabled') - ; + ->add('name') + ->add('enabled'); } + /** + * {@inheritdoc} + */ protected function configureListFields(ListMapper $listMapper) { $listMapper @@ -28,49 +33,57 @@ protected function configureListFields(ListMapper $listMapper) ->add('name') ->add('role') ->add('enabled') - ->add('_action', 'actions', array( - 'actions' => array( - 'edit' => array(), - 'delete' => array(), - ), - )) - ; + ->add('_action', 'actions', [ + 'actions' => [ + 'edit' => [], + 'delete' => [], + ], + ]); } + /** + * {@inheritdoc} + */ protected function configureFormFields(FormMapper $formMapper) { $roles = $this->getRoles(); $formMapper - ->add('name', 'text', array( + ->add('name', 'text', [ 'required' => true, - )) - ->add('enabled', 'checkbox', array( + ]) + ->add('enabled', 'checkbox', [ 'required' => false, - )) - ->add('role', 'choice', array( - 'choices' => array_combine($roles, $roles), + ]) + ->add('role', 'choice', [ + 'choices' => array_combine($roles, $roles), 'multiple' => false, 'required' => false, - )) - ; + ]); + if (!$this->getSubject()->getParent()) { - $formMapper - ->add('children', 'sonata_type_collection', array( - 'required' => false, - ), array( - 'edit' => 'inline', - 'inline' => 'table', - )) - ; + $formMapper->add( + 'children', + 'sonata_type_collection', + [ + 'required' => false, + ], + [ + 'edit' => 'inline', + 'inline' => 'table', + ] + ); } } protected function getRoles() { - $roleHierarchy = $this->getConfigurationPool()->getContainer()->getParameter('security.role_hierarchy.roles'); + $roleHierarchy = $this + ->getConfigurationPool() + ->getContainer() + ->getParameter('security.role_hierarchy.roles'); - $roles = array_keys($roleHierarchy); + $roles = array_keys($roleHierarchy); $roles[] = 'ROLE_PREVIOUS_ADMIN'; return $roles; @@ -80,7 +93,8 @@ public function createQuery($context = 'list') { $query = parent::createQuery($context); if ($context === 'list') { - $query->andWhere(current($query->getDQLPart('from'))->getAlias().'.parent IS NULL'); + $alias = current($query->getDQLPart('from'))->getAlias(); + $query->andWhere($alias.'.parent IS NULL'); } return $query; @@ -88,7 +102,11 @@ public function createQuery($context = 'list') public function postUpdate($object) { - $cache = $this->modelManager->getEntityManager($object)->getConfiguration()->getResultCacheImpl(); + $cache = $this->modelManager + ->getEntityManager($object) + ->getConfiguration() + ->getResultCacheImpl(); + foreach ($object->getChildren() as $child) { $cache->delete($this->getObjectCacheKey($child)); } @@ -96,6 +114,9 @@ public function postUpdate($object) protected function getObjectCacheKey($object) { - return FeatureManager::generateCacheKey($object->getParent()->getName(), $object->getName()); + return FeatureManager::generateCacheKey( + $object->getParent()->getName(), + $object->getName() + ); } } diff --git a/Command/LoadFeatureCommand.php b/Command/LoadFeatureCommand.php index b68d61c..a1aeddf 100644 --- a/Command/LoadFeatureCommand.php +++ b/Command/LoadFeatureCommand.php @@ -2,75 +2,112 @@ namespace Ae\FeatureBundle\Command; +use Ae\FeatureBundle\Twig\Node\FeatureNode; +use Exception; +use InvalidArgumentException; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; -use Ae\FeatureBundle\Twig\Node\FeatureNode; +use Twig_Node; /** * @author Carlo Forghieri */ class LoadFeatureCommand extends ContainerAwareCommand { + /** + * {@inheritdoc} + */ protected function configure() { $this ->setName('features:load') ->setDescription('Persist new features found in templates') - ->setDefinition(array( - new InputArgument('bundle', InputArgument::REQUIRED, 'The bundle where to load the features'), - new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Do not persist new features'), - )); + ->addArgument( + 'bundle', + InputArgument::REQUIRED, + 'The bundle where to load the features' + ) + ->addOption( + 'dry-run', + null, + InputOption::VALUE_NONE, + 'Do not persist new features' + ); } + /** + * {@inheritdoc} + */ public function execute(InputInterface $input, OutputInterface $output) { - $twig = $this->getContainer()->get('twig'); - $bundle = $this->getApplication()->getKernel()->getBundle($input->getArgument('bundle')); + $twig = $this->getContainer()->get('twig'); + $bundle = $this + ->getApplication() + ->getKernel() + ->getBundle($input->getArgument('bundle')); + if (!$bundle) { - new \InvalidArgumentException("Bundle `$bundle` does not exists"); + throw new InvalidArgumentException("Bundle `$bundle` does not exists"); } - $found = array(); + $found = []; $dir = $bundle->getPath().'/Resources/views/'; if (!is_dir($dir)) { - throw \Exception("'Directory `$dir` does not exists."); + throw new Exception("'Directory `$dir` does not exists."); } $finder = new Finder(); - $files = $finder->files()->name('*.html.twig')->in($dir); + $files = $finder->files()->name('*.html.twig')->in($dir); foreach ($files as $file) { - $tree = $twig->parse($twig->tokenize(file_get_contents($file->getPathname()))); + $tree = $twig->parse( + $twig->tokenize(file_get_contents($file->getPathname())) + ); $tags = $this->findFeatureNodes($tree); if ($tags) { $found = array_merge($found, $tags); foreach ($tags as $tag) { - $output->writeln(sprintf('Found %s.%s in %s', $tag['parent'], $tag['name'], $file->getFilename())); + $output->writeln(sprintf( + 'Found %s.%s in %s', + $tag['parent'], + $tag['name'], + $file->getFilename() + )); } } } + if ($input->getOption('dry-run')) { return; } + $manager = $this->getContainer()->get('cw_feature.manager'); foreach ($found as $tag) { $manager->findOrCreate($tag['name'], $tag['parent']); } } - protected function findFeatureNodes(\Twig_Node $node) + protected function findFeatureNodes(Twig_Node $node) { - $found = array(); - $stack = array($node); + $found = []; + $stack = [$node]; while ($stack) { $node = array_pop($stack); if ($node instanceof FeatureNode) { - $arguments = $node->getNode('tests')->getNode(0)->getNode('arguments')->getKeyValuePairs(); - $tag = array(); + $arguments = $node + ->getNode('tests') + ->getNode(0) + ->getNode('arguments') + ->getKeyValuePairs(); + + $tag = []; foreach ($arguments as $argument) { - $tag[$argument['key']->getAttribute('value')] = $argument['value']->getAttribute('value'); + $keyAttr = $argument['key']->getAttribute('value'); + $valueAttr = $argument['value']->getAttribute('value'); + + $tag[$keyAttr] = $valueAttr; } $key = md5(serialize($tag)); $found[$key] = $tag; diff --git a/DependencyInjection/AeFeatureExtension.php b/DependencyInjection/AeFeatureExtension.php index 0538949..4e63c4e 100644 --- a/DependencyInjection/AeFeatureExtension.php +++ b/DependencyInjection/AeFeatureExtension.php @@ -15,7 +15,7 @@ class AeFeatureExtension extends Extension { /** - * {@inheritDoc} + * {@inheritdoc} */ public function load(array $configs, ContainerBuilder $container) { diff --git a/Entity/FeatureManager.php b/Entity/FeatureManager.php index e36d503..ca87b56 100644 --- a/Entity/FeatureManager.php +++ b/Entity/FeatureManager.php @@ -11,7 +11,7 @@ class FeatureManager { /** - * @avr \Doctrine\ORM\EntityManager + * @var EntityManager */ protected $em; @@ -21,7 +21,7 @@ public static function generateCacheKey($parentName, $name) } /** - * @param \Doctrine\ORM\EntityManager $em + * @param EntityManager $em */ public function __construct(EntityManager $em) { @@ -36,11 +36,12 @@ public function __construct(EntityManager $em) */ public function find($name, $parent) { - return $this->em->createQuery('SELECT f,p FROM AeFeatureBundle:Feature f JOIN f.parent p WHERE f.name = :name AND p.name = :parent') - ->setParameters(array( - 'name' => $name, + return $this->em + ->createQuery('SELECT f,p FROM AeFeatureBundle:Feature f JOIN f.parent p WHERE f.name = :name AND p.name = :parent') + ->setParameters([ + 'name' => $name, 'parent' => $parent, - )) + ]) ->useResultCache(true, 3600 * 24, self::generateCacheKey($parent, $name)) ->getSingleResult(); } @@ -48,11 +49,12 @@ public function find($name, $parent) /** * @param string $name Feature name * - * @return Ae\FeatureBundle\Entity\Feature + * @return Feature */ public function findParent($name) { - return $this->em->createQuery('SELECT f FROM AeFeatureBundle:Feature f WHERE f.name = :name AND f.parent IS NULL') + return $this->em + ->createQuery('SELECT f FROM AeFeatureBundle:Feature f WHERE f.name = :name AND f.parent IS NULL') ->setParameter('name', $name) ->getSingleResult(); } @@ -99,8 +101,8 @@ public function create($name, Feature $parent = null) } /** - * @param \Ae\FeatureBundle\Entity\Feature $feature - * @param bool $andFlush + * @param Feature $feature + * @param bool $andFlush */ public function update(Feature $feature, $andFlush = true) { diff --git a/Security/FeatureSecurity.php b/Security/FeatureSecurity.php index a57eb6d..fbdafe0 100644 --- a/Security/FeatureSecurity.php +++ b/Security/FeatureSecurity.php @@ -2,8 +2,8 @@ namespace Ae\FeatureBundle\Security; -use Symfony\Component\Security\Core\SecurityContextInterface; use Ae\FeatureBundle\Entity\Feature; +use Symfony\Component\Security\Core\SecurityContextInterface; /** * Controls access to a Feature. @@ -12,10 +12,13 @@ */ class FeatureSecurity { + /** + * @param SecurityContextInterface|null + */ protected $context; /** - * @param \Symfony\Component\Security\Core\SecurityContextInterface $context + * @param SecurityContextInterface $context */ public function __construct(SecurityContextInterface $context = null) { @@ -23,7 +26,7 @@ public function __construct(SecurityContextInterface $context = null) } /** - * @param \Ae\FeatureBundle\Entity\Feature $feature + * @param Feature $feature * * @return bool */ diff --git a/Service/Feature.php b/Service/Feature.php index 5798bf9..622c6dc 100644 --- a/Service/Feature.php +++ b/Service/Feature.php @@ -4,21 +4,31 @@ use Ae\FeatureBundle\Entity\FeatureManager; use Ae\FeatureBundle\Security\FeatureSecurity; +use Exception; /** * @author Carlo Forghieri */ class Feature { - protected $security; + /** + * @var FeatureManager + */ protected $manager; /** - * @param \Ae\FeatureBundle\Entity\FeatureManager $manager - * @param \Ae\FeatureBundle\Security\FeatureSecurity $security + * @var FeatureSecurity */ - public function __construct(FeatureManager $manager, FeatureSecurity $security) - { + protected $security; + + /** + * @param FeatureManager $manager + * @param FeatureSecurity $security + */ + public function __construct( + FeatureManager $manager, + FeatureSecurity $security + ) { $this->manager = $manager; $this->security = $security; } @@ -34,8 +44,10 @@ public function __construct(FeatureManager $manager, FeatureSecurity $security) public function isGranted($name, $parent) { try { - return $this->security->isGranted($this->manager->find($name, $parent)); - } catch (\Exception $e) { + return $this->security->isGranted( + $this->manager->find($name, $parent) + ); + } catch (Exception $exception) { return false; } } diff --git a/Tests/DependencyInjection/AeFeatureExtensionTest.php b/Tests/DependencyInjection/AeFeatureExtensionTest.php index 3614e47..785cb32 100644 --- a/Tests/DependencyInjection/AeFeatureExtensionTest.php +++ b/Tests/DependencyInjection/AeFeatureExtensionTest.php @@ -3,10 +3,15 @@ namespace Ae\FeatureBundle\Tests\DependencyInjection; use Ae\FeatureBundle\DependencyInjection\AeFeatureExtension; +use Ae\FeatureBundle\Entity\FeatureManager; +use Ae\FeatureBundle\Security\FeatureSecurity; +use Ae\FeatureBundle\Service\Feature; +use Ae\FeatureBundle\Twig\Extension\FeatureExtension; use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase; /** - * @covers \Ae\FeatureBundle\DependencyInjection\AeFeatureExtension + * @author Emanuele Minotto + * @covers Ae\FeatureBundle\DependencyInjection\AeFeatureExtension */ class AeFeatureExtensionTest extends AbstractExtensionTestCase { @@ -29,13 +34,18 @@ protected function getContainerExtensions() * @dataProvider parametersProvider * @group legacy */ - public function testLegacyParameters($parameterName, $expectedParameterValue) - { + public function testLegacyParameters( + $parameterName, + $expectedParameterValue + ) { $this->load(); $this->compile(); - $parameterName = 'cw' . substr($parameterName, 2); - $this->assertContainerBuilderHasParameter($parameterName, $expectedParameterValue); + $parameterName = 'cw'.substr($parameterName, 2); + $this->assertContainerBuilderHasParameter( + $parameterName, + $expectedParameterValue + ); } /** @@ -51,7 +61,10 @@ public function testParameters($parameterName, $expectedParameterValue) $this->load(); $this->compile(); - $this->assertContainerBuilderHasParameter($parameterName, $expectedParameterValue); + $this->assertContainerBuilderHasParameter( + $parameterName, + $expectedParameterValue + ); } /** @@ -60,14 +73,16 @@ public function testParameters($parameterName, $expectedParameterValue) public function parametersProvider() { return [ - ['ae_feature.manager.class', 'Ae\FeatureBundle\Entity\FeatureManager'], - ['ae_feature.security.class', 'Ae\FeatureBundle\Security\FeatureSecurity'], - ['ae_feature.feature.class', 'Ae\FeatureBundle\Service\Feature'], - ['ae_feature.twig.extension.feature.class', 'Ae\FeatureBundle\Twig\Extension\FeatureExtension'], + ['ae_feature.manager.class', FeatureManager::class], + ['ae_feature.security.class', FeatureSecurity::class], + ['ae_feature.feature.class', Feature::class], + [ + 'ae_feature.twig.extension.feature.class', + FeatureExtension::class, + ], ]; } - /** * Test services "alias" to migrate from CreativeWeb to AdEspresso. * @@ -82,9 +97,12 @@ public function testLegacyServices($serviceId, $expectedClass) $this->load(); $this->compile(); - $oldServiceId = 'cw' . substr($serviceId, 2); + $oldServiceId = 'cw'.substr($serviceId, 2); $this->assertContainerBuilderHasService($serviceId, $expectedClass); - $this->assertContainerBuilderHasServiceDefinitionWithParent($oldServiceId, $serviceId); + $this->assertContainerBuilderHasServiceDefinitionWithParent( + $oldServiceId, + $serviceId + ); } /** @@ -109,10 +127,10 @@ public function testServices($serviceId, $expectedClass) public function servicesProvider() { return [ - ['ae_feature.manager', 'Ae\FeatureBundle\Entity\FeatureManager'], - ['ae_feature.security', 'Ae\FeatureBundle\Security\FeatureSecurity'], - ['ae_feature.feature', 'Ae\FeatureBundle\Service\Feature'], - ['ae_feature.twig.extension.feature', 'Ae\FeatureBundle\Twig\Extension\FeatureExtension'], + ['ae_feature.manager', FeatureManager::class], + ['ae_feature.security', FeatureSecurity::class], + ['ae_feature.feature', Feature::class], + ['ae_feature.twig.extension.feature', FeatureExtension::class], ]; } } diff --git a/Tests/Entity/FeatureManagerTest.php b/Tests/Entity/FeatureManagerTest.php index bad509a..1de23c2 100644 --- a/Tests/Entity/FeatureManagerTest.php +++ b/Tests/Entity/FeatureManagerTest.php @@ -2,31 +2,37 @@ namespace Ae\FeatureBundle\Tests\Entity; +use Ae\FeatureBundle\Entity\Feature; use Ae\FeatureBundle\Entity\FeatureManager; +use Doctrine\ORM\EntityManager; +use PHPUnit_Framework_TestCase; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Entity\FeatureManager */ -class FeatureManagerTest extends \PHPUnit_Framework_TestCase +class FeatureManagerTest extends PHPUnit_Framework_TestCase { protected $em; protected $manager; protected function setUp() { - $this->em = $this->getMockBuilder('\Doctrine\ORM\EntityManager') + $this->em = $this + ->getMockBuilder(EntityManager::class) ->disableOriginalConstructor() ->getMock(); - $this->manager = $this->getMockBuilder('\Ae\FeatureBundle\Entity\FeatureManager') - ->setConstructorArgs(array($this->em)) - ->setMethods(array('emptyCache')) + $this->manager = $this + ->getMockBuilder(FeatureManager::class) + ->setConstructorArgs([$this->em]) + ->setMethods(['emptyCache']) ->getMock(); } public function testCreate() { - $name = 'foo'; - $parent = $this->getMock('Ae\FeatureBundle\Entity\Feature'); + $name = 'foo'; + $parent = $this->getMock(Feature::class); $feature = $this->manager->create($name, $parent); $this->assertEquals($name, $feature->getName($name)); @@ -35,15 +41,18 @@ public function testCreate() public function testUpdate() { - $feature = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $parent = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $feature->expects($this->once()) + $feature = $this->getMock(Feature::class); + $parent = $this->getMock(Feature::class); + $feature + ->expects($this->once()) ->method('getParent') ->will($this->returnValue($parent)); - $this->em->expects($this->once()) + $this->em + ->expects($this->once()) ->method('persist') ->with($feature); - $this->em->expects($this->once()) + $this->em + ->expects($this->once()) ->method('flush'); $this->manager->update($feature); } @@ -53,6 +62,9 @@ public function testGenerateCacheKey() $parentName = 'PNAME'; $name = 'NAME'; - $this->assertEquals('feature_pname_name', FeatureManager::generateCacheKey($parentName, $name)); + $this->assertEquals( + 'feature_pname_name', + FeatureManager::generateCacheKey($parentName, $name) + ); } } diff --git a/Tests/Entity/FeatureTest.php b/Tests/Entity/FeatureTest.php index 8d8092b..7f866ef 100644 --- a/Tests/Entity/FeatureTest.php +++ b/Tests/Entity/FeatureTest.php @@ -3,11 +3,14 @@ namespace Ae\FeatureBundle\Tests\Entity; use Ae\FeatureBundle\Entity\Feature; +use Doctrine\Common\Collections\Collection; +use PHPUnit_Framework_TestCase; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Entity\Feature */ -class FeatureTest extends \PHPUnit_Framework_TestCase +class FeatureTest extends PHPUnit_Framework_TestCase { protected $entity; @@ -17,26 +20,21 @@ protected function setUp() } /** - * @covers Ae\FeatureBundle\Entity\Feature::getParent - * @covers Ae\FeatureBundle\Entity\Feature::setParent + * Test parent getter & setter. */ public function testParent() { - $parent = $this->getMock('Ae\FeatureBundle\Entity\Feature'); + $parent = $this->getMock(Feature::class); $this->entity->setParent($parent); $this->assertEquals($parent, $this->entity->getParent()); } - /** - * @covers Ae\FeatureBundle\Entity\Feature::addFeature - * @covers Ae\FeatureBundle\Entity\Feature::getChildren - */ public function testChildren() { - $parent = $this->getMock('Ae\FeatureBundle\Entity\Feature'); + $parent = $this->getMock(Feature::class); $this->entity->addFeature($parent); $collection = $this->entity->getChildren(); - $this->assertInstanceOf('Doctrine\Common\Collections\Collection', $collection); + $this->assertInstanceOf(Collection::class, $collection); $this->assertEquals($parent, $collection->first()); } diff --git a/Tests/Security/FeatureSecurityTest.php b/Tests/Security/FeatureSecurityTest.php index d73b9d5..62838d6 100644 --- a/Tests/Security/FeatureSecurityTest.php +++ b/Tests/Security/FeatureSecurityTest.php @@ -2,26 +2,31 @@ namespace Ae\FeatureBundle\Tests\Security; +use Ae\FeatureBundle\Entity\Feature; use Ae\FeatureBundle\Security\FeatureSecurity; +use PHPUnit_Framework_TestCase; +use Symfony\Component\Security\Core\SecurityContextInterface; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Security\FeatureSecurity */ -class FeatureSecurityTest extends \PHPUnit_Framework_TestCase +class FeatureSecurityTest extends PHPUnit_Framework_TestCase { protected $security; protected function setUp() { - $context = $this->getMockBuilder('\Symfony\Component\Security\Core\SecurityContextInterface') + $context = $this + ->getMockBuilder(SecurityContextInterface::class) ->disableOriginalConstructor() ->getMock(); $context->expects($this->any()) ->method('isGranted') - ->will($this->returnValueMap(array( - array('ROLE_USER', null, true), - array('ROLE_ADMIN', null, false), - ))); + ->will($this->returnValueMap([ + ['ROLE_USER', null, true], + ['ROLE_ADMIN', null, false], + ])); $this->security = new FeatureSecurity($context); } @@ -33,42 +38,52 @@ public function testIsGranted($feature, $expected) $this->assertEquals($expected, $this->security->isGranted($feature)); } + /** + * @return array + */ public function getFeatures() { - $tests = array(); + $tests = []; - $f = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $f->expects($this->once()) + $feature = $this->getMock(Feature::class); + $feature + ->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(false)); - $tests[] = array($f, false); + $tests[] = [$feature, false]; - $f = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $f->expects($this->once()) + $feature = $this->getMock(Feature::class); + $feature + ->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(true)); - $tests[] = array($f, true); + $tests[] = [$feature, true]; - $f = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $f->expects($this->once()) + $feature = $this->getMock(Feature::class); + $feature + ->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(true)); - $f->expects($this->atLeastOnce()) + $feature + ->expects($this->atLeastOnce()) ->method('getRole') ->will($this->returnValue('ROLE_USER')); - $tests[] = array($f, true); + $tests[] = [$feature, true]; - $f = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $f->expects($this->once()) + $feature = $this->getMock(Feature::class); + $feature + ->expects($this->once()) ->method('isEnabled') ->will($this->returnValue(true)); - $f->expects($this->atLeastOnce()) + $feature + ->expects($this->atLeastOnce()) ->method('getRole') ->will($this->returnValue('ROLE_USER')); - $f->expects($this->atLeastOnce()) + $feature + ->expects($this->atLeastOnce()) ->method('getParentRole') ->will($this->returnValue('ROLE_ADMIN')); - $tests[] = array($f, false); + $tests[] = [$feature, false]; return $tests; } diff --git a/Tests/Service/FeatureTest.php b/Tests/Service/FeatureTest.php index 5880560..7b95256 100644 --- a/Tests/Service/FeatureTest.php +++ b/Tests/Service/FeatureTest.php @@ -2,12 +2,17 @@ namespace Ae\FeatureBundle\Tests\Service; -use Ae\FeatureBundle\Service\Feature; +use Ae\FeatureBundle\Entity\Feature; +use Ae\FeatureBundle\Entity\FeatureManager; +use Ae\FeatureBundle\Security\FeatureSecurity; +use Ae\FeatureBundle\Service\Feature as FeatureService; +use PHPUnit_Framework_TestCase; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Service\Feature */ -class FeatureTest extends \PHPUnit_Framework_TestCase +class FeatureTest extends PHPUnit_Framework_TestCase { protected $manager; protected $security; @@ -15,45 +20,51 @@ class FeatureTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->manager = $this->getMockBuilder('Ae\FeatureBundle\Entity\FeatureManager') + $this->manager = $this + ->getMockBuilder(FeatureManager::class) ->disableOriginalConstructor() ->getMock(); - $this->security = $this->getMockBuilder('Ae\FeatureBundle\Security\FeatureSecurity') + $this->security = $this + ->getMockBuilder(FeatureSecurity::class) ->disableOriginalConstructor() ->getMock(); - $this->service = new Feature($this->manager, $this->security); + $this->service = new FeatureService($this->manager, $this->security); } public function testIsGrantedTrue() { - $featureEnabled = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $this->manager->expects($this->atLeastOnce()) + $featureEnabled = $this->getMock(Feature::class); + $this->manager + ->expects($this->atLeastOnce()) ->method('find') - ->will($this->returnValueMap(array( - array('featureA', 'group', $featureEnabled), - ))); - $this->security->expects($this->atLeastOnce()) + ->will($this->returnValueMap([ + ['featureA', 'group', $featureEnabled], + ])); + $this->security + ->expects($this->atLeastOnce()) ->method('isGranted') - ->will($this->returnValueMap(array( - array($featureEnabled, true), - ))); + ->will($this->returnValueMap([ + [$featureEnabled, true], + ])); $this->assertTrue($this->service->isGranted('featureA', 'group')); } public function testIsGrantedFalse() { - $featureDisabled = $this->getMock('Ae\FeatureBundle\Entity\Feature'); - $this->manager->expects($this->atLeastOnce()) + $featureDisabled = $this->getMock(Feature::class); + $this->manager + ->expects($this->atLeastOnce()) ->method('find') - ->will($this->returnValueMap(array( - array('featureB', 'group', $featureDisabled), - ))); - $this->security->expects($this->atLeastOnce()) + ->will($this->returnValueMap([ + ['featureB', 'group', $featureDisabled], + ])); + $this->security + ->expects($this->atLeastOnce()) ->method('isGranted') - ->will($this->returnValueMap(array( - array($featureDisabled, false), - ))); + ->will($this->returnValueMap([ + [$featureDisabled, false], + ])); $this->assertFalse($this->service->isGranted('featureB', 'group')); } diff --git a/Tests/Twig/IntegrationTest.php b/Tests/Twig/IntegrationTest.php index 1cbd30a..cff3424 100644 --- a/Tests/Twig/IntegrationTest.php +++ b/Tests/Twig/IntegrationTest.php @@ -2,54 +2,37 @@ namespace Ae\FeatureBundle\Tests\Twig; +use Ae\FeatureBundle\Service\Feature; use Ae\FeatureBundle\Twig\Extension\FeatureExtension; +use Twig_Test_IntegrationTestCase; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Twig\Node\FeatureNode */ -class IntegrationTest extends \Twig_Test_IntegrationTestCase +class IntegrationTest extends Twig_Test_IntegrationTestCase { - protected static $originalErrorLevel; - - public function __construct($name = null, array $data = array(), $dataName = '') - { - self::$originalErrorLevel = error_reporting(); - error_reporting(self::$originalErrorLevel & ~E_WARNING); - - parent::__construct($name, $data, $dataName); - } - - public function tearDown() - { - parent::tearDown(); - - error_reporting(self::$originalErrorLevel); - } - public function getExtensions() { - return array( - $this->getFeatureExtension(), - ); - } - - public function getFixturesDir() - { - return dirname(__FILE__).'/Fixtures/'; - } - - protected function getFeatureExtension() - { - $service = $this->getMockBuilder('Ae\FeatureBundle\Service\Feature') + $service = $this + ->getMockBuilder(Feature::class) ->disableOriginalConstructor() ->getMock(); - $service->expects($this->atLeastOnce()) + $service + ->expects($this->atLeastOnce()) ->method('isGranted') - ->will($this->returnValueMap(array( - array('featureA', 'group', true), - array('featureB', 'group', false), - ))); + ->will($this->returnValueMap([ + ['featureA', 'group', true], + ['featureB', 'group', false], + ])); + + return [ + new FeatureExtension($service), + ]; + } - return new FeatureExtension($service); + public function getFixturesDir() + { + return __DIR__.'/Fixtures'; } } diff --git a/Tests/Twig/Node/FeatureNodeTest.php b/Tests/Twig/Node/FeatureNodeTest.php index 12207fb..56c1d84 100644 --- a/Tests/Twig/Node/FeatureNodeTest.php +++ b/Tests/Twig/Node/FeatureNodeTest.php @@ -3,23 +3,25 @@ namespace Ae\FeatureBundle\Tests\Twig\Node; use Ae\FeatureBundle\Twig\Node\FeatureNode; +use Twig_Node; +use Twig_Node_Expression_Name; +use Twig_Node_Print; +use Twig_Test_NodeTestCase; /** * @author Carlo Forghieri + * @covers Ae\FeatureBundle\Twig\Node\FeatureNode */ -class FeatureNodeTest extends \Twig_Test_NodeTestCase +class FeatureNodeTest extends Twig_Test_NodeTestCase { - /** - * @covers Ae\FeatureBundle\Twig\Node\FeatureNode::__construct - */ public function testConstructor() { - $name = 'foo'; + $name = 'foo'; $parent = 'parent'; - $body = new \Twig_Node(array(), array(), 1); + $body = new Twig_Node([], [], 1); - $node = new FeatureNode($name, $parent, $body, null, 1); - $tests = $node->getNode('tests')->getIterator(); + $node = new FeatureNode($name, $parent, $body, null, 1); + $tests = $node->getNode('tests')->getIterator(); $this->assertInstanceOf('Twig_Node_Expression_MethodCall', $tests[0]); $this->assertEquals($body, $tests[1]); @@ -27,38 +29,41 @@ public function testConstructor() } /** - * @covers Ae\FeatureBundle\Twig\Node\FeatureNode::compile * @dataProvider getTests */ - public function testCompile($node, $source, $environment = null, $isPattern = null) - { + public function testCompile( + $node, + $source, + $environment = null, + $isPattern = null + ) { parent::testCompile($node, $source, $environment, $isPattern); } public function getTests() { - $tests = array(); + $tests = []; - $name = 'foo'; + $name = 'foo'; $parent = 'parent'; - $body = new \Twig_Node(array( - new \Twig_Node_Print(new \Twig_Node_Expression_Name('foo', 1), 1), - ), array(), 1); + $body = new Twig_Node([ + new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1), + ], [], 1); $node = new FeatureNode($name, $parent, $body, null, 1); - $tests[] = array($node, <<env->getExtension('feature')->isGranted("$name", "$parent")) { echo {$this->getVariableGetter('foo')}; } EOF - ); + ]; - $else = new \Twig_Node(array( - new \Twig_Node_Print(new \Twig_Node_Expression_Name('bar', 1), 1), - ), array(), 1); + $else = new Twig_Node([ + new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1), + ], [], 1); $node = new FeatureNode($name, $parent, $body, $else, 1); - $tests[] = array($node, <<env->getExtension('feature')->isGranted("$name", "$parent")) { echo {$this->getVariableGetter('foo')}; @@ -66,7 +71,7 @@ public function getTests() echo {$this->getVariableGetter('bar')}; } EOF - ); + ]; return $tests; } diff --git a/Twig/Extension/FeatureExtension.php b/Twig/Extension/FeatureExtension.php index 022b433..372ca52 100644 --- a/Twig/Extension/FeatureExtension.php +++ b/Twig/Extension/FeatureExtension.php @@ -4,34 +4,39 @@ use Ae\FeatureBundle\Service\Feature; use Ae\FeatureBundle\Twig\TokenParser\FeatureTokenParser; +use Twig_Extension; /** * @author Carlo Forghieri */ -class FeatureExtension extends \Twig_Extension +class FeatureExtension extends Twig_Extension { + /** + * @var Feature + */ protected $service; /** - * @param \Ae\FeatureBundle\Service\Feature $service + * @param Feature $service */ public function __construct(Feature $service) { - $this->service = $service; + $this->service = $service; } /** - * Returns the token parser instance to add to the existing list. - * - * @return array An array of Twig_TokenParser instances + * {@inheritdoc} */ public function getTokenParsers() { - return array( + return [ new FeatureTokenParser(), - ); + ]; } + /** + * {@inheritdoc} + */ public function getName() { return 'feature'; diff --git a/Twig/Node/FeatureNode.php b/Twig/Node/FeatureNode.php index 08fa9b9..9dd2791 100644 --- a/Twig/Node/FeatureNode.php +++ b/Twig/Node/FeatureNode.php @@ -2,40 +2,40 @@ namespace Ae\FeatureBundle\Twig\Node; +use Twig_Node; +use Twig_Node_Expression_Array; +use Twig_Node_Expression_Constant; +use Twig_Node_Expression_ExtensionReference; +use Twig_Node_Expression_MethodCall; +use Twig_Node_If; + /** * @author Carlo Forghieri */ -class FeatureNode extends \Twig_Node_If +class FeatureNode extends Twig_Node_If { - /** - * @param int $lineno - * @param string $tag - */ public function __construct($name, $parent, $body, $else, $lineno, $tag = null) { - $tests = new \Twig_Node(array( + $tests = new Twig_Node([ $this->createExpression($name, $parent, $lineno), $body, - )); + ]); - parent::__construct($tests, $else, $lineno, $tag = null); + parent::__construct($tests, $else, $lineno, $tag); } - /** - * @param integer $lineno - */ protected function createExpression($name, $parent, $lineno) { - return new \Twig_Node_Expression_MethodCall( - new \Twig_Node_Expression_ExtensionReference('feature', $lineno), + return new Twig_Node_Expression_MethodCall( + new Twig_Node_Expression_ExtensionReference('feature', $lineno), 'isGranted', - new \Twig_Node_Expression_Array( - array( - new \Twig_Node_Expression_Constant('name', $lineno), - new \Twig_Node_Expression_Constant($name, $lineno), - new \Twig_Node_Expression_Constant('parent', $lineno), - new \Twig_Node_Expression_Constant($parent, $lineno), - ), + new Twig_Node_Expression_Array( + [ + new Twig_Node_Expression_Constant('name', $lineno), + new Twig_Node_Expression_Constant($name, $lineno), + new Twig_Node_Expression_Constant('parent', $lineno), + new Twig_Node_Expression_Constant($parent, $lineno), + ], $lineno ), $lineno diff --git a/Twig/TokenParser/FeatureTokenParser.php b/Twig/TokenParser/FeatureTokenParser.php index 1d9ca3c..a8f947a 100644 --- a/Twig/TokenParser/FeatureTokenParser.php +++ b/Twig/TokenParser/FeatureTokenParser.php @@ -3,53 +3,60 @@ namespace Ae\FeatureBundle\Twig\TokenParser; use Ae\FeatureBundle\Twig\Node\FeatureNode; +use Twig_Error_Syntax; +use Twig_Token; +use Twig_TokenParser; /** * @author Carlo Forghieri */ -class FeatureTokenParser extends \Twig_TokenParser +class FeatureTokenParser extends Twig_TokenParser { /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance + * @param Twig_Token $token A Twig_Token instance. * - * @return \Twig_NodeInterface A Twig_NodeInterface instance + * @return \Twig_NodeInterface A Twig_NodeInterface instance. */ - public function parse(\Twig_Token $token) + public function parse(Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $name = null; + $name = null; $parent = null; - if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { - if ($stream->test(\Twig_Token::STRING_TYPE)) { + if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { + if ($stream->test(Twig_Token::STRING_TYPE)) { // {% feature "name" %} $name = $stream->next()->getValue(); - } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { - throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "name" string.'); + } elseif (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { + throw new Twig_Error_Syntax( + 'Unexpected token. Twig was looking for the "name" string.' + ); } if ($stream->test('from')) { // {% feature "name" from "parent" %} $stream->next(); $parent = $stream->next()->getValue(); - } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { - throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "from" keyword.'); + } elseif (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { + throw new Twig_Error_Syntax( + 'Unexpected token. Twig was looking for the "from" keyword.' + ); } } // {% feature %}...{% endfeature %} - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideFeatureFork')); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideFeatureFork']); $else = null; - $end = false; + $end = false; while (!$end) { switch ($this->parser->getStream()->next()->getValue()) { case 'else': - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideFeatureEnd')); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideFeatureEnd']); break; case 'endfeature': @@ -57,23 +64,38 @@ public function parse(\Twig_Token $token) break; default: - throw new \Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else" or "endfeature" to close the "feature" block started at line %d)', $lineno), -1); + throw new Twig_Error_Syntax( + sprintf( + 'Unexpected end of template. Twig was looking for '. + 'the following tags "else" or "endfeature" to '. + 'close the "feature" block started at line %d)', + $lineno + ), + -1 + ); } } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Twig_Token::BLOCK_END_TYPE); - return new FeatureNode($name, $parent, $body, $else, $lineno, $this->getTag()); + return new FeatureNode( + $name, + $parent, + $body, + $else, + $lineno, + $this->getTag() + ); } - public function decideFeatureFork(\Twig_Token $token) + public function decideFeatureFork(Twig_Token $token) { - return $token->test(array('else', 'endfeature')); + return $token->test(['else', 'endfeature']); } - public function decideFeatureEnd(\Twig_Token $token) + public function decideFeatureEnd(Twig_Token $token) { - return $token->test(array('endfeature')); + return $token->test(['endfeature']); } /** diff --git a/composer.json b/composer.json index 6ffc519..3e60431 100644 --- a/composer.json +++ b/composer.json @@ -1,31 +1,39 @@ { - "name": "adespresso/feature-bundle", - "description": "Manage release of new features", - "license": "Apache-2.0", - "type": "symfony-bundle", "authors": [ { - "name": "Carlo Forghieri", - "email": "carlo@adespresso.com" + "email": "carlo@adespresso.com", + "name": "Carlo Forghieri" } ], - "require": { - "php": ">=5.3.3", - "symfony/framework-bundle": "~2.3", - "symfony/security": "~2.3", - "symfony/twig-bundle": "~2.3", - "doctrine/orm": "~2.2,>=2.2.3", - "friendsofsymfony/user-bundle": "1.3.*", - "sonata-project/admin-bundle": "2.3.x-dev", - "sonata-project/doctrine-orm-admin-bundle": "2.3.x-dev" - }, "autoload": { + "exclude-from-classmap": [ + "/Tests/" + ], "psr-4": { "Ae\\FeatureBundle\\": "" } }, + "config": { + "sort-packages": true + }, + "description": "Manage release of new features", + "license": "Apache-2.0", + "name": "adespresso/feature-bundle", + "require": { + "php": "^5.5 || ^7.0", + "doctrine/orm": "^2.2.3", + "friendsofsymfony/user-bundle": "1.3.*", + "sonata-project/admin-bundle": "^2.3.4", + "sonata-project/doctrine-orm-admin-bundle": "^2.3.1", + "symfony/dependency-injection": "^2.8 || ^3.0", + "symfony/framework-bundle": "^2.7 || ^3.0", + "symfony/security": "^2.3 || ^3.0", + "symfony/twig-bundle": "^2.3 || ^3.0" + }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.1", - "matthiasnoback/symfony-dependency-injection-test": "^0.7.6" - } + "fabpot/php-cs-fixer": "^1.11", + "matthiasnoback/symfony-dependency-injection-test": "^0.7.6", + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "symfony-bundle" }