123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Api\ExtensionAttribute;
- use Magento\Framework\Api\ExtensionAttribute\Config;
- use Magento\Framework\Api\ExtensionAttribute\Config\Converter as Converter;
- use Magento\Framework\Data\Collection\AbstractDb as DbCollection;
- use Magento\Framework\Reflection\TypeProcessor;
- use Magento\Framework\Api\ExtensibleDataInterface;
- use Magento\Framework\Api\ExtensionAttributesFactory;
- /**
- * Join processor allows to join extension attributes during collections loading.
- */
- class JoinProcessor implements \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface
- {
- /**
- * Object Manager instance
- *
- * @var \Magento\Framework\ObjectManagerInterface
- */
- protected $objectManager;
- /**
- * @var \Magento\Framework\Reflection\TypeProcessor
- */
- private $typeProcessor;
- /**
- * @var \Magento\Framework\Api\ExtensionAttributesFactory
- */
- private $extensionAttributesFactory;
- /**
- * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorHelper
- */
- private $joinProcessorHelper;
- /**
- * Initialize dependencies.
- *
- * @param \Magento\Framework\ObjectManagerInterface $objectManager
- * @param TypeProcessor $typeProcessor
- * @param ExtensionAttributesFactory $extensionAttributesFactory
- * @param JoinProcessorHelper $joinProcessorHelper
- */
- public function __construct(
- \Magento\Framework\ObjectManagerInterface $objectManager,
- TypeProcessor $typeProcessor,
- ExtensionAttributesFactory $extensionAttributesFactory,
- JoinProcessorHelper $joinProcessorHelper
- ) {
- $this->objectManager = $objectManager;
- $this->typeProcessor = $typeProcessor;
- $this->extensionAttributesFactory = $extensionAttributesFactory;
- $this->joinProcessorHelper = $joinProcessorHelper;
- }
- /**
- * {@inheritdoc}
- */
- public function process(DbCollection $collection, $extensibleEntityClass = null)
- {
- $extensibleEntityClass = $extensibleEntityClass ?: $collection->getItemObjectClass();
- $joinDirectives = $this->getJoinDirectivesForType($extensibleEntityClass);
- foreach ($joinDirectives as $attributeCode => $directive) {
- /** @var JoinDataInterface $joinData */
- $joinData = $this->joinProcessorHelper->getJoinDataInterface();
- $joinData->setAttributeCode($attributeCode)
- ->setReferenceTable($directive[Converter::JOIN_REFERENCE_TABLE])
- ->setReferenceTableAlias($this->getReferenceTableAlias($attributeCode))
- ->setReferenceField($directive[Converter::JOIN_REFERENCE_FIELD])
- ->setJoinField($directive[Converter::JOIN_ON_FIELD]);
- $joinData->setSelectFields(
- $this->joinProcessorHelper->getSelectFieldsMap($attributeCode, $directive[Converter::JOIN_FIELDS])
- );
- $collection->joinExtensionAttribute($joinData, $this);
- }
- }
- /**
- * Generate reference table alias.
- *
- * @param string $attributeCode
- * @return string
- */
- private function getReferenceTableAlias($attributeCode)
- {
- return 'extension_attribute_' . $attributeCode;
- }
- /**
- * {@inheritdoc}
- */
- public function extractExtensionAttributes($extensibleEntityClass, array $data)
- {
- if (!$this->isExtensibleAttributesImplemented($extensibleEntityClass)) {
- /* do nothing as there are no extension attributes */
- return $data;
- }
- $joinDirectives = $this->getJoinDirectivesForType($extensibleEntityClass);
- $extensionData = [];
- foreach ($joinDirectives as $attributeCode => $directive) {
- $this->populateAttributeCodeWithDirective(
- $attributeCode,
- $directive,
- $data,
- $extensionData,
- $extensibleEntityClass
- );
- }
- if (!empty($extensionData)) {
- $extensionAttributes = $this->extensionAttributesFactory->create($extensibleEntityClass, $extensionData);
- $data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY] = $extensionAttributes;
- }
- return $data;
- }
- /**
- * Populate a specific attribute code with join directive instructions.
- *
- * @param string $attributeCode
- * @param array $directive
- * @param array &$data
- * @param array &$extensionData
- * @param string $extensibleEntityClass
- * @return void
- */
- private function populateAttributeCodeWithDirective(
- $attributeCode,
- $directive,
- &$data,
- &$extensionData,
- $extensibleEntityClass
- ) {
- $attributeType = $directive[Converter::DATA_TYPE];
- $selectFields = $this->joinProcessorHelper
- ->getSelectFieldsMap($attributeCode, $directive[Converter::JOIN_FIELDS]);
- foreach ($selectFields as $selectField) {
- $internalAlias = $selectField[JoinDataInterface::SELECT_FIELD_INTERNAL_ALIAS];
- if (isset($data[$internalAlias])) {
- if ($this->typeProcessor->isArrayType($attributeType)) {
- throw new \LogicException(
- sprintf(
- 'Join directives cannot be processed for attribute (%s) of extensible entity (%s),'
- . ' which has an Array type (%s).',
- $attributeCode,
- $this->extensionAttributesFactory->getExtensibleInterfaceName($extensibleEntityClass),
- $attributeType
- )
- );
- } elseif ($this->typeProcessor->isTypeSimple($attributeType)) {
- $extensionData['data'][$attributeCode] = $data[$internalAlias];
- unset($data[$internalAlias]);
- break;
- } else {
- if (!isset($extensionData['data'][$attributeCode])) {
- $extensionData['data'][$attributeCode] = $this->objectManager->create($attributeType);
- }
- $setterName = $selectField[JoinDataInterface::SELECT_FIELD_SETTER];
- $extensionData['data'][$attributeCode]->$setterName($data[$internalAlias]);
- unset($data[$internalAlias]);
- }
- }
- }
- }
- /**
- * Returns the internal join directive config for a given type.
- *
- * Array returned has all of the \Magento\Framework\Api\ExtensionAttribute\Config\Converter JOIN* fields set.
- *
- * @param string $extensibleEntityClass
- * @return array
- */
- private function getJoinDirectivesForType($extensibleEntityClass)
- {
- $extensibleInterfaceName = $this->extensionAttributesFactory
- ->getExtensibleInterfaceName($extensibleEntityClass);
- $extensibleInterfaceName = ltrim($extensibleInterfaceName, '\\');
- $config = $this->joinProcessorHelper->getConfigData();
- if (!isset($config[$extensibleInterfaceName])) {
- return [];
- }
- $typeAttributesConfig = $config[$extensibleInterfaceName];
- $joinDirectives = [];
- foreach ($typeAttributesConfig as $attributeCode => $attributeConfig) {
- if (isset($attributeConfig[Converter::JOIN_DIRECTIVE])) {
- $joinDirectives[$attributeCode] = $attributeConfig[Converter::JOIN_DIRECTIVE];
- $joinDirectives[$attributeCode][Converter::DATA_TYPE] = $attributeConfig[Converter::DATA_TYPE];
- }
- }
- return $joinDirectives;
- }
- /**
- * Determine if the type is an actual extensible data interface.
- *
- * @param string $typeName
- * @return bool
- */
- private function isExtensibleAttributesImplemented($typeName)
- {
- try {
- $this->extensionAttributesFactory->getExtensibleInterfaceName($typeName);
- return true;
- } catch (\LogicException $e) {
- return false;
- }
- }
- }
|