From 77a1bef5b680843018e611994836a36ee826f060 Mon Sep 17 00:00:00 2001 From: roadiz-ci Date: Mon, 18 Mar 2024 20:51:13 +0000 Subject: [PATCH] feat: Reduce NodeTypeField name to maximum 50 characters long. --- migrations/Version20240318184555.php | 34 ++++++++++ migrations/Version20240318184556.php | 68 +++++++++++++++++++ migrations/Version20240318204224.php | 44 ++++++++++++ src/Doctrine/ORM/Filter/ANodesFilter.php | 50 ++------------ src/Doctrine/ORM/Filter/BNodesFilter.php | 8 --- src/Entity/FieldAwareEntityTrait.php | 44 ++++++++++++ src/Entity/Node.php | 13 ++-- src/Entity/NodeTypeField.php | 5 +- src/Entity/NodesCustomForms.php | 39 ++--------- src/Entity/NodesSources.php | 15 ++-- src/Entity/NodesSourcesDocuments.php | 44 ++---------- src/Entity/NodesToNodes.php | 60 +++------------- src/EntityHandler/NodeHandler.php | 19 +++--- src/EntityHandler/NodesSourcesHandler.php | 23 +++---- src/Node/NodeDuplicator.php | 9 +-- src/Node/NodeTranstyper.php | 6 +- src/Node/UniversalDataDuplicator.php | 19 ++---- src/Repository/CustomFormRepository.php | 28 +++++++- src/Repository/DocumentRepository.php | 19 +++--- src/Repository/NodeRepository.php | 16 ++--- src/Repository/NodesCustomFormsRepository.php | 35 +++++++--- .../NodesSourcesDocumentsRepository.php | 27 ++++++-- src/Repository/NodesSourcesRepository.php | 36 +++++++++- src/Repository/NodesToNodesRepository.php | 30 ++++++-- 24 files changed, 419 insertions(+), 272 deletions(-) create mode 100644 migrations/Version20240318184555.php create mode 100644 migrations/Version20240318184556.php create mode 100644 migrations/Version20240318204224.php create mode 100644 src/Entity/FieldAwareEntityTrait.php diff --git a/migrations/Version20240318184555.php b/migrations/Version20240318184555.php new file mode 100644 index 00000000..e03fcf8c --- /dev/null +++ b/migrations/Version20240318184555.php @@ -0,0 +1,34 @@ +addSql('ALTER TABLE nodes_custom_forms ADD field_name VARCHAR(250)'); + $this->addSql('ALTER TABLE nodes_sources_documents ADD field_name VARCHAR(250)'); + $this->addSql('ALTER TABLE nodes_to_nodes ADD field_name VARCHAR(250)'); + } + + public function down(Schema $schema): void + { + $this->throwIrreversibleMigrationException('Cannot convert node-type fields name back to their identifiers'); + } +} diff --git a/migrations/Version20240318184556.php b/migrations/Version20240318184556.php new file mode 100644 index 00000000..69d87323 --- /dev/null +++ b/migrations/Version20240318184556.php @@ -0,0 +1,68 @@ +connection->beginTransaction(); + $this->connection->executeStatement('UPDATE nodes_custom_forms SET field_name = (SELECT name FROM node_type_fields WHERE id = node_type_field_id)'); + $this->connection->executeStatement('UPDATE nodes_sources_documents SET field_name = (SELECT name FROM node_type_fields WHERE id = node_type_field_id)'); + $this->connection->executeStatement('UPDATE nodes_to_nodes SET field_name = (SELECT name FROM node_type_fields WHERE id = node_type_field_id)'); + $this->connection->commit(); + + $this->addSql('ALTER TABLE nodes_custom_forms DROP FOREIGN KEY FK_4D401A0C47705282'); + $this->addSql('DROP INDEX IDX_4D401A0C47705282 ON nodes_custom_forms'); + $this->addSql('DROP INDEX customform_node_field_position ON nodes_custom_forms'); + $this->addSql('CREATE INDEX customform_node_field_position ON nodes_custom_forms (node_id, field_name, position)'); + $this->addSql('ALTER TABLE nodes_sources_documents DROP FOREIGN KEY FK_1CD104F747705282'); + $this->addSql('DROP INDEX IDX_1CD104F747705282 ON nodes_sources_documents'); + $this->addSql('DROP INDEX nsdoc_field ON nodes_sources_documents'); + $this->addSql('DROP INDEX nsdoc_field_position ON nodes_sources_documents'); + $this->addSql('CREATE INDEX nsdoc_field ON nodes_sources_documents (ns_id, field_name)'); + $this->addSql('CREATE INDEX nsdoc_field_position ON nodes_sources_documents (ns_id, field_name, position)'); + $this->addSql('ALTER TABLE nodes_to_nodes DROP FOREIGN KEY FK_761F9A9147705282'); + $this->addSql('DROP INDEX IDX_761F9A9147705282 ON nodes_to_nodes'); + $this->addSql('DROP INDEX node_a_field ON nodes_to_nodes'); + $this->addSql('DROP INDEX node_a_field_position ON nodes_to_nodes'); + $this->addSql('DROP INDEX node_b_field ON nodes_to_nodes'); + $this->addSql('DROP INDEX node_b_field_position ON nodes_to_nodes'); + $this->addSql('CREATE INDEX node_a_field ON nodes_to_nodes (node_a_id, field_name)'); + $this->addSql('CREATE INDEX node_a_field_position ON nodes_to_nodes (node_a_id, field_name, position)'); + $this->addSql('CREATE INDEX node_b_field ON nodes_to_nodes (node_b_id, field_name)'); + $this->addSql('CREATE INDEX node_b_field_position ON nodes_to_nodes (node_b_id, field_name, position)'); + + /* + * DESTRUCTIVE OPERATIONS + */ + $this->addSql('ALTER TABLE nodes_custom_forms CHANGE field_name field_name VARCHAR(250) NOT NULL'); + $this->addSql('ALTER TABLE nodes_sources_documents CHANGE field_name field_name VARCHAR(250) NOT NULL'); + $this->addSql('ALTER TABLE nodes_to_nodes CHANGE field_name field_name VARCHAR(250) NOT NULL'); + + $this->addSql('ALTER TABLE nodes_custom_forms DROP node_type_field_id'); + $this->addSql('ALTER TABLE nodes_sources_documents DROP node_type_field_id'); + $this->addSql('ALTER TABLE nodes_to_nodes DROP node_type_field_id'); + } + + public function down(Schema $schema): void + { + $this->throwIrreversibleMigrationException('Cannot convert node-type fields name back to their identifiers'); + } +} diff --git a/migrations/Version20240318204224.php b/migrations/Version20240318204224.php new file mode 100644 index 00000000..0897dc0b --- /dev/null +++ b/migrations/Version20240318204224.php @@ -0,0 +1,44 @@ +connection->executeQuery('SELECT max(length(name)) FROM `node_type_fields`'); + $maxLength = $result->fetchOne(); + + $this->skipIf(!is_numeric($maxLength), 'Cannot find node_type_fields name maximum length.'); + $this->skipIf($maxLength >= 50, 'You have at least on node_type_field name that exceed 50 characters long.'); + + // this up() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE node_type_fields CHANGE name name VARCHAR(50) NOT NULL'); + $this->addSql('CREATE INDEX ntf_name ON node_type_fields (name)'); + $this->addSql('ALTER TABLE nodes_custom_forms CHANGE field_name field_name VARCHAR(50) NOT NULL'); + $this->addSql('ALTER TABLE nodes_sources_documents CHANGE field_name field_name VARCHAR(50) NOT NULL'); + $this->addSql('ALTER TABLE nodes_to_nodes CHANGE field_name field_name VARCHAR(50) NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP INDEX ntf_name ON node_type_fields'); + $this->addSql('ALTER TABLE node_type_fields CHANGE name name VARCHAR(250) NOT NULL'); + $this->addSql('ALTER TABLE nodes_custom_forms CHANGE field_name field_name VARCHAR(250) NOT NULL'); + $this->addSql('ALTER TABLE nodes_sources_documents CHANGE field_name field_name VARCHAR(250) NOT NULL'); + $this->addSql('ALTER TABLE nodes_to_nodes CHANGE field_name field_name VARCHAR(250) NOT NULL'); + } +} diff --git a/src/Doctrine/ORM/Filter/ANodesFilter.php b/src/Doctrine/ORM/Filter/ANodesFilter.php index 8548be74..ebfcb49e 100644 --- a/src/Doctrine/ORM/Filter/ANodesFilter.php +++ b/src/Doctrine/ORM/Filter/ANodesFilter.php @@ -40,14 +40,6 @@ protected function getNodeJoinAlias(): string return 'a_n'; } - /** - * @return string - */ - protected function getNodeFieldJoinAlias(): string - { - return 'a_n_f'; - } - /** * @param QueryBuilderBuildEvent $event */ @@ -72,24 +64,9 @@ public function onNodeQueryBuilderBuild(QueryBuilderBuildEvent $event): void $this->getNodeJoinAlias() ); } - if (str_contains($event->getProperty(), $this->getProperty() . '.field.')) { - if ( - !$simpleQB->joinExists( - $simpleQB->getRootAlias(), - $this->getNodeFieldJoinAlias() - ) - ) { - $qb->innerJoin( - $this->getNodeJoinAlias() . '.field', - $this->getNodeFieldJoinAlias() - ); - } - $prefix = $this->getNodeFieldJoinAlias() . '.'; - $key = str_replace($this->getProperty() . '.field.', '', $event->getProperty()); - } else { - $prefix = $this->getNodeJoinAlias() . '.'; - $key = str_replace($this->getProperty() . '.', '', $event->getProperty()); - } + + $prefix = $this->getNodeJoinAlias() . '.'; + $key = str_replace($this->getProperty() . '.', '', $event->getProperty()); $qb->andWhere($simpleQB->buildExpressionWithoutBinding($event->getValue(), $prefix, $key, $baseKey)); } @@ -132,24 +109,9 @@ public function onNodesSourcesQueryBuilderBuild(QueryBuilderNodesSourcesBuildEve $this->getNodeJoinAlias() ); } - if (str_contains($event->getProperty(), 'node.' . $this->getProperty() . '.field.')) { - if ( - !$simpleQB->joinExists( - $simpleQB->getRootAlias(), - $this->getNodeFieldJoinAlias() - ) - ) { - $qb->innerJoin( - $this->getNodeJoinAlias() . '.field', - $this->getNodeFieldJoinAlias() - ); - } - $prefix = $this->getNodeFieldJoinAlias() . '.'; - $key = str_replace('node.' . $this->getProperty() . '.field.', '', $event->getProperty()); - } else { - $prefix = $this->getNodeJoinAlias() . '.'; - $key = str_replace('node.' . $this->getProperty() . '.', '', $event->getProperty()); - } + + $prefix = $this->getNodeJoinAlias() . '.'; + $key = str_replace('node.' . $this->getProperty() . '.', '', $event->getProperty()); $qb->andWhere($simpleQB->buildExpressionWithoutBinding($event->getValue(), $prefix, $key, $baseKey)); } diff --git a/src/Doctrine/ORM/Filter/BNodesFilter.php b/src/Doctrine/ORM/Filter/BNodesFilter.php index 032b9e7a..8cb6f894 100644 --- a/src/Doctrine/ORM/Filter/BNodesFilter.php +++ b/src/Doctrine/ORM/Filter/BNodesFilter.php @@ -35,12 +35,4 @@ protected function getNodeJoinAlias(): string { return 'b_n'; } - - /** - * @return string - */ - protected function getNodeFieldJoinAlias(): string - { - return 'b_n_f'; - } } diff --git a/src/Entity/FieldAwareEntityTrait.php b/src/Entity/FieldAwareEntityTrait.php new file mode 100644 index 00000000..be0611eb --- /dev/null +++ b/src/Entity/FieldAwareEntityTrait.php @@ -0,0 +1,44 @@ +fieldName; + } + + public function setFieldName(string $fieldName): self + { + $this->fieldName = $fieldName; + return $this; + } + + /** + * @deprecated Use setFieldName method instead + */ + public function setField(NodeTypeFieldInterface $field): self + { + $this->fieldName = $field->getName(); + return $this; + } + + protected function initializeFieldAwareEntityTrait(?NodeTypeFieldInterface $nodeTypeField = null): void + { + if (null === $nodeTypeField) { + return; + } + $this->fieldName = $nodeTypeField->getName(); + } +} diff --git a/src/Entity/Node.php b/src/Entity/Node.php index 547ec995..18b73384 100644 --- a/src/Entity/Node.php +++ b/src/Entity/Node.php @@ -15,6 +15,7 @@ use Gedmo\Loggable\Loggable; use Gedmo\Mapping\Annotation as Gedmo; use JMS\Serializer\Annotation as Serializer; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Contracts\NodeType\NodeTypeInterface; use RZ\Roadiz\Core\AbstractEntities\LeafInterface; use RZ\Roadiz\Core\AbstractEntities\LeafTrait; @@ -795,10 +796,10 @@ public function addNodeSources(NodesSources $ns): static * @return Collection */ #[SymfonySerializer\Ignore] - public function getBNodesByField(NodeTypeField $field): Collection + public function getBNodesByField(NodeTypeFieldInterface $field): Collection { $criteria = Criteria::create(); - $criteria->andWhere(Criteria::expr()->eq('field', $field)); + $criteria->andWhere(Criteria::expr()->eq('fieldName', $field->getName())); $criteria->orderBy(['position' => 'ASC']); return $this->getBNodes()->matching($criteria); } @@ -833,7 +834,7 @@ public function hasBNode(NodesToNodes $bNode): bool return $this->getBNodes()->exists(function ($key, NodesToNodes $element) use ($bNode) { return $bNode->getNodeB()->getId() !== null && $element->getNodeB()->getId() === $bNode->getNodeB()->getId() && - $element->getField()->getId() === $bNode->getField()->getId(); + $element->getFieldName() === $bNode->getFieldName(); }); } @@ -850,10 +851,10 @@ public function addBNode(NodesToNodes $bNode): static return $this; } - public function clearBNodesForField(NodeTypeField $nodeTypeField): Node + public function clearBNodesForField(NodeTypeFieldInterface $field): Node { - $toRemoveCollection = $this->getBNodes()->filter(function (NodesToNodes $element) use ($nodeTypeField) { - return $element->getField()->getId() === $nodeTypeField->getId(); + $toRemoveCollection = $this->getBNodes()->filter(function (NodesToNodes $element) use ($field) { + return $element->getFieldName() === $field->getName(); }); /** @var NodesToNodes $toRemove */ foreach ($toRemoveCollection as $toRemove) { diff --git a/src/Entity/NodeTypeField.php b/src/Entity/NodeTypeField.php index 83bd7700..07dd18bf 100644 --- a/src/Entity/NodeTypeField.php +++ b/src/Entity/NodeTypeField.php @@ -29,6 +29,7 @@ ORM\Index(columns: ["group_name"]), ORM\Index(columns: ["group_name_canonical"]), ORM\Index(columns: ["type"]), + ORM\Index(columns: ["name"], name: 'ntf_name'), ORM\Index(columns: ["universal"]), ORM\Index(columns: ["node_type_id", "position"], name: "ntf_type_position"), ORM\UniqueConstraint(columns: ["name", "node_type_id"]), @@ -39,11 +40,11 @@ class NodeTypeField extends AbstractField implements NodeTypeFieldInterface, SerializableInterface { #[ - ORM\Column(type: "string", length: 250), + ORM\Column(type: "string", length: 50), Serializer\Expose, Serializer\Groups(["node_type", "setting"]), SymfonySerializer\Groups(["node_type", "setting"]), - Assert\Length(max: 250), + Assert\Length(max: 50), Serializer\Type("string"), RoadizAssert\NonSqlReservedWord(), RoadizAssert\SimpleLatinString() diff --git a/src/Entity/NodesCustomForms.php b/src/Entity/NodesCustomForms.php index cff35a8b..8f7d4a39 100644 --- a/src/Entity/NodesCustomForms.php +++ b/src/Entity/NodesCustomForms.php @@ -18,10 +18,12 @@ ORM\Table(name: "nodes_custom_forms"), ORM\Index(columns: ["position"]), ORM\Index(columns: ["node_id", "position"], name: "customform_node_position"), - ORM\Index(columns: ["node_id", "node_type_field_id", "position"], name: "customform_node_field_position") + ORM\Index(columns: ["node_id", "field_name", "position"], name: "customform_node_field_position") ] class NodesCustomForms extends AbstractPositioned { + use FieldAwareEntityTrait; + #[ORM\ManyToOne(targetEntity: Node::class, fetch: 'EAGER', inversedBy: 'customForms')] #[ORM\JoinColumn(name: 'node_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] protected Node $node; @@ -30,25 +32,21 @@ class NodesCustomForms extends AbstractPositioned #[ORM\JoinColumn(name: 'custom_form_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] protected CustomForm $customForm; - #[ORM\ManyToOne(targetEntity: NodeTypeField::class)] - #[ORM\JoinColumn(name: 'node_type_field_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] - protected NodeTypeField $field; - /** * Create a new relation between a Node, a CustomForm and a NodeTypeField. * * @param Node $node * @param CustomForm $customForm - * @param NodeTypeFieldInterface $field NodeTypeField + * @param NodeTypeFieldInterface|null $field NodeTypeField */ - public function __construct(Node $node, CustomForm $customForm, NodeTypeFieldInterface $field) + public function __construct(Node $node, CustomForm $customForm, ?NodeTypeFieldInterface $field = null) { if (!$field instanceof NodeTypeField) { throw new \InvalidArgumentException('NodesCustomForms only accept NodeTypeField'); } $this->node = $node; $this->customForm = $customForm; - $this->field = $field; + $this->initializeFieldAwareEntityTrait($field); } public function __clone() @@ -101,31 +99,6 @@ public function getCustomForm(): CustomForm public function setCustomForm(CustomForm $customForm): NodesCustomForms { $this->customForm = $customForm; - - return $this; - } - - /** - * Gets the value of field. - * - * @return NodeTypeField - */ - public function getField(): NodeTypeField - { - return $this->field; - } - - /** - * Sets the value of field. - * - * @param NodeTypeField $field the field - * - * @return self - */ - public function setField(NodeTypeField $field): NodesCustomForms - { - $this->field = $field; - return $this; } } diff --git a/src/Entity/NodesSources.php b/src/Entity/NodesSources.php index a7a936a4..8ebc470e 100644 --- a/src/Entity/NodesSources.php +++ b/src/Entity/NodesSources.php @@ -16,6 +16,7 @@ use Gedmo\Loggable\Loggable; use Gedmo\Mapping\Annotation as Gedmo; use JMS\Serializer\Annotation as Serializer; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Core\AbstractEntities\AbstractEntity; use RZ\Roadiz\Core\AbstractEntities\TranslationInterface; use RZ\Roadiz\CoreBundle\Api\Filter as RoadizFilter; @@ -264,11 +265,11 @@ public function addUrlAlias(UrlAlias $urlAlias): NodesSources return $this; } - public function clearDocumentsByFields(NodeTypeField $nodeTypeField): NodesSources + public function clearDocumentsByFields(NodeTypeFieldInterface $field): NodesSources { $toRemoveCollection = $this->getDocumentsByFields()->filter( - function (NodesSourcesDocuments $element) use ($nodeTypeField) { - return $element->getField()->getId() === $nodeTypeField->getId(); + function (NodesSourcesDocuments $element) use ($field) { + return $element->getFieldName() === $field->getName(); } ); /** @var NodesSourcesDocuments $toRemove */ @@ -333,7 +334,7 @@ public function hasNodesSourcesDocuments(NodesSourcesDocuments $nodesSourcesDocu function ($key, NodesSourcesDocuments $element) use ($nodesSourcesDocuments) { return $nodesSourcesDocuments->getDocument()->getId() !== null && $element->getDocument()->getId() === $nodesSourcesDocuments->getDocument()->getId() && - $element->getField()->getId() === $nodesSourcesDocuments->getField()->getId(); + $element->getFieldName() === $nodesSourcesDocuments->getFieldName(); } ); } @@ -359,14 +360,14 @@ public function addDocumentsByFields(NodesSourcesDocuments $nodesSourcesDocument * * @return Document[] */ - public function getDocumentsByFieldsWithField(NodeTypeField $field): array + public function getDocumentsByFieldsWithField(NodeTypeFieldInterface $field): array { $criteria = Criteria::create(); $criteria->orderBy(['position' => 'ASC']); return $this->getDocumentsByFields() ->matching($criteria) ->filter(function (NodesSourcesDocuments $element) use ($field) { - return $element->getField() === $field; + return $element->getFieldName() === $field->getName(); }) ->map(function (NodesSourcesDocuments $nodesSourcesDocuments) { return $nodesSourcesDocuments->getDocument(); @@ -386,7 +387,7 @@ public function getDocumentsByFieldsWithName(string $fieldName): array return $this->getDocumentsByFields() ->matching($criteria) ->filter(function (NodesSourcesDocuments $element) use ($fieldName) { - return $element->getField()->getName() === $fieldName; + return $element->getFieldName() === $fieldName; }) ->map(function (NodesSourcesDocuments $nodesSourcesDocuments) { return $nodesSourcesDocuments->getDocument(); diff --git a/src/Entity/NodesSourcesDocuments.php b/src/Entity/NodesSourcesDocuments.php index 584f8571..6842bba9 100644 --- a/src/Entity/NodesSourcesDocuments.php +++ b/src/Entity/NodesSourcesDocuments.php @@ -18,11 +18,13 @@ ORM\Entity(repositoryClass: NodesSourcesDocumentsRepository::class), ORM\Table(name: "nodes_sources_documents"), ORM\Index(columns: ["position"]), - ORM\Index(columns: ["ns_id", "node_type_field_id"], name: "nsdoc_field"), - ORM\Index(columns: ["ns_id", "node_type_field_id", "position"], name: "nsdoc_field_position") + ORM\Index(columns: ["ns_id", "field_name"], name: "nsdoc_field"), + ORM\Index(columns: ["ns_id", "field_name", "position"], name: "nsdoc_field_position") ] class NodesSourcesDocuments extends AbstractPositioned { + use FieldAwareEntityTrait; + /** * @var NodesSources */ @@ -49,29 +51,21 @@ class NodesSourcesDocuments extends AbstractPositioned #[ORM\JoinColumn(name: 'document_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] protected Document $document; - /** - * @var NodeTypeField - */ - #[ORM\ManyToOne(targetEntity: NodeTypeField::class)] - #[Assert\NotNull] - #[ORM\JoinColumn(name: 'node_type_field_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] - protected NodeTypeField $field; - /** * Create a new relation between NodeSource, a Document and a NodeTypeField. * * @param NodesSources $nodeSource NodesSources and inherited types * @param Document $document Document to link - * @param NodeTypeFieldInterface $field NodeTypeField + * @param NodeTypeFieldInterface|null $field NodeTypeField */ - public function __construct(NodesSources $nodeSource, Document $document, NodeTypeFieldInterface $field) + public function __construct(NodesSources $nodeSource, Document $document, ?NodeTypeFieldInterface $field = null) { if (!$field instanceof NodeTypeField) { throw new \InvalidArgumentException('NodesSourcesDocuments field must be a NodeTypeField instance.'); } $this->nodeSource = $nodeSource; $this->document = $document; - $this->field = $field; + $this->initializeFieldAwareEntityTrait($field); } public function __clone() @@ -128,28 +122,4 @@ public function setDocument(Document $document): NodesSourcesDocuments return $this; } - - /** - * Gets the value of field. - * - * @return NodeTypeField - */ - public function getField(): NodeTypeField - { - return $this->field; - } - - /** - * Sets the value of field. - * - * @param NodeTypeField $field the field - * - * @return self - */ - public function setField(NodeTypeField $field): NodesSourcesDocuments - { - $this->field = $field; - - return $this; - } } diff --git a/src/Entity/NodesToNodes.php b/src/Entity/NodesToNodes.php index e5e73465..b80836c9 100644 --- a/src/Entity/NodesToNodes.php +++ b/src/Entity/NodesToNodes.php @@ -5,6 +5,7 @@ namespace RZ\Roadiz\CoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Core\AbstractEntities\AbstractPositioned; use RZ\Roadiz\CoreBundle\Repository\NodesToNodesRepository; @@ -16,46 +17,28 @@ ORM\Entity(repositoryClass: NodesToNodesRepository::class), ORM\Table(name: "nodes_to_nodes"), ORM\Index(columns: ["position"]), - ORM\Index(columns: ["node_a_id", "node_type_field_id"], name: "node_a_field"), - ORM\Index(columns: ["node_a_id", "node_type_field_id", "position"], name: "node_a_field_position"), - ORM\Index(columns: ["node_b_id", "node_type_field_id"], name: "node_b_field"), - ORM\Index(columns: ["node_b_id", "node_type_field_id", "position"], name: "node_b_field_position") + ORM\Index(columns: ["node_a_id", "field_name"], name: "node_a_field"), + ORM\Index(columns: ["node_a_id", "field_name", "position"], name: "node_a_field_position"), + ORM\Index(columns: ["node_b_id", "field_name"], name: "node_b_field"), + ORM\Index(columns: ["node_b_id", "field_name", "position"], name: "node_b_field_position") ] class NodesToNodes extends AbstractPositioned { - /** - * @var Node - */ + use FieldAwareEntityTrait; + #[ORM\ManyToOne(targetEntity: Node::class, cascade: ['persist'], fetch: 'EAGER', inversedBy: 'bNodes')] #[ORM\JoinColumn(name: 'node_a_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] protected Node $nodeA; - /** - * @var Node - */ #[ORM\ManyToOne(targetEntity: Node::class, cascade: ['persist'], fetch: 'EAGER', inversedBy: 'aNodes')] #[ORM\JoinColumn(name: 'node_b_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] protected Node $nodeB; - /** - * @var NodeTypeField - */ - #[ORM\ManyToOne(targetEntity: NodeTypeField::class)] - #[ORM\JoinColumn(name: 'node_type_field_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] - protected NodeTypeField $field; - - /** - * Create a new relation between two Nodes and a NodeTypeField. - * - * @param Node $nodeA - * @param Node $nodeB - * @param NodeTypeField $field NodeTypeField - */ - public function __construct(Node $nodeA, Node $nodeB, NodeTypeField $field) + public function __construct(Node $nodeA, Node $nodeB, ?NodeTypeFieldInterface $field = null) { $this->nodeA = $nodeA; $this->nodeB = $nodeB; - $this->field = $field; + $this->initializeFieldAwareEntityTrait($field); } public function __clone() @@ -109,31 +92,6 @@ public function getNodeB(): Node public function setNodeB(Node $nodeB): NodesToNodes { $this->nodeB = $nodeB; - - return $this; - } - - /** - * Gets the value of field. - * - * @return NodeTypeField - */ - public function getField(): NodeTypeField - { - return $this->field; - } - - /** - * Sets the value of field. - * - * @param NodeTypeField $field the field - * - * @return self - */ - public function setField(NodeTypeField $field): NodesToNodes - { - $this->field = $field; - return $this; } } diff --git a/src/EntityHandler/NodeHandler.php b/src/EntityHandler/NodeHandler.php index 20398867..3954b388 100644 --- a/src/EntityHandler/NodeHandler.php +++ b/src/EntityHandler/NodeHandler.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\NonUniqueResultException; use Doctrine\Persistence\ObjectManager; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Core\Handlers\AbstractHandler; use RZ\Roadiz\CoreBundle\Entity\CustomForm; use RZ\Roadiz\CoreBundle\Entity\Node; @@ -77,11 +78,11 @@ public function setNode(Node $node): self * @param bool $flush * @return $this */ - public function cleanCustomFormsFromField(NodeTypeField $field, bool $flush = true): self + public function cleanCustomFormsFromField(NodeTypeFieldInterface $field, bool $flush = true): self { $nodesCustomForms = $this->objectManager ->getRepository(NodesCustomForms::class) - ->findBy(['node' => $this->getNode(), 'field' => $field]); + ->findBy(['node' => $this->getNode(), 'fieldName' => $field->getName()]); foreach ($nodesCustomForms as $ncf) { $this->objectManager->remove($ncf); @@ -105,7 +106,7 @@ public function cleanCustomFormsFromField(NodeTypeField $field, bool $flush = tr */ public function addCustomFormForField( CustomForm $customForm, - NodeTypeField $field, + NodeTypeFieldInterface $field, bool $flush = true, ?float $position = null ): self { @@ -114,7 +115,7 @@ public function addCustomFormForField( if (null === $position) { $latestPosition = $this->objectManager ->getRepository(NodesCustomForms::class) - ->getLatestPosition($this->getNode(), $field); + ->getLatestPositionForFieldName($this->getNode(), $field->getName()); $ncf->setPosition($latestPosition + 1); } else { $ncf->setPosition($position); @@ -139,9 +140,9 @@ public function getCustomFormsFromFieldName(string $fieldName): array { return $this->objectManager ->getRepository(CustomForm::class) - ->findByNodeAndField( + ->findByNodeAndFieldName( $this->getNode(), - $this->getNode()->getNodeType()->getFieldByName($fieldName) + $fieldName ); } @@ -152,7 +153,7 @@ public function getCustomFormsFromFieldName(string $fieldName): array * @param bool $flush * @return $this */ - public function cleanNodesFromField(NodeTypeField $field, bool $flush = true): self + public function cleanNodesFromField(NodeTypeFieldInterface $field, bool $flush = true): self { $this->node->clearBNodesForField($field); @@ -172,7 +173,7 @@ public function cleanNodesFromField(NodeTypeField $field, bool $flush = true): s * @param null|float $position * @return $this */ - public function addNodeForField(Node $node, NodeTypeField $field, bool $flush = true, ?float $position = null): self + public function addNodeForField(Node $node, NodeTypeFieldInterface $field, bool $flush = true, ?float $position = null): self { $ntn = new NodesToNodes($this->getNode(), $node, $field); @@ -180,7 +181,7 @@ public function addNodeForField(Node $node, NodeTypeField $field, bool $flush = if (null === $position) { $latestPosition = $this->objectManager ->getRepository(NodesToNodes::class) - ->getLatestPosition($this->getNode(), $field); + ->getLatestPositionForFieldName($this->getNode(), $field->getName()); $ntn->setPosition($latestPosition + 1); } else { $ntn->setPosition($position); diff --git a/src/EntityHandler/NodesSourcesHandler.php b/src/EntityHandler/NodesSourcesHandler.php index 1945543e..55b2eb90 100644 --- a/src/EntityHandler/NodesSourcesHandler.php +++ b/src/EntityHandler/NodesSourcesHandler.php @@ -6,6 +6,7 @@ use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectManager; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Core\Handlers\AbstractHandler; use RZ\Roadiz\CoreBundle\Bag\Settings; use RZ\Roadiz\CoreBundle\Entity\Document; @@ -67,7 +68,7 @@ public function setNodeSource(NodesSources $nodeSource): self * @param bool $flush * @return $this */ - public function cleanDocumentsFromField(NodeTypeField $field, bool $flush = true): self + public function cleanDocumentsFromField(NodeTypeFieldInterface $field, bool $flush = true): self { $this->nodeSource->clearDocumentsByFields($field); @@ -89,7 +90,7 @@ public function cleanDocumentsFromField(NodeTypeField $field, bool $flush = true */ public function addDocumentForField( Document $document, - NodeTypeField $field, + NodeTypeFieldInterface $field, bool $flush = true, ?float $position = null ): self { @@ -99,7 +100,7 @@ public function addDocumentForField( if (null === $position) { $latestPosition = $this->objectManager ->getRepository(NodesSourcesDocuments::class) - ->getLatestPosition($this->nodeSource, $field); + ->getLatestPositionForFieldName($this->nodeSource, $field->getName()); $nsDoc->setPosition($latestPosition + 1); } else { @@ -124,16 +125,12 @@ public function addDocumentForField( */ public function getDocumentsFromFieldName(string $fieldName): array { - $field = $this->nodeSource->getNode()->getNodeType()->getFieldByName($fieldName); - if (null !== $field) { - return $this->objectManager - ->getRepository(Document::class) - ->findByNodeSourceAndField( - $this->nodeSource, - $field - ); - } - return []; + return $this->objectManager + ->getRepository(Document::class) + ->findByNodeSourceAndFieldName( + $this->nodeSource, + $fieldName + ); } /** diff --git a/src/Node/NodeDuplicator.php b/src/Node/NodeDuplicator.php index 0c1d6131..da995e69 100644 --- a/src/Node/NodeDuplicator.php +++ b/src/Node/NodeDuplicator.php @@ -102,8 +102,7 @@ private function doDuplicate(Node &$node): Node $nsDoc->setNodeSource($nodeSource); $doc = $nsDoc->getDocument(); $nsDoc->setDocument($doc); - $f = $nsDoc->getField(); - $nsDoc->setField($f); + $nsDoc->setFieldName($nsDoc->getFieldName()); $this->objectManager->persist($nsDoc); } } @@ -141,9 +140,11 @@ private function doDuplicate(Node &$node): Node */ private function doDuplicateNodeRelations(Node $node): Node { - $nodeRelations = new ArrayCollection($node->getBNodes()->toArray()); + /** @var NodesToNodes[] $nodeRelations */ + $nodeRelations = $node->getBNodes()->toArray(); foreach ($nodeRelations as $position => $nodeRelation) { - $ntn = new NodesToNodes($node, $nodeRelation->getNodeB(), $nodeRelation->getField()); + $ntn = new NodesToNodes($node, $nodeRelation->getNodeB()); + $ntn->setFieldName($nodeRelation->getFieldName()); $ntn->setPosition($position); $this->objectManager->persist($ntn); } diff --git a/src/Node/NodeTranstyper.php b/src/Node/NodeTranstyper.php index 8ea9d2a4..2109757e 100644 --- a/src/Node/NodeTranstyper.php +++ b/src/Node/NodeTranstyper.php @@ -97,6 +97,7 @@ public function transtype(Node $node, NodeTypeInterface $destinationNodeType, bo } $this->logger->debug('Get matching fields'); + /** @var class-string $sourceClass */ $sourceClass = $destinationNodeType->getSourceEntityFullQualifiedClassName(); /* @@ -164,7 +165,7 @@ protected function removeOldSources(Node $node, array &$sources): void * @param Node $node * @param NodesSources $existingSource * @param TranslationInterface $translation - * @param string $sourceClass + * @param class-string $sourceClass * @param array $fieldAssociations * @param array $existingRedirections * @return NodesSources @@ -201,7 +202,8 @@ protected function doTranstypeSingleSource( */ $documents = $existingSource->getDocumentsByFieldsWithName($oldField->getName()); foreach ($documents as $document) { - $nsDoc = new NodesSourcesDocuments($source, $document, $matchingField); + $nsDoc = new NodesSourcesDocuments($source, $document); + $nsDoc->setFieldName($matchingField->getName()); $this->getManager()->persist($nsDoc); $source->getDocumentsByFields()->add($nsDoc); } diff --git a/src/Node/UniversalDataDuplicator.php b/src/Node/UniversalDataDuplicator.php index 41b0ae45..c806f3ae 100644 --- a/src/Node/UniversalDataDuplicator.php +++ b/src/Node/UniversalDataDuplicator.php @@ -5,6 +5,7 @@ namespace RZ\Roadiz\CoreBundle\Node; use Doctrine\Persistence\ManagerRegistry; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\Core\AbstractEntities\AbstractField; use RZ\Roadiz\CoreBundle\Entity\NodesSources; use RZ\Roadiz\CoreBundle\Entity\NodesSourcesDocuments; @@ -110,15 +111,10 @@ private function hasDefaultTranslation(NodesSources $source): bool return $sourceCount === 1; } - /** - * @param NodesSources $universalSource - * @param NodesSources $destSource - * @param NodeTypeField $field - */ protected function duplicateNonVirtualField( NodesSources $universalSource, NodesSources $destSource, - NodeTypeField $field + NodeTypeFieldInterface $field ): void { $getter = $field->getGetterName(); $setter = $field->getSetterName(); @@ -126,23 +122,18 @@ protected function duplicateNonVirtualField( $destSource->$setter($universalSource->$getter()); } - /** - * @param NodesSources $universalSource - * @param NodesSources $destSource - * @param NodeTypeField $field - */ protected function duplicateDocumentsField( NodesSources $universalSource, NodesSources $destSource, - NodeTypeField $field + NodeTypeFieldInterface $field ): void { $newDocuments = $this->managerRegistry ->getRepository(NodesSourcesDocuments::class) - ->findBy(['nodeSource' => $universalSource, 'field' => $field]); + ->findBy(['nodeSource' => $universalSource, 'fieldName' => $field->getName()]); $formerDocuments = $this->managerRegistry ->getRepository(NodesSourcesDocuments::class) - ->findBy(['nodeSource' => $destSource, 'field' => $field]); + ->findBy(['nodeSource' => $destSource, 'fieldName' => $field->getName()]); $manager = $this->managerRegistry->getManagerForClass(NodesSourcesDocuments::class); if (null === $manager) { diff --git a/src/Repository/CustomFormRepository.php b/src/Repository/CustomFormRepository.php index 027ea52e..62df6b92 100644 --- a/src/Repository/CustomFormRepository.php +++ b/src/Repository/CustomFormRepository.php @@ -33,14 +33,38 @@ public function findAllWithRetentionTime(): array ->getResult(); } + /** + * @param Node $node + * @param NodeTypeFieldInterface $field + * @return CustomForm[] + * @deprecated Use findByNodeAndFieldName instead + */ public function findByNodeAndField(Node $node, NodeTypeFieldInterface $field): array { $query = $this->_em->createQuery(' SELECT cf FROM RZ\Roadiz\CoreBundle\Entity\CustomForm cf INNER JOIN cf.nodes ncf - WHERE ncf.field = :field AND ncf.node = :node + WHERE ncf.fieldName = :fieldName AND ncf.node = :node + ORDER BY ncf.position ASC') + ->setParameter('fieldName', $field->getName()) + ->setParameter('node', $node); + + return $query->getResult(); + } + + /** + * @param Node $node + * @param string $fieldName + * @return CustomForm[] + */ + public function findByNodeAndFieldName(Node $node, string $fieldName): array + { + $query = $this->_em->createQuery(' + SELECT cf FROM RZ\Roadiz\CoreBundle\Entity\CustomForm cf + INNER JOIN cf.nodes ncf + WHERE ncf.fieldName = :fieldName AND ncf.node = :node ORDER BY ncf.position ASC') - ->setParameter('field', $field) + ->setParameter('fieldName', $fieldName) ->setParameter('node', $node); return $query->getResult(); diff --git a/src/Repository/DocumentRepository.php b/src/Repository/DocumentRepository.php index e92ba864..163c8268 100644 --- a/src/Repository/DocumentRepository.php +++ b/src/Repository/DocumentRepository.php @@ -528,7 +528,8 @@ public function countBy( /** * @param NodesSources $nodeSource * @param NodeTypeFieldInterface $field - * @return array + * @return array + * @deprecated Use findByNodeSourceAndFieldName instead */ public function findByNodeSourceAndField( NodesSources $nodeSource, @@ -538,10 +539,10 @@ public function findByNodeSourceAndField( $qb->addSelect('dt') ->leftJoin('d.documentTranslations', 'dt', 'WITH', 'dt.translation = :translation') ->innerJoin('d.nodesSourcesByFields', 'nsf', 'WITH', 'nsf.nodeSource = :nodeSource') - ->andWhere($qb->expr()->eq('nsf.field', ':field')) + ->andWhere($qb->expr()->eq('nsf.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('d.raw', ':raw')) ->addOrderBy('nsf.position', 'ASC') - ->setParameter('field', $field) + ->setParameter('fieldName', $field->getName()) ->setParameter('nodeSource', $nodeSource) ->setParameter('translation', $nodeSource->getTranslation()) ->setParameter('raw', false) @@ -552,21 +553,21 @@ public function findByNodeSourceAndField( /** * @param NodesSources $nodeSource - * @param int $fieldId - * @return array + * @param string $fieldName + * @return array */ - public function findByNodeSourceAndFieldId( + public function findByNodeSourceAndFieldName( NodesSources $nodeSource, - int $fieldId + string $fieldName ): array { $qb = $this->createQueryBuilder('d'); $qb->addSelect('dt') ->leftJoin('d.documentTranslations', 'dt', 'WITH', 'dt.translation = :translation') ->innerJoin('d.nodesSourcesByFields', 'nsf', 'WITH', 'nsf.nodeSource = :nodeSource') - ->andWhere($qb->expr()->eq('nsf.field', ':field')) + ->andWhere($qb->expr()->eq('nsf.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('d.raw', ':raw')) ->addOrderBy('nsf.position', 'ASC') - ->setParameter('field', $fieldId) + ->setParameter('fieldName', $fieldName) ->setParameter('nodeSource', $nodeSource) ->setParameter('translation', $nodeSource->getTranslation()) ->setParameter('raw', false) diff --git a/src/Repository/NodeRepository.php b/src/Repository/NodeRepository.php index a9782831..2d298d0b 100644 --- a/src/Repository/NodeRepository.php +++ b/src/Repository/NodeRepository.php @@ -809,14 +809,14 @@ public function findByNodeAndField( $qb = $this->createQueryBuilder(self::NODE_ALIAS); $qb->select(self::NODE_ALIAS) ->innerJoin('n.aNodes', 'ntn') - ->andWhere($qb->expr()->eq('ntn.field', ':field')) + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('ntn.nodeA', ':nodeA')) ->addOrderBy('ntn.position', 'ASC') ->setCacheable(true); $this->alterQueryBuilderWithAuthorizationChecker($qb); - $qb->setParameter('field', $field) + $qb->setParameter('fieldName', $field->getName()) ->setParameter('nodeA', $node); return $qb->getQuery()->getResult(); @@ -837,7 +837,7 @@ public function findByNodeAndFieldAndTranslation( $qb->select('n, ns') ->innerJoin('n.aNodes', 'ntn') ->innerJoin('n.nodeSources', self::NODESSOURCES_ALIAS) - ->andWhere($qb->expr()->eq('ntn.field', ':field')) + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('ntn.nodeA', ':nodeA')) ->andWhere($qb->expr()->eq('ns.translation', ':translation')) ->addOrderBy('ntn.position', 'ASC') @@ -845,7 +845,7 @@ public function findByNodeAndFieldAndTranslation( $this->alterQueryBuilderWithAuthorizationChecker($qb); - $qb->setParameter('field', $field) + $qb->setParameter('fieldName', $field->getName()) ->setParameter('nodeA', $node) ->setParameter('translation', $translation); @@ -864,14 +864,14 @@ public function findByReverseNodeAndField( $qb = $this->createQueryBuilder(self::NODE_ALIAS); $qb->select(self::NODE_ALIAS) ->innerJoin('n.bNodes', 'ntn') - ->andWhere($qb->expr()->eq('ntn.field', ':field')) + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('ntn.nodeB', ':nodeB')) ->addOrderBy('ntn.position', 'ASC') ->setCacheable(true); $this->alterQueryBuilderWithAuthorizationChecker($qb); - $qb->setParameter('field', $field) + $qb->setParameter('fieldName', $field->getName()) ->setParameter('nodeB', $node); return $qb->getQuery()->getResult(); @@ -892,7 +892,7 @@ public function findByReverseNodeAndFieldAndTranslation( $qb->select('n, ns') ->innerJoin('n.bNodes', 'ntn') ->innerJoin('n.nodeSources', self::NODESSOURCES_ALIAS) - ->andWhere($qb->expr()->eq('ntn.field', ':field')) + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('ns.translation', ':translation')) ->andWhere($qb->expr()->eq('ntn.nodeB', ':nodeB')) ->addOrderBy('ntn.position', 'ASC') @@ -900,7 +900,7 @@ public function findByReverseNodeAndFieldAndTranslation( $this->alterQueryBuilderWithAuthorizationChecker($qb); - $qb->setParameter('field', $field) + $qb->setParameter('fieldName', $field->getName()) ->setParameter('translation', $translation) ->setParameter('nodeB', $node); diff --git a/src/Repository/NodesCustomFormsRepository.php b/src/Repository/NodesCustomFormsRepository.php index dc41cec0..112e0e90 100644 --- a/src/Repository/NodesCustomFormsRepository.php +++ b/src/Repository/NodesCustomFormsRepository.php @@ -5,6 +5,7 @@ namespace RZ\Roadiz\CoreBundle\Repository; use Doctrine\Persistence\ManagerRegistry; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\CoreBundle\Entity\Node; use RZ\Roadiz\CoreBundle\Entity\NodesCustomForms; use RZ\Roadiz\CoreBundle\Entity\NodeTypeField; @@ -22,20 +23,38 @@ public function __construct( ) { parent::__construct($registry, NodesCustomForms::class, $dispatcher); } + /** - * @param Node $node - * @param NodeTypeField $field - * - * @return integer + * @param Node $node + * @param NodeTypeFieldInterface $field + * @return int + * @throws \Doctrine\ORM\NoResultException + * @throws \Doctrine\ORM\NonUniqueResultException + * @deprecated Use getLatestPositionForFieldName instead */ - public function getLatestPosition(Node $node, NodeTypeField $field) + public function getLatestPosition(Node $node, NodeTypeFieldInterface $field): int + { + $query = $this->_em->createQuery(' + SELECT MAX(ncf.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesCustomForms ncf + WHERE ncf.node = :node AND ncf.fieldName = :fieldName') + ->setParameter('node', $node) + ->setParameter('fieldName', $field->getName()); + + $latestPosition = $query->getSingleScalarResult(); + + return is_numeric($latestPosition) ? (int) $latestPosition : 0; + } + + public function getLatestPositionForFieldName(Node $node, string $fieldName): int { $query = $this->_em->createQuery(' SELECT MAX(ncf.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesCustomForms ncf - WHERE ncf.node = :node AND ncf.field = :field') + WHERE ncf.node = :node AND ncf.fieldName = :fieldName') ->setParameter('node', $node) - ->setParameter('field', $field); + ->setParameter('fieldName', $fieldName); + + $latestPosition = $query->getSingleScalarResult(); - return (int) $query->getSingleScalarResult(); + return is_numeric($latestPosition) ? (int) $latestPosition : 0; } } diff --git a/src/Repository/NodesSourcesDocumentsRepository.php b/src/Repository/NodesSourcesDocumentsRepository.php index 0c24dc5d..3cc0ea1c 100644 --- a/src/Repository/NodesSourcesDocumentsRepository.php +++ b/src/Repository/NodesSourcesDocumentsRepository.php @@ -7,6 +7,7 @@ use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; use Doctrine\Persistence\ManagerRegistry; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\CoreBundle\Entity\NodesSources; use RZ\Roadiz\CoreBundle\Entity\NodesSourcesDocuments; use RZ\Roadiz\CoreBundle\Entity\NodeTypeField; @@ -26,19 +27,35 @@ public function __construct( /** * @param NodesSources $nodeSource - * @param NodeTypeField $field + * @param NodeTypeFieldInterface $field * @return int * @throws NoResultException * @throws NonUniqueResultException + * @deprecated Use getLatestPositionForFieldName instead */ - public function getLatestPosition(NodesSources $nodeSource, NodeTypeField $field): int + public function getLatestPosition(NodesSources $nodeSource, NodeTypeFieldInterface $field): int { $query = $this->_em->createQuery(' SELECT MAX(nsd.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesSourcesDocuments nsd - WHERE nsd.nodeSource = :nodeSource AND nsd.field = :field') + WHERE nsd.nodeSource = :nodeSource AND nsd.fieldName = :fieldName') ->setParameter('nodeSource', $nodeSource) - ->setParameter('field', $field); + ->setParameter('fieldName', $field->getName()); - return (int) $query->getSingleScalarResult(); + $latestPosition = $query->getSingleScalarResult(); + + return is_numeric($latestPosition) ? (int) $latestPosition : 0; + } + + public function getLatestPositionForFieldName(NodesSources $nodeSource, string $fieldName): int + { + $query = $this->_em->createQuery(' + SELECT MAX(nsd.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesSourcesDocuments nsd + WHERE nsd.nodeSource = :nodeSource AND nsd.fieldName = :fieldName') + ->setParameter('nodeSource', $nodeSource) + ->setParameter('fieldName', $fieldName); + + $latestPosition = $query->getSingleScalarResult(); + + return is_numeric($latestPosition) ? (int) $latestPosition : 0; } } diff --git a/src/Repository/NodesSourcesRepository.php b/src/Repository/NodesSourcesRepository.php index 2103a098..088a52cd 100644 --- a/src/Repository/NodesSourcesRepository.php +++ b/src/Repository/NodesSourcesRepository.php @@ -700,7 +700,7 @@ public function searchBy( /** * @param NodesSources $nodesSources * @param NodeTypeFieldInterface $field - * + * @deprecated Use findByNodesSourcesAndFieldNameAndTranslation instead * @return array|null */ public function findByNodesSourcesAndFieldAndTranslation( @@ -712,7 +712,37 @@ public function findByNodesSourcesAndFieldAndTranslation( ->innerJoin('ns.node', static::NODE_ALIAS) ->leftJoin('ns.urlAliases', 'ua') ->innerJoin('n.aNodes', 'ntn') - ->andWhere($qb->expr()->eq('ntn.field', ':field')) + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) + ->andWhere($qb->expr()->eq('ntn.nodeA', ':nodeA')) + ->andWhere($qb->expr()->eq('ns.translation', ':translation')) + ->addOrderBy('ntn.position', 'ASC') + ->setCacheable(true); + + $this->alterQueryBuilderWithAuthorizationChecker($qb); + + $qb->setParameter('fieldName', $field->getName()) + ->setParameter('nodeA', $nodesSources->getNode()) + ->setParameter('translation', $nodesSources->getTranslation()); + + return $qb->getQuery()->getResult(); + } + + /** + * @param NodesSources $nodesSources + * @param string $fieldName + * + * @return array|null + */ + public function findByNodesSourcesAndFieldNameAndTranslation( + NodesSources $nodesSources, + string $fieldName + ): ?array { + $qb = $this->createQueryBuilder(static::NODESSOURCES_ALIAS); + $qb->select('ns, n, ua') + ->innerJoin('ns.node', static::NODE_ALIAS) + ->leftJoin('ns.urlAliases', 'ua') + ->innerJoin('n.aNodes', 'ntn') + ->andWhere($qb->expr()->eq('ntn.fieldName', ':fieldName')) ->andWhere($qb->expr()->eq('ntn.nodeA', ':nodeA')) ->andWhere($qb->expr()->eq('ns.translation', ':translation')) ->addOrderBy('ntn.position', 'ASC') @@ -720,7 +750,7 @@ public function findByNodesSourcesAndFieldAndTranslation( $this->alterQueryBuilderWithAuthorizationChecker($qb); - $qb->setParameter('field', $field) + $qb->setParameter('fieldName', $fieldName) ->setParameter('nodeA', $nodesSources->getNode()) ->setParameter('translation', $nodesSources->getTranslation()); diff --git a/src/Repository/NodesToNodesRepository.php b/src/Repository/NodesToNodesRepository.php index a64042a3..d23079d9 100644 --- a/src/Repository/NodesToNodesRepository.php +++ b/src/Repository/NodesToNodesRepository.php @@ -7,6 +7,7 @@ use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; use Doctrine\Persistence\ManagerRegistry; +use RZ\Roadiz\Contracts\NodeType\NodeTypeFieldInterface; use RZ\Roadiz\CoreBundle\Entity\Node; use RZ\Roadiz\CoreBundle\Entity\NodesToNodes; use RZ\Roadiz\CoreBundle\Entity\NodeTypeField; @@ -27,20 +28,35 @@ public function __construct( /** * @param Node $node - * @param NodeTypeField $field - * - * @return integer + * @param NodeTypeFieldInterface $field + * @return int * @throws NoResultException * @throws NonUniqueResultException + * @deprecated Use getLatestPositionForFieldName instead */ - public function getLatestPosition(Node $node, NodeTypeField $field): int + public function getLatestPosition(Node $node, NodeTypeFieldInterface $field): int { $query = $this->_em->createQuery(' SELECT MAX(ntn.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesToNodes ntn - WHERE ntn.nodeA = :nodeA AND ntn.field = :field') + WHERE ntn.nodeA = :nodeA AND ntn.fieldName = :fieldName') ->setParameter('nodeA', $node) - ->setParameter('field', $field); + ->setParameter('fieldName', $field->getName()); - return (int) $query->getSingleScalarResult(); + $latestPosition = $query->getSingleScalarResult(); + + return is_numeric($latestPosition) ? (int) $latestPosition : 0; + } + + public function getLatestPositionForFieldName(Node $node, string $fieldName): int + { + $query = $this->_em->createQuery(' + SELECT MAX(ntn.position) FROM RZ\Roadiz\CoreBundle\Entity\NodesToNodes ntn + WHERE ntn.nodeA = :nodeA AND ntn.fieldName = :fieldName') + ->setParameter('nodeA', $node) + ->setParameter('fieldName', $fieldName); + + $latestPosition = $query->getSingleScalarResult(); + + return is_numeric($latestPosition) ? (int) $latestPosition : 0; } }