Skip to content

Commit

Permalink
[Data Object Editor] Use same format for relation normalizers like fo…
Browse files Browse the repository at this point in the history
…r manyToManyRelation (#710)

* adapt relation adapters

* Apply php-cs-fixer changes
  • Loading branch information
lukmzig authored Jan 21, 2025
1 parent b406747 commit 1d4bd63
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
namespace Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Adapter;

use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ConcreteObjectResolverInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\DataNormalizerInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\FieldContextData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\SetterDataInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationDataTrait;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationMetadataTrait;
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\ElementTypes;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\ClassDefinition\Data\AdvancedManyToManyObjectRelation;
use Pimcore\Model\DataObject\Concrete;
Expand All @@ -31,8 +35,11 @@
* @internal
*/
#[AutoconfigureTag(DataAdapterLoaderInterface::ADAPTER_TAG)]
final readonly class AdvancedManyToManyObjectRelationAdapter implements SetterDataInterface
final readonly class AdvancedManyToManyObjectRelationAdapter implements SetterDataInterface, DataNormalizerInterface
{
use RelationDataTrait;
use RelationMetadataTrait;

public function __construct(
private ConcreteObjectResolverInterface $concreteObjectResolver
) {
Expand All @@ -54,6 +61,26 @@ public function getDataForSetter(
return $this->buildRelationsMetadata($relationData, $fieldDefinition);
}

public function normalize(
mixed $value,
Data $fieldDefinition
): ?array {
if (!is_array($value)) {
return null;
}

$normalizedData = [];
foreach ($value as $relation) {
if (!$relation instanceof ObjectMetadata) {
continue;
}

$normalizedData[] = $this->getAdvancedRelationElementData($relation);
}

return $normalizedData;
}

private function buildRelationsMetadata(array $relationData, Data $fieldDefinition): array
{
if (!$fieldDefinition instanceof AdvancedManyToManyObjectRelation) {
Expand All @@ -62,39 +89,21 @@ private function buildRelationsMetadata(array $relationData, Data $fieldDefiniti

$relationsMetadata = [];
foreach ($relationData as $relation) {
$object = $this->concreteObjectResolver->getById($relation['id']);
if ($object && $object->getClassName() === $fieldDefinition->getAllowedClassId()) {
$relationsMetadata[] = $this->createObjectMetadata($object, $fieldDefinition, $relation);
if (empty($relation['element']['id']) || $relation['element']['type'] !== ElementTypes::TYPE_OBJECT) {
continue;
}
}

return $relationsMetadata;
}

private function createObjectMetadata(
Concrete $object,
AdvancedManyToManyObjectRelation $fieldDefinition,
array $relation,
): ObjectMetadata {
$metaData = new ObjectMetadata(
$fieldDefinition->getName(),
$fieldDefinition->getColumnKeys(),
$object
);
$metaData->_setOwner($object);
$metaData->_setOwnerFieldname($fieldDefinition->getName());

foreach ($fieldDefinition->getColumns() as $column) {
$setter = 'set' . ucfirst($column['key']);
$value = $relation[$column['key']] ?? null;

if ($column['type'] === 'multiselect' && is_array($value)) {
$value = implode(',', $value);
$object = $this->concreteObjectResolver->getById($relation['element']['id']);
if ($object && $object->getClassName() === $fieldDefinition->getAllowedClassId()) {
$fieldName = $fieldDefinition->getName();
$relationsMetadata[] = $this->addRelationMetadata(
$object,
$relation['data'],
new ObjectMetadata($fieldName, $fieldDefinition->getColumnKeys(), $object)
);
}

$metaData->$setter($value);
}

return $metaData;
return $relationsMetadata;
}
}
72 changes: 37 additions & 35 deletions src/DataObject/Data/Adapter/AdvancedManyToManyRelationAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,27 @@

use Exception;
use Pimcore\Bundle\StaticResolverBundle\Models\Element\ServiceResolverInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\DataNormalizerInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\FieldContextData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\SetterDataInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface;
use Pimcore\Bundle\StudioBackendBundle\Util\Trait\ElementProviderTrait;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationDataTrait;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationMetadataTrait;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\ClassDefinition\Data\AdvancedManyToManyRelation;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Model\DataObject\Data\ElementMetadata;
use Pimcore\Model\Element\ElementInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use function is_array;

/**
* @internal
*/
#[AutoconfigureTag(DataAdapterLoaderInterface::ADAPTER_TAG)]
final readonly class AdvancedManyToManyRelationAdapter implements SetterDataInterface
final readonly class AdvancedManyToManyRelationAdapter implements SetterDataInterface, DataNormalizerInterface
{
use ElementProviderTrait;
use RelationDataTrait;
use RelationMetadataTrait;

public function __construct(
private ServiceResolverInterface $serviceResolver
Expand All @@ -61,6 +63,26 @@ public function getDataForSetter(
return $this->buildRelationsMetadata($relationData, $fieldDefinition);
}

public function normalize(
mixed $value,
Data $fieldDefinition
): ?array {
if (!is_array($value)) {
return null;
}

$normalizedData = [];
foreach ($value as $relation) {
if (!$relation instanceof ElementMetadata) {
continue;
}

$normalizedData[] = $this->getAdvancedRelationElementData($relation);
}

return $normalizedData;
}

/**
* @throws Exception
*/
Expand All @@ -72,40 +94,20 @@ private function buildRelationsMetadata(array $relationData, Data $fieldDefiniti

$relationsMetadata = [];
foreach ($relationData as $relation) {
$element = $this->getElement($this->serviceResolver, $relation['type'], $relation['id']);
$relationsMetadata[] = $this->createObjectMetadata($element, $fieldDefinition, $relation);
}

return $relationsMetadata;
}

/**
* @throws Exception
*/
private function createObjectMetadata(
ElementInterface $element,
AdvancedManyToManyRelation $fieldDefinition,
array $relation,
): ElementMetadata {
$metaData = new ElementMetadata(
$fieldDefinition->getName(),
$fieldDefinition->getColumnKeys(),
$element
);
$metaData->_setOwner($element);
$metaData->_setOwnerFieldname($fieldDefinition->getName());

foreach ($fieldDefinition->getColumns() as $column) {
$setter = 'set' . ucfirst($column['key']);
$value = $relation[$column['key']] ?? null;

if ($column['type'] === 'multiselect' && is_array($value)) {
$value = implode(',', $value);
$elementData = $relation['element'];
if (empty($elementData['id']) || empty($elementData['type'])) {
continue;
}

$metaData->$setter($value);
$element = $this->getElement($this->serviceResolver, $elementData['type'], $elementData['id']);
$fieldName = $fieldDefinition->getName();
$relationsMetadata[] = $this->addRelationMetadata(
$element,
$relation['data'],
new ElementMetadata($fieldName, $fieldDefinition->getColumnKeys(), $element)
);
}

return $metaData;
return $relationsMetadata;
}
}
21 changes: 20 additions & 1 deletion src/DataObject/Data/Adapter/ManyToManyObjectRelationAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
namespace Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Adapter;

use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ConcreteObjectResolverInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\DataNormalizerInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\FieldContextData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\RelationData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\SetterDataInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationDataTrait;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\Concrete;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
Expand All @@ -29,8 +32,10 @@
* @internal
*/
#[AutoconfigureTag(DataAdapterLoaderInterface::ADAPTER_TAG)]
final readonly class ManyToManyObjectRelationAdapter implements SetterDataInterface
final readonly class ManyToManyObjectRelationAdapter implements SetterDataInterface, DataNormalizerInterface
{
use RelationDataTrait;

public function __construct(
private ConcreteObjectResolverInterface $concreteObjectResolver
) {
Expand All @@ -51,6 +56,20 @@ public function getDataForSetter(
return $this->getRelationObjects($relationData);
}

/**
* @return RelationData[]|null
*/
public function normalize(
mixed $value,
Data $fieldDefinition
): ?array {
if (!is_array($value)) {
return null;
}

return $this->getRelationElementsData($value);
}

private function getRelationObjects(array $relationData): array
{
$objects = [];
Expand Down
39 changes: 3 additions & 36 deletions src/DataObject/Data/Adapter/ManyToManyRelationAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\RelationData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\SetterDataInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationDataTrait;
use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException;
use Pimcore\Bundle\StudioBackendBundle\Util\Trait\ElementProviderTrait;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Model\Document;
use Pimcore\Model\Element\ElementInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use function is_array;

Expand All @@ -37,7 +35,7 @@
#[AutoconfigureTag(DataAdapterLoaderInterface::ADAPTER_TAG)]
final readonly class ManyToManyRelationAdapter implements SetterDataInterface, DataNormalizerInterface
{
use ElementProviderTrait;
use RelationDataTrait;

public function __construct(
private ServiceResolverInterface $serviceResolver
Expand Down Expand Up @@ -70,20 +68,7 @@ public function normalize(
return null;
}

$data = [];
/** @var ElementInterface[] $value */
foreach ($value as $relation) {
$elementType = $this->getElementType($relation);
$data[] = new RelationData(
$relation->getId(),
$elementType,
$this->getSubType($relation),
$relation->getRealFullPath(),
$this->getPublished($relation)
);
}

return $data;
return $this->getRelationElementsData($value);
}

private function getRelationElements(array $relationData): array
Expand All @@ -101,22 +86,4 @@ private function getRelationElements(array $relationData): array

return $relations;
}

private function getSubType(ElementInterface $element): string
{
if ($element instanceof Concrete) {
return $element->getClassName();
}

return $element->getType();
}

private function getPublished(ElementInterface $element): ?bool
{
if ($element instanceof Concrete || $element instanceof Document) {
return $element->getPublished();
}

return null;
}
}
21 changes: 20 additions & 1 deletion src/DataObject/Data/Adapter/ReverseObjectRelationAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
use Exception;
use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ClassDefinitionResolverInterface;
use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ConcreteObjectResolverInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\DataNormalizerInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\FieldContextData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Model\RelationData;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Data\SetterDataInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Util\Trait\RelationDataTrait;
use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\ClassDefinition\Data\ReverseObjectRelation;
Expand All @@ -35,8 +38,10 @@
* @internal
*/
#[AutoconfigureTag(DataAdapterLoaderInterface::ADAPTER_TAG)]
final readonly class ReverseObjectRelationAdapter implements SetterDataInterface
final readonly class ReverseObjectRelationAdapter implements SetterDataInterface, DataNormalizerInterface
{
use RelationDataTrait;

public function __construct(
private ClassDefinitionResolverInterface $classDefinitionResolver,
private ConcreteObjectResolverInterface $concreteObjectResolver,
Expand Down Expand Up @@ -72,6 +77,20 @@ public function getDataForSetter(
return null;
}

/**
* @return RelationData[]|null
*/
public function normalize(
mixed $value,
Data $fieldDefinition
): ?array {
if (!is_array($value)) {
return null;
}

return $this->getRelationElementsData($value);
}

private function processRemoteOwnerRelations(
Concrete $element,
array $relations,
Expand Down
Loading

0 comments on commit 1d4bd63

Please sign in to comment.