| Current Path : /home/rtorresani/www/app/code/Amasty/ExportCore/Export/SubEntity/Collector/ |
| Current File : //home/rtorresani/www/app/code/Amasty/ExportCore/Export/SubEntity/Collector/ManyToMany.php |
<?php
declare(strict_types=1);
/**
* @author Amasty Team
* @copyright Copyright (c) Amasty (https://www.amasty.com)
* @package Export Core for Magento 2 (System)
*/
namespace Amasty\ExportCore\Export\SubEntity\Collector;
use Amasty\ExportCore\Api\Config\Entity\SubEntityCollectorInterface;
use Amasty\ExportCore\Api\Config\Profile\FieldsConfigInterface;
use Amasty\ExportCore\Api\Config\Relation\RelationInterface;
use Amasty\ExportCore\Export\Action\Preparation\Collection\Factory as CollectionFactory;
use Amasty\ExportCore\Export\Action\Preparation\Collection\PrepareCollection;
use Amasty\ExportCore\Export\Config\EntityConfigProvider;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Data\Collection;
use Magento\Framework\EntityManager\MetadataPool;
class ManyToMany implements SubEntityCollectorInterface
{
public const CONNECT_TABLE_NAME = 'connect_table_name';
public const PARENT_FIELD_NAME = 'parent_field_name';
public const CONNECT_PARENT_FIELD_NAME = 'connect_parent_field_name';
public const CHILD_FIELD_NAME = 'child_field_name';
public const CONNECT_CHILD_FIELD_NAME = 'connect_child_field_name';
public const PARENT_ENTITY_NAME = 'parent_entity_name';
public const CHILD_ENTITY_NAME = 'child_entity_name';
/** @var string */
protected $connectTableName;
/** @var string */
protected $parentFieldName;
/** @var string */
protected $childFieldName;
/** @var string */
protected $connectParentFieldName;
/** @var string */
protected $connectChildFieldName;
/**
* @var CollectionFactory
*/
private $collectionFactory;
/**
* @var RelationInterface
*/
private $config;
/**
* @var PrepareCollection
*/
private $prepareCollection;
/**
* @var EntityConfigProvider
*/
private $entityConfigProvider;
/**
* @var ResourceConnection
*/
private $resourceConnection;
/**
* @var MetadataPool
*/
private $metadataPool;
public function __construct(
EntityConfigProvider $entityConfigProvider,
CollectionFactory $collectionFactory,
PrepareCollection $prepareCollection,
ResourceConnection $resourceConnection,
RelationInterface $config,
MetadataPool $metadataPool
) {
$arguments = $config->getArguments();
if (!isset($arguments[self::CONNECT_PARENT_FIELD_NAME])) {
throw new \LogicException(
'Connect parent field name is not specified in relation ' . $config->getSubEntityFieldName()
);
}
if (!isset($arguments[self::CONNECT_CHILD_FIELD_NAME])) {
throw new \LogicException(
'Connect child field name is not specified in relation ' . $config->getSubEntityFieldName()
);
}
if (!isset($arguments[self::PARENT_FIELD_NAME]) && !isset($arguments[self::PARENT_ENTITY_NAME])) {
throw new \LogicException(
'Parent field or entity is not specified in relation ' . $config->getSubEntityFieldName()
);
}
if (!isset($arguments[self::CHILD_FIELD_NAME]) && !isset($arguments[self::CHILD_ENTITY_NAME])) {
throw new \LogicException(
'Child field or entity is not specified in relation ' . $config->getSubEntityFieldName()
);
}
$this->metadataPool = $metadataPool;
$this->parentFieldName = isset($arguments[self::PARENT_ENTITY_NAME])
? $this->getLinkField($arguments[self::PARENT_ENTITY_NAME])
: $arguments[self::PARENT_FIELD_NAME];
$this->childFieldName = isset($arguments[self::CHILD_ENTITY_NAME])
? $this->getLinkField($arguments[self::CHILD_ENTITY_NAME])
: $arguments[self::CHILD_FIELD_NAME];
$this->connectParentFieldName = $this->getLinkField($arguments[self::CONNECT_PARENT_FIELD_NAME])
?: $arguments[self::CONNECT_PARENT_FIELD_NAME];
$this->connectChildFieldName = $this->getLinkField($arguments[self::CONNECT_CHILD_FIELD_NAME])
?: $arguments[self::CONNECT_CHILD_FIELD_NAME];
$this->connectTableName = $arguments[self::CONNECT_TABLE_NAME];
$this->collectionFactory = $collectionFactory;
$this->config = $config;
$this->prepareCollection = $prepareCollection;
$this->entityConfigProvider = $entityConfigProvider;
$this->resourceConnection = $resourceConnection;
}
public function collect(array &$parentData, FieldsConfigInterface $fieldsConfig): SubEntityCollectorInterface
{
$collection = $this->collectionFactory->create(
$this->entityConfigProvider->get($this->config->getChildEntityCode())
);
$this->prepareCollection->execute($collection, $this->config->getChildEntityCode(), $fieldsConfig);
$ids = $this->getChildIds(array_unique(array_column($parentData, $this->parentFieldName)));
$collection->addFieldToFilter(
$this->childFieldName,
['in' => $ids]
);
$collection->addFieldToSelect($this->childFieldName);
$subEntities = [];
foreach ($this->fetchData($collection) as $row) {
$id = $row[$this->childFieldName];
foreach ($ids as $parentId => $childIds) {
if (in_array($id, $childIds)) {
if (!isset($subEntities[$parentId])) {
$subEntities[$parentId] = [];
}
$subEntities[$parentId][] = $row;
}
}
}
foreach ($parentData as $key => &$parentRow) {
$id = $parentRow[$this->parentFieldName] ?? null;
if (isset($subEntities[$id])) {
$parentRow[$this->config->getSubEntityFieldName()] = $subEntities[$id];
} elseif ($fieldsConfig->isExcludeRowIfNoResultsFound()) {
unset($parentData[$key]);
} else {
$parentRow[$this->config->getSubEntityFieldName()] = [];
}
}
return $this;
}
protected function fetchData(Collection $collection)
{
return $collection->getData();
}
protected function getChildIds(array $ids): array
{
$connection = $this->resourceConnection->getConnection();
$select = $connection->select();
$select->from($this->resourceConnection->getTableName($this->connectTableName))
->columns([$this->connectParentFieldName, $this->connectChildFieldName])
->where($connection->quoteIdentifier($this->connectParentFieldName) . ' in (?)', $ids);
$result = [];
foreach ($connection->fetchAll($select) as $row) {
if (!isset($result[$row[$this->connectParentFieldName]])) {
$result[$row[$this->connectParentFieldName]] = [];
}
$result[$row[$this->connectParentFieldName]][] = $row[$this->connectChildFieldName];
}
return $result;
}
public function getParentRequiredFields(): array
{
return [$this->parentFieldName];
}
public function getLinkField($entityType): string
{
try {
$entityMetadata = $this->metadataPool->getMetadata($entityType);
} catch (\Exception $e) {
return '';
}
return $entityMetadata->getLinkField();
}
}