Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c2ba248
Finalize
woellundwoell Sep 13, 2021
8cc8b6e
Apply php-cs-fixer changes
woellundwoell Sep 13, 2021
b338b89
Merge branch '1.x' into data-target-extension
mcop1 Sep 22, 2021
f3c3566
Implement advanced relations
woellundwoell Sep 28, 2021
31d1488
Apply php-cs-fixer changes
woellundwoell Sep 28, 2021
5927b70
Implement option visibility
woellundwoell Sep 28, 2021
eb91305
Language fixes
woellundwoell Sep 28, 2021
887f3e0
Merge branch '1.x' into data-target-advanced-relations
woellundwoell Sep 28, 2021
80214d9
Development second solution
woellundwoell Sep 29, 2021
93bcb35
Apply php-cs-fixer changes
woellundwoell Sep 30, 2021
8e51854
Second solution - beta
woellundwoell Sep 30, 2021
fcfc301
Cleanup formatting
woellundwoell Sep 30, 2021
471bc69
Cleanup debug
woellundwoell Sep 30, 2021
3327b40
Development step 3
woellundwoell Sep 30, 2021
29eac91
Bugfix wrong var name
woellundwoell Sep 30, 2021
0e1e1ee
Bugfix
woellundwoell Sep 30, 2021
acc4758
Bugfix Accidentally deleted JS code
woellundwoell Oct 7, 2021
cb01cc4
Fix JS filename
woellundwoell Oct 7, 2021
ffd48dd
Improve overwite mode
woellundwoell Oct 7, 2021
b59eaf5
Apply php-cs-fixer changes
woellundwoell Oct 7, 2021
e0ecb93
* Change defaults for overwrite
woellundwoell Oct 11, 2021
f184b57
readded missing translation
fashxp Oct 27, 2021
00d6498
Update admin.de.yml
fashxp Oct 27, 2021
310ca0b
Update admin.en.yml
fashxp Oct 27, 2021
c488d72
updated checkbox handling
fashxp Oct 27, 2021
965bd3d
updated checkbox handling
fashxp Oct 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Controller/ConfigDataObjectController.php
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,15 @@ public function loadDataObjectAttributesAction(Request $request, TransformationD
if (empty($classId)) {
return new JsonResponse([]);
}
$loadAdvancedRelations = boolval($request->get('load_advanced_relations', false));

$includeSystemRead = boolval($request->get('system_read', false));
$includeSystemWrite = boolval($request->get('system_write', false));

$transformationTargetType = $request->get('transformation_result_type', [TransformationDataTypeService::DEFAULT_TYPE, TransformationDataTypeService::NUMERIC]);

return new JsonResponse([
'attributes' => $transformationDataTypeService->getPimcoreDataTypes($classId, $transformationTargetType, $includeSystemRead, $includeSystemWrite)
'attributes' => $transformationDataTypeService->getPimcoreDataTypes($classId, $transformationTargetType, $includeSystemRead, $includeSystemWrite, $loadAdvancedRelations)
]);
}

Expand Down
254 changes: 254 additions & 0 deletions src/Mapping/DataTarget/ManyToManyRelation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
<?php

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\DataImporterBundle\Mapping\DataTarget;

use Pimcore\Bundle\DataImporterBundle\Exception\InvalidConfigurationException;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\Data\ElementMetadata;
use Pimcore\Model\DataObject\Data\ObjectMetadata;
use Pimcore\Model\Element\ElementInterface;
use Pimcore\Model\Element\Service;

