From c08593d429e76f6e32bcd2c2891d5ed7b8cf12e1 Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Mon, 26 Jun 2023 11:39:43 +0200 Subject: [PATCH] chore: Removed deprecated UniqueEntity constraint fron roadiz --- lib/RoadizCompatBundle/src/Aliases.php | 2 - .../src/Controller/Controller.php | 5 +- .../src/Console/InstallCommand.php | 30 ++- .../NodesSourcesEntitiesPathCompilerPass.php | 3 + .../DocumentMessageDispatchSubscriber.php | 19 +- .../DocumentPdfMessageHandler.php | 9 + lib/RoadizCoreBundle/src/Entity/Node.php | 12 +- lib/RoadizCoreBundle/src/Entity/Theme.php | 15 +- .../src/Form/Constraint/UniqueEntity.php | 42 ----- .../Form/Constraint/UniqueEntityValidator.php | 171 ------------------ .../ApplyRealmNodeInheritanceMessage.php | 14 +- .../CleanRealmNodeInheritanceMessage.php | 14 +- .../src/Message/DeleteNodeTypeMessage.php | 10 +- .../Message/PurgeReverseProxyCacheMessage.php | 10 +- .../SearchRealmNodeInheritanceMessage.php | 8 +- .../Message/UpdateNodeTypeSchemaMessage.php | 10 +- lib/RoadizCoreBundle/src/Node/NodeMover.php | 1 + .../AjaxControllers/AjaxNodesController.php | 4 +- .../Documents/DocumentsController.php | 20 +- .../NodeTypes/NodeTypesUtilsController.php | 11 ++ .../src/Controllers/Nodes/NodesController.php | 2 +- .../Nodes/NodesSourcesController.php | 6 +- .../Controllers/Nodes/TranstypeController.php | 6 +- .../src/Controllers/RolesUtilsController.php | 3 + .../src/Controllers/SearchController.php | 6 +- .../Controllers/SettingsUtilsController.php | 4 + .../src/Controllers/Tags/TagsController.php | 6 +- .../src/Explorer/ConfigurableExplorerItem.php | 31 ++-- .../src/Explorer/FolderExplorerItem.php | 8 +- .../Forms/NodeSource/NodeSourceJoinType.php | 15 +- .../NodeSource/NodeSourceProviderType.php | 4 +- lib/Rozier/src/RozierApp.php | 9 +- 32 files changed, 196 insertions(+), 314 deletions(-) delete mode 100644 lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntity.php delete mode 100644 lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntityValidator.php diff --git a/lib/RoadizCompatBundle/src/Aliases.php b/lib/RoadizCompatBundle/src/Aliases.php index a8254486..c26a8346 100644 --- a/lib/RoadizCompatBundle/src/Aliases.php +++ b/lib/RoadizCompatBundle/src/Aliases.php @@ -169,8 +169,6 @@ public static function getAliases(): array \RZ\Roadiz\CoreBundle\Form\Constraint\RecaptchaValidator::class => \RZ\Roadiz\CMS\Forms\Constraints\RecaptchaValidator::class, \RZ\Roadiz\CoreBundle\Form\Constraint\SimpleLatinString::class => \RZ\Roadiz\CMS\Forms\Constraints\SimpleLatinString::class, \RZ\Roadiz\CoreBundle\Form\Constraint\SimpleLatinStringValidator::class => \RZ\Roadiz\CMS\Forms\Constraints\SimpleLatinStringValidator::class, - \RZ\Roadiz\CoreBundle\Form\Constraint\UniqueEntity::class => \RZ\Roadiz\CMS\Forms\Constraints\UniqueEntity::class, - \RZ\Roadiz\CoreBundle\Form\Constraint\UniqueEntityValidator::class => \RZ\Roadiz\CMS\Forms\Constraints\UniqueEntityValidator::class, \RZ\Roadiz\CoreBundle\Form\Constraint\UniqueFilename::class => \RZ\Roadiz\CMS\Forms\Constraints\UniqueFilename::class, \RZ\Roadiz\CoreBundle\Form\Constraint\UniqueFilenameValidator::class => \RZ\Roadiz\CMS\Forms\Constraints\UniqueFilenameValidator::class, \RZ\Roadiz\CoreBundle\Form\Constraint\UniqueNodeName::class => \RZ\Roadiz\CMS\Forms\Constraints\UniqueNodeName::class, diff --git a/lib/RoadizCompatBundle/src/Controller/Controller.php b/lib/RoadizCompatBundle/src/Controller/Controller.php index 6f71b04e..1bd34e00 100644 --- a/lib/RoadizCompatBundle/src/Controller/Controller.php +++ b/lib/RoadizCompatBundle/src/Controller/Controller.php @@ -191,8 +191,9 @@ protected function getPreviewResolver(): PreviewResolverInterface } /** - * @param object $event - * @return object The passed $event MUST be returned + * @template T of object + * @param T $event + * @return T The passed $event MUST be returned */ protected function dispatchEvent($event) { diff --git a/lib/RoadizCoreBundle/src/Console/InstallCommand.php b/lib/RoadizCoreBundle/src/Console/InstallCommand.php index 0e21d59e..8a1d32f0 100644 --- a/lib/RoadizCoreBundle/src/Console/InstallCommand.php +++ b/lib/RoadizCoreBundle/src/Console/InstallCommand.php @@ -70,26 +70,48 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->askQuestion($question) ) { $fixturesRoot = dirname(__DIR__) . '/../config'; - $data = Yaml::parse(file_get_contents($fixturesRoot . "/fixtures.yaml")); + $fixtureFile = file_get_contents($fixturesRoot . "/fixtures.yaml"); + + if (false === $fixtureFile) { + $io->error('No fixtures.yaml file found in ' . $fixturesRoot); + return 1; + } + + $data = Yaml::parse($fixtureFile); if (isset($data["importFiles"]['roles'])) { foreach ($data["importFiles"]['roles'] as $filename) { $filePath = $fixturesRoot . "/" . $filename; - $this->rolesImporter->import(file_get_contents($filePath)); + $fileContents = file_get_contents($filePath); + if (false === $fileContents) { + $io->error('No file found in ' . $filePath); + return 1; + } + $this->rolesImporter->import($fileContents); $io->success('Theme file “' . $filePath . '” has been imported.'); } } if (isset($data["importFiles"]['groups'])) { foreach ($data["importFiles"]['groups'] as $filename) { $filePath = $fixturesRoot . "/" . $filename; - $this->groupsImporter->import(file_get_contents($filePath)); + $fileContents = file_get_contents($filePath); + if (false === $fileContents) { + $io->error('No file found in ' . $filePath); + return 1; + } + $this->groupsImporter->import($fileContents); $io->success('Theme file “' . $filePath . '” has been imported.'); } } if (isset($data["importFiles"]['settings'])) { foreach ($data["importFiles"]['settings'] as $filename) { $filePath = $fixturesRoot . "/" . $filename; - $this->settingsImporter->import(file_get_contents($filePath)); + $fileContents = file_get_contents($filePath); + if (false === $fileContents) { + $io->error('No file found in ' . $filePath); + return 1; + } + $this->settingsImporter->import($fileContents); $io->success('Theme files “' . $filePath . '” has been imported.'); } } diff --git a/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/NodesSourcesEntitiesPathCompilerPass.php b/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/NodesSourcesEntitiesPathCompilerPass.php index d771a7ca..037afe46 100644 --- a/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/NodesSourcesEntitiesPathCompilerPass.php +++ b/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/NodesSourcesEntitiesPathCompilerPass.php @@ -15,6 +15,9 @@ class NodesSourcesEntitiesPathCompilerPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $projectDir = $container->getParameter('kernel.project_dir'); + if (!\is_string($projectDir)) { + throw new \RuntimeException('kernel.project_dir parameter must be a string.'); + } $container->setParameter('roadiz_core.generated_entities_dir', $projectDir . '/src/GeneratedEntity'); $container->setParameter('roadiz_core.serialized_node_types_dir', $projectDir . '/src/Resources/node-types'); $container->setParameter('roadiz_core.import_files_config_path', $projectDir . '/src/Resources/config.yml'); diff --git a/lib/RoadizCoreBundle/src/Document/EventSubscriber/DocumentMessageDispatchSubscriber.php b/lib/RoadizCoreBundle/src/Document/EventSubscriber/DocumentMessageDispatchSubscriber.php index 6abfdccf..8dfb1350 100644 --- a/lib/RoadizCoreBundle/src/Document/EventSubscriber/DocumentMessageDispatchSubscriber.php +++ b/lib/RoadizCoreBundle/src/Document/EventSubscriber/DocumentMessageDispatchSubscriber.php @@ -49,18 +49,19 @@ public function onFilterDocumentEvent(FilterDocumentEvent $event): void $document = $event->getDocument(); if ( $document instanceof Document && - null !== $document->getId() && + \is_numeric($document->getId()) && $document->isLocal() && null !== $document->getRelativePath() ) { - $this->bus->dispatch(new Envelope(new DocumentRawMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentFilesizeMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentSizeMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentAverageColorMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentExifMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentSvgMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentAudioVideoMessage($document->getId()))); - $this->bus->dispatch(new Envelope(new DocumentPdfMessage($document->getId()))); + $id = (int) $document->getId(); + $this->bus->dispatch(new Envelope(new DocumentRawMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentFilesizeMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentSizeMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentAverageColorMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentExifMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentSvgMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentAudioVideoMessage($id))); + $this->bus->dispatch(new Envelope(new DocumentPdfMessage($id))); } } } diff --git a/lib/RoadizCoreBundle/src/Document/MessageHandler/DocumentPdfMessageHandler.php b/lib/RoadizCoreBundle/src/Document/MessageHandler/DocumentPdfMessageHandler.php index 1a8340e3..292de562 100644 --- a/lib/RoadizCoreBundle/src/Document/MessageHandler/DocumentPdfMessageHandler.php +++ b/lib/RoadizCoreBundle/src/Document/MessageHandler/DocumentPdfMessageHandler.php @@ -51,12 +51,18 @@ protected function processMessage(AbstractDocumentMessage $message, DocumentInte * This process requires document files to be locally stored! */ $pdfPath = \tempnam(\sys_get_temp_dir(), 'pdf_'); + if (false === $pdfPath) { + throw new UnrecoverableMessageHandlingException('Cannot create temporary file for PDF thumbnail.'); + } \rename($pdfPath, $pdfPath .= $document->getFilename()); /* * Copy AV locally */ $pdfPathResource = \fopen($pdfPath, 'w'); + if (false === $pdfPathResource) { + throw new UnrecoverableMessageHandlingException('Cannot open temporary file for PDF thumbnail.'); + } \stream_copy_to_stream($this->documentsStorage->readStream($document->getMountPath()), $pdfPathResource); \fclose($pdfPathResource); @@ -75,6 +81,9 @@ protected function extractPdfThumbnail(DocumentInterface $document, string $loca } $thumbnailPath = \tempnam(\sys_get_temp_dir(), 'thumbnail_'); + if (false === $thumbnailPath) { + throw new UnrecoverableMessageHandlingException('Cannot create temporary file for PDF thumbnail.'); + } \rename($thumbnailPath, $thumbnailPath .= $document->getFilename() . '.jpg'); try { diff --git a/lib/RoadizCoreBundle/src/Entity/Node.php b/lib/RoadizCoreBundle/src/Entity/Node.php index bc0ec444..f2aef9b4 100644 --- a/lib/RoadizCoreBundle/src/Entity/Node.php +++ b/lib/RoadizCoreBundle/src/Entity/Node.php @@ -931,11 +931,19 @@ public function setVisible(bool $visible): Node #[SymfonySerializer\Ignore] public function getOneLineSourceSummary(): string { - $text = "Source " . $this->getNodeSources()->first()->getId() . PHP_EOL; + $text = "Source " . + ( + $this->getNodeSources()->first() ? + $this->getNodeSources()->first()->getId() : + '' + ) . + PHP_EOL; foreach ($this->getNodeType()->getFields() as $field) { $getterName = $field->getGetterName(); - $text .= '[' . $field->getLabel() . ']: ' . $this->getNodeSources()->first()->$getterName() . PHP_EOL; + $text .= '[' . $field->getLabel() . ']: ' . + ($this->getNodeSources()->first() ? $this->getNodeSources()->first()->$getterName() : '') . + PHP_EOL; } return $text; diff --git a/lib/RoadizCoreBundle/src/Entity/Theme.php b/lib/RoadizCoreBundle/src/Entity/Theme.php index 86807262..61ad9e64 100644 --- a/lib/RoadizCoreBundle/src/Entity/Theme.php +++ b/lib/RoadizCoreBundle/src/Entity/Theme.php @@ -4,6 +4,7 @@ namespace RZ\Roadiz\CoreBundle\Entity; +use RZ\Roadiz\CompatBundle\Controller\AppController; use RZ\Roadiz\Core\AbstractEntities\AbstractEntity; /** @@ -88,12 +89,16 @@ public function getInformations(): array if (class_exists($class)) { $reflector = new \ReflectionClass($class); - if ($reflector->isSubclassOf('\\RZ\\Roadiz\\CMS\\Controllers\\AppController')) { + if ($reflector->isSubclassOf(AppController::class)) { + $nameCallable = [$class, 'getThemeName']; + $authorCallable = [$class, 'getThemeAuthor']; + $copyrightCallable = [$class, 'getThemeCopyright']; + $dirCallable = [$class, 'getThemeDir']; return [ - 'name' => call_user_func([$class, 'getThemeName']), - 'author' => call_user_func([$class, 'getThemeAuthor']), - 'copyright' => call_user_func([$class, 'getThemeCopyright']), - 'dir' => call_user_func([$class, 'getThemeDir']) + 'name' => \is_callable($nameCallable) ? call_user_func($nameCallable) : null, + 'author' => \is_callable($authorCallable) ? call_user_func($authorCallable) : null, + 'copyright' => \is_callable($copyrightCallable) ? call_user_func($copyrightCallable) : null, + 'dir' => \is_callable($dirCallable) ? call_user_func($dirCallable) : null, ]; } } diff --git a/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntity.php b/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntity.php deleted file mode 100644 index f5bfd400..00000000 --- a/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntity.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @see https://github.com/symfony/doctrine-bridge/blob/master/Validator/Constraints/UniqueEntity.php - * @deprecated Use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity - */ -class UniqueEntity extends Constraint -{ - public const NOT_UNIQUE_ERROR = '23bd9dbf-6b9b-41cd-a99e-4844bcf3077f'; - - public string $message = 'value.is.already.used'; - /** - * @var class-string|null - */ - public ?string $entityClass = null; - public string $repositoryMethod = 'findBy'; - public ?string $errorPath = null; - public array $fields = []; - public bool $ignoreNull = true; - - public function getRequiredOptions(): array - { - return ['fields']; - } - - public function getDefaultOption(): string - { - return 'fields'; - } -} diff --git a/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntityValidator.php b/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntityValidator.php deleted file mode 100644 index 701af696..00000000 --- a/lib/RoadizCoreBundle/src/Form/Constraint/UniqueEntityValidator.php +++ /dev/null @@ -1,171 +0,0 @@ - - * @package RZ\Roadiz\CoreBundle\Form\Constraint - * @see https://github.com/symfony/doctrine-bridge/blob/master/Validator/Constraints/UniqueEntityValidator.php - * @deprecated Use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator - */ -class UniqueEntityValidator extends ConstraintValidator -{ - protected ManagerRegistry $managerRegistry; - - /** - * @param ManagerRegistry $managerRegistry - */ - public function __construct(ManagerRegistry $managerRegistry) - { - $this->managerRegistry = $managerRegistry; - } - - /** - * @param mixed $value - * @param UniqueEntity $constraint - * - * @throws \Exception - */ - public function validate(mixed $value, Constraint $constraint): void - { - if (!$constraint instanceof UniqueEntity) { - throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\UniqueEntity'); - } - - $fields = $constraint->fields; - if (0 === count($fields)) { - throw new ConstraintDefinitionException('At least one field has to be specified.'); - } - - $class = $this->managerRegistry - ->getManagerForClass(get_class($value)) - ->getClassMetadata(get_class($value)); - - $criteria = []; - $hasNullValue = false; - foreach ($fields as $fieldName) { - if (!$class instanceof ClassMetadataInfo) { - throw new ConstraintDefinitionException(sprintf('The class "%s" is not mapped by Doctrine, so it cannot be validated for uniqueness.', get_class($value))); - } - if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) { - throw new ConstraintDefinitionException(sprintf('The field "%s" is not mapped by Doctrine, so it cannot be validated for uniqueness.', $fieldName)); - } - $fieldValue = $class->getReflectionProperty($fieldName)->getValue($value); - - if (null === $fieldValue) { - $hasNullValue = true; - } - if ($constraint->ignoreNull && null === $fieldValue) { - continue; - } - $criteria[$fieldName] = $fieldValue; - if (null !== $criteria[$fieldName] && $class->hasAssociation($fieldName)) { - /* Ensure the Proxy is initialized before using reflection to - * read its identifiers. This is necessary because the wrapped - * getter methods in the Proxy are being bypassed. - */ - $this->managerRegistry - ->getManagerForClass(get_class($value)) - ->initializeObject($criteria[$fieldName]); - } - } - // validation doesn't fail if one of the fields is null and if null values should be ignored - if ($hasNullValue && $constraint->ignoreNull) { - return; - } - // skip validation if there are no criteria (this can happen when the - // "ignoreNull" option is enabled and fields to be checked are null - if (empty($criteria)) { - return; - } - if (null !== $constraint->entityClass) { - /* Retrieve repository from given entity name. - * We ensure the retrieved repository can handle the entity - * by checking the entity is the same, or subclass of the supported entity. - */ - $repository = $this->managerRegistry->getRepository($constraint->entityClass); - $supportedClass = $repository->getClassName(); - if (!$value instanceof $supportedClass) { - throw new ConstraintDefinitionException(sprintf('The "%s" entity repository does not support the "%s" entity. The entity should be an instance of or extend "%s".', $constraint->entityClass, $class->getName(), $supportedClass)); - } - } else { - $repository = $this->managerRegistry->getRepository(get_class($value)); - } - $result = $repository->{$constraint->repositoryMethod}($criteria); - if ($result instanceof \IteratorAggregate) { - $result = $result->getIterator(); - } - /* If the result is a MongoCursor, it must be advanced to the first - * element. Rewinding should have no ill effect if $result is another - * iterator implementation. - */ - if ($result instanceof \Iterator) { - $result->rewind(); - } elseif (is_array($result)) { - reset($result); - } - /* If no entity matched the query criteria or a single entity matched, - * which is the same as the entity being validated, the criteria is - * unique. - */ - if (0 === count($result) || (1 === count($result) && $value === ($result instanceof \Iterator ? $result->current() : current($result)))) { - return; - } - - $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; - $invalidValue = $criteria[$errorPath] ?? $criteria[$fields[0]]; - - $this->context->buildViolation($constraint->message) - ->atPath($errorPath) - ->setParameter('{{ value }}', $this->formatWithIdentifiers($class, $invalidValue)) - ->setInvalidValue($invalidValue) - ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) - ->addViolation(); - } - - private function formatWithIdentifiers(ClassMetadata $class, mixed $value): string - { - if (!is_object($value) || $value instanceof \DateTimeInterface) { - return $this->formatValue($value, self::PRETTY_DATE); - } - if ($class->getName() !== $idClass = get_class($value)) { - // non unique value might be a composite PK that consists of other entity objects - if ($this->managerRegistry->getManagerForClass($idClass)->getMetadataFactory()->hasMetadataFor($idClass)) { - $identifiers = $this->managerRegistry - ->getManagerForClass($idClass) - ->getClassMetadata($idClass) - ->getIdentifierValues($value); - } else { - // this case might happen if the non unique column has a custom doctrine type and its value is an object - // in which case we cannot get any identifiers for it - $identifiers = []; - } - } else { - $identifiers = $class->getIdentifierValues($value); - } - if (!$identifiers) { - return sprintf('object("%s")', $idClass); - } - array_walk($identifiers, function (&$id, $field) { - if (!is_object($id) || $id instanceof \DateTimeInterface) { - $idAsString = $this->formatValue($id, self::PRETTY_DATE); - } else { - $idAsString = sprintf('object("%s")', get_class($id)); - } - $id = sprintf('%s => %s', $field, $idAsString); - }); - return sprintf('object("%s") identified by (%s)', $idClass, implode(', ', $identifiers)); - } -} diff --git a/lib/RoadizCoreBundle/src/Message/ApplyRealmNodeInheritanceMessage.php b/lib/RoadizCoreBundle/src/Message/ApplyRealmNodeInheritanceMessage.php index 7159e176..7943f8a8 100644 --- a/lib/RoadizCoreBundle/src/Message/ApplyRealmNodeInheritanceMessage.php +++ b/lib/RoadizCoreBundle/src/Message/ApplyRealmNodeInheritanceMessage.php @@ -6,27 +6,27 @@ final class ApplyRealmNodeInheritanceMessage implements AsyncMessage { - private int $nodeId; - private ?int $realmId; + private int|string|null $nodeId; + private int|string|null $realmId; - public function __construct(int $nodeId, ?int $realmId) + public function __construct(int|string|null $nodeId, int|string|null $realmId) { $this->nodeId = $nodeId; $this->realmId = $realmId; } /** - * @return int + * @return int|string|null */ - public function getNodeId(): int + public function getNodeId(): int|string|null { return $this->nodeId; } /** - * @return int|null + * @return int|string|null */ - public function getRealmId(): ?int + public function getRealmId(): int|string|null { return $this->realmId; } diff --git a/lib/RoadizCoreBundle/src/Message/CleanRealmNodeInheritanceMessage.php b/lib/RoadizCoreBundle/src/Message/CleanRealmNodeInheritanceMessage.php index 05579c30..cf1d1201 100644 --- a/lib/RoadizCoreBundle/src/Message/CleanRealmNodeInheritanceMessage.php +++ b/lib/RoadizCoreBundle/src/Message/CleanRealmNodeInheritanceMessage.php @@ -6,27 +6,27 @@ final class CleanRealmNodeInheritanceMessage implements AsyncMessage { - private int $nodeId; - private ?int $realmId; + private int|string|null $nodeId; + private int|string|null $realmId; - public function __construct(int $nodeId, ?int $realmId) + public function __construct(int|string|null $nodeId, int|string|null $realmId) { $this->nodeId = $nodeId; $this->realmId = $realmId; } /** - * @return int + * @return int|string|null */ - public function getNodeId(): int + public function getNodeId(): int|string|null { return $this->nodeId; } /** - * @return int|null + * @return int|string|null */ - public function getRealmId(): ?int + public function getRealmId(): int|string|null { return $this->realmId; } diff --git a/lib/RoadizCoreBundle/src/Message/DeleteNodeTypeMessage.php b/lib/RoadizCoreBundle/src/Message/DeleteNodeTypeMessage.php index a5f3c682..0f3caca1 100644 --- a/lib/RoadizCoreBundle/src/Message/DeleteNodeTypeMessage.php +++ b/lib/RoadizCoreBundle/src/Message/DeleteNodeTypeMessage.php @@ -6,20 +6,20 @@ final class DeleteNodeTypeMessage implements AsyncMessage { - private int $nodeTypeId; + private int|string|null $nodeTypeId; /** - * @param int $nodeTypeId + * @param int|string|null $nodeTypeId */ - public function __construct(int $nodeTypeId) + public function __construct(int|string|null $nodeTypeId) { $this->nodeTypeId = $nodeTypeId; } /** - * @return int + * @return int|string|null */ - public function getNodeTypeId(): int + public function getNodeTypeId(): int|string|null { return $this->nodeTypeId; } diff --git a/lib/RoadizCoreBundle/src/Message/PurgeReverseProxyCacheMessage.php b/lib/RoadizCoreBundle/src/Message/PurgeReverseProxyCacheMessage.php index 58e79384..be0c54c0 100644 --- a/lib/RoadizCoreBundle/src/Message/PurgeReverseProxyCacheMessage.php +++ b/lib/RoadizCoreBundle/src/Message/PurgeReverseProxyCacheMessage.php @@ -6,20 +6,20 @@ final class PurgeReverseProxyCacheMessage implements AsyncMessage { - private int $nodeSourceId; + private int|string|null $nodeSourceId; /** - * @param int $nodeSourceId + * @param int|string|null $nodeSourceId */ - public function __construct(int $nodeSourceId) + public function __construct(int|string|null $nodeSourceId) { $this->nodeSourceId = $nodeSourceId; } /** - * @return int + * @return int|string|null */ - public function getNodeSourceId(): int + public function getNodeSourceId(): int|string|null { return $this->nodeSourceId; } diff --git a/lib/RoadizCoreBundle/src/Message/SearchRealmNodeInheritanceMessage.php b/lib/RoadizCoreBundle/src/Message/SearchRealmNodeInheritanceMessage.php index e3732026..c9ec45ff 100644 --- a/lib/RoadizCoreBundle/src/Message/SearchRealmNodeInheritanceMessage.php +++ b/lib/RoadizCoreBundle/src/Message/SearchRealmNodeInheritanceMessage.php @@ -6,17 +6,17 @@ final class SearchRealmNodeInheritanceMessage implements AsyncMessage { - private int $nodeId; + private int|string|null $nodeId; - public function __construct(int $nodeId) + public function __construct(int|string|null $nodeId) { $this->nodeId = $nodeId; } /** - * @return int + * @return int|string|null */ - public function getNodeId(): int + public function getNodeId(): int|string|null { return $this->nodeId; } diff --git a/lib/RoadizCoreBundle/src/Message/UpdateNodeTypeSchemaMessage.php b/lib/RoadizCoreBundle/src/Message/UpdateNodeTypeSchemaMessage.php index 830828b5..f4a309a5 100644 --- a/lib/RoadizCoreBundle/src/Message/UpdateNodeTypeSchemaMessage.php +++ b/lib/RoadizCoreBundle/src/Message/UpdateNodeTypeSchemaMessage.php @@ -9,20 +9,20 @@ */ final class UpdateNodeTypeSchemaMessage { - private int $nodeTypeId; + private int|string|null $nodeTypeId; /** - * @param int $nodeTypeId + * @param int|string|null $nodeTypeId */ - public function __construct(int $nodeTypeId) + public function __construct(int|string|null $nodeTypeId) { $this->nodeTypeId = $nodeTypeId; } /** - * @return int + * @return int|string|null */ - public function getNodeTypeId(): int + public function getNodeTypeId(): int|string|null { return $this->nodeTypeId; } diff --git a/lib/RoadizCoreBundle/src/Node/NodeMover.php b/lib/RoadizCoreBundle/src/Node/NodeMover.php index 901559d3..b82d8204 100644 --- a/lib/RoadizCoreBundle/src/Node/NodeMover.php +++ b/lib/RoadizCoreBundle/src/Node/NodeMover.php @@ -203,6 +203,7 @@ protected function redirect(NodesSources $nodeSource, string $previousPath, bool $this->getManager()->remove($loopingRedirection); } + /** @var Redirection|null $existingRedirection */ $existingRedirection = $redirectionRepo->findOneBy([ 'query' => $previousPath, ]); diff --git a/lib/Rozier/src/AjaxControllers/AjaxNodesController.php b/lib/Rozier/src/AjaxControllers/AjaxNodesController.php index 802fa451..0ab98a4e 100644 --- a/lib/Rozier/src/AjaxControllers/AjaxNodesController.php +++ b/lib/Rozier/src/AjaxControllers/AjaxNodesController.php @@ -306,14 +306,14 @@ public function statusesAction(Request $request): JsonResponse '%name%' => $node->getNodeName(), '%visible%' => $node->isVisible() ? $this->getTranslator()->trans('visible') : $this->getTranslator()->trans('invisible'), ]); - $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first()); + $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first() ?: null); $this->dispatchEvent(new NodeVisibilityChangedEvent($node)); } else { $msg = $this->getTranslator()->trans('node.%name%.%field%.updated', [ '%name%' => $node->getNodeName(), '%field%' => $request->get('statusName'), ]); - $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first()); + $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first() ?: null); } $this->dispatchEvent(new NodeUpdatedEvent($node)); $this->em()->flush(); diff --git a/lib/Rozier/src/Controllers/Documents/DocumentsController.php b/lib/Rozier/src/Controllers/Documents/DocumentsController.php index bbc36579..ad25bb3a 100644 --- a/lib/Rozier/src/Controllers/Documents/DocumentsController.php +++ b/lib/Rozier/src/Controllers/Documents/DocumentsController.php @@ -140,20 +140,16 @@ public function indexAction(Request $request, ?int $folderId = null): Response $this->assignation['folder'] = $folder; } - if ( - $request->query->has('type') && - $request->query->get('type', '') !== '' - ) { - $prefilters['mimeType'] = trim($request->query->get('type', '')); - $this->assignation['mimeType'] = trim($request->query->get('type', '')); + $type = $request->query->get('type', null); + if (\is_string($type) && trim($type) !== '') { + $prefilters['mimeType'] = trim($type); + $this->assignation['mimeType'] = trim($type); } - if ( - $request->query->has('embedPlatform') && - $request->query->get('embedPlatform', '') !== '' - ) { - $prefilters['embedPlatform'] = trim($request->query->get('embedPlatform', '')); - $this->assignation['embedPlatform'] = trim($request->query->get('embedPlatform', '')); + $embedPlatform = $request->query->get('embedPlatform', null); + if (\is_string($embedPlatform) && trim($embedPlatform) !== '') { + $prefilters['embedPlatform'] = trim($embedPlatform); + $this->assignation['embedPlatform'] = trim($embedPlatform); } $this->assignation['availablePlatforms'] = $this->documentPlatforms; diff --git a/lib/Rozier/src/Controllers/NodeTypes/NodeTypesUtilsController.php b/lib/Rozier/src/Controllers/NodeTypes/NodeTypesUtilsController.php index f0e656ca..d79bac8e 100644 --- a/lib/Rozier/src/Controllers/NodeTypes/NodeTypesUtilsController.php +++ b/lib/Rozier/src/Controllers/NodeTypes/NodeTypesUtilsController.php @@ -83,6 +83,7 @@ public function exportJsonFileAction(Request $request, int $nodeTypeId): Respons * @param Request $request * * @return BinaryFileResponse + * @throws RuntimeError */ public function exportDocumentationAction(Request $request): BinaryFileResponse { @@ -91,6 +92,10 @@ public function exportDocumentationAction(Request $request): BinaryFileResponse $documentationGenerator = new DocumentationGenerator($this->nodeTypesBag, $this->getTranslator()); $tmpfname = tempnam(sys_get_temp_dir(), date('Y-m-d-H-i-s') . '.zip'); + if (false === $tmpfname) { + throw new RuntimeError('Unable to create temporary file.'); + } + unlink($tmpfname); // Deprecated: ZipArchive::open(): Using empty file as ZipArchive is deprecated $zipArchive = new ZipArchive(); $zipArchive->open($tmpfname, ZipArchive::CREATE); @@ -161,6 +166,9 @@ public function exportAllAction(Request $request): BinaryFileResponse $zipArchive = new ZipArchive(); $tmpfname = tempnam(sys_get_temp_dir(), date('Y-m-d-H-i-s') . '.zip'); + if (false === $tmpfname) { + throw new RuntimeError('Unable to create temporary file.'); + } unlink($tmpfname); // Deprecated: ZipArchive::open(): Using empty file as ZipArchive is deprecated $zipArchive->open($tmpfname, ZipArchive::CREATE); @@ -212,6 +220,9 @@ public function importJsonFileAction(Request $request): Response if ($file->isValid()) { $serializedData = file_get_contents($file->getPathname()); + if (false === $serializedData) { + throw new RuntimeError('Unable to read uploaded file.'); + } if (null !== json_decode($serializedData)) { $this->nodeTypesImporter->import($serializedData); diff --git a/lib/Rozier/src/Controllers/Nodes/NodesController.php b/lib/Rozier/src/Controllers/Nodes/NodesController.php index fc590498..220f00ff 100644 --- a/lib/Rozier/src/Controllers/Nodes/NodesController.php +++ b/lib/Rozier/src/Controllers/Nodes/NodesController.php @@ -669,7 +669,7 @@ public function undeleteAction(Request $request, int $nodeId): Response 'node.%name%.undeleted', ['%name%' => $node->getNodeName()] ); - $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first()); + $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first() ?: null); /* * Force redirect to avoid resending form when refreshing page */ diff --git a/lib/Rozier/src/Controllers/Nodes/NodesSourcesController.php b/lib/Rozier/src/Controllers/Nodes/NodesSourcesController.php index 84012609..03409dcb 100644 --- a/lib/Rozier/src/Controllers/Nodes/NodesSourcesController.php +++ b/lib/Rozier/src/Controllers/Nodes/NodesSourcesController.php @@ -248,7 +248,11 @@ public function removeAction(Request $request, int $nodeSourceId): Response $this->em()->remove($ns); $this->em()->flush(); - $ns = $node->getNodeSources()->first(); + $ns = $node->getNodeSources()->first() ?: null; + + if (null === $ns) { + throw new ResourceNotFoundException('No more node-source available for this node.'); + } $msg = $this->getTranslator()->trans('node_source.%node_source%.deleted.%translation%', [ '%node_source%' => $node->getNodeName(), diff --git a/lib/Rozier/src/Controllers/Nodes/TranstypeController.php b/lib/Rozier/src/Controllers/Nodes/TranstypeController.php index de1a7f3b..c57cbc40 100644 --- a/lib/Rozier/src/Controllers/Nodes/TranstypeController.php +++ b/lib/Rozier/src/Controllers/Nodes/TranstypeController.php @@ -91,13 +91,15 @@ public function transtypeAction(Request $request, int $nodeId) '%node%' => $node->getNodeName(), '%type%' => $newNodeType->getName(), ]); - $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first()); + $this->publishConfirmMessage($request, $msg, $node->getNodeSources()->first() ?: null); return $this->redirectToRoute( 'nodesEditSourcePage', [ 'nodeId' => $node->getId(), - 'translationId' => $node->getNodeSources()->first()->getTranslation()->getId(), + 'translationId' => $node->getNodeSources()->first() ? + $node->getNodeSources()->first()->getTranslation()->getId() : + null, ] ); } diff --git a/lib/Rozier/src/Controllers/RolesUtilsController.php b/lib/Rozier/src/Controllers/RolesUtilsController.php index 382baaf3..f0a5907e 100644 --- a/lib/Rozier/src/Controllers/RolesUtilsController.php +++ b/lib/Rozier/src/Controllers/RolesUtilsController.php @@ -90,6 +90,9 @@ public function importJsonFileAction(Request $request): Response if ($file->isValid()) { $serializedData = file_get_contents($file->getPathname()); + if (false === $serializedData) { + throw new RuntimeError('Cannot read uploaded file.'); + } if (null !== \json_decode($serializedData)) { if ($this->rolesImporter->import($serializedData)) { diff --git a/lib/Rozier/src/Controllers/SearchController.php b/lib/Rozier/src/Controllers/SearchController.php index 923cedaf..e23ec35b 100644 --- a/lib/Rozier/src/Controllers/SearchController.php +++ b/lib/Rozier/src/Controllers/SearchController.php @@ -383,8 +383,10 @@ protected function handleNodeForm(FormInterface $form, NodeType $nodetype): ?Res || (is_array($value) && isset($value["compareDate"])) || (is_array($value) && $value != [] && !isset($value["compareOp"])) ) { - if (strstr($key, "__node__") == 0) { - $data[str_replace("__node__", "node.", $key)] = $value; + if (\is_string($key) & str_contains($key, "__node__")) { + /** @var string $newKey */ + $newKey = str_replace("__node__", "node.", $key); + $data[$newKey] = $value; } else { $data[$key] = $value; } diff --git a/lib/Rozier/src/Controllers/SettingsUtilsController.php b/lib/Rozier/src/Controllers/SettingsUtilsController.php index 75e61568..31f5a38f 100644 --- a/lib/Rozier/src/Controllers/SettingsUtilsController.php +++ b/lib/Rozier/src/Controllers/SettingsUtilsController.php @@ -103,6 +103,10 @@ public function importJsonFileAction(Request $request): Response if ($file->isValid()) { $serializedData = file_get_contents($file->getPathname()); + if (!\is_string($serializedData)) { + throw new RuntimeError('Imported file is not a string.'); + } + if (null !== \json_decode($serializedData)) { if ($this->settingsImporter->import($serializedData)) { $msg = $this->getTranslator()->trans('setting.imported'); diff --git a/lib/Rozier/src/Controllers/Tags/TagsController.php b/lib/Rozier/src/Controllers/Tags/TagsController.php index 659c18a5..1c2cb442 100644 --- a/lib/Rozier/src/Controllers/Tags/TagsController.php +++ b/lib/Rozier/src/Controllers/Tags/TagsController.php @@ -482,7 +482,11 @@ public function deleteAction(Request $request, int $tagId) $this->em()->remove($tag); $this->em()->flush(); - $msg = $this->getTranslator()->trans('tag.%name%.deleted', ['%name%' => $tag->getTranslatedTags()->first()->getName()]); + $msg = $this->getTranslator()->trans('tag.%name%.deleted', [ + '%name%' => $tag->getTranslatedTags()->first() ? + $tag->getTranslatedTags()->first()->getName() : + $tag->getTagName(), + ]); $this->publishConfirmMessage($request, $msg); /* diff --git a/lib/Rozier/src/Explorer/ConfigurableExplorerItem.php b/lib/Rozier/src/Explorer/ConfigurableExplorerItem.php index 4fb67bfa..bc86157e 100644 --- a/lib/Rozier/src/Explorer/ConfigurableExplorerItem.php +++ b/lib/Rozier/src/Explorer/ConfigurableExplorerItem.php @@ -55,9 +55,12 @@ public function getAlternativeDisplayable(): ?string { $alt = $this->configuration['classname']; if (!empty($this->configuration['alt_displayable'])) { - $alt = call_user_func([$this->entity, $this->configuration['alt_displayable']]); - if ($alt instanceof \DateTimeInterface) { - $alt = $alt->format('c'); + $altDisplayableCallable = [$this->entity, $this->configuration['alt_displayable']]; + if (\is_callable($altDisplayableCallable)) { + $alt = call_user_func($altDisplayableCallable); + if ($alt instanceof \DateTimeInterface) { + $alt = $alt->format('c'); + } } } return (new UnicodeString($alt ?? ''))->truncate(30, '…')->toString(); @@ -68,9 +71,12 @@ public function getAlternativeDisplayable(): ?string */ public function getDisplayable(): string { - $displayable = call_user_func([$this->entity, $this->configuration['displayable']]); - if ($displayable instanceof \DateTimeInterface) { - $displayable = $displayable->format('c'); + $displayableCallable = [$this->entity, $this->configuration['displayable']]; + if (\is_callable($displayableCallable)) { + $displayable = call_user_func($displayableCallable); + if ($displayable instanceof \DateTimeInterface) { + $displayable = $displayable->format('c'); + } } return (new UnicodeString($displayable ?? ''))->truncate(30, '…')->toString(); } @@ -88,11 +94,14 @@ protected function getThumbnail(): ?array /** @var DocumentInterface|null $thumbnail */ $thumbnail = null; if (!empty($this->configuration['thumbnail'])) { - $thumbnail = call_user_func([$this->entity, $this->configuration['thumbnail']]); - if ($thumbnail instanceof Collection && $thumbnail->count() > 0 && $thumbnail->first() instanceof DocumentInterface) { - $thumbnail = $thumbnail->first(); - } elseif (is_array($thumbnail) && count($thumbnail) > 0 && $thumbnail[0] instanceof DocumentInterface) { - $thumbnail = $thumbnail[0]; + $thumbnailCallable = [$this->entity, $this->configuration['thumbnail']]; + if (\is_callable($thumbnailCallable)) { + $thumbnail = call_user_func($thumbnailCallable); + if ($thumbnail instanceof Collection && $thumbnail->count() > 0 && $thumbnail->first() instanceof DocumentInterface) { + $thumbnail = $thumbnail->first(); + } elseif (is_array($thumbnail) && count($thumbnail) > 0 && $thumbnail[0] instanceof DocumentInterface) { + $thumbnail = $thumbnail[0]; + } } } diff --git a/lib/Rozier/src/Explorer/FolderExplorerItem.php b/lib/Rozier/src/Explorer/FolderExplorerItem.php index 10588ae0..9a85e7ae 100644 --- a/lib/Rozier/src/Explorer/FolderExplorerItem.php +++ b/lib/Rozier/src/Explorer/FolderExplorerItem.php @@ -35,7 +35,9 @@ public function getAlternativeDisplayable(): ?string /** @var Folder|null $parent */ $parent = $this->folder->getParent(); if (null !== $parent) { - return $parent->getTranslatedFolders()->first()->getName(); + return $parent->getTranslatedFolders()->first() ? + $parent->getTranslatedFolders()->first()->getName() : + $parent->getName(); } return ''; } @@ -45,7 +47,9 @@ public function getAlternativeDisplayable(): ?string */ public function getDisplayable(): string { - return $this->folder->getTranslatedFolders()->first()->getName(); + return $this->folder->getTranslatedFolders()->first() ? + $this->folder->getTranslatedFolders()->first()->getName() : + $this->folder->getName(); } /** diff --git a/lib/Rozier/src/Forms/NodeSource/NodeSourceJoinType.php b/lib/Rozier/src/Forms/NodeSource/NodeSourceJoinType.php index 27b90477..b7810c44 100644 --- a/lib/Rozier/src/Forms/NodeSource/NodeSourceJoinType.php +++ b/lib/Rozier/src/Forms/NodeSource/NodeSourceJoinType.php @@ -55,8 +55,9 @@ public function buildView(FormView $view, FormInterface $form, array $options): $configuration = $this->getFieldConfiguration($options); $displayableData = []; - - $entities = call_user_func([$options['nodeSource'], $options['nodeTypeField']->getGetterName()]); + /** @var callable $callable */ + $callable = [$options['nodeSource'], $options['nodeTypeField']->getGetterName()]; + $entities = call_user_func($callable); if ($entities instanceof \Traversable) { /** @var PersistableInterface $entity */ @@ -68,8 +69,9 @@ public function buildView(FormView $view, FormInterface $form, array $options): 'id' => $entity->getId(), 'classname' => $configuration['classname'], ]; - if (is_callable([$entity, $configuration['displayable']])) { - $data['name'] = call_user_func([$entity, $configuration['displayable']]); + $displayableCallable = [$entity, $configuration['displayable']]; + if (\is_callable($displayableCallable)) { + $data['name'] = call_user_func($displayableCallable); } $displayableData[] = $data; } @@ -81,8 +83,9 @@ public function buildView(FormView $view, FormInterface $form, array $options): 'id' => $entities->getId(), 'classname' => $configuration['classname'], ]; - if (is_callable([$entities, $configuration['displayable']])) { - $data['name'] = call_user_func([$entities, $configuration['displayable']]); + $displayableCallable = [$entities, $configuration['displayable']]; + if (\is_callable($displayableCallable)) { + $data['name'] = call_user_func($displayableCallable); } $displayableData[] = $data; } diff --git a/lib/Rozier/src/Forms/NodeSource/NodeSourceProviderType.php b/lib/Rozier/src/Forms/NodeSource/NodeSourceProviderType.php index 3471cfdb..9132793c 100644 --- a/lib/Rozier/src/Forms/NodeSource/NodeSourceProviderType.php +++ b/lib/Rozier/src/Forms/NodeSource/NodeSourceProviderType.php @@ -105,7 +105,9 @@ public function buildView(FormView $view, FormInterface $form, array $options): $provider = $this->getProvider($configuration, $options); $displayableData = []; - $ids = call_user_func([$options['nodeSource'], $options['nodeTypeField']->getGetterName()]); + /** @var callable $callable */ + $callable = [$options['nodeSource'], $options['nodeTypeField']->getGetterName()]; + $ids = call_user_func($callable); if (!is_array($ids)) { $entities = $provider->getItemsById([$ids]); } else { diff --git a/lib/Rozier/src/RozierApp.php b/lib/Rozier/src/RozierApp.php index a321cafa..a8fab084 100644 --- a/lib/Rozier/src/RozierApp.php +++ b/lib/Rozier/src/RozierApp.php @@ -114,17 +114,18 @@ public function prepareBaseAssignation() */ $this->assignation['themeServices'] = $this->get(RozierServiceRegistry::class); + /** @var CsrfTokenManagerInterface $tokenManager */ + $tokenManager = $this->get('csrfTokenManager'); /* * Switch this to true to use uncompressed JS and CSS files */ $this->assignation['head']['backDevMode'] = false; - //Settings $this->assignation['head']['siteTitle'] = $this->getSettingsBag()->get('site_name') . ' backstage'; $this->assignation['head']['mapsLocation'] = $this->getSettingsBag()->get('maps_default_location') ? $this->getSettingsBag()->get('maps_default_location') : null; $this->assignation['head']['mainColor'] = $this->getSettingsBag()->get('main_color'); $this->assignation['head']['googleClientId'] = $this->getSettingsBag()->get('google_client_id', ""); $this->assignation['head']['themeName'] = static::$themeName; - $this->assignation['head']['ajaxToken'] = $this->get('csrfTokenManager')->getToken(static::AJAX_TOKEN_INTENTION); + $this->assignation['head']['ajaxToken'] = $tokenManager->getToken(static::AJAX_TOKEN_INTENTION); $this->assignation['rozier_user_actions'] = $this->dispatchEvent(new UserActionsMenuEvent())->getActions(); $this->assignation['nodeStatuses'] = [ @@ -159,8 +160,10 @@ public function indexAction(Request $request) */ public function cssAction(Request $request): Response { + /** @var NodeTypes $nodeTypesBag */ + $nodeTypesBag = $this->get('nodeTypesBag'); $this->assignation['mainColor'] = $this->getSettingsBag()->get('main_color'); - $this->assignation['nodeTypes'] = $this->get('nodeTypesBag')->all(); + $this->assignation['nodeTypes'] = $nodeTypesBag->all(); $folderQb = $this->em()->getRepository(Folder::class)->createQueryBuilder('f'); $this->assignation['folders'] = $folderQb->andWhere($folderQb->expr()->neq('f.color', ':defaultColor'))