diff --git a/CHANGELOG.md b/CHANGELOG.md index d391129..e14ae70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Changelog ----- * Support Symfony 6 +* Use DateTimeInterface instead of DateTime. * Adjust to doctrine and twig BC breaks. If you extended classes or customized services, check for old `Twig_*` classes or `Doctrine\Common\Persistence` namespace. * Drop support for old Symfony versions * Drop support for old PHP versions diff --git a/composer.json b/composer.json index 44c851c..207e37e 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "symfony/security-core": "^6.4" }, "require-dev": { + "ext-dom": "*", "jackalope/jackalope-doctrine-dbal": "^1.3 || ^2.0", "mockery/mockery": "^1.4.1", "symfony-cmf/routing-bundle": "dev-sf7 as 3.1.0", diff --git a/src/CmfCoreBundle.php b/src/CmfCoreBundle.php index 7640806..fb7f3a5 100644 --- a/src/CmfCoreBundle.php +++ b/src/CmfCoreBundle.php @@ -17,7 +17,7 @@ class CmfCoreBundle extends Bundle { - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { $container->addCompilerPass(new AddPublishedVotersPass()); } diff --git a/src/DependencyInjection/CmfCoreExtension.php b/src/DependencyInjection/CmfCoreExtension.php index 862e687..87a1349 100644 --- a/src/DependencyInjection/CmfCoreExtension.php +++ b/src/DependencyInjection/CmfCoreExtension.php @@ -29,7 +29,7 @@ class CmfCoreExtension extends Extension implements PrependExtensionInterface * * {@inheritdoc} */ - public function prepend(ContainerBuilder $container) + public function prepend(ContainerBuilder $container): void { // process the configuration of CmfCoreExtension $configs = $container->getExtensionConfig($this->getAlias()); @@ -243,10 +243,7 @@ public function prepend(ContainerBuilder $container) } } - /** - * {@inheritdoc} - */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $config = $this->processConfiguration(new Configuration(), $configs); @@ -283,7 +280,7 @@ public function load(array $configs, ContainerBuilder $container) /** * Setup the cmf_core_checkbox_url_label form type if the routing bundle is there. */ - public function setupFormTypes(ContainerBuilder $container, LoaderInterface $loader) + public function setupFormTypes(ContainerBuilder $container, LoaderInterface $loader): void { $bundles = $container->getParameter('kernel.bundles'); if (isset($bundles['CmfRoutingBundle'])) { @@ -302,7 +299,7 @@ public function setupFormTypes(ContainerBuilder $container, LoaderInterface $loa * * @throws InvalidConfigurationException */ - private function loadPublishWorkflow($config, XmlFileLoader $loader, ContainerBuilder $container) + private function loadPublishWorkflow($config, XmlFileLoader $loader, ContainerBuilder $container): void { $bundles = $container->getParameter('kernel.bundles'); @@ -336,18 +333,12 @@ private function loadPublishWorkflow($config, XmlFileLoader $loader, ContainerBu } } - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() + public function getXsdValidationBasePath(): bool|string { return __DIR__.'/../Resources/config/schema'; } - /** - * {@inheritdoc} - */ - public function getNamespace() + public function getNamespace(): string { return 'http://cmf.symfony.com/schema/dic/core'; } diff --git a/src/DependencyInjection/Compiler/AddPublishedVotersPass.php b/src/DependencyInjection/Compiler/AddPublishedVotersPass.php index 195a17b..08846dc 100644 --- a/src/DependencyInjection/Compiler/AddPublishedVotersPass.php +++ b/src/DependencyInjection/Compiler/AddPublishedVotersPass.php @@ -31,7 +31,7 @@ class AddPublishedVotersPass implements CompilerPassInterface * * {@inheritdoc} */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('cmf_core.publish_workflow.access_decision_manager')) { return; diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index ce6f0a7..d3ae7f3 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -16,10 +16,7 @@ class Configuration implements ConfigurationInterface { - /** - * {@inheritdoc} - */ - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('cmf_core'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Doctrine/Phpcr/NonTranslatableMetadataListener.php b/src/Doctrine/Phpcr/NonTranslatableMetadataListener.php index 0447f6f..7906fb0 100644 --- a/src/Doctrine/Phpcr/NonTranslatableMetadataListener.php +++ b/src/Doctrine/Phpcr/NonTranslatableMetadataListener.php @@ -26,7 +26,7 @@ class NonTranslatableMetadataListener implements EventSubscriber /** * @return array */ - public function getSubscribedEvents() + public function getSubscribedEvents(): array { return [ 'loadClassMetadata', @@ -37,7 +37,7 @@ public function getSubscribedEvents() * Handle the load class metadata event: remove translated attribute from * fields and remove the locale mapping if present. */ - public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void { /** @var ClassMetadata $meta */ $meta = $eventArgs->getClassMetadata(); diff --git a/src/Doctrine/Phpcr/TranslatableMetadataListener.php b/src/Doctrine/Phpcr/TranslatableMetadataListener.php index 3524830..3a986ad 100644 --- a/src/Doctrine/Phpcr/TranslatableMetadataListener.php +++ b/src/Doctrine/Phpcr/TranslatableMetadataListener.php @@ -23,23 +23,15 @@ */ class TranslatableMetadataListener implements EventSubscriber { - /** - * @var string - */ - private $translationStrategy; - - /** - * @param string $translationStrategy - */ - public function __construct($translationStrategy) - { - $this->translationStrategy = $translationStrategy; + public function __construct( + private string $translationStrategy + ) { } /** * @return array */ - public function getSubscribedEvents() + public function getSubscribedEvents(): array { return [ 'loadClassMetadata', @@ -49,7 +41,7 @@ public function getSubscribedEvents() /** * Handle the load class metadata event: set the translation strategy. */ - public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void { /** @var ClassMetadata $meta */ $meta = $eventArgs->getClassMetadata(); diff --git a/src/EventListener/PublishWorkflowListener.php b/src/EventListener/PublishWorkflowListener.php index f20a481..56a3a77 100644 --- a/src/EventListener/PublishWorkflowListener.php +++ b/src/EventListener/PublishWorkflowListener.php @@ -26,39 +26,21 @@ */ class PublishWorkflowListener implements EventSubscriberInterface { - /** - * @var PublishWorkflowChecker - */ - protected $publishWorkflowChecker; - - /** - * The attribute to check with the workflow checker, typically VIEW or VIEW_ANONYMOUS. - * - * @var string - */ - private $publishWorkflowPermission; - - /** - * @param string $attribute the attribute name to check - */ - public function __construct(PublishWorkflowChecker $publishWorkflowChecker, $attribute = PublishWorkflowChecker::VIEW_ATTRIBUTE) + public function __construct( + private PublishWorkflowChecker $publishWorkflowChecker, + /** + * The attribute to check with the workflow checker, typically VIEW or VIEW_ANONYMOUS. + */ + private string $publishWorkflowPermission = PublishWorkflowChecker::VIEW_ATTRIBUTE) { - $this->publishWorkflowChecker = $publishWorkflowChecker; - $this->publishWorkflowPermission = $attribute; } - /** - * @return string - */ - public function getPublishWorkflowPermission() + public function getPublishWorkflowPermission(): string { return $this->publishWorkflowPermission; } - /** - * @param string $attribute specify what permission to check, typically VIEW or VIEW_ANONYMOUS - */ - public function setPublishWorkflowPermission($attribute) + public function setPublishWorkflowPermission(string $attribute): void { $this->publishWorkflowPermission = $attribute; } @@ -66,7 +48,7 @@ public function setPublishWorkflowPermission($attribute) /** * Handling the request event. */ - public function onKernelRequest(RequestEvent $event) + public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); @@ -83,10 +65,8 @@ public function onKernelRequest(RequestEvent $event) /** * We are only interested in request events. - * - * @return array */ - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [['onKernelRequest', 1]], diff --git a/src/Form/Type/CheckboxUrlLabelFormType.php b/src/Form/Type/CheckboxUrlLabelFormType.php index 59002a1..12a18a6 100644 --- a/src/Form/Type/CheckboxUrlLabelFormType.php +++ b/src/Form/Type/CheckboxUrlLabelFormType.php @@ -34,60 +34,46 @@ */ class CheckboxUrlLabelFormType extends AbstractType { - /** - * @var RouterInterface - */ - protected $router; - - public function __construct(RouterInterface $router) - { - $this->router = $router; + public function __construct( + private RouterInterface $router + ) { } /** * {@inheritdoc} */ - public function buildView(FormView $view, FormInterface $form, array $options) + public function buildView(FormView $view, FormInterface $form, array $options): void { $routes = $options['routes']; $paths = []; foreach ($routes as $key => $route) { - $name = isset($route['name']) ? $route['name'] : ''; - $parameters = isset($route['parameters']) ? $route['parameters'] : []; - $referenceType = isset($route['referenceType']) ? $route['referenceType'] : UrlGeneratorInterface::ABSOLUTE_PATH; + $name = $route['name'] ?? ''; + $parameters = $route['parameters'] ?? []; + $referenceType = $route['referenceType'] ?? UrlGeneratorInterface::ABSOLUTE_PATH; $paths[$key] = $this->router->generate($name, $parameters, $referenceType); } $view->vars['paths'] = $paths; parent::buildView($view, $form, $options); } - public function configureOptions(OptionsResolver $resolver) + public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'routes' => [], ]); } - /** - * {@inheritdoc} - */ - public function getName() + public function getName(): string { return $this->getBlockPrefix(); } - /** - * {@inheritdoc} - */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'cmf_core_checkbox_url_label'; } - /** - * {@inheritdoc} - */ - public function getParent() + public function getParent(): ?string { return CheckboxType::class; } diff --git a/src/Model/ChildInterface.php b/src/Model/ChildInterface.php index 6b48030..ba380ec 100644 --- a/src/Model/ChildInterface.php +++ b/src/Model/ChildInterface.php @@ -19,13 +19,7 @@ */ interface ChildInterface { - /** - * @param $parent object - */ - public function setParentObject($parent); + public function setParentObject(object $parent); - /** - * @return object - */ - public function getParentObject(); + public function getParentObject(): object; } diff --git a/src/PublishWorkflow/AlwaysPublishedWorkflowChecker.php b/src/PublishWorkflow/AlwaysPublishedWorkflowChecker.php index 7aebc3d..8e234c1 100644 --- a/src/PublishWorkflow/AlwaysPublishedWorkflowChecker.php +++ b/src/PublishWorkflow/AlwaysPublishedWorkflowChecker.php @@ -28,7 +28,7 @@ class AlwaysPublishedWorkflowChecker implements AuthorizationCheckerInterface /** * {@inheritdoc} */ - public function isGranted($attributes, $object = null) + public function isGranted(mixed $attribute, mixed $subject = null): bool { return true; } diff --git a/src/PublishWorkflow/PublishTimePeriodInterface.php b/src/PublishWorkflow/PublishTimePeriodInterface.php index de33bde..abba7e6 100644 --- a/src/PublishWorkflow/PublishTimePeriodInterface.php +++ b/src/PublishWorkflow/PublishTimePeriodInterface.php @@ -23,7 +23,7 @@ interface PublishTimePeriodInterface extends PublishTimePeriodReadInterface * Setting a NULL value asserts that the content * has always been publishable. */ - public function setPublishStartDate(\DateTime $publishDate = null); + public function setPublishStartDate(\DateTimeInterface $publishDate = null): void; /** * Set the date at which the content should @@ -32,5 +32,5 @@ public function setPublishStartDate(\DateTime $publishDate = null); * Setting a NULL value asserts that the * content will always be publishable. */ - public function setPublishEndDate(\DateTime $publishDate = null); + public function setPublishEndDate(\DateTimeInterface $publishDate = null): void; } diff --git a/src/PublishWorkflow/PublishTimePeriodReadInterface.php b/src/PublishWorkflow/PublishTimePeriodReadInterface.php index 9466b44..a62ee4e 100644 --- a/src/PublishWorkflow/PublishTimePeriodReadInterface.php +++ b/src/PublishWorkflow/PublishTimePeriodReadInterface.php @@ -24,18 +24,14 @@ interface PublishTimePeriodReadInterface * * A NULL value is interpreted as a date in the past, meaning the content * is publishable unless publish end date is set and in the past. - * - * @return \DateTime|null */ - public function getPublishStartDate(); + public function getPublishStartDate(): ?\DateTimeInterface; /** * Return the date at which the content should stop being published. * * A NULL value is interpreted as saying that the document will * never end being publishable. - * - * @return \DateTime|null */ - public function getPublishEndDate(); + public function getPublishEndDate(): ?\DateTimeInterface; } diff --git a/src/PublishWorkflow/PublishWorkflowChecker.php b/src/PublishWorkflow/PublishWorkflowChecker.php index de19336..b588c3f 100644 --- a/src/PublishWorkflow/PublishWorkflowChecker.php +++ b/src/PublishWorkflow/PublishWorkflowChecker.php @@ -11,9 +11,8 @@ namespace Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow; -use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; +use Symfony\Component\Security\Core\Authentication\Token\NullToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; @@ -39,7 +38,7 @@ class PublishWorkflowChecker implements AuthorizationCheckerInterface * This attribute means the user is allowed to see this content, either * because it is published or because he is granted the bypassingRole. */ - const VIEW_ATTRIBUTE = 'VIEW'; + public const VIEW_ATTRIBUTE = 'VIEW'; /** * This attribute means the content is available for viewing by anonymous @@ -49,53 +48,24 @@ class PublishWorkflowChecker implements AuthorizationCheckerInterface * The bypass role is handled by the workflow checker, the individual * voters should treat VIEW and VIEW_ANONYMOUS the same. */ - const VIEW_ANONYMOUS_ATTRIBUTE = 'VIEW_ANONYMOUS'; + public const VIEW_ANONYMOUS_ATTRIBUTE = 'VIEW_ANONYMOUS'; /** - * @var bool|string Role allowed to bypass the published check if the - * VIEW attribute is used, or false to never bypass + * @param bool|string $bypassingRole A role that is allowed to bypass the published check if we + * ask for the VIEW permission. Ignored on VIEW_ANONYMOUS. */ - private $bypassingRole; - - /** - * @var TokenStorageInterface - */ - private $tokenStorage; - - /** - * @var AuthorizationCheckerInterface - */ - private $authorizationChecker; - - /** - * @var AccessDecisionManagerInterface - */ - private $accessDecisionManager; - - /** - * @var TokenInterface - */ - private $token; - - /** - * @param AccessDecisionManagerInterface $accessDecisionManager Service to do the actual decision - * @param bool|string $bypassingRole A role that is allowed to bypass - * the published check if we ask for - * the VIEW permission. Ignored on - * VIEW_ANONYMOUS - */ - public function __construct(TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authorizationChecker, AccessDecisionManagerInterface $accessDecisionManager, $bypassingRole = false) + public function __construct( + private TokenStorageInterface $tokenStorage, + private AuthorizationCheckerInterface $authorizationChecker, + private AccessDecisionManagerInterface $accessDecisionManager, + private string|bool $bypassingRole = false) { - $this->tokenStorage = $tokenStorage; - $this->authorizationChecker = $authorizationChecker; - $this->accessDecisionManager = $accessDecisionManager; - $this->bypassingRole = $bypassingRole; } /** * {@inheritdoc} */ - public function isGranted($attribute, $object = null) + public function isGranted(mixed $attribute, mixed $subject = null): bool { if (self::VIEW_ATTRIBUTE === $attribute && null !== $this->tokenStorage->getToken() @@ -108,9 +78,9 @@ public function isGranted($attribute, $object = null) // not logged in, just check with a dummy token if (null === $token) { - $token = new AnonymousToken('', ''); + $token = new NullToken(); } - return $this->accessDecisionManager->decide($token, [$attribute], $object); + return $this->accessDecisionManager->decide($token, [$attribute], $subject); } } diff --git a/src/PublishWorkflow/PublishableInterface.php b/src/PublishWorkflow/PublishableInterface.php index cebeeea..b145a16 100644 --- a/src/PublishWorkflow/PublishableInterface.php +++ b/src/PublishWorkflow/PublishableInterface.php @@ -18,8 +18,6 @@ interface PublishableInterface extends PublishableReadInterface { /** * Set the boolean flag whether this content is publishable or not. - * - * @param bool $publishable */ - public function setPublishable($publishable); + public function setPublishable(bool $publishable): void; } diff --git a/src/PublishWorkflow/PublishableReadInterface.php b/src/PublishWorkflow/PublishableReadInterface.php index 7b5fd98..5cef78d 100644 --- a/src/PublishWorkflow/PublishableReadInterface.php +++ b/src/PublishWorkflow/PublishableReadInterface.php @@ -24,8 +24,6 @@ interface PublishableReadInterface * * A false value indicates that the content is not published. True means it * is allowed to show this content. - * - * @return bool */ - public function isPublishable(); + public function isPublishable(): bool; } diff --git a/src/PublishWorkflow/Voter/PublishTimePeriodVoter.php b/src/PublishWorkflow/Voter/PublishTimePeriodVoter.php index 77ab23d..7526618 100644 --- a/src/PublishWorkflow/Voter/PublishTimePeriodVoter.php +++ b/src/PublishWorkflow/Voter/PublishTimePeriodVoter.php @@ -24,27 +24,24 @@ */ class PublishTimePeriodVoter extends Voter { - /** - * @var \DateTime - */ - protected $currentTime; + private \DateTimeInterface $currentTime; public function __construct() { // we create the timestamp on instantiation to avoid glitches due to // the time passing during the request - $this->currentTime = new \DateTime(); + $this->currentTime = new \DateTimeImmutable(); } /** * Overwrite the current time. */ - public function setCurrentTime(\DateTime $currentTime) + public function setCurrentTime(\DateTimeInterface $currentTime): void { $this->currentTime = $currentTime; } - protected function supports($attribute, $subject) + protected function supports($attribute, $subject): bool { return $subject instanceof PublishTimePeriodReadInterface && $this->supportsAttribute($attribute); @@ -55,7 +52,7 @@ protected function supports($attribute, $subject) * * @param PublishTimePeriodReadInterface $subject */ - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool { $startDate = $subject->getPublishStartDate(); $endDate = $subject->getPublishEndDate(); diff --git a/src/PublishWorkflow/Voter/PublishableVoter.php b/src/PublishWorkflow/Voter/PublishableVoter.php index 88a0061..ef0b668 100644 --- a/src/PublishWorkflow/Voter/PublishableVoter.php +++ b/src/PublishWorkflow/Voter/PublishableVoter.php @@ -24,7 +24,7 @@ */ class PublishableVoter extends Voter { - protected function supports($attribute, $subject) + protected function supports(string $attribute, mixed $subject): bool { return $subject instanceof PublishableReadInterface && $this->supportsAttribute($attribute); @@ -35,7 +35,7 @@ protected function supports($attribute, $subject) * * @param PublishableReadInterface $subject */ - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { return $subject->isPublishable(); } diff --git a/src/Security/Authorization/Voter/PublishedVoter.php b/src/Security/Authorization/Voter/PublishedVoter.php index 83db2c0..fac6b0c 100644 --- a/src/Security/Authorization/Voter/PublishedVoter.php +++ b/src/Security/Authorization/Voter/PublishedVoter.php @@ -26,14 +26,9 @@ */ class PublishedVoter extends Voter { - /** - * @var PublishWorkflowChecker - */ - private $publishWorkflowChecker; - - public function __construct(PublishWorkflowChecker $publishWorkflowChecker) - { - $this->publishWorkflowChecker = $publishWorkflowChecker; + public function __construct( + private PublishWorkflowChecker $publishWorkflowChecker + ) { } /** @@ -52,13 +47,13 @@ public function supportsType(string $subjectType): bool || is_subclass_of($subjectType, PublishTimePeriodReadInterface::class); } - protected function supports($attribute, $subject) + protected function supports(string $attribute, mixed $subject): bool { return \is_object($subject) && $this->supportsType(\get_class($subject)) && $this->supportsAttribute($attribute); } - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { return $this->publishWorkflowChecker->isGranted($attribute, $subject); } diff --git a/src/Templating/Helper/Cmf.php b/src/Templating/Helper/Cmf.php index 4b8e11a..d5c2d44 100644 --- a/src/Templating/Helper/Cmf.php +++ b/src/Templating/Helper/Cmf.php @@ -24,35 +24,23 @@ /** * Layout helper for the CMF. * - * This class is used by the symfony templating integration and by the twig extension. + * This class is used by the twig extension. * * @author Wouter J */ class Cmf { - /** - * @var ManagerRegistry - */ - private $doctrineRegistry; - - /** - * @var string - */ - private $doctrineManagerName; + private ManagerRegistry $doctrineRegistry; + private ?string $doctrineManagerName; /** * @var DocumentManager */ - protected $dm; + protected DocumentManager $dm; - /** - * @var AuthorizationCheckerInterface - */ - private $publishWorkflowChecker; - - public function __construct(AuthorizationCheckerInterface $publishWorkflowChecker = null) - { - $this->publishWorkflowChecker = $publishWorkflowChecker; + public function __construct( + private ?AuthorizationCheckerInterface $publishWorkflowChecker = null + ) { } /** @@ -60,9 +48,9 @@ public function __construct(AuthorizationCheckerInterface $publishWorkflowChecke * * @param string|null $managerName Manager name if not the default */ - public function setDoctrineRegistry(ManagerRegistry $registry, ?string $managerName = null) + public function setDoctrineRegistry(ManagerRegistry $registry, ?string $managerName = null): void { - if ($this->doctrineRegistry) { + if (isset($this->doctrineRegistry)) { throw new \LogicException('Do not call this setter repeatedly.'); } @@ -72,8 +60,8 @@ public function setDoctrineRegistry(ManagerRegistry $registry, ?string $managerN protected function getDm(): DocumentManager { - if (!$this->dm) { - if (!$this->doctrineRegistry) { + if (!isset($this->dm)) { + if (!isset($this->doctrineRegistry)) { throw new \RuntimeException('Doctrine is not available.'); } @@ -88,7 +76,7 @@ protected function getDm(): DocumentManager * * @return bool|string node name or false if the document is not in the unit of work */ - public function getNodeName($document) + public function getNodeName($document): bool|string { $path = $this->getPath($document); if (false === $path) { @@ -103,7 +91,7 @@ public function getNodeName($document) * * @return bool|string node name or false if the document is not in the unit of work */ - public function getParentPath($document) + public function getParentPath($document): bool|string { $path = $this->getPath($document); if (!$path) { @@ -118,11 +106,11 @@ public function getParentPath($document) * * @return bool|string path or false if the document is not in the unit of work */ - public function getPath($document) + public function getPath($document): bool|string { try { return $this->getDm()->getUnitOfWork()->getDocumentId($document); - } catch (\Exception $e) { + } catch (\Exception) { return false; } } @@ -132,7 +120,7 @@ public function getPath($document) * * @return object|null */ - public function find($path) + public function find($path): ?object { return $this->getDm()->find(null, $path); } @@ -146,7 +134,7 @@ public function find($path) * * @return object|null */ - public function findTranslation($pathOrDocument, string $locale, bool $fallback = true) + public function findTranslation($pathOrDocument, string $locale, bool $fallback = true): ?object { if (\is_object($pathOrDocument)) { $path = $this->getDm()->getUnitOfWork()->getDocumentId($pathOrDocument); @@ -169,7 +157,7 @@ public function findTranslation($pathOrDocument, string $locale, bool $fallback * * @return object|null */ - private function getDocument($document, ?bool $ignoreRole = false, ?string $class = null) + private function getDocument($document, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if (\is_string($document)) { try { @@ -184,9 +172,9 @@ private function getDocument($document, ?bool $ignoreRole = false, ?string $clas } if (empty($document) + || (null !== $class && !($document instanceof $class)) || (false === $ignoreRole && !$this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ATTRIBUTE, $document)) || (true === $ignoreRole && !$this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE, $document)) - || (null !== $class && !($document instanceof $class)) ) { return null; } @@ -203,7 +191,7 @@ private function getDocument($document, ?bool $ignoreRole = false, ?string $clas * * @return array */ - public function findMany(array $paths = [], $limit = false, $offset = false, ?bool $ignoreRole = false, ?string $class = null) + public function findMany(array $paths = [], $limit = false, $offset = false, ?bool $ignoreRole = false, ?string $class = null): array { if ($offset) { $paths = \array_slice($paths, $offset); @@ -282,7 +270,7 @@ public function getLocalesFor($document, bool $includeFallbacks = false): array * or false if the parent is not managed by * the configured document manager */ - public function getChild($parent, string $name) + public function getChild($parent, string $name): object|bool|null { if (\is_object($parent)) { try { @@ -310,7 +298,7 @@ public function getChild($parent, string $name) * * @return array */ - public function getChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null) + public function getChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null): array { if (empty($parent)) { return []; @@ -323,7 +311,7 @@ public function getChildren($parent, $limit = false, $offset = false, $filter = $children = (array) $node->getNodeNames(); foreach ($children as $key => $child) { // filter before fetching data already to save some traffic - if (0 === strpos($child, 'phpcr_locale:')) { + if (str_starts_with($child, 'phpcr_locale:')) { unset($children[$key]); continue; @@ -331,7 +319,7 @@ public function getChildren($parent, $limit = false, $offset = false, $filter = $children[$key] = "$parent/$child"; } if ($offset) { - $key = array_search($offset, $children); + $key = array_search($offset, $children, true); if (false === $key) { return []; } @@ -341,7 +329,7 @@ public function getChildren($parent, $limit = false, $offset = false, $filter = $result = []; foreach ($children as $name => $child) { // if we requested all children above, we did not filter yet - if (0 === strpos($name, 'phpcr_locale:')) { + if (str_starts_with($name, 'phpcr_locale:')) { continue; } @@ -404,11 +392,9 @@ public function getLinkableChildren($parent, $limit = false, $offset = false, ?s * This does not work for route names or other things some routers may * support, only for objects. * - * @param object $document - * * @return bool true if it is possible to generate a link to $document */ - public function isLinkable($document): bool + public function isLinkable(mixed $document): bool { return $document instanceof Route @@ -424,7 +410,7 @@ public function isLinkable($document): bool * @param string[] $children * @param ?int $depth */ - private function getChildrenPaths(string $path, array &$children, ?int $depth) + private function getChildrenPaths(string $path, array &$children, ?int $depth): void { if (null !== $depth) { if ($depth-- < 1) { @@ -471,10 +457,10 @@ public function getDescendants($parent, ?int $depth = null): array * * @return object|null */ - private function checkChildren(array $childNames, string $path, ?bool $ignoreRole = false, ?string $class = null) + private function checkChildren(array $childNames, string $path, ?bool $ignoreRole = false, ?string $class = null): object|string|null { foreach ($childNames as $name) { - if (0 === strpos($name, 'phpcr_locale:')) { + if (str_starts_with($name, 'phpcr_locale:')) { continue; } @@ -493,7 +479,7 @@ private function checkChildren(array $childNames, string $path, ?bool $ignoreRol * * @return object|null */ - private function traversePrevDepth(?int $depth, int $anchorDepth, array $childNames, string $path, bool $ignoreRole, ?string $class) + private function traversePrevDepth(?int $depth, int $anchorDepth, array $childNames, string $path, bool $ignoreRole, ?string $class): object|string|null { foreach ($childNames as $childName) { $childPath = "$path/$childName"; @@ -529,7 +515,7 @@ private function traversePrevDepth(?int $depth, int $anchorDepth, array $childNa * * @return object|null */ - private function searchDepthPrev($path, $anchor, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null) + private function searchDepthPrev($path, $anchor, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if (\is_object($path)) { $path = $this->getDm()->getUnitOfWork()->getDocumentId($path); @@ -559,7 +545,7 @@ private function searchDepthPrev($path, $anchor, ?int $depth = null, ?bool $igno $childNames = $parent->getNodeNames()->getArrayCopy(); if (!empty($childNames)) { $childNames = array_reverse($childNames); - $key = array_search($node->getName(), $childNames); + $key = array_search($node->getName(), $childNames, true); $childNames = \array_slice($childNames, $key + 1); if (!empty($childNames)) { @@ -578,10 +564,10 @@ private function searchDepthPrev($path, $anchor, ?int $depth = null, ?bool $igno } // check parents - if (0 === strpos($parentPath, $anchor)) { + if (str_starts_with($parentPath, $anchor)) { $parent = $parent->getParent(); $childNames = $parent->getNodeNames()->getArrayCopy(); - $key = array_search(PathHelper::getNodeName($parentPath), $childNames); + $key = array_search(PathHelper::getNodeName($parentPath), $childNames, true); $childNames = \array_slice($childNames, 0, $key + 1); $childNames = array_reverse($childNames); if (!empty($childNames)) { @@ -603,10 +589,8 @@ private function searchDepthPrev($path, $anchor, ?int $depth = null, ?bool $igno * @param int|null $depth depth up to which to traverse down the tree when an anchor is provided * @param bool $ignoreRole if to ignore the role * @param string|null $class the class to filter by - * - * @return object|null */ - private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null) + private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if (\is_object($path)) { $path = $this->getDm()->getUnitOfWork()->getDocumentId($path); @@ -622,7 +606,7 @@ private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $igno $anchor = $this->getDm()->getUnitOfWork()->getDocumentId($anchor); } - if (0 !== strpos($path, $anchor)) { + if (!str_starts_with($path, $anchor)) { throw new \RuntimeException("The anchor path '$anchor' is not a parent of the current path '$path'."); } @@ -639,9 +623,9 @@ private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $igno $parentPath = PathHelper::getParentPath($path); // take the first eligible sibling - if (0 === strpos($parentPath, $anchor)) { + if (str_starts_with($parentPath, $anchor)) { $childNames = $parent->getNodeNames()->getArrayCopy(); - $key = array_search($node->getName(), $childNames); + $key = array_search($node->getName(), $childNames, true); $childNames = \array_slice($childNames, $key + 1); $result = $this->checkChildren($childNames, $parentPath, $ignoreRole, $class); if ($result) { @@ -652,12 +636,12 @@ private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $igno // take the first eligible parent, traverse up while ('/' !== $parentPath) { $parent = $parent->getParent(); - if (false === strpos($parent->getPath(), $anchor)) { + if (!str_contains($parent->getPath(), $anchor)) { return null; } $childNames = $parent->getNodeNames()->getArrayCopy(); - $key = array_search(PathHelper::getNodeName($parentPath), $childNames); + $key = array_search(PathHelper::getNodeName($parentPath), $childNames, true); $childNames = \array_slice($childNames, $key + 1); $parentPath = $parent->getPath(); $result = $this->checkChildren($childNames, $parentPath, $ignoreRole, $class); @@ -679,7 +663,7 @@ private function searchDepthNext($path, $anchor, ?int $depth = null, ?bool $igno * * @return object|null */ - private function search($path, ?bool $reverse = false, ?bool $ignoreRole = false, ?string $class = null) + private function search($path, ?bool $reverse = false, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if (\is_object($path)) { $path = $this->getDm()->getUnitOfWork()->getDocumentId($path); @@ -696,7 +680,7 @@ private function search($path, ?bool $reverse = false, ?bool $ignoreRole = false $childNames = array_reverse($childNames); } - $key = array_search($node->getName(), $childNames); + $key = array_search($node->getName(), $childNames, true); $childNames = \array_slice($childNames, $key + 1); return $this->checkChildren($childNames, $parentNode->getPath(), $ignoreRole, $class); @@ -713,7 +697,7 @@ private function search($path, ?bool $reverse = false, ?bool $ignoreRole = false * * @return object|null */ - public function getPrev($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null) + public function getPrev($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if ($anchor) { return $this->searchDepthPrev($current, $anchor, $depth, $ignoreRole, $class); @@ -733,7 +717,7 @@ public function getPrev($current, $anchor = null, ?int $depth = null, ?bool $ign * * @return object|null */ - public function getNext($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null) + public function getNext($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false, ?string $class = null): object|string|null { if ($anchor) { return $this->searchDepthNext($current, $anchor, $depth, $ignoreRole, $class); @@ -761,7 +745,7 @@ public function getNext($current, $anchor = null, ?int $depth = null, ?bool $ign * * @see isLinkable */ - public function getPrevLinkable($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false) + public function getPrevLinkable($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false): object|string|null { while ($candidate = $this->getPrev($current, $anchor, $depth, $ignoreRole)) { if ($this->isLinkable($candidate)) { @@ -793,7 +777,7 @@ public function getPrevLinkable($current, $anchor = null, ?int $depth = null, ?b * * @see isLinkable */ - public function getNextLinkable($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false) + public function getNextLinkable($current, $anchor = null, ?int $depth = null, ?bool $ignoreRole = false): object|string|null { while ($candidate = $this->getNext($current, $anchor, $depth, $ignoreRole)) { if ($this->isLinkable($candidate)) { diff --git a/src/Templating/Helper/CmfHelper.php b/src/Templating/Helper/CmfHelper.php deleted file mode 100644 index b782f68..0000000 --- a/src/Templating/Helper/CmfHelper.php +++ /dev/null @@ -1,308 +0,0 @@ - - */ -class CmfHelper extends Helper -{ - /** - * @var Cmf - */ - private $cmf; - - public function __construct(Cmf $cmf) - { - $this->cmf = $cmf; - } - - /** - * Gets the helper name. - * - * @return string - */ - public function getName() - { - return 'cmf'; - } - - /** - * @param object $document - * - * @return bool|string node name or false if the document is not in the unit of work - */ - public function getNodeName($document) - { - return $this->cmf->getNodeName($document); - } - - /** - * @param object $document - * - * @return bool|string node name or false if the document is not in the unit of work - */ - public function getParentPath($document) - { - return $this->cmf->getParentPath($document); - } - - /** - * @param object $document - * - * @return bool|string path or false if the document is not in the unit of work - */ - public function getPath($document) - { - return $this->cmf->getPath($document); - } - - /** - * Finds a document by path. - * - * @return object|null - */ - public function find($path) - { - return $this->cmf->find($path); - } - - /** - * Finds a document by path and locale. - * - * @param string|object $pathOrDocument the identifier of the class (path or document object) - * @param string $locale the language to try to load - * @param bool $fallback set to true if the language fallback mechanism should be used - * - * @return object|null - */ - public function findTranslation($pathOrDocument, $locale, $fallback = true) - { - return $this->cmf->findTranslation($pathOrDocument, $locale, $fallback); - } - - /** - * @param array $paths list of paths - * @param int|bool $limit int limit or false - * @param string|bool $offset string node name to which to skip to or false - * @param bool|null $ignoreRole if the role should be ignored or null if publish workflow should be ignored - * @param string|null $class class name to filter on - * - * @return array - */ - public function findMany($paths = [], $limit = false, $offset = false, $ignoreRole = false, $class = null) - { - return $this->cmf->findMany($paths, $limit, $offset, $ignoreRole, $class); - } - - /** - * Check if a document is published, regardless of the current users role. - * - * If you need the bypass role, you will have a firewall configured and can - * simply use {{ is_granted('VIEW', document) }} - * - * @param object $document - * - * @return bool - */ - public function isPublished($document) - { - return $this->cmf->isPublished($document); - } - - /** - * Get the locales of the document. - * - * @param string|object $document Document instance or path - * @param bool $includeFallbacks - * - * @return array - */ - public function getLocalesFor($document, $includeFallbacks = false) - { - return $this->cmf->getLocalesFor($document, $includeFallbacks); - } - - /** - * @param string|object $parent parent path/document - * @param string $name - * - * @return bool|object|null child or null if the child cannot be found - * or false if the parent is not managed by - * the configured document manager - */ - public function getChild($parent, $name) - { - return $this->cmf->getChild($parent, $name); - } - - /** - * Gets child documents. - * - * @param string|object $parent parent id or document - * @param int|bool $limit maximum number of children to get or - * false for no limit - * @param string|bool $offset node name to which to skip to or false - * @param string|null $filter child name filter (optional) - * @param bool|null $ignoreRole whether the role should be ignored or - * null if publish workflow should be - * ignored (defaults to false) - * @param string|null $class class name to filter on (optional) - * - * @return array - */ - public function getChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null) - { - return $this->cmf->getChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); - } - - /** - * Gets linkable child documents of a document or repository id. - * - * This has the same semantics as the isLinkable method. - * - * @param string|object $parent parent path/document - * @param int|bool $limit limit or false for no limit - * @param string|bool $offset node name to which to skip to or false - * to not skip any elements - * @param string|null $filter child name filter - * @param bool|null $ignoreRole whether the role should be ignored or - * null if publish workflow should be - * ignored (defaults to false) - * @param string|null $class class name to filter on - * - * @return array - * - * @see isLinkable - */ - public function getLinkableChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null) - { - return $this->cmf->getLinkableChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); - } - - /** - * Check whether a document can be linked to, meaning the path() function - * should be usable. - * - * A document is linkable if it is either instance of - * Symfony\Component\Routing\Route or implements the - * RouteReferrersReadInterface and actually returns at least one route in - * getRoutes. - * - * This does not work for route names or other things some routers may - * support, only for objects. - * - * @param object $document - * - * @return bool true if it is possible to generate a link to $document - */ - public function isLinkable($document) - { - return $this->cmf->isLinkable($document); - } - - /** - * @param string|object $parent parent path/document - * @param int|null $depth null denotes no limit, depth of 1 means - * direct children only - * - * @return array - */ - public function getDescendants($parent, $depth = null) - { - return $this->cmf->getDescendants($parent, $depth); - } - - /** - * Gets the previous document. - * - * @param string|object $current document instance or path from which to search - * @param string|object|null $anchor document instance or path which serves as an anchor from which to flatten the hierarchy - * @param int|null $depth depth up to which to traverse down the tree when an anchor is provided - * @param bool $ignoreRole if to ignore the role - * @param string|null $class the class to filter by - * - * @return object|null - */ - public function getPrev($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null) - { - return $this->cmf->getPrev($current, $anchor, $depth, $ignoreRole, $class); - } - - /** - * Gets the next document. - * - * @param string|object $current document instance or path from which to search - * @param string|object|null $anchor document instance or path which serves as an anchor from which to flatten the hierarchy - * @param int|null $depth depth up to which to traverse down the tree when an anchor is provided - * @param bool $ignoreRole if to ignore the role - * @param string|null $class the class to filter by - * - * @return object|null - */ - public function getNext($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null) - { - return $this->cmf->getNext($current, $anchor, $depth, $ignoreRole, $class); - } - - /** - * Gets the previous linkable document. - * - * This has the same semantics as the isLinkable method. - * - * @param string|object $current Document instance or path from - * which to search - * @param string|object|null $anchor Document instance or path which - * serves as an anchor from which to - * flatten the hierarchy - * @param int|null $depth Depth up to which to traverse down - * the tree when an anchor is - * provided - * @param bool $ignoreRole Whether to ignore the role, - * - * @return object|null - * - * @see isLinkable - */ - public function getPrevLinkable($current, $anchor = null, $depth = null, $ignoreRole = false) - { - return $this->cmf->getPrevLinkable($current, $anchor, $depth, $ignoreRole); - } - - /** - * Gets the next linkable document. - * - * This has the same semantics as the isLinkable method. - * - * @param string|object $current Document instance or path from - * which to search - * @param string|object|null $anchor Document instance or path which - * serves as an anchor from which to - * flatten the hierarchy - * @param int|null $depth Depth up to which to traverse down - * the tree when an anchor is - * provided - * @param bool $ignoreRole Whether to ignore the role - * - * @return object|null - * - * @see isLinkable - */ - public function getNextLinkable($current, $anchor = null, $depth = null, $ignoreRole = false) - { - return $this->cmf->getNextLinkable($current, $anchor, $depth, $ignoreRole); - } -} diff --git a/src/Twig/Extension/CmfExtension.php b/src/Twig/Extension/CmfExtension.php index 3b2b69f..0e4b25c 100644 --- a/src/Twig/Extension/CmfExtension.php +++ b/src/Twig/Extension/CmfExtension.php @@ -18,19 +18,15 @@ class CmfExtension extends AbstractExtension { - protected $helper; - - public function __construct(Cmf $helper) - { - $this->helper = $helper; + public function __construct( + private Cmf $cmf + ) { } /** * Get list of available functions. - * - * @return array */ - public function getFunctions() + public function getFunctions(): array { $functions = [ new TwigFunction('cmf_is_published', [$this, 'isPublished']), @@ -60,92 +56,92 @@ public function getFunctions() return $functions; } - public function isPublished($document) + public function isPublished($document): bool { - return $this->helper->isPublished($document); + return $this->cmf->isPublished($document); } - public function isLinkable($document) + public function isLinkable($document): bool { - return $this->helper->isLinkable($document); + return $this->cmf->isLinkable($document); } - public function getChild($parent, $name) + public function getChild($parent, $name): object|bool|null { - return $this->helper->getChild($parent, $name); + return $this->cmf->getChild($parent, $name); } - public function getChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null) + public function getChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null): array { - return $this->helper->getChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); + return $this->cmf->getChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); } - public function getPrev($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null) + public function getPrev($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null): object|string|null { - return $this->helper->getPrev($current, $anchor, $depth, $ignoreRole, $class); + return $this->cmf->getPrev($current, $anchor, $depth, $ignoreRole, $class); } - public function getNext($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null) + public function getNext($current, $anchor = null, $depth = null, $ignoreRole = false, $class = null): object|string|null { - return $this->helper->getNext($current, $anchor, $depth, $ignoreRole, $class); + return $this->cmf->getNext($current, $anchor, $depth, $ignoreRole, $class); } public function find($path) { - return $this->helper->find($path); + return $this->cmf->find($path); } public function findTranslation($path, $locale, $fallback = true) { - return $this->helper->findTranslation($path, $locale, $fallback); + return $this->cmf->findTranslation($path, $locale, $fallback); } - public function findMany($paths = [], $limit = false, $offset = false, $ignoreRole = false, $class = null) + public function findMany($paths = [], $limit = false, $offset = false, $ignoreRole = false, $class = null): array { - return $this->helper->findMany($paths, $limit, $offset, $ignoreRole, $class); + return $this->cmf->findMany($paths, $limit, $offset, $ignoreRole, $class); } - public function getDescendants($parent, $depth = null) + public function getDescendants($parent, $depth = null): array { - return $this->helper->getDescendants($parent, $depth); + return $this->cmf->getDescendants($parent, $depth); } - public function getNodeName($document) + public function getNodeName($document): bool|string { - return $this->helper->getNodeName($document); + return $this->cmf->getNodeName($document); } - public function getParentPath($document) + public function getParentPath($document): bool|string { - return $this->helper->getParentPath($document); + return $this->cmf->getParentPath($document); } - public function getPath($document) + public function getPath($document): bool|string { - return $this->helper->getPath($document); + return $this->cmf->getPath($document); } - public function getLocalesFor($document, $includeFallbacks = false) + public function getLocalesFor($document, $includeFallbacks = false): array { - return $this->helper->getLocalesFor($document, $includeFallbacks); + return $this->cmf->getLocalesFor($document, $includeFallbacks); } - public function getPrevLinkable($current, $anchor = null, $depth = null, $ignoreRole = false) + public function getPrevLinkable($current, $anchor = null, $depth = null, $ignoreRole = false): object|string|null { - return $this->helper->getPrevLinkable($current, $anchor, $depth, $ignoreRole); + return $this->cmf->getPrevLinkable($current, $anchor, $depth, $ignoreRole); } - public function getNextLinkable($current, $anchor = null, $depth = null, $ignoreRole = false) + public function getNextLinkable($current, $anchor = null, $depth = null, $ignoreRole = false): object|string|null { - return $this->helper->getNextLinkable($current, $anchor, $depth, $ignoreRole); + return $this->cmf->getNextLinkable($current, $anchor, $depth, $ignoreRole); } - public function getLinkableChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null) + public function getLinkableChildren($parent, $limit = false, $offset = false, $filter = null, $ignoreRole = false, $class = null): array { - return $this->helper->getLinkableChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); + return $this->cmf->getLinkableChildren($parent, $limit, $offset, $filter, $ignoreRole, $class); } - public function getName() + public function getName(): string { return 'cmf'; } diff --git a/tests/Functional/Form/CheckboxUrlLabelFormTypeTest.php b/tests/Functional/Form/CheckboxUrlLabelFormTypeTest.php index 95330a9..5b94097 100644 --- a/tests/Functional/Form/CheckboxUrlLabelFormTypeTest.php +++ b/tests/Functional/Form/CheckboxUrlLabelFormTypeTest.php @@ -11,10 +11,6 @@ namespace Symfony\Cmf\Bundle\CoreBundle\Tests\Functional\Form; -use Symfony\Bridge\Twig\AppVariable; -use Symfony\Bridge\Twig\Command\DebugCommand; -use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Cmf\Bundle\CoreBundle\Form\Type\CheckboxUrlLabelFormType; use Symfony\Cmf\Bundle\CoreBundle\Tests\Fixtures\App\DataFixture\LoadRouteData; use Symfony\Cmf\Component\Testing\Functional\BaseTestCase; @@ -28,9 +24,9 @@ public function setUp(): void $this->db('PHPCR')->loadFixtures([LoadRouteData::class]); } - public function testFormTwigTemplate() + public function testFormTwigTemplate(): void { - $view = $this->getContainer()->get('test.service_container')->get('form.factory')->createNamedBuilder('name') + $view = self::getContainer()->get('test.service_container')->get('form.factory')->createNamedBuilder('name') ->add('terms', CheckboxUrlLabelFormType::class, [ 'label' => '%a% and %b% and %c%', 'routes' => [ @@ -46,33 +42,16 @@ public function testFormTwigTemplate() $this->assertMatchesXpath($template, '//label[@class="checkbox"][contains(.,"/a and /b and http://localhost/hello/world")]'); } - /** - * @return FormRenderer|TwigRenderer - */ - private function getFormRenderer() + private function getFormRenderer(): FormRenderer { - $twig = $this->getContainer()->get('test.service_container')->get('twig'); - - // BC for Symfony < 3.2 where this runtime does not exists - if (!method_exists(AppVariable::class, 'getToken')) { - $twig25 = !method_exists($twig, 'getRuntime'); - - $renderer = $twig->getExtension($twig25 ? 'form' : FormExtension::class)->renderer; - $renderer->setEnvironment($twig); - - return $renderer; - } - // BC for Symfony < 3.4 where runtime should be TwigRenderer - if (!method_exists(DebugCommand::class, 'getLoaderPaths')) { - $runtime = $twig->getRuntime(TwigRenderer::class); - - return $runtime; - } - - return $twig->getRuntime(FormRenderer::class); + return self::getContainer() + ->get('test.service_container') + ->get('twig') + ->getRuntime(FormRenderer::class) + ; } - protected function assertMatchesXpath($html, $expression, $count = 1) + protected function assertMatchesXpath($html, $expression, $count = 1): void { $dom = new \DOMDocument('UTF-8'); diff --git a/tests/Functional/PublishWorkflow/PublishWorkflowTest.php b/tests/Functional/PublishWorkflow/PublishWorkflowTest.php index c90acaf..351a0ec 100644 --- a/tests/Functional/PublishWorkflow/PublishWorkflowTest.php +++ b/tests/Functional/PublishWorkflow/PublishWorkflowTest.php @@ -40,7 +40,7 @@ public function setUp(): void public function testPublishable() { $doc = $this->createMock(PublishableReadInterface::class); - $doc->expects($this->any()) + $doc ->method('isPublishable') ->will($this->returnValue(true)) ; @@ -52,11 +52,11 @@ public function testPublishable() public function testPublishPeriod() { $doc = $this->createMock(PublishModel::class); - $doc->expects($this->any()) + $doc ->method('isPublishable') ->will($this->returnValue(true)) ; - $doc->expects($this->any()) + $doc ->method('getPublishEndDate') ->will($this->returnValue(new \DateTime('01/01/1980'))) ; @@ -68,7 +68,7 @@ public function testPublishPeriod() public function testIgnoreRoleHas() { $doc = $this->createMock(PublishModel::class); - $doc->expects($this->any()) + $doc ->method('isPublishable') ->will($this->returnValue(false)) ; @@ -85,7 +85,7 @@ public function testIgnoreRoleHas() public function testIgnoreRoleNotHas() { $doc = $this->createMock(PublishModel::class); - $doc->expects($this->any()) + $doc ->method('isPublishable') ->will($this->returnValue(false)) ; diff --git a/tests/Functional/Templating/Helper/CmfHierarchyTest.php b/tests/Functional/Templating/Helper/CmfHierarchyTest.php index a13409d..1c24d26 100644 --- a/tests/Functional/Templating/Helper/CmfHierarchyTest.php +++ b/tests/Functional/Templating/Helper/CmfHierarchyTest.php @@ -37,7 +37,7 @@ public function setUp(): void $dbManager->loadFixtures([LoadHierarchyRouteData::class]); $this->publishWorkflowChecker = $this->createMock(AuthorizationCheckerInterface::class); - $this->publishWorkflowChecker->expects($this->any()) + $this->publishWorkflowChecker ->method('isGranted') ->will($this->returnValue(true)) ; diff --git a/tests/Unit/DependencyInjection/CmfCoreExtensionTest.php b/tests/Unit/DependencyInjection/CmfCoreExtensionTest.php index b1f1a42..19e1bfb 100644 --- a/tests/Unit/DependencyInjection/CmfCoreExtensionTest.php +++ b/tests/Unit/DependencyInjection/CmfCoreExtensionTest.php @@ -23,17 +23,14 @@ class CmfCoreExtensionTest extends TestCase { - /** - * @var CmfCoreExtension - */ - protected $extension; + private CmfCoreExtension $extension; protected function setUp(): void { $this->extension = new CmfCoreExtension(); } - public function testPublishWorkflowAutoSupported() + public function testPublishWorkflowAutoSupported(): void { $container = $this->createContainer(['kernel.bundles' => ['SecurityBundle' => SecurityBundle::class]]); @@ -46,7 +43,7 @@ public function testPublishWorkflowAutoSupported() $this->assertFalse($container->hasDefinition('cmf_core.publish_workflow.request_listener')); } - public function testPublishWorkflowListenerEnabled() + public function testPublishWorkflowListenerEnabled(): void { $container = $this->createContainer(['kernel.bundles' => [ 'SecurityBundle' => SecurityBundle::class, @@ -62,7 +59,7 @@ public function testPublishWorkflowListenerEnabled() $this->assertTrue($container->hasDefinition('cmf_core.publish_workflow.request_listener')); } - public function testPublishWorkflowAutoNotSupported() + public function testPublishWorkflowAutoNotSupported(): void { $container = $this->createContainer(['kernel.bundles' => []]); @@ -76,7 +73,7 @@ public function testPublishWorkflowAutoNotSupported() $this->assertFalse($container->hasDefinition('cmf_core.publish_workflow.request_listener')); } - public function testPublishWorkflowFalse() + public function testPublishWorkflowFalse(): void { $container = $this->createContainer(['kernel.bundles' => [ 'SecurityBundle' => SecurityBundle::class, @@ -93,7 +90,7 @@ public function testPublishWorkflowFalse() $this->assertFalse($container->hasDefinition('cmf_core.publish_workflow.request_listener')); } - public function testPublishWorkflowTrueSupported() + public function testPublishWorkflowTrueSupported(): void { $container = $this->createContainer(['kernel.bundles' => [ 'SecurityBundle' => SecurityBundle::class, @@ -109,7 +106,7 @@ public function testPublishWorkflowTrueSupported() $this->assertTrue($container->hasDefinition('cmf_core.publish_workflow.request_listener')); } - public function testPublishWorkflowTrueNotSupported() + public function testPublishWorkflowTrueNotSupported(): void { $container = $this->createContainer(['kernel.bundles' => [ 'CmfRoutingBundle' => CmfRoutingBundle::class, @@ -119,7 +116,7 @@ public function testPublishWorkflowTrueNotSupported() $this->extension->load([['publish_workflow' => true]], $container); } - private function createContainer(array $parameters) + private function createContainer(array $parameters): ContainerBuilder { $parameters = array_merge(['kernel.debug' => false], $parameters); $container = new ContainerBuilder( diff --git a/tests/Unit/DependencyInjection/XmlSchemaTest.php b/tests/Unit/DependencyInjection/XmlSchemaTest.php index ca9c544..324f892 100644 --- a/tests/Unit/DependencyInjection/XmlSchemaTest.php +++ b/tests/Unit/DependencyInjection/XmlSchemaTest.php @@ -15,9 +15,9 @@ class XmlSchemaTest extends XmlSchemaTestCase { - public function testSchema() + public function testSchema(): void { - $xmlFiles = array_map(function ($file) { + $xmlFiles = array_map(static function ($file) { return __DIR__.'/../../Fixtures/config/'.$file; }, [ 'config1.xml', diff --git a/tests/Unit/Form/CheckboxUrlLabelFormTypeTest.php b/tests/Unit/Form/CheckboxUrlLabelFormTypeTest.php index 20248a3..b9df4b2 100644 --- a/tests/Unit/Form/CheckboxUrlLabelFormTypeTest.php +++ b/tests/Unit/Form/CheckboxUrlLabelFormTypeTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RouterInterface; class Router implements RouterInterface @@ -23,19 +24,20 @@ public function setContext(RequestContext $context) { } - public function getContext() + public function getContext(): RequestContext { } - public function match($pathinfo) + public function match($pathinfo): array { + return []; } - public function getRouteCollection() + public function getRouteCollection(): RouteCollection { } - public function generate($name, $parameters = [], $absolute = false) + public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string { return '/test/'.$name; } @@ -43,7 +45,7 @@ public function generate($name, $parameters = [], $absolute = false) class CheckboxUrlLabelFormTypeTest extends TypeTestCase { - public function testContentPathsAreSet() + public function testContentPathsAreSet(): void { $checkboxUrlLabelForm = $this->factory->create(CheckboxUrlLabelFormType::class, null, [ 'routes' => ['a' => ['name' => 'a'], 'b' => ['name' => 'b']], @@ -54,7 +56,7 @@ public function testContentPathsAreSet() $this->assertSame('/test/b', $view->vars['paths']['b']); } - protected function getExtensions() + protected function getExtensions(): array { return array_merge(parent::getExtensions(), [ new PreloadedExtension([ diff --git a/tests/Unit/PublishWorkflow/PublishWorkflowCheckerTest.php b/tests/Unit/PublishWorkflow/PublishWorkflowCheckerTest.php index 33fd2a4..9bb6e96 100644 --- a/tests/Unit/PublishWorkflow/PublishWorkflowCheckerTest.php +++ b/tests/Unit/PublishWorkflow/PublishWorkflowCheckerTest.php @@ -11,35 +11,36 @@ namespace Symfony\Cmf\Bundle\CoreBundle\Tests\Unit\PublishWorkflow; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishableReadInterface; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishWorkflowChecker; -use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class PublishWorkflowCheckerTest extends TestCase { - private $publishWorkflowChecker; + private PublishWorkflowChecker $publishWorkflowChecker; - private $role; + private string $role; - private $document; + private PublishableReadInterface&MockObject $document; - private $accessDecisionManager; + private AccessDecisionManagerInterface&MockObject $accessDecisionManager; - private $authorizationChecker; + private AuthorizationCheckerInterface&MockObject $authorizationChecker; - private $tokenStorage; + private TokenStorageInterface&MockObject $tokenStorage; public function setUp(): void { $this->role = 'IS_FOOBAR'; - $this->authorizationChecker = \Mockery::mock(AuthorizationCheckerInterface::class); - $this->tokenStorage = \Mockery::mock(TokenStorageInterface::class); - $this->document = \Mockery::mock(PublishableReadInterface::class); - $this->accessDecisionManager = \Mockery::mock(AccessDecisionManagerInterface::class); + $this->authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); + $this->tokenStorage = $this->createMock(TokenStorageInterface::class); + $this->document = $this->createMock(PublishableReadInterface::class); + $this->accessDecisionManager = $this->createMock(AccessDecisionManagerInterface::class); $this->publishWorkflowChecker = new PublishWorkflowChecker( $this->tokenStorage, @@ -54,58 +55,58 @@ protected function tearDown(): void \Mockery::close(); } - public function testIsGranted() + public function testIsGranted(): void { - $token = new AnonymousToken('', ''); - $this->tokenStorage->shouldReceive('getToken')->andReturn($token); + $token = $this->createMock(TokenInterface::class); + $this->tokenStorage->method('getToken')->willReturn($token); - $this->authorizationChecker->shouldNotReceive('isGranted'); + $this->authorizationChecker->expects($this->never())->method('isGranted'); $this->accessDecisionManager - ->shouldReceive('decide')->once() + ->expects($this->once()) + ->method('decide') ->with($token, [PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE], $this->document) - ->andReturn(true); + ->willReturn(true); $this->assertTrue($this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE, $this->document)); } - public function testNotHasBypassRole() + public function testNotHasBypassRole(): void { - $token = new AnonymousToken('', ''); - $this->tokenStorage->shouldReceive('getToken')->andReturn($token); + $token = $this->createMock(TokenInterface::class); + $this->tokenStorage->method('getToken')->willReturn($token); - $this->authorizationChecker->shouldReceive('isGranted')->once()->with($this->role)->andReturn(false); + $this->authorizationChecker->expects($this->once())->method('isGranted')->with($this->role)->willReturn(false); - $this->accessDecisionManager - ->shouldReceive('decide')->once() + $this->accessDecisionManager->expects($this->once()) + ->method('decide') ->with($token, [PublishWorkflowChecker::VIEW_ATTRIBUTE], $this->document) - ->andReturn(true); + ->willReturn(true); $this->assertTrue($this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ATTRIBUTE, $this->document)); } - public function testHasBypassRole() + public function testHasBypassRole(): void { - $token = new AnonymousToken('', ''); - $this->tokenStorage->shouldReceive('getToken')->andReturn($token); + $token = $this->createMock(TokenInterface::class); + $this->tokenStorage->method('getToken')->willReturn($token); - $this->authorizationChecker->shouldReceive('isGranted')->once()->with($this->role)->andReturn(true); + $this->authorizationChecker->expects($this->once())->method('isGranted')->with($this->role)->willReturn(true); - $this->accessDecisionManager->shouldNotReceive('decide'); + $this->accessDecisionManager->expects($this->never())->method('decide'); $this->assertTrue($this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ATTRIBUTE, $this->document)); } - public function testNoFirewall() + public function testNoFirewall(): void { - $this->tokenStorage->shouldReceive('getToken')->andReturnNull(); + $this->tokenStorage->method('getToken')->willReturn(null); - $this->authorizationChecker->shouldNotReceive('isGranted'); + $this->authorizationChecker->expects($this->never())->method('isGranted'); - $this->accessDecisionManager - ->shouldReceive('decide')->once() - ->with(\Mockery::type(AnonymousToken::class), [PublishWorkflowChecker::VIEW_ATTRIBUTE], $this->document) - ->andReturn(true); + $this->accessDecisionManager->expects($this->once()) + ->method('decide') + ->willReturn(true); $this->assertTrue($this->publishWorkflowChecker->isGranted(PublishWorkflowChecker::VIEW_ATTRIBUTE, $this->document)); } diff --git a/tests/Unit/PublishWorkflow/Voter/PublishTimePeriodVoterTest.php b/tests/Unit/PublishWorkflow/Voter/PublishTimePeriodVoterTest.php index 5e4f375..f27d113 100644 --- a/tests/Unit/PublishWorkflow/Voter/PublishTimePeriodVoterTest.php +++ b/tests/Unit/PublishWorkflow/Voter/PublishTimePeriodVoterTest.php @@ -11,36 +11,28 @@ namespace Symfony\Cmf\Bundle\CoreBundle\Tests\Unit\PublishWorkflow\Voter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishTimePeriodReadInterface; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishWorkflowChecker; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\Voter\PublishTimePeriodVoter; -use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Authorization\Voter\CacheableVoterInterface; -use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use function is_subclass_of; class PublishTimePeriodVoterTest extends TestCase { - /** - * @var PublishTimePeriodVoter - */ - private $voter; + private PublishTimePeriodVoter $voter; - /** - * @var TokenInterface - */ - private $token; + private TokenInterface&MockObject $token; public function setUp(): void { $this->voter = new PublishTimePeriodVoter(); - $this->token = new AnonymousToken('', ''); + $this->token = $this->createMock(TokenInterface::class); } - public function providePublishWorkflowChecker() + public function providePublishWorkflowChecker(): array { return [ [ @@ -104,19 +96,19 @@ public function providePublishWorkflowChecker() /** * @dataProvider providePublishWorkflowChecker */ - public function testPublishWorkflowChecker($expected, $startDate, $endDate, $attributes = PublishWorkflowChecker::VIEW_ATTRIBUTE, $currentTime = false) + public function testPublishWorkflowChecker(int $expected, ?\DateTimeInterface $startDate, ?\DateTimeInterface $endDate, array|string $attributes = PublishWorkflowChecker::VIEW_ATTRIBUTE, \DateTimeInterface|false $currentTime = false): void { $attributes = (array) $attributes; $doc = $this->createMock(PublishTimePeriodReadInterface::class); - $doc->expects($this->any()) + $doc ->method('getPublishStartDate') - ->will($this->returnValue($startDate)) + ->willReturn($startDate) ; - $doc->expects($this->any()) + $doc ->method('getPublishEndDate') - ->will($this->returnValue($endDate)) + ->willReturn($endDate) ; if (false !== $currentTime) { @@ -126,7 +118,7 @@ public function testPublishWorkflowChecker($expected, $startDate, $endDate, $att $this->assertEquals($expected, $this->voter->vote($this->token, $doc, $attributes)); } - public function testUnsupportedClass() + public function testUnsupportedClass(): void { $result = $this->voter->vote( $this->token, @@ -136,35 +128,21 @@ public function testUnsupportedClass() $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $result); } - public function testNonClassSubject() + public function testNonClassSubject(): void { $result = $this->voter->vote($this->token, [1, 2, 3], [PublishWorkflowChecker::VIEW_ATTRIBUTE]); $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $result); } - public function testCachableVoterSupportsAttributes() + public function testCachableVoterSupportsAttributes(): void { - if (!$this->voter instanceof CacheableVoterInterface) { - $this->assertFalse( - is_subclass_of(Voter::class, CacheableVoterInterface::class), - 'Voter cache is supported and expected to be implemented' - ); - } - $this->assertTrue($this->voter->supportsAttribute(PublishWorkflowChecker::VIEW_ATTRIBUTE)); $this->assertTrue($this->voter->supportsAttribute(PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE)); $this->assertFalse($this->voter->supportsAttribute('other')); } - public function testCachableVoterSupportsSubjectType() + public function testCachableVoterSupportsSubjectType(): void { - if (!$this->voter instanceof CacheableVoterInterface) { - $this->assertFalse( - is_subclass_of(Voter::class, CacheableVoterInterface::class), - 'Voter cache is supported and expected to be implemented' - ); - } - $doc = $this->createMock(PublishTimePeriodReadInterface::class); $this->assertTrue($this->voter->supportsType(\get_class($doc))); $this->assertFalse($this->voter->supportsType(static::class)); diff --git a/tests/Unit/PublishWorkflow/Voter/PublishableVoterTest.php b/tests/Unit/PublishWorkflow/Voter/PublishableVoterTest.php index 26e9eef..aca88b5 100644 --- a/tests/Unit/PublishWorkflow/Voter/PublishableVoterTest.php +++ b/tests/Unit/PublishWorkflow/Voter/PublishableVoterTest.php @@ -11,11 +11,11 @@ namespace Symfony\Cmf\Bundle\CoreBundle\Tests\Unit\PublishWorkflow\Voter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishableReadInterface; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishWorkflowChecker; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\Voter\PublishableVoter; -use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\CacheableVoterInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; @@ -24,23 +24,17 @@ class PublishableVoterTest extends TestCase { - /** - * @var PublishableVoter - */ - private $voter; + private PublishableVoter $voter; - /** - * @var TokenInterface - */ - private $token; + private TokenInterface&MockObject $token; public function setUp(): void { $this->voter = new PublishableVoter(); - $this->token = new AnonymousToken('', ''); + $this->token = $this->createMock(TokenInterface::class); } - public function providePublishWorkflowChecker() + public function providePublishWorkflowChecker(): array { return [ [ @@ -84,19 +78,19 @@ public function providePublishWorkflowChecker() * * use for voters! */ - public function testPublishWorkflowChecker($expected, $isPublishable, $attributes) + public function testPublishWorkflowChecker(int $expected, bool $isPublishable, array|string $attributes): void { $attributes = (array) $attributes; $doc = $this->createMock(PublishableReadInterface::class); - $doc->expects($this->any()) + $doc ->method('isPublishable') - ->will($this->returnValue($isPublishable)) + ->willReturn($isPublishable) ; $this->assertEquals($expected, $this->voter->vote($this->token, $doc, $attributes)); } - public function testUnsupportedClass() + public function testUnsupportedClass(): void { $result = $this->voter->vote( $this->token, @@ -106,35 +100,21 @@ public function testUnsupportedClass() $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $result); } - public function testNonClassSubject() + public function testNonClassSubject(): void { $result = $this->voter->vote($this->token, [1, 2, 3], [PublishWorkflowChecker::VIEW_ATTRIBUTE]); $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $result); } - public function testCachableVoterSupportsAttributes() + public function testCachableVoterSupportsAttributes(): void { - if (!$this->voter instanceof CacheableVoterInterface) { - $this->assertFalse( - is_subclass_of(Voter::class, CacheableVoterInterface::class), - 'Voter cache is supported and expected to be implemented' - ); - } - $this->assertTrue($this->voter->supportsAttribute(PublishWorkflowChecker::VIEW_ATTRIBUTE)); $this->assertTrue($this->voter->supportsAttribute(PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE)); $this->assertFalse($this->voter->supportsAttribute('other')); } - public function testCachableVoterSupportsSubjectType() + public function testCachableVoterSupportsSubjectType(): void { - if (!$this->voter instanceof CacheableVoterInterface) { - $this->assertFalse( - is_subclass_of(Voter::class, CacheableVoterInterface::class), - 'Voter cache is supported and expected to be implemented' - ); - } - $doc = $this->createMock(PublishableReadInterface::class); $this->assertTrue($this->voter->supportsType(\get_class($doc))); $this->assertFalse($this->voter->supportsType(static::class)); diff --git a/tests/Unit/Templating/Helper/CmfTest.php b/tests/Unit/Templating/Helper/CmfTest.php index 243e2b2..2722b05 100644 --- a/tests/Unit/Templating/Helper/CmfTest.php +++ b/tests/Unit/Templating/Helper/CmfTest.php @@ -14,6 +14,7 @@ use Doctrine\ODM\PHPCR\DocumentManager; use Doctrine\ODM\PHPCR\UnitOfWork; use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Cmf\Bundle\CoreBundle\PublishWorkflow\PublishWorkflowChecker; use Symfony\Cmf\Bundle\CoreBundle\Templating\Helper\Cmf; @@ -24,18 +25,15 @@ class CmfTest extends TestCase { - private $pwc; + private AuthorizationCheckerInterface&MockObject $pwc; - private $managerRegistry; + private ManagerRegistry&MockObject $managerRegistry; - private $manager; + private DocumentManager&MockObject $manager; - private $uow; + private UnitOfWork&MockObject $uow; - /** - * @var Cmf - */ - private $helper; + private Cmf $helper; public function setUp(): void { @@ -45,25 +43,25 @@ public function setUp(): void $this->manager = $this->createMock(DocumentManager::class); - $this->managerRegistry->expects($this->any()) + $this->managerRegistry ->method('getManager') ->with('foo') - ->will($this->returnValue($this->manager)) + ->willReturn($this->manager) ; $this->uow = $this->createMock(UnitOfWork::class); - $this->manager->expects($this->any()) + $this->manager ->method('getUnitOfWork') ->with() - ->will($this->returnValue($this->uow)) + ->willReturn($this->uow) ; $this->helper = new Cmf($this->pwc); $this->helper->setDoctrineRegistry($this->managerRegistry, 'foo'); } - public function testGetNodeName() + public function testGetNodeName(): void { $document = new \stdClass(); @@ -77,37 +75,58 @@ public function testGetNodeName() $this->assertEquals('bar', $this->helper->getNodeName($document)); } - public function testGetParentPath() + public function testGetParentPath(): void { $document = new \stdClass(); - $this->assertFalse($this->helper->getParentPath($document)); - $this->uow->expects($this->once()) ->method('getDocumentId') ->with($document) - ->will($this->returnValue('/foo/bar')) + ->willReturn('/foo/bar') ; $this->assertEquals('/foo', $this->helper->getParentPath($document)); } - public function testGetPath() + public function testGetParentPathNotManaged(): void { $document = new \stdClass(); - $this->assertNull($this->helper->getPath($document)); + $this->uow->expects($this->once()) + ->method('getDocumentId') + ->with($document) + ->willThrowException(new \Exception()) + ; + + $this->assertFalse($this->helper->getParentPath($document)); + } + + public function testGetPath(): void + { + $document = new \stdClass(); $this->uow->expects($this->once()) ->method('getDocumentId') ->with($document) - ->will($this->returnValue('/foo/bar')) + ->willReturn('/foo/bar') ; $this->assertEquals('/foo/bar', $this->helper->getPath($document)); } - public function testGetPathInvalid() + public function testGetPathNotManaged(): void + { + $document = new \stdClass(); + + $this->uow->expects($this->once()) + ->method('getDocumentId') + ->with($document) + ->willThrowException(new \Exception()) + ; + $this->assertFalse($this->helper->getPath($document)); + } + + public function testGetPathInvalid(): void { $document = new \stdClass(); @@ -119,64 +138,64 @@ public function testGetPathInvalid() $this->assertFalse($this->helper->getPath($document)); } - public function testFind() + public function testFind(): void { $document = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->with(null, '/foo') - ->will($this->onConsecutiveCalls(null, $document)) + ->willReturnOnConsecutiveCalls(null, $document) ; $this->assertNull($this->helper->find('/foo')); $this->assertEquals($document, $this->helper->find('/foo')); } - public function testFindTranslation() + public function testFindTranslation(): void { $document = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('findTranslation') ->with(null, '/foo', 'en') - ->will($this->onConsecutiveCalls(null, $document, 'en')) + ->willReturnOnConsecutiveCalls(null, $document, 'en') ; $this->assertNull($this->helper->findTranslation('/foo', 'en')); $this->assertEquals($document, $this->helper->findTranslation('/foo', 'en')); } - public function testFindMany() + public function testFindMany(): void { $this->assertEquals([], $this->helper->findMany()); } - public function testFindManyFilterClass() + public function testFindManyFilterClass(): void { $documentA = new \stdClass(); $documentB = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') - ->will($this->onConsecutiveCalls($documentA, null, $documentA, $documentB)) + ->willReturnOnConsecutiveCalls($documentA, null, $documentA, $documentB) ; $this->assertEquals([], $this->helper->findMany(['/foo', 'bar'], false, false, null, 'Exception')); $this->assertEquals([$documentA, $documentB], $this->helper->findMany(['/foo', 'bar'], false, false, null, 'stdClass')); } - public function testFindManyIgnoreRole() + public function testFindManyIgnoreRole(): void { $documentA = new \stdClass(); $documentB = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->will($this->onConsecutiveCalls($documentA, $documentB)) ; - $this->pwc->expects($this->any()) + $this->pwc ->method('isGranted') ->will($this->onConsecutiveCalls(false, true)) ; @@ -184,12 +203,12 @@ public function testFindManyIgnoreRole() $this->assertEquals([$documentB], $this->helper->findMany(['/foo', '/bar'], false, false, true)); } - public function testFindManyIgnoreWorkflow() + public function testFindManyIgnoreWorkflow(): void { $documentA = new \stdClass(); $documentB = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->will($this->onConsecutiveCalls($documentA, $documentB)) ; @@ -201,12 +220,12 @@ public function testFindManyIgnoreWorkflow() $this->assertEquals([$documentA, $documentB], $this->helper->findMany(['/foo', '/bar'], false, false, null)); } - public function testFindManyLimitOffset() + public function testFindManyLimitOffset(): void { $documentA = new \stdClass(); $documentB = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->will($this->onConsecutiveCalls($documentA, $documentB, $documentA, $documentB, $documentA, $documentB)) ; @@ -216,30 +235,30 @@ public function testFindManyLimitOffset() $this->assertEquals([$documentB], $this->helper->findMany(['/foo', 'bar'], 1, 1, null)); } - public function testFindManyNoWorkflow() + public function testFindManyNoWorkflow(): void { $extension = new Cmf(null); $extension->setDoctrineRegistry($this->managerRegistry, 'foo'); $documentA = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->with(null, '/foo') - ->will($this->returnValue($documentA)) + ->willReturn($documentA) ; $this->expectException(InvalidConfigurationException::class); $extension->findMany(['/foo', '/bar'], false, false); } - public function testIsPublished() + public function testIsPublished(): void { $this->assertFalse($this->helper->isPublished(null)); $document = new \stdClass(); - $this->pwc->expects($this->any()) + $this->pwc ->method('isGranted') ->with(PublishWorkflowChecker::VIEW_ANONYMOUS_ATTRIBUTE, $document) ->will($this->onConsecutiveCalls(false, true)) @@ -249,7 +268,7 @@ public function testIsPublished() $this->assertTrue($this->helper->isPublished($document)); } - public function testIsPublishedNoWorkflow() + public function testIsPublishedNoWorkflow(): void { $extension = new Cmf(null); $extension->setDoctrineRegistry($this->managerRegistry, 'foo'); @@ -258,7 +277,7 @@ public function testIsPublishedNoWorkflow() $extension->isPublished(new \stdClass()); } - public function testIsLinkable() + public function testIsLinkable(): void { $this->assertFalse($this->helper->isLinkable(null)); $this->assertFalse($this->helper->isLinkable('a')); @@ -268,7 +287,7 @@ public function testIsLinkable() $content ->expects($this->once()) ->method('getRoutes') - ->will($this->returnValue([])) + ->willReturn([]) ; $this->assertFalse($this->helper->isLinkable($content)); @@ -277,18 +296,18 @@ public function testIsLinkable() $content ->expects($this->once()) ->method('getRoutes') - ->will($this->returnValue([$route])) + ->willReturn([$route]) ; $this->assertTrue($this->helper->isLinkable($content)); } - public function testGetLocalesFor() + public function testGetLocalesFor(): void { $this->assertEquals([], $this->helper->getLocalesFor(null)); $document = new \stdClass(); - $this->manager->expects($this->any()) + $this->manager ->method('find') ->with(null, '/foo') ->will($this->onConsecutiveCalls(null, $document)) @@ -299,18 +318,18 @@ public function testGetLocalesFor() $this->manager->expects($this->once()) ->method('getLocalesFor') ->with($document) - ->will($this->returnValue(['en', 'de'])) + ->willReturn(['en', 'de']) ; $this->assertEquals(['en', 'de'], $this->helper->getLocalesFor('/foo')); } - public function testGetLocalesForMissingTranslationException() + public function testGetLocalesForMissingTranslationException(): void { $this->markTestIncomplete('TODO: write test'); } - public function testGetChild() + public function testGetChild(): void { $parent = new \stdClass(); @@ -321,52 +340,52 @@ public function testGetChild() $this->uow->expects($this->once()) ->method('getDocumentId') ->with($parent) - ->will($this->returnValue('/foo')) + ->willReturn('/foo') ; $this->manager->expects($this->once()) ->method('find') ->with(null, '/foo/bar') - ->will($this->returnValue($child)) + ->willReturn($child) ; $this->assertEquals($child, $this->helper->getChild($parent, 'bar')); } - public function testGetChildError() + public function testGetChildError(): void { $parent = new \stdClass(); $this->uow->expects($this->once()) ->method('getDocumentId') ->with($parent) - ->will($this->throwException(new \Exception('test'))) + ->willThrowException(new \Exception('test')) ; $this->assertFalse($this->helper->getChild($parent, 'bar')); } - public function testGetChildren() + public function testGetChildren(): void { $this->markTestIncomplete('TODO: write test'); } - public function testGetChildrenFilterClass() + public function testGetChildrenFilterClass(): void { $this->markTestIncomplete('TODO: write test'); } - public function testGetChildrenIgnoreRole() + public function testGetChildrenIgnoreRole(): void { $this->markTestIncomplete('TODO: write test'); } - public function testGetChildrenLimitOffset() + public function testGetChildrenLimitOffset(): void { $this->markTestIncomplete('TODO: write test'); } - public function testGetLinkableChildren() + public function testGetLinkableChildren(): void { $this->assertEquals([], $this->helper->getLinkableChildren(null)); diff --git a/tests/Unit/Twig/Extension/CmfExtensionTest.php b/tests/Unit/Twig/Extension/CmfExtensionTest.php index 490fa33..7743f8a 100644 --- a/tests/Unit/Twig/Extension/CmfExtensionTest.php +++ b/tests/Unit/Twig/Extension/CmfExtensionTest.php @@ -20,20 +20,9 @@ class CmfExtensionTest extends TestCase { - /** - * @var Cmf&MockObject - */ - private $cmfHelper; - - /** - * @var Environment - */ - private $env; - - /** - * @var CmfExtension - */ - private $cmfExtension; + private Cmf&MockObject $cmfHelper; + private Environment $env; + private CmfExtension $cmfExtension; public function setUp(): void { @@ -47,7 +36,7 @@ public function setUp(): void /** * @dataProvider getFunctionsData */ - public function testFunctions($methodName, array $methodArguments, $helperMethod = null, array $helperArguments = []) + public function testFunctions($methodName, array $methodArguments, $helperMethod = null, array $helperArguments = []): void { if (null === $helperMethod) { $helperMethod = $methodName; @@ -62,7 +51,7 @@ public function testFunctions($methodName, array $methodArguments, $helperMethod \call_user_func_array([$this->cmfExtension, $methodName], $methodArguments); } - public function getFunctionsData() + public function getFunctionsData(): array { return [ ['isPublished', ['document1']],