class ManyToManyRelation implements DataTargetInterface
{
const OVERWRITE_MODE_MERGE = 'merge';
const OVERWRITE_MODE_REPLACE = 'replace';
/**
* @var string
*/
protected $fieldName;

/**
* @var string
*/
protected $language;

/**
* @var bool
*/
protected $writeIfSourceIsEmpty;

/**
* @var bool
*/
protected $writeIfTargetIsNotEmpty;

/**
* @var bool
*/
protected $overwriteMode;

/**
* @param array $settings
*
* @throws InvalidConfigurationException
*/
public function setSettings(array $settings): void
{
if (empty($settings['fieldName'])) {
throw new InvalidConfigurationException('Empty field name.');
}

$this->fieldName = $settings['fieldName'];
$this->language = $settings['language'] ?? null;

//note - cannot be replaced with ?? as $settings['writeIfSourceIsEmpty'] can be false on purpose
$this->writeIfSourceIsEmpty = isset($settings['writeIfSourceIsEmpty']) ? $settings['writeIfSourceIsEmpty'] : true;
$this->writeIfTargetIsNotEmpty = isset($settings['writeIfTargetIsNotEmpty']) ? $settings['writeIfTargetIsNotEmpty'] : true;

$this->overwriteMode = $settings['overwriteMode'] ?? self::OVERWRITE_MODE_REPLACE;
}

/**
* @param ElementInterface $element
* @param mixed $data
*
* @return void
*
* @throws InvalidConfigurationException
*/
public function assignData(ElementInterface $element, $data): void
{
$setterParts = explode('.', $this->fieldName);
$hideUnpublished = DataObject::getHideUnpublished();

if (count($setterParts) === 1) {
//direct class attribute
$setter = 'set' . ucfirst($this->fieldName);
$getter = 'get' . ucfirst($this->fieldName);
DataObject::setHideUnpublished(false);
$currentData = $element->$getter($this->language);
DataObject::setHideUnpublished($hideUnpublished);
if (!$this->checkAssignData($data, $currentData)) {
return;
}
$element->$setter($this->getPreprocessData($element, $element->getClass(), $this->fieldName, $data), $this->language);
} elseif (count($setterParts) === 3) {
//brick attribute

$brickContainerGetter = 'get' . ucfirst($setterParts[0]);
$brickContainer = $element->$brickContainerGetter();

$brickGetter = 'get' . ucfirst($setterParts[1]);
$brick = $brickContainer->$brickGetter();

if (empty($brick)) {
$brickClassName = '\\Pimcore\\Model\\DataObject\\Objectbrick\\Data\\' . ucfirst($setterParts[1]);
$brick = new $brickClassName($element);
$brickSetter = 'set' . ucfirst($setterParts[1]);
$brickContainer->$brickSetter($brick);
}

$setter = 'set' . ucfirst($setterParts[2]);
$getter = 'get' . ucfirst($setterParts[2]);
DataObject::setHideUnpublished(false);
$currentData = $brick->$getter($this->language);
DataObject::setHideUnpublished($hideUnpublished);
if (!$this->checkAssignData($data, $currentData)) {
return;
}
$brick->$setter($this->getPreprocessData($brick, $brick->getDefinition(), $setterParts[2], $data), $this->language);
} else {
throw new InvalidConfigurationException('Invalid number of setter parts for ' . $this->fieldName);
}
}

/**
* @param $object
* @param $definition
* @param string $attributeName
* @param $data
*
* @return array
*/
protected function getPreprocessData($object, $definition, string $attributeName, $data)
{
$fieldDef = $definition->getFieldDefinition($attributeName);

switch ($fieldDef->getFieldtype()) {
case 'manyToManyRelation':
case 'manyToManyObjectRelation':
case 'advancedManyToManyRelation':
case 'advancedManyToManyObjectRelation':
$getter = 'get' . ucfirst($attributeName);
$existingData = $object->$getter();

return $this->getMergedDataArray($existingData ?? [], $data, $fieldDef->getFieldtype());

default:
throw new InvalidConfigurationException('Only supports addvanced relation types');
}
}

/**
* @param array $existingData
* @param array $data
* @param string $fieldType
*
* @return array
*
* @throws \Exception
*/
protected function getMergedDataArray(array $existingData, array $data, string $fieldType): array
{
$newData = [];
switch ($fieldType) {
case 'manyToManyObjectRelation':
if ($this->overwriteMode == self::OVERWRITE_MODE_MERGE) {
foreach ($existingData as $dataObject) {
$newData[$dataObject->getId()] = $dataObject;
}

foreach ($data as $dataObject) {
if (!isset($newData[$dataObject->getId()])) {
$newData[$dataObject->getId()] = $dataObject;
}
}
} else {
return $data;
}
break;

case 'advancedManyToManyObjectRelation':
if ($this->overwriteMode == self::OVERWRITE_MODE_MERGE) {
foreach ($existingData as $metaDataObject) {
$newData[$metaDataObject->getObject()->getId()] = $metaDataObject;
}
}
foreach ($data as $dataObject) {
if ($this->overwriteMode == self::OVERWRITE_MODE_REPLACE || !isset($newData[$dataObject->getId()])) {
$metaDataObject = new ObjectMetadata($this->fieldName, [], $dataObject);
$newData[$metaDataObject->getObject()->getId()] = $metaDataObject;
}
}

break;

case 'manyToManyRelation':
if ($this->overwriteMode == self::OVERWRITE_MODE_MERGE) {
foreach ($existingData as $element) {
$newData[Service::getElementType($element) . '_' . $element->getId()] = $element;
}
foreach ($data as $element) {
if (!isset($newData[Service::getElementType($element) . '_' . $element->getId()])) {
$newData[Service::getElementType($element) . '_' . $element->getId()] = $element;
}
}
} else {
return $data;
}

break;

case 'advancedManyToManyRelation':
if ($this->overwriteMode == self::OVERWRITE_MODE_MERGE) {
foreach ($existingData as $metaDataElement) {
$newData[Service::getElementType($metaDataElement->getElement()) . '_' .
$metaDataElement->getElement()->getId()] = $metaDataElement;
}
}
foreach ($data as $element) {
if ($this->overwriteMode == self::OVERWRITE_MODE_REPLACE ||
!isset($newData[Service::getElementType($element) . '_' . $element->getId()])) {
$metaDataElement = new ElementMetadata($this->fieldName, [], $element);
$newData[Service::getElementType($metaDataElement->getElement()) . '_' . $element->getId()] =
$metaDataElement;
}
}
break;

}

return array_values($newData);
}

/**
* @param mixed $value Value from element attribute
*
* @return bool
*/
protected function checkAssignData($valueData, $valueAttribute)
{
if (!empty($valueAttribute) && $this->writeIfTargetIsNotEmpty === false) {
return false;
}
if (empty($valueData) && $this->writeIfSourceIsEmpty === false) {
return false;
}

return true;
}
}
31 changes: 29 additions & 2 deletions src/Mapping/Type/TransformationDataTypeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class TransformationDataTypeService
const IMAGE_ADVANCED = 'imageAdvanced';
const DATA_OBJECT = 'dataObject';
const DATA_OBJECT_ARRAY = 'dataObjectArray';
const ADVANCED_DATA_OBJECT_ARRAY = 'advancedDataObjectArray';
const ADVANCED_ASSET_ARRAY = 'advancedAssetArray';

