diff --git a/app/code/Magento/Backend/Helper/Dashboard/Data.php b/app/code/Magento/Backend/Helper/Dashboard/Data.php index efaf955675d59..a7fbf36c88863 100644 --- a/app/code/Magento/Backend/Helper/Dashboard/Data.php +++ b/app/code/Magento/Backend/Helper/Dashboard/Data.php @@ -14,7 +14,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper { /** - * @var \MagentoFrameworkDataCollectionAbstractDb + * @var \Magento\Framework\Data\Collection\AbstractDb */ protected $_stores; @@ -48,7 +48,7 @@ public function __construct( /** * Retrieve stores configured in system. * - * @return \MagentoFrameworkDataCollectionAbstractDb + * @return \Magento\Framework\Data\Collection\AbstractDb */ public function getStores() { diff --git a/app/code/Magento/Bundle/Model/Product/OptionList.php b/app/code/Magento/Bundle/Model/Product/OptionList.php index c90d6347e6015..7e26305be731b 100644 --- a/app/code/Magento/Bundle/Model/Product/OptionList.php +++ b/app/code/Magento/Bundle/Model/Product/OptionList.php @@ -28,22 +28,30 @@ class OptionList */ protected $dataObjectHelper; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor; + /** * @param Type $type * @param \Magento\Bundle\Api\Data\OptionInterfaceFactory $optionFactory * @param LinksList $linkList * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( \Magento\Bundle\Model\Product\Type $type, \Magento\Bundle\Api\Data\OptionInterfaceFactory $optionFactory, \Magento\Bundle\Model\Product\LinksList $linkList, - \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->type = $type; $this->optionFactory = $optionFactory; $this->linkList = $linkList; $this->dataObjectHelper = $dataObjectHelper; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -53,6 +61,7 @@ public function __construct( public function getItems(\Magento\Catalog\Api\Data\ProductInterface $product) { $optionCollection = $this->type->getOptionsCollection($product); + $this->extensionAttributesJoinProcessor->process($optionCollection); $optionList = []; /** @var \Magento\Bundle\Model\Option $option */ foreach ($optionCollection as $option) { diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/OptionListTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/OptionListTest.php index 4827a7efd2fda..855c15bc06fd0 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/OptionListTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/OptionListTest.php @@ -33,6 +33,16 @@ class OptionListTest extends \PHPUnit_Framework_TestCase */ protected $dataObjectHelperMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionAttributesFactoryMock; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + protected function setUp() { $this->typeMock = $this->getMock('\Magento\Bundle\Model\Product\Type', [], [], '', false); @@ -43,15 +53,26 @@ protected function setUp() '', false ); - $this->dataObjectHelperMock = $this->getMockBuilder('\Magento\Framework\Api\DataObjectHelper') - ->disableOriginalConstructor() - ->getMock(); + $this->dataObjectHelperMock = $this->getMock('\Magento\Framework\Api\DataObjectHelper', [], [], '', false); $this->linkListMock = $this->getMock('\Magento\Bundle\Model\Product\LinksList', [], [], '', false); - $this->model = new \Magento\Bundle\Model\Product\OptionList( - $this->typeMock, - $this->optionFactoryMock, - $this->linkListMock, - $this->dataObjectHelperMock + $this->extensionAttributesFactoryMock = $this->getMock( + '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + [], + [], + '', + false + ); + + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $this->objectManager->getObject( + 'Magento\Bundle\Model\Product\OptionList', + [ + 'type' => $this->typeMock, + 'optionFactory' => $this->optionFactoryMock, + 'linkList' => $this->linkListMock, + 'dataObjectHelper' => $this->dataObjectHelperMock, + 'extensionAttributesJoinProcessor' => $this->extensionAttributesFactoryMock + ] ); } @@ -71,8 +92,7 @@ public function testGetItems() '', false ); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $optionsCollMock = $objectManager->getCollectionMock( + $optionsCollMock = $this->objectManager->getCollectionMock( 'Magento\Bundle\Model\Resource\Option\Collection', [$optionMock] ); diff --git a/app/code/Magento/Catalog/Api/Data/ProductCustomOptionInterface.php b/app/code/Magento/Catalog/Api/Data/ProductCustomOptionInterface.php index ee11f877129b6..f57491b950d33 100644 --- a/app/code/Magento/Catalog/Api/Data/ProductCustomOptionInterface.php +++ b/app/code/Magento/Catalog/Api/Data/ProductCustomOptionInterface.php @@ -9,7 +9,7 @@ /** * @api */ -interface ProductCustomOptionInterface +interface ProductCustomOptionInterface extends \Magento\Framework\Api\ExtensibleDataInterface { /** * Get product SKU @@ -201,4 +201,21 @@ public function getValues(); * @return $this */ public function setValues(array $values = null); + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface $extensionAttributes + ); } diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 32ad8cfb390d3..11ae8402ce6fb 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -317,6 +317,11 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements 'group_price', ]; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -351,6 +356,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements * @param \Magento\Catalog\Api\Data\ProductLinkExtensionFactory $productLinkExtensionFactory * @param \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory $mediaGalleryEntryFactory * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -389,6 +395,7 @@ public function __construct( \Magento\Catalog\Api\Data\ProductLinkExtensionFactory $productLinkExtensionFactory, \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterfaceFactory $mediaGalleryEntryFactory, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor, array $data = [] ) { $this->metadataService = $metadataService; @@ -417,6 +424,7 @@ public function __construct( $this->productLinkExtensionFactory = $productLinkExtensionFactory; $this->mediaGalleryEntryFactory = $mediaGalleryEntryFactory; $this->dataObjectHelper = $dataObjectHelper; + $this->joinProcessor = $joinProcessor; parent::__construct( $context, $registry, @@ -1961,7 +1969,9 @@ public function getOptionById($optionId) public function getOptions() { if (empty($this->_options) && $this->getHasOptions() && !$this->optionsInitialized) { - foreach ($this->getProductOptionsCollection() as $option) { + $collection = $this->getProductOptionsCollection(); + $this->joinProcessor->process($collection); + foreach ($collection as $option) { $option->setProduct($this); $this->addOption($option); } diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php index 8c5d3d25675d9..05ca2bbdf9c98 100644 --- a/app/code/Magento/Catalog/Model/Product/Option.php +++ b/app/code/Magento/Catalog/Model/Product/Option.php @@ -12,7 +12,6 @@ use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Resource\Product\Option\Value\Collection; use Magento\Catalog\Pricing\Price\BasePrice; -use Magento\Framework\Model\AbstractModel; use Magento\Framework\Exception\LocalizedException; /** @@ -26,7 +25,8 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessivePublicCount) */ -class Option extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCustomOptionInterface +class Option extends \Magento\Framework\Model\AbstractExtensibleModel + implements \Magento\Catalog\Api\Data\ProductCustomOptionInterface { const OPTION_GROUP_TEXT = 'text'; @@ -116,6 +116,8 @@ class Option extends AbstractModel implements \Magento\Catalog\Api\Data\ProductC /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry + * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory + * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param Option\Value $productOptionValue * @param Option\Type\Factory $optionFactory * @param \Magento\Framework\Stdlib\String $string @@ -128,6 +130,8 @@ class Option extends AbstractModel implements \Magento\Catalog\Api\Data\ProductC public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, + \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, + \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, Option\Value $productOptionValue, \Magento\Catalog\Model\Product\Option\Type\Factory $optionFactory, \Magento\Framework\Stdlib\String $string, @@ -143,6 +147,8 @@ public function __construct( parent::__construct( $context, $registry, + $extensionFactory, + $customAttributeFactory, $resource, $resourceCollection, $data @@ -406,7 +412,7 @@ public function saveOptions() } /** - * @return AbstractModel + * @return \Magento\Framework\Model\AbstractModel * @throws \Magento\Framework\Exception\LocalizedException */ public function afterSave() @@ -845,5 +851,27 @@ public function setValues(array $values = null) $this->_values = $values; return $this; } + + /** + * {@inheritdoc} + * + * @return \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + * + * @param \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Catalog\Api\Data\ProductCustomOptionExtensionInterface $extensionAttributes + ) { + return $this->_setExtensionAttributes($extensionAttributes); + } //@codeCoverageIgnoreEnd } diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 79f26720fff4d..33ef608575c92 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -11,7 +11,6 @@ use Magento\Catalog\Model\Resource\Product\Collection; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; -use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteriaInterface; @@ -137,9 +136,9 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa protected $imageProcessor; /** - * @var ExtensionAttributesFactory + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface */ - protected $extensionAttributesFactory; + protected $extensionAttributesJoinProcessor; /** * @param ProductFactory $productFactory @@ -149,20 +148,20 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository * @param Resource\Product $resourceModel - * @param \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $linkInitializer - * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider - * @param \Magento\Store\Model\StoreManagerInterface $storeManager , + * @param Product\Initialization\Helper\ProductLinks $linkInitializer + * @param Product\LinkTypeProvider $linkTypeProvider + * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Api\FilterBuilder $filterBuilder * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $metadataServiceInterface * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter - * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Catalog\Model\Product\Option\Converter $optionConverter + * @param Product\Option\Converter $optionConverter * @param \Magento\Framework\Filesystem $fileSystem * @param ImageContentValidatorInterface $contentValidator * @param ImageContentInterfaceFactory $contentFactory * @param MimeTypeExtensionMap $mimeTypeExtensionMap + * @param \Magento\Eav\Model\Config $eavConfig * @param ImageProcessorInterface $imageProcessor - * @param ExtensionAttributesFactory $extensionAttributesFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -186,7 +185,7 @@ public function __construct( MimeTypeExtensionMap $mimeTypeExtensionMap, \Magento\Eav\Model\Config $eavConfig, ImageProcessorInterface $imageProcessor, - ExtensionAttributesFactory $extensionAttributesFactory + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -208,7 +207,7 @@ public function __construct( $this->mimeTypeExtensionMap = $mimeTypeExtensionMap; $this->eavConfig = $eavConfig; $this->imageProcessor = $imageProcessor; - $this->extensionAttributesFactory = $extensionAttributesFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -649,6 +648,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr { /** @var \Magento\Catalog\Model\Resource\Product\Collection $collection */ $collection = $this->collectionFactory->create(); + $this->extensionAttributesJoinProcessor->process($collection); $defaultAttributeSetId = $this->eavConfig ->getEntityType(\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE) ->getDefaultAttributeSetId(); @@ -681,8 +681,6 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr } $collection->setCurPage($searchCriteria->getCurrentPage()); $collection->setPageSize($searchCriteria->getPageSize()); - $productDataClass = 'Magento\Catalog\Model\Product'; - $this->extensionAttributesFactory->process($collection, $productDataClass); $collection->load(); $searchResult = $this->searchResultsFactory->create(); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index 545c8d990ed95..da842214bbd80 100755 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -1277,7 +1277,10 @@ public function priceDataProvider() public function testGetOptions() { - $optionInstanceMock = $this->getMockBuilder('\Magento\Catalog\Model\Product\Option') + $optionInstanceMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Option') + ->disableOriginalConstructor() + ->getMock(); + $joinProcessorMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface') ->disableOriginalConstructor() ->getMock(); @@ -1286,6 +1289,7 @@ public function testGetOptions() 'Magento\Catalog\Model\Product', [ 'catalogProductOption' => $optionInstanceMock, + 'joinProcessor' => $joinProcessorMock ] ); $productModel->setHasOptions(true); @@ -1315,12 +1319,19 @@ public function testGetOptions() ->method('setProduct') ->with($productModel) ->willReturn($option1Id); - $options = [$optionMock1, $optionMock2]; + $optionColl = $this->objectManagerHelper->getCollectionMock( + 'Magento\Catalog\Model\Resource\Product\Option\Collection', + [$optionMock1, $optionMock2] + ); $optionInstanceMock->expects($this->once()) ->method('getProductOptionCollection') ->with($productModel) - ->willReturn($options); + ->willReturn($optionColl); + + $joinProcessorMock->expects($this->once()) + ->method('process') + ->with($this->isInstanceOf('Magento\Catalog\Model\Resource\Product\Option\Collection')); $expectedOptions = [ $option1Id => $optionMock1, diff --git a/app/code/Magento/CheckoutAgreements/Api/Data/AgreementInterface.php b/app/code/Magento/CheckoutAgreements/Api/Data/AgreementInterface.php index 90a67c71146c5..299e027ac248a 100644 --- a/app/code/Magento/CheckoutAgreements/Api/Data/AgreementInterface.php +++ b/app/code/Magento/CheckoutAgreements/Api/Data/AgreementInterface.php @@ -5,7 +5,7 @@ */ namespace Magento\CheckoutAgreements\Api\Data; -interface AgreementInterface +interface AgreementInterface extends \Magento\Framework\Api\ExtensibleDataInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case @@ -128,4 +128,21 @@ public function getIsHtml(); * @return $this */ public function setIsHtml($isHtml); + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface $extensionAttributes + ); } diff --git a/app/code/Magento/CheckoutAgreements/Model/Agreement.php b/app/code/Magento/CheckoutAgreements/Model/Agreement.php index 6f951c12d5b62..98b1b36b153c1 100644 --- a/app/code/Magento/CheckoutAgreements/Model/Agreement.php +++ b/app/code/Magento/CheckoutAgreements/Model/Agreement.php @@ -8,7 +8,7 @@ use Magento\CheckoutAgreements\Api\Data\AgreementInterface; use Magento\Framework\Model\AbstractModel; -class Agreement extends AbstractModel implements AgreementInterface +class Agreement extends \Magento\Framework\Model\AbstractExtensibleModel implements AgreementInterface { /** * Allowed CSS units for height field @@ -176,5 +176,27 @@ public function setIsHtml($isHtml) { return $this->setData(self::IS_HTML, $isHtml); } + + /** + * {@inheritdoc} + * + * @return \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + * + * @param \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\CheckoutAgreements\Api\Data\AgreementExtensionInterface $extensionAttributes + ) { + return $this->_setExtensionAttributes($extensionAttributes); + } //@codeCoverageIgnoreEnd } diff --git a/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php b/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php index eae3f09c667a9..845bb2a9d2c74 100644 --- a/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php +++ b/app/code/Magento/CheckoutAgreements/Model/CheckoutAgreementsRepository.php @@ -10,6 +10,7 @@ use Magento\CheckoutAgreements\Model\Resource\Agreement\CollectionFactory as AgreementCollectionFactory; use Magento\CheckoutAgreements\Model\Resource\Agreement\Collection as AgreementCollection; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Model\ScopeInterface; @@ -56,6 +57,11 @@ class CheckoutAgreementsRepository implements CheckoutAgreementsRepositoryInterf */ private $agreementFactory; + /** + * @var JoinProcessorInterface + */ + private $extensionAttributesJoinProcessor; + /** * Constructs a checkout agreement data object. * @@ -64,19 +70,22 @@ class CheckoutAgreementsRepository implements CheckoutAgreementsRepositoryInterf * @param ScopeConfigInterface $scopeConfig Scope config. * @param AgreementResource $agreementResource * @param AgreementFactory $agreementFactory + * @param JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( AgreementCollectionFactory $collectionFactory, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, AgreementResource $agreementResource, - AgreementFactory $agreementFactory + AgreementFactory $agreementFactory, + JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->collectionFactory = $collectionFactory; $this->storeManager = $storeManager; $this->scopeConfig = $scopeConfig; $this->resourceModel = $agreementResource; $this->agreementFactory = $agreementFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -92,9 +101,9 @@ public function getList() $storeId = $this->storeManager->getStore()->getId(); /** @var $agreementCollection AgreementCollection */ $agreementCollection = $this->collectionFactory->create(); + $this->extensionAttributesJoinProcessor->process($agreementCollection); $agreementCollection->addStoreFilter($storeId); $agreementCollection->addFieldToFilter('is_active', 1); - $agreementDataObjects = []; foreach ($agreementCollection as $agreement) { $agreementDataObjects[] = $agreement; diff --git a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/CheckoutAgreementsRepositoryTest.php b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/CheckoutAgreementsRepositoryTest.php index 9d27e3e471e23..04543777e3470 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Unit/Model/CheckoutAgreementsRepositoryTest.php +++ b/app/code/Magento/CheckoutAgreements/Test/Unit/Model/CheckoutAgreementsRepositoryTest.php @@ -56,6 +56,11 @@ class CheckoutAgreementsRepositoryTest extends \PHPUnit_Framework_TestCase */ private $storeMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionAttributesJoinProcessorMock; + protected function setUp() { $this->objectManager = new ObjectManager($this); @@ -81,17 +86,28 @@ protected function setUp() $this->agreementMock = $this->getMock('\Magento\CheckoutAgreements\Model\Agreement', $methods, [], '', false); $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + '\Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + ['process'], + [], + '', + false + ); + $this->model = new \Magento\CheckoutAgreements\Model\CheckoutAgreementsRepository( $this->factoryMock, $this->storeManagerMock, $this->scopeConfigMock, $this->resourceMock, - $this->agrFactoryMock + $this->agrFactoryMock, + $this->extensionAttributesJoinProcessorMock ); } public function testGetListReturnsEmptyListIfCheckoutAgreementsAreDisabledOnFrontend() { + $this->extensionAttributesJoinProcessorMock->expects($this->never()) + ->method('process'); $this->scopeConfigMock->expects($this->once()) ->method('isSetFlag') ->with('checkout/options/enable_agreements', ScopeInterface::SCOPE_STORE, null) @@ -102,6 +118,10 @@ public function testGetListReturnsEmptyListIfCheckoutAgreementsAreDisabledOnFron public function testGetListReturnsTheListOfActiveCheckoutAgreements() { + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with($this->isInstanceOf('Magento\CheckoutAgreements\Model\Resource\Agreement\Collection')); + $this->scopeConfigMock->expects($this->once()) ->method('isSetFlag') ->with('checkout/options/enable_agreements', ScopeInterface::SCOPE_STORE, null) diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index c1fb0b41ef427..20d861e695135 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -158,6 +158,11 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType */ protected $jsonHelper; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor; + /** * @codingStandardsIgnoreStart/End * @@ -181,6 +186,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType * @param \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable $catalogProductTypeConfigurable * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Catalog\Model\ProductFactory $productFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -205,7 +211,8 @@ public function __construct( \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable $catalogProductTypeConfigurable, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration, - \Magento\Catalog\Model\ProductFactory $productFactory + \Magento\Catalog\Model\ProductFactory $productFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->_typeConfigurableFactory = $typeConfigurableFactory; $this->_entityFactory = $entityFactory; @@ -218,6 +225,7 @@ public function __construct( $this->_scopeConfig = $scopeConfig; $this->stockConfiguration = $stockConfiguration; $this->jsonHelper = $jsonHelper; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; parent::__construct( $catalogProductOption, $eavConfig, @@ -370,7 +378,9 @@ public function getConfigurableAttributes($product) ['group' => 'CONFIGURABLE', 'method' => __METHOD__] ); if (!$product->hasData($this->_configurableAttributes)) { - $configurableAttributes = $this->getConfigurableAttributeCollection($product)->orderByPosition()->load(); + $configurableAttributes = $this->getConfigurableAttributeCollection($product); + $this->extensionAttributesJoinProcessor->process($configurableAttributes); + $configurableAttributes->orderByPosition()->load(); $product->setData($this->_configurableAttributes, $configurableAttributes); } \Magento\Framework\Profiler::stop('CONFIGURABLE:' . __METHOD__); diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php index 4ca090adef44b..a4fcb50da0362 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php @@ -83,6 +83,11 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase */ protected $_objectHelper; + /** + * @var JoinProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionAttributesJoinProcessorMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -169,6 +174,14 @@ protected function setUp() '', false ); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + [], + [], + '', + false + ); + $this->_model = $this->_objectHelper->getObject( 'Magento\ConfigurableProduct\Model\Product\Type\Configurable', [ @@ -186,7 +199,8 @@ protected function setUp() 'filesystem' => $filesystem, 'coreRegistry' => $coreRegistry, 'logger' => $logger, - 'stockConfiguration' => $this->_stockConfiguration + 'stockConfiguration' => $this->_stockConfiguration, + 'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock ] ); } @@ -202,9 +216,20 @@ public function testHasWeightTrue() public function testSave() { $product = $this->getMockBuilder('\Magento\Catalog\Model\Product') - ->setMethods(['getIsDuplicate', 'dataHasChangedFor', 'getConfigurableAttributesData', 'getStoreId', - 'getId', 'getData', 'hasData', 'getAssociatedProductIds', '__wakeup', '__sleep', - ])->disableOriginalConstructor() + ->setMethods( + [ + 'getIsDuplicate', + 'dataHasChangedFor', + 'getConfigurableAttributesData', + 'getStoreId', + 'getId', + 'getData', + 'hasData', + 'getAssociatedProductIds', + '__wakeup', + '__sleep', + ] + )->disableOriginalConstructor() ->getMock(); $product->expects($this->any())->method('dataHasChangedFor')->will($this->returnValue('false')); $product->expects($this->any())->method('getConfigurableAttributesData') @@ -297,9 +322,19 @@ public function testGetUsedProducts() $this->_attributeCollectionFactory->expects($this->any())->method('create') ->will($this->returnValue($attributeCollection)); $product = $this->getMockBuilder('\Magento\Catalog\Model\Product') - ->setMethods(['dataHasChangedFor', 'getConfigurableAttributesData', 'getStoreId', - 'getId', 'getData', 'hasData', 'getAssociatedProductIds', '__wakeup', '__sleep', - ])->disableOriginalConstructor() + ->setMethods( + [ + 'dataHasChangedFor', + 'getConfigurableAttributesData', + 'getStoreId', + 'getId', + 'getData', + 'hasData', + 'getAssociatedProductIds', + '__wakeup', + '__sleep', + ] + )->disableOriginalConstructor() ->getMock(); $product->expects($this->any())->method('getConfigurableAttributesData') ->will($this->returnValue($this->attributeData)); @@ -307,18 +342,28 @@ public function testGetUsedProducts() $product->expects($this->any())->method('getId')->will($this->returnValue(1)); $product->expects($this->any())->method('getAssociatedProductIds')->will($this->returnValue([2])); $product->expects($this->any())->method('hasData') - ->will($this->returnValueMap([ - ['_cache_instance_used_product_attribute_ids', 1], - ['_cache_instance_products', 0], - ['_cache_instance_configurable_attributes', 1], - ])); + ->will( + $this->returnValueMap( + [ + ['_cache_instance_used_product_attribute_ids', 1], + ['_cache_instance_products', 0], + ['_cache_instance_configurable_attributes', 1], + ] + ) + ); $product->expects($this->any())->method('getData') ->will($this->returnValue(1)); $productCollection = $this->getMockBuilder( 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection' )->setMethods( - ['setFlag', 'setProductFilter', 'addStoreFilter', 'addAttributeToSelect', 'addFilterByRequiredOptions', - 'setStoreId', ] + [ + 'setFlag', + 'setProductFilter', + 'addStoreFilter', + 'addAttributeToSelect', + 'addFilterByRequiredOptions', + 'setStoreId', + ] )->disableOriginalConstructor() ->getMock(); $productCollection->expects($this->any())->method('addAttributeToSelect')->will($this->returnSelf()); @@ -385,13 +430,21 @@ public function testGetConfigurableAttributesAsArray($productStore, $attributeSt ->getMock(); $product->expects($this->any())->method('getStoreId')->will($this->returnValue($productStore)); $product->expects($this->any())->method('hasData') - ->will($this->returnValueMap([ - ['_cache_instance_configurable_attributes', 1], - ])); + ->will( + $this->returnValueMap( + [ + ['_cache_instance_configurable_attributes', 1], + ] + ) + ); $product->expects($this->any())->method('getData') - ->will($this->returnValueMap([ - ['_cache_instance_configurable_attributes', null, [$attribute]], - ])); + ->will( + $this->returnValueMap( + [ + ['_cache_instance_configurable_attributes', null, [$attribute]], + ] + ) + ); $result = $this->_model->getConfigurableAttributesAsArray($product); $this->assertCount(1, $result); @@ -408,6 +461,41 @@ public function getConfigurableAttributesAsArrayDataProvider() ]; } + public function testGetConfigurableAttributes() + { + $expectedData = [1]; + $configurableAttributes = '_cache_instance_configurable_attributes'; + + /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $product */ + $product = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->setMethods(['getData', 'hasData', 'setData']) + ->disableOriginalConstructor() + ->getMock(); + $product->expects($this->once())->method('hasData')->with($configurableAttributes)->willReturn(false); + $product->expects($this->once())->method('setData')->willReturnSelf(); + $product->expects($this->once())->method('getData')->with($configurableAttributes)->willReturn($expectedData); + + $attributeCollection = $this->getMockBuilder( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Collection' + ) + ->setMethods(['setProductFilter', 'orderByPosition', 'load']) + ->disableOriginalConstructor() + ->getMock(); + $attributeCollection->expects($this->any())->method('setProductFilter')->will($this->returnSelf()); + $attributeCollection->expects($this->any())->method('orderByPosition')->will($this->returnSelf()); + $this->_attributeCollectionFactory->expects($this->any())->method('create')->willReturn($attributeCollection); + + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with( + $this->isInstanceOf( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute\Collection' + ) + ); + + $this->assertEquals($expectedData, $this->_model->getConfigurableAttributes($product)); + } + public function testResetConfigurableAttributes() { $product = $this->getMockBuilder('\Magento\Catalog\Model\Product') diff --git a/app/code/Magento/Customer/Model/Resource/AddressRepository.php b/app/code/Magento/Customer/Model/Resource/AddressRepository.php index 1a97ba112fbcf..833cf68fd70b8 100644 --- a/app/code/Magento/Customer/Model/Resource/AddressRepository.php +++ b/app/code/Magento/Customer/Model/Resource/AddressRepository.php @@ -56,6 +56,11 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf */ protected $addressCollectionFactory; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor; + /** * @param \Magento\Customer\Model\AddressFactory $addressFactory * @param \Magento\Customer\Model\AddressRegistry $addressRegistry @@ -64,6 +69,7 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf * @param \Magento\Directory\Helper\Data $directoryData * @param \Magento\Customer\Api\Data\AddressSearchResultsInterfaceFactory $addressSearchResultsFactory * @param \Magento\Customer\Model\Resource\Address\CollectionFactory $addressCollectionFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( \Magento\Customer\Model\AddressFactory $addressFactory, @@ -72,7 +78,8 @@ public function __construct( \Magento\Customer\Model\Resource\Address $addressResourceModel, \Magento\Directory\Helper\Data $directoryData, \Magento\Customer\Api\Data\AddressSearchResultsInterfaceFactory $addressSearchResultsFactory, - \Magento\Customer\Model\Resource\Address\CollectionFactory $addressCollectionFactory + \Magento\Customer\Model\Resource\Address\CollectionFactory $addressCollectionFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->addressFactory = $addressFactory; $this->addressRegistry = $addressRegistry; @@ -81,6 +88,7 @@ public function __construct( $this->directoryData = $directoryData; $this->addressSearchResultsFactory = $addressSearchResultsFactory; $this->addressCollectionFactory = $addressCollectionFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -146,6 +154,7 @@ public function getList(SearchCriteriaInterface $searchCriteria) /** @var Collection $collection */ $collection = $this->addressCollectionFactory->create(); + $this->extensionAttributesJoinProcessor->process($collection, 'Magento\Customer\Api\Data\AddressInterface'); // Add filters from root filter group to the collection foreach ($searchCriteria->getFilterGroups() as $group) { $this->addFilterGroupToCollection($group, $collection); diff --git a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php index b20ce2bb0d599..bd3064d2f9317 100644 --- a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php @@ -13,7 +13,6 @@ use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Api\ExtensionAttributesFactory; /** * Customer repository. @@ -82,9 +81,9 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte protected $imageProcessor; /** - * @var ExtensionAttributesFactory + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface */ - protected $extensionAttributesFactory; + protected $extensionAttributesJoinProcessor; /** * @param \Magento\Customer\Model\CustomerFactory $customerFactory @@ -99,7 +98,7 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param DataObjectHelper $dataObjectHelper * @param ImageProcessorInterface $imageProcessor - * @param ExtensionAttributesFactory $extensionAttributesFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -115,7 +114,7 @@ public function __construct( \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, DataObjectHelper $dataObjectHelper, ImageProcessorInterface $imageProcessor, - ExtensionAttributesFactory $extensionAttributesFactory + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->customerFactory = $customerFactory; $this->customerSecureFactory = $customerSecureFactory; @@ -129,7 +128,7 @@ public function __construct( $this->extensibleDataObjectConverter = $extensibleDataObjectConverter; $this->dataObjectHelper = $dataObjectHelper; $this->imageProcessor = $imageProcessor; - $this->extensionAttributesFactory = $extensionAttributesFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -250,6 +249,7 @@ public function getList(SearchCriteriaInterface $searchCriteria) $searchResults->setSearchCriteria($searchCriteria); /** @var \Magento\Customer\Model\Resource\Customer\Collection $collection */ $collection = $this->customerFactory->create()->getCollection(); + $this->extensionAttributesJoinProcessor->process($collection, 'Magento\Customer\Api\Data\CustomerInterface'); // This is needed to make sure all the attributes are properly loaded foreach ($this->customerMetadata->getAllAttributesMetadata() as $metadata) { $collection->addAttributeToSelect($metadata->getAttributeCode()); @@ -279,7 +279,6 @@ public function getList(SearchCriteriaInterface $searchCriteria) } $collection->setCurPage($searchCriteria->getCurrentPage()); $collection->setPageSize($searchCriteria->getPageSize()); - $this->extensionAttributesFactory->process($collection, 'Magento\Customer\Model\Data\Customer'); $customers = []; /** @var \Magento\Customer\Model\Customer $customerModel */ foreach ($collection as $customerModel) { diff --git a/app/code/Magento/Customer/Model/Resource/GroupRepository.php b/app/code/Magento/Customer/Model/Resource/GroupRepository.php index fe0d52ca471ef..2b87df95a55bd 100644 --- a/app/code/Magento/Customer/Model/Resource/GroupRepository.php +++ b/app/code/Magento/Customer/Model/Resource/GroupRepository.php @@ -14,6 +14,8 @@ use Magento\Framework\Exception\State\InvalidTransitionException; use Magento\Tax\Api\Data\TaxClassInterface; use Magento\Tax\Api\TaxClassManagementInterface; +use Magento\Framework\Api\ExtensibleDataInterface; +use Magento\Customer\Api\Data\GroupExtensionInterface; /** * Customer group CRUD class @@ -62,6 +64,11 @@ class GroupRepository implements \Magento\Customer\Api\GroupRepositoryInterface */ private $taxClassRepository; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor; + /** * @param \Magento\Customer\Model\GroupRegistry $groupRegistry * @param \Magento\Customer\Model\GroupFactory $groupFactory @@ -70,6 +77,7 @@ class GroupRepository implements \Magento\Customer\Api\GroupRepositoryInterface * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor * @param \Magento\Customer\Api\Data\GroupSearchResultsInterfaceFactory $searchResultsFactory * @param \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepositoryInterface + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( \Magento\Customer\Model\GroupRegistry $groupRegistry, @@ -78,7 +86,8 @@ public function __construct( \Magento\Customer\Model\Resource\Group $groupResourceModel, \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor, \Magento\Customer\Api\Data\GroupSearchResultsInterfaceFactory $searchResultsFactory, - \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepositoryInterface + \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepositoryInterface, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->groupRegistry = $groupRegistry; $this->groupFactory = $groupFactory; @@ -87,6 +96,7 @@ public function __construct( $this->dataObjectProcessor = $dataObjectProcessor; $this->searchResultsFactory = $searchResultsFactory; $this->taxClassRepository = $taxClassRepositoryInterface; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -164,6 +174,8 @@ public function getList(SearchCriteriaInterface $searchCriteria) /** @var \Magento\Customer\Model\Resource\Group\Collection $collection */ $collection = $this->groupFactory->create()->getCollection(); + $groupInterfaceName = 'Magento\Customer\Api\Data\GroupInterface'; + $this->extensionAttributesJoinProcessor->process($collection, $groupInterfaceName); $collection->addTaxClass(); //Add filters from root filter group to the collection @@ -171,7 +183,6 @@ public function getList(SearchCriteriaInterface $searchCriteria) foreach ($searchCriteria->getFilterGroups() as $group) { $this->addFilterGroupToCollection($group, $collection); } - $searchResults->setTotalCount($collection->getSize()); $sortOrders = $searchCriteria->getSortOrders(); /** @var \Magento\Framework\Api\SortOrder $sortOrder */ if ($sortOrders) { @@ -182,6 +193,11 @@ public function getList(SearchCriteriaInterface $searchCriteria) ($sortOrder->getDirection() == SearchCriteriaInterface::SORT_ASC) ? 'ASC' : 'DESC' ); } + } else { + // set a default sorting order since this method is used constantly in many + // different blocks + $field = $this->translateField('id'); + $collection->addOrder($field, 'ASC'); } $collection->setCurPage($searchCriteria->getCurrentPage()); $collection->setPageSize($searchCriteria->getPageSize()); @@ -190,13 +206,22 @@ public function getList(SearchCriteriaInterface $searchCriteria) $groups = []; /** @var \Magento\Customer\Model\Group $group */ foreach ($collection as $group) { + /** @var \Magento\Customer\Api\Data\GroupInterface $groupDataObject */ $groupDataObject = $this->groupDataFactory->create() ->setId($group->getId()) ->setCode($group->getCode()) ->setTaxClassId($group->getTaxClassId()) ->setTaxClassName($group->getTaxClassName()); + $data = $group->getData(); + $data = $this->extensionAttributesJoinProcessor->extractExtensionAttributes($groupInterfaceName, $data); + if (isset($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]) + && ($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY] instanceof GroupExtensionInterface) + ) { + $groupDataObject->setExtensionAttributes($data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]); + } $groups[] = $groupDataObject; } + $searchResults->setTotalCount($collection->getSize()); return $searchResults->setItems($groups); } diff --git a/app/code/Magento/Downloadable/Model/Product/Type.php b/app/code/Magento/Downloadable/Model/Product/Type.php index c25d6886e20ab..e34c9bdf1b576 100644 --- a/app/code/Magento/Downloadable/Model/Product/Type.php +++ b/app/code/Magento/Downloadable/Model/Product/Type.php @@ -6,6 +6,7 @@ namespace Magento\Downloadable\Model\Product; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; /** * Downloadable product type model @@ -59,6 +60,11 @@ class Type extends \Magento\Catalog\Model\Product\Type\Virtual */ private $typeHandler; + /** + * @var JoinProcessorInterface + */ + private $extensionAttributesJoinProcessor; + /** * Construct * @@ -78,6 +84,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\Virtual * @param \Magento\Downloadable\Model\SampleFactory $sampleFactory * @param \Magento\Downloadable\Model\LinkFactory $linkFactory * @param TypeHandler\TypeHandlerInterface $typeHandler + * @param JoinProcessorInterface $extensionAttributesJoinProcessor * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -96,7 +103,8 @@ public function __construct( \Magento\Downloadable\Model\Resource\Sample\CollectionFactory $samplesFactory, \Magento\Downloadable\Model\SampleFactory $sampleFactory, \Magento\Downloadable\Model\LinkFactory $linkFactory, - \Magento\Downloadable\Model\Product\TypeHandler\TypeHandlerInterface $typeHandler + \Magento\Downloadable\Model\Product\TypeHandler\TypeHandlerInterface $typeHandler, + JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->_sampleResFactory = $sampleResFactory; $this->_linkResource = $linkResource; @@ -105,6 +113,7 @@ public function __construct( $this->_sampleFactory = $sampleFactory; $this->_linkFactory = $linkFactory; $this->typeHandler = $typeHandler; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; parent::__construct( $catalogProductOption, $eavConfig, @@ -127,17 +136,18 @@ public function __construct( public function getLinks($product) { if ($product->getDownloadableLinks() === null) { - $_linkCollection = $this->_linksFactory->create()->addProductToFilter( + /** @var \Magento\Downloadable\Model\Resource\Link\Collection $linkCollection */ + $linkCollection = $this->_linksFactory->create()->addProductToFilter( $product->getId() )->addTitleToResult( $product->getStoreId() )->addPriceToResult( $product->getStore()->getWebsiteId() ); + $this->extensionAttributesJoinProcessor->process($linkCollection); $linksCollectionById = []; - foreach ($_linkCollection as $link) { + foreach ($linkCollection as $link) { /* @var \Magento\Downloadable\Model\Link $link */ - $link->setProduct($product); $linksCollectionById[$link->getId()] = $link; } @@ -203,12 +213,13 @@ public function getLinkSelectionRequired($product) public function getSamples($product) { if ($product->getDownloadableSamples() === null) { - $_sampleCollection = $this->_samplesFactory->create()->addProductToFilter( + $sampleCollection = $this->_samplesFactory->create()->addProductToFilter( $product->getId() )->addTitleToResult( $product->getStoreId() ); - $product->setDownloadableSamples($_sampleCollection); + $this->extensionAttributesJoinProcessor->process($sampleCollection); + $product->setDownloadableSamples($sampleCollection); } return $product->getDownloadableSamples(); diff --git a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php index 5b1b7d539d930..bfa5952bdbfc6 100644 --- a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php +++ b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php @@ -37,25 +37,33 @@ class GroupRepository implements \Magento\Eav\Api\AttributeGroupRepositoryInterf */ protected $searchResultsFactory; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param \Magento\Eav\Model\Resource\Entity\Attribute\Group $groupResource * @param \Magento\Eav\Model\Resource\Entity\Attribute\Group\CollectionFactory $groupListFactory * @param \Magento\Eav\Model\Entity\Attribute\GroupFactory $groupFactory * @param \Magento\Eav\Api\AttributeSetRepositoryInterface $setRepository * @param \Magento\Eav\Api\Data\AttributeGroupSearchResultsInterfaceFactory $searchResultsFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( \Magento\Eav\Model\Resource\Entity\Attribute\Group $groupResource, \Magento\Eav\Model\Resource\Entity\Attribute\Group\CollectionFactory $groupListFactory, \Magento\Eav\Model\Entity\Attribute\GroupFactory $groupFactory, \Magento\Eav\Api\AttributeSetRepositoryInterface $setRepository, - \Magento\Eav\Api\Data\AttributeGroupSearchResultsInterfaceFactory $searchResultsFactory + \Magento\Eav\Api\Data\AttributeGroupSearchResultsInterfaceFactory $searchResultsFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->groupResource = $groupResource; $this->groupListFactory = $groupListFactory; $this->groupFactory = $groupFactory; $this->setRepository = $setRepository; $this->searchResultsFactory = $searchResultsFactory; + $this->joinProcessor = $joinProcessor; } /** @@ -108,6 +116,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr } $collection = $this->groupListFactory->create(); + $this->joinProcessor->process($collection); $collection->setAttributeSetFilter($attributeSetId); $collection->setSortOrder(); diff --git a/app/code/Magento/Eav/Model/AttributeRepository.php b/app/code/Magento/Eav/Model/AttributeRepository.php index e325fea2f4717..a308bcf630f49 100644 --- a/app/code/Magento/Eav/Model/AttributeRepository.php +++ b/app/code/Magento/Eav/Model/AttributeRepository.php @@ -42,25 +42,33 @@ class AttributeRepository implements \Magento\Eav\Api\AttributeRepositoryInterfa */ protected $attributeFactory; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param Config $eavConfig * @param Resource\Entity\Attribute $eavResource * @param Resource\Entity\Attribute\CollectionFactory $attributeCollectionFactory * @param \Magento\Eav\Api\Data\AttributeSearchResultsInterfaceFactory $searchResultsFactory * @param Entity\AttributeFactory $attributeFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( \Magento\Eav\Model\Config $eavConfig, \Magento\Eav\Model\Resource\Entity\Attribute $eavResource, \Magento\Eav\Model\Resource\Entity\Attribute\CollectionFactory $attributeCollectionFactory, \Magento\Eav\Api\Data\AttributeSearchResultsInterfaceFactory $searchResultsFactory, - \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory + \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->eavConfig = $eavConfig; $this->eavResource = $eavResource; $this->attributeCollectionFactory = $attributeCollectionFactory; $this->searchResultsFactory = $searchResultsFactory; $this->attributeFactory = $attributeFactory; + $this->joinProcessor = $joinProcessor; } /** @@ -87,6 +95,7 @@ public function getList($entityTypeCode, \Magento\Framework\Api\SearchCriteriaIn /** @var \Magento\Eav\Model\Resource\Entity\Attribute\Collection $attributeCollection */ $attributeCollection = $this->attributeCollectionFactory->create(); + $this->joinProcessor->process($attributeCollection); $attributeCollection->addFieldToFilter('entity_type_code', ['eq' => $entityTypeCode]); $attributeCollection->join( ['entity_type' => $attributeCollection->getTable('eav_entity_type')], diff --git a/app/code/Magento/Eav/Model/AttributeSetRepository.php b/app/code/Magento/Eav/Model/AttributeSetRepository.php index 2e0d4457eb293..3cc9a46867910 100644 --- a/app/code/Magento/Eav/Model/AttributeSetRepository.php +++ b/app/code/Magento/Eav/Model/AttributeSetRepository.php @@ -46,25 +46,33 @@ class AttributeSetRepository implements AttributeSetRepositoryInterface */ private $searchResultsFactory; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param AttributeSetResource $attributeSetResource * @param AttributeSetFactory $attributeSetFactory * @param CollectionFactory $collectionFactory * @param Config $eavConfig * @param \Magento\Eav\Api\Data\AttributeSetSearchResultsInterfaceFactory $searchResultFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( AttributeSetResource $attributeSetResource, AttributeSetFactory $attributeSetFactory, CollectionFactory $collectionFactory, EavConfig $eavConfig, - \Magento\Eav\Api\Data\AttributeSetSearchResultsInterfaceFactory $searchResultFactory + \Magento\Eav\Api\Data\AttributeSetSearchResultsInterfaceFactory $searchResultFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->attributeSetResource = $attributeSetResource; $this->attributeSetFactory = $attributeSetFactory; $this->collectionFactory = $collectionFactory; $this->eavConfig = $eavConfig; $this->searchResultsFactory = $searchResultFactory; + $this->joinProcessor = $joinProcessor; } /** @@ -87,6 +95,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr { /** @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection $collection */ $collection = $this->collectionFactory->create(); + $this->joinProcessor->process($collection); /** The only possible/meaningful search criteria for attribute set is entity type code */ $entityTypeCode = $this->getEntityTypeCode($searchCriteria); diff --git a/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php b/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php index 5975bf3b5f422..56d56b6035d23 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/AttributeSetRepositoryTest.php @@ -42,6 +42,11 @@ class AttributeSetRepositoryTest extends \PHPUnit_Framework_TestCase */ private $resultFactoryMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $extensionAttributesJoinProcessorMock; + /** * @return void */ @@ -76,12 +81,20 @@ protected function setUp() '', false ); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + '\Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + ['process'], + [], + '', + false + ); $this->model = new \Magento\Eav\Model\AttributeSetRepository( $this->resourceMock, $this->setFactoryMock, $this->collectionFactoryMock, $this->eavConfigMock, - $this->resultFactoryMock + $this->resultFactoryMock, + $this->extensionAttributesJoinProcessorMock ); } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 9cc216d09012c..95fa91f6c6c5c 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -16,6 +16,7 @@ use Magento\Sales\Model\Resource; use Magento\Sales\Model\Status; use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; /** * Quote model @@ -322,6 +323,11 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C */ protected $dataObjectHelper; + /** + * @var JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -355,6 +361,7 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param Cart\CurrencyFactory $currencyFactory + * @param JoinProcessorInterface $extensionAttributesJoinProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -393,6 +400,7 @@ public function __construct( \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, \Magento\Quote\Model\Cart\CurrencyFactory $currencyFactory, + JoinProcessorInterface $extensionAttributesJoinProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] @@ -425,6 +433,7 @@ public function __construct( $this->dataObjectHelper = $dataObjectHelper; $this->extensibleDataObjectConverter = $extensibleDataObjectConverter; $this->currencyFactory = $currencyFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; parent::__construct( $context, $registry, @@ -1323,6 +1332,7 @@ public function getItemsCollection($useCache = true) } if (null === $this->_items) { $this->_items = $this->_quoteItemCollectionFactory->create(); + $this->extensionAttributesJoinProcessor->process($this->_items); $this->_items->setQuote($this); } return $this->_items; diff --git a/app/code/Magento/Quote/Model/QuoteRepository.php b/app/code/Magento/Quote/Model/QuoteRepository.php index b54652e7fd8ed..6fa9bca5e4e33 100644 --- a/app/code/Magento/Quote/Model/QuoteRepository.php +++ b/app/code/Magento/Quote/Model/QuoteRepository.php @@ -12,6 +12,7 @@ use Magento\Framework\Api\Search\FilterGroup; use Magento\Quote\Model\Resource\Quote\Collection as QuoteCollection; use Magento\Framework\Exception\InputException; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface { @@ -45,22 +46,30 @@ class QuoteRepository implements \Magento\Quote\Api\CartRepositoryInterface */ protected $searchResultsDataFactory; + /** + * @var JoinProcessorInterface + */ + private $extensionAttributesJoinProcessor; + /** * @param QuoteFactory $quoteFactory * @param StoreManagerInterface $storeManager * @param \Magento\Quote\Model\Resource\Quote\Collection $quoteCollection * @param \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory $searchResultsDataFactory + * @param JoinProcessorInterface $extensionAttributesJoinProcessor */ public function __construct( QuoteFactory $quoteFactory, StoreManagerInterface $storeManager, \Magento\Quote\Model\Resource\Quote\Collection $quoteCollection, - \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory $searchResultsDataFactory + \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory $searchResultsDataFactory, + JoinProcessorInterface $extensionAttributesJoinProcessor ) { $this->quoteFactory = $quoteFactory; $this->storeManager = $storeManager; $this->searchResultsDataFactory = $searchResultsDataFactory; $this->quoteCollection = $quoteCollection; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -220,6 +229,7 @@ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) } $this->quoteCollection->setCurPage($searchCriteria->getCurrentPage()); $this->quoteCollection->setPageSize($searchCriteria->getPageSize()); + $this->extensionAttributesJoinProcessor->process($this->quoteCollection); $searchData->setItems($this->quoteCollection->getItems()); diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php index 3690aa6cbf310..872cfa989fbda 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepositoryTest.php @@ -10,6 +10,7 @@ use \Magento\Quote\Model\QuoteRepository; use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; class QuoteRepositoryTest extends \PHPUnit_Framework_TestCase { @@ -19,35 +20,40 @@ class QuoteRepositoryTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Quote\Model\QuoteFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $quoteFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $storeManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject */ protected $storeMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject */ protected $quoteMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Quote\Api\Data\CartSearchResultsInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $searchResultsDataFactory; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Quote\Model\Resource\Quote\Collection|\PHPUnit_Framework_MockObject_MockObject */ protected $quoteCollectionMock; + /** + * @var JoinProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $extensionAttributesJoinProcessorMock; + protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -56,8 +62,17 @@ protected function setUp() $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); $this->quoteMock = $this->getMock( '\Magento\Quote\Model\Quote', - ['load', 'loadByCustomer', 'getIsActive', 'getId', '__wakeup', 'setSharedStoreIds', 'save', 'delete', - 'getCustomerId'], + [ + 'load', + 'loadByCustomer', + 'getIsActive', + 'getId', + '__wakeup', + 'setSharedStoreIds', + 'save', + 'delete', + 'getCustomerId' + ], [], '', false @@ -73,6 +88,14 @@ protected function setUp() $this->quoteCollectionMock = $this->getMock('Magento\Quote\Model\Resource\Quote\Collection', [], [], '', false); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + [], + [], + '', + false + ); + $this->model = $objectManager->getObject( 'Magento\Quote\Model\QuoteRepository', [ @@ -80,6 +103,7 @@ protected function setUp() 'storeManager' => $this->storeManagerMock, 'searchResultsDataFactory' => $this->searchResultsDataFactory, 'quoteCollection' => $this->quoteCollectionMock, + 'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock ] ); } @@ -362,6 +386,11 @@ public function testGetListSuccess($direction, $expectedDirection) $this->quoteCollectionMock->expects($this->once())->method('setCurPage')->with(1); $this->quoteCollectionMock->expects($this->once())->method('setPageSize')->with(10); + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with( + $this->isInstanceOf('\Magento\Quote\Model\Resource\Quote\Collection') + ); $this->quoteCollectionMock->expects($this->once())->method('getItems')->willReturn([$cartMock]); $searchResult->expects($this->once())->method('setItems')->with([$cartMock]); diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php index 96815ef257fa1..4412f8fc3669e 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php @@ -12,6 +12,7 @@ use Magento\Store\Model\ScopeInterface; use Magento\Quote\Api\Data\CartInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; /** * Test class for \Magento\Quote\Model @@ -131,6 +132,11 @@ class QuoteTest extends \PHPUnit_Framework_TestCase */ protected $objectCopyServiceMock; + /** + * @var JoinProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $extensionAttributesJoinProcessorMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -260,6 +266,14 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + [], + [], + '', + false + ); + $this->quote = (new ObjectManager($this)) ->getObject( 'Magento\Quote\Model\Quote', @@ -280,7 +294,8 @@ protected function setUp() 'scopeConfig' => $this->scopeConfig, 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverterMock, 'customerRepository' => $this->customerRepositoryMock, - 'objectCopyService' => $this->objectCopyServiceMock + 'objectCopyService' => $this->objectCopyServiceMock, + 'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock ] ); } @@ -1123,7 +1138,6 @@ public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected) $this->assertEquals($expected, $this->quote->getDataByKey(CartInterface::KEY_IS_VIRTUAL)); } - /** * @return array */ @@ -1137,4 +1151,24 @@ public function dataProviderForTestBeforeSaveIsVirtualQuote() [[false, false], 0] ]; } + + public function testGetItemsCollection() + { + $itemCollectionMock = $this->getMockBuilder('Magento\Quote\Model\Resource\Quote\Collection') + ->disableOriginalConstructor() + ->setMethods(['setQuote']) + ->getMock(); + $this->quoteItemCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($itemCollectionMock); + + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with( + $this->isInstanceOf('Magento\Quote\Model\Resource\Quote\Collection') + ); + $itemCollectionMock->expects($this->once())->method('setQuote')->with($this->quote); + + $this->quote->getItemsCollection(); + } } diff --git a/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php b/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php index b11a2c04de8d3..a7c67652dd7a4 100644 --- a/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php @@ -18,7 +18,7 @@ interface OrderSearchResultInterface /** * Gets collection items. * - * @return \Magento\Sales\Api\Data\OrderSearchResultInterface[] Array of collection items. + * @return \Magento\Sales\Api\Data\OrderInterface[] Array of collection items. */ public function getItems(); } diff --git a/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php b/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php index c7e2d8cfb759c..f256bb88af2ab 100644 --- a/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php @@ -18,7 +18,7 @@ interface InvoiceCommentRepositoryInterface * Lists invoice comments that match specified search criteria. * * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. - * @return \Magento\Sales\Api\Data\InvoiceSearchResultInterface Invoice search result interface. + * @return \Magento\Sales\Api\Data\InvoiceCommentSearchResultInterface Invoice search result interface. */ public function getList(\Magento\Framework\Api\SearchCriteria $criteria); diff --git a/app/code/Magento/Tax/Model/Calculation/RateRepository.php b/app/code/Magento/Tax/Model/Calculation/RateRepository.php index 6f099ea27ae35..d124469768d16 100644 --- a/app/code/Magento/Tax/Model/Calculation/RateRepository.php +++ b/app/code/Magento/Tax/Model/Calculation/RateRepository.php @@ -65,6 +65,11 @@ class RateRepository implements \Magento\Tax\Api\TaxRateRepositoryInterface */ protected $resourceModel; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param Converter $converter * @param RateRegistry $rateRegistry @@ -73,6 +78,7 @@ class RateRepository implements \Magento\Tax\Api\TaxRateRepositoryInterface * @param CountryFactory $countryFactory * @param RegionFactory $regionFactory * @param \Magento\Tax\Model\Resource\Calculation\Rate $rateResource + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( Converter $converter, @@ -81,7 +87,8 @@ public function __construct( RateFactory $rateFactory, CountryFactory $countryFactory, RegionFactory $regionFactory, - \Magento\Tax\Model\Resource\Calculation\Rate $rateResource + \Magento\Tax\Model\Resource\Calculation\Rate $rateResource, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->converter = $converter; $this->rateRegistry = $rateRegistry; @@ -90,6 +97,7 @@ public function __construct( $this->countryFactory = $countryFactory; $this->regionFactory = $regionFactory; $this->resourceModel = $rateResource; + $this->joinProcessor = $joinProcessor; } /** @@ -146,6 +154,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr { /** @var \Magento\Tax\Model\Resource\Calculation\Rate\Collection $collection */ $collection = $this->rateFactory->create()->getCollection(); + $this->joinProcessor->process($collection); $collection->joinRegionTable(); //Add filters from root filter group to the collection diff --git a/app/code/Magento/Tax/Model/TaxClass/Repository.php b/app/code/Magento/Tax/Model/TaxClass/Repository.php index 01dd656b0d5e5..54b92c00c6633 100644 --- a/app/code/Magento/Tax/Model/TaxClass/Repository.php +++ b/app/code/Magento/Tax/Model/TaxClass/Repository.php @@ -62,6 +62,11 @@ class Repository implements \Magento\Tax\Api\TaxClassRepositoryInterface */ protected $taxClassResource; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param FilterBuilder $filterBuilder @@ -69,6 +74,7 @@ class Repository implements \Magento\Tax\Api\TaxClassRepositoryInterface * @param \Magento\Tax\Api\Data\TaxClassSearchResultsInterfaceFactory $searchResultsFactory * @param ClassModelRegistry $classModelRegistry * @param \Magento\Tax\Model\Resource\TaxClass $taxClassResource + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( SearchCriteriaBuilder $searchCriteriaBuilder, @@ -76,7 +82,8 @@ public function __construct( TaxClassCollectionFactory $taxClassCollectionFactory, \Magento\Tax\Api\Data\TaxClassSearchResultsInterfaceFactory $searchResultsFactory, ClassModelRegistry $classModelRegistry, - \Magento\Tax\Model\Resource\TaxClass $taxClassResource + \Magento\Tax\Model\Resource\TaxClass $taxClassResource, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->filterBuilder = $filterBuilder; @@ -84,6 +91,7 @@ public function __construct( $this->searchResultsFactory = $searchResultsFactory; $this->classModelRegistry = $classModelRegistry; $this->taxClassResource = $taxClassResource; + $this->joinProcessor = $joinProcessor; } /** @@ -195,6 +203,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr $searchResults->setSearchCriteria($searchCriteria); /** @var TaxClassCollection $collection */ $collection = $this->taxClassCollectionFactory->create(); + $this->joinProcessor->process($collection); foreach ($searchCriteria->getFilterGroups() as $group) { $this->addFilterGroupToCollection($group, $collection); } diff --git a/app/code/Magento/Tax/Model/TaxRuleRepository.php b/app/code/Magento/Tax/Model/TaxRuleRepository.php index d186c79b562aa..28ff8015b9a66 100644 --- a/app/code/Magento/Tax/Model/TaxRuleRepository.php +++ b/app/code/Magento/Tax/Model/TaxRuleRepository.php @@ -52,25 +52,33 @@ class TaxRuleRepository implements TaxRuleRepositoryInterface */ protected $resource; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @param TaxRuleRegistry $taxRuleRegistry * @param TaxRuleSearchResultsInterfaceFactory $searchResultsFactory * @param RuleFactory $ruleFactory * @param CollectionFactory $collectionFactory * @param Resource $resource + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor */ public function __construct( TaxRuleRegistry $taxRuleRegistry, TaxRuleSearchResultsInterfaceFactory $searchResultsFactory, RuleFactory $ruleFactory, CollectionFactory $collectionFactory, - Resource $resource + Resource $resource, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor ) { $this->taxRuleRegistry = $taxRuleRegistry; $this->taxRuleSearchResultsFactory = $searchResultsFactory; $this->taxRuleModelFactory = $ruleFactory; $this->collectionFactory = $collectionFactory; $this->resource = $resource; + $this->joinProcessor = $joinProcessor; } /** @@ -133,6 +141,7 @@ public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) $fields = []; $collection = $this->collectionFactory->create(); + $this->joinProcessor->process($collection); //Add filters from root filter group to the collection foreach ($searchCriteria->getFilterGroups() as $group) { diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php index 7feff54990150..f2d8b4b17d164 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateRepositoryTest.php @@ -59,6 +59,11 @@ class RateRepositoryTest extends \PHPUnit_Framework_TestCase */ private $rateResourceMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $joinProcessorMock; + public function setUp() { $this->rateConverterMock = $this->getMock( @@ -117,6 +122,13 @@ public function setUp() '', false ); + $this->joinProcessorMock = $this->getMock( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + [], + [], + '', + false + ); $this->model = new RateRepository( $this->rateConverterMock, $this->rateRegistryMock, @@ -124,7 +136,8 @@ public function setUp() $this->rateFactoryMock, $this->countryFactoryMock, $this->regionFactoryMock, - $this->rateResourceMock + $this->rateResourceMock, + $this->joinProcessorMock ); } @@ -256,6 +269,8 @@ public function testGetList() ->willReturnSelf(); $this->searchResultFactory->expects($this->once())->method('create')->willReturn($this->searchResultMock); + $this->joinProcessorMock->expects($this->once())->method('process')->with($collectionMock); + $this->model->getList($searchCriteriaMock); } @@ -402,6 +417,8 @@ public function testGetListWhenFilterGroupExists() ->willReturnSelf(); $this->searchResultFactory->expects($this->once())->method('create')->willReturn($this->searchResultMock); + $this->joinProcessorMock->expects($this->once())->method('process')->with($collectionMock); + $this->model->getList($searchCriteriaMock); } diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/RepositoryTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/RepositoryTest.php index 80894cab62e2a..bfab6b77acc7f 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/TaxClass/RepositoryTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxClass/RepositoryTest.php @@ -47,6 +47,11 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase */ protected $taxClassCollectionFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionAttributesJoinProcessorMock; + /** * @return void */ @@ -85,13 +90,23 @@ protected function setUp() ); $this->taxClassResourceMock = $this->getMock('\Magento\Tax\Model\Resource\TaxClass', [], [], '', false); + + $this->extensionAttributesJoinProcessorMock = $this->getMock( + '\Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + ['process'], + [], + '', + false + ); + $this->model = $this->objectManager->getObject( 'Magento\Tax\Model\TaxClass\Repository', [ 'classModelRegistry' => $this->classModelRegistryMock, 'taxClassResource' => $this->taxClassResourceMock, 'searchResultsFactory' => $this->searchResultFactory, - 'taxClassCollectionFactory' => $this->taxClassCollectionFactory + 'taxClassCollectionFactory' => $this->taxClassCollectionFactory, + 'joinProcessor' => $this->extensionAttributesJoinProcessorMock ] ); } @@ -187,6 +202,10 @@ public function testGetList() $collection = $this->getMock('\Magento\Tax\Model\Resource\TaxClass\Collection', [], [], '', false); $sortOrder = $this->getMock('\Magento\Framework\Api\SortOrder', [], [], '', false); + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with($collection); + $searchCriteria->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroup]); $filterGroup->expects($this->once())->method('getFilters')->willReturn([$filter]); $filter->expects($this->atLeastOnce())->method('getConditionType')->willReturn('eq'); diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxRuleRepositoryTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxRuleRepositoryTest.php index 435fa82bbe9e4..3225be5242f8a 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/TaxRuleRepositoryTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxRuleRepositoryTest.php @@ -46,6 +46,11 @@ class TaxRuleRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $resource; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionAttributesJoinProcessorMock; + /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ @@ -78,13 +83,21 @@ protected function setUp() false ); $this->resource = $this->getMock('\Magento\Tax\Model\Resource\Calculation\Rule', [], [], '', false); + $this->extensionAttributesJoinProcessorMock = $this->getMock( + '\Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + ['process'], + [], + '', + false + ); $this->model = new TaxRuleRepository( $this->taxRuleRegistry, $this->searchResultFactory, $this->ruleFactory, $this->collectionFactory, - $this->resource + $this->resource, + $this->extensionAttributesJoinProcessorMock ); } @@ -181,6 +194,10 @@ public function testGetList() $filterMock = $this->getMock('\Magento\Framework\Api\Filter', [], [], '', false); $sortOrderMock = $this->getMock('\Magento\Framework\Api\SortOrder', [], [], '', false); + $this->extensionAttributesJoinProcessorMock->expects($this->once()) + ->method('process') + ->with($collectionMock); + $this->searchResultsMock->expects($this->once())->method('setSearchCriteria')->with($searchCriteriaMock); $this->collectionFactory->expects($this->once())->method('create')->willReturn($collectionMock); $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroupMock]); diff --git a/app/code/Magento/User/Model/UserInterface.php b/app/code/Magento/User/Api/Data/UserInterface.php similarity index 91% rename from app/code/Magento/User/Model/UserInterface.php rename to app/code/Magento/User/Api/Data/UserInterface.php index 4b4cecf569a01..c5de7bd1bc5e8 100644 --- a/app/code/Magento/User/Model/UserInterface.php +++ b/app/code/Magento/User/Api/Data/UserInterface.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\User\Model; +namespace Magento\User\Api\Data; /** * Admin user interface. @@ -14,119 +14,119 @@ interface UserInterface { /** * Get ID. - * + * * @return int */ public function getId(); - + /** * Set ID. - * + * * @param int $id * @return $this */ public function setId($id); - + /** * Get first name. - * + * * @return string */ public function getFirstName(); - + /** * Set first name. - * + * * @param string $firstName * @return $this */ public function setFirstName($firstName); - + /** * Get last name. - * + * * @return string */ public function getLastName(); - + /** * Set last name. - * + * * @param string $lastName * @return $this */ public function setLastName($lastName); - + /** * Get email. - * + * * @return string */ public function getEmail(); - + /** * Set email. - * + * * @param string $email * @return $this */ public function setEmail($email); - + /** * Get user name. - * + * * @return string */ public function getUserName(); - + /** * Set user name. - * + * * @param string $userName * @return $this */ public function setUserName($userName); - + /** * Get password or password hash. - * + * * @return string */ public function getPassword(); - + /** * Set password or password hash. - * + * * @param string $password * @return $this */ public function setPassword($password); - + /** * Get user record creation date. - * + * * @return string */ public function getCreated(); - + /** * Set user record creation date. - * + * * @param string $created * @return $this */ public function setCreated($created); - + /** * Get user record modification date. - * + * * @return string */ public function getModified(); - + /** * Set user record modification date. - * + * * @param string $modified * @return $this */ diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index 9ab8a1039fcfb..b152509226ddb 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -8,6 +8,7 @@ use Magento\Backend\Model\Auth\Credential\StorageInterface; use Magento\Framework\Model\AbstractModel; use Magento\Framework\Exception\AuthenticationException; +use Magento\User\Api\Data\UserInterface; /** * Admin user model diff --git a/app/code/Magento/User/etc/di.xml b/app/code/Magento/User/etc/di.xml index f76198da27e60..962ccc2aa632a 100644 --- a/app/code/Magento/User/etc/di.xml +++ b/app/code/Magento/User/etc/di.xml @@ -14,5 +14,5 @@ - + diff --git a/app/etc/di.xml b/app/etc/di.xml index 02cd1c358cb7e..87986caa2ba5a 100644 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -34,6 +34,8 @@ system/currency/installed + + diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/Api/TestRepositoryInterface.php b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/Api/TestRepositoryInterface.php new file mode 100644 index 0000000000000..fd70ae4b5fb01 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/Api/TestRepositoryInterface.php @@ -0,0 +1,20 @@ +quoteCollectionFactory = $quoteCollectionFactory; + $this->searchResultsDataFactory = $searchResultsDataFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; + } + + /** + * {@inheritdoc} + */ + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) + { + $quoteCollection = $this->quoteCollectionFactory->create(); + $this->extensionAttributesJoinProcessor->process($quoteCollection); + $searchData = $this->searchResultsDataFactory->create(); + $searchData->setSearchCriteria($searchCriteria); + $searchData->setItems($quoteCollection->getItems()); + return $searchData; + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/composer.json b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/composer.json new file mode 100644 index 0000000000000..72d19bcf34cfb --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/composer.json @@ -0,0 +1,20 @@ +{ + "name": "magento/module-test-join-directives", + "description": "test integration for join directives", + "require": { + "php": "~5.5.0|~5.6.0", + "magento/framework": "0.42.0-beta8", + "magento/module-sales": "0.42.0-beta8", + "magento/magento-composer-installer": "*" + }, + "type": "magento2-module", + "version": "1.0", + "extra": { + "map": [ + [ + "*", + "Magento/TestModuleJoinDirectives" + ] + ] + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/acl.xml b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/acl.xml new file mode 100644 index 0000000000000..ad548566ba7d1 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/acl.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/di.xml new file mode 100644 index 0000000000000..a3633a8adf41f --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/di.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/extension_attributes.xml b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/extension_attributes.xml new file mode 100644 index 0000000000000..e20f73c0d237f --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/extension_attributes.xml @@ -0,0 +1,34 @@ + + + + + + + firstname + lastname + email + + + + + + + firstname + lastname + email + + + + diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/module.xml b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/module.xml new file mode 100644 index 0000000000000..7f91223ddc7d2 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/module.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/webapi.xml b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/webapi.xml new file mode 100644 index 0000000000000..741e134c76d7e --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestJoinDirectives/etc/webapi.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php index fa8be5fc2dcc2..722dfb6770135 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/GroupRepositoryTest.php @@ -863,16 +863,16 @@ private function createGroup($group) public function testSearchGroupsDataProvider() { return [ - ['tax_class_id', '3', []], - ['tax_class_id', '0', null], + ['tax_class_id', 3, []], + ['tax_class_id', 0, null], ['code', md5(mt_rand(0, 10000000000) . time()), null], [ 'id', - '0', + 0, [ - 'id' => '0', + 'id' => 0, 'code' => 'NOT LOGGED IN', - 'tax_class_id' => '3', + 'tax_class_id' => 3, 'tax_class_name' => 'Retail Customer' ] ], @@ -880,19 +880,19 @@ public function testSearchGroupsDataProvider() 'code', 'General', [ - 'id' => '1', + 'id' => 1, 'code' => 'General', - 'tax_class_id' => '3', + 'tax_class_id' => 3, 'tax_class_name' => 'Retail Customer' ] ], [ 'id', - '2', + 2, [ - 'id' => '2', + 'id' => 2, 'code' => 'Wholesale', - 'tax_class_id' => '3', + 'tax_class_id' => 3, 'tax_class_name' => 'Retail Customer' ] ], @@ -900,9 +900,9 @@ public function testSearchGroupsDataProvider() 'code', 'Retailer', [ - 'id' => '3', + 'id' => 3, 'code' => 'Retailer', - 'tax_class_id' => '3', + 'tax_class_id' => 3, 'tax_class_name' => 'Retail Customer' ] ] diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php new file mode 100644 index 0000000000000..142283fa8ac35 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php @@ -0,0 +1,136 @@ +searchBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder'); + $this->sortOrderBuilder = $objectManager->create('Magento\Framework\Api\SortOrderBuilder'); + $this->filterBuilder = $objectManager->create('Magento\Framework\Api\FilterBuilder'); + $this->user = $objectManager->create('Magento\User\Model\User'); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/quote.php + */ + public function testGetList() + { + /** @var SortOrder $sortOrder */ + $sortOrder = $this->sortOrderBuilder->setField('store_id')->setDirection(SearchCriteria::SORT_ASC)->create(); + $this->searchBuilder->setSortOrders([$sortOrder]); + $searchCriteria = $this->searchBuilder->create()->__toArray(); + $requestData = ['searchCriteria' => $searchCriteria]; + + $restResourcePath = '/V1/TestJoinDirectives/'; + $soapService = 'testJoinDirectivesTestRepositoryV1'; + $expectedExtensionAttributes = $this->getExpectedExtensionAttributes(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $restResourcePath . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => $soapService, + 'operation' => $soapService . 'GetList', + ], + ]; + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertArrayHasKey('items', $searchResult); + $itemData = array_pop($searchResult['items']); + $this->assertArrayHasKey('extension_attributes', $itemData); + $this->assertArrayHasKey('quote_api_test_attribute', $itemData['extension_attributes']); + $testAttribute = $itemData['extension_attributes']['quote_api_test_attribute']; + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute['first_name']); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute['last_name']); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute['email']); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/invoice.php + */ + public function testAutoGeneratedGetList() + { + $this->getExpectedExtensionAttributes(); + /** @var SortOrder $sortOrder */ + $sortOrder = $this->sortOrderBuilder->setField('store_id')->setDirection(SearchCriteria::SORT_ASC)->create(); + $this->searchBuilder->setSortOrders([$sortOrder]); + $this->searchBuilder->addFilter([$this->filterBuilder->setField('state')->setValue(2)->create()]); + $searchCriteria = $this->searchBuilder->create()->__toArray(); + $requestData = ['criteria' => $searchCriteria]; + + $restResourcePath = '/V1/invoices/'; + $soapService = 'salesInvoiceRepositoryV1'; + $expectedExtensionAttributes = $this->getExpectedExtensionAttributes(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $restResourcePath . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => $soapService, + 'operation' => $soapService . 'GetList', + ], + ]; + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertArrayHasKey('items', $searchResult); + $itemData = array_pop($searchResult['items']); + $this->assertArrayHasKey('extension_attributes', $itemData); + $this->assertArrayHasKey('invoice_api_test_attribute', $itemData['extension_attributes']); + $testAttribute = $itemData['extension_attributes']['invoice_api_test_attribute']; + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute['first_name']); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute['last_name']); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute['email']); + } + + /** + * Retrieve the admin user's information. + * + * @return array + */ + private function getExpectedExtensionAttributes() + { + $this->user->load(1); + return [ + 'firstname' => $this->user->getFirstname(), + 'lastname' => $this->user->getLastname(), + 'email' => $this->user->getEmail() + ]; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 13aefd3cb0531..e5d71b3055b8f 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -122,6 +122,13 @@ class Application */ private $globalConfigFile; + /** + * Defines whether load test extension attributes or not + * + * @var bool + */ + private $loadTestExtensionAttributes; + /** * Constructor * @@ -132,6 +139,7 @@ class Application * @param string $globalConfigDir * @param string $appMode * @param AutoloaderInterface $autoloadWrapper + * @param bool|null $loadTestExtensionAttributes */ public function __construct( \Magento\Framework\Shell $shell, @@ -140,7 +148,8 @@ public function __construct( $globalConfigFile, $globalConfigDir, $appMode, - AutoloaderInterface $autoloadWrapper + AutoloaderInterface $autoloadWrapper, + $loadTestExtensionAttributes = false ) { if (getcwd() != BP . '/dev/tests/integration') { chdir(BP . '/dev/tests/integration'); @@ -150,6 +159,7 @@ public function __construct( $this->_globalConfigDir = realpath($globalConfigDir); $this->_appMode = $appMode; $this->installDir = $installDir; + $this->loadTestExtensionAttributes = $loadTestExtensionAttributes; $customDirs = $this->getCustomDirs(); $this->dirList = new \Magento\Framework\App\Filesystem\DirectoryList(BP, $customDirs); @@ -323,25 +333,28 @@ public function initialize($overriddenParams = []) $objectManager->addSharedInstance($logger, 'Magento\Framework\Logger\Monolog'); $sequenceBuilder = $objectManager->get('\Magento\TestFramework\Db\Sequence\Builder'); $objectManager->addSharedInstance($sequenceBuilder, 'Magento\SalesSequence\Model\Builder'); - Helper\Bootstrap::setObjectManager($objectManager); - - $objectManager->configure( - [ - 'preferences' => [ - 'Magento\Framework\App\State' => 'Magento\TestFramework\App\State', - 'Magento\Framework\Mail\TransportInterface' => 'Magento\TestFramework\Mail\TransportInterfaceMock', - 'Magento\Framework\Mail\Template\TransportBuilder' - => 'Magento\TestFramework\Mail\Template\TransportBuilderMock', - ], - 'Magento\Framework\Api\ExtensionAttribute\Config\Reader' => [ - 'arguments' => [ - 'fileResolver' => ['instance' => 'Magento\TestFramework\Api\Config\Reader\FileResolver'], - ], - ], + $objectManagerConfiguration = [ + 'preferences' => [ + 'Magento\Framework\App\State' => 'Magento\TestFramework\App\State', + 'Magento\Framework\Mail\TransportInterface' => 'Magento\TestFramework\Mail\TransportInterfaceMock', + 'Magento\Framework\Mail\Template\TransportBuilder' + => 'Magento\TestFramework\Mail\Template\TransportBuilderMock', ] - ); - + ]; + if ($this->loadTestExtensionAttributes) { + $objectManagerConfiguration = array_merge( + $objectManagerConfiguration, + [ + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader' => [ + 'arguments' => [ + 'fileResolver' => ['instance' => 'Magento\TestFramework\Api\Config\Reader\FileResolver'], + ], + ], + ] + ); + } + $objectManager->configure($objectManagerConfiguration); /** Register event observer of Integration Framework */ /** @var \Magento\Framework\Event\Config\Data $eventConfigData */ $eventConfigData = $objectManager->get('Magento\Framework\Event\Config\Data'); @@ -356,7 +369,6 @@ public function initialize($overriddenParams = []) ] ] ); - $this->loadArea(\Magento\TestFramework\Application::DEFAULT_APP_AREA); \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->configure( $objectManager->get('Magento\Framework\ObjectManager\DynamicConfigInterface')->getConfiguration() diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 2f607671fe773..e39836e58dd5b 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -52,7 +52,8 @@ $globalConfigFile, $settings->get('TESTS_GLOBAL_CONFIG_DIR'), $settings->get('TESTS_MAGENTO_MODE'), - AutoloaderRegistry::getAutoloader() + AutoloaderRegistry::getAutoloader(), + true ); $bootstrap = new \Magento\TestFramework\Bootstrap( @@ -71,7 +72,7 @@ if (!$application->isInstalled()) { $application->install(); } - $application->initialize(); + $application->initialize([]); \Magento\TestFramework\Helper\Bootstrap::setInstance(new \Magento\TestFramework\Helper\Bootstrap($bootstrap)); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/OptionListTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/OptionListTest.php new file mode 100644 index 0000000000000..62f5cff1ff52e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/OptionListTest.php @@ -0,0 +1,44 @@ +objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product.php + */ + public function testGetItems() + { + $this->product = $this->objectManager->get('Magento\Catalog\Model\Product'); + $this->product->load(3); + /** + * @var \Magento\Bundle\Model\Product\OptionList $optionList + */ + $optionList = $this->objectManager->create('\Magento\Bundle\Model\Product\OptionList'); + $options = $optionList->getItems($this->product); + $this->assertEquals(1, count($options)); + $this->assertEquals('Bundle Product Items', $options[0]->getTitle()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index db9cfaa872bda..cbd558ed2f3e0 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -419,4 +419,15 @@ public function testValidate() $this->assertTrue($error); } } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoAppIsolation enabled + */ + public function testGetOptions() + { + $this->_model->load(1); + $options = $this->_model->getOptions(); + $this->assertEquals(4, count($options)); + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/OptionRepositoryTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/OptionRepositoryTest.php new file mode 100644 index 0000000000000..dfe06c0deefe3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/OptionRepositoryTest.php @@ -0,0 +1,33 @@ +create('Magento\ConfigurableProduct\Api\OptionRepositoryInterface'); + + $options = $optionRepository->getList($productSku); + $this->assertCount(1, $options, "Invalid number of option."); + $this->assertNotNull($options[0]->getExtensionAttributes(), "Extension attributes not loaded"); + /** @var \Magento\Eav\Model\Entity\Attribute $joinedEntity */ + $joinedEntity = $objectManager->create('Magento\Eav\Model\Entity\Attribute'); + $joinedEntity->load($options[0]->getId()); + $joinedExtensionAttributeValue = $joinedEntity->getAttributeCode(); + $this->assertEquals( + $joinedExtensionAttributeValue, + $options[0]->getExtensionAttributes()->getTestDummyAttribute(), + "Extension attributes were not loaded correctly" + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/etc/extension_attributes.xml new file mode 100644 index 0000000000000..dbf00dbc8c5b0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/etc/extension_attributes.xml @@ -0,0 +1,20 @@ + + + + + + + attribute_code + + + + diff --git a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php index 16cfa26b08873..438de55ed11d1 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Api/AddressRepositoryTest.php @@ -316,7 +316,7 @@ public function testSearchAddresses($filters, $filterGroup, $expectedResult) $this->assertEquals(count($expectedResult), $searchResults->getTotalCount()); - /** @var \Magento\Customer\Api\Data\AddressInterface $item*/ + /** @var \Magento\Customer\Api\Data\AddressInterface $item */ foreach ($searchResults->getItems() as $item) { $this->assertEquals( $expectedResult[$item->getId()]['city'], diff --git a/dev/tests/integration/testsuite/Magento/Customer/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Customer/etc/extension_attributes.xml new file mode 100644 index 0000000000000..6c210f6f4125f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/etc/extension_attributes.xml @@ -0,0 +1,19 @@ + + + + + + + group_id + + + + diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/Model/Product/TypeTest.php b/dev/tests/integration/testsuite/Magento/Downloadable/Model/Product/TypeTest.php index 2628c9c0e2880..cb06602f2c2a5 100644 --- a/dev/tests/integration/testsuite/Magento/Downloadable/Model/Product/TypeTest.php +++ b/dev/tests/integration/testsuite/Magento/Downloadable/Model/Product/TypeTest.php @@ -69,6 +69,7 @@ public function testDeleteTypeSpecificData() /** * @magentoDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php * @magentoAppArea adminhtml + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testSaveTypeSpecificData() { @@ -129,12 +130,21 @@ public function testSaveTypeSpecificData() 'title' => 'Updated downloadable link #1', 'website_price' => '15.0000', ]; - - + $expectedExtensionAttributes = [ + 'firstname' => 'firstname', + 'lastname' => 'lastname', + 'email' => 'admin@example.com' + ]; $links = $this->_model->getLinks($product); $this->assertNotEmpty($links); $this->assertCount(1, $links); + /** @var \Magento\Downloadable\Model\Link $link */ $link = reset($links); + /** @var \Magento\User\Api\Data\UserInterface $testAttribute */ + $testAttribute = $link->getExtensionAttributes()->getTestAttribute(); + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute->getFirstName()); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute->getLastName()); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute->getEmail()); foreach ($expectedLink as $key => $value) { $this->assertTrue($link->hasData($key), 'Key ' . $key . ' not exist!'); $this->assertArrayHasKey($key, $link); @@ -157,6 +167,11 @@ public function testSaveTypeSpecificData() $this->assertEquals(1, $samples->count()); /** @var \Magento\Downloadable\Model\Sample $sample */ $sample = $samples->getFirstItem()->getData(); + /** @var \Magento\User\Api\Data\UserInterface $testAttribute */ + $testAttribute = $sample['extension_attributes']->getTestAttribute(); + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute->getFirstName()); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute->getLastName()); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute->getEmail()); foreach ($expectedSample as $key => $value) { $this->assertArrayHasKey($key, $sample); $this->assertEquals($value, $sample[$key]); diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Downloadable/etc/extension_attributes.xml new file mode 100644 index 0000000000000..e120bbea99bcf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Downloadable/etc/extension_attributes.xml @@ -0,0 +1,34 @@ + + + + + + + firstname + lastname + email + + + + + + + firstname + lastname + email + + + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php new file mode 100644 index 0000000000000..10be075426201 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php @@ -0,0 +1,404 @@ +config = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') + ->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributeJoinDataFactory = $this + ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataInterfaceFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributeJoinDataFactory = $this + ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataInterfaceFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->typeProcessor = $this->getMockBuilder('Magento\Framework\Reflection\TypeProcessor') + ->disableOriginalConstructor() + ->getMock(); + + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + $this->appResource = $objectManager->get('Magento\Framework\App\Resource'); + + $this->joinProcessor = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + [ + 'objectManager' => $objectManager, + 'config' => $this->config, + 'extensionAttributeJoinDataFactory' => $this->extensionAttributeJoinDataFactory, + 'typeProcessor' => $this->typeProcessor + ] + ); + } + + /** + * Test the processing of the join config for a particular type + */ + public function testProcess() + { + $this->config->expects($this->once()) + ->method('get') + ->will($this->returnValue($this->getConfig())); + + $collection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setMethods(['joinExtensionAttribute']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $extensionAttributeJoinData = new JoinData(); + $this->extensionAttributeJoinDataFactory + ->expects($this->once()) + ->method('create') + ->willReturn($extensionAttributeJoinData); + + $collection->expects($this->once())->method('joinExtensionAttribute')->with($extensionAttributeJoinData); + + $this->joinProcessor->process($collection, 'Magento\Catalog\Api\Data\ProductInterface'); + $expectedTableName = 'reviews'; + $this->assertEquals($expectedTableName, $extensionAttributeJoinData->getReferenceTable()); + $this->assertEquals('extension_attribute_review_id', $extensionAttributeJoinData->getReferenceTableAlias()); + $this->assertEquals('product_id', $extensionAttributeJoinData->getReferenceField()); + $this->assertEquals('id', $extensionAttributeJoinData->getJoinField()); + $this->assertEquals( + [ + [ + 'external_alias' => 'review_id', + 'internal_alias' => 'extension_attribute_review_id_db_review_id', + 'with_db_prefix' => 'extension_attribute_review_id.db_review_id', + 'setter' => 'setReviewId', + ] + ], + $extensionAttributeJoinData->getSelectFields() + ); + } + + private function getConfig() + { + return [ + 'Magento\Catalog\Api\Data\ProductInterface' => [ + 'review_id' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "reviews", + Converter::JOIN_REFERENCE_FIELD => "product_id", + Converter::JOIN_FIELDS => [ + [ + Converter::JOIN_FIELD => "review_id", + Converter::JOIN_FIELD_COLUMN => "db_review_id", + ], + ], + Converter::JOIN_ON_FIELD => "id", + ], + ], + ], + 'Magento\Customer\Api\Data\CustomerInterface' => [ + 'library_card_id' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "library_account", + Converter::JOIN_FIELDS => [ + [ + Converter::JOIN_FIELD => "library_card_id", + Converter::JOIN_FIELD_COLUMN => "", + ], + ], + Converter::JOIN_ON_FIELD => "customer_id", + ], + ], + 'reviews' => [ + Converter::DATA_TYPE => 'Magento\Reviews\Api\Data\Reviews[]', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "reviews", + Converter::JOIN_FIELDS => [ + [ + Converter::JOIN_FIELD => "comment", + Converter::JOIN_FIELD_COLUMN => "", + ], + [ + Converter::JOIN_FIELD => "rating", + Converter::JOIN_FIELD_COLUMN => "", + ], + ], + Converter::JOIN_ON_FIELD => "customer_id", + ], + ], + ], + ]; + } + + public function testProcessSqlSelectVerification() + { + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ + $config = $objectManager->get('Magento\Framework\Api\ExtensionAttribute\Config'); + $config->reset(); + + $extensionConfigFileResolverMock = $this->getMockBuilder('Magento\Framework\Config\FileResolverInterface') + ->disableOriginalConstructor() + ->getMock(); + $extensionConfigFilePath = __DIR__ . '/../_files/extension_attributes.xml'; + $extensionConfigFileContent = file_get_contents($extensionConfigFilePath); + $extensionConfigFileResolverMock->expects($this->any()) + ->method('get') + ->willReturn([$extensionConfigFilePath => $extensionConfigFileContent]); + $configReader = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader', + ['fileResolver' => $extensionConfigFileResolverMock] + ); + /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ + $config = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\Config', + ['reader' => $configReader] + ); + /** @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessor $extensionAttributesProcessor */ + $extensionAttributesProcessor = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessor', + ['config' => $config] + ); + /** @var \Magento\Catalog\Model\Resource\Product\Collection $collection */ + $collection = $objectManager->create('Magento\Catalog\Model\Resource\Product\Collection'); + $extensionAttributesProcessor->process($collection); + $config->reset(); + + $catalogProductEntity = $this->appResource->getTableName('catalog_product_entity'); + $catalogInventoryStockItem = $this->appResource->getTableName('cataloginventory_stock_item'); + $reviews = $this->appResource->getTableName('reviews'); + $expectedSql = <<getSelectSql(true); + $formattedResultSql = str_replace(',', ",\n ", $resultSql); + $this->assertEquals($expectedSql, $formattedResultSql); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/products.php + */ + public function testGetListWithExtensionAttributesAbstractModel() + { + $firstProductId = 1; + $firstProductQty = 11; + $secondProductId = 2; + $secondProductQty = 22; + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = $objectManager->create('Magento\Catalog\Api\ProductRepositoryInterface'); + /** @var \Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository */ + $stockItemRepository = $objectManager->get('Magento\CatalogInventory\Api\StockItemRepositoryInterface'); + + /** Prepare stock items */ + $firstStockItem = $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem(); + $firstStockItem->setQty($firstProductQty); + $stockItemRepository->save($firstStockItem); + $this->assertEquals( + $firstProductQty, + $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem()->getQty(), + 'Precondition failed.' + ); + $secondStockItem = $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem(); + $secondStockItem->setQty($secondProductQty); + $stockItemRepository->save($secondStockItem); + $this->assertEquals( + $secondProductQty, + $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem()->getQty(), + 'Precondition failed.' + ); + + /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ + $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); + /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ + $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); + $searchCriteria->setFilterGroups([$searchCriteriaGroup]); + $products = $productRepository->getList($searchCriteria)->getItems(); + + /** Ensure that simple extension attributes were populated correctly */ + $this->assertEquals( + $firstProductQty, + $products[$firstProductId]->getExtensionAttributes()->getTestStockItemQty() + ); + $this->assertEquals( + $secondProductQty, + $products[$secondProductId]->getExtensionAttributes()->getTestStockItemQty() + ); + + /** Check population of complex extension attributes */ + $this->assertEquals( + $firstProductQty, + $products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getQty() + ); + $this->assertNotEmpty($products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getItemId()); + + $this->assertArrayNotHasKey( + 'extension_attribute_test_stock_item_qty_qty', + $products[$firstProductId]->getData(), + "Selected extension field should be unset after it is added to extension attributes object." + ); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_group.php + */ + public function testGetListWithExtensionAttributesAbstractObject() + { + $customerId = 1; + $customerGroupName = 'General'; + $taxClassId = 3; + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ + $customerRepository = $objectManager->get('Magento\Customer\Api\CustomerRepositoryInterface'); + /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ + $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); + /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ + $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); + $searchCriteria->setFilterGroups([$searchCriteriaGroup]); + $customers = $customerRepository->getList($searchCriteria)->getItems(); + + /** Ensure that simple extension attributes were populated correctly */ + $customer = $customers[0]; + $this->assertEquals($customerId, $customer->getId(), 'Precondition failed'); + $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroupCode()); + + /** Check population of complex extension attributes */ + $this->assertEquals($taxClassId, $customer->getExtensionAttributes()->getTestGroup()->getTaxClassId()); + $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroup()->getCode()); + } + + public function testGetListWithFilterBySimpleDummyAttributeWithMapping() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $groupRepository = $objectManager->create('Magento\Customer\Api\GroupRepositoryInterface'); + $searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder'); + $builder = $objectManager->create('Magento\Framework\Api\FilterBuilder'); + $joinedExtensionAttribute = 'test_dummy_attribute'; + $joinedExtensionAttributeValue = 'website_id'; + $filter = $builder->setField($joinedExtensionAttribute) + ->setValue($joinedExtensionAttributeValue) + ->create(); + $searchCriteriaBuilder->addFilter([$filter]); + $searchResults = $groupRepository->getList($searchCriteriaBuilder->create()); + $items = $searchResults->getItems(); + $this->assertCount(1, $items, 'Filtration by extension attribute does not work.'); + $expectedGroupCode = 'General'; + $this->assertEquals($expectedGroupCode, $items[0]->getCode(), 'Invalid group loaded.'); + $this->assertNotNull($items[0]->getExtensionAttributes(), "Extension attributes not loaded"); + $this->assertEquals( + $joinedExtensionAttributeValue, + $items[0]->getExtensionAttributes()->getTestDummyAttribute(), + "Extension attributes were not loaded correctly" + ); + } + + public function testGetListWithFilterByComplexDummyAttributeWithSetterMapping() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $groupRepository = $objectManager->create('Magento\Customer\Api\GroupRepositoryInterface'); + $searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder'); + $builder = $objectManager->create('Magento\Framework\Api\FilterBuilder'); + $joinedExtensionAttribute = 'test_complex_dummy_attribute.frontend_label'; + $joinedExtensionAttributeValue = 'firstname'; + $filter = $builder->setField($joinedExtensionAttribute) + ->setValue($joinedExtensionAttributeValue) + ->create(); + $searchCriteriaBuilder->addFilter([$filter]); + $searchResults = $groupRepository->getList($searchCriteriaBuilder->create()); + $items = $searchResults->getItems(); + $this->assertCount(1, $items, 'Filtration by extension attribute does not work.'); + $expectedGroupCode = 'General'; + $this->assertEquals($expectedGroupCode, $items[0]->getCode(), 'Invalid group loaded.'); + $this->assertNotNull($items[0]->getExtensionAttributes(), "Extension attributes not loaded"); + $this->assertNotNull( + $items[0]->getExtensionAttributes()->getTestComplexDummyAttribute(), + "Complex extension attribute not loaded" + ); + $this->assertEquals( + 'user', + $items[0]->getExtensionAttributes()->getTestComplexDummyAttribute()->getAttributeCode(), + "Extension attributes were not loaded correctly" + ); + $this->assertEquals( + $joinedExtensionAttributeValue, + $items[0]->getExtensionAttributes()->getTestComplexDummyAttribute()->getFrontendLabel(), + "Extension attributes were not loaded correctly" + ); + } + + /** + * @magentoDataFixture Magento/Sales/_files/invoice.php + */ + public function testGetListWithExtensionAttributesAutoGeneratedRepository() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder'); + /** @var \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository */ + $invoiceRepository = $objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface'); + $invoices = $invoiceRepository->getList($searchCriteriaBuilder->create())->getItems(); + $this->assertCount(1, $invoices, "Invalid number of loaded invoices."); + $invoice = reset($invoices); + + /** @var \Magento\Eav\Model\Entity\Attribute $joinedEntity */ + $joinedEntity = $objectManager->create('Magento\Eav\Model\Entity\Attribute'); + $joinedEntity->load($invoice->getId()); + $joinedExtensionAttributeValue = $joinedEntity->getAttributeCode(); + + $this->assertNotNull($invoice->getExtensionAttributes(), "Extension attributes not loaded"); + $this->assertEquals( + $joinedExtensionAttributeValue, + $invoice->getExtensionAttributes()->getTestDummyAttribute(), + "Extension attributes were not loaded correctly" + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php index 674fc1432f0ef..faec140dbdab7 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php @@ -5,70 +5,21 @@ */ namespace Magento\Framework\Api; -use Magento\Framework\Api\ExtensionAttribute\Config\Converter; -use Magento\Framework\Api\ExtensionAttribute\Config\Reader; -use Magento\Framework\Api\ExtensionAttribute\JoinData; -use Magento\Framework\Api\ExtensionAttribute\JoinDataFactory; -use Magento\Framework\Reflection\TypeProcessor; -use Magento\Framework\App\Resource; - class ExtensionAttributesFactoryTest extends \PHPUnit_Framework_TestCase { /** @var \Magento\Framework\Api\ExtensionAttributesFactory */ private $factory; - /** - * @var Reader|\PHPUnit_Framework_MockObject_MockObject - */ - private $config; - - /** - * @var JoinDataFactory|\PHPUnit_Framework_MockObject_MockObject - */ - private $extensionAttributeJoinDataFactory; - - /** - * @var TypeProcessor|\PHPUnit_Framework_MockObject_MockObject - */ - private $typeProcessor; - - /** - * @var AppResource|\PHPUnit_Framework_MockObject_MockObject - */ - private $appResource; - protected function setUp() { - $this->config = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') - ->disableOriginalConstructor() - ->getMock(); - $this->extensionAttributeJoinDataFactory = $this - ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataFactory') - ->disableOriginalConstructor() - ->getMock(); - $this->extensionAttributeJoinDataFactory = $this - ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataFactory') - ->disableOriginalConstructor() - ->getMock(); - $this->typeProcessor = $this->getMockBuilder('Magento\Framework\Reflection\TypeProcessor') - ->disableOriginalConstructor() - ->getMock(); - $autoloadWrapper = \Magento\Framework\Autoload\AutoloaderRegistry::getAutoloader(); $autoloadWrapper->addPsr4('Magento\\Wonderland\\', realpath(__DIR__ . '/_files/Magento/Wonderland')); /** @var \Magento\Framework\ObjectManagerInterface */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->appResource = $objectManager->get('Magento\Framework\App\Resource'); - $this->factory = $objectManager->create( 'Magento\Framework\Api\ExtensionAttributesFactory', - [ - 'objectManager' => $objectManager, - 'config' => $this->config, - 'extensionAttributeJoinDataFactory' => $this->extensionAttributeJoinDataFactory, - 'typeProcessor' => $this->typeProcessor - ] + ['objectManager' => $objectManager] ); } @@ -104,240 +55,6 @@ public function testCreate() ); } - /** - * Test the processing of the join config for a particular type - */ - public function testProcess() - { - $this->config->expects($this->once()) - ->method('get') - ->will($this->returnValue($this->getConfig())); - - $collection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') - ->setMethods(['joinExtensionAttribute']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - - $extensionAttributeJoinData = new JoinData(); - $this->extensionAttributeJoinDataFactory - ->expects($this->once()) - ->method('create') - ->willReturn($extensionAttributeJoinData); - - $collection->expects($this->once())->method('joinExtensionAttribute')->with($extensionAttributeJoinData); - - $this->factory->process($collection, 'Magento\Catalog\Api\Data\ProductInterface'); - $expectedTableName = 'reviews'; - $this->assertEquals($expectedTableName, $extensionAttributeJoinData->getReferenceTable()); - $this->assertEquals('extension_attribute_review_id', $extensionAttributeJoinData->getReferenceTableAlias()); - $this->assertEquals('product_id', $extensionAttributeJoinData->getReferenceField()); - $this->assertEquals('id', $extensionAttributeJoinData->getJoinField()); - $this->assertEquals(['review_id'], $extensionAttributeJoinData->getSelectFields()); - } - - private function getConfig() - { - return [ - 'Magento\Catalog\Api\Data\ProductInterface' => [ - 'review_id' => [ - Converter::DATA_TYPE => 'string', - Converter::RESOURCE_PERMISSIONS => [], - Converter::JOIN_DIRECTIVE => [ - Converter::JOIN_REFERENCE_TABLE => "reviews", - Converter::JOIN_REFERENCE_FIELD => "product_id", - Converter::JOIN_SELECT_FIELDS => [ - [ - Converter::JOIN_SELECT_FIELD => "review_id", - ], - ], - Converter::JOIN_JOIN_ON_FIELD => "id", - ], - ], - ], - 'Magento\Customer\Api\Data\CustomerInterface' => [ - 'library_card_id' => [ - Converter::DATA_TYPE => 'string', - Converter::RESOURCE_PERMISSIONS => [], - Converter::JOIN_DIRECTIVE => [ - Converter::JOIN_REFERENCE_TABLE => "library_account", - Converter::JOIN_SELECT_FIELDS => [ - [ - Converter::JOIN_SELECT_FIELD => "library_card_id", - ], - ], - Converter::JOIN_JOIN_ON_FIELD => "customer_id", - ], - ], - 'reviews' => [ - Converter::DATA_TYPE => 'Magento\Reviews\Api\Data\Reviews[]', - Converter::RESOURCE_PERMISSIONS => [], - Converter::JOIN_DIRECTIVE => [ - Converter::JOIN_REFERENCE_TABLE => "reviews", - Converter::JOIN_SELECT_FIELDS => [ - [ - Converter::JOIN_SELECT_FIELD => "comment", - ], - [ - Converter::JOIN_SELECT_FIELD => "rating", - ], - ], - Converter::JOIN_JOIN_ON_FIELD => "customer_id", - ], - ], - ], - ]; - } - - public function testProcessSqlSelectVerification() - { - /** @var \Magento\Framework\ObjectManagerInterface */ - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ - $config = $objectManager->get('Magento\Framework\Api\ExtensionAttribute\Config'); - $config->reset(); - - $extensionConfigFileResolverMock = $this->getMockBuilder('Magento\Framework\Config\FileResolverInterface') - ->disableOriginalConstructor() - ->getMock(); - $extensionConfigFilePath = __DIR__ . '/_files/extension_attributes.xml'; - $extensionConfigFileContent = file_get_contents($extensionConfigFilePath); - $extensionConfigFileResolverMock->expects($this->any()) - ->method('get') - ->willReturn([$extensionConfigFilePath => $extensionConfigFileContent]); - $configReader = $objectManager->create( - 'Magento\Framework\Api\ExtensionAttribute\Config\Reader', - ['fileResolver' => $extensionConfigFileResolverMock] - ); - /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ - $config = $objectManager->create( - 'Magento\Framework\Api\ExtensionAttribute\Config', - ['reader' => $configReader] - ); - /** @var \Magento\Framework\Api\ExtensionAttributesFactory $extensionAttributesFactory */ - $extensionAttributesFactory = $objectManager->create( - 'Magento\Framework\Api\ExtensionAttributesFactory', - ['config' => $config] - ); - $productClassName = 'Magento\Catalog\Model\Product'; - /** @var \Magento\Catalog\Model\Resource\Product\Collection $collection */ - $collection = $objectManager->create('Magento\Catalog\Model\Resource\Product\Collection'); - - $extensionAttributesFactory->process($collection, $productClassName); - $config->reset(); - - $catalogProductEntity = $this->appResource->getTableName('catalog_product_entity'); - $catalogInventoryStockItem = $this->appResource->getTableName('cataloginventory_stock_item'); - $reviews = $this->appResource->getTableName('reviews'); - $expectedSql = <<getSelectSql(true); - $formattedResultSql = str_replace(',', ",\n ", $resultSql); - $this->assertEquals($expectedSql, $formattedResultSql); - } - - /** - * @magentoDataFixture Magento/Catalog/_files/products.php - */ - public function testGetListWithExtensionAttributesAbstractModel() - { - $firstProductId = 1; - $firstProductQty = 11; - $secondProductId = 2; - $secondProductQty = 22; - /** @var \Magento\Framework\ObjectManagerInterface */ - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = $objectManager->create('Magento\Catalog\Api\ProductRepositoryInterface'); - /** @var \Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository */ - $stockItemRepository = $objectManager->get('Magento\CatalogInventory\Api\StockItemRepositoryInterface'); - - /** Prepare stock items */ - $firstStockItem = $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem(); - $firstStockItem->setQty($firstProductQty); - $stockItemRepository->save($firstStockItem); - $this->assertEquals( - $firstProductQty, - $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem()->getQty(), - 'Precondition failed.' - ); - $secondStockItem = $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem(); - $secondStockItem->setQty($secondProductQty); - $stockItemRepository->save($secondStockItem); - $this->assertEquals( - $secondProductQty, - $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem()->getQty(), - 'Precondition failed.' - ); - - /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ - $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); - /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ - $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); - $searchCriteria->setFilterGroups([$searchCriteriaGroup]); - $products = $productRepository->getList($searchCriteria)->getItems(); - - /** Ensure that simple extension attributes were populated correctly */ - $this->assertEquals( - $firstProductQty, - $products[$firstProductId]->getExtensionAttributes()->getTestStockItemQty() - ); - $this->assertEquals( - $secondProductQty, - $products[$secondProductId]->getExtensionAttributes()->getTestStockItemQty() - ); - - /** Check population of complex extension attributes */ - $this->assertEquals( - $firstProductQty, - $products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getQty() - ); - $this->assertNotEmpty($products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getItemId()); - - $this->assertArrayNotHasKey( - 'extension_attribute_test_stock_item_qty_qty', - $products[$firstProductId]->getData(), - "Selected extension field should be unset after it is added to extension attributes object." - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - * @magentoDataFixture Magento/Customer/_files/customer_group.php - */ - public function testGetListWithExtensionAttributesAbstractObject() - { - $customerId = 1; - $customerGroupName = 'General'; - $taxClassId = 3; - /** @var \Magento\Framework\ObjectManagerInterface */ - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - /** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ - $customerRepository = $objectManager->get('Magento\Customer\Api\CustomerRepositoryInterface'); - /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ - $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); - /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ - $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); - $searchCriteria->setFilterGroups([$searchCriteriaGroup]); - $customers = $customerRepository->getList($searchCriteria)->getItems(); - - /** Ensure that simple extension attributes were populated correctly */ - $customer = $customers[0]; - $this->assertEquals($customerId, $customer->getId(), 'Precondition failed'); - $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroupCode()); - - /** Check population of complex extension attributes */ - $this->assertEquals($taxClassId, $customer->getExtensionAttributes()->getTestGroup()->getTaxClassId()); - $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroup()->getCode()); - } - public function testCreateWithLogicException() { $this->setExpectedException( diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml index 4b47d317898ab..6b79d122ab836 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml @@ -16,7 +16,7 @@ join_on_field="id" reference_field="id" > - qty + qty @@ -24,9 +24,9 @@ reference_field="product_id" join_on_field="id" > - comment - rating - date + comment + rating + date diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml index 68bc09b6590be..6f5910737fe47 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml @@ -16,8 +16,8 @@ join_on_field="entity_id" reference_field="product_id" > - qty - item_id + qty + item_id @@ -28,17 +28,18 @@ join_on_field="entity_id" reference_field="product_id" > - qty + qty + - customer_group_code + customer_group_code @@ -46,8 +47,39 @@ join_on_field="group_id" reference_field="customer_group_id" > - tax_class_id - customer_group_code + tax_class_id + code + + + + + + + + attribute_code + + + + + attribute_code + frontend_label + + + + + + + + attribute_code diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/RemoveTest.php b/dev/tests/integration/testsuite/Magento/Framework/Composer/RemoveTest.php index 17eaeb9c4eb94..bd9f8528bc1d7 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Composer/RemoveTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/RemoveTest.php @@ -11,7 +11,13 @@ class RemoveTest extends \PHPUnit_Framework_TestCase { public function testRemove() { - $composerApp = $this->getMock('Composer\Console\Application', [], [], '', false); + $composerApp = $this->getMock( + 'Composer\Console\Application', + ['setAutoExit', 'resetComposer', 'run'], + [], + '', + false + ); $directoryList = $this->getMock('Magento\Framework\App\Filesystem\DirectoryList', [], [], '', false); $directoryList->expects($this->once())->method('getRoot'); $directoryList->expects($this->once()) diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/Item/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/Item/RepositoryTest.php new file mode 100644 index 0000000000000..b7e78e977191f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/Item/RepositoryTest.php @@ -0,0 +1,40 @@ + 'firstname', + 'lastname' => 'lastname', + 'email' => 'admin@example.com' + ]; + + /** @var \Magento\Quote\Model\Quote\Item\Repository $quoteItemRepository */ + $quoteItemRepository = Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote\Item\Repository'); + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote'); + $quoteId = $quote->load('test01', 'reserved_order_id')->getId(); + + /** @var \Magento\Quote\Api\Data\CartItemInterface[] $quoteItems */ + $quoteItems = $quoteItemRepository->getList($quoteId); + /** @var \Magento\Quote\Api\Data\CartItemInterface $actualQuoteItem */ + $actualQuoteItem = array_pop($quoteItems); + $this->assertInstanceOf('Magento\Quote\Api\Data\CartItemInterface', $actualQuoteItem); + /** @var \Magento\User\Api\Data\UserInterface $testAttribute */ + $testAttribute = $actualQuoteItem->getExtensionAttributes()->getQuoteItemTestAttribute(); + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute->getFirstName()); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute->getLastName()); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute->getEmail()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteRepositoryTest.php new file mode 100644 index 0000000000000..0d7b1ea35f3b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteRepositoryTest.php @@ -0,0 +1,40 @@ + 'firstname', + 'lastname' => 'lastname', + 'email' => 'admin@example.com' + ]; + + /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\SearchCriteriaBuilder'); + + /** @var \Magento\Quote\Model\QuoteRepository $quoteRepository */ + $quoteRepository = Bootstrap::getObjectManager()->create('Magento\Quote\Model\QuoteRepository'); + $searchResult = $quoteRepository->getList($searchCriteriaBuilder->create()); + $items = $searchResult->getItems(); + /** @var \Magento\Quote\Api\Data\CartInterface $actualQuote */ + $actualQuote = array_pop($items); + $this->assertInstanceOf('Magento\Quote\Api\Data\CartInterface', $actualQuote); + $this->assertEquals('test01', $actualQuote->getReservedOrderId()); + /** @var \Magento\User\Api\Data\UserInterface $testAttribute */ + $testAttribute = $actualQuote->getExtensionAttributes()->getQuoteTestAttribute(); + $this->assertEquals($expectedExtensionAttributes['firstname'], $testAttribute->getFirstName()); + $this->assertEquals($expectedExtensionAttributes['lastname'], $testAttribute->getLastName()); + $this->assertEquals($expectedExtensionAttributes['email'], $testAttribute->getEmail()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Quote/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Quote/etc/extension_attributes.xml new file mode 100644 index 0000000000000..b71757a71adde --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/etc/extension_attributes.xml @@ -0,0 +1,34 @@ + + + + + + + firstname + lastname + email + + + + + + + firstname + lastname + email + + + + diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php index b9c4925d392fa..a38ef69ab30ed 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/TaxClass/RepositoryTest.php @@ -112,6 +112,29 @@ public function testGet() $this->assertEquals(TaxClassManagementInterface::TYPE_CUSTOMER, $data->getClassType()); } + /** + * @magentoDbIsolation enabled + */ + public function testGetList() + { + $taxClassName = 'Get Me'; + $taxClassDataObject = $this->taxClassFactory->create(); + $taxClassDataObject->setClassName($taxClassName) + ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER); + $taxClassId = $this->taxClassRepository->save($taxClassDataObject); + /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\SearchCriteriaBuilder'); + /** @var \Magento\Tax\Api\Data\TaxClassSearchResultsInterface */ + $searchResult = $this->taxClassRepository->getList($searchCriteriaBuilder->create()); + $items = $searchResult->getItems(); + /** @var \Magento\Tax\Api\Data\TaxClassInterface */ + $taxClass = array_pop($items); + $this->assertInstanceOf('Magento\Tax\Api\Data\TaxClassInterface', $taxClass); + $this->assertEquals($taxClassName, $taxClass->getClassName()); + $this->assertEquals($taxClassId, $taxClass->getClassId()); + $this->assertEquals(TaxClassManagementInterface::TYPE_CUSTOMER, $taxClass->getClassType()); + } + /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException * @expectedExceptionMessage No such entity with class_id = -9999 diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index 6ab58f1aa7740..ac58d760d24f1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -2123,6 +2123,16 @@ 'Magento\Customer\Controller\Account\LoginPost', 'Magento\Customer\Model\Account\Redirect::getRedirect', ], + [ + 'process', + 'Magento\Framework\Api\ExtensionAttributesFactory', + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessor::process' + ], + [ + 'extractExtensionAttributes', + 'Magento\Framework\Api\ExtensionAttributesFactory', + 'Magento\Framework\Api\ExtensionAttribute\JoinProcessor::extractExtensionAttributes' + ], ['isReviewOwner', 'Magento\Review\Block\Customer\View'], ['getRegistration', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getRegistration'], ['getCreateAccountUrl', 'Magento\Customer\Block\Form\Login', 'Magento\Customer\Block\Form\Login\Info::getCreateAccountUrl'], diff --git a/lib/internal/Magento/Framework/Api/DataObjectHelper.php b/lib/internal/Magento/Framework/Api/DataObjectHelper.php index 80e8587315bd5..2fb75d5f84161 100644 --- a/lib/internal/Magento/Framework/Api/DataObjectHelper.php +++ b/lib/internal/Magento/Framework/Api/DataObjectHelper.php @@ -35,6 +35,11 @@ class DataObjectHelper */ protected $extensionFactory; + /** + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $joinProcessor; + /** * @var MethodsMap */ @@ -45,6 +50,7 @@ class DataObjectHelper * @param \Magento\Framework\Reflection\DataObjectProcessor $objectProcessor * @param \Magento\Framework\Reflection\TypeProcessor $typeProcessor * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor * @param MethodsMap $methodsMapProcessor */ public function __construct( @@ -52,16 +58,20 @@ public function __construct( \Magento\Framework\Reflection\DataObjectProcessor $objectProcessor, \Magento\Framework\Reflection\TypeProcessor $typeProcessor, \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, + \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $joinProcessor, MethodsMap $methodsMapProcessor ) { $this->objectFactory = $objectFactory; $this->objectProcessor = $objectProcessor; $this->typeProcessor = $typeProcessor; $this->extensionFactory = $extensionFactory; + $this->joinProcessor = $joinProcessor; $this->methodsMapProcessor = $methodsMapProcessor; } /** + * Populate data object using data in array format. + * * @param mixed $dataObject * @param array $data * @param string $interfaceName @@ -70,7 +80,7 @@ public function __construct( public function populateWithArray($dataObject, array $data, $interfaceName) { if ($dataObject instanceof ExtensibleDataInterface) { - $data = $this->extensionFactory->extractExtensionAttributes(get_class($dataObject), $data); + $data = $this->joinProcessor->extractExtensionAttributes(get_class($dataObject), $data); } $this->_setDataValues($dataObject, $data, $interfaceName); return $this; diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php index f4e9df7cd643a..64fb32ecdf166 100644 --- a/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php @@ -9,13 +9,15 @@ class Converter implements \Magento\Framework\Config\ConverterInterface { const RESOURCE_PERMISSIONS = "resourceRefs"; const DATA_TYPE = "type"; + const JOIN_DIRECTIVE = "join"; const JOIN_REFERENCE_TABLE = "join_reference_table"; const JOIN_REFERENCE_FIELD = "join_reference_field"; - const JOIN_SELECT_FIELDS = "join_select_fields"; - const JOIN_SELECT_FIELD = "select_field"; - const JOIN_SELECT_FIELD_SETTER = "setter_name"; - const JOIN_JOIN_ON_FIELD= "join_join_on_field"; + const JOIN_ON_FIELD= "join_on_field"; + + const JOIN_FIELDS = "fields"; + const JOIN_FIELD = "field"; + const JOIN_FIELD_COLUMN = "column"; /** * Convert dom node tree to array @@ -83,16 +85,15 @@ private function processJoinElement($joinElement, $attribute) $joinAttributes = $joinElement->attributes; $join = [ self::JOIN_REFERENCE_TABLE => $joinAttributes->getNamedItem('reference_table')->nodeValue, - self::JOIN_JOIN_ON_FIELD => $joinAttributes->getNamedItem('join_on_field')->nodeValue, + self::JOIN_ON_FIELD => $joinAttributes->getNamedItem('join_on_field')->nodeValue, self::JOIN_REFERENCE_FIELD => $joinAttributes->getNamedItem('reference_field')->nodeValue, ]; - $selectElements = $attribute->getElementsByTagName('select_field'); - foreach ($selectElements as $selectElement) { - $selectField = $selectElement->nodeValue; - $setterName = $selectElement->getAttribute('setter_name'); - $join[self::JOIN_SELECT_FIELDS][] = [ - self::JOIN_SELECT_FIELD => $selectField, - self::JOIN_SELECT_FIELD_SETTER => $setterName + $fields = $attribute->getElementsByTagName('field'); + foreach ($fields as $field) { + $column = $field->getAttribute('column'); + $join[self::JOIN_FIELDS][] = [ + self::JOIN_FIELD => $field->nodeValue, + self::JOIN_FIELD_COLUMN => $column ]; } } diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php index 6457c79d1e145..27200762555b6 100644 --- a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php @@ -11,8 +11,13 @@ * * @codeCoverageIgnore */ -class JoinData +class JoinData implements JoinDataInterface { + /** + * @var string + */ + private $attributeCode; + /** * @var string */ @@ -39,9 +44,24 @@ class JoinData private $selectFields; /** - * Get reference table name. - * - * @return string + * {@inheritdoc} + */ + public function getAttributeCode() + { + return $this->attributeCode; + } + + /** + * {@inheritdoc} + */ + public function setAttributeCode($attributeCode) + { + $this->attributeCode = $attributeCode; + return $this; + } + + /** + * {@inheritdoc} */ public function getReferenceTable() { @@ -49,10 +69,7 @@ public function getReferenceTable() } /** - * Set reference table name. - * - * @param string $referenceTable - * @return $this + * {@inheritdoc} */ public function setReferenceTable($referenceTable) { @@ -61,9 +78,7 @@ public function setReferenceTable($referenceTable) } /** - * Get reference table alias. - * - * @return string + * {@inheritdoc} */ public function getReferenceTableAlias() { @@ -71,10 +86,7 @@ public function getReferenceTableAlias() } /** - * Set reference table alias. - * - * @param string $referenceTableAlias - * @return $this + * {@inheritdoc} */ public function setReferenceTableAlias($referenceTableAlias) { @@ -83,9 +95,7 @@ public function setReferenceTableAlias($referenceTableAlias) } /** - * Get reference field. - * - * @return string + * {@inheritdoc} */ public function getReferenceField() { @@ -93,10 +103,7 @@ public function getReferenceField() } /** - * Set reference field. - * - * @param string $referenceField - * @return $this + * {@inheritdoc} */ public function setReferenceField($referenceField) { @@ -105,9 +112,7 @@ public function setReferenceField($referenceField) } /** - * Get join field. - * - * @return string + * {@inheritdoc} */ public function getJoinField() { @@ -115,10 +120,7 @@ public function getJoinField() } /** - * Set join field. - * - * @param string $joinField - * @return $this + * {@inheritdoc} */ public function setJoinField($joinField) { @@ -127,9 +129,7 @@ public function setJoinField($joinField) } /** - * Get select fields. - * - * @return string[] + * {@inheritdoc} */ public function getSelectFields() { @@ -137,10 +137,7 @@ public function getSelectFields() } /** - * Set select field. - * - * @param string[] $selectFields - * @return $this + * {@inheritdoc} */ public function setSelectFields(array $selectFields) { diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataInterface.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataInterface.php new file mode 100644 index 0000000000000..91000c4e62e29 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataInterface.php @@ -0,0 +1,108 @@ +_objectManager = $objectManager; $this->_instanceName = $instanceName; diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessor.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessor.php new file mode 100644 index 0000000000000..dbe83d1d343a2 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessor.php @@ -0,0 +1,258 @@ +objectManager = $objectManager; + $this->config = $config; + $this->extensionAttributeJoinDataFactory = $extensionAttributeJoinDataFactory; + $this->typeProcessor = $typeProcessor; + $this->extensionAttributesFactory = $extensionAttributesFactory; + } + + /** + * {@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->extensionAttributeJoinDataFactory->create(); + $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->getSelectFieldsMap($attributeCode, $directive[Converter::JOIN_FIELDS]) + ); + $collection->joinExtensionAttribute($joinData, $this); + } + } + + /** + * Generate a list of select fields with mapping of client facing attribute names to field names used in SQL select. + * + * @param string $attributeCode + * @param array $selectFields + * @return array + */ + private function getSelectFieldsMap($attributeCode, $selectFields) + { + $referenceTableAlias = $this->getReferenceTableAlias($attributeCode); + $useFieldInAlias = (count($selectFields) > 1); + $selectFieldsAliases = []; + foreach ($selectFields as $selectField) { + $internalFieldName = $selectField[Converter::JOIN_FIELD_COLUMN] + ? $selectField[Converter::JOIN_FIELD_COLUMN] + : $selectField[Converter::JOIN_FIELD]; + $setterName = 'set' + . ucfirst(SimpleDataObjectConverter::snakeCaseToCamelCase($selectField[Converter::JOIN_FIELD])); + $selectFieldsAliases[] = [ + JoinDataInterface::SELECT_FIELD_EXTERNAL_ALIAS => $attributeCode + . ($useFieldInAlias ? '.' . $selectField[Converter::JOIN_FIELD] : ''), + JoinDataInterface::SELECT_FIELD_INTERNAL_ALIAS => $referenceTableAlias . '_' . $internalFieldName, + JoinDataInterface::SELECT_FIELD_WITH_DB_PREFIX => $referenceTableAlias . '.' . $internalFieldName, + JoinDataInterface::SELECT_FIELD_SETTER => $setterName + ]; + } + return $selectFieldsAliases; + } + + /** + * 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->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->config->get(); + 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; + } + } +} diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessorInterface.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessorInterface.php new file mode 100644 index 0000000000000..6b9c47b6d10fc --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinProcessorInterface.php @@ -0,0 +1,38 @@ +objectManager = $objectManager; - $this->config = $config; - $this->extensionAttributeJoinDataFactory = $extensionAttributeJoinDataFactory; - $this->typeProcessor = $typeProcessor; } /** @@ -110,155 +77,13 @@ public function create($extensibleClassName, $data = []) return $extensionFactory->create($data); } - /** - * Processes join instructions to add to the collection for a data interface. - * - * @param DbCollection $collection - * @param string $extensibleEntityClass - * @return void - */ - public function process(DbCollection $collection, $extensibleEntityClass) - { - $joinDirectives = $this->getJoinDirectivesForType($extensibleEntityClass); - foreach ($joinDirectives as $attributeCode => $directive) { - /** @var JoinData $joinData */ - $joinData = $this->extensionAttributeJoinDataFactory->create(); - $joinData->setReferenceTable($directive[Converter::JOIN_REFERENCE_TABLE]) - ->setReferenceTableAlias('extension_attribute_' . $attributeCode) - ->setReferenceField($directive[Converter::JOIN_REFERENCE_FIELD]) - ->setJoinField($directive[Converter::JOIN_JOIN_ON_FIELD]); - $selectFieldsMapper = function ($selectFieldData) { - return $selectFieldData[Converter::JOIN_SELECT_FIELD]; - }; - $joinData->setSelectFields(array_map($selectFieldsMapper, $directive[Converter::JOIN_SELECT_FIELDS])); - $collection->joinExtensionAttribute($joinData, [$this, 'extractExtensionAttributes']); - } - } - - /** - * Extract extension attributes into separate extension object. - * - * @param string $extensibleEntityClass - * @param array $data - * @return array - * @throws \LogicException - */ - 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->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 = $directive[Converter::JOIN_SELECT_FIELDS]; - foreach ($selectFields as $selectField) { - $selectFieldAlias = 'extension_attribute_' . $attributeCode - . '_' . $selectField[Converter::JOIN_SELECT_FIELD]; - if (isset($data[$selectFieldAlias])) { - 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->getExtensibleInterfaceName($extensibleEntityClass), - $attributeType - ) - ); - } elseif ($this->typeProcessor->isTypeSimple($attributeType)) { - $extensionData['data'][$attributeCode] = $data[$selectFieldAlias]; - unset($data[$selectFieldAlias]); - break; - } else { - if (!isset($extensionData['data'][$attributeCode])) { - $extensionData['data'][$attributeCode] = $this->objectManager->create($attributeType); - } - $setterName = $selectField[Converter::JOIN_SELECT_FIELD_SETTER] - ? $selectField[Converter::JOIN_SELECT_FIELD_SETTER] - :'set' . ucfirst( - SimpleDataObjectConverter::snakeCaseToCamelCase( - $selectField[Converter::JOIN_SELECT_FIELD] - ) - ); - $extensionData['data'][$attributeCode]->$setterName($data[$selectFieldAlias]); - unset($data[$selectFieldAlias]); - } - } - } - } - - /** - * 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->getExtensibleInterfaceName($extensibleEntityClass); - $extensibleInterfaceName = ltrim($extensibleInterfaceName, '\\'); - $config = $this->config->get(); - 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; - } - /** * Identify concrete extensible interface name based on the class name. * * @param string $extensibleClassName * @return string */ - private function getExtensibleInterfaceName($extensibleClassName) + public function getExtensibleInterfaceName($extensibleClassName) { $exceptionMessage = "Class '{$extensibleClassName}' must implement an interface, " . "which extends from '" . self::EXTENSIBLE_INTERFACE_NAME . "'"; @@ -289,20 +114,4 @@ private function getExtensibleInterfaceName($extensibleClassName) $this->classInterfaceMap[$extensibleClassName] = $notExtensibleClassFlag; throw new \LogicException($exceptionMessage); } - - /** - * Determine if the type is an actual extensible data interface. - * - * @param string $typeName - * @return bool - */ - private function isExtensibleAttributesImplemented($typeName) - { - try { - $this->getExtensibleInterfaceName($typeName); - return true; - } catch (\LogicException $e) { - return false; - } - } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php index 079ebbaec7832..484920c2a6740 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php @@ -44,14 +44,14 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase protected $attributeValueFactoryMock; /** - * @var \Magento\Framework\Api\ExtensionAttributesFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Reflection\MethodsMap|\PHPUnit_Framework_MockObject_MockObject */ - protected $extensionFactoryMock; + protected $methodsMapProcessor; /** - * @var \Magento\Framework\Reflection\MethodsMap|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessor|\PHPUnit_Framework_MockObject_MockObject */ - protected $methodsMapProcessor; + protected $joinProcessorMock; public function setUp() { @@ -69,22 +69,23 @@ public function setUp() $this->attributeValueFactoryMock = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory') ->disableOriginalConstructor() ->getMock(); - $this->extensionFactoryMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttributesFactory') + $this->joinProcessorMock = $this->getMockBuilder('\Magento\Framework\Api\ExtensionAttribute\JoinProcessor') ->setMethods(['extractExtensionAttributes']) ->disableOriginalConstructor() ->getMock(); - $this->extensionFactoryMock->expects($this->any()) + $this->joinProcessorMock->expects($this->any()) ->method('extractExtensionAttributes') ->willReturnArgument(1); $this->typeProcessor = $this->objectManager->getObject('Magento\Framework\Reflection\TypeProcessor'); + $this->dataObjectHelper = $this->objectManager->getObject( 'Magento\Framework\Api\DataObjectHelper', [ 'objectFactory' => $this->objectFactoryMock, 'typeProcessor' => $this->typeProcessor, 'objectProcessor' => $this->objectProcessorMock, - 'extensionFactory' => $this->extensionFactoryMock, 'methodsMapProcessor' => $this->methodsMapProcessor, + 'joinProcessor' => $this->joinProcessorMock ] ); } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php index 46b46456c828a..dca3d3af4382f 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php @@ -105,13 +105,13 @@ public function testConvertWithJoinDirectives() Converter::RESOURCE_PERMISSIONS => [], Converter::JOIN_DIRECTIVE => [ Converter::JOIN_REFERENCE_TABLE => "library_account", - Converter::JOIN_SELECT_FIELDS => [ + Converter::JOIN_FIELDS => [ [ - Converter::JOIN_SELECT_FIELD => "library_card_id", - Converter::JOIN_SELECT_FIELD_SETTER => "" + Converter::JOIN_FIELD => "library_card_id", + Converter::JOIN_FIELD_COLUMN => "" ] ], - Converter::JOIN_JOIN_ON_FIELD => "id", + Converter::JOIN_ON_FIELD => "id", Converter::JOIN_REFERENCE_FIELD => "customer_id", ], ], @@ -120,17 +120,17 @@ public function testConvertWithJoinDirectives() Converter::RESOURCE_PERMISSIONS => [], Converter::JOIN_DIRECTIVE => [ Converter::JOIN_REFERENCE_TABLE => "reviews", - Converter::JOIN_SELECT_FIELDS => [ + Converter::JOIN_FIELDS => [ [ - Converter::JOIN_SELECT_FIELD => "comment", - Converter::JOIN_SELECT_FIELD_SETTER => "" + Converter::JOIN_FIELD => "comment", + Converter::JOIN_FIELD_COLUMN => "" ], [ - Converter::JOIN_SELECT_FIELD => "rating", - Converter::JOIN_SELECT_FIELD_SETTER => "" + Converter::JOIN_FIELD => "rating", + Converter::JOIN_FIELD_COLUMN => "" ] ], - Converter::JOIN_JOIN_ON_FIELD => "customer_id", + Converter::JOIN_ON_FIELD => "customer_id", Converter::JOIN_REFERENCE_FIELD => "customer_id", ], ], diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php index c599760f5934f..9dab40a9ad26c 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php @@ -89,7 +89,7 @@ public function exemplarXmlDataProvider() reference_field="customer_id" join_on_field="id" > - library_card_id + library_card_id @@ -107,7 +107,7 @@ public function exemplarXmlDataProvider() reference_field="customer_id" join_on_field="id" > - library_card_id + library_card_id @@ -142,7 +142,7 @@ public function exemplarXmlDataProvider() "Element 'join': The attribute 'reference_table' is required but missing.", "Element 'join': The attribute 'join_on_field' is required but missing.", "Element 'join': The attribute 'reference_field' is required but missing.", - "Element 'join': Missing child element(s). Expected is ( select_field ).", + "Element 'join': Missing child element(s). Expected is ( field ).", ], ], ]; diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml index bdf8f3920bb19..baacb34779535 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml @@ -12,7 +12,7 @@ reference_field="customer_id" join_on_field="id" > - library_card_id + library_card_id @@ -20,8 +20,8 @@ reference_field="customer_id" join_on_field="customer_id" > - comment - rating + comment + rating diff --git a/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd b/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd index 6bccd9b1643b0..ef21443cec8b4 100644 --- a/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd +++ b/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd @@ -41,13 +41,13 @@ - + - + diff --git a/lib/internal/Magento/Framework/Composer/Test/Unit/DependencyCheckerTest.php b/lib/internal/Magento/Framework/Composer/Test/Unit/DependencyCheckerTest.php index 75b6239c776dd..46279d8fb1065 100644 --- a/lib/internal/Magento/Framework/Composer/Test/Unit/DependencyCheckerTest.php +++ b/lib/internal/Magento/Framework/Composer/Test/Unit/DependencyCheckerTest.php @@ -11,7 +11,13 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase { public function testCheckDependencies() { - $composerApp = $this->getMock('Composer\Console\Application', [], [], '', false); + $composerApp = $this->getMock( + 'Composer\Console\Application', + ['setAutoExit', 'resetComposer', 'run'], + [], + '', + false + ); $directoryList = $this->getMock('Magento\Framework\App\Filesystem\DirectoryList', [], [], '', false); $directoryList->expects($this->exactly(2))->method('getRoot'); $composerApp->expects($this->once())->method('setAutoExit')->with(false); @@ -44,7 +50,13 @@ function ($input, $buffer) { public function testCheckDependenciesExcludeSelf() { - $composerApp = $this->getMock('Composer\Console\Application', [], [], '', false); + $composerApp = $this->getMock( + 'Composer\Console\Application', + ['setAutoExit', 'resetComposer', 'run'], + [], + '', + false + ); $directoryList = $this->getMock('Magento\Framework\App\Filesystem\DirectoryList', [], [], '', false); $directoryList->expects($this->exactly(3))->method('getRoot'); $composerApp->expects($this->once())->method('setAutoExit')->with(false); diff --git a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index e745a916a8092..3573fdb87f541 100755 --- a/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -8,7 +8,8 @@ use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; -use Magento\Framework\Api\ExtensionAttribute\JoinData; +use Magento\Framework\Api\ExtensionAttribute\JoinDataInterface; +use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; use Psr\Log\LoggerInterface as Logger; /** @@ -87,11 +88,11 @@ abstract class AbstractDb extends \Magento\Framework\Data\Collection private $_fetchStrategy; /** - * Flag which determines if extension attributes were joined before the collection was loaded. + * Join processor is set only if extension attributes were joined before the collection was loaded. * - * @var callable|null + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface|null */ - protected $extensionAttributesExtractorCallback; + protected $extensionAttributesJoinProcessor; /** * @param EntityFactoryInterface $entityFactory @@ -743,7 +744,7 @@ protected function _reset() $this->_setIsLoaded(false); $this->_items = []; $this->_data = null; - $this->extensionAttributesExtractorCallback = null; + $this->extensionAttributesJoinProcessor = null; return $this; } @@ -756,11 +757,11 @@ protected function _reset() protected function _fetchAll(\Zend_Db_Select $select) { $data = $this->_fetchStrategy->fetchAll($select, $this->_bindParams); - if ($this->extensionAttributesExtractorCallback && is_callable($this->extensionAttributesExtractorCallback)) { + if ($this->extensionAttributesJoinProcessor) { foreach ($data as $key => $dataItem) { - $data[$key] = call_user_func_array( - $this->extensionAttributesExtractorCallback, - [$this->_itemObjectClass, $dataItem] + $data[$key] = $this->extensionAttributesJoinProcessor->extractExtensionAttributes( + $this->_itemObjectClass, + $dataItem ); } } @@ -812,32 +813,46 @@ protected function _initSelect() /** * Join extension attribute. * - * @param \Magento\Framework\Api\ExtensionAttribute\JoinData $join - * @param callable $extensionAttributesExtractorCallback + * @param JoinDataInterface $join + * @param JoinProcessorInterface $extensionAttributesJoinProcessor * @return $this */ - public function joinExtensionAttribute($join, $extensionAttributesExtractorCallback) - { + public function joinExtensionAttribute( + JoinDataInterface $join, + JoinProcessorInterface $extensionAttributesJoinProcessor + ) { $selectFrom = $this->getSelect()->getPart(\Zend_Db_Select::FROM); $joinRequired = !isset($selectFrom[$join->getReferenceTableAlias()]); if ($joinRequired) { + $joinOn = $this->getMainTableAlias() . '.' . $join->getJoinField() + . ' = ' . $join->getReferenceTableAlias() . '.' . $join->getReferenceField(); $this->getSelect()->joinLeft( [$join->getReferenceTableAlias() => $this->getResource()->getTable($join->getReferenceTable())], - $this->getMainTableAlias() . '.' . $join->getJoinField() - . ' = ' . $join->getReferenceTableAlias() . '.' . $join->getReferenceField(), + $joinOn, [] ); } $columns = []; foreach ($join->getSelectFields() as $selectField) { - $fieldAlias = $join->getReferenceTableAlias() . '_' . $selectField; - $columns[$fieldAlias] = $join->getReferenceTableAlias() . '.' . $selectField; + $fieldWIthDbPrefix = $selectField[JoinDataInterface::SELECT_FIELD_WITH_DB_PREFIX]; + $columns[$selectField[JoinDataInterface::SELECT_FIELD_INTERNAL_ALIAS]] = $fieldWIthDbPrefix; + $this->addFilterToMap($selectField[JoinDataInterface::SELECT_FIELD_EXTERNAL_ALIAS], $fieldWIthDbPrefix); } $this->getSelect()->columns($columns); - $this->extensionAttributesExtractorCallback = $extensionAttributesExtractorCallback; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; return $this; } + /** + * Get collection item object class name. + * + * @return string + */ + public function getItemObjectClass() + { + return $this->_itemObjectClass; + } + /** * Identify main table alias or its name if alias is not defined. * diff --git a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php index 22857fcf9bcfa..496ba2e8d173a 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php +++ b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php @@ -73,6 +73,19 @@ protected function _getClassProperties() ], ] ], + [ + 'name' => 'extensionAttributesJoinProcessor', + 'visibility' => 'protected', + 'docblock' => [ + 'shortDescription' => 'Extension attributes join processor.', + 'tags' => [ + [ + 'name' => 'var', + 'description' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + ], + ], + ] + ], ]; return $properties; } @@ -138,13 +151,18 @@ protected function _getDefaultConstructorDefinition() 'name' => $this->_getSourceCollectionFactoryPropertyName(), 'type' => $this->_getCollectionFactoryClassName(), ], + [ + 'name' => 'extensionAttributesJoinProcessor', + 'type' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface', + ], ], 'body' => "\$this->" . $this->_getSourcePersistorPropertyName() . " = \$" . $this->_getSourcePersistorPropertyName() . ";\n" . "\$this->" . $this->_getSourceCollectionFactoryPropertyName() - . " = \$" . $this->_getSourceCollectionFactoryPropertyName() . ";" + . " = \$" . $this->_getSourceCollectionFactoryPropertyName() . ";\n" + . "\$this->extensionAttributesJoinProcessor = \$extensionAttributesJoinProcessor;" , 'docblock' => [ 'shortDescription' => ucfirst(static::ENTITY_TYPE) . ' constructor', @@ -158,6 +176,11 @@ protected function _getDefaultConstructorDefinition() 'description' => $this->_getCollectionFactoryClassName() . " \$" . $this->_getSourceCollectionFactoryPropertyName() ], + [ + 'name' => 'param', + 'description' => '\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface' + . " \$extensionAttributesJoinProcessor" + ], ], ] ]; @@ -362,6 +385,10 @@ protected function _getDeleteMethod() 'name' => 'param', 'description' => $this->getSourceClassName() . ' $entity', ], + [ + 'name' => 'return', + 'description' => 'bool', + ], ], ] ]; @@ -393,6 +420,10 @@ protected function _getDeleteByIdMethod() 'name' => 'param', 'description' => 'int $id', ], + [ + 'name' => 'return', + 'description' => 'bool', + ], ], ] ]; @@ -428,14 +459,15 @@ protected function _getRemoveMethod() } /** - * Returns find() method + * Returns getList() method * * @return string */ protected function _getGetListMethod() { $body = "\$collection = \$this->" . $this->_getSourceCollectionFactoryPropertyName() . "->create();\n" - . "foreach(\$criteria->getFilterGroups() as \$filterGroup) {\n" + . "\$this->extensionAttributesJoinProcessor->process(\$collection);\n" + . "foreach (\$criteria->getFilterGroups() as \$filterGroup) {\n" . " foreach (\$filterGroup->getFilters() as \$filter) {\n" . " \$condition = \$filter->getConditionType() ? \$filter->getConditionType() : 'eq';\n" . " \$collection->addFieldToFilter(\$filter->getField(), [\$condition => \$filter->getValue()]);\n" diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php index 33ff3368e02de..a2744ca17becd 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php @@ -58,8 +58,12 @@ public function testGenerate() ->with('\Magento\Framework\ObjectManager\Code\Generator\SampleRepository') ->willReturn('SampleRepository.php'); + $repositoryCode = file_get_contents(__DIR__ . '/_files/SampleRepository.txt'); + $this->ioObjectMock->expects($this->once())->method('writeResultFile') + ->with('SampleRepository.php', $repositoryCode); + $model->expects($this->once())->method('_validateData')->willReturn(true); - $this->assertEquals('SampleRepository.php', $model->generate()); + $this->assertEquals('SampleRepository.php', $model->generate(), "Generated repository is invalid."); } /** diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt index 4b1ee7b010837..d135ca64dd1fc 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt @@ -1,7 +1,7 @@ namespace Magento\Framework\ObjectManager\Code\Generator; /** - * Repository class for + * Repository class for @see * \Magento\Framework\ObjectManager\Code\Generator\SampleInterface */ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generator\SampleRepositoryInterface @@ -22,7 +22,7 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato protected $sampleInterfaceSearchResultFactory = null; /** - * Magento\Framework\ObjectManager\Code\Generator\SampleInterface[] + * \Magento\Framework\ObjectManager\Code\Generator\SampleInterface[] * * @var array */ @@ -30,6 +30,13 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato ); + /** + * Extension attributes join processor. + * + * @var \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + */ + protected $extensionAttributesJoinProcessor = null; + /** * Repository constructor * @@ -38,11 +45,14 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato * @param * \Magento\Framework\ObjectManager\Code\Generator\SampleSearchResultInterfaceFactory * $sampleInterfaceSearchResultFactory + * @param \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface + * $extensionAttributesJoinProcessor */ - public function __construct(\Magento\Framework\ObjectManager\Code\Generator\SampleInterfacePersistor $sampleInterfacePersistor, \Magento\Framework\ObjectManager\Code\Generator\SampleSearchResultInterfaceFactory $sampleInterfaceSearchResultFactory) + public function __construct(\Magento\Framework\ObjectManager\Code\Generator\SampleInterfacePersistor $sampleInterfacePersistor, \Magento\Framework\ObjectManager\Code\Generator\SampleSearchResultInterfaceFactory $sampleInterfaceSearchResultFactory, \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface $extensionAttributesJoinProcessor) { $this->sampleInterfacePersistor = $sampleInterfacePersistor; $this->sampleInterfaceSearchResultFactory = $sampleInterfaceSearchResultFactory; + $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; } /** @@ -53,13 +63,13 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function get($id, $arguments = array()) + public function get($id) { if (!$id) { throw new \Magento\Framework\Exception\InputException('ID required'); } if (!isset($this->registry[$id])) { - $entity = $this->sampleInterfacePersistor->loadEntity($id, $arguments); + $entity = $this->sampleInterfacePersistor->loadEntity($id); if (!$entity->getId()) { throw new \Magento\Framework\Exception\NoSuchEntityException('Requested entity doesn\'t exist'); } @@ -94,13 +104,13 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato * Find entities by criteria * * @param \Magento\Framework\Api\SearchCriteria $criteria - * @param array $arguments - * @return \Magento\Framework\ObjectManager\Code\Generator\Sample[] + * @return \Magento\Framework\ObjectManager\Code\Generator\SampleInterface[] */ - public function find(\Magento\Framework\Api\SearchCriteria $criteria, $arguments = array()) + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) { $collection = $this->sampleInterfaceSearchResultFactory->create(); - foreach($criteria->getFilterGroups() as $filterGroup) { + $this->extensionAttributesJoinProcessor->process($collection); + foreach ($criteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); @@ -125,11 +135,25 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato * Register entity to delete * * @param \Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity + * @return bool + */ + public function delete(\Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity) + { + $this->sampleInterfacePersistor->registerDeleted($entity); + return $this->sampleInterfacePersistor->doPersistEntity($entity); + } + + /** + * Delete entity by Id + * + * @param int $id + * @return bool */ - public function delete(\Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity, $arguments = array()) + public function deleteById($id) { + $entity = $this->get($id); $this->sampleInterfacePersistor->registerDeleted($entity); - $this->sampleInterfacePersistor->save($entity); + return $this->sampleInterfacePersistor->doPersistEntity($entity); } /** @@ -147,9 +171,11 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato * Perform persist operations for one entity * * @param \Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity + * @return \Magento\Framework\ObjectManager\Code\Generator\SampleInterface */ - public function save(\Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity, $arguments = array()) + public function save(\Magento\Framework\ObjectManager\Code\Generator\SampleInterface $entity) { - return $this->sampleInterfacePersistor->doPersistEntity($entity); + $this->sampleInterfacePersistor->doPersistEntity($entity); + return $entity; } }