BlackbitDigitalCommerce / pimcore-data-director

Import Bundle for Pimcore
16 stars 3 forks source link

Creating a tree structure creates a folder instead of an object #147

Open betterapp opened 6 months ago

betterapp commented 6 months ago

I have a few dataport which create tree structure.

I do not know why sometimes for random values DD create folders not objects.

For example.

image

When I remove those folders and run the DataPorts once again everything is ok.

I tried with enabled and disabled Compatibilty Mode

why does this happen?

betterapp commented 6 months ago

@BlackbitDevs

we use DD: 3.5.43 with Pimcore: 11.1.5

BlackbitDevs commented 6 months ago

Can you please send your callback function for field Path? If you return a data query selector there, an object should get created but if you return a string, a folder will get created.

Example: return 'Product:key:ALOE VERA'; will create an object with key "ALOE VERA" if none exists

return 'ALOE VERA'; will create a folder named "ALOE VERA"

betterapp commented 6 months ago

I am returning the string but why it does not always create folders. I am returning string and it once create object and other time - folder.

betterapp commented 6 months ago

When I use data query selector it is much better :) but this "if you return a string, a folder will get created" is not true at least not always

BlackbitDevs commented 6 months ago

but this "if you return a string, a folder will get created" is not true at least not always

Hmm, this is the responsible code:

if (is_string($value)) {
    if(\preg_match('/^[A-Za-z0-9\\\.]+:[^:]+(::?[^:]+)*$/', $value)) {
        $itemMold = $this->itemMoldBuilder->getItemMold($this->importer->getDataport()['id']);
        $parentObject = $this->importer->getOneObjectByIdentifier($value, $itemMold);

        if (!$parentObject instanceof ElementInterface) {
            try {
                $objectIdentifierParts = $this->importer->getObjectIdentifierParts($value);
            } catch (Exception $e) {
                $this->importer->getLogger()->warning('Could not parse data query selector "'.$value.'"');
                return null;
            }

            $parentObject = $this->importer->createObject($this->itemMoldBuilder->getItemMoldByClassname($objectIdentifierParts[0]), $objectIdentifierParts[2]);
            $referencedObjectClassDefinition = ClassDefinition::getById($objectIdentifierParts[0]::classId());
            $parentValue = $this->importer->map(['fieldName' => $objectIdentifierParts[1], 'brickName' => $objectIdentifierParts[0]], $objectIdentifierParts[2], null, Importer::getFieldDefinition($referencedObjectClassDefinition, $objectIdentifierParts[1]), $parentObject);

            $fieldParts = explode('#', $objectIdentifierParts[1]);

            $parentSetter = 'set'.ucfirst($fieldParts[0]);
            $parentObject->$parentSetter($parentValue, $fieldParts[1] ?? null);
            $parentObject->setProperty('auto_generated', 'bool', true);

            $this->importer->saveObject($parentObject, true);

            $this->importer->addToRelationCache($value, ['type' => \Pimcore\Model\Element\Service::getElementType($parentObject), 'id' => $parentObject->getId()]);
        }
    } else {
        if (substr($value, 0, 1) !== '/') {
            // relative path
            $value = rtrim($this->importer->getItemFolder()->getRealFullPath(), '/').'/'.$value;
        }

        $objectPathArray = explode('/', $value);
        $elementType = $this->importer->getItemType();
        $objectPathArray = array_map(static function ($pathPart) use ($elementType) {
            return Service::getValidKey($pathPart, $elementType);
        }, $objectPathArray);
        $value = implode('/', $objectPathArray);

        $itemMold = $this->itemMoldBuilder->getItemMold($this->importer->getDataport()['id']);
        $parentObject = \Pimcore\Model\Element\Service::getElementByPath(\Pimcore\Model\Element\Service::getElementType($itemMold), $value);

        if (!$parentObject instanceof ElementInterface) {
            $itemCacheIterator = new ResettableIterator($this->importer->getCachedItems());
            foreach ($itemCacheIterator as $item) {
                if ($item->getRealFullPath() === rtrim($value, '/')) {
                    $parentObject = $item;
                    $this->importer->saveObject($parentObject, true);

                    break;
                }
            }
            $itemCacheIterator->reset();
        }

        if (!$parentObject instanceof ElementInterface) {
            $folderPath = $value;
            if ($this->importer->getTargetConfig()['optimizeInheritance']) {
                $parentObject = $this->createParentPath($folderPath, $itemMold);
            } elseif ($itemMold instanceof Concrete) {
                $parentObject = Service::createFolderByPath($folderPath);
            } elseif ($itemMold instanceof Asset) {
                $parentObject = Asset\Service::createFolderByPath($folderPath);
            } elseif ($itemMold instanceof PageSnippet) {
                if ($itemMold instanceof \Pimcore\Model\Document\Printpage) {
                    $parentParentObject = \Pimcore\Model\Document\Service::createFolderByPath(dirname($folderPath));
                    $parentObject = $this->importer->createObject(new \Pimcore\Model\Document\Printcontainer(), basename($folderPath));
                    $parentObject->setParent($parentParentObject);
                    $parentObject->setController('App\Controller\Web2printController::containerAction');
                    $parentObject->setProperty('auto_generated', 'bool', true);
                    $parentObject->setPublished(true);
                    $this->importer->saveObject($parentObject, true);
                } else {
                    $parentObject = \Pimcore\Model\Document\Service::createFolderByPath($folderPath);
                }
            }
        }
    }
}

So in short this is:

if (is_string($value)) {
    if($value is data query selector) {
        $parentObject = findObjectByDataQuerySelector();
        if (!$parentObject instanceof ElementInterface) {
            $parentObject = createObject();
        }
    } else {
        $parentObject = Service::createFolderByPath($folderPath);
    }
}

Can you send an example dataport (maybe only with path and key (object name) mapping and an example file so that I can try to reproduce the problem?