protected $transformationDataTypesMapping = [
self::DEFAULT_TYPE => [
Expand Down Expand Up @@ -84,6 +86,10 @@ class TransformationDataTypeService
self::ASSET_ARRAY => [
'manyToManyRelation'
],
self::ADVANCED_ASSET_ARRAY => [
'manyToManyRelation',
'advancedManyToManyRelation'
],
self::GALLERY => [
'imageGallery'
],
Expand All @@ -96,6 +102,12 @@ class TransformationDataTypeService
self::DATA_OBJECT_ARRAY => [
'manyToManyRelation',
'manyToManyObjectRelation'
],
self::ADVANCED_DATA_OBJECT_ARRAY => [
'manyToManyRelation',
'advancedManyToManyRelation',
'manyToManyObjectRelation',
'advancedManyToManyObjectRelation'
]
];

Expand Down Expand Up @@ -142,15 +154,16 @@ protected function addTypesToAttributesArray(ClassDefinition\Data $fieldDefiniti

/**
* @param string $classId
* @param string|array $transformationTargetType
* @param $transformationTargetType
* @param bool $includeSystemRead
* @param bool $includeSystemWrite
* @param bool $includeAdvancedRelations
*
* @return array
*
* @throws \Exception
*/
public function getPimcoreDataTypes(string $classId, $transformationTargetType, bool $includeSystemRead, bool $includeSystemWrite): array
public function getPimcoreDataTypes(string $classId, $transformationTargetType, bool $includeSystemRead, bool $includeSystemWrite, bool $includeAdvancedRelations): array
{
$class = ClassDefinition::getById($classId);

Expand All @@ -160,6 +173,20 @@ public function getPimcoreDataTypes(string $classId, $transformationTargetType,
$transformationTargetType = [$transformationTargetType];
}

//replace for advanced relations
if ($includeAdvancedRelations) {
$transformationTargetType = array_map(function ($item) {
switch ($item) {
case self::ASSET_ARRAY:
return self::ADVANCED_ASSET_ARRAY;
case self::DATA_OBJECT_ARRAY:
return self::ADVANCED_DATA_OBJECT_ARRAY;
default:
return $item;
}
}, $transformationTargetType);
}

foreach ($transformationTargetType as $targetType) {
foreach ($class->getFieldDefinitions() as $definition) {
$this->addTypesToAttributesArray($definition, $targetType, $attributes);
Expand Down
1 change: 1 addition & 0 deletions src/PimcoreDataImporterBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public function getJsPaths()
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/mappingConfigurationItem.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/transformationResultHandler.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/datatarget/direct.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/datatarget/manyToManyRelation.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/datatarget/classificationstore.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/datatarget/classificationstoreBatch.js',
'/bundles/pimcoredataimporter/js/pimcore/configuration/components/mapping/tools/classificationStoreKeySearchWindow.js',
Expand Down
4 changes: 4 additions & 0 deletions src/Resources/config/services/mapping.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ services:
tags:
- { name: "pimcore.datahub.data_importer.data_target", type: "direct" }

Pimcore\Bundle\DataImporterBundle\Mapping\DataTarget\ManyToManyRelation:
tags:
- { name: "pimcore.datahub.data_importer.data_target", type: "manyToManyRelation" }

Pimcore\Bundle\DataImporterBundle\Mapping\DataTarget\Classificationstore:
tags:
- { name: "pimcore.datahub.data_importer.data_target", type: "classificationstore" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ pimcore.plugin.pimcoreDataImporterBundle.configuration.components.mapping.datata
},

initAttributeStore: function (attributeStore) {

const classId = this.dataObjectClassId;
const transformationResultType = this.transformationResultType;

Expand Down Expand Up @@ -189,4 +188,4 @@ pimcore.plugin.pimcoreDataImporterBundle.configuration.components.mapping.datata
}
}

});
});
Loading