diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index cfd47ea146697a6e2dffaf2c1342bc7374c08a33..eb97aa454f6e8c63583bfd9cd4b6fec32b6d67e1 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -72,6 +72,6 @@ <plugin name="catalogInventoryAfterLoad" type="\Magento\CatalogInventory\Model\Plugin\AfterProductLoad"/> </type> <type name="Magento\Catalog\Api\ProductRepositoryInterface"> - <plugin name="catalogInventoryAroundSave" type="\Magento\CatalogInventory\Model\Plugin\AroundProductRepositorySave"/> + <plugin name="catalogInventoryAroundSave" sortOrder="20" type="Magento\CatalogInventory\Model\Plugin\AroundProductRepositorySave"/> </type> </config> diff --git a/app/code/Magento/CatalogSearch/Model/Search/ReaderPlugin.php b/app/code/Magento/CatalogSearch/Model/Search/ReaderPlugin.php index 21dd2f62495b2b7bf9b41c80beeed612a07ae47b..307b34c008fb238e6e79b87ec21a6a3a4099d431 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/ReaderPlugin.php +++ b/app/code/Magento/CatalogSearch/Model/Search/ReaderPlugin.php @@ -24,18 +24,17 @@ class ReaderPlugin /** * Merge reader's value with generated * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @param \Magento\Framework\Config\ReaderInterface $subject - * @param \Closure $proceed - * @param string $scope + * @param array $result + * @param string|null $scope * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundRead( + public function afterRead( \Magento\Framework\Config\ReaderInterface $subject, - \Closure $proceed, + array $result, $scope = null ) { - $result = $proceed($scope); $result = array_merge_recursive($result, $this->requestGenerator->generate()); return $result; } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/ReaderPluginTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/ReaderPluginTest.php index 69644eee90222f09e7a3d9e74ee23292c4801070..afae3ccb4f4b595ed04141927b1e85279689988b 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/ReaderPluginTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/ReaderPluginTest.php @@ -29,18 +29,18 @@ class ReaderPluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundRead() + public function testAfterRead() { + $readerConfig = ['test' => 'b', 'd' => 'e']; $this->requestGenerator->expects($this->once()) ->method('generate') ->will($this->returnValue(['test' => 'a'])); - $result = $this->object->aroundRead( + $result = $this->object->afterRead( $this->getMockBuilder(\Magento\Framework\Config\ReaderInterface::class) ->disableOriginalConstructor()->getMock(), - function () { - return ['test' => 'b', 'd' => 'e']; - } + $readerConfig, + null ); $this->assertEquals(['test' => ['b', 'a'], 'd' => 'e'], $result); diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php index 1477a10655472d3e88543e0567dd2d6733af3d3c..4175a7ddb4ef9d9fd0f05d92d0d3d5bd53cfa374 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php @@ -14,6 +14,11 @@ class Move /** @var CategoryUrlPathGenerator */ protected $categoryUrlPathGenerator; + /** + * @var ChildrenCategoriesProvider + */ + private $childrenCategoriesProvider; + /** * @param CategoryUrlPathGenerator $categoryUrlPathGenerator * @param ChildrenCategoriesProvider $childrenCategoriesProvider @@ -27,22 +32,23 @@ class Move } /** + * Perform url updating for children categories + * * @param \Magento\Catalog\Model\ResourceModel\Category $subject - * @param callable $proceed + * @param \Magento\Catalog\Model\ResourceModel\Category $result * @param Category $category * @param Category $newParent * @param null|int $afterCategoryId - * @return callable + * @return \Magento\Catalog\Model\ResourceModel\Category * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundChangeParent( + public function afterChangeParent( \Magento\Catalog\Model\ResourceModel\Category $subject, - \Closure $proceed, - $category, - $newParent, + \Magento\Catalog\Model\ResourceModel\Category $result, + Category $category, + Category $newParent, $afterCategoryId ) { - $result = $proceed($category, $newParent, $afterCategoryId); $category->setUrlPath($this->categoryUrlPathGenerator->getUrlPath($category)); $category->getResource()->saveAttribute($category, 'url_path'); $this->updateUrlPathForChildren($category); diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Storage.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Storage.php index 768660e56daf5c25b6f8953bb2477aab97659d74..740c32762690e72eb588d7387f2a71467a15e2f7 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Storage.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Storage.php @@ -33,14 +33,13 @@ class Storage /** * @param \Magento\UrlRewrite\Model\StorageInterface $object - * @param callable $proceed - * @param array $urls + * @param null $result + * @param \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] $urls * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundReplace(StorageInterface $object, \Closure $proceed, array $urls) + public function afterReplace(StorageInterface $object, $result, array $urls) { - $proceed($urls); $toSave = []; foreach ($this->filterUrls($urls) as $record) { $metadata = $record->getMetadata(); diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php index f3c86bad49936bc044d05a9fe5b6ca07ba293dad..1b18385d4a6fd8e9da1e693cf181fad8adfbd328 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php @@ -63,19 +63,19 @@ class Group } /** - * @param \Magento\Store\Model\ResourceModel\Group $object - * @param callable $proceed + * Perform updating url for categories and products assigned to the group + * + * @param \Magento\Store\Model\ResourceModel\Group $subject + * @param \Magento\Store\Model\ResourceModel\Group $result * @param AbstractModel $group * @return \Magento\Store\Model\ResourceModel\Group * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundSave( - \Magento\Store\Model\ResourceModel\Group $object, - \Closure $proceed, + public function afterSave( + \Magento\Store\Model\ResourceModel\Group $subject, + \Magento\Store\Model\ResourceModel\Group $result, AbstractModel $group ) { - $originGroup = $group; - $result = $proceed($originGroup); if (!$group->isObjectNew() && ($group->dataHasChangedFor('website_id') || $group->dataHasChangedFor('root_category_id')) diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php index ade02f8446921f74e34cb8bd3b58bc836575fe54..ea28b20f3f8f6d58211377bd9b16034d8f04a23c 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php @@ -5,7 +5,6 @@ */ namespace Magento\CatalogUrlRewrite\Model\Category\Plugin\Store; -use Magento\Catalog\Model\Category; use Magento\Catalog\Model\CategoryFactory; use Magento\Catalog\Model\ProductFactory; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; @@ -53,19 +52,19 @@ class View } /** - * @param \Magento\Store\Model\ResourceModel\Store $object - * @param callable $proceed + * Perform updating url for categories and products assigned to the store view + * + * @param \Magento\Store\Model\ResourceModel\Store $subject + * @param \Magento\Store\Model\ResourceModel\Store $result * @param AbstractModel $store * @return \Magento\Store\Model\ResourceModel\Store * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundSave( - \Magento\Store\Model\ResourceModel\Store $object, - \Closure $proceed, + public function afterSave( + \Magento\Store\Model\ResourceModel\Store $subject, + \Magento\Store\Model\ResourceModel\Store $result, AbstractModel $store ) { - $originStore = $store; - $result = $proceed($originStore); if ($store->isObjectNew() || $store->dataHasChangedFor('group_id')) { if (!$store->isObjectNew()) { $this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $store->getId()]); @@ -102,6 +101,7 @@ class View ->addCategoryIds() ->addAttributeToSelect(['name', 'url_path', 'url_key', 'visibility']) ->addWebsiteFilter($websiteIds); + foreach ($collection as $product) { $product->setStoreId($storeId); /** @var \Magento\Catalog\Model\Product $product */ @@ -110,6 +110,7 @@ class View $this->productUrlRewriteGenerator->generate($product) ); } + return $urls; } @@ -130,23 +131,26 @@ class View $this->categoryUrlRewriteGenerator->generate($category) ); } + return $urls; } /** - * @param \Magento\Store\Model\ResourceModel\Store $object - * @param callable $proceed + * Delete unused url rewrites + * + * @param \Magento\Store\Model\ResourceModel\Store $subject + * @param \Magento\Store\Model\ResourceModel\Store $result * @param AbstractModel $store - * @return mixed + * @return \Magento\Store\Model\ResourceModel\Store * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDelete( - \Magento\Store\Model\ResourceModel\Store $object, - \Closure $proceed, + public function afterDelete( + \Magento\Store\Model\ResourceModel\Store $subject, + \Magento\Store\Model\ResourceModel\Store $result, AbstractModel $store ) { - $result = $proceed($store); $this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $store->getId()]); + return $result; } } diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7fe042232b82d85146365136f54b02f1a1842818 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin\Category; + +use Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Move as CategoryMovePlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; +use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider; +use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; +use Magento\Catalog\Model\Category; + +class MoveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ChildrenCategoriesProvider|\PHPUnit_Framework_MockObject_MockObject + */ + private $childrenCategoriesProviderMock; + + /** + * @var CategoryUrlPathGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryUrlPathGeneratorMock; + + /** + * @var CategoryResourceModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; + + /** + * @var Category|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryMock; + + /** + * @var CategoryMovePlugin + */ + private $plugin; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->categoryUrlPathGeneratorMock = $this->getMockBuilder(CategoryUrlPathGenerator::class) + ->disableOriginalConstructor() + ->setMethods(['getUrlPath']) + ->getMock(); + $this->childrenCategoriesProviderMock = $this->getMockBuilder(ChildrenCategoriesProvider::class) + ->disableOriginalConstructor() + ->setMethods(['getChildren']) + ->getMock(); + $this->subjectMock = $this->getMockBuilder(CategoryResourceModel::class) + ->disableOriginalConstructor() + ->getMock(); + $this->categoryMock = $this->getMockBuilder(Category::class) + ->disableOriginalConstructor() + ->setMethods(['getResource', 'setUrlPath']) + ->getMock(); + $this->plugin = $this->objectManager->getObject( + CategoryMovePlugin::class, + [ + 'categoryUrlPathGenerator' => $this->categoryUrlPathGeneratorMock, + 'childrenCategoriesProvider' => $this->childrenCategoriesProviderMock + ] + ); + } + + public function testAfterChangeParent() + { + $urlPath = 'test/path'; + $this->categoryMock->expects($this->once()) + ->method('getResource') + ->willReturn($this->subjectMock); + $this->childrenCategoriesProviderMock->expects($this->once()) + ->method('getChildren') + ->with($this->categoryMock, true) + ->willReturn([]); + $this->categoryUrlPathGeneratorMock->expects($this->once()) + ->method('getUrlPath') + ->with($this->categoryMock) + ->willReturn($urlPath); + $this->categoryMock->expects($this->once()) + ->method('getResource') + ->willReturn($this->subjectMock); + $this->categoryMock->expects($this->once()) + ->method('setUrlPath') + ->with($urlPath); + $this->assertSame( + $this->subjectMock, + $this->plugin->afterChangeParent( + $this->subjectMock, + $this->subjectMock, + $this->categoryMock, + $this->categoryMock, + null + ) + ); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/RemoveTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/RemoveTest.php new file mode 100644 index 0000000000000000000000000000000000000000..520975871bf4b657a408b399c144b49353998959 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/RemoveTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin\Category; + +use Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Remove as CategoryRemovePlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider; +use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; +use Magento\Catalog\Model\Category; + +class RemoveTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $urlPersistMock; + + /** + * @var ChildrenCategoriesProvider|\PHPUnit_Framework_MockObject_MockObject + */ + private $childrenCategoriesProviderMock; + + /** + * @var CategoryResourceModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; + + /** + * @var Category|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectMock; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->urlPersistMock = $this->getMockBuilder(UrlPersistInterface::class) + ->getMockForAbstractClass(); + $this->childrenCategoriesProviderMock = $this->getMockBuilder(ChildrenCategoriesProvider::class) + ->getMock(); + $this->subjectMock = $this->getMockBuilder(CategoryResourceModel::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectMock = $this->getMockBuilder(Category::class) + ->disableOriginalConstructor() + ->getMock(); + } + + public function testAroundDelete() + { + $closureSubject = $this->subjectMock; + $proceed = function () use ($closureSubject) { + return $closureSubject; + }; + $plugin = $this->objectManager->getObject( + CategoryRemovePlugin::class, + [ + 'urlPersist' => $this->urlPersistMock, + 'childrenCategoriesProvider' => $this->childrenCategoriesProviderMock + ] + ); + $this->childrenCategoriesProviderMock->expects($this->once()) + ->method('getChildrenIds') + ->with($this->objectMock, true) + ->willReturn([]); + $this->objectMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->urlPersistMock->expects($this->exactly(2)) + ->method('deleteByData'); + $this->assertSame( + $this->subjectMock, + $plugin->aroundDelete($this->subjectMock, $proceed, $this->objectMock) + ); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/StorageTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/StorageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..21ab961dcbdcb3b1c5eb08d5d59bd176b87c321a --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/StorageTest.php @@ -0,0 +1,106 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\CatalogUrlRewrite\Model\Category\ProductFactory; +use Magento\UrlRewrite\Model\StorageInterface; +use Magento\CatalogUrlRewrite\Model\Category\Plugin\Storage as CategoryStoragePlugin; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\UrlRewrite\Model\UrlFinderInterface; +use Magento\CatalogUrlRewrite\Model\Category\Product; +use Magento\CatalogUrlRewrite\Model\ResourceModel\Category\Product as ProductResourceModel; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class StorageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var CategoryStoragePlugin + */ + private $plugin; + + /** + * @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $productFactory; + + /** + * @var UrlFinderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $urlFinder; + + /** + * @var StorageInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storage; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $product; + + /** + * @var ProductResourceModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $productResourceModel; + + /** + * @var UrlRewrite|\PHPUnit_Framework_MockObject_MockObject + */ + private $urlRewrite; + + protected function setUp() + { + $this->productFactory = $this->getMockBuilder(ProductFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->storage = $this->getMockBuilder(StorageInterface::class) + ->getMockForAbstractClass(); + $this->urlFinder = $this->getMockBuilder(UrlFinderInterface::class) + ->getMockForAbstractClass(); + $this->product = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productResourceModel = $this->getMockBuilder(ProductResourceModel::class) + ->disableOriginalConstructor() + ->getMock(); + $this->urlRewrite = $this->getMockBuilder(UrlRewrite::class) + ->disableOriginalConstructor() + ->setMethods(['getMetadata', 'getEntityType', 'getIsAutogenerated', 'getUrlRewriteId', 'getEntityId']) + ->getMock(); + + $this->plugin = (new ObjectManager($this))->getObject( + CategoryStoragePlugin::class, + [ + 'productFactory' => $this->productFactory, + 'urlFinder' => $this->urlFinder + ] + ); + } + + public function testAfterReplace() + { + $this->urlRewrite->expects(static::any())->method('getMetadata')->willReturn(['category_id' => '5']); + $this->urlRewrite->expects(static::once())->method('getEntityTYpe')->willReturn('product'); + $this->urlRewrite->expects(static::once())->method('getIsAutogenerated')->willReturn(1); + $this->urlRewrite->expects(static::once())->method('getUrlRewriteId')->willReturn('4'); + $this->urlRewrite->expects(static::once())->method('getEntityId')->willReturn('2'); + $this->urlRewrite->setData('request_path', 'test'); + $this->urlRewrite->setData('store_id', '1'); + $productUrls = ['targetPath' => $this->urlRewrite]; + + $this->urlFinder->expects(static::once())->method('findAllByData')->willReturn([$this->urlRewrite]); + + $this->productFactory->expects(static::once())->method('create')->willReturn($this->product); + $this->product->expects(static::once())->method('getResource')->willReturn($this->productResourceModel); + $this->productResourceModel->expects(static::once())->method('saveMultiple')->willReturnSelf(); + + $this->plugin->afterReplace($this->storage, null, $productUrls); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dc69597ef6db9ccd1299c6e7887239c890bb05e5 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php @@ -0,0 +1,178 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin\Store; + +use Magento\CatalogUrlRewrite\Model\Category\Plugin\Store\Group as GroupPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Model\AbstractModel; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Model\ResourceModel\Group; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\CategoryFactory; +use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; +use Magento\Catalog\Model\Product as Product; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\Catalog\Model\ProductFactory; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class GroupTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var GroupPlugin + */ + private $plugin; + + /** + * @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $abstractModelMock; + + /** + * @var Group|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; + + /** + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManagerMock; + + /** + * @var CategoryFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryFactoryMock; + + /** + * @var Category|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryMock; + + /** + * @var ProductCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $productCollectionMock; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $productMock; + + /** + * @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $productFactoryMock; + + /** + * @var ProductUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + private $productUrlRewriteGeneratorMock; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->abstractModelMock = $this->getMockBuilder(AbstractModel::class) + ->disableOriginalConstructor() + ->setMethods(['isObjectNew', 'dataHasChangedFor', 'getStoreIds']) + ->getMockForAbstractClass(); + $this->abstractModelMock->expects($this->any()) + ->method('getStoreIds') + ->willReturn([]); + $this->subjectMock = $this->getMockBuilder(Group::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['reinitStores']) + ->getMockForAbstractClass(); + $this->categoryMock = $this->getMockBuilder(Category::class) + ->disableOriginalConstructor() + ->setMethods(['getCategories']) + ->getMock(); + $this->categoryFactoryMock = $this->getMockBuilder(CategoryFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->productFactoryMock = $this->getMockBuilder(ProductFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->productCollectionMock = $this->getMockBuilder(ProductCollection::class) + ->disableOriginalConstructor() + ->setMethods(['addCategoryIds', 'addAttributeToSelect', 'addWebsiteFilter', 'getIterator']) + ->getMock(); + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getCollection']) + ->getMock(); + $this->productUrlRewriteGeneratorMock = $this->getMockBuilder(ProductUrlRewriteGenerator::class) + ->disableOriginalConstructor() + ->setMethods(['generate']) + ->getMock(); + $this->plugin = $this->objectManager->getObject( + GroupPlugin::class, + [ + 'storeManager' => $this->storeManagerMock, + 'categoryFactory' => $this->categoryFactoryMock, + 'productFactory' => $this->productFactoryMock, + 'productUrlRewriteGenerator' => $this->productUrlRewriteGeneratorMock + ] + ); + } + + public function testAfterSave() + { + $this->abstractModelMock->expects($this->once()) + ->method('isObjectNew') + ->willReturn(false); + $this->abstractModelMock->expects($this->once()) + ->method('dataHasChangedFor') + ->with('website_id') + ->willReturn(true); + $this->storeManagerMock->expects($this->once()) + ->method('reinitStores'); + $this->categoryMock->expects($this->once()) + ->method('getCategories') + ->willReturn([]); + $this->categoryFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->categoryMock); + $this->productFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getCollection') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addCategoryIds') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addAttributeToSelect') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addWebsiteFilter') + ->willReturn($this->productCollectionMock); + $iterator = new \ArrayIterator([$this->productMock]); + $this->productCollectionMock->expects($this->once()) + ->method('getIterator') + ->willReturn($iterator); + $this->productUrlRewriteGeneratorMock->expects($this->once()) + ->method('generate') + ->with($this->productMock) + ->willReturn([]); + + $this->assertSame( + $this->subjectMock, + $this->plugin->afterSave($this->subjectMock, $this->subjectMock, $this->abstractModelMock) + ); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d30c2dde6e033fd3f3d10300ed59aa7a6c249916 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php @@ -0,0 +1,188 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Category\Plugin\Store; + +use Magento\CatalogUrlRewrite\Model\Category\Plugin\Store\View as StoreViewPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Model\AbstractModel; +use Magento\Store\Model\ResourceModel\Store; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\Catalog\Model\CategoryFactory; +use Magento\Catalog\Model\ProductFactory; +use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; +use Magento\Catalog\Model\Product; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ViewTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var StoreViewPlugin + */ + private $plugin; + + /** + * @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $abstractModelMock; + + /** + * @var Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; + + /** + * @var UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $urlPersistMock; + + /** + * @var CategoryFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryFactoryMock; + + /** + * @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $productFactoryMock; + + /** + * @var CategoryUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryUrlRewriteGeneratorMock; + + /** + * @var ProductUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + private $productUrlRewriteGeneratorMock; + + /** + * @var Category|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryMock; + + /** + * @var ProductCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $productCollectionMock; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $productMock; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->abstractModelMock = $this->getMockBuilder(AbstractModel::class) + ->disableOriginalConstructor() + ->setMethods(['isObjectNew']) + ->getMockForAbstractClass(); + $this->subjectMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->urlPersistMock = $this->getMockBuilder(UrlPersistInterface::class) + ->setMethods(['deleteByData']) + ->getMockForAbstractClass(); + $this->categoryMock = $this->getMockBuilder(Category::class) + ->disableOriginalConstructor() + ->setMethods(['getCategories']) + ->getMock(); + $this->categoryFactoryMock = $this->getMockBuilder(CategoryFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->productFactoryMock = $this->getMockBuilder(ProductFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->categoryUrlRewriteGeneratorMock = $this->getMockBuilder(CategoryUrlRewriteGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productUrlRewriteGeneratorMock = $this->getMockBuilder(ProductUrlRewriteGenerator::class) + ->disableOriginalConstructor() + ->setMethods(['generate']) + ->getMock(); + $this->productCollectionMock = $this->getMockBuilder(ProductCollection::class) + ->disableOriginalConstructor() + ->setMethods(['addCategoryIds', 'addAttributeToSelect', 'addWebsiteFilter', 'getIterator']) + ->getMock(); + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getCollection']) + ->getMock(); + $this->plugin = $this->objectManager->getObject( + StoreViewPlugin::class, + [ + 'urlPersist' => $this->urlPersistMock, + 'categoryFactory' => $this->categoryFactoryMock, + 'productFactory' => $this->productFactoryMock, + 'categoryUrlRewriteGenerator' => $this->categoryUrlRewriteGeneratorMock, + 'productUrlRewriteGenerator' => $this->productUrlRewriteGeneratorMock + ] + ); + } + + public function testAfterSave() + { + $this->abstractModelMock->expects($this->any()) + ->method('isObjectNew') + ->willReturn(true); + $this->categoryMock->expects($this->once()) + ->method('getCategories') + ->willReturn([]); + $this->categoryFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->categoryMock); + $this->productFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getCollection') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addCategoryIds') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addAttributeToSelect') + ->willReturn($this->productCollectionMock); + $this->productCollectionMock->expects($this->once()) + ->method('addWebsiteFilter') + ->willReturn($this->productCollectionMock); + $iterator = new \ArrayIterator([$this->productMock]); + $this->productCollectionMock->expects($this->once()) + ->method('getIterator') + ->willReturn($iterator); + $this->productUrlRewriteGeneratorMock->expects($this->once()) + ->method('generate') + ->with($this->productMock) + ->willReturn([]); + + $this->assertSame( + $this->subjectMock, + $this->plugin->afterSave($this->subjectMock, $this->subjectMock, $this->abstractModelMock) + ); + } + + public function testAfterDelete() + { + $this->urlPersistMock->expects($this->once()) + ->method('deleteByData'); + $this->assertSame( + $this->subjectMock, + $this->plugin->afterDelete($this->subjectMock, $this->subjectMock, $this->abstractModelMock) + ); + } +} diff --git a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/ResourceModel/Page.php b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/ResourceModel/Page.php index 45579f37b0c0cdeac82c14ff40f7e81eab227c9d..c605d3977d9f2a79f1f8d9d6d5b3cd04b241d14f 100644 --- a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/ResourceModel/Page.php +++ b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/ResourceModel/Page.php @@ -9,6 +9,8 @@ use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator; use Magento\CmsUrlRewrite\Model\CmsPageUrlRewriteGenerator; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /** * Before save and around delete plugin for \Magento\Cms\Model\ResourceModel\Page: @@ -63,18 +65,16 @@ class Page * On delete handler to remove related url rewrites * * @param \Magento\Cms\Model\ResourceModel\Page $subject - * @param \Closure $proceed - * @param \Magento\Framework\Model\AbstractModel $page - * @return \Magento\Cms\Model\ResourceModel\Page - * + * @param AbstractDb $result + * @param AbstractModel $page + * @return AbstractDb * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDelete( + public function afterDelete( \Magento\Cms\Model\ResourceModel\Page $subject, - \Closure $proceed, - \Magento\Framework\Model\AbstractModel $page + AbstractDb $result, + AbstractModel $page ) { - $result = $proceed($page); if ($page->isDeleted()) { $this->urlPersist->deleteByData( [ diff --git a/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/ResourceModel/PageTest.php b/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/ResourceModel/PageTest.php index 42b1b42469d5e0ee748a9795b8d3ac91ab54adc9..277e36b94fc8360c1a4bd4aec192e7cea94cc58d 100644 --- a/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/ResourceModel/PageTest.php +++ b/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/ResourceModel/PageTest.php @@ -30,19 +30,10 @@ class PageTest extends \PHPUnit_Framework_TestCase */ protected $cmsPageResourceMock; - /** - * @var \Closure - */ - protected $closureMock; - protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->closureMock = function () { - return 'URL Rewrite Result'; - }; - $this->urlPersistMock = $this->getMockBuilder(\Magento\UrlRewrite\Model\UrlPersistInterface::class) ->getMockForAbstractClass(); @@ -62,7 +53,7 @@ class PageTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundDeletePositive() + public function testAfterDeletePositive() { $productId = 100; @@ -83,17 +74,17 @@ class PageTest extends \PHPUnit_Framework_TestCase ] ); - $this->assertEquals( - 'URL Rewrite Result', - $this->pageObject->aroundDelete( + $this->assertSame( + $this->cmsPageResourceMock, + $this->pageObject->afterDelete( + $this->cmsPageResourceMock, $this->cmsPageResourceMock, - $this->closureMock, $this->cmsPageMock ) ); } - public function testAroundDeleteNegative() + public function testAfterDeleteNegative() { $this->cmsPageMock->expects($this->once()) ->method('isDeleted') @@ -102,11 +93,11 @@ class PageTest extends \PHPUnit_Framework_TestCase $this->urlPersistMock->expects($this->never()) ->method('deleteByData'); - $this->assertEquals( - 'URL Rewrite Result', - $this->pageObject->aroundDelete( + $this->assertSame( + $this->cmsPageResourceMock, + $this->pageObject->afterDelete( + $this->cmsPageResourceMock, $this->cmsPageResourceMock, - $this->closureMock, $this->cmsPageMock ) ); diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php index ada1488e9cd9ce71e4b8b7b82afd795922845adb..354ebdb0ea7c94bcb639f0e4329d8bd2e6aa0ff7 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Builder/Plugin.php @@ -8,6 +8,9 @@ namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Builder; use Magento\Catalog\Model\ProductFactory; use Magento\ConfigurableProduct\Model\Product\Type; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Controller\Adminhtml\Product\Builder as CatalogProductBuilder; +use Magento\Framework\App\RequestInterface; class Plugin { @@ -32,21 +35,17 @@ class Plugin } /** - * @param \Magento\Catalog\Controller\Adminhtml\Product\Builder $subject - * @param callable $proceed - * @param \Magento\Framework\App\RequestInterface $request + * Set type and data to configurable product * - * @return \Magento\Catalog\Model\Product + * @param CatalogProductBuilder $subject + * @param Product $product + * @param RequestInterface $request + * @return Product * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function aroundBuild( - \Magento\Catalog\Controller\Adminhtml\Product\Builder $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { - $product = $proceed($request); - + public function afterBuild(CatalogProductBuilder $subject, Product $product, RequestInterface $request) + { if ($request->has('attributes')) { $attributes = $request->getParam('attributes'); if (!empty($attributes)) { diff --git a/app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/ConfigurableProduct/Model/Plugin/ProductRepositorySave.php similarity index 93% rename from app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php rename to app/code/Magento/ConfigurableProduct/Model/Plugin/ProductRepositorySave.php index be12fc8da2904165f22a16b5750e20ac8c3ef37d..cfcb5e41799e8fda8239c32f2a67dd3dc0ebcd04 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Plugin/AroundProductRepositorySave.php +++ b/app/code/Magento/ConfigurableProduct/Model/Plugin/ProductRepositorySave.php @@ -14,10 +14,7 @@ use Magento\ConfigurableProduct\Api\Data\OptionInterface; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -/** - * Class AroundProductRepositorySave - */ -class AroundProductRepositorySave +class ProductRepositorySave { /** * @var ProductAttributeRepositoryInterface @@ -42,8 +39,10 @@ class AroundProductRepositorySave } /** + * Validate product links and reset configurable attributes to configurable product + * * @param ProductRepositoryInterface $subject - * @param callable $proceed + * @param ProductInterface $result * @param ProductInterface $product * @param bool $saveOptions * @return ProductInterface @@ -52,14 +51,12 @@ class AroundProductRepositorySave * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundSave( + public function afterSave( ProductRepositoryInterface $subject, - \Closure $proceed, + ProductInterface $result, ProductInterface $product, $saveOptions = false ) { - /** @var ProductInterface $result */ - $result = $proceed($product, $saveOptions); if ($product->getTypeId() !== Configurable::TYPE_CODE) { return $result; } diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Validator/Plugin.php b/app/code/Magento/ConfigurableProduct/Model/Product/Validator/Plugin.php index c0b287214ea3d32ea80beebe2dbe4cff865812d8..b5970c902743ee8c5959dca2a2922502c169a2d2 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Validator/Plugin.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Validator/Plugin.php @@ -5,12 +5,12 @@ */ namespace Magento\ConfigurableProduct\Model\Product\Validator; -use Closure; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ProductFactory; use Magento\Framework\App\RequestInterface; use Magento\Framework\Event\Manager; use Magento\Framework\Json\Helper\Data; +use Magento\Framework\DataObject; /** * Configurable product validation @@ -48,27 +48,44 @@ class Plugin } /** - * Validate product data + * Set configurable type to product * * @param Product\Validator $subject - * @param Closure $proceed * @param Product $product * @param RequestInterface $request - * @param \Magento\Framework\DataObject $response - * @return bool + * @param DataObject $response + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundValidate( + public function beforeValidate( \Magento\Catalog\Model\Product\Validator $subject, - Closure $proceed, \Magento\Catalog\Model\Product $product, - \Magento\Framework\App\RequestInterface $request, - \Magento\Framework\DataObject $response + RequestInterface $request, + DataObject $response ) { if ($request->has('attributes')) { $product->setTypeId(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); } - $result = $proceed($product, $request, $response); + } + + /** + * Validate product data + * + * @param Product\Validator $subject + * @param bool|array $result + * @param Product $product + * @param RequestInterface $request + * @param \Magento\Framework\DataObject $response + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterValidate( + \Magento\Catalog\Model\Product\Validator $subject, + $result, + \Magento\Catalog\Model\Product $product, + RequestInterface $request, + DataObject $response + ) { $variationProducts = (array)$request->getPost('variations-matrix'); if ($variationProducts) { $validationResult = $this->_validateProductVariations($product, $variationProducts, $request); diff --git a/app/code/Magento/ConfigurableProduct/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProduct.php b/app/code/Magento/ConfigurableProduct/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProduct.php index 73e88eb5333cb4ef62eef43e2aae5d02d9e53294..1657fb8aaae12788c217cd124a25a46d97ea3b0b 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProduct.php +++ b/app/code/Magento/ConfigurableProduct/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProduct.php @@ -13,20 +13,19 @@ class ConfigurableProduct * Initialize stock item for configurable product type * * @param \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option $subject - * @param callable $proceed + * @param \Magento\CatalogInventory\Model\Stock\Item $stockItem * @param \Magento\Quote\Model\Quote\Item\Option $option * @param \Magento\Quote\Model\Quote\Item $quoteItem * * @return \Magento\CatalogInventory\Api\Data\StockItemInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundGetStockItem( + public function afterGetStockItem( \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option $subject, - \Closure $proceed, + \Magento\CatalogInventory\Model\Stock\Item $stockItem, \Magento\Quote\Model\Quote\Item\Option $option, \Magento\Quote\Model\Quote\Item $quoteItem ) { - $stockItem = $proceed($option, $quoteItem); if ($quoteItem->getProductType() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { $stockItem->setProductName($quoteItem->getName()); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Builder/PluginTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Builder/PluginTest.php index 7056224cffd6843ea3dd35729cd5add8c01dc6ea..e6c13a23541fad21e5d592d4b0b9dc7bb32e7ed0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Builder/PluginTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Builder/PluginTest.php @@ -23,12 +23,12 @@ class PluginTest extends \PHPUnit_Framework_TestCase protected $configurableTypeMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ protected $requestMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ protected $productMock; @@ -48,15 +48,10 @@ class PluginTest extends \PHPUnit_Framework_TestCase protected $frontendAttrMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Controller\Adminhtml\Product\Builder|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; - /** - * @var \Closure - */ - protected $closureMock; - protected function setUp() { $this->productFactoryMock = $this->getMock( @@ -76,7 +71,6 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, [], [], '', false); $methods = ['setTypeId', 'getAttributes', 'addData', 'setWebsiteIds', '__wakeup']; $this->productMock = $this->getMock(\Magento\Catalog\Model\Product::class, $methods, [], '', false); - $product = $this->productMock; $attributeMethods = [ 'getId', 'getFrontend', @@ -124,9 +118,6 @@ class PluginTest extends \PHPUnit_Framework_TestCase '', false ); - $this->closureMock = function () use ($product) { - return $product; - }; $this->plugin = new \Magento\ConfigurableProduct\Controller\Adminhtml\Product\Builder\Plugin( $this->productFactoryMock, $this->configurableTypeMock @@ -137,7 +128,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testAroundBuild() + public function testAfterBuild() { $this->requestMock->expects($this->once())->method('has')->with('attributes')->will($this->returnValue(true)); $valueMap = [ @@ -256,11 +247,11 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->assertEquals( $this->productMock, - $this->plugin->aroundBuild($this->subjectMock, $this->closureMock, $this->requestMock) + $this->plugin->afterBuild($this->subjectMock, $this->productMock, $this->requestMock) ); } - public function testAroundBuildWhenProductNotHaveAttributeAndRequiredParameters() + public function testAfterBuildWhenProductNotHaveAttributeAndRequiredParameters() { $valueMap = [ ['attributes', null, null], @@ -283,11 +274,11 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->attributeMock->expects($this->never())->method('getAttributeCode'); $this->assertEquals( $this->productMock, - $this->plugin->aroundBuild($this->subjectMock, $this->closureMock, $this->requestMock) + $this->plugin->afterBuild($this->subjectMock, $this->productMock, $this->requestMock) ); } - public function testAroundBuildWhenAttributesAreEmpty() + public function testAfterBuildWhenAttributesAreEmpty() { $valueMap = [['popup', null, false], ['product', null, 'product'], ['id', false, false]]; $this->requestMock->expects($this->once())->method('has')->with('attributes')->will($this->returnValue(false)); @@ -299,7 +290,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->attributeMock->expects($this->never())->method('getAttributeCode'); $this->assertEquals( $this->productMock, - $this->plugin->aroundBuild($this->subjectMock, $this->closureMock, $this->requestMock) + $this->plugin->afterBuild($this->subjectMock, $this->productMock, $this->requestMock) ); } } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/ProductRepositorySaveTest.php similarity index 87% rename from app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php rename to app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/ProductRepositorySaveTest.php index dee340fca9d8688aee08904078039ad3f82b4849..3b2069296db9a4e20ae75c010fdca7000e53e403 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Plugin/ProductRepositorySaveTest.php @@ -11,16 +11,17 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ProductFactory; use Magento\ConfigurableProduct\Api\Data\OptionInterface; -use Magento\ConfigurableProduct\Model\Plugin\AroundProductRepositorySave; +use Magento\ConfigurableProduct\Model\Plugin\ProductRepositorySave; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\ConfigurableProduct\Test\Unit\Model\Product\ProductExtensionAttributes; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit_Framework_MockObject_MockObject as MockObject; /** - * Class AroundProductRepositorySaveTest + * Class ProductRepositorySaveTest * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase +class ProductRepositorySaveTest extends \PHPUnit_Framework_TestCase { /** * @var ProductAttributeRepositoryInterface|MockObject @@ -32,11 +33,6 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase */ private $productFactory; - /** - * @var \Closure - */ - private $closure; - /** * @var Product|MockObject */ @@ -68,7 +64,7 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase private $option; /** - * @var AroundProductRepositorySave + * @var ProductRepositorySave */ private $plugin; @@ -91,10 +87,6 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase ->setMethods(['getExtensionAttributes']) ->getMock(); - $this->closure = function () { - return $this->result; - }; - $this->productRepository = $this->getMockForAbstractClass(ProductRepositoryInterface::class); $this->extensionAttributes = $this->getMockBuilder(ProductExtensionAttributes::class) @@ -106,13 +98,16 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase $this->option = $this->getMockForAbstractClass(OptionInterface::class); - $this->plugin = new AroundProductRepositorySave( - $this->productAttributeRepository, - $this->productFactory + $this->plugin = (new ObjectManager($this))->getObject( + ProductRepositorySave::class, + [ + 'productAttributeRepository' => $this->productAttributeRepository, + 'productFactory' => $this->productFactory + ] ); } - public function testAroundSaveWhenProductIsSimple() + public function testAfterSaveWhenProductIsSimple() { $this->product->expects(static::once()) ->method('getTypeId') @@ -122,11 +117,11 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase $this->assertEquals( $this->result, - $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product) + $this->plugin->afterSave($this->productRepository, $this->result, $this->product) ); } - public function testAroundSaveWithoutOptions() + public function testAfterSaveWithoutOptions() { $this->product->expects(static::once()) ->method('getTypeId') @@ -148,7 +143,7 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase $this->assertEquals( $this->result, - $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product) + $this->plugin->afterSave($this->productRepository, $this->result, $this->product) ); } @@ -156,7 +151,7 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase * @expectedException \Magento\Framework\Exception\InputException * @expectedExceptionMessage Products "5" and "4" have the same set of attribute values. */ - public function testAroundSaveWithLinks() + public function testAfterSaveWithLinks() { $links = [4, 5]; $this->product->expects(static::once()) @@ -191,14 +186,14 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase $product->expects(static::never()) ->method('getData'); - $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product); + $this->plugin->afterSave($this->productRepository, $this->result, $this->product); } /** * @expectedException \Magento\Framework\Exception\InputException * @expectedExceptionMessage Product with id "4" does not contain required attribute "color". */ - public function testAroundSaveWithLinksWithMissingAttribute() + public function testAfterSaveWithLinksWithMissingAttribute() { $simpleProductId = 4; $links = [$simpleProductId, 5]; @@ -248,14 +243,14 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase ->with($attributeCode) ->willReturn(false); - $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product); + $this->plugin->afterSave($this->productRepository, $this->result, $this->product); } /** * @expectedException \Magento\Framework\Exception\InputException * @expectedExceptionMessage Products "5" and "4" have the same set of attribute values. */ - public function testAroundSaveWithLinksWithDuplicateAttributes() + public function testAfterSaveWithLinksWithDuplicateAttributes() { $links = [4, 5]; $attributeCode = 'color'; @@ -303,6 +298,6 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase ->with($attributeCode) ->willReturn($attributeId); - $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product); + $this->plugin->afterSave($this->productRepository, $this->result, $this->product); } } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Validator/PluginTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Validator/PluginTest.php index d66e32aa0e7b04ad4c39d0e767182656dd9ff75b..65d3f42767de5e136ac33f9c95fe702619c16613 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Validator/PluginTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Validator/PluginTest.php @@ -28,17 +28,17 @@ class PluginTest extends \PHPUnit_Framework_TestCase protected $jsonHelperMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ protected $productMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ protected $requestMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\DataObject|\PHPUnit_Framework_MockObject_MockObject */ protected $responseMock; @@ -53,15 +53,10 @@ class PluginTest extends \PHPUnit_Framework_TestCase protected $proceedResult = [1, 2, 3]; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product\Validator|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; - /** - * @var \Closure - */ - protected $closureMock; - protected function setUp() { $this->eventManagerMock = $this->getMock(\Magento\Framework\Event\Manager::class, [], [], '', false); @@ -82,14 +77,14 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->jsonHelperMock->expects($this->any())->method('jsonDecode')->will($this->returnArgument(0)); $this->productMock = $this->getMock( \Magento\Catalog\Model\Product::class, - ['getData', 'getAttributes'], + ['getData', 'getAttributes', 'setTypeId'], [], '', false ); $this->requestMock = $this->getMock( \Magento\Framework\App\Request\Http::class, - ['getPost', 'getParam', '__wakeup'], + ['getPost', 'getParam', '__wakeup', 'has'], [], '', false @@ -102,10 +97,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase false ); $this->arguments = [$this->productMock, $this->requestMock, $this->responseMock]; - $proceedResult = $this->proceedResult; - $this->closureMock = function () use ($proceedResult) { - return $proceedResult; - }; + $this->subjectMock = $this->getMock(\Magento\Catalog\Model\Product\Validator::class, [], [], '', false); $this->plugin = new \Magento\ConfigurableProduct\Model\Product\Validator\Plugin( $this->eventManagerMock, @@ -114,7 +106,20 @@ class PluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundValidateWithVariationsValid() + public function testBeforeValidate() + { + $this->requestMock->expects(static::once())->method('has')->with('attributes')->willReturn(true); + $this->productMock->expects(static::once())->method('setTypeId')->willReturnSelf(); + + $this->plugin->beforeValidate( + $this->subjectMock, + $this->productMock, + $this->requestMock, + $this->responseMock + ); + } + + public function testAfterValidateWithVariationsValid() { $matrix = ['products']; @@ -150,9 +155,9 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->assertEquals( $this->proceedResult, - $plugin->aroundValidate( + $plugin->afterValidate( $this->subjectMock, - $this->closureMock, + $this->proceedResult, $this->productMock, $this->requestMock, $this->responseMock @@ -160,7 +165,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundValidateWithVariationsInvalid() + public function testAfterValidateWithVariationsInvalid() { $matrix = ['products']; @@ -197,9 +202,9 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->responseMock->expects($this->once())->method('setAttributes')->will($this->returnSelf()); $this->assertEquals( $this->proceedResult, - $plugin->aroundValidate( + $plugin->afterValidate( $this->subjectMock, - $this->closureMock, + $this->proceedResult, $this->productMock, $this->requestMock, $this->responseMock @@ -207,7 +212,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundValidateIfVariationsNotExist() + public function testAfterValidateIfVariationsNotExist() { $this->requestMock->expects( $this->once() @@ -219,16 +224,16 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->returnValue(null) ); $this->eventManagerMock->expects($this->never())->method('dispatch'); - $this->plugin->aroundValidate( + $this->plugin->afterValidate( $this->subjectMock, - $this->closureMock, + $this->proceedResult, $this->productMock, $this->requestMock, $this->responseMock ); } - public function testAroundValidateWithVariationsAndRequiredAttributes() + public function testAfterValidateWithVariationsAndRequiredAttributes() { $matrix = [ ['data1', 'data2', 'configurable_attribute' => ['data1']], @@ -313,9 +318,9 @@ class PluginTest extends \PHPUnit_Framework_TestCase $this->responseMock->expects($this->never())->method('setError'); - $result = $this->plugin->aroundValidate( + $result = $this->plugin->afterValidate( $this->subjectMock, - $this->closureMock, + $this->proceedResult, $this->productMock, $this->requestMock, $this->responseMock diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProductTest.php index 7d10cb4511e13e60ff0c4d75cbf844d02c5d42ab..6b162bbde85c4ca46e2bdf27c4328b7b2deef144 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProductTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/Option/Plugin/ConfigurableProductTest.php @@ -3,20 +3,20 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\ConfigurableProduct\Test\Unit\Model\Quote\Item\QuantityValidator\Initializer\Option\Plugin; +use \Magento\ConfigurableProduct\Model\Quote\Item\QuantityValidator\Initializer\Option\Plugin\ConfigurableProduct + as InitializerOptionPlugin; + class ConfigurableProductTest extends \PHPUnit_Framework_TestCase { /** * @param array $data - * @dataProvider aroundGetStockItemDataProvider + * @dataProvider afterGetStockItemDataProvider */ - public function testAroundGetStockItem(array $data) + public function testAfterGetStockItem(array $data) { - $subjectMock = $this->getMock( + $subjectMock = $this->getMock( \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\Initializer\Option::class, [], [], @@ -24,36 +24,44 @@ class ConfigurableProductTest extends \PHPUnit_Framework_TestCase false ); - $quoteItemMock = $this->getMock( - \Magento\Quote\Model\Quote\Item::class, ['getProductType', '__wakeup'], [], '', false + $quoteItemMock = $this->getMock( + \Magento\Quote\Model\Quote\Item::class, + ['getProductType', '__wakeup'], + [], + '', + false ); $quoteItemMock->expects($this->once()) ->method('getProductType') ->will($this->returnValue($data['product_type'])); - $stockItemMock = $this->getMock( - \Magento\CatalogInventory\Model\Stock\Item::class, ['setProductName', '__wakeup'], [], '', false + $stockItemMock = $this->getMock( + \Magento\CatalogInventory\Model\Stock\Item::class, + ['setProductName', '__wakeup'], + [], + '', + false ); $matcherMethod = $data['matcher_method']; $stockItemMock->expects($this->$matcherMethod()) ->method('setProductName'); - $optionMock = $this->getMock( - \Magento\Quote\Model\Quote\Item\Option::class, ['getProduct', '__wakeup'], [], '', false + $optionMock = $this->getMock( + \Magento\Quote\Model\Quote\Item\Option::class, + ['getProduct', '__wakeup'], + [], + '', + false ); - $proceed = function () use ($stockItemMock) { - return $stockItemMock; - }; - - $model = new \Magento\ConfigurableProduct\Model\Quote\Item\QuantityValidator\Initializer\Option\Plugin\ConfigurableProduct(); - $model->aroundGetStockItem($subjectMock, $proceed, $optionMock, $quoteItemMock, 0); + $model = new InitializerOptionPlugin(); + $model->afterGetStockItem($subjectMock, $stockItemMock, $optionMock, $quoteItemMock, 0); } /** * @return array */ - public function aroundGetStockItemDataProvider() + public function afterGetStockItemDataProvider() { return [ [ diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index e32286764f56ec959044cb11a5e65c13928f4d7c..c3be4aaea189a63edb9091df2712d063eb8e09e1 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -59,7 +59,7 @@ </arguments> </type> <type name="Magento\Catalog\Api\ProductRepositoryInterface"> - <plugin name="configurableProductSaveOptions" type="\Magento\ConfigurableProduct\Model\Plugin\AroundProductRepositorySave"/> + <plugin name="configurableProductSaveOptions" sortOrder="10" type="Magento\ConfigurableProduct\Model\Plugin\ProductRepositorySave"/> </type> <type name="Magento\Catalog\Model\Product"> <plugin name="configurable_identity" type="Magento\ConfigurableProduct\Plugin\Model\Product" /> diff --git a/app/code/Magento/Customer/Controller/Plugin/Account.php b/app/code/Magento/Customer/Controller/Plugin/Account.php index 0a19f87b5050c4b188be70f2f0f23850bc1bf61e..5da79b8aa46a21cb5847f1eb916994938e4698d4 100644 --- a/app/code/Magento/Customer/Controller/Plugin/Account.php +++ b/app/code/Magento/Customer/Controller/Plugin/Account.php @@ -8,6 +8,9 @@ namespace Magento\Customer\Controller\Plugin; use Magento\Customer\Model\Session; use Magento\Framework\App\ActionInterface; use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\Controller\ResultInterface; class Account { @@ -36,16 +39,12 @@ class Account /** * Dispatch actions allowed for not authorized users * - * @param ActionInterface $subject - * @param \Closure $proceed + * @param AbstractAction $subject * @param RequestInterface $request - * @return mixed + * @return void */ - public function aroundDispatch( - ActionInterface $subject, - \Closure $proceed, - RequestInterface $request - ) { + public function beforeDispatch(AbstractAction $subject, RequestInterface $request) + { $action = strtolower($request->getActionName()); $pattern = '/^(' . implode('|', $this->allowedActions) . ')$/i'; @@ -56,8 +55,19 @@ class Account } else { $this->session->setNoReferer(true); } + } - $result = $proceed($request); + /** + * Remove No-referer flag from customer session + * + * @param AbstractAction $subject + * @param ResponseInterface|ResultInterface $result + * @param RequestInterface $request + * @return ResponseInterface|ResultInterface + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterDispatch(AbstractAction $subject, $result, RequestInterface $request) + { $this->session->unsNoReferer(false); return $result; } diff --git a/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php b/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php index f102664df537b846aa5376f198a04f8b06a2d5fe..7518c4b4783a04a488256d15fd6d107b13da2cc9 100644 --- a/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Customer/Model/App/Action/ContextPlugin.php @@ -8,6 +8,10 @@ namespace Magento\Customer\Model\App\Action; use Magento\Customer\Model\Context; use Magento\Customer\Model\GroupManagement; +use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\App\RequestInterface; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Http\Context as HttpContext; /** * Class ContextPlugin @@ -15,39 +19,35 @@ use Magento\Customer\Model\GroupManagement; class ContextPlugin { /** - * @var \Magento\Customer\Model\Session + * @var Session */ protected $customerSession; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext */ protected $httpContext; /** - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\App\Http\Context $httpContext + * @param Session $customerSession + * @param HttpContext $httpContext */ - public function __construct( - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\App\Http\Context $httpContext - ) { + public function __construct(Session $customerSession, HttpContext $httpContext) + { $this->customerSession = $customerSession; $this->httpContext = $httpContext; } /** - * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed - * @param \Magento\Framework\App\RequestInterface $request - * @return mixed + * Set customer group and customer session id to HTTP context + * + * @param AbstractAction $subject + * @param RequestInterface $request + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeDispatch(AbstractAction $subject, RequestInterface $request) + { $this->httpContext->setValue( Context::CONTEXT_GROUP, $this->customerSession->getCustomerGroupId(), @@ -58,6 +58,5 @@ class ContextPlugin $this->customerSession->isLoggedIn(), false ); - return $proceed($request); } } diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php index b175e55f1d3be90b4b6b886c3db22eb361e8e904..b9c05d4005be5e6664f9a36b76db7814140a55b8 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php @@ -9,7 +9,10 @@ use Magento\Customer\Controller\Plugin\Account; use Magento\Customer\Model\Session; use Magento\Framework\App\ActionFlag; use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\Action\AbstractAction; use Magento\Framework\App\Request\Http; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class AccountTest extends \PHPUnit_Framework_TestCase { @@ -29,12 +32,7 @@ class AccountTest extends \PHPUnit_Framework_TestCase protected $session; /** - * @var \Closure - */ - protected $proceed; - - /** - * @var ActionInterface | \PHPUnit_Framework_MockObject_MockObject + * @var AbstractAction | \PHPUnit_Framework_MockObject_MockObject */ protected $subject; @@ -48,6 +46,11 @@ class AccountTest extends \PHPUnit_Framework_TestCase */ protected $actionFlag; + /** + * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $resultInterface; + protected function setUp() { $this->session = $this->getMockBuilder(\Magento\Customer\Model\Session::class) @@ -59,16 +62,13 @@ class AccountTest extends \PHPUnit_Framework_TestCase ]) ->getMock(); - $this->subject = $this->getMockBuilder(\Magento\Framework\App\ActionInterface::class) + $this->subject = $this->getMockBuilder(AbstractAction::class) ->setMethods([ 'getActionFlag', ]) + ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->proceed = function () { - return self::EXPECTED_VALUE; - }; - $this->request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) ->disableOriginalConstructor() ->setMethods([ @@ -76,6 +76,9 @@ class AccountTest extends \PHPUnit_Framework_TestCase ]) ->getMock(); + $this->resultInterface = $this->getMockBuilder(ResultInterface::class) + ->getMockForAbstractClass(); + $this->actionFlag = $this->getMockBuilder(\Magento\Framework\App\ActionFlag::class) ->disableOriginalConstructor() ->getMock(); @@ -87,9 +90,9 @@ class AccountTest extends \PHPUnit_Framework_TestCase * @param boolean $isActionAllowed * @param boolean $isAuthenticated * - * @dataProvider dataProviderAroundDispatch + * @dataProvider beforeDispatchDataProvider */ - public function testAroundDispatch( + public function testBeforeDispatch( $action, $allowedActions, $isActionAllowed, @@ -99,11 +102,6 @@ class AccountTest extends \PHPUnit_Framework_TestCase ->method('getActionName') ->willReturn($action); - $this->session->expects($this->once()) - ->method('unsNoReferer') - ->with(false) - ->willReturnSelf(); - if ($isActionAllowed) { $this->session->expects($this->once()) ->method('setNoReferer') @@ -126,13 +124,13 @@ class AccountTest extends \PHPUnit_Framework_TestCase } $plugin = new Account($this->session, $allowedActions); - $this->assertEquals( - self::EXPECTED_VALUE, - $plugin->aroundDispatch($this->subject, $this->proceed, $this->request) - ); + $plugin->beforeDispatch($this->subject, $this->request); } - public function dataProviderAroundDispatch() + /** + * @return array + */ + public function beforeDispatchDataProvider() { return [ [ @@ -167,4 +165,24 @@ class AccountTest extends \PHPUnit_Framework_TestCase ], ]; } + + public function testAfterDispatch() + { + $this->session->expects($this->once()) + ->method('unsNoReferer') + ->with(false) + ->willReturnSelf(); + + $plugin = (new ObjectManager($this))->getObject( + Account::class, + [ + 'session' => $this->session, + 'allowedActions' => ['testaction'] + ] + ); + $this->assertSame( + $this->resultInterface, + $plugin->afterDispatch($this->subject, $this->resultInterface, $this->request) + ); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php b/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php index c5ab448f976474dac910b7d090fe84a448f385a4..985e2ecb7efd3a25c333dc9ecd24fe7e9b1dc11d 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/App/Action/ContextPluginTest.php @@ -28,11 +28,6 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase */ protected $httpContextMock; - /** - * @var \Closure - */ - protected $closureMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -62,9 +57,6 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase '', false ); - $this->closureMock = function () { - return 'ExpectedValue'; - }; $this->subjectMock = $this->getMock(\Magento\Framework\App\Action\Action::class, [], [], '', false); $this->requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class); $this->plugin = new \Magento\Customer\Model\App\Action\ContextPlugin( @@ -76,7 +68,7 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase /** * Test aroundDispatch */ - public function testAroundDispatch() + public function testBeforeDispatch() { $this->customerSessionMock->expects($this->once()) ->method('getCustomerGroupId') @@ -94,9 +86,6 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase ] ) ); - $this->assertEquals( - 'ExpectedValue', - $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); + $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); } } diff --git a/app/code/Magento/GiftMessage/Block/Message/Multishipping/Plugin/ItemsBox.php b/app/code/Magento/GiftMessage/Block/Message/Multishipping/Plugin/ItemsBox.php index e79052a1fb3e3826977f625e167384bd8127fdb7..acc5fb484ada7a2ccd76b1d426b9d1eed5a398ae 100644 --- a/app/code/Magento/GiftMessage/Block/Message/Multishipping/Plugin/ItemsBox.php +++ b/app/code/Magento/GiftMessage/Block/Message/Multishipping/Plugin/ItemsBox.php @@ -5,6 +5,10 @@ */ namespace Magento\GiftMessage\Block\Message\Multishipping\Plugin; +use Magento\Multishipping\Block\Checkout\Shipping as ShippingBlock; +use Magento\GiftMessage\Helper\Message as MessageHelper; +use Magento\Framework\DataObject; + /** * Multishipping items box plugin */ @@ -13,16 +17,16 @@ class ItemsBox /** * Gift message helper * - * @var \Magento\GiftMessage\Helper\Message + * @var MessageHelper */ protected $helper; /** * Construct * - * @param \Magento\GiftMessage\Helper\Message $helper + * @param MessageHelper $helper */ - public function __construct(\Magento\GiftMessage\Helper\Message $helper) + public function __construct(MessageHelper $helper) { $this->helper = $helper; } @@ -30,19 +34,15 @@ class ItemsBox /** * Get items box message text for multishipping * - * @param \Magento\Multishipping\Block\Checkout\Shipping $subject - * @param callable $proceed - * @param \Magento\Framework\DataObject $addressEntity + * @param ShippingBlock $subject + * @param string $itemsBoxText + * @param DataObject $addressEntity * * @return string * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundGetItemsBoxTextAfter( - \Magento\Multishipping\Block\Checkout\Shipping $subject, - \Closure $proceed, - \Magento\Framework\DataObject $addressEntity - ) { - $itemsBoxText = $proceed($addressEntity); + public function afterGetItemsBoxTextAfter(ShippingBlock $subject, $itemsBoxText, DataObject $addressEntity) + { return $itemsBoxText . $this->helper->getInline('multishipping_address', $addressEntity); } } diff --git a/app/code/Magento/GiftMessage/Model/Plugin/QuoteItem.php b/app/code/Magento/GiftMessage/Model/Plugin/QuoteItem.php index 0faee488baea061b83e1180a715dd213a5ceec07..6367fd7ced4052e06cd7b787c98de861ed8b166a 100644 --- a/app/code/Magento/GiftMessage/Model/Plugin/QuoteItem.php +++ b/app/code/Magento/GiftMessage/Model/Plugin/QuoteItem.php @@ -5,40 +5,42 @@ */ namespace Magento\GiftMessage\Model\Plugin; -use Closure; -use Magento\Sales\Model\Order\Item; +use Magento\Sales\Api\Data\OrderItemInterface; +use Magento\GiftMessage\Helper\Message as MessageHelper; +use Magento\Quote\Model\Quote\Item\ToOrderItem; +use Magento\Quote\Model\Quote\Item\AbstractItem; class QuoteItem { /** - * @var \Magento\GiftMessage\Helper\Message + * @var MessageHelper */ protected $_helper; /** - * @param \Magento\GiftMessage\Helper\Message $helper + * @param MessageHelper $helper */ - public function __construct(\Magento\GiftMessage\Helper\Message $helper) + public function __construct(MessageHelper $helper) { $this->_helper = $helper; } /** - * @param \Magento\Quote\Model\Quote\Item\ToOrderItem $subject - * @param callable $proceed - * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item + * Apply gift message per every item in order if available + * + * @param ToOrderItem $subject + * @param OrderItemInterface $orderItem + * @param AbstractItem $item * @param array $additional - * @return Item + * @return OrderItemInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundConvert( - \Magento\Quote\Model\Quote\Item\ToOrderItem $subject, - Closure $proceed, - \Magento\Quote\Model\Quote\Item\AbstractItem $item, + public function afterConvert( + ToOrderItem $subject, + OrderItemInterface $orderItem, + AbstractItem $item, $additional = [] ) { - /** @var $orderItem Item */ - $orderItem = $proceed($item, $additional); $isAvailable = $this->_helper->isMessagesAllowed('item', $item, $item->getStoreId()); $orderItem->setGiftMessageId($item->getGiftMessageId()); diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/QuoteItemTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/QuoteItemTest.php index ad099bebc8847d7556414d6118687c1da108c8d5..cfb8f1463d6eb0d8aba41e60a271ebc4ccfa33f7 100644 --- a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/QuoteItemTest.php +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/QuoteItemTest.php @@ -68,7 +68,7 @@ class QuoteItemTest extends \PHPUnit_Framework_TestCase $this->model = new \Magento\GiftMessage\Model\Plugin\QuoteItem($this->helperMock); } - public function testAroundItemToOrderItem() + public function testAfterItemToOrderItem() { $storeId = 1; $giftMessageId = 1; @@ -99,7 +99,7 @@ class QuoteItemTest extends \PHPUnit_Framework_TestCase $this->assertSame( $this->orderItemMock, - $this->model->aroundConvert($this->subjectMock, $this->closureMock, $this->quoteItemMock, []) + $this->model->afterConvert($this->subjectMock, $this->orderItemMock, $this->quoteItemMock, []) ); } } diff --git a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link/RelationPersister.php b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link/RelationPersister.php index f83b34ec3b30d694207511fc096a87a1b90ff90c..f431bf3af952b2109b60e44436944f9040e16049 100644 --- a/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link/RelationPersister.php +++ b/app/code/Magento/GroupedProduct/Model/ResourceModel/Product/Link/RelationPersister.php @@ -9,6 +9,7 @@ namespace Magento\GroupedProduct\Model\ResourceModel\Product\Link; use Magento\Catalog\Model\ProductLink\LinkFactory; use Magento\Catalog\Model\ResourceModel\Product\Link; use Magento\Catalog\Model\ResourceModel\Product\Relation; +use Magento\GroupedProduct\Model\ResourceModel\Product\Link as GroupedLink; class RelationPersister { @@ -38,17 +39,16 @@ class RelationPersister * Save grouped products to product relation table * * @param Link $subject - * @param \Closure $proceed + * @param Link $result * @param int $parentId * @param array $data * @param int $typeId * @return Link * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundSaveProductLinks(Link $subject, \Closure $proceed, $parentId, $data, $typeId) + public function afterSaveProductLinks(Link $subject, Link $result, $parentId, $data, $typeId) { - $result = $proceed($parentId, $data, $typeId); - if ($typeId == \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED) { + if ($typeId == GroupedLink::LINK_TYPE_GROUPED) { foreach ($data as $linkData) { $this->relationProcessor->addRelation( $parentId, @@ -73,7 +73,7 @@ class RelationPersister $link = $this->linkFactory->create(); $subject->load($link, $linkId, $subject->getIdFieldName()); $result = $proceed($linkId); - if ($link->getLinkTypeId() == \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED) { + if ($link->getLinkTypeId() == GroupedLink::LINK_TYPE_GROUPED) { $this->relationProcessor->removeRelations( $link->getProductId(), $link->getLinkedProductId() diff --git a/app/code/Magento/GroupedProduct/Model/Sales/AdminOrder/Product/Quote/Plugin/Initializer.php b/app/code/Magento/GroupedProduct/Model/Sales/AdminOrder/Product/Quote/Plugin/Initializer.php index f1204efa714a502cfec8563e408df353e4f89b53..2ab99856df306f9af5b2d951bb75785e64107c95 100644 --- a/app/code/Magento/GroupedProduct/Model/Sales/AdminOrder/Product/Quote/Plugin/Initializer.php +++ b/app/code/Magento/GroupedProduct/Model/Sales/AdminOrder/Product/Quote/Plugin/Initializer.php @@ -18,7 +18,7 @@ class Initializer { /** * @param \Magento\Sales\Model\AdminOrder\Product\Quote\Initializer $subject - * @param callable $proceed + * @param \Magento\Quote\Model\Quote\Item|string $item * @param \Magento\Quote\Model\Quote $quote * @param \Magento\Catalog\Model\Product $product * @param \Magento\Framework\DataObject $config @@ -26,15 +26,13 @@ class Initializer * @return \Magento\Quote\Model\Quote\Item|string * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundInit( + public function afterInit( \Magento\Sales\Model\AdminOrder\Product\Quote\Initializer $subject, - \Closure $proceed, + $item, \Magento\Quote\Model\Quote $quote, \Magento\Catalog\Model\Product $product, \Magento\Framework\DataObject $config ) { - $item = $proceed($quote, $product, $config); - if (is_string($item) && $product->getTypeId() != Grouped::TYPE_CODE) { $item = $quote->addProduct( $product, diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/ResourceModel/Product/Link/RelationPersisterTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/ResourceModel/Product/Link/RelationPersisterTest.php index d11539945b0e84f7437b43975de4abc6db00dcc3..49bcd76cc2b83d0f838438e333924eaca62b912e 100644 --- a/app/code/Magento/GroupedProduct/Test/Unit/Model/ResourceModel/Product/Link/RelationPersisterTest.php +++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/ResourceModel/Product/Link/RelationPersisterTest.php @@ -3,13 +3,14 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\GroupedProduct\Test\Unit\Model\ResourceModel\Product\Link; use Magento\GroupedProduct\Model\ResourceModel\Product\Link\RelationPersister; use Magento\Catalog\Model\ProductLink\LinkFactory; use Magento\Catalog\Model\Product\Link; use Magento\Catalog\Model\ResourceModel\Product\Relation; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Catalog\Model\ResourceModel\Product\Link as LinkResourceModel; class RelationPersisterTest extends \PHPUnit_Framework_TestCase { @@ -22,12 +23,29 @@ class RelationPersisterTest extends \PHPUnit_Framework_TestCase /** @var Relation */ private $relationProcessor; + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var LinkFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $linkFactory; + + /** + * @var LinkResourceModel|\PHPUnit_Framework_MockObject_MockObject + */ + private $subject; + /** * @inheritDoc */ protected function setUp() { - $linkFactory = $this->getMockBuilder(LinkFactory::class) + $this->objectManager = new ObjectManager($this); + + $this->linkFactory = $this->getMockBuilder(LinkFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); @@ -41,23 +59,27 @@ class RelationPersisterTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $linkFactory->expects($this->any())->method('create')->willReturn($this->link); + $this->linkFactory->expects($this->any())->method('create')->willReturn($this->link); - $this->object = new RelationPersister( - $this->relationProcessor, - $linkFactory + $this->subject = $this->getMockBuilder(LinkResourceModel::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->object = $this->objectManager->getObject( + RelationPersister::class, + [ + 'relationProcessor' => $this->relationProcessor, + 'linkFactory' => $this->linkFactory + ] ); } - public function testAroundSaveProductLinks() + public function testAfterSaveProductLinks() { - $subject = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Link::class) - ->disableOriginalConstructor() - ->getMock(); $this->relationProcessor->expects($this->once())->method('addRelation')->with(2, 10); - $this->assertEquals($subject, $this->object->aroundSaveProductLinks( - $subject, - function() use ($subject) { return $subject; }, + $this->assertEquals($this->subject, $this->object->afterSaveProductLinks( + $this->subject, + $this->subject, 2, [['product_id' => 10]], 3 @@ -87,10 +109,11 @@ class RelationPersisterTest extends \PHPUnit_Framework_TestCase $subject, $this->object->aroundDeleteProductLink( $subject, - function() use ($subject) { return $subject; }, + function () use ($subject) { + return $subject; + }, 155 ) ); - } } diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/Sales/AdminOrder/Product/Quote/Plugin/InitializerTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/Sales/AdminOrder/Product/Quote/Plugin/InitializerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..43d7aa93dd0df9d6030640114241dfe64273209a --- /dev/null +++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/Sales/AdminOrder/Product/Quote/Plugin/InitializerTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\GroupedProduct\Test\Unit\Model\Sales\AdminOrder\Product\Quote\Plugin; + +use Magento\GroupedProduct\Model\Sales\AdminOrder\Product\Quote\Plugin\Initializer as QuoteInitializerPlugin; +use Magento\Sales\Model\AdminOrder\Product\Quote\Initializer as QuoteInitializer; +use Magento\Quote\Model\Quote; +use Magento\Catalog\Model\Product; +use Magento\Quote\Model\Quote\Item as QuoteItem; +use Magento\Framework\DataObject; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class InitializerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var QuoteInitializerPlugin|\PHPUnit_Framework_MockObject_MockObject + */ + private $plugin; + + /** + * @var QuoteInitializer|\PHPUnit_Framework_MockObject_MockObject + */ + private $initializer; + + /** + * @var Quote|\PHPUnit_Framework_MockObject_MockObject + */ + private $quote; + + /** + * @var QuoteItem|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteItem; + + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $product; + + /** + * @var DataObject|\PHPUnit_Framework_MockObject_MockObject + */ + private $config; + + protected function setUp() + { + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $this->initializer = $this->getMockBuilder(QuoteInitializer::class) + ->disableOriginalConstructor() + ->getMock(); + $this->quote = $this->getMockBuilder(Quote::class) + ->setMethods(['addProduct']) + ->disableOriginalConstructor() + ->getMock(); + $this->product = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getTypeId']) + ->getMock(); + $this->quoteItem = $this->getMockBuilder(QuoteItem::class) + ->disableOriginalConstructor() + ->getMock(); + $this->config = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->plugin = $this->objectManagerHelper->getObject( + QuoteInitializerPlugin::class + ); + } + + public function testAfterInit() + { + $this->assertSame( + $this->quoteItem, + $this->plugin->afterInit($this->initializer, $this->quoteItem, $this->quote, $this->product, $this->config) + ); + } +} diff --git a/app/code/Magento/MediaStorage/Model/Asset/Plugin/CleanMergedJsCss.php b/app/code/Magento/MediaStorage/Model/Asset/Plugin/CleanMergedJsCss.php index 0100c9887f1537081af83a477da9c78c107615a9..4cd6d67a01073b76b396c29c3ad933022c4ee94f 100644 --- a/app/code/Magento/MediaStorage/Model/Asset/Plugin/CleanMergedJsCss.php +++ b/app/code/Magento/MediaStorage/Model/Asset/Plugin/CleanMergedJsCss.php @@ -35,15 +35,13 @@ class CleanMergedJsCss * Clean files in database on cleaning merged assets * * @param \Magento\Framework\View\Asset\MergeService $subject - * @param callable $proceed + * @param void $result * * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundCleanMergedJsCss(\Magento\Framework\View\Asset\MergeService $subject, \Closure $proceed) + public function afterCleanMergedJsCss(\Magento\Framework\View\Asset\MergeService $subject, $result) { - $proceed(); - /** @var \Magento\Framework\Filesystem\Directory\ReadInterface $pubStaticDirectory */ $pubStaticDirectory = $this->filesystem->getDirectoryRead(DirectoryList::STATIC_VIEW); $mergedDir = $pubStaticDirectory->getAbsolutePath() . '/' diff --git a/app/code/Magento/MediaStorage/Test/Unit/Model/Asset/Plugin/CleanMergedJsCssTest.php b/app/code/Magento/MediaStorage/Test/Unit/Model/Asset/Plugin/CleanMergedJsCssTest.php index aa6578ebc7effec18df4e88a0f99784aed580ad3..9ff391185952255ccc216f376bf7c65e595bd21a 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Model/Asset/Plugin/CleanMergedJsCssTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Model/Asset/Plugin/CleanMergedJsCssTest.php @@ -3,9 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\MediaStorage\Test\Unit\Model\Asset\Plugin; use Magento\Framework\App\Filesystem\DirectoryList; @@ -22,11 +19,6 @@ class CleanMergedJsCssTest extends \Magento\Framework\TestFramework\Unit\BaseTes */ private $filesystemMock; - /** - * @var bool - */ - private $hasBeenCalled = false; - /** * @var \Magento\MediaStorage\Model\Asset\Plugin\CleanMergedJsCss */ @@ -46,11 +38,8 @@ class CleanMergedJsCssTest extends \Magento\Framework\TestFramework\Unit\BaseTes ); } - public function testAroundCleanMergedJsCss() + public function testAfterCleanMergedJsCss() { - $callable = function () { - $this->hasBeenCalled = true; - }; $readDir = 'read directory'; $mergedDir = $readDir . '/' . \Magento\Framework\View\Asset\Merged::getRelativeDir(); @@ -65,11 +54,9 @@ class CleanMergedJsCssTest extends \Magento\Framework\TestFramework\Unit\BaseTes ->with(DirectoryList::STATIC_VIEW) ->willReturn($readDirectoryMock); - $this->model->aroundCleanMergedJsCss( + $this->model->afterCleanMergedJsCss( $this->basicMock(\Magento\Framework\View\Asset\MergeService::class), - $callable + null ); - - $this->assertTrue($this->hasBeenCalled); } } diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php index d785b3a82aff76cf200a5c662ad1070acc83d944..3cae720825a04efae6277123f8ba56d62325a08f 100644 --- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php +++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php @@ -31,46 +31,27 @@ class CustomerPlugin /** * Plugin after create customer that updates any newsletter subscription that may have existed. * + * If we have extension attribute (is_subscribed) we need to subscribe that customer + * * @param CustomerRepository $subject + * @param CustomerInterface $result * @param CustomerInterface $customer * @return CustomerInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterSave(CustomerRepository $subject, CustomerInterface $customer) + public function afterSave(CustomerRepository $subject, CustomerInterface $result, CustomerInterface $customer) { - $this->subscriberFactory->create()->updateSubscription($customer->getId()); - return $customer; - } - - /** - * Plugin around customer repository save. If we have extension attribute (is_subscribed) we need to subscribe that customer - * - * @param CustomerRepository $subject - * @param \Closure $proceed - * @param CustomerInterface $customer - * @param null $passwordHash - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function aroundSave( - CustomerRepository $subject, - \Closure $proceed, - CustomerInterface $customer, - $passwordHash = null - ) { - /** @var CustomerInterface $savedCustomer */ - $savedCustomer = $proceed($customer, $passwordHash); - - if ($savedCustomer->getId() && $customer->getExtensionAttributes()) { + $this->subscriberFactory->create()->updateSubscription($result->getId()); + if ($result->getId() && $customer->getExtensionAttributes()) { if ($customer->getExtensionAttributes()->getIsSubscribed() === true) { - $this->subscriberFactory->create()->subscribeCustomerById($savedCustomer->getId()); + $this->subscriberFactory->create()->subscribeCustomerById($result->getId()); } elseif ($customer->getExtensionAttributes()->getIsSubscribed() === false) { - $this->subscriberFactory->create()->unsubscribeCustomerById($savedCustomer->getId()); + $this->subscriberFactory->create()->unsubscribeCustomerById($result->getId()); } } - - return $savedCustomer; + return $result; } - + /** * Plugin around delete customer that updates any newsletter subscription that may have existed. * @@ -96,21 +77,16 @@ class CustomerPlugin } /** - * Plugin around delete customer that updates any newsletter subscription that may have existed. + * Plugin after delete customer that updates any newsletter subscription that may have existed. * * @param CustomerRepository $subject - * @param callable $deleteCustomer Function we are wrapping around - * @param CustomerInterface $customer Input to the function + * @param bool $result + * @param CustomerInterface $customer * @return bool * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDelete( - CustomerRepository $subject, - callable $deleteCustomer, - $customer - ) { - $result = $deleteCustomer($customer); - /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ + public function afterDelete(CustomerRepository $subject, $result, CustomerInterface $customer) + { $subscriber = $this->subscriberFactory->create(); $subscriber->loadByEmail($customer->getEmail()); if ($subscriber->getId()) { diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php index b4bc13043bf97409bfc6ceb7d8db47a5440fadca..458d6ea22b009323da9aee75dfe7a1a416833d19 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php @@ -60,26 +60,11 @@ class CustomerPluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAfterSave() + public function testAfterSaveWithoutIsSubscribed() { - $customerId = 1; - $subject = $this->getMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); - $customer = $this->getMock(\Magento\Customer\Api\Data\CustomerInterface::class); - $customer->expects($this->once())->method('getId')->willReturn($customerId); - $this->subscriber->expects($this->once())->method('updateSubscription')->with($customerId)->willReturnSelf(); - - $this->assertEquals($customer, $this->plugin->afterSave($subject, $customer)); - } - - public function testAroundSaveWithoutIsSubscribed() - { - $passwordHash = null; $customerId = 1; /** @var CustomerInterface | \PHPUnit_Framework_MockObject_MockObject $customer */ $customer = $this->getMock(\Magento\Customer\Api\Data\CustomerInterface::class); - $proceed = function (CustomerInterface $customer, $passwordHash = null) use ($customer) { - return $customer; - }; /** @var CustomerRepository | \PHPUnit_Framework_MockObject_MockObject $subject */ $subject = $this->getMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); @@ -87,26 +72,27 @@ class CustomerPluginTest extends \PHPUnit_Framework_TestCase ->method("getId") ->willReturn($customerId); - $this->assertEquals($customer, $this->plugin->aroundSave($subject, $proceed, $customer, $passwordHash)); + $this->assertEquals($customer, $this->plugin->afterSave($subject, $customer, $customer)); } /** * @return array */ - public function provideExtensionAttributeDataForAroundSave() + public function afterSaveExtensionAttributeDataProvider() { return [ - [true, true] , + [true, true], [false, false] ]; } /** - * @dataProvider provideExtensionAttributeDataForAroundSave + * @param boolean $isSubscribed + * @param boolean $subscribeIsCreated + * @dataProvider afterSaveExtensionAttributeDataProvider */ - public function testAroundSaveWithIsSubscribed($isSubscribed, $subscribeIsCreated) + public function testAfterSaveWithIsSubscribed($isSubscribed, $subscribeIsCreated) { - $passwordHash = null; $customerId = 1; /** @var CustomerInterface | \PHPUnit_Framework_MockObject_MockObject $customer */ $customer = $this->getMock(\Magento\Customer\Api\Data\CustomerInterface::class); @@ -134,9 +120,6 @@ class CustomerPluginTest extends \PHPUnit_Framework_TestCase ->with($customerId); } - $proceed = function (CustomerInterface $customer, $passwordHash = null) use ($customer) { - return $customer; - }; /** @var CustomerRepository | \PHPUnit_Framework_MockObject_MockObject $subject */ $subject = $this->getMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); @@ -144,14 +127,11 @@ class CustomerPluginTest extends \PHPUnit_Framework_TestCase ->method("getId") ->willReturn($customerId); - $this->assertEquals($customer, $this->plugin->aroundSave($subject, $proceed, $customer, $passwordHash)); + $this->assertEquals($customer, $this->plugin->afterSave($subject, $customer, $customer)); } - public function testAroundDelete() + public function testAfterDelete() { - $deleteCustomer = function () { - return true; - }; $subject = $this->getMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); $customer = $this->getMock(\Magento\Customer\Api\Data\CustomerInterface::class); $customer->expects($this->once())->method('getEmail')->willReturn('test@test.com'); @@ -159,7 +139,7 @@ class CustomerPluginTest extends \PHPUnit_Framework_TestCase $this->subscriber->expects($this->once())->method('getId')->willReturn(1); $this->subscriber->expects($this->once())->method('delete')->willReturnSelf(); - $this->assertEquals(true, $this->plugin->aroundDelete($subject, $deleteCustomer, $customer)); + $this->assertEquals(true, $this->plugin->afterDelete($subject, true, $customer)); } public function testAroundDeleteById() diff --git a/app/code/Magento/PageCache/Model/App/FrontController/VarnishPlugin.php b/app/code/Magento/PageCache/Model/App/FrontController/VarnishPlugin.php index 1d716991f9d3f9dca62b76f12c0b1060d36ea31f..08b68447c9d4d8dd4f3612692e5488dd204d1e15 100644 --- a/app/code/Magento/PageCache/Model/App/FrontController/VarnishPlugin.php +++ b/app/code/Magento/PageCache/Model/App/FrontController/VarnishPlugin.php @@ -5,61 +5,67 @@ */ namespace Magento\PageCache\Model\App\FrontController; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Version; +use Magento\Framework\App\State as AppState; +use Magento\Framework\App\FrontControllerInterface; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Controller\ResultInterface; + /** * Varnish for processing builtin cache */ class VarnishPlugin { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var Config */ - protected $config; + private $config; /** - * @var \Magento\Framework\App\PageCache\Version + * @var Version */ - protected $version; + private $version; /** - * @var \Magento\Framework\App\State + * @var AppState */ - protected $state; + private $state; /** - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Version $version - * @param \Magento\Framework\App\State $state + * @param Config $config + * @param Version $version + * @param AppState $state */ - public function __construct( - \Magento\PageCache\Model\Config $config, - \Magento\Framework\App\PageCache\Version $version, - \Magento\Framework\App\State $state - ) { + public function __construct(Config $config, Version $version, AppState $state) + { $this->config = $config; $this->version = $version; $this->state = $state; } /** - * @param \Magento\Framework\App\FrontControllerInterface $subject - * @param callable $proceed - * @param \Magento\Framework\App\RequestInterface $request - * @return false|\Magento\Framework\App\Response\Http|\Magento\Framework\Controller\ResultInterface + * Perform response postprocessing + * + * @param FrontControllerInterface $subject + * @param ResponseInterface|ResultInterface $result + * @return ResponseHttp|ResultInterface + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDispatch( - \Magento\Framework\App\FrontControllerInterface $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { - $response = $proceed($request); - if ($this->config->getType() == \Magento\PageCache\Model\Config::VARNISH && $this->config->isEnabled() - && $response instanceof \Magento\Framework\App\Response\Http) { + public function afterDispatch(FrontControllerInterface $subject, $result) + { + if ($this->config->getType() == Config::VARNISH && $this->config->isEnabled() + && $result instanceof ResponseHttp + ) { $this->version->process(); - if ($this->state->getMode() == \Magento\Framework\App\State::MODE_DEVELOPER) { - $response->setHeader('X-Magento-Debug', 1); + + if ($this->state->getMode() == AppState::MODE_DEVELOPER) { + $result->setHeader('X-Magento-Debug', 1); } } - return $response; + + return $result; } } diff --git a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php index 0fcad45130d3ebb0dfe94ae8eeafbd885fb5e38b..d2ef015fb69272586576a335ce7df3c9d81acf59 100644 --- a/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php +++ b/app/code/Magento/PageCache/Model/Controller/Result/BuiltinPlugin.php @@ -5,47 +5,50 @@ */ namespace Magento\PageCache\Model\Controller\Result; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Kernel; +use Magento\Framework\App\State as AppState; +use Magento\Framework\Registry; +use Magento\Framework\Controller\ResultInterface; use Magento\Framework\App\Response\Http as ResponseHttp; +use Zend\Http\Header\HeaderInterface as HttpHeaderInterface; +use Magento\PageCache\Model\Cache\Type as CacheType; /** * Plugin for processing builtin cache + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BuiltinPlugin { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var Config */ - protected $config; + private $config; /** - * @var \Magento\Framework\App\PageCache\Kernel + * @var Kernel */ - protected $kernel; + private $kernel; /** - * @var \Magento\Framework\App\State + * @var AppState */ - protected $state; + private $state; /** - * @var \Magento\Framework\Registry + * @var Registry */ - protected $registry; + private $registry; /** - * Constructor - * - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Kernel $kernel - * @param \Magento\Framework\App\State $state - * @param \Magento\Framework\Registry $registry + * @param Config $config + * @param Kernel $kernel + * @param AppState $state + * @param Registry $registry */ - public function __construct( - \Magento\PageCache\Model\Config $config, - \Magento\Framework\App\PageCache\Kernel $kernel, - \Magento\Framework\App\State $state, - \Magento\Framework\Registry $registry - ) { + public function __construct(Config $config, Kernel $kernel, AppState $state, Registry $registry) + { $this->config = $config; $this->kernel = $kernel; $this->state = $state; @@ -53,43 +56,45 @@ class BuiltinPlugin } /** - * @param \Magento\Framework\Controller\ResultInterface $subject - * @param callable $proceed + * Perform result postprocessing + * + * @param ResultInterface $subject + * @param ResultInterface $result * @param ResponseHttp $response - * @return \Magento\Framework\Controller\ResultInterface + * @return ResultInterface + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundRenderResult( - \Magento\Framework\Controller\ResultInterface $subject, - \Closure $proceed, - ResponseHttp $response - ) { - $result = $proceed($response); + public function afterRenderResult(ResultInterface $subject, ResultInterface $result, ResponseHttp $response) + { $usePlugin = $this->registry->registry('use_page_cache_plugin'); - if (!$usePlugin || !$this->config->isEnabled() - || $this->config->getType() != \Magento\PageCache\Model\Config::BUILT_IN - ) { + + if (!$usePlugin || !$this->config->isEnabled() || $this->config->getType() != Config::BUILT_IN) { return $result; } - if ($this->state->getMode() == \Magento\Framework\App\State::MODE_DEVELOPER) { + if ($this->state->getMode() == AppState::MODE_DEVELOPER) { $cacheControlHeader = $response->getHeader('Cache-Control'); - if ($cacheControlHeader instanceof \Zend\Http\Header\HeaderInterface) { + + if ($cacheControlHeader instanceof HttpHeaderInterface) { $response->setHeader('X-Magento-Cache-Control', $cacheControlHeader->getFieldValue()); } + $response->setHeader('X-Magento-Cache-Debug', 'MISS', true); } $tagsHeader = $response->getHeader('X-Magento-Tags'); $tags = []; + if ($tagsHeader) { $tags = explode(',', $tagsHeader->getFieldValue()); $response->clearHeader('X-Magento-Tags'); } - $tags = array_unique(array_merge($tags, [\Magento\PageCache\Model\Cache\Type::CACHE_TAG])); - $response->setHeader('X-Magento-Tags', implode(',', $tags)); + $tags = array_unique(array_merge($tags, [CacheType::CACHE_TAG])); + $response->setHeader('X-Magento-Tags', implode(',', $tags)); $this->kernel->process($response); + return $result; } } diff --git a/app/code/Magento/PageCache/Model/Controller/Result/VarnishPlugin.php b/app/code/Magento/PageCache/Model/Controller/Result/VarnishPlugin.php index 19868a2261f1fd7d486fab066b1e4cc02704a6c5..368a6db80c7e01d7fdaafca710beb3470d870e33 100644 --- a/app/code/Magento/PageCache/Model/Controller/Result/VarnishPlugin.php +++ b/app/code/Magento/PageCache/Model/Controller/Result/VarnishPlugin.php @@ -5,7 +5,12 @@ */ namespace Magento\PageCache\Model\Controller\Result; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Version; +use Magento\Framework\App\State as AppState; +use Magento\Framework\Registry; use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Controller\ResultInterface; /** * Plugin for processing varnish cache @@ -13,74 +18,61 @@ use Magento\Framework\App\Response\Http as ResponseHttp; class VarnishPlugin { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var Config */ - protected $config; + private $config; /** - * @var \Magento\Framework\App\PageCache\Version + * @var Version */ - protected $version; + private $version; /** - * @var \Magento\Framework\App\PageCache\Kernel + * @var AppState */ - protected $kernel; + private $state; /** - * @var \Magento\Framework\App\State + * @var Registry */ - protected $state; + private $registry; /** - * @var \Magento\Framework\Registry + * @param Config $config + * @param Version $version + * @param AppState $state + * @param Registry $registry */ - protected $registry; - - /** - * Constructor - * - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Version $version - * @param \Magento\Framework\App\PageCache\Kernel $kernel - * @param \Magento\Framework\App\State $state - * @param \Magento\Framework\Registry $registry - */ - public function __construct( - \Magento\PageCache\Model\Config $config, - \Magento\Framework\App\PageCache\Version $version, - \Magento\Framework\App\PageCache\Kernel $kernel, - \Magento\Framework\App\State $state, - \Magento\Framework\Registry $registry - ) { + public function __construct(Config $config, Version $version, AppState $state, Registry $registry) + { $this->config = $config; $this->version = $version; - $this->kernel = $kernel; $this->state = $state; $this->registry = $registry; } /** - * @param \Magento\Framework\Controller\ResultInterface $subject - * @param callable $proceed + * Perform result postprocessing + * + * @param ResultInterface $subject + * @param ResultInterface $result * @param ResponseHttp $response - * @return \Magento\Framework\Controller\ResultInterface + * @return ResultInterface + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundRenderResult( - \Magento\Framework\Controller\ResultInterface $subject, - \Closure $proceed, - ResponseHttp $response - ) { - $proceed($response); + public function afterRenderResult(ResultInterface $subject, ResultInterface $result, ResponseHttp $response) + { $usePlugin = $this->registry->registry('use_page_cache_plugin'); - if ($this->config->getType() == \Magento\PageCache\Model\Config::VARNISH && $this->config->isEnabled() - && $usePlugin) { + + if ($this->config->getType() == Config::VARNISH && $this->config->isEnabled() && $usePlugin) { $this->version->process(); - if ($this->state->getMode() == \Magento\Framework\App\State::MODE_DEVELOPER) { + + if ($this->state->getMode() == AppState::MODE_DEVELOPER) { $response->setHeader('X-Magento-Debug', 1); } } - return $subject; + return $result; } } diff --git a/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/VarnishPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/VarnishPluginTest.php index 32328d7d027930b768683f9773366f6be9b92f84..a9b0e10307ae37d556f9c4cc96224f01fcd2bb9d 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/VarnishPluginTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/VarnishPluginTest.php @@ -3,148 +3,169 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\PageCache\Test\Unit\Model\App\FrontController; use Magento\PageCache\Model\App\FrontController\VarnishPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Version; +use Magento\Framework\App\State as AppState; +use Magento\Framework\App\FrontControllerInterface; +use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Controller\ResultInterface; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class VarnishPluginTest extends \PHPUnit_Framework_TestCase { /** * @var VarnishPlugin */ - protected $plugin; + private $plugin; /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerHelper */ - protected $configMock; + private $objectManagerHelper; /** - * @var \Magento\Framework\App\PageCache\Version|\PHPUnit_Framework_MockObject_MockObject + * @var Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $versionMock; + private $configMock; /** - * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + * @var Version|\PHPUnit_Framework_MockObject_MockObject */ - protected $stateMock; + private $versionMock; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var AppState|\PHPUnit_Framework_MockObject_MockObject */ - protected $responseMock; + private $stateMock; /** - * @var \Magento\Framework\App\FrontControllerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var FrontControllerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $frontControllerMock; + private $frontControllerMock; /** - * @var \Closure + * @var ResponseHttp|\PHPUnit_Framework_MockObject_MockObject */ - protected $closure; + private $responseMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $requestMock; + private $resultMock; - /** - * SetUp - */ protected function setUp() { - $this->configMock = $this->getMock(\Magento\PageCache\Model\Config::class, [], [], '', false); - $this->versionMock = $this->getMock(\Magento\Framework\App\PageCache\Version::class, [], [], '', false); - $this->stateMock = $this->getMock(\Magento\Framework\App\State::class, [], [], '', false); - $this->frontControllerMock = $this->getMock( - \Magento\Framework\App\FrontControllerInterface::class, - [], - [], - '', - false - ); - $this->requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class, [], [], '', false); - $this->responseMock = $this->getMock(\Magento\Framework\App\Response\Http::class, [], [], '', false); - $response = $this->responseMock; - $this->closure = function () use ($response) { - return $response; - }; - $this->plugin = new \Magento\PageCache\Model\App\FrontController\VarnishPlugin( - $this->configMock, - $this->versionMock, - $this->stateMock + $this->configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->versionMock = $this->getMockBuilder(Version::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stateMock = $this->getMockBuilder(AppState::class) + ->disableOriginalConstructor() + ->getMock(); + $this->frontControllerMock = $this->getMockBuilder(FrontControllerInterface::class) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder(ResponseHttp::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resultMock = $this->getMockBuilder(ResultInterface::class) + ->getMockForAbstractClass(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + VarnishPlugin::class, + [ + 'config' => $this->configMock, + 'version' => $this->versionMock, + 'state' => $this->stateMock + ] ); } /** - * @dataProvider dataProvider + * @param string $state + * @param int $countHeader + * + * @dataProvider afterDispatchDataProvider */ - public function testAroundDispatchReturnsCache($state, $countHeader, $countProcess, $countGetMode, $response) + public function testAfterDispatchReturnsCache($state, $countHeader) { - $this->configMock - ->expects($this->once()) + $this->configMock->expects(static::once()) ->method('isEnabled') - ->will($this->returnValue(true)); - $this->configMock - ->expects($this->once()) + ->willReturn(true); + $this->configMock->expects(static::once()) ->method('getType') - ->will($this->returnValue(\Magento\PageCache\Model\Config::VARNISH)); - $this->versionMock - ->expects($countProcess) + ->willReturn(Config::VARNISH); + $this->versionMock->expects(static::once()) ->method('process'); - $this->stateMock->expects($countGetMode) + $this->stateMock->expects(static::once()) ->method('getMode') - ->will($this->returnValue($state)); - $response->expects($countHeader) + ->willReturn($state); + $this->responseMock->expects(static::exactly($countHeader)) ->method('setHeader') ->with('X-Magento-Debug'); - $this->closure = function () use ($response) { - return $response; - }; + $this->assertSame( + $this->responseMock, + $this->plugin->afterDispatch($this->frontControllerMock, $this->responseMock) + ); + } - $this->plugin->aroundDispatch($this->frontControllerMock, $this->closure, $this->requestMock); + public function testAfterDispatchNotResponse() + { + $this->configMock->expects(static::once()) + ->method('isEnabled') + ->willReturn(true); + $this->configMock->expects(static::once()) + ->method('getType') + ->willReturn(Config::VARNISH); + $this->versionMock->expects(static::never()) + ->method('process'); + $this->stateMock->expects(static::never()) + ->method('getMode'); + $this->resultMock->expects(static::never()) + ->method('setHeader'); + + $this->assertSame( + $this->resultMock, + $this->plugin->afterDispatch($this->frontControllerMock, $this->resultMock) + ); } - /** - * @dataProvider dataProvider - */ - public function testAroundDispatchDisabled($state) + public function testAfterDispatchDisabled() { - $this->configMock - ->expects($this->any()) + $this->configMock->expects(static::any()) ->method('getType') - ->will($this->returnValue(null)); - $this->versionMock - ->expects($this->never()) + ->willReturn(null); + $this->versionMock->expects(static::never()) ->method('process'); - $this->stateMock->expects($this->any()) + $this->stateMock->expects(static::any()) ->method('getMode') - ->will($this->returnValue($state)); - $this->responseMock->expects($this->never()) + ->willReturn(AppState::MODE_DEVELOPER); + $this->responseMock->expects(static::never()) ->method('setHeader'); - $this->plugin->aroundDispatch($this->frontControllerMock, $this->closure, $this->requestMock); + + $this->assertSame( + $this->responseMock, + $this->plugin->afterDispatch($this->frontControllerMock, $this->responseMock) + ); } - public function dataProvider() + /** + * @return array + */ + public function afterDispatchDataProvider() { return [ - 'developer_mode' => [ - \Magento\Framework\App\State::MODE_DEVELOPER, - $this->once(), - $this->once(), - $this->once(), - $this->getMock(\Magento\Framework\App\Response\Http::class, [], [], '', false), - ], - 'production' => [ - \Magento\Framework\App\State::MODE_PRODUCTION, - $this->never(), - $this->never(), - $this->never(), - $this->getMock(\Magento\Framework\Controller\ResultInterface::class, [], [], '', false), - ], + 'developer_mode' => [AppState::MODE_DEVELOPER, 1], + 'production' => [AppState::MODE_PRODUCTION, 0] ]; } } diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php index 15934f3104b2305c00a8a0f2b23c3ab8717daba7..f0ba7b22dad2d5126b6b1481f8776f5bacc7843f 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/BuiltinPluginTest.php @@ -3,141 +3,195 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\PageCache\Test\Unit\Model\Controller\Result; +use Magento\PageCache\Model\Controller\Result\BuiltinPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Kernel; +use Magento\Framework\App\State as AppState; +use Magento\Framework\Registry; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\App\Response\Http as ResponseHttp; +use Zend\Http\Header\HeaderInterface as HttpHeaderInterface; +use Magento\PageCache\Model\Cache\Type as CacheType; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class BuiltinPluginTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\PageCache\Model\Controller\Result\BuiltinPlugin + * @var BuiltinPlugin + */ + private $plugin; + + /** + * @var ObjectManagerHelper */ - protected $plugin; + private $objectManagerHelper; /** - * @var \Magento\Framework\Controller\ResultInterface + * @var Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $subject; + private $configMock; /** - * @var \Closure + * @var Kernel|\PHPUnit_Framework_MockObject_MockObject */ - protected $closure; + private $kernelMock; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var AppState|\PHPUnit_Framework_MockObject_MockObject */ - protected $response; + private $stateMock; /** - * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + * @var Registry|\PHPUnit_Framework_MockObject_MockObject */ - protected $registry; + private $registryMock; /** - * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $state; + private $resultMock; /** - * @var \Zend\Http\Header\HeaderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ResponseHttp|\PHPUnit_Framework_MockObject_MockObject */ - protected $header; + private $responseMock; /** - * @var \Magento\Framework\App\PageCache\Kernel|\PHPUnit_Framework_MockObject_MockObject + * @var HttpHeaderInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $kernel; + private $httpHeaderMock; protected function setUp() { - $result = $this->getMock(\Magento\Framework\Controller\ResultInterface::class, [], [], '', false); - $this->closure = function() use ($result) { - return $result; - }; - - $this->header = $this->getMock(\Zend\Http\Header\HeaderInterface::class, [], [], '', false); - $this->subject = $this->getMock(\Magento\Framework\Controller\ResultInterface::class, [], [], '', false); - $this->response = $this->getMock( - \Magento\Framework\App\Response\Http::class, - ['getHeader', 'clearHeader', 'setHeader'], - [], - '', - false - ); - $this->response->expects($this->any())->method('getHeader')->willReturnMap( + $this->configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->kernelMock = $this->getMockBuilder(Kernel::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stateMock = $this->getMockBuilder(AppState::class) + ->disableOriginalConstructor() + ->getMock(); + $this->registryMock = $this->getMockBuilder(Registry::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resultMock = $this->getMockBuilder(ResultInterface::class) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder(ResponseHttp::class) + ->disableOriginalConstructor() + ->getMock(); + $this->httpHeaderMock = $this->getMockBuilder(HttpHeaderInterface::class) + ->getMockForAbstractClass(); + + $this->responseMock->expects(static::any()) + ->method('getHeader') + ->willReturnMap( + [ + ['X-Magento-Tags', $this->httpHeaderMock], + ['Cache-Control', $this->httpHeaderMock] + ] + ); + $this->configMock->expects(static::any()) + ->method('isEnabled') + ->willReturn(true); + $this->configMock->expects(static::any()) + ->method('getType') + ->willReturn(Config::BUILT_IN); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + BuiltinPlugin::class, [ - ['X-Magento-Tags', $this->header], - ['Cache-Control', $this->header] - ] - ); - - $this->registry = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); - - $config = $this->getMock(\Magento\PageCache\Model\Config::class, ['isEnabled', 'getType'], [], '', false); - $config->expects($this->any())->method('isEnabled')->willReturn(true); - $config->expects($this->any())->method('getType')->willReturn(\Magento\PageCache\Model\Config::BUILT_IN); - - $this->kernel = $this->getMock(\Magento\Framework\App\PageCache\Kernel::class, [], [], '', false); - - $this->state = $this->getMock(\Magento\Framework\App\State::class, [], [], '', false); - $this->plugin = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( - \Magento\PageCache\Model\Controller\Result\BuiltinPlugin::class, - [ - 'registry' => $this->registry, - 'config' => $config, - 'kernel' => $this->kernel, - 'state' => $this->state + 'registry' => $this->registryMock, + 'config' => $this->configMock, + 'kernel' => $this->kernelMock, + 'state' => $this->stateMock ] ); } - public function testAroundResultWithoutPlugin() + public function testAfterResultWithoutPlugin() { - $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(false); - $this->kernel->expects($this->never())->method('process')->with($this->response); + $this->registryMock->expects(static::once()) + ->method('registry') + ->with('use_page_cache_plugin') + ->willReturn(false); + $this->kernelMock->expects(static::never()) + ->method('process') + ->with($this->responseMock); + $this->assertSame( - call_user_func($this->closure), - $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response) + $this->resultMock, + $this->plugin->afterRenderResult($this->resultMock, $this->resultMock, $this->responseMock) ); } - public function testAroundResultWithPlugin() + public function testAfterResultWithPlugin() { - $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(true); - $this->state->expects($this->once())->method('getMode')->willReturn(null); - $this->header->expects($this->any())->method('getFieldValue')->willReturn('tag,tag'); - $this->response->expects($this->once())->method('clearHeader')->with('X-Magento-Tags'); - $this->response->expects($this->once())->method('setHeader')->with( - 'X-Magento-Tags', - 'tag,' . \Magento\PageCache\Model\Cache\Type::CACHE_TAG + $this->registryMock->expects(static::once()) + ->method('registry') + ->with('use_page_cache_plugin') + ->willReturn(true); + $this->stateMock->expects(static::once()) + ->method('getMode') + ->willReturn(null); + $this->httpHeaderMock->expects(static::any()) + ->method('getFieldValue') + ->willReturn('tag,tag'); + $this->responseMock->expects(static::once()) + ->method('clearHeader') + ->with('X-Magento-Tags'); + $this->responseMock->expects(static::once()) + ->method('setHeader') + ->with('X-Magento-Tags', 'tag,' . CacheType::CACHE_TAG); + $this->kernelMock->expects(static::once()) + ->method('process') + ->with($this->responseMock); + + $this->assertSame( + $this->resultMock, + $this->plugin->afterRenderResult($this->resultMock, $this->resultMock, $this->responseMock) ); - $this->kernel->expects($this->once())->method('process')->with($this->response); - $result = call_user_func($this->closure); - $this->assertSame($result, $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response)); } - public function testAroundResultWithPluginDeveloperMode() + public function testAfterResultWithPluginDeveloperMode() { - $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin')->willReturn(true); - $this->state->expects($this->once())->method('getMode') - ->willReturn(\Magento\Framework\App\State::MODE_DEVELOPER); - - $this->header->expects($this->any())->method('getFieldValue')->willReturnOnConsecutiveCalls('test', 'tag,tag2'); + $this->registryMock->expects(static::once()) + ->method('registry') + ->with('use_page_cache_plugin') + ->willReturn(true); + $this->stateMock->expects(static::once()) + ->method('getMode') + ->willReturn(AppState::MODE_DEVELOPER); + $this->httpHeaderMock->expects(static::any()) + ->method('getFieldValue') + ->willReturnOnConsecutiveCalls('test', 'tag,tag2'); + $this->responseMock->expects(static::any()) + ->method('setHeader') + ->withConsecutive( + ['X-Magento-Cache-Control', 'test'], + ['X-Magento-Cache-Debug', 'MISS', true], + ['X-Magento-Tags', 'tag,tag2,' . CacheType::CACHE_TAG] + ); + $this->responseMock->expects(static::once()) + ->method('clearHeader') + ->with('X-Magento-Tags'); + $this->registryMock->expects(static::once()) + ->method('registry') + ->with('use_page_cache_plugin') + ->willReturn(true); + $this->kernelMock->expects(static::once()) + ->method('process') + ->with($this->responseMock); - $this->response->expects($this->any())->method('setHeader')->withConsecutive( - ['X-Magento-Cache-Control', 'test'], - ['X-Magento-Cache-Debug', 'MISS', true], - ['X-Magento-Tags', 'tag,tag2,' . \Magento\PageCache\Model\Cache\Type::CACHE_TAG] + $this->assertSame( + $this->resultMock, + $this->plugin->afterRenderResult($this->resultMock, $this->resultMock, $this->responseMock) ); - - $this->response->expects($this->once())->method('clearHeader')->with('X-Magento-Tags'); - $this->registry->expects($this->once())->method('registry')->with('use_page_cache_plugin') - ->will($this->returnValue(true)); - $this->kernel->expects($this->once())->method('process')->with($this->response); - - $result = call_user_func($this->closure); - $this->assertSame($result, $this->plugin->aroundRenderResult($this->subject, $this->closure, $this->response)); } } diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/VarnishPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/VarnishPluginTest.php index e58aae1668ff8dbaeda016465d126b63c1fc4924..a54dc5bacb5a6dc31dc317622c74a9f7b18ba2d0 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/VarnishPluginTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/Controller/Result/VarnishPluginTest.php @@ -5,72 +5,135 @@ */ namespace Magento\PageCache\Test\Unit\Model\Controller\Result; +use Magento\PageCache\Model\Controller\Result\VarnishPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\PageCache\Model\Config; +use Magento\Framework\App\PageCache\Version; +use Magento\Framework\App\State as AppState; +use Magento\Framework\Registry; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\App\Response\Http as ResponseHttp; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class VarnishPluginTest extends \PHPUnit_Framework_TestCase { /** - * @param bool $usePlugin - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $setCacheDebugHeaderCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $getModeCount - * @param \PHPUnit_Framework_MockObject_Matcher_InvokedCount $processCount - * @dataProvider dataProvider + * @var VarnishPlugin */ - public function testAroundResult($usePlugin, $setCacheDebugHeaderCount, $getModeCount, $processCount) - { - /** @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject $response */ - $response = $this->getMock(\Magento\Framework\App\Response\Http::class, [], [], '', false); - $response->expects($setCacheDebugHeaderCount)->method('setHeader') - ->with('X-Magento-Debug', 1); + private $plugin; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; - /** @var \Magento\Framework\Controller\ResultInterface $result */ - $result = $this->getMock(\Magento\Framework\Controller\ResultInterface::class, [], [], '', false); - $closure = function () use ($result) { - return $result; - }; + /** + * @var Version|\PHPUnit_Framework_MockObject_MockObject + */ + private $versionMock; - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject $registry */ - $registry = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); - $registry->expects($this->once())->method('registry')->with('use_page_cache_plugin') - ->will($this->returnValue($usePlugin)); + /** + * @var AppState|\PHPUnit_Framework_MockObject_MockObject + */ + private $appStateMock; - /** @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->getMock(\Magento\PageCache\Model\Config::class, [], [], '', false); - $config->expects($this->once())->method('isEnabled')->will($this->returnValue(true)); - $config->expects($this->once())->method('getType') - ->will($this->returnValue(\Magento\PageCache\Model\Config::VARNISH)); + /** + * @var Registry|\PHPUnit_Framework_MockObject_MockObject + */ + private $registryMock; - /** @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject $state */ - $state = $this->getMock(\Magento\Framework\App\State::class, [], [], '', false); - $state->expects($getModeCount)->method('getMode') - ->will($this->returnValue(\Magento\Framework\App\State::MODE_DEVELOPER)); + /** + * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $resultMock; - /** @var \Magento\Framework\Controller\ResultInterface|\PHPUnit_Framework_MockObject_MockObject $subject */ - $subject = $this->getMock(\Magento\Framework\Controller\ResultInterface::class, [], [], '', false); + /** + * @var ResponseHttp|\PHPUnit_Framework_MockObject_MockObject + */ + private $responseMock; - /** @var \Magento\Framework\App\PageCache\Version|\PHPUnit_Framework_MockObject_MockObject $version */ - $version = $this->getMock(\Magento\Framework\App\PageCache\Version::class, [], [], '', false); - $version->expects($processCount)->method('process'); + protected function setUp() + { + $this->configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->versionMock = $this->getMockBuilder(Version::class) + ->disableOriginalConstructor() + ->getMock(); + $this->appStateMock = $this->getMockBuilder(AppState::class) + ->disableOriginalConstructor() + ->getMock(); + $this->registryMock = $this->getMockBuilder(Registry::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resultMock = $this->getMockBuilder(ResultInterface::class) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder(ResponseHttp::class) + ->disableOriginalConstructor() + ->getMock(); - /** @var \Magento\PageCache\Model\Controller\Result\VarnishPlugin $plugin */ - $plugin = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( - \Magento\PageCache\Model\Controller\Result\VarnishPlugin::class, + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + VarnishPlugin::class, [ - 'registry' => $registry, - 'config' => $config, - 'state' => $state, - 'version' => $version + 'registry' => $this->registryMock, + 'config' => $this->configMock, + 'state' => $this->appStateMock, + 'version' => $this->versionMock ] ); - $this->assertSame($subject, $plugin->aroundRenderResult($subject, $closure, $response)); + } + + /** + * @param bool $usePlugin + * @param int $setCacheDebugHeaderCount + * @param int $getModeCount + * @param int $processCount + * + * @dataProvider afterRenderResultDataProvider + */ + public function testAfterRenderResult($usePlugin, $setCacheDebugHeaderCount, $getModeCount, $processCount) + { + $this->responseMock->expects(static::exactly($setCacheDebugHeaderCount)) + ->method('setHeader') + ->with('X-Magento-Debug', 1); + $this->registryMock->expects(static::once()) + ->method('registry') + ->with('use_page_cache_plugin') + ->willReturn($usePlugin); + $this->configMock->expects(static::once()) + ->method('isEnabled') + ->willReturn(true); + $this->configMock->expects(static::once()) + ->method('getType') + ->willReturn(Config::VARNISH); + $this->appStateMock->expects(static::exactly($getModeCount)) + ->method('getMode') + ->willReturn(AppState::MODE_DEVELOPER); + $this->versionMock->expects(static::exactly($processCount)) + ->method('process'); + + $this->assertSame( + $this->resultMock, + $this->plugin->afterRenderResult($this->resultMock, $this->resultMock, $this->responseMock) + ); } /** * @return array */ - public function dataProvider() + public function afterRenderResultDataProvider() { return [ - [true, $this->once(), $this->once(), $this->once()], - [false, $this->never(), $this->never(), $this->never()] + [true, 1, 1, 1], + [false, 0, 0, 0] ]; } } diff --git a/app/code/Magento/Paypal/Block/Adminhtml/Store/SwitcherPlugin.php b/app/code/Magento/Paypal/Block/Adminhtml/Store/SwitcherPlugin.php index 3af4493e61e1f869a9c5288c076f609add10b4fe..23b7fa31fb578056dba1e4e9ea440dd0ec53bc63 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/Store/SwitcherPlugin.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/Store/SwitcherPlugin.php @@ -5,26 +5,28 @@ */ namespace Magento\Paypal\Block\Adminhtml\Store; +use Magento\Backend\Block\Store\Switcher as StoreSwitcherBlock; +use Magento\Paypal\Model\Config\StructurePlugin as ConfigStructurePlugin; + +/** + * Plugin for \Magento\Backend\Block\Store\Switcher + */ class SwitcherPlugin { /** * Remove country request param from url * - * @param \Magento\Backend\Block\Store\Switcher $subject - * @param \Closure $proceed + * @param StoreSwitcherBlock $subject * @param string $route * @param array $params - * @return string + * @return array */ - public function aroundGetUrl( - \Magento\Backend\Block\Store\Switcher $subject, - \Closure $proceed, - $route = '', - $params = [] - ) { - if ($subject->getRequest()->getParam(\Magento\Paypal\Model\Config\StructurePlugin::REQUEST_PARAM_COUNTRY)) { - $params[\Magento\Paypal\Model\Config\StructurePlugin::REQUEST_PARAM_COUNTRY] = null; + public function beforeGetUrl(StoreSwitcherBlock $subject, $route = '', $params = []) + { + if ($subject->getRequest()->getParam(ConfigStructurePlugin::REQUEST_PARAM_COUNTRY)) { + $params[ConfigStructurePlugin::REQUEST_PARAM_COUNTRY] = null; } - return $proceed($route, $params); + + return [$route, $params]; } } diff --git a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php index 2d49ddfcb3d01955fefd089052f4b444d9c91134..a6288b8fc685c45aa823e807433c1df896c5dc9f 100644 --- a/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php +++ b/app/code/Magento/Paypal/Model/Config/Structure/Element/FieldPlugin.php @@ -5,39 +5,45 @@ */ namespace Magento\Paypal\Model\Config\Structure\Element; +use Magento\Framework\App\RequestInterface; +use Magento\Config\Model\Config\Structure\Element\Field as FieldConfigStructure; +use Magento\Paypal\Model\Config\StructurePlugin as ConfigStructurePlugin; + +/** + * Plugin for \Magento\Config\Model\Config\Structure\Element\Field + */ class FieldPlugin { /** - * @var \Magento\Framework\App\RequestInterface + * @var RequestInterface */ - protected $_request; + private $request; /** - * @param \Magento\Framework\App\RequestInterface $request + * @param RequestInterface $request */ - public function __construct(\Magento\Framework\App\RequestInterface $request) + public function __construct(RequestInterface $request) { - $this->_request = $request; + $this->request = $request; } /** * Get original configPath (not changed by PayPal configuration inheritance) * - * @param \Magento\Config\Model\Config\Structure\Element\Field $subject - * @param \Closure $proceed + * @param FieldConfigStructure $subject + * @param string|null $result * @return string|null */ - public function aroundGetConfigPath( - \Magento\Config\Model\Config\Structure\Element\Field $subject, - \Closure $proceed - ) { - $configPath = $proceed(); - if (!isset($configPath) && $this->_request->getParam('section') == 'payment') { - $configPath = preg_replace('@^(' . implode( - '|', - \Magento\Paypal\Model\Config\StructurePlugin::getPaypalConfigCountries(true) - ) . ')/@', 'payment/', $subject->getPath()); + public function afterGetConfigPath(FieldConfigStructure $subject, $result) + { + if (!$result && $this->request->getParam('section') == 'payment') { + $result = preg_replace( + '@^(' . implode('|', ConfigStructurePlugin::getPaypalConfigCountries(true)) . ')/@', + 'payment/', + $subject->getPath() + ); } - return $configPath; + + return $result; } } diff --git a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php index 52f46a8411c0257d1f894ce0693d6b77d8dd35c0..f45a7948906253ec53a4dd710b37825363f39877 100644 --- a/app/code/Magento/Paypal/Model/Config/StructurePlugin.php +++ b/app/code/Magento/Paypal/Model/Config/StructurePlugin.php @@ -11,6 +11,9 @@ use Magento\Config\Model\Config\Structure\Element\Section; use Magento\Config\Model\Config\Structure\ElementInterface; use Magento\Paypal\Helper\Backend as BackendHelper; +/** + * Plugin for \Magento\Config\Model\Config\Structure + */ class StructurePlugin { /** @@ -21,17 +24,17 @@ class StructurePlugin /** * @var BackendHelper */ - protected $_helper; + private $backendHelper; /** * @var ScopeDefiner */ - protected $_scopeDefiner; + private $scopeDefiner; /** * @var string[] */ - private static $_paypalConfigCountries = [ + private static $paypalConfigCountries = [ 'payment_us', 'payment_ca', 'payment_au', @@ -49,12 +52,10 @@ class StructurePlugin * @param ScopeDefiner $scopeDefiner * @param BackendHelper $helper */ - public function __construct( - ScopeDefiner $scopeDefiner, - BackendHelper $helper - ) { - $this->_scopeDefiner = $scopeDefiner; - $this->_helper = $helper; + public function __construct(ScopeDefiner $scopeDefiner, BackendHelper $helper) + { + $this->scopeDefiner = $scopeDefiner; + $this->backendHelper = $helper; } /** @@ -65,10 +66,12 @@ class StructurePlugin */ public static function getPaypalConfigCountries($addOther = false) { - $countries = self::$_paypalConfigCountries; + $countries = self::$paypalConfigCountries; + if ($addOther) { $countries[] = 'payment_other'; } + return $countries; } @@ -78,39 +81,45 @@ class StructurePlugin * @param Structure $subject * @param \Closure $proceed * @param array $pathParts - * @return ElementInterface + * @return ElementInterface|null + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundGetElementByPathParts( - Structure $subject, - \Closure $proceed, - array $pathParts - ) { + public function aroundGetElementByPathParts(Structure $subject, \Closure $proceed, array $pathParts) + { $isSectionChanged = $pathParts[0] == 'payment'; + if ($isSectionChanged) { - $requestedCountrySection = 'payment_' . strtolower($this->_helper->getConfigurationCountryCode()); + $requestedCountrySection = 'payment_' . strtolower($this->backendHelper->getConfigurationCountryCode()); + if (in_array($requestedCountrySection, self::getPaypalConfigCountries())) { $pathParts[0] = $requestedCountrySection; } else { $pathParts[0] = 'payment_other'; } } - /** @var ElementInterface $result */ + $result = $proceed($pathParts); - if ($isSectionChanged && isset($result)) { + + if ($isSectionChanged && $result) { if ($result instanceof Section) { $this->restructurePayments($result); - $result->setData(array_merge( - $result->getData(), - ['showInDefault' => true, 'showInWebsite' => true, 'showInStore' => true] - ), $this->_scopeDefiner->getScope()); + $result->setData( + array_merge( + $result->getData(), + ['showInDefault' => true, 'showInWebsite' => true, 'showInStore' => true] + ), + $this->scopeDefiner->getScope() + ); } } + return $result; } /** - * Changes payment config structure. + * Change payment config structure + * * Groups which have `displayIn` element, transfer to appropriate group. * Groups without `displayIn` transfer to other payment methods group. * @@ -139,7 +148,7 @@ class StructurePlugin } $configuration['children'] = $sectionMap; - $result->setData($configuration, $this->_scopeDefiner->getScope()); + $result->setData($configuration, $this->scopeDefiner->getScope()); } /** diff --git a/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php b/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php index a171cd5628f0fb90dcb57ec521d5c47533f9ccc7..f2b650b95e9e8cdfaa86f2bf7e398f9fad74abb2 100644 --- a/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php +++ b/app/code/Magento/Paypal/Model/Method/Checks/SpecificationPlugin.php @@ -11,49 +11,54 @@ use Magento\Paypal\Model\Config; use Magento\Paypal\Model\Billing\AgreementFactory; use Magento\Quote\Model\Quote; +/** + * Plugin for \Magento\Payment\Model\Checks\Composite + */ class SpecificationPlugin { /** * @var AgreementFactory */ - protected $_agreementFactory; + private $agreementFactory; /** * @param AgreementFactory $agreementFactory */ public function __construct(AgreementFactory $agreementFactory) { - $this->_agreementFactory = $agreementFactory; + $this->agreementFactory = $agreementFactory; } /** * Override check for Billing Agreements * * @param SpecificationInterface $specification - * @param \Closure $proceed + * @param bool $result * @param MethodInterface $paymentMethod * @param Quote $quote * @return bool + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundIsApplicable( + public function afterIsApplicable( SpecificationInterface $specification, - \Closure $proceed, + $result, MethodInterface $paymentMethod, Quote $quote ) { - $originallyIsApplicable = $proceed($paymentMethod, $quote); - if (!$originallyIsApplicable) { + if (!$result) { return false; } if ($paymentMethod->getCode() == Config::METHOD_BILLING_AGREEMENT) { if ($quote->getCustomerId()) { - $availableBA = $this->_agreementFactory->create()->getAvailableCustomerBillingAgreements( + $availableBA = $this->agreementFactory->create()->getAvailableCustomerBillingAgreements( $quote->getCustomerId() ); + return count($availableBA) > 0; } + return false; } diff --git a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/Store/SwitcherPluginTest.php b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/Store/SwitcherPluginTest.php index 320e89d567b9cac8155c45885671d20ed569ef99..a97fb0ad2a6fcc5723635b980571559e82742e70 100644 --- a/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/Store/SwitcherPluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Block/Adminhtml/Store/SwitcherPluginTest.php @@ -5,42 +5,72 @@ */ namespace Magento\Paypal\Test\Unit\Block\Adminhtml\Store; +use Magento\Paypal\Block\Adminhtml\Store\SwitcherPlugin as StoreSwitcherBlockPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Backend\Block\Store\Switcher as StoreSwitcherBlock; +use Magento\Framework\App\RequestInterface; +use Magento\Paypal\Model\Config\StructurePlugin as ConfigStructurePlugin; + class SwitcherPluginTest extends \PHPUnit_Framework_TestCase { /** - * @var SwitcherPlugin + * @var StoreSwitcherBlockPlugin + */ + private $plugin; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var StoreSwitcherBlock|\PHPUnit_Framework_MockObject_MockObject */ - protected $_model; + private $subjectMock; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; protected function setUp() { - $this->_model = new \Magento\Paypal\Block\Adminhtml\Store\SwitcherPlugin(); + $this->subjectMock = $this->getMockBuilder(StoreSwitcherBlock::class) + ->disableOriginalConstructor() + ->getMock(); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->getMockForAbstractClass(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject(StoreSwitcherBlockPlugin::class); } /** - * @param null|string $countryParam + * @param string|null $countryParam * @param array $getUrlParams - * @dataProvider aroundGetUrlDataProvider + * + * @dataProvider beforeGetUrlDataProvider */ - public function testAroundGetUrl($countryParam, $getUrlParams) + public function testBeforeGetUrl($countryParam, $getUrlParams) { - $subjectRequest = $this->getMockForAbstractClass(\Magento\Framework\App\RequestInterface::class); - $subjectRequest->expects($this->once()) + $this->requestMock->expects(static::once()) ->method('getParam') - ->with(\Magento\Paypal\Model\Config\StructurePlugin::REQUEST_PARAM_COUNTRY) - ->will($this->returnValue($countryParam)); - $subject = $this->getMock(\Magento\Backend\Block\Store\Switcher::class, ['getRequest'], [], '', false); - $subject->expects($this->any())->method('getRequest')->will($this->returnValue($subjectRequest)); - $getUrl = function ($route, $params) { - return [$route, $params]; - }; - $this->assertEquals(['', $getUrlParams], $this->_model->aroundGetUrl($subject, $getUrl, '', [])); + ->with(ConfigStructurePlugin::REQUEST_PARAM_COUNTRY) + ->willReturn($countryParam); + $this->subjectMock->expects(static::any()) + ->method('getRequest') + ->willReturn($this->requestMock); + + $this->assertEquals(['', $getUrlParams], $this->plugin->beforeGetUrl($this->subjectMock, '', [])); } - public function aroundGetUrlDataProvider() + /** + * @return array + */ + public function beforeGetUrlDataProvider() { return [ - ['any value', [\Magento\Paypal\Model\Config\StructurePlugin::REQUEST_PARAM_COUNTRY => null]], + ['any value', [ConfigStructurePlugin::REQUEST_PARAM_COUNTRY => null]], [null, []] ]; } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php index e630e3c57207c113e502da623dd77f116de6bc53..48314c28ceb983b5ca660aa6e3e34345cc0d1cd3 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Structure/Element/FieldPluginTest.php @@ -3,80 +3,96 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Paypal\Test\Unit\Model\Config\Structure\Element; +use Magento\Paypal\Model\Config\Structure\Element\FieldPlugin as FieldConfigStructurePlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\App\RequestInterface; +use Magento\Config\Model\Config\Structure\Element\Field as FieldConfigStructureMock; + class FieldPluginTest extends \PHPUnit_Framework_TestCase { - /** @var FieldPlugin */ - protected $model; + /** + * @var FieldConfigStructurePlugin + */ + private $plugin; - /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $request; + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; - /** @var \Magento\Config\Model\Config\Structure\Element\Field|\PHPUnit_Framework_MockObject_MockObject */ - protected $subject; + /** + * @var FieldConfigStructureMock|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; protected function setUp() { - $this->request = $this->getMockForAbstractClass(\Magento\Framework\App\RequestInterface::class); - $this->subject = $this->getMock(\Magento\Config\Model\Config\Structure\Element\Field::class, [], [], '', false); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->getMockForAbstractClass(); + $this->subjectMock = $this->getMockBuilder(FieldConfigStructureMock::class) + ->disableOriginalConstructor() + ->getMock(); - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->model = $helper->getObject( - \Magento\Paypal\Model\Config\Structure\Element\FieldPlugin::class, - ['request' => $this->request] + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + FieldConfigStructurePlugin::class, + ['request' => $this->requestMock] ); } public function testAroundGetConfigPathHasResult() { $someResult = 'some result'; - $callback = function () use ($someResult) { - return $someResult; - }; - $this->assertEquals($someResult, $this->model->aroundGetConfigPath($this->subject, $callback)); + + $this->assertEquals($someResult, $this->plugin->afterGetConfigPath($this->subjectMock, $someResult)); } public function testAroundGetConfigPathNonPaymentSection() { - $callback = function () { - return null; - }; - $this->request->expects($this->once()) + $this->requestMock->expects(static::once()) ->method('getParam') ->with('section') - ->will($this->returnValue('non-payment')); - $this->assertNull($this->model->aroundGetConfigPath($this->subject, $callback)); + ->willReturn('non-payment'); + + $this->assertNull($this->plugin->afterGetConfigPath($this->subjectMock, null)); } /** * @param string $subjectPath * @param string $expectedConfigPath - * @dataProvider aroundGetConfigPathDataProvider + * + * @dataProvider afterGetConfigPathDataProvider */ public function testAroundGetConfigPath($subjectPath, $expectedConfigPath) { - $callback = function () { - return null; - }; - $this->request->expects($this->once()) + $this->requestMock->expects(static::once()) ->method('getParam') ->with('section') - ->will($this->returnValue('payment')); - $this->subject->expects($this->once()) + ->willReturn('payment'); + $this->subjectMock->expects(static::once()) ->method('getPath') - ->will($this->returnValue($subjectPath)); - $this->assertEquals($expectedConfigPath, $this->model->aroundGetConfigPath($this->subject, $callback)); + ->willReturn($subjectPath); + + $this->assertEquals($expectedConfigPath, $this->plugin->afterGetConfigPath($this->subjectMock, null)); } - public function aroundGetConfigPathDataProvider() + /** + * @return array + */ + public function afterGetConfigPathDataProvider() { return [ ['payment_us/group/field', 'payment/group/field'], ['payment_other/group/field', 'payment/group/field'], ['payment_us', 'payment_us'], - ['payment_wrong_country/group/field', 'payment_wrong_country/group/field'], + ['payment_wrong_country/group/field', 'payment_wrong_country/group/field'] ]; } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php index 4479f0a1233515039e499f73cc4595c5369007f7..63abcd660425abd7173fbd2528e047498c7cce62 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/StructurePluginTest.php @@ -3,45 +3,80 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Paypal\Test\Unit\Model\Config; -use Magento\Paypal\Model\Config\StructurePlugin; +use Magento\Paypal\Model\Config\StructurePlugin as ConfigStructurePlugin; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Config\Model\Config\ScopeDefiner as ConfigScopeDefiner; +use Magento\Paypal\Helper\Backend as BackendHelper; +use Magento\Config\Model\Config\Structure as ConfigStructure; +use Magento\Config\Model\Config\Structure\ElementInterface as ElementConfigStructure; class StructurePluginTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Paypal\Model\Config\StructurePlugin */ - protected $_model; + /** + * @var ConfigStructurePlugin + */ + private $plugin; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var ConfigScopeDefiner|\PHPUnit_Framework_MockObject_MockObject + */ + private $configScopeDefinerMock; + + /** + * @var BackendHelper|\PHPUnit_Framework_MockObject_MockObject + */ + private $backendHelperMock; - /** @var \Magento\Config\Model\Config\ScopeDefiner|\PHPUnit_Framework_MockObject_MockObject */ - protected $_scopeDefiner; + /** + * @var ConfigStructure|\PHPUnit_Framework_MockObject_MockObject + */ + private $configStructureMock; - /** @var \Magento\Paypal\Helper\Backend|\PHPUnit_Framework_MockObject_MockObject */ - protected $_helper; + /** + * @var ElementConfigStructure|\PHPUnit_Framework_MockObject_MockObject + */ + private $elementConfigStructureMock; protected function setUp() { - $this->_scopeDefiner = $this->getMock(\Magento\Config\Model\Config\ScopeDefiner::class, [], [], '', false); - $this->_helper = $this->getMock(\Magento\Paypal\Helper\Backend::class, [], [], '', false); - - $objectManagerHelper = new ObjectManagerHelper($this); - $this->_model = $objectManagerHelper->getObject( - \Magento\Paypal\Model\Config\StructurePlugin::class, - ['scopeDefiner' => $this->_scopeDefiner, 'helper' => $this->_helper] + $this->configScopeDefinerMock = $this->getMockBuilder(ConfigScopeDefiner::class) + ->disableOriginalConstructor() + ->getMock(); + $this->backendHelperMock = $this->getMockBuilder(BackendHelper::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configStructureMock = $this->getMockBuilder(ConfigStructure::class) + ->disableOriginalConstructor() + ->getMock(); + $this->elementConfigStructureMock = $this->getMockBuilder(ElementConfigStructure::class) + ->getMockForAbstractClass(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + ConfigStructurePlugin::class, + ['scopeDefiner' => $this->configScopeDefinerMock, 'helper' => $this->backendHelperMock] ); } public function testGetPaypalConfigCountriesWithOther() { - $countries = StructurePlugin::getPaypalConfigCountries(true); + $countries = ConfigStructurePlugin::getPaypalConfigCountries(true); + $this->assertContains('payment_us', $countries); $this->assertContains('payment_other', $countries); } public function testGetPaypalConfigCountries() { - $countries = StructurePlugin::getPaypalConfigCountries(false); + $countries = ConfigStructurePlugin::getPaypalConfigCountries(false); + $this->assertContains('payment_us', $countries); $this->assertNotContains('payment_other', $countries); } @@ -49,20 +84,25 @@ class StructurePluginTest extends \PHPUnit_Framework_TestCase /** * @param array $pathParts * @param bool $returnResult + * * @dataProvider aroundGetElementByPathPartsNonPaymentDataProvider */ public function testAroundGetElementByPathPartsNonPayment($pathParts, $returnResult) { - $result = $returnResult - ? $this->getMockForAbstractClass(\Magento\Config\Model\Config\Structure\ElementInterface::class) - : null; - $this->_aroundGetElementByPathPartsAssertResult( + $result = $returnResult ? $this->elementConfigStructureMock : null; + $proceed = function () use ($result) { + return $result; + }; + + $this->assertSame( $result, - $this->_getElementByPathPartsCallback($pathParts, $result), - $pathParts + $this->plugin->aroundGetElementByPathParts($this->configStructureMock, $proceed, $pathParts) ); } + /** + * @return array + */ public function aroundGetElementByPathPartsNonPaymentDataProvider() { return [ @@ -76,146 +116,62 @@ class StructurePluginTest extends \PHPUnit_Framework_TestCase /** * @param array $pathParts * @param string $countryCode - * @param array $expectedPathParts + * * @dataProvider aroundGetElementByPathPartsDataProvider */ - public function testAroundGetElementByPathPartsNoResult($pathParts, $countryCode, $expectedPathParts) + public function testAroundGetElementByPathPartsNoResult($pathParts, $countryCode) { - $this->_getElementByPathPartsPrepareHelper($countryCode); - $this->_aroundGetElementByPathPartsAssertResult( + $proceed = function () { + return null; + }; + + $this->backendHelperMock->expects(static::once()) + ->method('getConfigurationCountryCode') + ->willReturn($countryCode); + + $this->assertEquals( null, - $this->_getElementByPathPartsCallback($expectedPathParts, null), - $pathParts + $this->plugin->aroundGetElementByPathParts($this->configStructureMock, $proceed, $pathParts) ); } /** * @param array $pathParts * @param string $countryCode - * @param array $expectedPathParts + * * @dataProvider aroundGetElementByPathPartsDataProvider */ - public function testAroundGetElementByPathParts($pathParts, $countryCode, $expectedPathParts) + public function testAroundGetElementByPathParts($pathParts, $countryCode) { - $this->_getElementByPathPartsPrepareHelper($countryCode); - $result = $this->getMockForAbstractClass(\Magento\Config\Model\Config\Structure\ElementInterface::class); - $this->_aroundGetElementByPathPartsAssertResult( - $result, - $this->_getElementByPathPartsCallback($expectedPathParts, $result), - $pathParts + $result = $this->elementConfigStructureMock; + $proceed = function () use ($result) { + return $result; + }; + + $this->backendHelperMock->expects(static::once()) + ->method('getConfigurationCountryCode') + ->willReturn($countryCode); + + $this->assertSame( + $this->elementConfigStructureMock, + $this->plugin->aroundGetElementByPathParts($this->configStructureMock, $proceed, $pathParts) ); } + /** + * @return array + */ public function aroundGetElementByPathPartsDataProvider() { return [ [ ['payment', 'group1', 'group2', 'field'], 'any', - ['payment_other', 'group1', 'group2', 'field'], ], [ ['payment', 'group1', 'group2', 'field'], 'DE', - ['payment_de', 'group1', 'group2', 'field'] - ], + ] ]; } - - /** - * @param array $pathParts - * @param string $countryCode - * @param array $expectedPathParts - * @dataProvider aroundGetSectionByPathPartsDataProvider - */ - public function testAroundGetSectionByPathParts($pathParts, $countryCode, $expectedPathParts) - { - $this->_getElementByPathPartsPrepareHelper($countryCode); - $result = $this->getMock(\Magento\Config\Model\Config\Structure\Element\Section::class, [], [], '', false); - $self = $this; - $getElementByPathParts = function ($pathParts) use ($self, $expectedPathParts, $result) { - $self->assertEquals($expectedPathParts, $pathParts); - $scope = 'any scope'; - $sectionMap = [ - 'account' => [], - 'recommended_solutions' => [], - 'other_paypal_payment_solutions' => [], - 'other_payment_methods' => [] - ]; - $self->_scopeDefiner->expects($self->any()) - ->method('getScope') - ->will($self->returnValue($scope)); - $result->expects($self->at(0)) - ->method('getData') - ->will($self->returnValue(['children' => []])); - $result->expects($self->at(2)) - ->method('getData') - ->will($self->returnValue(['children' => $sectionMap])); - $result->expects($self->at(1)) - ->method('setData') - ->with(['children' => $sectionMap], $scope) - ->will($self->returnSelf()); - $result->expects($self->at(3)) - ->method('setData') - ->with(['children' => $sectionMap, - 'showInDefault' => true, - 'showInWebsite' => true, - 'showInStore' => true], $scope) - ->will($self->returnSelf()); - return $result; - }; - $this->_aroundGetElementByPathPartsAssertResult($result, $getElementByPathParts, $pathParts); - } - - public function aroundGetSectionByPathPartsDataProvider() - { - return [ - [['payment'], 'GB', ['payment_gb']], - [['payment'], 'any', ['payment_other']], - ]; - } - - /** - * Assert result of aroundGetElementByPathParts method - * - * @param \PHPUnit_Framework_MockObject_MockObject|null $result - * @param \Closure $getElementByPathParts - * @param array $pathParts - */ - private function _aroundGetElementByPathPartsAssertResult($result, $getElementByPathParts, $pathParts) - { - $this->assertEquals($result, $this->_model->aroundGetElementByPathParts( - $this->getMock(\Magento\Config\Model\Config\Structure::class, [], [], '', false), - $getElementByPathParts, - $pathParts - )); - } - - /** - * Get callback for aroundGetElementByPathParts method - * - * @param array $expectedPathParts - * @param \PHPUnit_Framework_MockObject_MockObject|null $result - * @return \Closure - */ - private function _getElementByPathPartsCallback($expectedPathParts, $result) - { - $self = $this; - return function ($pathParts) use ($self, $expectedPathParts, $result) { - $self->assertEquals($expectedPathParts, $pathParts); - return $result; - }; - } - - /** - * Prepare helper for test - * - * @param string $countryCode - */ - private function _getElementByPathPartsPrepareHelper($countryCode) - { - $this->_helper->expects($this->once()) - ->method('getConfigurationCountryCode') - ->will($this->returnValue($countryCode)); - } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Method/Checks/SpecificationPluginTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Method/Checks/SpecificationPluginTest.php index eb8eb1091b083d70d0ee7b1c69d26da87525d113..0994088d84a259f3596065e1ffdc9bb423110b52 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Method/Checks/SpecificationPluginTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Method/Checks/SpecificationPluginTest.php @@ -3,155 +3,179 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Paypal\Test\Unit\Model\Method\Checks; +use Magento\Paypal\Model\Method\Checks\SpecificationPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Paypal\Model\Billing\AgreementFactory as BillingAgreementFactory; +use Magento\Payment\Model\Checks\SpecificationInterface; use Magento\Payment\Model\MethodInterface; -use Magento\Paypal\Model\Billing\AgreementFactory; use Magento\Quote\Model\Quote; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Paypal\Model\ResourceModel\Billing\Agreement\Collection as BillingAgreementCollection; +use Magento\Paypal\Model\Billing\Agreement as BillingAgreement; class SpecificationPluginTest extends \PHPUnit_Framework_TestCase { - /** @var SpecificationPlugin */ - protected $model; + /** + * @var SpecificationPlugin + */ + private $plugin; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; - /** @var AgreementFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $agreementFactory; + /** + * @var BillingAgreementFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $billingAgreementFactoryMock; + + /** + * @var SpecificationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $specificationMock; + + /** + * @var MethodInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentMethodMock; + + /** + * @var Quote|\PHPUnit_Framework_MockObject_MockObject + */ + private $quoteMock; + + /** + * @var BillingAgreementCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $billingAgreementCollectionMock; + + /** + * @var BillingAgreement|\PHPUnit_Framework_MockObject_MockObject + */ + private $billingAgreementMock; protected function setUp() { - $this->agreementFactory = $this->getMockBuilder(\Magento\Paypal\Model\Billing\AgreementFactory::class) + $this->billingAgreementFactoryMock = $this->getMockBuilder(BillingAgreementFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); + $this->specificationMock = $this->getMockBuilder(SpecificationInterface::class) + ->getMockForAbstractClass(); + $this->paymentMethodMock = $this->getMockBuilder(MethodInterface::class) + ->getMockForAbstractClass(); + $this->quoteMock = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->setMethods(['getCustomerId']) + ->getMock(); + $this->billingAgreementCollectionMock = $this->getMockBuilder(BillingAgreementCollection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->billingAgreementMock = $this->getMockBuilder(BillingAgreement::class) + ->disableOriginalConstructor() + ->getMock(); - $objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $objectManagerHelper->getObject( - \Magento\Paypal\Model\Method\Checks\SpecificationPlugin::class, + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + SpecificationPlugin::class, [ - 'agreementFactory' => $this->agreementFactory + 'agreementFactory' => $this->billingAgreementFactoryMock ] ); } - public function testAroundIsApplicableNotOriginallyApplicable() + public function testAfterIsApplicableNotOriginallyApplicable() { - $paymentMethod = $this->getPaymentMethod('any'); - $quote = $this->getQuote('any'); - $proceed = $this->getProceedClosure(false, $paymentMethod, $quote); - $this->assertFalse($this->callAroundIsApplicable($proceed, $paymentMethod, $quote)); + $this->setExpectations('any', 'any'); + + $this->assertFalse( + $this->plugin->afterIsApplicable( + $this->specificationMock, + false, + $this->paymentMethodMock, + $this->quoteMock + ) + ); } - public function testAroundIsApplicableNotAgreement() + public function testAfterIsApplicableNotAgreement() { - $paymentMethod = $this->getPaymentMethod('not_agreement'); - $quote = $this->getQuote('any'); - $proceed = $this->getProceedClosure(true, $paymentMethod, $quote); - $this->assertTrue($this->callAroundIsApplicable($proceed, $paymentMethod, $quote)); + $this->setExpectations('not_agreement', 'any'); + + $this->assertTrue( + $this->plugin->afterIsApplicable( + $this->specificationMock, + true, + $this->paymentMethodMock, + $this->quoteMock + ) + ); } - public function testAroundIsApplicableNoCustomerId() + public function testAfterIsApplicableNoCustomerId() { - $paymentMethod = $this->getPaymentMethod('paypal_billing_agreement'); - $quote = $this->getQuote(null); - $proceed = $this->getProceedClosure(true, $paymentMethod, $quote); - $this->assertFalse($this->callAroundIsApplicable($proceed, $paymentMethod, $quote)); + $this->setExpectations('paypal_billing_agreement', null); + + $this->assertFalse( + $this->plugin->afterIsApplicable( + $this->specificationMock, + true, + $this->paymentMethodMock, + $this->quoteMock + ) + ); } /** * @param int $count - * @dataProvider aroundIsApplicableDataProvider + * + * @dataProvider afterIsApplicableDataProvider */ - public function testAroundIsApplicable($count) + public function testAfterIsApplicable($count) { - $paymentMethod = $this->getPaymentMethod('paypal_billing_agreement'); - $quote = $this->getQuote(1); - $proceed = $this->getProceedClosure(true, $paymentMethod, $quote); - $agreementCollection = $this->getMock( - \Magento\Paypal\Model\ResourceModel\Billing\Agreement\Collection::class, - [], - [], - '', - false - ); - $agreementCollection->expects($this->once()) - ->method('count') - ->will($this->returnValue($count)); - $agreement = $this->getMock(\Magento\Paypal\Model\Billing\Agreement::class, [], [], '', false); - $agreement->expects($this->once()) + $this->setExpectations('paypal_billing_agreement', 1); + + $this->billingAgreementFactoryMock->expects(static::once()) + ->method('create') + ->willReturn($this->billingAgreementMock); + $this->billingAgreementMock->expects(static::once()) ->method('getAvailableCustomerBillingAgreements') ->with(1) - ->will($this->returnValue($agreementCollection)); - $this->agreementFactory->expects($this->once()) - ->method('create') - ->will($this->returnValue($agreement)); - $this->assertEquals($count > 0, $this->callAroundIsApplicable($proceed, $paymentMethod, $quote)); - } - - public function aroundIsApplicableDataProvider() - { - return [[0], [1], [2]]; - } + ->willReturn($this->billingAgreementCollectionMock); + $this->billingAgreementCollectionMock->expects(static::once()) + ->method('count') + ->willReturn($count); - /** - * @param bool $result - * @param MethodInterface $paymentMethod - * @param Quote $quote - * @return \Closure - */ - private function getProceedClosure($result, MethodInterface $paymentMethod, Quote $quote) - { - $self = $this; - return function ($parameter1, $parameter2) use ($result, $paymentMethod, $quote, $self) { - $self->assertSame($paymentMethod, $parameter1); - $self->assertSame($quote, $parameter2); - return $result; - }; + $this->assertEquals( + $count > 0, + $this->plugin->afterIsApplicable($this->specificationMock, true, $this->paymentMethodMock, $this->quoteMock) + ); } /** - * Get payment method parameter - * - * @param string $code - * @return MethodInterface|\PHPUnit_Framework_MockObject_MockObject + * @return array */ - private function getPaymentMethod($code) + public function afterIsApplicableDataProvider() { - $paymentMethod = $this->getMockForAbstractClass(\Magento\Payment\Model\MethodInterface::class); - $paymentMethod->expects($this->any()) - ->method('getCode') - ->will($this->returnValue($code)); - return $paymentMethod; + return [[0], [1], [2]]; } /** - * Get quote parameter + * Set expectations * + * @param mixed $paymentMethodCode * @param mixed $customerId - * @return Quote|\PHPUnit_Framework_MockObject_MockObject + * @return void */ - private function getQuote($customerId) + private function setExpectations($paymentMethodCode, $customerId) { - $quote = $this->getMock(\Magento\Quote\Model\Quote::class, ['__wakeup'], [], '', false); - $quote->setCustomerId($customerId); - return $quote; - } - - /** - * Call aroundIsApplicable method - * - * @param \Closure $proceed - * @param MethodInterface $paymentMethod - * @param Quote $quote - * @return bool - */ - private function callAroundIsApplicable( - \Closure $proceed, - MethodInterface $paymentMethod, - Quote $quote - ) { - $specification = $this->getMockForAbstractClass(\Magento\Payment\Model\Checks\SpecificationInterface::class); - return $this->model->aroundIsApplicable($specification, $proceed, $paymentMethod, $quote); + $this->paymentMethodMock->expects(static::any()) + ->method('getCode') + ->willReturn($paymentMethodCode); + $this->quoteMock->expects(static::any()) + ->method('getCustomerId') + ->willReturn($customerId); } } diff --git a/app/code/Magento/Sales/Api/Data/CommentInterface.php b/app/code/Magento/Sales/Api/Data/CommentInterface.php index d7021dc9f9546b76f427a282a38a31d64f033775..fcab786319340535c1c6309c884a678a91341d90 100644 --- a/app/code/Magento/Sales/Api/Data/CommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/CommentInterface.php @@ -12,6 +12,16 @@ namespace Magento\Sales\Api\Data; */ interface CommentInterface { + /* + * Is-visible-on-storefront flag. + */ + const IS_VISIBLE_ON_FRONT = 'is_visible_on_front'; + + /* + * Comment. + */ + const COMMENT = 'comment'; + /** * Gets the comment for the invoice. * diff --git a/app/code/Magento/Sales/Api/Data/EntityInterface.php b/app/code/Magento/Sales/Api/Data/EntityInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d09b25920f899aa652f87dad269047136892a061 --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/EntityInterface.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +/** + * Interface EntityInterface + * @api + */ +interface EntityInterface +{ + /* + * Entity ID. + */ + const ENTITY_ID = 'entity_id'; + + /* + * Created-at timestamp. + */ + const CREATED_AT = 'created_at'; + + /** + * Gets the created-at timestamp for the invoice. + * + * @return string|null Created-at timestamp. + */ + public function getCreatedAt(); + + /** + * Sets the created-at timestamp for the invoice. + * + * @param string $createdAt timestamp + * @return $this + */ + public function setCreatedAt($createdAt); + + /** + * Gets the ID for the invoice. + * + * @return int|null Invoice ID. + */ + public function getEntityId(); + + /** + * Sets entity ID. + * + * @param int $entityId + * @return $this + */ + public function setEntityId($entityId); +} diff --git a/app/code/Magento/Sales/Api/Data/InvoiceCommentCreationInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceCommentCreationInterface.php index 85c114da3821eb7cb0d98538c37513ddd10fed84..5e4d85e93cb98969580df87b71d7bcc9f6c916f6 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceCommentCreationInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceCommentCreationInterface.php @@ -6,11 +6,29 @@ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Interface InvoiceCommentCreationInterface * * @api */ -interface InvoiceCommentCreationInterface extends \Magento\Sales\Api\Data\CommentInterface +interface InvoiceCommentCreationInterface extends ExtensibleDataInterface, CommentInterface { + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface $extensionAttributes + ); } diff --git a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php index 1447fab476ad9cad5a4f498450952324264b9eec..f661a1ab6a4ca1755f003304c9ff55ee287bba98 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Invoice comment interface. * @@ -12,16 +14,11 @@ namespace Magento\Sales\Api\Data; * invoice history. * @api */ -interface InvoiceCommentInterface extends \Magento\Framework\Api\ExtensibleDataInterface, -\Magento\Sales\Api\Data\InvoiceCommentCreationInterface +interface InvoiceCommentInterface extends ExtensibleDataInterface, CommentInterface, EntityInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case. */ - /* - * Entity ID. - */ - const ENTITY_ID = 'entity_id'; /* * Parent ID. */ @@ -30,48 +27,6 @@ interface InvoiceCommentInterface extends \Magento\Framework\Api\ExtensibleDataI * Is-customer-notified flag. */ const IS_CUSTOMER_NOTIFIED = 'is_customer_notified'; - /* - * Is-visible-on-storefront flag. - */ - const IS_VISIBLE_ON_FRONT = 'is_visible_on_front'; - /* - * Comment. - */ - const COMMENT = 'comment'; - /* - * Created-at timestamp. - */ - const CREATED_AT = 'created_at'; - - /** - * Gets the created-at timestamp for the invoice. - * - * @return string|null Created-at timestamp. - */ - public function getCreatedAt(); - - /** - * Sets the created-at timestamp for the invoice. - * - * @param string $createdAt timestamp - * @return $this - */ - public function setCreatedAt($createdAt); - - /** - * Gets the ID for the invoice. - * - * @return int|null Invoice ID. - */ - public function getEntityId(); - - /** - * Sets entity ID. - * - * @param int $entityId - * @return $this - */ - public function setEntityId($entityId); /** * Gets the is-customer-notified flag value for the invoice. diff --git a/app/code/Magento/Sales/Api/Data/InvoiceItemCreationInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceItemCreationInterface.php index 4b5c6fa2c6136f4d5896a418636d87632af5d603..2f2ddfbf758a0de4341b60b840263704bf6968ab 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceItemCreationInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceItemCreationInterface.php @@ -6,6 +6,8 @@ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Input argument for invoice creation * @@ -13,6 +15,22 @@ namespace Magento\Sales\Api\Data; * * @api */ -interface InvoiceItemCreationInterface extends LineItemInterface +interface InvoiceItemCreationInterface extends LineItemInterface, ExtensibleDataInterface { + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface $extensionAttributes + ); } diff --git a/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php index ecdcd07bc0ca5b90f4970dcffbfcbcdd3757774d..37a933f97a29ab26a192735e808c031ede534900 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php @@ -5,14 +5,15 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Invoice item interface. * * An invoice is a record of the receipt of payment for an order. An invoice item is a purchased item in an invoice. * @api */ -interface InvoiceItemInterface extends \Magento\Sales\Api\Data\InvoiceItemCreationInterface, -\Magento\Framework\Api\ExtensibleDataInterface +interface InvoiceItemInterface extends ExtensibleDataInterface, LineItemInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case. diff --git a/app/code/Magento/Sales/Api/Data/ShipmentCommentCreationInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentCommentCreationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..40beaa32d02f25c57af5fe93cbfd3e3f6d97e93f --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/ShipmentCommentCreationInterface.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +use Magento\Framework\Api\ExtensibleDataInterface; + +/** + * Interface ShipmentCommentCreationInterface + * @api + */ +interface ShipmentCommentCreationInterface extends ExtensibleDataInterface, CommentInterface +{ + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php index a67b0577a7761ee72bc1fad3c9fda679f31aa27e..0c00bf80d78f1d4f0311f7331a3639eec3e30bba 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Shipment comment interface. * @@ -12,15 +14,11 @@ namespace Magento\Sales\Api\Data; * document lists the products and their quantities in the delivery package. A shipment document can contain comments. * @api */ -interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface ShipmentCommentInterface extends ExtensibleDataInterface, CommentInterface, EntityInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case. */ - /* - * Entity ID. - */ - const ENTITY_ID = 'entity_id'; /* * Parent ID. */ @@ -29,55 +27,6 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData * Is-customer-notified flag. */ const IS_CUSTOMER_NOTIFIED = 'is_customer_notified'; - /* - * Is-visible-on-storefront flag. - */ - const IS_VISIBLE_ON_FRONT = 'is_visible_on_front'; - /* - * Comment. - */ - const COMMENT = 'comment'; - /* - * Created-at timestamp. - */ - const CREATED_AT = 'created_at'; - - /** - * Gets the comment for the shipment. - * - * @return string Comment. - */ - public function getComment(); - - /** - * Gets the created-at timestamp for the shipment comment. - * - * @return string|null Created-at timestamp. - */ - public function getCreatedAt(); - - /** - * Sets the created-at timestamp for the shipment comment. - * - * @param string $createdAt timestamp - * @return $this - */ - public function setCreatedAt($createdAt); - - /** - * Gets the ID for the shipment comment. - * - * @return int|null Shipment comment ID. - */ - public function getEntityId(); - - /** - * Sets entity ID. - * - * @param int $entityId - * @return $this - */ - public function setEntityId($entityId); /** * Gets the is-customer-notified flag value for the shipment comment. @@ -86,13 +35,6 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData */ public function getIsCustomerNotified(); - /** - * Gets the is-visible-on-storefront flag value for the shipment comment. - * - * @return int Is-visible-on-storefront flag value. - */ - public function getIsVisibleOnFront(); - /** * Gets the parent ID for the shipment comment. * @@ -116,22 +58,6 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData */ public function setIsCustomerNotified($isCustomerNotified); - /** - * Sets the is-visible-on-storefront flag value for the shipment comment. - * - * @param int $isVisibleOnFront - * @return $this - */ - public function setIsVisibleOnFront($isVisibleOnFront); - - /** - * Sets the comment for the shipment. - * - * @param string $comment - * @return $this - */ - public function setComment($comment); - /** * Retrieve existing extension attributes object or create a new one. * diff --git a/app/code/Magento/Sales/Api/Data/ShipmentCreationArgumentsInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentCreationArgumentsInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f03d05be3c7426bf28d16a7976957b087c432b0d --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/ShipmentCreationArgumentsInterface.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +/** + * Interface for creation arguments for Shipment. + * + * @api + */ +interface ShipmentCreationArgumentsInterface extends \Magento\Framework\Api\ExtensibleDataInterface +{ + /** + * Gets existing extension attributes. + * + * @return \Magento\Sales\Api\Data\ShipmentCreationArgumentsExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Sets extension attributes. + * + * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsExtensionInterface $extensionAttributes + * + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentCreationArgumentsExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Sales/Api/Data/ShipmentItemCreationInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentItemCreationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..57c908fb88c5e9aa5e1dd7dbc6e8c39449d2217d --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/ShipmentItemCreationInterface.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Api\Data; + +/** + * Input argument for shipment item creation + * + * Interface ShipmentItemCreationInterface + * + * @api + */ +interface ShipmentItemCreationInterface extends LineItemInterface, +\Magento\Framework\Api\ExtensibleDataInterface +{ + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php index 03f8fba0b431cbb39be5642aede49993bb8d202c..6d891371d04a14be86c4740b70a4838ccbc5a8cb 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php @@ -12,7 +12,8 @@ namespace Magento\Sales\Api\Data; * document lists the products and their quantities in the delivery package. A product is an item in a shipment. * @api */ -interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface ShipmentItemInterface extends \Magento\Sales\Api\Data\LineItemInterface, +\Magento\Framework\Api\ExtensibleDataInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case @@ -102,13 +103,6 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt */ public function getName(); - /** - * Gets the order item ID for the shipment item. - * - * @return int Order item ID. - */ - public function getOrderItemId(); - /** * Gets the parent ID for the shipment item. * @@ -130,13 +124,6 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt */ public function getProductId(); - /** - * Gets the quantity for the shipment item. - * - * @return float Quantity. - */ - public function getQty(); - /** * Gets the row total for the shipment item. * @@ -190,14 +177,6 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt */ public function setWeight($weight); - /** - * Sets the quantity for the shipment item. - * - * @param float $qty - * @return $this - */ - public function setQty($qty); - /** * Sets the product ID for the shipment item. * @@ -206,14 +185,6 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt */ public function setProductId($id); - /** - * Sets the order item ID for the shipment item. - * - * @param int $id - * @return $this - */ - public function setOrderItemId($id); - /** * Sets the additional data for the shipment item. * diff --git a/app/code/Magento/Sales/Api/Data/ShipmentPackageCreationInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentPackageCreationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c83c54b3019bec5dfe507c97fe82bab02dc8f96b --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/ShipmentPackageCreationInterface.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +/** + * Shipment package interface. + * + * A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This + * document lists the products and their quantities in the delivery package. + * @api + */ +interface ShipmentPackageCreationInterface extends \Magento\Framework\Api\ExtensibleDataInterface +{ + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\ShipmentPackageCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\ShipmentPackageCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentPackageCreationExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Sales/Api/Data/ShipmentTrackCreationInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentTrackCreationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6a45242fcd1568275db8727b64e83a22fdbdd73f --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/ShipmentTrackCreationInterface.php @@ -0,0 +1,34 @@ +<?php + +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +use Magento\Framework\Api\ExtensibleDataInterface; + +/** + * Shipment Track Creation interface. + * + * @api + */ +interface ShipmentTrackCreationInterface extends TrackInterface, ExtensibleDataInterface +{ + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\ShipmentTrackCreationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\ShipmentTrackCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentTrackCreationExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php index f28a0b0e7a1970a05dfeef5739238966b1503182..beafa1370f107e1ba725568b893b4d390d9469b5 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Shipment track interface. * @@ -13,7 +15,7 @@ namespace Magento\Sales\Api\Data; * shipments. * @api */ -interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface ShipmentTrackInterface extends TrackInterface, ExtensibleDataInterface { /**#@+ * Constants for keys of data array. Identical to the name of the getter in snake case. @@ -64,11 +66,19 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn const UPDATED_AT = 'updated_at'; /** - * Gets the carrier code for the shipment package. + * Sets the order_id for the shipment package. * - * @return string Carrier code. + * @param int $id + * @return $this */ - public function getCarrierCode(); + public function setOrderId($id); + + /** + * Gets the order_id for the shipment package. + * + * @return int + */ + public function getOrderId(); /** * Gets the created-at timestamp for the shipment package. @@ -85,13 +95,6 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn */ public function setCreatedAt($createdAt); - /** - * Gets the description for the shipment package. - * - * @return string Description. - */ - public function getDescription(); - /** * Gets the ID for the shipment package. * @@ -107,13 +110,6 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn */ public function setEntityId($entityId); - /** - * Gets the order_id for the shipment package. - * - * @return int - */ - public function getOrderId(); - /** * Gets the parent ID for the shipment package. * @@ -121,27 +117,6 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn */ public function getParentId(); - /** - * Gets the quantity for the shipment package. - * - * @return float Quantity. - */ - public function getQty(); - - /** - * Gets the title for the shipment package. - * - * @return string Title. - */ - public function getTitle(); - - /** - * Gets the track number for the shipment package. - * - * @return string Track number. - */ - public function getTrackNumber(); - /** * Gets the updated-at timestamp for the shipment package. * @@ -149,13 +124,6 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn */ public function getUpdatedAt(); - /** - * Gets the weight for the shipment package. - * - * @return float Weight. - */ - public function getWeight(); - /** * Sets the updated-at timestamp for the shipment package. * @@ -181,28 +149,26 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn public function setWeight($weight); /** - * Sets the quantity for the shipment package. + * Gets the weight for the shipment package. * - * @param float $qty - * @return $this + * @return float Weight. */ - public function setQty($qty); + public function getWeight(); /** - * Sets the order_id for the shipment package. + * Sets the quantity for the shipment package. * - * @param int $id + * @param float $qty * @return $this */ - public function setOrderId($id); + public function setQty($qty); /** - * Sets the track number for the shipment package. + * Gets the quantity for the shipment package. * - * @param string $trackNumber - * @return $this + * @return float Quantity. */ - public function setTrackNumber($trackNumber); + public function getQty(); /** * Sets the description for the shipment package. @@ -213,20 +179,11 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn public function setDescription($description); /** - * Sets the title for the shipment package. - * - * @param string $title - * @return $this - */ - public function setTitle($title); - - /** - * Sets the carrier code for the shipment package. + * Gets the description for the shipment package. * - * @param string $code - * @return $this + * @return string Description. */ - public function setCarrierCode($code); + public function getDescription(); /** * Retrieve existing extension attributes object or create a new one. diff --git a/app/code/Magento/Sales/Api/Data/TrackInterface.php b/app/code/Magento/Sales/Api/Data/TrackInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..17c08ff9b983031efa1268fc0a4c0fc359f60bd5 --- /dev/null +++ b/app/code/Magento/Sales/Api/Data/TrackInterface.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Data; + +/** + * Shipment Track Creation interface. + * + * @api + */ +interface TrackInterface +{ + /** + * Sets the track number for the shipment package. + * + * @param string $trackNumber + * @return $this + */ + public function setTrackNumber($trackNumber); + + /** + * Gets the track number for the shipment package. + * + * @return string Track number. + */ + public function getTrackNumber(); + + /** + * Sets the title for the shipment package. + * + * @param string $title + * @return $this + */ + public function setTitle($title); + + /** + * Gets the title for the shipment package. + * + * @return string Title. + */ + public function getTitle(); + + /** + * Sets the carrier code for the shipment package. + * + * @param string $code + * @return $this + */ + public function setCarrierCode($code); + + /** + * Gets the carrier code for the shipment package. + * + * @return string Carrier code. + */ + public function getCarrierCode(); +} diff --git a/app/code/Magento/Sales/Api/Exception/CouldNotShipExceptionInterface.php b/app/code/Magento/Sales/Api/Exception/CouldNotShipExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b52e627791249eb6b347d495e32639e20536370e --- /dev/null +++ b/app/code/Magento/Sales/Api/Exception/CouldNotShipExceptionInterface.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api\Exception; + +/** + * @api + */ +interface CouldNotShipExceptionInterface +{ +} diff --git a/app/code/Magento/Sales/Api/OrderInvoiceInterface.php b/app/code/Magento/Sales/Api/InvoiceOrderInterface.php similarity index 93% rename from app/code/Magento/Sales/Api/OrderInvoiceInterface.php rename to app/code/Magento/Sales/Api/InvoiceOrderInterface.php index 80fa6159afc3e449115a6b373560628a5aa7157f..0f0ce4596991664671cc6ea4d1f231ad05066ed3 100644 --- a/app/code/Magento/Sales/Api/OrderInvoiceInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceOrderInterface.php @@ -7,11 +7,11 @@ namespace Magento\Sales\Api; /** - * Class OrderInvoiceInterface + * Class InvoiceOrderInterface * * @api */ -interface OrderInvoiceInterface +interface InvoiceOrderInterface { /** * @param int $orderId diff --git a/app/code/Magento/Sales/Api/ShipOrderInterface.php b/app/code/Magento/Sales/Api/ShipOrderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d28fedf4e507fc9c73f64ef60d42032e5d0c2114 --- /dev/null +++ b/app/code/Magento/Sales/Api/ShipOrderInterface.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Api; + +/** + * Class ShipOrderInterface + * + * @api + */ +interface ShipOrderInterface +{ + /** + * Creates new Shipment for given Order. + * + * @param int $orderId + * @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items + * @param bool $notify + * @param bool $appendComment + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks + * @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages + * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments + * @return int Id of created Shipment. + */ + public function execute( + $orderId, + array $items = [], + $notify = false, + $appendComment = false, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + array $tracks = [], + array $packages = [], + \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null + ); +} diff --git a/app/code/Magento/Sales/Exception/CouldNotShipException.php b/app/code/Magento/Sales/Exception/CouldNotShipException.php new file mode 100644 index 0000000000000000000000000000000000000000..4881bbd79a3a3eec84c74f66ffaf8a4c5553bd16 --- /dev/null +++ b/app/code/Magento/Sales/Exception/CouldNotShipException.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Exception; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Sales\Api\Exception\CouldNotShipExceptionInterface; + +/** + * Class CouldNotShipException + */ +class CouldNotShipException extends LocalizedException implements CouldNotShipExceptionInterface +{ +} diff --git a/app/code/Magento/Sales/Model/OrderInvoice.php b/app/code/Magento/Sales/Model/InvoiceOrder.php similarity index 86% rename from app/code/Magento/Sales/Model/OrderInvoice.php rename to app/code/Magento/Sales/Model/InvoiceOrder.php index b499b7028bce1336f29688b4ebb04aaa9db32048..e51b46082d943d8ff609bacb80fae19c861afba4 100644 --- a/app/code/Magento/Sales/Model/OrderInvoice.php +++ b/app/code/Magento/Sales/Model/InvoiceOrder.php @@ -9,22 +9,25 @@ namespace Magento\Sales\Model; use Magento\Framework\App\ResourceConnection; use Magento\Sales\Api\Data\InvoiceCommentCreationInterface; use Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface; -use Magento\Sales\Api\OrderInvoiceInterface; +use Magento\Sales\Api\InvoiceOrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order\Config as OrderConfig; +use Magento\Sales\Model\Order\Invoice\InvoiceValidatorInterface; use Magento\Sales\Model\Order\Invoice\NotifierInterface; use Magento\Sales\Model\Order\InvoiceDocumentFactory; +use Magento\Sales\Model\Order\InvoiceQuantityValidator; use Magento\Sales\Model\Order\InvoiceRepository; -use Magento\Sales\Model\Order\InvoiceValidatorInterface; use Magento\Sales\Model\Order\OrderStateResolverInterface; +use Magento\Sales\Model\Order\OrderValidatorInterface; use Magento\Sales\Model\Order\PaymentAdapterInterface; +use Magento\Sales\Model\Order\Validation\CanInvoice; use Psr\Log\LoggerInterface; /** - * Class InvoiceService + * Class InvoiceOrder * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class OrderInvoice implements OrderInvoiceInterface +class InvoiceOrder implements InvoiceOrderInterface { /** * @var ResourceConnection @@ -76,12 +79,18 @@ class OrderInvoice implements OrderInvoiceInterface */ private $logger; + /** + * @var OrderValidatorInterface + */ + private $orderValidator; + /** * OrderInvoice constructor. * @param ResourceConnection $resourceConnection * @param OrderRepositoryInterface $orderRepository * @param InvoiceDocumentFactory $invoiceDocumentFactory * @param InvoiceValidatorInterface $invoiceValidator + * @param OrderValidatorInterface $orderValidator * @param PaymentAdapterInterface $paymentAdapter * @param OrderStateResolverInterface $orderStateResolver * @param OrderConfig $config @@ -95,6 +104,7 @@ class OrderInvoice implements OrderInvoiceInterface OrderRepositoryInterface $orderRepository, InvoiceDocumentFactory $invoiceDocumentFactory, InvoiceValidatorInterface $invoiceValidator, + OrderValidatorInterface $orderValidator, PaymentAdapterInterface $paymentAdapter, OrderStateResolverInterface $orderStateResolver, OrderConfig $config, @@ -106,6 +116,7 @@ class OrderInvoice implements OrderInvoiceInterface $this->orderRepository = $orderRepository; $this->invoiceDocumentFactory = $invoiceDocumentFactory; $this->invoiceValidator = $invoiceValidator; + $this->orderValidator = $orderValidator; $this->paymentAdapter = $paymentAdapter; $this->orderStateResolver = $orderStateResolver; $this->config = $config; @@ -147,7 +158,16 @@ class OrderInvoice implements OrderInvoiceInterface ($appendComment && $notify), $arguments ); - $errorMessages = $this->invoiceValidator->validate($invoice, $order); + $errorMessages = array_merge( + $this->invoiceValidator->validate( + $invoice, + [InvoiceQuantityValidator::class] + ), + $this->orderValidator->validate( + $order, + [CanInvoice::class] + ) + ); if (!empty($errorMessages)) { throw new \Magento\Sales\Exception\DocumentValidationException( __("Invoice Document Validation Error(s):\n" . implode("\n", $errorMessages)) diff --git a/app/code/Magento/Sales/Model/Order/Invoice/CommentCreation.php b/app/code/Magento/Sales/Model/Order/Invoice/CommentCreation.php new file mode 100644 index 0000000000000000000000000000000000000000..fa53f72ebcafcccc24a5e0cbf35b9cf208ec49ad --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Invoice/CommentCreation.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Order\Invoice; + +use Magento\Sales\Api\Data\InvoiceCommentCreationInterface; + +/** + * Class InvoiceCommentCreation + */ +class CommentCreation implements InvoiceCommentCreationInterface +{ + + /** + * @var string + */ + private $comment; + + /** + * @var int + */ + private $isVisibleOnFront; + + /** + * @var \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface + */ + private $extensionAttributes; + + /** + * Gets the comment for the invoice. + * + * @return string Comment. + */ + public function getComment() + { + return $this->comment; + } + + /** + * Sets the comment for the invoice. + * + * @param string $comment + * @return $this + */ + public function setComment($comment) + { + $this->comment = $comment; + return $this; + } + + /** + * Gets the is-visible-on-storefront flag value for the invoice. + * + * @return int Is-visible-on-storefront flag value. + */ + public function getIsVisibleOnFront() + { + return $this->isVisibleOnFront; + } + + /** + * Sets the is-visible-on-storefront flag value for the invoice. + * + * @param int $isVisibleOnFront + * @return $this + */ + public function setIsVisibleOnFront($isVisibleOnFront) + { + $this->isVisibleOnFront = $isVisibleOnFront; + return $this; + } + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\InvoiceCommentCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidator.php b/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..cbb68edaa8a5508968ce4453973b5631a35768e5 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidator.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Invoice; + +use Magento\Sales\Api\Data\InvoiceInterface; + +/** + * Class InvoiceValidatorRunner + */ +class InvoiceValidator implements InvoiceValidatorInterface +{ + /** + * @var \Magento\Sales\Model\Validator + */ + private $validator; + + /** + * InvoiceValidatorRunner constructor. + * @param \Magento\Sales\Model\Validator $validator + */ + public function __construct(\Magento\Sales\Model\Validator $validator) + { + $this->validator = $validator; + } + + /** + * @inheritdoc + */ + public function validate(InvoiceInterface $entity, array $validators) + { + return $this->validator->validate($entity, $validators); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidatorInterface.php b/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..568019a40fce5bc69ccab49ca8b3f4fee048505e --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Invoice/InvoiceValidatorInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Invoice; + +use Magento\Sales\Api\Data\InvoiceInterface; +use Magento\Sales\Exception\DocumentValidationException; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Interface InvoiceValidatorInterface + */ +interface InvoiceValidatorInterface +{ + /** + * @param InvoiceInterface $entity + * @param ValidatorInterface[] $validators + * @return string[] + * @throws DocumentValidationException + */ + public function validate(InvoiceInterface $entity, array $validators); +} diff --git a/app/code/Magento/Sales/Model/Order/Invoice/ItemCreation.php b/app/code/Magento/Sales/Model/Order/Invoice/ItemCreation.php index abc19c3aaa73d99550f9157634d315b1053baf1d..26d8d7ae6ca99fd7191fdfaae957d4a067cd1455 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/ItemCreation.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/ItemCreation.php @@ -23,6 +23,11 @@ class ItemCreation implements InvoiceItemCreationInterface */ private $qty; + /** + * @var \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface + */ + private $extensionAttributes; + /** * {@inheritdoc} */ @@ -54,4 +59,27 @@ class ItemCreation implements InvoiceItemCreationInterface { $this->qty = $qty; } + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\InvoiceItemCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } } diff --git a/app/code/Magento/Sales/Model/Order/InvoiceValidator.php b/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php similarity index 73% rename from app/code/Magento/Sales/Model/Order/InvoiceValidator.php rename to app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php index 35222599fc69ec67f636a6db69949d8d33006655..9ae81dacb0a17408337bec32961da40056ab4a8a 100644 --- a/app/code/Magento/Sales/Model/Order/InvoiceValidator.php +++ b/app/code/Magento/Sales/Model/Order/InvoiceQuantityValidator.php @@ -9,42 +9,38 @@ namespace Magento\Sales\Model\Order; use Magento\Sales\Api\Data\InvoiceInterface; use Magento\Sales\Api\Data\InvoiceItemInterface; use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\ValidatorInterface; /** * Interface InvoiceValidatorInterface */ -class InvoiceValidator implements InvoiceValidatorInterface +class InvoiceQuantityValidator implements ValidatorInterface { /** - * @var OrderValidatorInterface + * @var OrderRepositoryInterface */ - private $orderValidator; + private $orderRepository; /** * InvoiceValidator constructor. - * @param OrderValidatorInterface $orderValidator + * @param OrderRepositoryInterface $orderRepository */ - public function __construct(OrderValidatorInterface $orderValidator) + public function __construct(OrderRepositoryInterface $orderRepository) { - $this->orderValidator = $orderValidator; + $this->orderRepository = $orderRepository; } /** - * @param InvoiceInterface $invoice - * @param OrderInterface $order - * @return array + * @inheritdoc */ - public function validate(InvoiceInterface $invoice, OrderInterface $order) + public function validate($invoice) { - $messages = $this->checkQtyAvailability($invoice, $order); - - if (!$this->orderValidator->canInvoice($order)) { - $messages[] = __( - 'An invoice cannot be created when an order has a status of %1.', - $order->getStatus() - ); + if ($invoice->getOrderId() === null) { + return [__('Order Id is required for invoice document')]; } - return $messages; + $order = $this->orderRepository->get($invoice->getOrderId()); + return $this->checkQtyAvailability($invoice, $order); } /** diff --git a/app/code/Magento/Sales/Model/Order/InvoiceValidatorInterface.php b/app/code/Magento/Sales/Model/Order/InvoiceValidatorInterface.php deleted file mode 100644 index 64b2f98dfe37eb15463d77509a14a9b5a579e043..0000000000000000000000000000000000000000 --- a/app/code/Magento/Sales/Model/Order/InvoiceValidatorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Model\Order; - -use Magento\Sales\Api\Data\InvoiceInterface; -use Magento\Sales\Api\Data\OrderInterface; - -/** - * Interface InvoiceValidatorInterface - * - * @api - */ -interface InvoiceValidatorInterface -{ - /** - * @param InvoiceInterface $invoice - * @param OrderInterface $order - * @return array - */ - public function validate(InvoiceInterface $invoice, OrderInterface $order); -} diff --git a/app/code/Magento/Sales/Model/Order/OrderValidator.php b/app/code/Magento/Sales/Model/Order/OrderValidator.php index c476671136875658e16185770b223c538e0d4e2f..8208af96c93d34cbae918883047b116713faad98 100644 --- a/app/code/Magento/Sales/Model/Order/OrderValidator.php +++ b/app/code/Magento/Sales/Model/Order/OrderValidator.php @@ -3,40 +3,35 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Sales\Model\Order; use Magento\Sales\Api\Data\OrderInterface; -use Magento\Sales\Model\Order; +use Magento\Sales\Exception\DocumentValidationException; /** - * Order Validator - * + * Class OrderValidator */ class OrderValidator implements OrderValidatorInterface { /** - * Retrieve order invoice availability - * - * @param OrderInterface $order - * @return bool + * @var \Magento\Sales\Model\Validator + */ + private $validator; + + /** + * OrderValidator constructor. + * @param \Magento\Sales\Model\Validator $validator + */ + public function __construct(\Magento\Sales\Model\Validator $validator) + { + $this->validator = $validator; + } + + /** + * @inheritdoc */ - public function canInvoice(OrderInterface $order) + public function validate(OrderInterface $entity, array $validators) { - if ($order->getState() === Order::STATE_PAYMENT_REVIEW || - $order->getState() === Order::STATE_HOLDED || - $order->getState() === Order::STATE_CANCELED || - $order->getState() === Order::STATE_COMPLETE || - $order->getState() === Order::STATE_CLOSED - ) { - return false; - }; - /** @var \Magento\Sales\Model\Order\Item $item */ - foreach ($order->getItems() as $item) { - if ($item->getQtyToInvoice() > 0 && !$item->getLockedDoInvoice()) { - return true; - } - } - return false; + return $this->validator->validate($entity, $validators); } } diff --git a/app/code/Magento/Sales/Model/Order/OrderValidatorInterface.php b/app/code/Magento/Sales/Model/Order/OrderValidatorInterface.php index d0dcc38af642a7633af1b3ec4de124bc140c9497..c5a9a6c1d32963fcc223099efe1fcb81bb530464 100644 --- a/app/code/Magento/Sales/Model/Order/OrderValidatorInterface.php +++ b/app/code/Magento/Sales/Model/Order/OrderValidatorInterface.php @@ -3,21 +3,22 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Sales\Model\Order; use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Exception\DocumentValidationException; +use Magento\Sales\Model\ValidatorInterface; /** * Interface OrderValidatorInterface - * - * @api */ interface OrderValidatorInterface { /** - * @param OrderInterface $order - * @return bool + * @param OrderInterface $entity + * @param ValidatorInterface[] $validators + * @return string[] + * @throws DocumentValidationException */ - public function canInvoice(OrderInterface $order); + public function validate(OrderInterface $entity, array $validators); } diff --git a/app/code/Magento/Sales/Model/Order/Shipment.php b/app/code/Magento/Sales/Model/Order/Shipment.php index 6647bae750fffebc8a28ca09102b596336badd7f..2277f92d6e0e8be638c919f02dfc13d1054fb819 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment.php @@ -405,7 +405,7 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa * Adds comment to shipment with additional possibility to send it to customer via email * and show it in customer account * - * @param \Magento\Sales\Model\Order\Shipment\Comment $comment + * @param \Magento\Sales\Model\Order\Shipment\Comment|string $comment * @param bool $notify * @param bool $visibleOnFront * @return $this diff --git a/app/code/Magento/Sales/Model/Order/Shipment/CommentCreation.php b/app/code/Magento/Sales/Model/Order/Shipment/CommentCreation.php new file mode 100644 index 0000000000000000000000000000000000000000..19d06fb0eff3275a41ccd2d0c9cc42e77c0436c7 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/CommentCreation.php @@ -0,0 +1,96 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\ShipmentCommentCreationInterface; + +/** + * Class CommentCreation + */ +class CommentCreation implements ShipmentCommentCreationInterface +{ + /** + * @var \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface + */ + private $extensionAttributes; + + /** + * @var string + */ + private $comment; + + /** + * @var int + */ + private $isVisibleOnFront; + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * Set an extension attributes object. + * + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentCommentCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } + + /** + * Gets the comment for the invoice. + * + * @return string Comment. + */ + public function getComment() + { + return $this->comment; + } + + /** + * Sets the comment for the invoice. + * + * @param string $comment + * @return $this + */ + public function setComment($comment) + { + $this->comment = $comment; + return $this; + } + + /** + * Gets the is-visible-on-storefront flag value for the invoice. + * + * @return int Is-visible-on-storefront flag value. + */ + public function getIsVisibleOnFront() + { + return $this->isVisibleOnFront; + } + + /** + * Sets the is-visible-on-storefront flag value for the invoice. + * + * @param int $isVisibleOnFront + * @return $this + */ + public function setIsVisibleOnFront($isVisibleOnFront) + { + $this->isVisibleOnFront = $isVisibleOnFront; + return $this; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/CreationArguments.php b/app/code/Magento/Sales/Model/Order/Shipment/CreationArguments.php new file mode 100644 index 0000000000000000000000000000000000000000..8a43a73553e79ab7887995c3a691263ff86c7cd6 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/CreationArguments.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Creation arguments for Shipment. + * + * @api + */ +class CreationArguments implements \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface +{ + /** + * @var \Magento\Sales\Api\Data\ShipmentCreationArgumentsExtensionInterface + */ + private $extensionAttributes; + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentCreationArgumentsExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Item.php b/app/code/Magento/Sales/Model/Order/Shipment/Item.php index c7fdca853b17e366e9a64201623b5f68697c8381..8627f76031b06657d2d727b5261a89cc261ea6e1 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Item.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Item.php @@ -151,22 +151,7 @@ class Item extends AbstractModel implements ShipmentItemInterface */ public function setQty($qty) { - if ($this->getOrderItem()->getIsQtyDecimal()) { - $qty = (double)$qty; - } else { - $qty = (int)$qty; - } - $qty = $qty > 0 ? $qty : 0; - /** - * Check qty availability - */ - if ($qty <= $this->getOrderItem()->getQtyToShip() || $this->getOrderItem()->isDummy(true)) { - $this->setData('qty', $qty); - } else { - throw new \Magento\Framework\Exception\LocalizedException( - __('We found an invalid quantity to ship for item "%1".', $this->getName()) - ); - } + $this->setData('qty', $qty); return $this; } @@ -174,6 +159,7 @@ class Item extends AbstractModel implements ShipmentItemInterface * Applying qty to order item * * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ public function register() { diff --git a/app/code/Magento/Sales/Model/Order/Shipment/ItemCreation.php b/app/code/Magento/Sales/Model/Order/Shipment/ItemCreation.php new file mode 100644 index 0000000000000000000000000000000000000000..e3cb2f23d7cf31e81a737fa06c64b89d1d11d796 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/ItemCreation.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\ShipmentItemCreationInterface; + +/** + * Class ItemCreation + */ +class ItemCreation implements ShipmentItemCreationInterface +{ + /** + * @var int + */ + private $orderItemId; + + /** + * @var float + */ + private $qty; + + /** + * @var \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface + */ + private $extensionAttributes; + + //@codeCoverageIgnoreStart + + /** + * {@inheritdoc} + */ + public function getOrderItemId() + { + return $this->orderItemId; + } + + /** + * {@inheritdoc} + */ + public function setOrderItemId($orderItemId) + { + $this->orderItemId = $orderItemId; + } + + /** + * {@inheritdoc} + */ + public function getQty() + { + return $this->qty; + } + + /** + * {@inheritdoc} + */ + public function setQty($qty) + { + $this->qty = $qty; + } + + /** + * {@inheritdoc} + * + * @return \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * {@inheritdoc} + * + * @param \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentItemCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } + //@codeCoverageIgnoreEnd +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Notifier.php b/app/code/Magento/Sales/Model/Order/Shipment/Notifier.php new file mode 100644 index 0000000000000000000000000000000000000000..21dd5ad4a58f62ad2b77143e373f9e0f19c3bc66 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/Notifier.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Shipment notifier. + * + * @api + */ +class Notifier implements \Magento\Sales\Model\Order\Shipment\NotifierInterface +{ + /** + * @var \Magento\Sales\Model\Order\Shipment\SenderInterface[] + */ + private $senders; + + /** + * @param \Magento\Sales\Model\Order\Shipment\SenderInterface[] $senders + */ + public function __construct(array $senders = []) + { + $this->senders = $senders; + } + + /** + * {@inheritdoc} + */ + public function notify( + \Magento\Sales\Api\Data\OrderInterface $order, + \Magento\Sales\Api\Data\ShipmentInterface $shipment, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + $forceSyncMode = false + ) { + foreach ($this->senders as $sender) { + $sender->send($order, $shipment, $comment, $forceSyncMode); + } + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/NotifierInterface.php b/app/code/Magento/Sales/Model/Order/Shipment/NotifierInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f34eb6178d09468de16f48fba3a717de3b22091a --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/NotifierInterface.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Interface for Shipment notifier. + * + * @api + */ +interface NotifierInterface +{ + /** + * Notifies customer. + * + * @param \Magento\Sales\Api\Data\OrderInterface $order + * @param \Magento\Sales\Api\Data\ShipmentInterface $shipment + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param bool $forceSyncMode + * + * @return void + */ + public function notify( + \Magento\Sales\Api\Data\OrderInterface $order, + \Magento\Sales\Api\Data\ShipmentInterface $shipment, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + $forceSyncMode = false + ); +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrar.php b/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrar.php new file mode 100644 index 0000000000000000000000000000000000000000..040ab12949be1748638cd7e83ff8c971b7e34161 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrar.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\ShipmentInterface; + +class OrderRegistrar implements \Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface +{ + /** + * @param OrderInterface $order + * @param ShipmentInterface $shipment + * @return OrderInterface + */ + public function register(OrderInterface $order, ShipmentInterface $shipment) + { + /** @var \Magento\Sales\Api\Data\ShipmentItemInterface|\Magento\Sales\Model\Order\Shipment\Item $item */ + foreach ($shipment->getItems() as $item) { + if ($item->getQty() > 0) { + $item->register(); + } + } + return $order; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrarInterface.php b/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrarInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7d54acece35997efcb2db7c62a9fb92c42cd4788 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrarInterface.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\ShipmentInterface; + +/** + * Interface OrderRegistrarInterface + * + * Calculate order shipped data based on created shipment + * + * @api + */ +interface OrderRegistrarInterface +{ + /** + * @param OrderInterface $order + * @param ShipmentInterface $shipment + * @return OrderInterface + */ + public function register(OrderInterface $order, ShipmentInterface $shipment); +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Package.php b/app/code/Magento/Sales/Model/Order/Shipment/Package.php new file mode 100644 index 0000000000000000000000000000000000000000..6f8f54336a2c5b989ef7728866d8b18039c492f4 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/Package.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Class Package + * @api + */ +class Package implements \Magento\Sales\Api\Data\ShipmentPackageInterface +{ + /** + * @var \Magento\Sales\Api\Data\ShipmentPackageExtensionInterface + */ + private $extensionAttributes; + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentPackageExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/PackageCreation.php b/app/code/Magento/Sales/Model/Order/Shipment/PackageCreation.php new file mode 100644 index 0000000000000000000000000000000000000000..50ad944b8251c62a6df8af329839d58a49d8827d --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/PackageCreation.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Class PackageCreation + * @api + */ +class PackageCreation implements \Magento\Sales\Api\Data\ShipmentPackageCreationInterface +{ + /** + * @var \Magento\Sales\Api\Data\ShipmentPackageCreationExtensionInterface + */ + private $extensionAttributes; + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentPackageCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Sender/EmailSender.php b/app/code/Magento/Sales/Model/Order/Shipment/Sender/EmailSender.php new file mode 100644 index 0000000000000000000000000000000000000000..228a45ff16aaef74de124cbd24041d1e27227112 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/Sender/EmailSender.php @@ -0,0 +1,149 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment\Sender; + +use Magento\Sales\Model\Order\Email\Sender; +use Magento\Sales\Model\Order\Shipment\SenderInterface; + +/** + * Email notification sender for Shipment. + */ +class EmailSender extends Sender implements SenderInterface +{ + /** + * @var \Magento\Payment\Helper\Data + */ + private $paymentHelper; + + /** + * @var \Magento\Sales\Model\ResourceModel\Order\Shipment + */ + private $shipmentResource; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + private $globalConfig; + + /** + * @var \Magento\Framework\Event\ManagerInterface + */ + private $eventManager; + + /** + * @param \Magento\Sales\Model\Order\Email\Container\Template $templateContainer + * @param \Magento\Sales\Model\Order\Email\Container\ShipmentIdentity $identityContainer + * @param \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory + * @param \Psr\Log\LoggerInterface $logger + * @param \Magento\Sales\Model\Order\Address\Renderer $addressRenderer + * @param \Magento\Payment\Helper\Data $paymentHelper + * @param \Magento\Sales\Model\ResourceModel\Order\Shipment $shipmentResource + * @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig + * @param \Magento\Framework\Event\ManagerInterface $eventManager + */ + public function __construct( + \Magento\Sales\Model\Order\Email\Container\Template $templateContainer, + \Magento\Sales\Model\Order\Email\Container\ShipmentIdentity $identityContainer, + \Magento\Sales\Model\Order\Email\SenderBuilderFactory $senderBuilderFactory, + \Psr\Log\LoggerInterface $logger, + \Magento\Sales\Model\Order\Address\Renderer $addressRenderer, + \Magento\Payment\Helper\Data $paymentHelper, + \Magento\Sales\Model\ResourceModel\Order\Shipment $shipmentResource, + \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig, + \Magento\Framework\Event\ManagerInterface $eventManager + ) { + parent::__construct( + $templateContainer, + $identityContainer, + $senderBuilderFactory, + $logger, + $addressRenderer + ); + + $this->paymentHelper = $paymentHelper; + $this->shipmentResource = $shipmentResource; + $this->globalConfig = $globalConfig; + $this->eventManager = $eventManager; + } + + /** + * Sends order shipment email to the customer. + * + * Email will be sent immediately in two cases: + * + * - if asynchronous email sending is disabled in global settings + * - if $forceSyncMode parameter is set to TRUE + * + * Otherwise, email will be sent later during running of + * corresponding cron job. + * + * @param \Magento\Sales\Api\Data\OrderInterface $order + * @param \Magento\Sales\Api\Data\ShipmentInterface $shipment + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param bool $forceSyncMode + * + * @return bool + */ + public function send( + \Magento\Sales\Api\Data\OrderInterface $order, + \Magento\Sales\Api\Data\ShipmentInterface $shipment, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + $forceSyncMode = false + ) { + $shipment->setSendEmail(true); + + if (!$this->globalConfig->getValue('sales_email/general/async_sending') || $forceSyncMode) { + $transport = [ + 'order' => $order, + 'shipment' => $shipment, + 'comment' => $comment ? $comment->getComment() : '', + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $this->getFormattedShippingAddress($order), + 'formattedBillingAddress' => $this->getFormattedBillingAddress($order) + ]; + + $this->eventManager->dispatch( + 'email_shipment_set_template_vars_before', + ['sender' => $this, 'transport' => $transport] + ); + + $this->templateContainer->setTemplateVars($transport); + + if ($this->checkAndSend($order)) { + $shipment->setEmailSent(true); + + $this->shipmentResource->saveAttribute($shipment, ['send_email', 'email_sent']); + + return true; + } + } else { + $shipment->setEmailSent(null); + + $this->shipmentResource->saveAttribute($shipment, 'email_sent'); + } + + $this->shipmentResource->saveAttribute($shipment, 'send_email'); + + return false; + } + + /** + * Returns payment info block as HTML. + * + * @param \Magento\Sales\Api\Data\OrderInterface $order + * + * @return string + */ + private function getPaymentHtml(\Magento\Sales\Api\Data\OrderInterface $order) + { + return $this->paymentHelper->getInfoBlockHtml( + $order->getPayment(), + $this->identityContainer->getStore()->getStoreId() + ); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/SenderInterface.php b/app/code/Magento/Sales/Model/Order/Shipment/SenderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a030038b7b139a65ebc38fd5f9fb2c1a76f8a188 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/SenderInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +/** + * Interface for notification sender for Shipment. + */ +interface SenderInterface +{ + /** + * Sends notification to a customer. + * + * @param \Magento\Sales\Api\Data\OrderInterface $order + * @param \Magento\Sales\Api\Data\ShipmentInterface $shipment + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param bool $forceSyncMode + * + * @return bool + */ + public function send( + \Magento\Sales\Api\Data\OrderInterface $order, + \Magento\Sales\Api\Data\ShipmentInterface $shipment, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + $forceSyncMode = false + ); +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidator.php b/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..816551b8b322c126d82795349a4ba081598a955c --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidator.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\ShipmentInterface; + +/** + * Class ShipmentValidator + */ +class ShipmentValidator implements ShipmentValidatorInterface +{ + /** + * @var \Magento\Sales\Model\Validator + */ + private $validator; + + /** + * ShipmentValidator constructor. + * @param \Magento\Sales\Model\Validator $validator + */ + public function __construct(\Magento\Sales\Model\Validator $validator) + { + $this->validator = $validator; + } + + /** + * @inheritdoc + */ + public function validate(ShipmentInterface $entity, array $validators) + { + return $this->validator->validate($entity, $validators); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidatorInterface.php b/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..198a4019bf6b898e0c85fd2e2ff7c7ff77c2a9f6 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/ShipmentValidatorInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Exception\DocumentValidationException; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Interface ShipmentValidatorInterface + */ +interface ShipmentValidatorInterface +{ + /** + * @param ShipmentInterface $shipment + * @param ValidatorInterface[] $validators + * @return string[] + * @throws DocumentValidationException + */ + public function validate(ShipmentInterface $shipment, array $validators); +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/TrackCreation.php b/app/code/Magento/Sales/Model/Order/Shipment/TrackCreation.php new file mode 100644 index 0000000000000000000000000000000000000000..6e8ce097f411d91794ea07ce904851bce725f169 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/TrackCreation.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment; + +use Magento\Sales\Api\Data\ShipmentTrackCreationInterface; + +/** + * Class TrackCreation + */ +class TrackCreation implements ShipmentTrackCreationInterface +{ + /** + * @var string + */ + private $trackNumber; + + /** + * @var string + */ + private $title; + + /** + * @var string + */ + private $carrierCode; + + /** + * @var \Magento\Sales\Api\Data\ShipmentTrackCreationExtensionInterface + */ + private $extensionAttributes; + + //@codeCoverageIgnoreStart + + /** + * {@inheritdoc} + */ + public function getTrackNumber() + { + return $this->trackNumber; + } + + /** + * {@inheritdoc} + */ + public function setTrackNumber($trackNumber) + { + $this->trackNumber = $trackNumber; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getTitle() + { + return $this->title; + } + + /** + * {@inheritdoc} + */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCarrierCode() + { + return $this->carrierCode; + } + + /** + * {@inheritdoc} + */ + public function setCarrierCode($carrierCode) + { + $this->carrierCode = $carrierCode; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->extensionAttributes; + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Sales\Api\Data\ShipmentTrackCreationExtensionInterface $extensionAttributes + ) { + $this->extensionAttributes = $extensionAttributes; + return $this; + } + + //@codeCoverageIgnoreEnd +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Validation/QuantityValidator.php b/app/code/Magento/Sales/Model/Order/Shipment/Validation/QuantityValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..20e3712d889ed249ebca9fbbab0945d37a8cb8cf --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/Validation/QuantityValidator.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment\Validation; + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderItemInterface; +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Exception\DocumentValidationException; +use Magento\Sales\Model\Order\Item; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Class QuantityValidator + */ +class QuantityValidator implements ValidatorInterface +{ + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * InvoiceValidator constructor. + * @param OrderRepositoryInterface $orderRepository + */ + public function __construct( + OrderRepositoryInterface $orderRepository + ) { + $this->orderRepository = $orderRepository; + } + + /** + * @param ShipmentInterface $entity + * @return array + * @throws DocumentValidationException + * @throws NoSuchEntityException + */ + public function validate($entity) + { + if ($entity->getOrderId() === null) { + return [__('Order Id is required for shipment document')]; + } + + if (empty($entity->getItems())) { + return [__('You can\'t create a shipment without products.')]; + } + $messages = []; + + $order = $this->orderRepository->get($entity->getOrderId()); + $orderItemsById = $this->getOrderItems($order); + + $totalQuantity = 0; + foreach ($entity->getItems() as $item) { + if (!isset($orderItemsById[$item->getOrderItemId()])) { + $messages[] = __( + 'The shipment contains product SKU "%1" that is not part of the original order.', + $item->getSku() + ); + continue; + } + $orderItem = $orderItemsById[$item->getOrderItemId()]; + + if (!$this->isQtyAvailable($orderItem, $item->getQty())) { + $messages[] =__( + 'The quantity to ship must not be greater than the unshipped quantity' + . ' for product SKU "%1".', + $orderItem->getSku() + ); + } else { + $totalQuantity += $item->getQty(); + } + } + if ($totalQuantity <= 0) { + $messages[] = __('You can\'t create a shipment without products.'); + } + + return $messages; + } + + /** + * @param OrderInterface $order + * @return OrderItemInterface[] + */ + private function getOrderItems(OrderInterface $order) + { + $orderItemsById = []; + foreach ($order->getItems() as $item) { + $orderItemsById[$item->getItemId()] = $item; + } + + return $orderItemsById; + } + + /** + * @param Item $orderItem + * @param int $qty + * @return bool + */ + private function isQtyAvailable(Item $orderItem, $qty) + { + return $qty <= $orderItem->getQtyToShip() || $orderItem->isDummy(true); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Validation/TrackValidator.php b/app/code/Magento/Sales/Model/Order/Shipment/Validation/TrackValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..55970d37c597d7af6d0369e26b2085ab431108ed --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Shipment/Validation/TrackValidator.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Shipment\Validation; + +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Class TrackRequiredField + */ +class TrackValidator implements ValidatorInterface +{ + /** + * @param object|ShipmentInterface $entity + * @return array + */ + public function validate($entity) + { + $messages = []; + if (!$entity->getTracks()) { + return $messages; + } + foreach ($entity->getTracks() as $track) { + if (!$track->getTrackNumber()) { + $messages[] = __('Please enter a tracking number.'); + } + } + return $messages; + } +} diff --git a/app/code/Magento/Sales/Model/Order/ShipmentDocumentFactory.php b/app/code/Magento/Sales/Model/Order/ShipmentDocumentFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..d10f84d8155432954ec95c75f9b49108767f2dd3 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/ShipmentDocumentFactory.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order; + +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Api\Data\ShipmentItemCreationInterface; +use Magento\Sales\Api\Data\ShipmentPackageCreationInterface; +use Magento\Sales\Api\Data\ShipmentTrackCreationInterface; +use Magento\Framework\EntityManager\HydratorPool; +use Magento\Sales\Model\Order\Shipment\TrackFactory; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\ShipmentCommentCreationInterface; +use Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface; + +/** + * Class ShipmentDocumentFactory + * + * @api + */ +class ShipmentDocumentFactory +{ + /** + * @var ShipmentFactory + */ + private $shipmentFactory; + + /** + * @var TrackFactory + */ + private $trackFactory; + + /** + * @var HydratorPool + */ + private $hydratorPool; + + /** + * ShipmentDocumentFactory constructor. + * + * @param ShipmentFactory $shipmentFactory + * @param HydratorPool $hydratorPool + * @param TrackFactory $trackFactory + */ + public function __construct( + ShipmentFactory $shipmentFactory, + HydratorPool $hydratorPool, + TrackFactory $trackFactory + ) { + $this->shipmentFactory = $shipmentFactory; + $this->trackFactory = $trackFactory; + $this->hydratorPool = $hydratorPool; + } + + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * + * @param OrderInterface $order + * @param ShipmentItemCreationInterface[] $items + * @param ShipmentTrackCreationInterface[] $tracks + * @param ShipmentCommentCreationInterface|null $comment + * @param bool $appendComment + * @param ShipmentPackageCreationInterface[] $packages + * @param ShipmentCreationArgumentsInterface|null $arguments + * @return ShipmentInterface + */ + public function create( + OrderInterface $order, + array $items = [], + array $tracks = [], + ShipmentCommentCreationInterface $comment = null, + $appendComment = false, + array $packages = [], + ShipmentCreationArgumentsInterface $arguments = null + ) { + $shipmentItems = $this->itemsToArray($items); + /** @var Shipment $shipment */ + $shipment = $this->shipmentFactory->create( + $order, + $shipmentItems + ); + $this->prepareTracks($shipment, $tracks); + if ($comment) { + $shipment->addComment( + $comment->getComment(), + $appendComment, + $comment->getIsVisibleOnFront() + ); + } + + return $shipment; + } + + /** + * Adds tracks to the shipment. + * + * @param ShipmentInterface $shipment + * @param ShipmentTrackCreationInterface[] $tracks + * @return ShipmentInterface + */ + private function prepareTracks(\Magento\Sales\Api\Data\ShipmentInterface $shipment, array $tracks) + { + foreach ($tracks as $track) { + $hydrator = $this->hydratorPool->getHydrator( + \Magento\Sales\Api\Data\ShipmentTrackCreationInterface::class + ); + $shipment->addTrack($this->trackFactory->create(['data' => $hydrator->extract($track)])); + } + return $shipment; + } + + /** + * Convert items to array + * + * @param ShipmentItemCreationInterface[] $items + * @return array + */ + private function itemsToArray(array $items = []) + { + $shipmentItems = []; + foreach ($items as $item) { + $shipmentItems[$item->getOrderItemId()] = $item->getQty(); + } + return $shipmentItems; + } +} diff --git a/app/code/Magento/Sales/Model/Order/ShipmentFactory.php b/app/code/Magento/Sales/Model/Order/ShipmentFactory.php index 2ac012760ee4704be9defe05cfe7c2d01529359e..a8839c75375870ce03294ca3d585635fdff84f14 100644 --- a/app/code/Magento/Sales/Model/Order/ShipmentFactory.php +++ b/app/code/Magento/Sales/Model/Order/ShipmentFactory.php @@ -5,6 +5,10 @@ */ namespace Magento\Sales\Model\Order; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\LocalizedException; +use Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface; + /** * Factory class for @see \Magento\Sales\Api\Data\ShipmentInterface */ @@ -72,6 +76,8 @@ class ShipmentFactory * @param \Magento\Sales\Model\Order $order * @param array $items * @return \Magento\Sales\Api\Data\ShipmentInterface + * @throws LocalizedException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function prepareItems( \Magento\Sales\Api\Data\ShipmentInterface $shipment, @@ -79,7 +85,6 @@ class ShipmentFactory array $items = [] ) { $totalQty = 0; - foreach ($order->getAllItems() as $orderItem) { if (!$this->canShipItem($orderItem, $items)) { continue; @@ -103,7 +108,7 @@ class ShipmentFactory $qty = $bundleSelectionAttributes['qty'] * $items[$orderItem->getParentItemId()]; $qty = min($qty, $orderItem->getSimpleQtyToShip()); - $item->setQty($qty); + $item->setQty($this->castQty($orderItem, $qty)); $shipment->addItem($item); continue; @@ -126,10 +131,9 @@ class ShipmentFactory $totalQty += $qty; - $item->setQty($qty); + $item->setQty($this->castQty($orderItem, $qty)); $shipment->addItem($item); } - return $shipment->setTotalQty($totalQty); } @@ -211,4 +215,20 @@ class ShipmentFactory return $item->getQtyToShip() > 0; } } + + /** + * @param Item $item + * @param string|int|float $qty + * @return float|int + */ + private function castQty(\Magento\Sales\Model\Order\Item $item, $qty) + { + if ($item->getIsQtyDecimal()) { + $qty = (double)$qty; + } else { + $qty = (int)$qty; + } + + return $qty > 0 ? $qty : 0; + } } diff --git a/app/code/Magento/Sales/Model/Order/Validation/CanInvoice.php b/app/code/Magento/Sales/Model/Order/Validation/CanInvoice.php new file mode 100644 index 0000000000000000000000000000000000000000..bb14dc1bb5180758825966d47d7f92bb06ddacda --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Validation/CanInvoice.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Validation; + +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Class CanInvoice + */ +class CanInvoice implements ValidatorInterface +{ + /** + * @param OrderInterface $entity + * @return array + */ + public function validate($entity) + { + $messages = []; + + if (!$this->isStateReadyForInvoice($entity)) { + $messages[] = __('An invoice cannot be created when an order has a status of %1', $entity->getStatus()); + } elseif (!$this->canInvoice($entity)) { + $messages[] = __('The order does not allow an invoice to be created.'); + } + + return $messages; + } + + /** + * @param OrderInterface $order + * @return bool + */ + private function isStateReadyForInvoice(OrderInterface $order) + { + if ($order->getState() === Order::STATE_PAYMENT_REVIEW || + $order->getState() === Order::STATE_HOLDED || + $order->getState() === Order::STATE_CANCELED || + $order->getState() === Order::STATE_COMPLETE || + $order->getState() === Order::STATE_CLOSED + ) { + return false; + }; + + return true; + } + + /** + * @param OrderInterface $order + * @return bool + */ + private function canInvoice(OrderInterface $order) + { + /** @var \Magento\Sales\Model\Order\Item $item */ + foreach ($order->getItems() as $item) { + if ($item->getQtyToInvoice() > 0 && !$item->getLockedDoInvoice()) { + return true; + } + } + return false; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Validation/CanShip.php b/app/code/Magento/Sales/Model/Order/Validation/CanShip.php new file mode 100644 index 0000000000000000000000000000000000000000..46638a62483e6ce0f45a1c79d2774fe2c34d7970 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Validation/CanShip.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Validation; + +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\ValidatorInterface; + +/** + * Class CanShip + */ +class CanShip implements ValidatorInterface +{ + /** + * @param OrderInterface $entity + * @return array + */ + public function validate($entity) + { + $messages = []; + if (!$this->isStateReadyForShipment($entity)) { + $messages[] = __('A shipment cannot be created when an order has a status of %1', $entity->getStatus()); + } elseif (!$this->canShip($entity)) { + $messages[] = __('The order does not allow a shipment to be created.'); + } + + return $messages; + } + + /** + * @param OrderInterface $order + * @return bool + */ + private function isStateReadyForShipment(OrderInterface $order) + { + if ($order->getState() === Order::STATE_PAYMENT_REVIEW || + $order->getState() === Order::STATE_HOLDED || + $order->getIsVirtual() || + $order->getState() === Order::STATE_CANCELED + ) { + return false; + } + + return true; + } + + /** + * @param OrderInterface $order + * @return bool + */ + private function canShip(OrderInterface $order) + { + /** @var \Magento\Sales\Model\Order\Item $item */ + foreach ($order->getItems() as $item) { + if ($item->getQtyToShip() > 0 && !$item->getIsVirtual() && !$item->getLockedDoShip()) { + return true; + } + } + + return false; + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Plugin/Authorization.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Plugin/Authorization.php index a44a7b78717975a0945ab23a7976c1fc009e371e..f6b459ba4638d0d5db59fe8fb06d3054f5299ec3 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Plugin/Authorization.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Plugin/Authorization.php @@ -8,6 +8,8 @@ namespace Magento\Sales\Model\ResourceModel\Order\Plugin; use Magento\Authorization\Model\UserContextInterface; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\ResourceModel\Order as ResourceOrder; class Authorization { @@ -20,33 +22,28 @@ class Authorization * @param UserContextInterface $userContext */ public function __construct( - \Magento\Authorization\Model\UserContextInterface $userContext + UserContextInterface $userContext ) { $this->userContext = $userContext; } /** - * Checks if order is allowed - * - * @param \Magento\Sales\Model\ResourceModel\Order $subject - * @param callable $proceed + * @param ResourceOrder $subject + * @param ResourceOrder $result * @param \Magento\Framework\Model\AbstractModel $order - * @param mixed $value - * @param null|string $field - * @return \Magento\Sales\Model\Order + * @return ResourceOrder * @throws NoSuchEntityException * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundLoad( - \Magento\Sales\Model\ResourceModel\Order $subject, - \Closure $proceed, - \Magento\Framework\Model\AbstractModel $order, - $value, - $field = null + public function afterLoad( + ResourceOrder $subject, + ResourceOrder $result, + \Magento\Framework\Model\AbstractModel $order ) { - $result = $proceed($order, $value, $field); - if (!$this->isAllowed($order)) { - throw NoSuchEntityException::singleField('orderId', $order->getId()); + if ($order instanceof Order) { + if (!$this->isAllowed($order)) { + throw NoSuchEntityException::singleField('orderId', $order->getId()); + } } return $result; } @@ -57,7 +54,7 @@ class Authorization * @param \Magento\Sales\Model\Order $order * @return bool */ - protected function isAllowed(\Magento\Sales\Model\Order $order) + protected function isAllowed(Order $order) { return $this->userContext->getUserType() == UserContextInterface::USER_TYPE_CUSTOMER ? $order->getCustomerId() == $this->userContext->getUserId() diff --git a/app/code/Magento/Sales/Model/ShipOrder.php b/app/code/Magento/Sales/Model/ShipOrder.php new file mode 100644 index 0000000000000000000000000000000000000000..d051144cf73ca166c30ebd6eb9f626306b1720a6 --- /dev/null +++ b/app/code/Magento/Sales/Model/ShipOrder.php @@ -0,0 +1,206 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model; + +use Magento\Framework\App\ResourceConnection; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Api\ShipmentRepositoryInterface; +use Magento\Sales\Api\ShipOrderInterface; +use Magento\Sales\Model\Order\Config as OrderConfig; +use Magento\Sales\Model\Order\OrderStateResolverInterface; +use Magento\Sales\Model\Order\OrderValidatorInterface; +use Magento\Sales\Model\Order\ShipmentDocumentFactory; +use Magento\Sales\Model\Order\Shipment\NotifierInterface; +use Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface; +use Magento\Sales\Model\Order\Shipment\Validation\QuantityValidator; +use Magento\Sales\Model\Order\Shipment\Validation\TrackValidator; +use Magento\Sales\Model\Order\Validation\CanShip; +use Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface; +use Psr\Log\LoggerInterface; + +/** + * Class ShipOrder + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ShipOrder implements ShipOrderInterface +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var ShipmentDocumentFactory + */ + private $shipmentDocumentFactory; + + /** + * @var ShipmentValidatorInterface + */ + private $shipmentValidator; + + /** + * @var OrderStateResolverInterface + */ + private $orderStateResolver; + + /** + * @var OrderConfig + */ + private $config; + + /** + * @var ShipmentRepositoryInterface + */ + private $shipmentRepository; + + /** + * @var NotifierInterface + */ + private $notifierInterface; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var OrderValidatorInterface + */ + private $orderValidator; + + /** + * @var OrderRegistrarInterface + */ + private $orderRegistrar; + + /** + * @param ResourceConnection $resourceConnection + * @param OrderRepositoryInterface $orderRepository + * @param ShipmentDocumentFactory $shipmentDocumentFactory + * @param ShipmentValidatorInterface $shipmentValidator + * @param OrderValidatorInterface $orderValidator + * @param OrderStateResolverInterface $orderStateResolver + * @param OrderConfig $config + * @param ShipmentRepositoryInterface $shipmentRepository + * @param NotifierInterface $notifierInterface + * @param OrderRegistrarInterface $orderRegistrar + * @param LoggerInterface $logger + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + ResourceConnection $resourceConnection, + OrderRepositoryInterface $orderRepository, + ShipmentDocumentFactory $shipmentDocumentFactory, + ShipmentValidatorInterface $shipmentValidator, + OrderValidatorInterface $orderValidator, + OrderStateResolverInterface $orderStateResolver, + OrderConfig $config, + ShipmentRepositoryInterface $shipmentRepository, + NotifierInterface $notifierInterface, + OrderRegistrarInterface $orderRegistrar, + LoggerInterface $logger + ) { + $this->resourceConnection = $resourceConnection; + $this->orderRepository = $orderRepository; + $this->shipmentDocumentFactory = $shipmentDocumentFactory; + $this->shipmentValidator = $shipmentValidator; + $this->orderValidator = $orderValidator; + $this->orderStateResolver = $orderStateResolver; + $this->config = $config; + $this->shipmentRepository = $shipmentRepository; + $this->notifierInterface = $notifierInterface; + $this->logger = $logger; + $this->orderRegistrar = $orderRegistrar; + } + + /** + * @param int $orderId + * @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items + * @param bool $notify + * @param bool $appendComment + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks + * @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages + * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments + * @return int + * @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface + * @throws \Magento\Sales\Api\Exception\CouldNotShipExceptionInterface + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \DomainException + */ + public function execute( + $orderId, + array $items = [], + $notify = false, + $appendComment = false, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, + array $tracks = [], + array $packages = [], + \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null + ) { + $connection = $this->resourceConnection->getConnection('sales'); + $order = $this->orderRepository->get($orderId); + $shipment = $this->shipmentDocumentFactory->create( + $order, + $items, + $tracks, + $comment, + ($appendComment && $notify), + $packages, + $arguments + ); + $orderValidationResult = $this->orderValidator->validate( + $order, + [ + CanShip::class + ] + ); + $shipmentValidationResult = $this->shipmentValidator->validate( + $shipment, + [ + QuantityValidator::class, + TrackValidator::class + ] + ); + $validationMessages = array_merge($orderValidationResult, $shipmentValidationResult); + if (!empty($validationMessages)) { + throw new \Magento\Sales\Exception\DocumentValidationException( + __("Shipment Document Validation Error(s):\n" . implode("\n", $validationMessages)) + ); + } + $connection->beginTransaction(); + try { + $this->orderRegistrar->register($order, $shipment); + $order->setState( + $this->orderStateResolver->getStateForOrder($order, [OrderStateResolverInterface::IN_PROGRESS]) + ); + $order->setStatus($this->config->getStateDefaultStatus($order->getState())); + $this->shipmentRepository->save($shipment); + $this->orderRepository->save($order); + $connection->commit(); + } catch (\Exception $e) { + $this->logger->critical($e); + $connection->rollBack(); + throw new \Magento\Sales\Exception\CouldNotShipException( + __('Could not save a shipment, see error log for details') + ); + } + if ($notify) { + if (!$appendComment) { + $comment = null; + } + $this->notifierInterface->notify($order, $shipment, $comment); + } + return $shipment->getEntityId(); + } +} diff --git a/app/code/Magento/Sales/Model/Validator.php b/app/code/Magento/Sales/Model/Validator.php new file mode 100644 index 0000000000000000000000000000000000000000..b8d57ded2970209d5d2184945fbb22f13de47dbd --- /dev/null +++ b/app/code/Magento/Sales/Model/Validator.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model; + +use Magento\Framework\Exception\ConfigurationMismatchException; +use Magento\Framework\ObjectManagerInterface; + +/** + * Class Validator + * + * @internal + */ +class Validator +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * Validator constructor. + * + * @param ObjectManagerInterface $objectManager + */ + public function __construct(ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * @param object $entity + * @param ValidatorInterface[] $validators + * @return string[] + * @throws ConfigurationMismatchException + */ + public function validate($entity, array $validators) + { + $messages = []; + foreach ($validators as $validatorName) { + $validator = $this->objectManager->get($validatorName); + if (!$validator instanceof ValidatorInterface) { + throw new ConfigurationMismatchException( + __( + sprintf('Validator %s is not instance of general validator interface', $validatorName) + ) + ); + } + $messages = array_merge($messages, $validator->validate($entity)); + } + + return $messages; + } +} diff --git a/app/code/Magento/Sales/Model/ValidatorInterface.php b/app/code/Magento/Sales/Model/ValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1882782e314f7b47b507c042697f223eadbf36b7 --- /dev/null +++ b/app/code/Magento/Sales/Model/ValidatorInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model; + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Sales\Exception\DocumentValidationException; + +/** + * Interface ValidatorInterface + */ +interface ValidatorInterface +{ + /** + * @param object $entity + * @return array + * @throws DocumentValidationException + * @throws NoSuchEntityException + */ + public function validate($entity); +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderInvoiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/InvoiceOrderTest.php similarity index 89% rename from app/code/Magento/Sales/Test/Unit/Model/OrderInvoiceTest.php rename to app/code/Magento/Sales/Test/Unit/Model/InvoiceOrderTest.php index bc36da112aa291e82e5f06af887334095544f43f..6dfa929acb6290e0e95bf2011b76ec9811691ecc 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderInvoiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/InvoiceOrderTest.php @@ -14,21 +14,23 @@ use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Config as OrderConfig; +use Magento\Sales\Model\Order\Invoice\InvoiceValidatorInterface; use Magento\Sales\Model\Order\Invoice\NotifierInterface; use Magento\Sales\Model\Order\InvoiceDocumentFactory; use Magento\Sales\Model\Order\InvoiceRepository; -use Magento\Sales\Model\Order\InvoiceValidatorInterface; use Magento\Sales\Model\Order\OrderStateResolverInterface; +use Magento\Sales\Model\Order\OrderValidatorInterface; use Magento\Sales\Model\Order\PaymentAdapterInterface; -use Magento\Sales\Model\OrderInvoice; +use Magento\Sales\Model\InvoiceOrder; use Psr\Log\LoggerInterface; /** - * Class OrderInvoiceTest + * Class InvoiceOrderTest + * * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class OrderInvoiceTest extends \PHPUnit_Framework_TestCase +class InvoiceOrderTest extends \PHPUnit_Framework_TestCase { /** * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject @@ -50,6 +52,11 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase */ private $invoiceValidatorMock; + /** + * @var OrderValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderValidatorMock; + /** * @var PaymentAdapterInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -76,9 +83,9 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase private $notifierInterfaceMock; /** - * @var OrderInvoice|\PHPUnit_Framework_MockObject_MockObject + * @var InvoiceOrder|\PHPUnit_Framework_MockObject_MockObject */ - private $orderInvoice; + private $invoiceOrder; /** * @var InvoiceCreationArgumentsInterface|\PHPUnit_Framework_MockObject_MockObject @@ -128,6 +135,10 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); + $this->orderValidatorMock = $this->getMockBuilder(OrderValidatorInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->paymentAdapterMock = $this->getMockBuilder(PaymentAdapterInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -172,11 +183,12 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $this->orderInvoice = new OrderInvoice( + $this->invoiceOrder = new InvoiceOrder( $this->resourceConnectionMock, $this->orderRepositoryMock, $this->invoiceDocumentFactoryMock, $this->invoiceValidatorMock, + $this->orderValidatorMock, $this->paymentAdapterMock, $this->orderStateResolverMock, $this->configMock, @@ -212,7 +224,11 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase $this->invoiceValidatorMock->expects($this->once()) ->method('validate') - ->with($this->invoiceMock, $this->orderMock) + ->with($this->invoiceMock) + ->willReturn([]); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) ->willReturn([]); $this->paymentAdapterMock->expects($this->once()) @@ -271,7 +287,7 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase $this->assertEquals( 2, - $this->orderInvoice->execute( + $this->invoiceOrder->execute( $orderId, $capture, $items, @@ -311,10 +327,14 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase $this->invoiceValidatorMock->expects($this->once()) ->method('validate') - ->with($this->invoiceMock, $this->orderMock) + ->with($this->invoiceMock) ->willReturn($errorMessages); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) + ->willReturn([]); - $this->orderInvoice->execute( + $this->invoiceOrder->execute( $orderId, $capture, $items, @@ -356,7 +376,11 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase $this->invoiceValidatorMock->expects($this->once()) ->method('validate') - ->with($this->invoiceMock, $this->orderMock) + ->with($this->invoiceMock) + ->willReturn([]); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) ->willReturn([]); $e = new \Exception(); @@ -372,7 +396,7 @@ class OrderInvoiceTest extends \PHPUnit_Framework_TestCase $this->adapterInterface->expects($this->once()) ->method('rollBack'); - $this->orderInvoice->execute( + $this->invoiceOrder->execute( $orderId, $capture, $items, diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php similarity index 66% rename from app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceValidatorTest.php rename to app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php index 6fdfdb61b36359d367200e8506ef9484200c723e..8d800e12a6ff0a562330aee3ea09f25f44fae23d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceQuantityValidatorTest.php @@ -6,15 +6,16 @@ namespace Magento\Sales\Test\Unit\Model\Order; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order; /** * Test for \Magento\Sales\Model\Order\InvoiceValidator class */ -class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase +class InvoiceQuantityValidatorTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sales\Model\Order\InvoiceValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\InvoiceQuantityValidator|\PHPUnit_Framework_MockObject_MockObject */ private $model; @@ -24,14 +25,14 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase private $objectManager; /** - * @var \Magento\Sales\Model\Order\OrderValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Api\Data\OrderInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $orderValidatorMock; + private $orderMock; /** - * @var \Magento\Sales\Api\Data\OrderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Api\OrderRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $orderMock; + private $orderRepositoryMock; /** * @var \Magento\Sales\Api\Data\InvoiceInterface|\PHPUnit_Framework_MockObject_MockObject @@ -42,24 +43,21 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->orderValidatorMock = $this->getMockBuilder(\Magento\Sales\Model\Order\OrderValidatorInterface::class) - ->disableOriginalConstructor() - ->setMethods(['canInvoice']) - ->getMockForAbstractClass(); - $this->orderMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderInterface::class) ->disableOriginalConstructor() - ->setMethods(['getStatus']) ->getMockForAbstractClass(); $this->invoiceMock = $this->getMockBuilder(\Magento\Sales\Api\Data\InvoiceInterface::class) ->disableOriginalConstructor() ->setMethods(['getTotalQty', 'getItems']) ->getMockForAbstractClass(); - + $this->orderRepositoryMock = $this->getMockBuilder( + OrderRepositoryInterface::class + )->disableOriginalConstructor()->getMockForAbstractClass(); + $this->orderRepositoryMock->expects($this->any())->method('get')->willReturn($this->orderMock); $this->model = $this->objectManager->getObject( - \Magento\Sales\Model\Order\InvoiceValidator::class, - ['orderValidator' => $this->orderValidatorMock] + \Magento\Sales\Model\Order\InvoiceQuantityValidator::class, + ['orderRepository' => $this->orderRepositoryMock] ); } @@ -75,39 +73,12 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase $this->orderMock->expects($this->once()) ->method('getItems') ->willReturn([$orderItemMock]); - $this->orderValidatorMock->expects($this->once()) - ->method('canInvoice') - ->with($this->orderMock) - ->willReturn(true); - $this->assertEquals( - $expectedResult, - $this->model->validate($this->invoiceMock, $this->orderMock) - ); - } - - public function testValidateCanNotInvoiceOrder() - { - $orderStatus = 'Test Status'; - $expectedResult = [__('An invoice cannot be created when an order has a status of %1.', $orderStatus)]; - $invoiceItemMock = $this->getInvoiceItemMock(1, 1); - $this->invoiceMock->expects($this->once()) - ->method('getItems') - ->willReturn([$invoiceItemMock]); - - $orderItemMock = $this->getOrderItemMock(1, 1, true); - $this->orderMock->expects($this->once()) - ->method('getItems') - ->willReturn([$orderItemMock]); - $this->orderMock->expects($this->once()) - ->method('getStatus') - ->willReturn($orderStatus); - $this->orderValidatorMock->expects($this->once()) - ->method('canInvoice') - ->with($this->orderMock) - ->willReturn(false); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getOrderId') + ->willReturn(1); $this->assertEquals( $expectedResult, - $this->model->validate($this->invoiceMock, $this->orderMock) + $this->model->validate($this->invoiceMock) ); } @@ -125,13 +96,12 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase $this->orderMock->expects($this->once()) ->method('getItems') ->willReturn([$orderItemMock]); - $this->orderValidatorMock->expects($this->once()) - ->method('canInvoice') - ->with($this->orderMock) - ->willReturn(true); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getOrderId') + ->willReturn(1); $this->assertEquals( $expectedResult, - $this->model->validate($this->invoiceMock, $this->orderMock) + $this->model->validate($this->invoiceMock) ); } @@ -146,13 +116,21 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase $this->orderMock->expects($this->once()) ->method('getItems') ->willReturn([]); - $this->orderValidatorMock->expects($this->once()) - ->method('canInvoice') - ->with($this->orderMock) - ->willReturn(true); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getOrderId') + ->willReturn(1); + $this->assertEquals( + $expectedResult, + $this->model->validate($this->invoiceMock) + ); + } + + public function testValidateNoOrder() + { + $expectedResult = [__('Order Id is required for invoice document')]; $this->assertEquals( $expectedResult, - $this->model->validate($this->invoiceMock, $this->orderMock) + $this->model->validate($this->invoiceMock) ); } @@ -169,13 +147,12 @@ class InvoiceValidatorTest extends \PHPUnit_Framework_TestCase $this->orderMock->expects($this->once()) ->method('getItems') ->willReturn([$orderItemMock]); - $this->orderValidatorMock->expects($this->once()) - ->method('canInvoice') - ->with($this->orderMock) - ->willReturn(true); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getOrderId') + ->willReturn(1); $this->assertEquals( $expectedResult, - $this->model->validate($this->invoiceMock, $this->orderMock) + $this->model->validate($this->invoiceMock) ); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/OrderRegistrarTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/OrderRegistrarTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e5bff791edcca99d72918eaacb915a4257b60e37 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/OrderRegistrarTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\Order\Shipment; + +class OrderRegistrarTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Order\Shipment\OrderRegistrar + */ + private $model; + + /** + * @var \Magento\Sales\Api\Data\OrderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + + /** + * @var \Magento\Sales\Api\Data\ShipmentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentMock; + + protected function setUp() + { + $this->orderMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->shipmentMock = $this->getMockBuilder(\Magento\Sales\Api\Data\ShipmentInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->model = new \Magento\Sales\Model\Order\Shipment\OrderRegistrar(); + } + + public function testRegister() + { + $item1 = $this->getShipmentItemMock(); + $item1->expects($this->once()) + ->method('getQty') + ->willReturn(0); + $item1->expects($this->never()) + ->method('register'); + + $item2 = $this->getShipmentItemMock(); + $item2->expects($this->once()) + ->method('getQty') + ->willReturn(0.5); + $item2->expects($this->once()) + ->method('register'); + + $items = [$item1, $item2]; + $this->shipmentMock->expects($this->once()) + ->method('getItems') + ->willReturn($items); + $this->assertEquals( + $this->orderMock, + $this->model->register($this->orderMock, $this->shipmentMock) + ); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getShipmentItemMock() + { + return $this->getMockBuilder(\Magento\Sales\Api\Data\ShipmentItemInterface::class) + ->disableOriginalConstructor() + ->setMethods(['register']) + ->getMockForAbstractClass(); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Sender/EmailSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Sender/EmailSenderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8373c7e57d0fe32a400a02f0f77362b9676bf3f6 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Sender/EmailSenderTest.php @@ -0,0 +1,361 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\Order\Shipment\Sender; + +/** + * Unit test for email notification sender for Shipment. + * + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class EmailSenderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Order\Shipment\Sender\EmailSender + */ + private $subject; + + /** + * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + + /** + * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeMock; + + /** + * @var \Magento\Sales\Model\Order\Email\Sender|\PHPUnit_Framework_MockObject_MockObject + */ + private $senderMock; + + /** + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $loggerMock; + + /** + * @var \Magento\Sales\Api\Data\ShipmentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentMock; + + /** + * @var \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $commentMock; + + /** + * @var \Magento\Sales\Model\Order\Address|\PHPUnit_Framework_MockObject_MockObject + */ + private $addressMock; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $globalConfigMock; + + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $eventManagerMock; + + /** + * @var \Magento\Payment\Model\Info|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentInfoMock; + + /** + * @var \Magento\Payment\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentHelperMock; + + /** + * @var \Magento\Sales\Model\ResourceModel\Order\Shipment|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentResourceMock; + + /** + * @var \Magento\Sales\Model\Order\Address\Renderer|\PHPUnit_Framework_MockObject_MockObject + */ + private $addressRendererMock; + + /** + * @var \Magento\Sales\Model\Order\Email\Container\Template|\PHPUnit_Framework_MockObject_MockObject + */ + private $templateContainerMock; + + /** + * @var \Magento\Sales\Model\Order\Email\Container\ShipmentIdentity|\PHPUnit_Framework_MockObject_MockObject + */ + private $identityContainerMock; + + /** + * @var \Magento\Sales\Model\Order\Email\SenderBuilderFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $senderBuilderFactoryMock; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function setUp() + { + $this->orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->setMethods(['getStoreId']) + ->disableOriginalConstructor() + ->getMock(); + + $this->storeMock->expects($this->any()) + ->method('getStoreId') + ->willReturn(1); + $this->orderMock->expects($this->any()) + ->method('getStore') + ->willReturn($this->storeMock); + + $this->senderMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Email\Sender::class) + ->disableOriginalConstructor() + ->setMethods(['send', 'sendCopyTo']) + ->getMock(); + + $this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Shipment::class) + ->disableOriginalConstructor() + ->setMethods(['setSendEmail', 'setEmailSent']) + ->getMock(); + + $this->commentMock = $this->getMockBuilder(\Magento\Sales\Api\Data\ShipmentCommentCreationInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->commentMock->expects($this->any()) + ->method('getComment') + ->willReturn('Comment text'); + + $this->addressMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Address::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock->expects($this->any()) + ->method('getBillingAddress') + ->willReturn($this->addressMock); + $this->orderMock->expects($this->any()) + ->method('getShippingAddress') + ->willReturn($this->addressMock); + + $this->globalConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->paymentInfoMock = $this->getMockBuilder(\Magento\Payment\Model\Info::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock->expects($this->any()) + ->method('getPayment') + ->willReturn($this->paymentInfoMock); + + $this->paymentHelperMock = $this->getMockBuilder(\Magento\Payment\Helper\Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->paymentHelperMock->expects($this->any()) + ->method('getInfoBlockHtml') + ->with($this->paymentInfoMock, 1) + ->willReturn('Payment Info Block'); + + $this->shipmentResourceMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Shipment::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->addressRendererMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Address\Renderer::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->addressRendererMock->expects($this->any()) + ->method('format') + ->with($this->addressMock, 'html') + ->willReturn('Formatted address'); + + $this->templateContainerMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Email\Container\Template::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->identityContainerMock = $this->getMockBuilder( + \Magento\Sales\Model\Order\Email\Container\ShipmentIdentity::class + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->identityContainerMock->expects($this->any()) + ->method('getStore') + ->willReturn($this->storeMock); + + $this->senderBuilderFactoryMock = $this->getMockBuilder( + \Magento\Sales\Model\Order\Email\SenderBuilderFactory::class + ) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->subject = new \Magento\Sales\Model\Order\Shipment\Sender\EmailSender( + $this->templateContainerMock, + $this->identityContainerMock, + $this->senderBuilderFactoryMock, + $this->loggerMock, + $this->addressRendererMock, + $this->paymentHelperMock, + $this->shipmentResourceMock, + $this->globalConfigMock, + $this->eventManagerMock + ); + } + + /** + * @param int $configValue + * @param bool $forceSyncMode + * @param bool $isComment + * @param bool $emailSendingResult + * + * @dataProvider sendDataProvider + * + * @return void + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testSend($configValue, $forceSyncMode, $isComment, $emailSendingResult) + { + $this->globalConfigMock->expects($this->once()) + ->method('getValue') + ->with('sales_email/general/async_sending') + ->willReturn($configValue); + + if (!$isComment) { + $this->commentMock = null; + } + + $this->shipmentMock->expects($this->once()) + ->method('setSendEmail') + ->with(true); + + if (!$configValue || $forceSyncMode) { + $transport = [ + 'order' => $this->orderMock, + 'shipment' => $this->shipmentMock, + 'comment' => $isComment ? 'Comment text' : '', + 'billing' => $this->addressMock, + 'payment_html' => 'Payment Info Block', + 'store' => $this->storeMock, + 'formattedShippingAddress' => 'Formatted address', + 'formattedBillingAddress' => 'Formatted address', + ]; + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'email_shipment_set_template_vars_before', + [ + 'sender' => $this->subject, + 'transport' => $transport, + ] + ); + + $this->templateContainerMock->expects($this->once()) + ->method('setTemplateVars') + ->with($transport); + + $this->identityContainerMock->expects($this->once()) + ->method('isEnabled') + ->willReturn($emailSendingResult); + + if ($emailSendingResult) { + $this->senderBuilderFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->senderMock); + + $this->senderMock->expects($this->once()) + ->method('send'); + + $this->senderMock->expects($this->once()) + ->method('sendCopyTo'); + + $this->shipmentMock->expects($this->once()) + ->method('setEmailSent') + ->with(true); + + $this->shipmentResourceMock->expects($this->once()) + ->method('saveAttribute') + ->with($this->shipmentMock, ['send_email', 'email_sent']); + + $this->assertTrue( + $this->subject->send( + $this->orderMock, + $this->shipmentMock, + $this->commentMock, + $forceSyncMode + ) + ); + } else { + $this->shipmentResourceMock->expects($this->once()) + ->method('saveAttribute') + ->with($this->shipmentMock, 'send_email'); + + $this->assertFalse( + $this->subject->send( + $this->orderMock, + $this->shipmentMock, + $this->commentMock, + $forceSyncMode + ) + ); + } + } else { + $this->shipmentMock->expects($this->once()) + ->method('setEmailSent') + ->with(null); + + $this->shipmentResourceMock->expects($this->at(0)) + ->method('saveAttribute') + ->with($this->shipmentMock, 'email_sent'); + $this->shipmentResourceMock->expects($this->at(1)) + ->method('saveAttribute') + ->with($this->shipmentMock, 'send_email'); + + $this->assertFalse( + $this->subject->send( + $this->orderMock, + $this->shipmentMock, + $this->commentMock, + $forceSyncMode + ) + ); + } + } + + /** + * @return array + */ + public function sendDataProvider() + { + return [ + 'Successful sync sending with comment' => [0, false, true, true], + 'Successful sync sending without comment' => [0, false, false, true], + 'Failed sync sending with comment' => [0, false, true, false], + 'Successful forced sync sending with comment' => [1, true, true, true], + 'Async sending' => [1, false, false, false], + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/QuantityValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/QuantityValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..01cccd2458695247f2c67f8e35fd40a71dc1b757 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/QuantityValidatorTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\Order\Shipment\Validation; + +use Magento\Sales\Model\Order\Shipment\Validation\QuantityValidator; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Api\Data\ShipmentItemInterface; + +/** + * Class QuantityValidatorTest + */ +class QuantityValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var QuantityValidator + */ + private $validator; + + /** + * @var ShipmentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentMock; + + /** + * @var ShipmentItemInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentItemMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + $this->shipmentMock = $this->getMockBuilder(ShipmentInterface::class) + ->getMock(); + $this->shipmentItemMock = $this->getMockBuilder(ShipmentItemInterface::class) + ->getMock(); + $this->validator = $objectManagerHelper->getObject(QuantityValidator::class); + } + + public function testValidateTrackWithoutOrderId() + { + $this->shipmentMock->expects($this->once()) + ->method('getOrderId') + ->willReturn(null); + $this->assertEquals( + [__('Order Id is required for shipment document')], + $this->validator->validate($this->shipmentMock) + ); + } + + public function testValidateTrackWithoutItems() + { + $this->shipmentMock->expects($this->once()) + ->method('getOrderId') + ->willReturn(1); + $this->shipmentMock->expects($this->once()) + ->method('getItems') + ->willReturn(null); + $this->assertEquals( + [__('You can\'t create a shipment without products.')], + $this->validator->validate($this->shipmentMock) + ); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/TrackValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/TrackValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0d8d951ccf18acd29649b8de05a5c3f97ce5a8c1 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/Validation/TrackValidatorTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\Order\Shipment\Validation; + +use Magento\Sales\Model\Order\Shipment\Validation\TrackValidator; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Api\Data\ShipmentTrackInterface; + +/** + * Class TrackValidatorTest + */ +class TrackValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var TrackValidator + */ + private $validator; + + /** + * @var ShipmentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentMock; + + /** + * @var ShipmentTrackInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentTrackMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + $this->shipmentMock = $this->getMockBuilder(ShipmentInterface::class) + ->getMockForAbstractClass(); + $this->shipmentTrackMock = $this->getMockBuilder(ShipmentTrackInterface::class) + ->getMockForAbstractClass(); + $this->validator = $objectManagerHelper->getObject(TrackValidator::class); + } + + public function testValidateTrackWithNumber() + { + $this->shipmentTrackMock->expects($this->once()) + ->method('getTrackNumber') + ->willReturn('12345'); + $this->shipmentMock->expects($this->exactly(2)) + ->method('getTracks') + ->willReturn([$this->shipmentTrackMock]); + $this->assertEquals([], $this->validator->validate($this->shipmentMock)); + } + + public function testValidateTrackWithoutNumber() + { + $this->shipmentTrackMock->expects($this->once()) + ->method('getTrackNumber') + ->willReturn(null); + $this->shipmentMock->expects($this->exactly(2)) + ->method('getTracks') + ->willReturn([$this->shipmentTrackMock]); + $this->assertEquals([__('Please enter a tracking number.')], $this->validator->validate($this->shipmentMock)); + } + + public function testValidateTrackWithEmptyTracks() + { + $this->shipmentTrackMock->expects($this->never()) + ->method('getTrackNumber'); + $this->shipmentMock->expects($this->once()) + ->method('getTracks') + ->willReturn([]); + $this->assertEquals([], $this->validator->validate($this->shipmentMock)); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentDocumentFactoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentDocumentFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b0677b050f6fbe4f7b1894a34481a6aa59fcecd9 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentDocumentFactoryTest.php @@ -0,0 +1,195 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\Order; + +use Magento\Framework\EntityManager\HydratorPool; +use Magento\Sales\Api\Data\ShipmentCommentCreationInterface; +use Magento\Sales\Api\Data\ShipmentItemCreationInterface; +use Magento\Sales\Api\Data\ShipmentTrackCreationInterface; +use Magento\Sales\Model\Order\ShipmentFactory; +use Magento\Sales\Model\Order\ShipmentDocumentFactory; +use Magento\Sales\Model\Order; +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Model\Order\Shipment\TrackFactory; +use Magento\Sales\Model\Order\Shipment\Track; +use Magento\Framework\EntityManager\HydratorInterface; + +/** + * Class ShipmentDocumentFactoryTest + */ +class ShipmentDocumentFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentFactory + */ + private $shipmentFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Order + */ + private $orderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentItemCreationInterface + */ + private $itemMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentCommentCreationInterface + */ + private $commentMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|ShipmentInterface + */ + private $shipmentMock; + + /** + * @var ShipmentDocumentFactory + */ + private $shipmentDocumentFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|HydratorPool + */ + private $hydratorPoolMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|TrackFactory + */ + private $trackFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|HydratorInterface + */ + private $hydratorMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Track + */ + private $trackMock; + + protected function setUp() + { + $this->shipmentFactoryMock = $this->getMockBuilder(ShipmentFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->itemMock = $this->getMockBuilder(ShipmentItemCreationInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->commentMock = $this->getMockBuilder(ShipmentCommentCreationInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->shipmentMock = $this->getMockBuilder(ShipmentInterface::class) + ->disableOriginalConstructor() + ->setMethods(['addComment', 'addTrack']) + ->getMockForAbstractClass(); + + $this->hydratorPoolMock = $this->getMockBuilder(HydratorPool::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->trackFactoryMock = $this->getMockBuilder(TrackFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->trackMock = $this->getMockBuilder(Track::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->hydratorMock = $this->getMockBuilder(HydratorInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentDocumentFactory = new ShipmentDocumentFactory( + $this->shipmentFactoryMock, + $this->hydratorPoolMock, + $this->trackFactoryMock + ); + } + + public function testCreate() + { + $trackNum = "123456789"; + $trackData = [$trackNum]; + $tracks = [$this->trackMock]; + $appendComment = true; + $packages = []; + $items = [1 => 10]; + + $this->itemMock->expects($this->once()) + ->method('getOrderItemId') + ->willReturn(1); + + $this->itemMock->expects($this->once()) + ->method('getQty') + ->willReturn(10); + + $this->shipmentFactoryMock->expects($this->once()) + ->method('create') + ->with( + $this->orderMock, + $items + ) + ->willReturn($this->shipmentMock); + + $this->shipmentMock->expects($this->once()) + ->method('addTrack') + ->willReturnSelf(); + + $this->hydratorPoolMock->expects($this->once()) + ->method('getHydrator') + ->with(ShipmentTrackCreationInterface::class) + ->willReturn($this->hydratorMock); + + $this->hydratorMock->expects($this->once()) + ->method('extract') + ->with($this->trackMock) + ->willReturn($trackData); + + $this->trackFactoryMock->expects($this->once()) + ->method('create') + ->with(['data' => $trackData]) + ->willReturn($this->trackMock); + + if ($appendComment) { + $comment = "New comment!"; + $visibleOnFront = true; + $this->commentMock->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + + $this->commentMock->expects($this->once()) + ->method('getIsVisibleOnFront') + ->willReturn($visibleOnFront); + + $this->shipmentMock->expects($this->once()) + ->method('addComment') + ->with($comment, $appendComment, $visibleOnFront) + ->willReturnSelf(); + } + + $this->assertEquals( + $this->shipmentDocumentFactory->create( + $this->orderMock, + [$this->itemMock], + $tracks, + $this->commentMock, + $appendComment, + $packages + ), + $this->shipmentMock + ); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php index 3760934457a85eae8f3e4f6f4b8070b1ef7d716a..46d6ac62fc256a45b76edb12c787f4627f8f0ed7 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php @@ -5,10 +5,9 @@ */ namespace Magento\Sales\Test\Unit\Model\Order; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; - /** * Unit test for shipment factory class. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShipmentFactoryTest extends \PHPUnit_Framework_TestCase { @@ -39,7 +38,7 @@ class ShipmentFactoryTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $objectManager = new ObjectManager($this); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->converter = $this->getMock( \Magento\Sales\Model\Convert\Order::class, diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/OrderValidatorTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanInvoiceTest.php similarity index 77% rename from app/code/Magento/Sales/Test/Unit/Model/Order/OrderValidatorTest.php rename to app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanInvoiceTest.php index 905d7c7a5b3f89951afcd261904a99df38f27ce5..dd76bc1e52586fe57a68d1e5c3278441a18eddd6 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/OrderValidatorTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanInvoiceTest.php @@ -4,17 +4,17 @@ * See COPYING.txt for license details. */ -namespace Magento\Sales\Test\Unit\Model\Order; +namespace Magento\Sales\Test\Unit\Model\Order\Validation; use Magento\Sales\Model\Order; /** * Test for \Magento\Sales\Model\Order\OrderValidator class */ -class OrderValidatorTest extends \PHPUnit_Framework_TestCase +class CanInvoiceTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sales\Model\Order\OrderValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Validation\CanInvoice|\PHPUnit_Framework_MockObject_MockObject */ private $model; @@ -47,7 +47,7 @@ class OrderValidatorTest extends \PHPUnit_Framework_TestCase ->setMethods(['getQtyToInvoice', 'getLockedDoInvoice']) ->getMockForAbstractClass(); - $this->model = new \Magento\Sales\Model\Order\OrderValidator(); + $this->model = new \Magento\Sales\Model\Order\Validation\CanInvoice(); } /** @@ -62,9 +62,12 @@ class OrderValidatorTest extends \PHPUnit_Framework_TestCase ->willReturn($state); $this->orderMock->expects($this->never()) ->method('getItems'); + $this->orderMock->expects($this->once()) + ->method('getStatus') + ->willReturn('status'); $this->assertEquals( - false, - $this->model->canInvoice($this->orderMock) + [__('An invoice cannot be created when an order has a status of %1', 'status')], + $this->model->validate($this->orderMock) ); } @@ -93,9 +96,8 @@ class OrderValidatorTest extends \PHPUnit_Framework_TestCase ->method('getItems') ->willReturn([]); - $this->assertEquals( - false, - $this->model->canInvoice($this->orderMock) + $this->assertNotEmpty( + $this->model->validate($this->orderMock) ); } @@ -125,7 +127,7 @@ class OrderValidatorTest extends \PHPUnit_Framework_TestCase $this->assertEquals( $expectedResult, - $this->model->canInvoice($this->orderMock) + $this->model->validate($this->orderMock) ); } @@ -137,10 +139,10 @@ class OrderValidatorTest extends \PHPUnit_Framework_TestCase public function canInvoiceDataProvider() { return [ - [0, null, false], - [-1, null, false], - [1, true, false], - [0.5, false, true], + [0, null, [__('The order does not allow an invoice to be created.')]], + [-1, null, [__('The order does not allow an invoice to be created.')]], + [1, true, [__('The order does not allow an invoice to be created.')]], + [0.5, false, []], ]; } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanShipTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanShipTest.php new file mode 100644 index 0000000000000000000000000000000000000000..11d99fbb9cced0e9a9d88de161898df42c5a71d7 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Validation/CanShipTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Order\Validation; + +use Magento\Sales\Model\Order; + +/** + * Test for \Magento\Sales\Model\Order\Validation\CanShip class + */ +class CanShipTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Order\Validation\CanShip|\PHPUnit_Framework_MockObject_MockObject + */ + private $model; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + + /** + * @var \Magento\Sales\Api\Data\OrderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + + /** + * @var \Magento\Sales\Api\Data\OrderItemInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderItemMock; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->orderMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStatus', 'getItems']) + ->getMockForAbstractClass(); + + $this->orderItemMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderItemInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getQtyToShip', 'getLockedDoShip']) + ->getMockForAbstractClass(); + + $this->model = new \Magento\Sales\Model\Order\Validation\CanShip(); + } + + /** + * @param string $state + * + * @dataProvider canShipWrongStateDataProvider + */ + public function testCanShipWrongState($state) + { + $this->orderMock->expects($this->any()) + ->method('getState') + ->willReturn($state); + $this->orderMock->expects($this->once()) + ->method('getStatus') + ->willReturn('status'); + $this->orderMock->expects($this->never()) + ->method('getItems'); + $this->assertEquals( + [__('A shipment cannot be created when an order has a status of %1', 'status')], + $this->model->validate($this->orderMock) + ); + } + + /** + * Data provider for testCanShipWrongState + * @return array + */ + public function canShipWrongStateDataProvider() + { + return [ + [Order::STATE_PAYMENT_REVIEW], + [Order::STATE_HOLDED], + [Order::STATE_CANCELED], + ]; + } + + public function testCanShipNoItems() + { + $this->orderMock->expects($this->any()) + ->method('getState') + ->willReturn(Order::STATE_PROCESSING); + + $this->orderMock->expects($this->once()) + ->method('getItems') + ->willReturn([]); + + $this->assertNotEmpty( + $this->model->validate($this->orderMock) + ); + } + + /** + * @param float $qtyToShipment + * @param bool|null $itemLockedDoShipment + * @param bool $expectedResult + * + * @dataProvider canShipDataProvider + */ + public function testCanShip($qtyToShipment, $itemLockedDoShipment, $expectedResult) + { + $this->orderMock->expects($this->any()) + ->method('getState') + ->willReturn(Order::STATE_PROCESSING); + + $items = [$this->orderItemMock]; + $this->orderMock->expects($this->once()) + ->method('getItems') + ->willReturn($items); + $this->orderItemMock->expects($this->any()) + ->method('getQtyToShip') + ->willReturn($qtyToShipment); + $this->orderItemMock->expects($this->any()) + ->method('getLockedDoShip') + ->willReturn($itemLockedDoShipment); + + $this->assertEquals( + $expectedResult, + $this->model->validate($this->orderMock) + ); + } + + /** + * Data provider for testCanShip + * + * @return array + */ + public function canShipDataProvider() + { + return [ + [0, null, [__('The order does not allow a shipment to be created.')]], + [-1, null, [__('The order does not allow a shipment to be created.')]], + [1, true, [__('The order does not allow a shipment to be created.')]], + [0.5, false, []], + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Plugin/AuthorizationTest.php b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Plugin/AuthorizationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..eeee0b2b910ea3d4d793952471fa1958de618f30 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/Plugin/AuthorizationTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model\ResourceModel\Order\Plugin; + +use Magento\Authorization\Model\UserContextInterface; +use Magento\Sales\Model\ResourceModel\Order as ResourceOrder; +use Magento\Sales\Model\Order; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sales\Model\ResourceModel\Order\Plugin\Authorization; + +class AuthorizationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var UserContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $userContextMock; + + /** + * @var ResourceOrder|\PHPUnit_Framework_MockObject_MockObject + */ + private $subjectMock; + + /** + * @var Order|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + + /** + * @var Authorization + */ + private $plugin; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->userContextMock = $this->getMockBuilder(UserContextInterface::class) + ->setMethods(['getUserType', 'getUserId']) + ->getMockForAbstractClass(); + $this->subjectMock = $this->getMockBuilder(ResourceOrder::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->setMethods(['getCustomerId', 'getId']) + ->getMock(); + $this->plugin = $this->objectManager->getObject( + Authorization::class, + ['userContext' => $this->userContextMock] + ); + } + + public function testAfterLoad() + { + $this->userContextMock->expects($this->once()) + ->method('getUserType') + ->willReturn('testType'); + $this->assertEquals( + $this->subjectMock, + $this->plugin->afterLoad($this->subjectMock, $this->subjectMock, $this->orderMock) + ); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage No such entity with orderId = 1 + */ + public function testAfterLoadWithException() + { + $this->userContextMock->expects($this->once()) + ->method('getUserType') + ->willReturn(UserContextInterface::USER_TYPE_CUSTOMER); + $this->orderMock->expects($this->once()) + ->method('getCustomerId') + ->willReturn(1); + $this->userContextMock->expects($this->once()) + ->method('getUserId') + ->willReturn(2); + $this->orderMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->plugin->afterLoad($this->subjectMock, $this->subjectMock, $this->orderMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b719babf209f0ceb98c4d019f1e5929b23e7e11f --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php @@ -0,0 +1,430 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Model; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\ShipmentCommentCreationInterface; +use Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface; +use Magento\Sales\Api\Data\ShipmentInterface; +use Magento\Sales\Api\Data\ShipmentPackageInterface; +use Magento\Sales\Api\Data\ShipmentTrackCreationInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Api\ShipmentRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Config as OrderConfig; +use Magento\Sales\Model\Order\OrderStateResolverInterface; +use Magento\Sales\Model\Order\OrderValidatorInterface; +use Magento\Sales\Model\Order\ShipmentDocumentFactory; +use Magento\Sales\Model\Order\Shipment\NotifierInterface; +use Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface; +use Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface; +use Magento\Sales\Model\ShipOrder; +use Psr\Log\LoggerInterface; + +/** + * Class ShipOrderTest + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) + */ +class ShipOrderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + */ + private $resourceConnectionMock; + + /** + * @var OrderRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderRepositoryMock; + + /** + * @var ShipmentDocumentFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentDocumentFactoryMock; + + /** + * @var ShipmentValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentValidatorMock; + + /** + * @var OrderValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderValidatorMock; + + /** + * @var OrderRegistrarInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderRegistrarMock; + + /** + * @var OrderStateResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderStateResolverMock; + + /** + * @var OrderConfig|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + /** + * @var ShipmentRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentRepositoryMock; + + /** + * @var NotifierInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $notifierInterfaceMock; + + /** + * @var ShipOrder|\PHPUnit_Framework_MockObject_MockObject + */ + private $model; + + /** + * @var ShipmentCreationArgumentsInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentCommentCreationMock; + + /** + * @var ShipmentCommentCreationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentCreationArgumentsMock; + + /** + * @var OrderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + + /** + * @var ShipmentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentMock; + + /** + * @var AdapterInterface + */ + private $adapterMock; + + /** + * @var ShipmentTrackCreationInterface + */ + private $trackMock; + + /** + * @var ShipmentPackageInterface + */ + private $packageMock; + + /** + * @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $loggerMock; + + protected function setUp() + { + $this->resourceConnectionMock = $this->getMockBuilder(ResourceConnection::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentDocumentFactoryMock = $this->getMockBuilder(ShipmentDocumentFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->shipmentValidatorMock = $this->getMockBuilder(ShipmentValidatorInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->orderValidatorMock = $this->getMockBuilder(OrderValidatorInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->orderRegistrarMock = $this->getMockBuilder(OrderRegistrarInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->orderStateResolverMock = $this->getMockBuilder(OrderStateResolverInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->configMock = $this->getMockBuilder(OrderConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->shipmentRepositoryMock = $this->getMockBuilder(ShipmentRepositoryInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->notifierInterfaceMock = $this->getMockBuilder(NotifierInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentCommentCreationMock = $this->getMockBuilder(ShipmentCommentCreationInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentCreationArgumentsMock = $this->getMockBuilder(ShipmentCreationArgumentsInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->shipmentMock = $this->getMockBuilder(ShipmentInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->packageMock = $this->getMockBuilder(ShipmentPackageInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->trackMock = $this->getMockBuilder(ShipmentTrackCreationInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->adapterMock = $this->getMockBuilder(AdapterInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->model = $helper->getObject( + ShipOrder::class, + [ + 'resourceConnection' => $this->resourceConnectionMock, + 'orderRepository' => $this->orderRepositoryMock, + 'shipmentRepository' => $this->shipmentRepositoryMock, + 'shipmentDocumentFactory' => $this->shipmentDocumentFactoryMock, + 'shipmentValidator' => $this->shipmentValidatorMock, + 'orderValidator' => $this->orderValidatorMock, + 'orderStateResolver' => $this->orderStateResolverMock, + 'orderRegistrar' => $this->orderRegistrarMock, + 'notifierInterface' => $this->notifierInterfaceMock, + 'config' => $this->configMock, + 'logger' => $this->loggerMock + ] + ); + } + + /** + * @dataProvider dataProvider + */ + public function testExecute($orderId, $items, $notify, $appendComment) + { + $this->resourceConnectionMock->expects($this->once()) + ->method('getConnection') + ->with('sales') + ->willReturn($this->adapterMock); + + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->willReturn($this->orderMock); + + $this->shipmentDocumentFactoryMock->expects($this->once()) + ->method('create') + ->with( + $this->orderMock, + $items, + [$this->trackMock], + $this->shipmentCommentCreationMock, + ($appendComment && $notify), + [$this->packageMock], + $this->shipmentCreationArgumentsMock + )->willReturn($this->shipmentMock); + + $this->shipmentValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->shipmentMock) + ->willReturn([]); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) + ->willReturn([]); + + $this->orderRegistrarMock->expects($this->once()) + ->method('register') + ->with($this->orderMock, $this->shipmentMock) + ->willReturn($this->orderMock); + + $this->orderStateResolverMock->expects($this->once()) + ->method('getStateForOrder') + ->with($this->orderMock, [OrderStateResolverInterface::IN_PROGRESS]) + ->willReturn(Order::STATE_PROCESSING); + + $this->orderMock->expects($this->once()) + ->method('setState') + ->with(Order::STATE_PROCESSING) + ->willReturnSelf(); + + $this->orderMock->expects($this->once()) + ->method('getState') + ->willReturn(Order::STATE_PROCESSING); + + $this->configMock->expects($this->once()) + ->method('getStateDefaultStatus') + ->with(Order::STATE_PROCESSING) + ->willReturn('Processing'); + + $this->orderMock->expects($this->once()) + ->method('setStatus') + ->with('Processing') + ->willReturnSelf(); + + $this->shipmentRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->shipmentMock) + ->willReturn($this->shipmentMock); + + $this->orderRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->orderMock) + ->willReturn($this->orderMock); + + if ($notify) { + $this->notifierInterfaceMock->expects($this->once()) + ->method('notify') + ->with($this->orderMock, $this->shipmentMock, $this->shipmentCommentCreationMock); + } + + $this->shipmentMock->expects($this->once()) + ->method('getEntityId') + ->willReturn(2); + + $this->assertEquals( + 2, + $this->model->execute( + $orderId, + $items, + $notify, + $appendComment, + $this->shipmentCommentCreationMock, + [$this->trackMock], + [$this->packageMock], + $this->shipmentCreationArgumentsMock + ) + ); + } + + /** + * @expectedException \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface + */ + public function testDocumentValidationException() + { + $orderId = 1; + $items = [1 => 2]; + $notify = true; + $appendComment = true; + $errorMessages = ['error1', 'error2']; + + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->willReturn($this->orderMock); + + $this->shipmentDocumentFactoryMock->expects($this->once()) + ->method('create') + ->with( + $this->orderMock, + $items, + [$this->trackMock], + $this->shipmentCommentCreationMock, + ($appendComment && $notify), + [$this->packageMock], + $this->shipmentCreationArgumentsMock + )->willReturn($this->shipmentMock); + + $this->shipmentValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->shipmentMock) + ->willReturn($errorMessages); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) + ->willReturn([]); + + $this->model->execute( + $orderId, + $items, + $notify, + $appendComment, + $this->shipmentCommentCreationMock, + [$this->trackMock], + [$this->packageMock], + $this->shipmentCreationArgumentsMock + ); + } + + /** + * @expectedException \Magento\Sales\Api\Exception\CouldNotShipExceptionInterface + */ + public function testCouldNotInvoiceException() + { + $orderId = 1; + $this->resourceConnectionMock->expects($this->once()) + ->method('getConnection') + ->with('sales') + ->willReturn($this->adapterMock); + + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->willReturn($this->orderMock); + + $this->shipmentDocumentFactoryMock->expects($this->once()) + ->method('create') + ->with( + $this->orderMock + )->willReturn($this->shipmentMock); + + $this->shipmentValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->shipmentMock) + ->willReturn([]); + $this->orderValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->orderMock) + ->willReturn([]); + $e = new \Exception(); + + $this->orderRegistrarMock->expects($this->once()) + ->method('register') + ->with($this->orderMock, $this->shipmentMock) + ->willThrowException($e); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($e); + + $this->adapterMock->expects($this->once()) + ->method('rollBack'); + + $this->model->execute( + $orderId + ); + } + + /** + * @return array + */ + public function dataProvider() + { + return [ + 'TestWithNotifyTrue' => [1, [1 => 2], true, true], + 'TestWithNotifyFalse' => [1, [1 => 2], false, true], + ]; + } +} diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 383650c8688fc847ac030bc6c216293a925956bf..dfdb0f6a261c51490e99955bdd61fd1bae328e60 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -30,7 +30,9 @@ <preference for="Magento\Sales\Api\Data\OrderStatusHistorySearchResultInterface" type="Magento\Sales\Model\ResourceModel\Order\Status\History\Collection"/> <preference for="Magento\Sales\Api\Data\ShipmentCommentInterface" type="Magento\Sales\Model\Order\Shipment\Comment"/> <preference for="Magento\Sales\Api\Data\ShipmentCommentSearchResultInterface" type="Magento\Sales\Model\ResourceModel\Order\Shipment\Comment\Collection"/> + <preference for="Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface" type="Magento\Sales\Model\Order\Shipment\CreationArguments"/> <preference for="Magento\Sales\Api\Data\ShipmentInterface" type="Magento\Sales\Model\Order\Shipment"/> + <preference for="Magento\Sales\Api\Data\ShipmentItemCreationInterface" type="Magento\Sales\Model\Order\Shipment\ItemCreation"/> <preference for="Magento\Sales\Api\Data\ShipmentItemInterface" type="Magento\Sales\Model\Order\Shipment\Item"/> <preference for="Magento\Sales\Api\Data\ShipmentItemSearchResultInterface" type="Magento\Sales\Model\ResourceModel\Order\Shipment\Item\Collection"/> <preference for="Magento\Sales\Api\Data\ShipmentSearchResultInterface" type="Magento\Sales\Model\ResourceModel\Order\Shipment\Collection"/> @@ -49,7 +51,10 @@ <preference for="Magento\Sales\Api\InvoiceItemRepositoryInterface" type="Magento\Sales\Api\Data\InvoiceItem\Repository"/> <preference for="Magento\Sales\Api\InvoiceRepositoryInterface" type="Magento\Sales\Model\Order\InvoiceRepository"/> <preference for="Magento\Sales\Api\InvoiceManagementInterface" type="Magento\Sales\Model\Service\InvoiceService"/> - <preference for="Magento\Sales\Api\InvoiceCreationArgumentsInterface" type="Magento\Sales\Model\Order\Invoice\CreationArguments"/> + <preference for="Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface" type="Magento\Sales\Model\Order\Invoice\CreationArguments"/> + <preference for="Magento\Sales\Api\Data\InvoiceItemCreationInterface" type="Magento\Sales\Model\Order\Invoice\ItemCreation"/> + <preference for="Magento\Sales\Api\Data\InvoiceCommentCreationInterface" type="Magento\Sales\Model\Order\Invoice\CommentCreation"/> + <preference for="Magento\Sales\Api\Data\ShipmentCommentCreationInterface" type="Magento\Sales\Model\Order\Shipment\CommentCreation"/> <preference for="Magento\Sales\Api\OrderAddressRepositoryInterface" type="Magento\Sales\Model\Order\AddressRepository"/> <preference for="Magento\Sales\Api\OrderCustomerManagementInterface" type="Magento\Sales\Model\Order\CustomerManagement"/> <preference for="Magento\Sales\Api\OrderItemRepositoryInterface" type="Magento\Sales\Model\Order\ItemRepository"/> @@ -62,13 +67,14 @@ <preference for="Magento\Sales\Api\ShipmentRepositoryInterface" type="Magento\Sales\Model\Order\ShipmentRepository"/> <preference for="Magento\Sales\Api\ShipmentManagementInterface" type="Magento\Sales\Model\Service\ShipmentService"/> <preference for="Magento\Sales\Api\ShipmentTrackRepositoryInterface" type="Magento\Sales\Api\Data\ShipmentTrack\Repository"/> + <preference for="Magento\Sales\Api\ShipOrderInterface" type="Magento\Sales\Model\ShipOrder"/> <preference for="Magento\Sales\Api\TransactionRepositoryInterface" type="Magento\Sales\Model\Order\Payment\Transaction\Repository"/> <preference for="Magento\Sales\Model\Order\Invoice\NotifierInterface" type="Magento\Sales\Model\Order\Invoice\Notifier"/> - <preference for="Magento\Sales\Model\Order\InvoiceValidatorInterface" type="Magento\Sales\Model\Order\InvoiceValidator"/> + <preference for="Magento\Sales\Model\Order\Shipment\NotifierInterface" type="Magento\Sales\Model\Order\Shipment\Notifier"/> <preference for="Magento\Sales\Model\Order\PaymentAdapterInterface" type="Magento\Sales\Model\Order\PaymentAdapter"/> - <preference for="Magento\Sales\Model\Order\OrderValidatorInterface" type="Magento\Sales\Model\Order\OrderValidator"/> <preference for="Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface" type="Magento\Sales\Model\Order\Payment\Transaction\Manager"/> <preference for="Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface" type="Magento\Sales\Model\Order\Payment\Transaction\Builder"/> + <preference for="Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface" type="Magento\Sales\Model\Order\Shipment\OrderRegistrar"/> <preference for="Magento\Sales\Model\Spi\CreditmemoCommentResourceInterface" type="Magento\Sales\Model\ResourceModel\Order\Creditmemo\Comment"/> <preference for="Magento\Sales\Model\Spi\CreditmemoItemResourceInterface" type="Magento\Sales\Model\ResourceModel\Order\Creditmemo\Item"/> <preference for="Magento\Sales\Model\Spi\CreditmemoResourceInterface" type="Magento\Sales\Model\ResourceModel\Order\Creditmemo"/> @@ -86,10 +92,14 @@ <preference for="Magento\Sales\Model\Spi\ShipmentTrackResourceInterface" type="Magento\Sales\Model\ResourceModel\Order\Shipment\Track"/> <preference for="Magento\Sales\Model\Spi\TransactionResourceInterface" type="Magento\Sales\Model\ResourceModel\Order\Payment\Transaction"/> <preference for="Magento\Sales\Model\ResourceModel\Order\CollectionFactoryInterface" type="Magento\Sales\Model\ResourceModel\Order\CollectionFactory"/> - <preference for="Magento\Sales\Api\Data\InvoiceCommentCreationInterface" type="Magento\Sales\Model\Order\Invoice\Comment"/> - <preference for="Magento\Sales\Api\Data\InvoiceItemCreationInterface" type="Magento\Sales\Model\Order\Invoice\ItemCreation"/> - <preference for="Magento\Sales\Api\OrderInvoiceInterface" type="Magento\Sales\Model\OrderInvoice"/> + <preference for="Magento\Sales\Api\InvoiceOrderInterface" type="Magento\Sales\Model\InvoiceOrder"/> <preference for="Magento\Sales\Model\Order\OrderStateResolverInterface" type="Magento\Sales\Model\Order\StateResolver"/> + <preference for="Magento\Sales\Api\Data\ShipmentTrackCreationInterface" type="Magento\Sales\Model\Order\Shipment\TrackCreation"/> + <preference for="Magento\Sales\Api\Data\ShipmentPackageInterface" type="Magento\Sales\Model\Order\Shipment\Package"/> + <preference for="Magento\Sales\Api\Data\ShipmentPackageCreationInterface" type="Magento\Sales\Model\Order\Shipment\PackageCreation"/> + <preference for="Magento\Sales\Model\Order\OrderValidatorInterface" type="Magento\Sales\Model\Order\OrderValidator"/> + <preference for="Magento\Sales\Model\Order\Invoice\InvoiceValidatorInterface" type="Magento\Sales\Model\Order\Invoice\InvoiceValidator"/> + <preference for="Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface" type="Magento\Sales\Model\Order\Shipment\ShipmentValidator"/> <type name="Magento\Sales\Model\ResourceModel\Report" shared="false"/> <type name="Magento\Sales\Model\Order\Pdf\Config\Reader"> <arguments> @@ -909,4 +919,18 @@ </argument> </arguments> </type> + <type name="Magento\Sales\Model\Order\Shipment\Notifier"> + <arguments> + <argument name="senders" xsi:type="array"> + <item name="email" xsi:type="object">Magento\Sales\Model\Order\Shipment\Sender\EmailSender</item> + </argument> + </arguments> + </type> + <type name="Magento\Framework\EntityManager\HydratorPool"> + <arguments> + <argument name="hydrators" xsi:type="array"> + <item name="Magento\Sales\Api\Data\ShipmentTrackCreationInterface" xsi:type="string">Magento\Framework\EntityManager\HydratorInterface</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Sales/etc/webapi.xml b/app/code/Magento/Sales/etc/webapi.xml index 8d1b1fda5bc314fdbd3dec616f7af8d56f1d8191..4c7fe03a201f8b25c2af83219fd0576da4c2cd3e 100644 --- a/app/code/Magento/Sales/etc/webapi.xml +++ b/app/code/Magento/Sales/etc/webapi.xml @@ -235,6 +235,12 @@ <resource ref="Magento_Sales::sales" /> </resources> </route> + <route url="/V1/order/:orderId/ship" method="POST"> + <service class="Magento\Sales\Api\ShipOrderInterface" method="execute"/> + <resources> + <resource ref="Magento_Sales::sales" /> + </resources> + </route> <route url="/V1/orders/" method="POST"> <service class="Magento\Sales\Api\OrderRepositoryInterface" method="save"/> <resources> @@ -254,7 +260,7 @@ </resources> </route> <route url="/V1/order/:orderId/invoice" method="POST"> - <service class="Magento\Sales\Api\OrderInvoiceInterface" method="execute"/> + <service class="Magento\Sales\Api\InvoiceOrderInterface" method="execute"/> <resources> <resource ref="Magento_Sales::sales" /> </resources> diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php index adbd96624649d5c7aff56a95156579ed16cc7f9d..d265159bc630be220bc4a7a64b706e36786510ef 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php @@ -7,8 +7,12 @@ namespace Magento\Shipping\Controller\Adminhtml\Order\Shipment; use Magento\Backend\App\Action; -use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; +use Magento\Sales\Model\Order\Shipment\Validation\QuantityValidator; +/** + * Class Save + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Save extends \Magento\Backend\App\Action { /** @@ -29,21 +33,26 @@ class Save extends \Magento\Backend\App\Action protected $labelGenerator; /** - * @var ShipmentSender + * @var \Magento\Sales\Model\Order\Email\Sender\ShipmentSender */ protected $shipmentSender; /** - * @param Action\Context $context + * @var \Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface + */ + private $shipmentValidator; + + /** + * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Shipping\Controller\Adminhtml\Order\ShipmentLoader $shipmentLoader * @param \Magento\Shipping\Model\Shipping\LabelGenerator $labelGenerator - * @param ShipmentSender $shipmentSender + * @param \Magento\Sales\Model\Order\Email\Sender\ShipmentSender $shipmentSender */ public function __construct( - Action\Context $context, + \Magento\Backend\App\Action\Context $context, \Magento\Shipping\Controller\Adminhtml\Order\ShipmentLoader $shipmentLoader, \Magento\Shipping\Model\Shipping\LabelGenerator $labelGenerator, - ShipmentSender $shipmentSender + \Magento\Sales\Model\Order\Email\Sender\ShipmentSender $shipmentSender ) { $this->shipmentLoader = $shipmentLoader; $this->labelGenerator = $labelGenerator; @@ -119,7 +128,14 @@ class Save extends \Magento\Backend\App\Action $shipment->setCustomerNote($data['comment_text']); $shipment->setCustomerNoteNotify(isset($data['comment_customer_notify'])); } - + $errorMessages = $this->getShipmentValidator()->validate($shipment, [QuantityValidator::class]); + if (!empty($errorMessages)) { + $this->messageManager->addError( + __("Shipment Document Validation Error(s):\n" . implode("\n", $errorMessages)) + ); + $this->_redirect('*/*/new', ['order_id' => $this->getRequest()->getParam('order_id')]); + return; + } $shipment->register(); $shipment->getOrder()->setCustomerNoteNotify(!empty($data['send_email'])); @@ -168,4 +184,19 @@ class Save extends \Magento\Backend\App\Action $this->_redirect('sales/order/view', ['order_id' => $shipment->getOrderId()]); } } + + /** + * @return \Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface + * @deprecated + */ + private function getShipmentValidator() + { + if ($this->shipmentValidator === null) { + $this->shipmentValidator = $this->_objectManager->get( + \Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface::class + ); + } + + return $this->shipmentValidator; + } } diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php index b452c88887c9e59bea3711578dff9e6db886ba84..c4efe6f6507d5641d7ef7d9ed378c73a6038c1de 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ diff --git a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php index af89f1a9146be07f49a31f7c5b0ad90c5d3c96b0..f8d9c06dc8ec05c07c699c4b22e7b830c796e4dc 100644 --- a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php @@ -11,6 +11,9 @@ namespace Magento\Shipping\Test\Unit\Controller\Adminhtml\Order\Shipment; use Magento\Backend\App\Action; use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Sales\Model\Order\Shipment\ShipmentValidatorInterface; +use Magento\Sales\Model\Order\Shipment\Validation\QuantityValidator; + /** * Class SaveTest * @@ -88,6 +91,11 @@ class SaveTest extends \PHPUnit_Framework_TestCase */ protected $saveAction; + /** + * @var ShipmentValidatorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shipmentValidatorMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -210,6 +218,10 @@ class SaveTest extends \PHPUnit_Framework_TestCase ->method('getFormKeyValidator') ->will($this->returnValue($this->formKeyValidator)); + $this->shipmentValidatorMock = $this->getMockBuilder(ShipmentValidatorInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->saveAction = $objectManagerHelper->getObject( \Magento\Shipping\Controller\Adminhtml\Order\Shipment\Save::class, [ @@ -218,7 +230,8 @@ class SaveTest extends \PHPUnit_Framework_TestCase 'context' => $this->context, 'shipmentLoader' => $this->shipmentLoader, 'request' => $this->request, - 'response' => $this->response + 'response' => $this->response, + 'shipmentValidator' => $this->shipmentValidatorMock ] ); } @@ -346,6 +359,11 @@ class SaveTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($orderId)); $this->prepareRedirect($path, $arguments); + $this->shipmentValidatorMock->expects($this->once()) + ->method('validate') + ->with($shipment, [QuantityValidator::class]) + ->willReturn([]); + $this->saveAction->execute(); $this->assertEquals($this->response, $this->saveAction->getResponse()); } diff --git a/app/code/Magento/Store/App/Action/Plugin/Context.php b/app/code/Magento/Store/App/Action/Plugin/Context.php index e56b301733cca65b6cb7cfdfce4a8b870f75ee47..1b4545384255c3154212ce84cc81c1a83fa6dcbb 100644 --- a/app/code/Magento/Store/App/Action/Plugin/Context.php +++ b/app/code/Magento/Store/App/Action/Plugin/Context.php @@ -11,6 +11,8 @@ use Magento\Framework\Phrase; use Magento\Store\Api\StoreCookieManagerInterface; use Magento\Store\Api\StoreResolverInterface; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\App\RequestInterface; /** * Class ContextPlugin @@ -27,11 +29,6 @@ class Context */ protected $httpContext; - /** - * @var \Magento\Framework\App\Request\Http - */ - protected $httpRequest; - /** * @var \Magento\Store\Model\StoreManagerInterface */ @@ -45,40 +42,35 @@ class Context /** * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Framework\App\Request\Http $httpRequest * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param StoreCookieManagerInterface $storeCookieManager */ public function __construct( \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Framework\App\Http\Context $httpContext, - \Magento\Framework\App\Request\Http $httpRequest, \Magento\Store\Model\StoreManagerInterface $storeManager, StoreCookieManagerInterface $storeCookieManager ) { $this->session = $session; $this->httpContext = $httpContext; - $this->httpRequest = $httpRequest; $this->storeManager = $storeManager; $this->storeCookieManager = $storeCookieManager; } /** - * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed - * @param \Magento\Framework\App\RequestInterface $request - * @return mixed + * Set store and currency to http context + * + * @param AbstractAction $subject + * @param RequestInterface $request + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeDispatch(AbstractAction $subject, RequestInterface $request) + { /** @var \Magento\Store\Model\Store $defaultStore */ $defaultStore = $this->storeManager->getWebsite()->getDefaultStore(); - $storeCode = $this->httpRequest->getParam( + $storeCode = $request->getParam( StoreResolverInterface::PARAM_NAME, $this->storeCookieManager->getStoreCodeFromCookie() ); @@ -103,6 +95,5 @@ class Context $this->session->getCurrencyCode() ?: $currentStore->getDefaultCurrencyCode(), $defaultStore->getDefaultCurrencyCode() ); - return $proceed($request); } } diff --git a/app/code/Magento/Store/App/Action/Plugin/StoreCheck.php b/app/code/Magento/Store/App/Action/Plugin/StoreCheck.php index 56a7157e7004c2b9ec87460b45dcf68d082557b5..fcb9316220793669b93630eb36b879de7be9a426 100644 --- a/app/code/Magento/Store/App/Action/Plugin/StoreCheck.php +++ b/app/code/Magento/Store/App/Action/Plugin/StoreCheck.php @@ -23,17 +23,14 @@ class StoreCheck } /** - * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed + * @param \Magento\Framework\App\Action\AbstractAction $subject * @param \Magento\Framework\App\RequestInterface $request - * - * @return \Magento\Framework\App\ResponseInterface + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @throws \Magento\Framework\Exception\State\InitException */ - public function aroundDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, + public function beforeDispatch( + \Magento\Framework\App\Action\AbstractAction $subject, \Magento\Framework\App\RequestInterface $request ) { if (!$this->_storeManager->getStore()->isActive()) { @@ -41,6 +38,5 @@ class StoreCheck __('Current store is not active.') ); } - return $proceed($request); } } diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextTest.php index 32aeb0b515124f1d552624d2a7a09b2ad520a85b..2411475b203818c28af71de117172236a5b321bf 100644 --- a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/ContextTest.php @@ -3,14 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Store\Test\Unit\App\Action\Plugin; use Magento\Framework\App\Http\Context; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Action\AbstractAction; +use Magento\Framework\App\RequestInterface; /** * Class ContextPluginTest @@ -38,11 +37,6 @@ class ContextTest extends \PHPUnit_Framework_TestCase */ protected $httpContextMock; - /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $httpRequestMock; - /** * @var \Magento\Store\Model\StoreManager|\PHPUnit_Framework_MockObject_MockObject */ @@ -69,17 +63,12 @@ class ContextTest extends \PHPUnit_Framework_TestCase protected $websiteMock; /** - * @var \Closure - */ - protected $closureMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var AbstractAction|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $requestMock; @@ -88,67 +77,53 @@ class ContextTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $this->sessionMock = $this->getMock( + $this->sessionMock = $this->getMock( \Magento\Framework\Session\Generic::class, ['getCurrencyCode'], [], '', false ); - $this->httpContextMock = $this->getMock( + $this->httpContextMock = $this->getMock( \Magento\Framework\App\Http\Context::class, [], [], '', false ); - $this->httpRequestMock = $this->getMock( - \Magento\Framework\App\Request\Http::class, - ['getParam'], - [], - '', - false - ); $this->storeManager = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); $this->storeCookieManager = $this->getMock(\Magento\Store\Api\StoreCookieManagerInterface::class); - $this->storeMock = $this->getMock( + $this->storeMock = $this->getMock( \Magento\Store\Model\Store::class, [], [], '', false ); - $this->currentStoreMock = $this->getMock( + $this->currentStoreMock = $this->getMock( \Magento\Store\Model\Store::class, [], [], '', false ); - $this->websiteMock = $this->getMock( + $this->websiteMock = $this->getMock( \Magento\Store\Model\Website::class, ['getDefaultStore', '__wakeup'], [], '', false ); - $this->closureMock = function () { - return 'ExpectedValue'; - }; - $this->subjectMock = $this->getMock( - \Magento\Framework\App\Action\Action::class, - [], - [], - '', - false - ); - $this->requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class); + $this->requestMock = $this->getMockBuilder(RequestInterface::class)->getMockForAbstractClass(); + $this->subjectMock = $this->getMockBuilder(AbstractAction::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); - $this->plugin = (new ObjectManager($this))->getObject(\Magento\Store\App\Action\Plugin\Context::class, + $this->plugin = (new ObjectManager($this))->getObject( + \Magento\Store\App\Action\Plugin\Context::class, [ 'session' => $this->sessionMock, 'httpContext' => $this->httpContextMock, - 'httpRequest' => $this->httpRequestMock, 'storeManager' => $this->storeManager, 'storeCookieManager' => $this->storeCookieManager, ] @@ -171,7 +146,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(self::CURRENCY_CURRENT_STORE)); } - public function testAroundDispatchCurrencyFromSession() + public function testBeforeDispatchCurrencyFromSession() { $this->storeMock->expects($this->once()) ->method('getDefaultCurrencyCode') @@ -184,7 +159,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->method('getCode') ->willReturn('custom_store'); - $this->httpRequestMock->expects($this->once()) + $this->requestMock->expects($this->once()) ->method('getParam') ->with($this->equalTo('___store')) ->will($this->returnValue('default')); @@ -205,10 +180,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->method('setValue') ->with(Context::CONTEXT_CURRENCY, self::CURRENCY_SESSION, self::CURRENCY_DEFAULT); - $this->assertEquals( - 'ExpectedValue', - $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); + $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); } public function testDispatchCurrentStoreCurrency() @@ -224,7 +196,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->method('getCode') ->willReturn('custom_store'); - $this->httpRequestMock->expects($this->once()) + $this->requestMock->expects($this->once()) ->method('getParam') ->with($this->equalTo('___store')) ->will($this->returnValue('default')); @@ -241,10 +213,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->method('setValue') ->with(Context::CONTEXT_CURRENCY, self::CURRENCY_CURRENT_STORE, self::CURRENCY_DEFAULT); - $this->assertEquals( - 'ExpectedValue', - $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); + $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); } public function testDispatchStoreParameterIsArray() @@ -266,7 +235,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ] ]; - $this->httpRequestMock->expects($this->once()) + $this->requestMock->expects($this->once()) ->method('getParam') ->with($this->equalTo('___store')) ->will($this->returnValue($store)); @@ -284,11 +253,7 @@ class ContextTest extends \PHPUnit_Framework_TestCase ->method('setValue') ->with(Context::CONTEXT_CURRENCY, self::CURRENCY_CURRENT_STORE, self::CURRENCY_DEFAULT); - $result = $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock); - $this->assertEquals( - 'ExpectedValue', - $result - ); + $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); } /** @@ -314,10 +279,10 @@ class ContextTest extends \PHPUnit_Framework_TestCase ] ]; - $this->httpRequestMock->expects($this->once()) + $this->requestMock->expects($this->once()) ->method('getParam') ->with($this->equalTo('___store')) ->will($this->returnValue($store)); - $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock); + $this->plugin->beforeDispatch($this->subjectMock, $this->requestMock); } } diff --git a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php index 1170377a6b27c8abf96648c5491ef68d6b35fa5e..7e443a05c1b25b2edfcce4499036d65010c215bf 100644 --- a/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Action/Plugin/StoreCheckTest.php @@ -3,9 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Store\Test\Unit\App\Action\Plugin; class StoreCheckTest extends \PHPUnit_Framework_TestCase @@ -26,17 +23,12 @@ class StoreCheckTest extends \PHPUnit_Framework_TestCase protected $_storeMock; /** - * @var \Closure - */ - protected $closureMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\AbstractAction|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $requestMock; @@ -51,11 +43,10 @@ class StoreCheckTest extends \PHPUnit_Framework_TestCase )->will( $this->returnValue($this->_storeMock) ); - $this->subjectMock = $this->getMock(\Magento\Framework\App\Action\Action::class, [], [], '', false); - $this->closureMock = function () { - return 'Expected'; - }; $this->requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class); + $this->subjectMock = $this->getMockBuilder(\Magento\Framework\App\Action\AbstractAction::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->_plugin = new \Magento\Store\App\Action\Plugin\StoreCheck($this->_storeManagerMock); } @@ -64,22 +55,15 @@ class StoreCheckTest extends \PHPUnit_Framework_TestCase * @expectedException \Magento\Framework\Exception\State\InitException * @expectedExceptionMessage Current store is not active. */ - public function testAroundDispatchWhenStoreNotActive() + public function testBeforeDispatchWhenStoreNotActive() { $this->_storeMock->expects($this->any())->method('isActive')->will($this->returnValue(false)); - $this->assertEquals( - 'Expected', - $this->_plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); + $this->_plugin->beforeDispatch($this->subjectMock, $this->requestMock); } - public function testAroundDispatchWhenStoreIsActive() + public function testBeforeDispatchWhenStoreIsActive() { $this->_storeMock->expects($this->any())->method('isActive')->will($this->returnValue(true)); - $this->assertEquals( - 'Expected', - $this->_plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); + $this->_plugin->beforeDispatch($this->subjectMock, $this->requestMock); } - } diff --git a/app/code/Magento/Store/Test/Unit/Url/Plugin/RouteParamsResolverTest.php b/app/code/Magento/Store/Test/Unit/Url/Plugin/RouteParamsResolverTest.php index b2c5a972734a9663cbcfa3ae13f7cd9f42812ee7..959f9efd0334546196a12df2bf1b546f42c7d6d4 100644 --- a/app/code/Magento/Store/Test/Unit/Url/Plugin/RouteParamsResolverTest.php +++ b/app/code/Magento/Store/Test/Unit/Url/Plugin/RouteParamsResolverTest.php @@ -39,10 +39,7 @@ class RouteParamsResolverTest extends \PHPUnit_Framework_TestCase ); } - /** - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function testAroundSetRouteParamsScopeInParams() + public function testBeforeSetRouteParamsScopeInParams() { $storeCode = 'custom_store'; $this->scopeConfigMock @@ -66,20 +63,13 @@ class RouteParamsResolverTest extends \PHPUnit_Framework_TestCase $this->queryParamsResolverMock->expects($this->once())->method('setQueryParam')->with('___store', $storeCode); - $this->model->aroundSetRouteParams( + $this->model->beforeSetRouteParams( $routeParamsResolverMock, - function ($data, $unsetOldParams) { - $this->assertArrayNotHasKey('_scope_to_url', $data, 'This data item should have been unset.'); - $this->assertArrayNotHasKey('_scope', $data, 'This data item should have been unset.'); - }, $data ); } - /** - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function testAroundSetRouteParamsScopeUseStoreInUrl() + public function testBeforeSetRouteParamsScopeUseStoreInUrl() { $storeCode = 'custom_store'; $this->scopeConfigMock @@ -103,20 +93,13 @@ class RouteParamsResolverTest extends \PHPUnit_Framework_TestCase $this->queryParamsResolverMock->expects($this->never())->method('setQueryParam'); - $this->model->aroundSetRouteParams( + $this->model->beforeSetRouteParams( $routeParamsResolverMock, - function ($data, $unsetOldParams) { - $this->assertArrayNotHasKey('_scope_to_url', $data, 'This data item should have been unset.'); - $this->assertArrayNotHasKey('_scope', $data, 'This data item should have been unset.'); - }, $data ); } - /** - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function testAroundSetRouteParamsSingleStore() + public function testBeforeSetRouteParamsSingleStore() { $storeCode = 'custom_store'; $this->scopeConfigMock @@ -140,20 +123,13 @@ class RouteParamsResolverTest extends \PHPUnit_Framework_TestCase $this->queryParamsResolverMock->expects($this->never())->method('setQueryParam'); - $this->model->aroundSetRouteParams( + $this->model->beforeSetRouteParams( $routeParamsResolverMock, - function ($data, $unsetOldParams) { - $this->assertArrayNotHasKey('_scope_to_url', $data, 'This data item should have been unset.'); - $this->assertArrayNotHasKey('_scope', $data, 'This data item should have been unset.'); - }, $data ); } - /** - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function testAroundSetRouteParamsNoScopeInParams() + public function testBeforeSetRouteParamsNoScopeInParams() { $storeCode = 'custom_store'; $this->scopeConfigMock @@ -185,11 +161,8 @@ class RouteParamsResolverTest extends \PHPUnit_Framework_TestCase $this->queryParamsResolverMock->expects($this->once())->method('setQueryParam')->with('___store', $storeCode); - $this->model->aroundSetRouteParams( + $this->model->beforeSetRouteParams( $routeParamsResolverMock, - function ($data, $unsetOldParams) { - $this->assertArrayNotHasKey('_scope_to_url', $data, 'This data item should have been unset.'); - }, $data ); } diff --git a/app/code/Magento/Store/Url/Plugin/RouteParamsResolver.php b/app/code/Magento/Store/Url/Plugin/RouteParamsResolver.php index 4435dfe108cffbffcfd458cc4a8a53dbdd8eb821..8ef0420a23cbe706d8df93abf18ae0fb573f709f 100644 --- a/app/code/Magento/Store/Url/Plugin/RouteParamsResolver.php +++ b/app/code/Magento/Store/Url/Plugin/RouteParamsResolver.php @@ -49,15 +49,12 @@ class RouteParamsResolver * Process scope query parameters. * * @param \Magento\Framework\Url\RouteParamsResolver $subject - * @param callable $proceed * @param array $data * @param bool $unsetOldParams - * @return \Magento\Framework\Url\RouteParamsResolver - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @return array */ - public function aroundSetRouteParams( + public function beforeSetRouteParams( \Magento\Framework\Url\RouteParamsResolver $subject, - \Closure $proceed, array $data, $unsetOldParams = true ) { @@ -78,6 +75,6 @@ class RouteParamsResolver } unset($data['_scope_to_url']); - return $proceed($data, $unsetOldParams); + return [$data, $unsetOldParams]; } } diff --git a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php index 00dd9ff4cda98962934294e1ba52dfbc588b0e50..03927aed968889324c3e44df9dcb5f5fd1de36ac 100644 --- a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php @@ -6,9 +6,6 @@ namespace Magento\Tax\Model\App\Action; -use Magento\Customer\Model\Context; -use Magento\Customer\Model\GroupManagement; - /** * Class ContextPlugin */ @@ -74,21 +71,19 @@ class ContextPlugin /** * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed * @param \Magento\Framework\App\RequestInterface $request * @return mixed * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDispatch( + public function beforeDispatch( \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, \Magento\Framework\App\RequestInterface $request ) { if (!$this->customerSession->isLoggedIn() || !$this->moduleManager->isEnabled('Magento_PageCache') || !$this->cacheConfig->isEnabled() || !$this->taxHelper->isCatalogPriceDisplayAffectedByTax()) { - return $proceed($request); + return; } $defaultBillingAddress = $this->customerSession->getDefaultTaxBillingAddress(); @@ -107,6 +102,5 @@ class ContextPlugin 0 ); } - return $proceed($request); } } diff --git a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php index 7964353a74c96eb40ac652eb72c19730c6c135f8..a727beef10b0648934dbb21b89945ff2d1462193 100644 --- a/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php +++ b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php @@ -71,18 +71,18 @@ class GrandTotalDetailsPlugin /** * @param \Magento\Quote\Model\Cart\TotalsConverter $subject - * @param \Closure $proceed + * @param \Magento\Quote\Api\Data\TotalSegmentInterface[] $totalSegments * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals + * * @return \Magento\Quote\Api\Data\TotalSegmentInterface[] * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function aroundProcess( + public function afterProcess( \Magento\Quote\Model\Cart\TotalsConverter $subject, - \Closure $proceed, + array $totalSegments, array $addressTotals = [] ) { - $totalSegments = $proceed($addressTotals); if (!array_key_exists($this->code, $addressTotals)) { return $totalSegments; diff --git a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php index 6bf64c3300937045c7bde0a6f455f2d4667f4b10..a95ead9efe30405a51558dc8f7ade3ef23306ae4 100644 --- a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php @@ -111,9 +111,9 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase * @param bool $cache * @param bool $taxEnabled * @param bool $loggedIn - * @dataProvider dataProviderAroundDispatch + * @dataProvider beforeDispatchDataProvider */ - public function testAroundDispatch($cache, $taxEnabled, $loggedIn) + public function testBeforeDispatch($cache, $taxEnabled, $loggedIn) { $this->customerSessionMock->expects($this->any()) ->method('isLoggedIn') @@ -160,18 +160,14 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); $request = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getActionName'], [], '', false); - $expectedResult = 'expectedResult'; - $proceed = function ($request) use ($expectedResult) { - return $expectedResult; - }; - $this->contextPlugin->aroundDispatch($action, $proceed, $request); + $this->contextPlugin->beforeDispatch($action, $request); } } /** * @return array */ - public function dataProviderAroundDispatch() + public function beforeDispatchDataProvider() { return [ [false, false, false], diff --git a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php index 52af1315ba76685ac64662f425bcfb9f6b11837e..693b0d437afc45853b5ab224d04c535f1af1ca92 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php @@ -38,11 +38,6 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase */ protected $subjectMock; - /** - * @var \Closure|\PHPUnit_Framework_MockObject_MockObject - */ - protected $closureMock; - /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ @@ -153,7 +148,7 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase return $taxDetailsMock; } - public function testAroundProcess() + public function testAfterProcess() { $taxRate = [ 'percent' => 8.25, @@ -211,11 +206,7 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase 'tax' => $taxSegmentMock, ]; - $this->closureMock = function () use ($totalSegments) { - return $totalSegments; - }; - - $result = $this->model->aroundProcess($this->subjectMock, $this->closureMock, $addressTotals); + $result = $this->model->afterProcess($this->subjectMock, $totalSegments, $addressTotals); $this->assertEquals($totalSegments, $result); } } diff --git a/app/code/Magento/Theme/Model/Url/Plugin/Signature.php b/app/code/Magento/Theme/Model/Url/Plugin/Signature.php index 2a4d878e80d7a1fec2a8daaf970298575b8a633a..8934c598feb79a438b442a39612f81673b3d8f4b 100644 --- a/app/code/Magento/Theme/Model/Url/Plugin/Signature.php +++ b/app/code/Magento/Theme/Model/Url/Plugin/Signature.php @@ -47,7 +47,7 @@ class Signature * Append signature to rendered base URL for static view files * * @param \Magento\Framework\Url\ScopeInterface $subject - * @param callable $proceed + * @param string $baseUrl * @param string $type * @param null $secure * @return string @@ -55,13 +55,12 @@ class Signature * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundGetBaseUrl( + public function afterGetBaseUrl( \Magento\Framework\Url\ScopeInterface $subject, - \Closure $proceed, + $baseUrl, $type = \Magento\Framework\UrlInterface::URL_TYPE_LINK, $secure = null ) { - $baseUrl = $proceed($type, $secure); if ($type == \Magento\Framework\UrlInterface::URL_TYPE_STATIC && $this->isUrlSignatureEnabled()) { $baseUrl .= $this->renderUrlSignature() . '/'; } diff --git a/app/code/Magento/Theme/Test/Unit/Model/Url/Plugin/SignatureTest.php b/app/code/Magento/Theme/Test/Unit/Model/Url/Plugin/SignatureTest.php index 46097a13db12f48c6670649568e44e1cd6d67ee6..58cf9bcc31e5b8bb4a02cf9d5c93e5ca6f645bce 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Url/Plugin/SignatureTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Url/Plugin/SignatureTest.php @@ -3,9 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Theme\Test\Unit\Model\Url\Plugin; use \Magento\Theme\Model\Url\Plugin\Signature; @@ -27,29 +24,25 @@ class SignatureTest extends \PHPUnit_Framework_TestCase */ private $deploymentVersion; - /** - * @var callable - */ - private $closureMock; - protected function setUp() { $this->config = $this->getMock(\Magento\Framework\View\Url\ConfigInterface::class); - $this->deploymentVersion = $this->getMock( - \Magento\Framework\App\View\Deployment\Version::class, [], [], '', false + $this->deploymentVersion = $this->getMock( + \Magento\Framework\App\View\Deployment\Version::class, + [], + [], + '', + false ); - $this->closureMock = function () { - return 'http://127.0.0.1/magento/pub/static/'; - }; $this->object = new Signature($this->config, $this->deploymentVersion); } /** * @param bool|int $fixtureConfigFlag * @param string $inputUrlType - * @dataProvider aroundGetBaseUrlInactiveDataProvider + * @dataProvider afterGetBaseUrlInactiveDataProvider */ - public function testAroundGetBaseUrlInactive($fixtureConfigFlag, $inputUrlType) + public function testAfterGetBaseUrlInactive($fixtureConfigFlag, $inputUrlType) { $this->config ->expects($this->any()) @@ -59,11 +52,14 @@ class SignatureTest extends \PHPUnit_Framework_TestCase $this->deploymentVersion->expects($this->never())->method($this->anything()); $url = $this->getMockForAbstractClass(\Magento\Framework\Url\ScopeInterface::class); - $actualResult = $this->object->aroundGetBaseUrl($url, $this->closureMock, $inputUrlType); + $actualResult = $this->object->afterGetBaseUrl($url, 'http://127.0.0.1/magento/pub/static/', $inputUrlType); $this->assertEquals('http://127.0.0.1/magento/pub/static/', $actualResult); } - public function aroundGetBaseUrlInactiveDataProvider() + /** + * @return array + */ + public function afterGetBaseUrlInactiveDataProvider() { return [ 'disabled in config, relevant URL type' => [0, \Magento\Framework\UrlInterface::URL_TYPE_STATIC], @@ -81,8 +77,10 @@ class SignatureTest extends \PHPUnit_Framework_TestCase $this->deploymentVersion->expects($this->once())->method('getValue')->will($this->returnValue('123')); $url = $this->getMockForAbstractClass(\Magento\Framework\Url\ScopeInterface::class); - $actualResult = $this->object->aroundGetBaseUrl( - $url, $this->closureMock, \Magento\Framework\UrlInterface::URL_TYPE_STATIC + $actualResult = $this->object->afterGetBaseUrl( + $url, + 'http://127.0.0.1/magento/pub/static/', + \Magento\Framework\UrlInterface::URL_TYPE_STATIC ); $this->assertEquals('http://127.0.0.1/magento/pub/static/version123/', $actualResult); } diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultAttributesLoad.php b/app/code/Magento/Vault/Plugin/PaymentVaultAttributesLoad.php index 810a8c5242da8ce24cbbb5ac15d63260f3853687..710b765d11effb155d17c02986ec561e0d54207d 100644 --- a/app/code/Magento/Vault/Plugin/PaymentVaultAttributesLoad.php +++ b/app/code/Magento/Vault/Plugin/PaymentVaultAttributesLoad.php @@ -10,6 +10,8 @@ namespace Magento\Vault\Plugin; use Magento\Sales\Api\Data\OrderPaymentExtensionInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Vault\Api\PaymentTokenManagementInterface; +use Magento\Sales\Api\Data\OrderPaymentExtensionFactory; +use Magento\Vault\Api\Data\PaymentTokenInterface; /** * Plugin for loading vault payment extension attribute to order/payment entity @@ -17,7 +19,7 @@ use Magento\Vault\Api\PaymentTokenManagementInterface; class PaymentVaultAttributesLoad { /** - * @var \Magento\Sales\Api\Data\OrderPaymentExtensionFactory + * @var OrderPaymentExtensionFactory */ protected $paymentExtensionFactory; @@ -27,11 +29,11 @@ class PaymentVaultAttributesLoad protected $paymentTokenManagement; /** - * @param \Magento\Sales\Api\Data\OrderPaymentExtensionFactory $paymentExtensionFactory + * @param OrderPaymentExtensionFactory $paymentExtensionFactory * @param PaymentTokenManagement|PaymentTokenManagementInterface $paymentTokenManagement */ public function __construct( - \Magento\Sales\Api\Data\OrderPaymentExtensionFactory $paymentExtensionFactory, + OrderPaymentExtensionFactory $paymentExtensionFactory, PaymentTokenManagementInterface $paymentTokenManagement ) { $this->paymentExtensionFactory = $paymentExtensionFactory; @@ -42,16 +44,13 @@ class PaymentVaultAttributesLoad * Load vault payment extension attribute to order/payment entity * * @param OrderPaymentInterface $payment - * @param \Closure $proceed + * @param OrderPaymentExtensionInterface|null $paymentExtension * @return OrderPaymentExtensionInterface */ - public function aroundGetExtensionAttributes( + public function afterGetExtensionAttributes( OrderPaymentInterface $payment, - \Closure $proceed + OrderPaymentExtensionInterface $paymentExtension = null ) { - /** @var OrderPaymentExtensionInterface $paymentExtension */ - $paymentExtension = $proceed(); - if ($paymentExtension === null) { $paymentExtension = $this->paymentExtensionFactory->create(); } @@ -59,7 +58,7 @@ class PaymentVaultAttributesLoad $paymentToken = $paymentExtension->getVaultPaymentToken(); if ($paymentToken === null) { $paymentToken = $this->paymentTokenManagement->getByPaymentId($payment->getEntityId()); - if ($paymentToken instanceof \Magento\Vault\Api\Data\PaymentTokenInterface) { + if ($paymentToken instanceof PaymentTokenInterface) { $paymentExtension->setVaultPaymentToken($paymentToken); } $payment->setExtensionAttributes($paymentExtension); diff --git a/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php index c00f2f3491e03b16628d49ea34e5990e705c13e5..43344c196ec524e053842854db76c86951f70ad0 100644 --- a/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php +++ b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php @@ -92,29 +92,27 @@ class ContextPlugin /** * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed * @param \Magento\Framework\App\RequestInterface $request - * @return mixed + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function aroundDispatch( + public function beforeDispatch( \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, \Magento\Framework\App\RequestInterface $request ) { if (!$this->weeeHelper->isEnabled() || !$this->customerSession->isLoggedIn() || !$this->moduleManager->isEnabled('Magento_PageCache') || !$this->cacheConfig->isEnabled()) { - return $proceed($request); + return; } $basedOn = $this->taxHelper->getTaxBasedOn(); if ($basedOn != 'shipping' && $basedOn != 'billing') { - return $proceed($request); + return; } $weeeTaxRegion = $this->getWeeeTaxRegion($basedOn); @@ -124,7 +122,7 @@ class ContextPlugin if (!$countryId && !$regionId) { // country and region does not exist - return $proceed($request); + return; } else if ($countryId && !$regionId) { // country exist and region does not exist $regionId = 0; @@ -158,7 +156,6 @@ class ContextPlugin 0 ); } - return $proceed($request); } /** diff --git a/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php index ebb0837d3c14474f27951a1158927d75cace4ed3..77c8070ca44eb51ff546a71a85545393657f6f94 100644 --- a/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php +++ b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php @@ -123,7 +123,7 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase ); } - public function testAroundDispatchBasedOnDefault() + public function testBeforeDispatchBasedOnDefault() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -187,14 +187,11 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); $request = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getActionName'], [], '', false); - $expectedResult = 'expectedResult'; - $proceed = function ($request) use ($expectedResult) { - return $expectedResult; - }; - $this->contextPlugin->aroundDispatch($action, $proceed, $request); + + $this->contextPlugin->beforeDispatch($action, $request); } - public function testAroundDispatchBasedOnOrigin() + public function testBeforeDispatchBasedOnOrigin() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -219,14 +216,11 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); $request = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getActionName'], [], '', false); - $expectedResult = 'expectedResult'; - $proceed = function ($request) use ($expectedResult) { - return $expectedResult; - }; - $this->contextPlugin->aroundDispatch($action, $proceed, $request); + + $this->contextPlugin->beforeDispatch($action, $request); } - public function testAroundDispatchBasedOnBilling() + public function testBeforeDispatchBasedOnBilling() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -294,14 +288,11 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); $request = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getActionName'], [], '', false); - $expectedResult = 'expectedResult'; - $proceed = function ($request) use ($expectedResult) { - return $expectedResult; - }; - $this->contextPlugin->aroundDispatch($action, $proceed, $request); + + $this->contextPlugin->beforeDispatch($action, $request); } - public function testAroundDispatchBasedOnShipping() + public function testBeforeDispatchBasedOnShipping() { $this->customerSessionMock->expects($this->once()) ->method('isLoggedIn') @@ -369,10 +360,7 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase $action = $this->objectManager->getObject(\Magento\Framework\App\Test\Unit\Action\Stub\ActionStub::class); $request = $this->getMock(\Magento\Framework\App\Request\Http::class, ['getActionName'], [], '', false); - $expectedResult = 'expectedResult'; - $proceed = function ($request) use ($expectedResult) { - return $expectedResult; - }; - $this->contextPlugin->aroundDispatch($action, $proceed, $request); + + $this->contextPlugin->beforeDispatch($action, $request); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderInvoiceCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderInvoiceCreateTest.php index cb384134a7c68c63955a0d97ab27aaa6c4f4f002..60c9f54ea132c5a0af3970ac58b87710b7b1688c 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderInvoiceCreateTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderInvoiceCreateTest.php @@ -10,7 +10,7 @@ namespace Magento\Sales\Service\V1; */ class OrderInvoiceCreateTest extends \Magento\TestFramework\TestCase\WebapiAbstract { - const SERVICE_READ_NAME = 'salesOrderInvoiceV1'; + const SERVICE_READ_NAME = 'salesInvoiceOrderV1'; const SERVICE_VERSION = 'V1'; /** diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8de7c4dc7f65b9318eca04c2656f22aa08cc447f --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php @@ -0,0 +1,100 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Service\V1; + +/** + * API test for creation of Shipment for certain Order. + */ +class ShipOrderTest extends \Magento\TestFramework\TestCase\WebapiAbstract +{ + const SERVICE_READ_NAME = 'salesShipOrderV1'; + const SERVICE_VERSION = 'V1'; + + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var \Magento\Sales\Api\ShipmentRepositoryInterface + */ + private $shipmentRepository; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + $this->shipmentRepository = $this->objectManager->get( + \Magento\Sales\Api\ShipmentRepositoryInterface::class + ); + } + + /** + * @magentoApiDataFixture Magento/Sales/_files/order_new.php + */ + public function testShipOrder() + { + /** @var \Magento\Sales\Model\Order $existingOrder */ + $existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId('100000001'); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/order/' . $existingOrder->getId() . '/ship', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_READ_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_READ_NAME . 'execute', + ], + ]; + + $requestData = [ + 'orderId' => $existingOrder->getId(), + 'items' => [], + 'comment' => [ + 'comment' => 'Test Comment', + 'is_visible_on_front' => 1, + ], + 'tracks' => [ + [ + 'track_number' => 'TEST_TRACK_0001', + 'title' => 'Simple shipment track', + 'carrier_code' => 'UPS' + ] + ] + ]; + + /** @var \Magento\Sales\Api\Data\OrderItemInterface $item */ + foreach ($existingOrder->getAllItems() as $item) { + $requestData['items'][] = [ + 'order_item_id' => $item->getItemId(), + 'qty' => $item->getQtyOrdered(), + ]; + } + + $result = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertNotEmpty($result); + + try { + $this->shipmentRepository->get($result); + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + $this->fail('Failed asserting that Shipment was created'); + } + + /** @var \Magento\Sales\Model\Order $updatedOrder */ + $updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class) + ->loadByIncrementId('100000001'); + + $this->assertNotEquals( + $existingOrder->getStatus(), + $updatedOrder->getStatus(), + 'Failed asserting that Order status was changed' + ); + } +} diff --git a/lib/internal/Magento/Framework/EntityManager/CustomAttributesMapper.php b/lib/internal/Magento/Framework/EntityManager/CustomAttributesMapper.php index 9147d47f3d9dd8c21cec93ff47de2e065a13dd9d..fe3a199da86a32bdb866894b53831fe4c5e8a246 100644 --- a/lib/internal/Magento/Framework/EntityManager/CustomAttributesMapper.php +++ b/lib/internal/Magento/Framework/EntityManager/CustomAttributesMapper.php @@ -55,8 +55,9 @@ class CustomAttributesMapper implements MapperInterface */ public function entityToDatabase($entityType, $data) { - $metadata = $this->metadataPool->getMetadata($entityType); - if (!$metadata->getEavEntityType()) { + if (!$this->metadataPool->hasConfiguration($entityType) + || !$this->metadataPool->getMetadata($entityType)->getEavEntityType() + ) { return $data; } if (isset($data[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES])) { diff --git a/lib/internal/Magento/Framework/EntityManager/Test/Unit/CustomAttributesMapperTest.php b/lib/internal/Magento/Framework/EntityManager/Test/Unit/CustomAttributesMapperTest.php index a39ad4afaa6eed43f552f14b5bdb85c16fa712dc..56977af1dd6eb5c62872572ec22f2024f7479223 100644 --- a/lib/internal/Magento/Framework/EntityManager/Test/Unit/CustomAttributesMapperTest.php +++ b/lib/internal/Magento/Framework/EntityManager/Test/Unit/CustomAttributesMapperTest.php @@ -48,12 +48,18 @@ class CustomAttributesMapperTest extends \PHPUnit_Framework_TestCase $metadataPool = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class) ->disableOriginalConstructor() - ->setMethods(['getMetadata']) + ->setMethods(['getMetadata', 'hasConfiguration']) ->getMock(); + $metadataPool->expects($this->any()) + ->method('hasConfiguration') + ->willReturn(true); $metadataPool->expects($this->any()) ->method('getMetadata') ->with($this->equalTo(\Magento\Customer\Api\Data\AddressInterface::class)) ->will($this->returnValue($metadata)); + $metadataPool->expects($this->once()) + ->method('hasConfiguration') + ->willReturn(true); $searchCriteriaBuilder = $this->getMockBuilder(\Magento\Framework\Api\SearchCriteriaBuilder::class) ->disableOriginalConstructor() @@ -76,6 +82,7 @@ class CustomAttributesMapperTest extends \PHPUnit_Framework_TestCase 'metadataPool' => $metadataPool, 'searchCriteriaBuilder' => $searchCriteriaBuilder ]); + $actual = $customAttributesMapper->entityToDatabase( \Magento\Customer\Api\Data\AddressInterface::class, [ diff --git a/lib/internal/Magento/Framework/EntityManager/TypeResolver.php b/lib/internal/Magento/Framework/EntityManager/TypeResolver.php index 28e2bdaa7094223d604cf174cd627982b6ecd0e9..2718162e80d669acfbc70eb78310b5911d7a668b 100644 --- a/lib/internal/Magento/Framework/EntityManager/TypeResolver.php +++ b/lib/internal/Magento/Framework/EntityManager/TypeResolver.php @@ -20,7 +20,8 @@ class TypeResolver */ private $typeMapping = [ \Magento\SalesRule\Model\Rule::class => \Magento\SalesRule\Api\Data\RuleInterface::class, - \Magento\SalesRule\Model\Rule\Interceptor::class => \Magento\SalesRule\Api\Data\RuleInterface::class + \Magento\SalesRule\Model\Rule\Interceptor::class => \Magento\SalesRule\Api\Data\RuleInterface::class, + \Magento\SalesRule\Model\Rule\Proxy::class => \Magento\SalesRule\Api\Data\RuleInterface::class ]; /** @@ -50,8 +51,7 @@ class TypeResolver $dataInterfaces = []; foreach ($interfaceNames as $interfaceName) { if (strpos($interfaceName, '\Api\Data\\')) { - $dataInterfaces[] = isset($this->config[$interfaceName]) - ? $this->config[$interfaceName] : $interfaceName; + $dataInterfaces[] = $interfaceName; } } @@ -64,7 +64,9 @@ class TypeResolver $this->typeMapping[$className] = $dataInterface; } } - + if (empty($this->typeMapping[$className])) { + $this->typeMapping[$className] = reset($dataInterfaces); + } return $this->typeMapping[$className]; } } diff --git a/lib/internal/Magento/Framework/Interception/Code/InterfaceValidator.php b/lib/internal/Magento/Framework/Interception/Code/InterfaceValidator.php index 1ff11552533b1e6514409402e778687483ae6d18..93945c607b53d7498a9031fbb475f30e015ecb6c 100644 --- a/lib/internal/Magento/Framework/Interception/Code/InterfaceValidator.php +++ b/lib/internal/Magento/Framework/Interception/Code/InterfaceValidator.php @@ -111,13 +111,13 @@ class InterfaceValidator ); break; case self::METHOD_AFTER: - // TODO: Remove this condition check in scope of MAGETWO-56123 if (count($pluginMethodParameters) > 1) { // remove result array_shift($pluginMethodParameters); + $matchedParameters = array_intersect_key($originMethodParameters, $pluginMethodParameters); $this->validateMethodsParameters( $pluginMethodParameters, - $originMethodParameters, + $matchedParameters, $pluginClass, $pluginMethod->getName() ); diff --git a/lib/internal/Magento/Framework/Module/Plugin/DbStatusValidator.php b/lib/internal/Magento/Framework/Module/Plugin/DbStatusValidator.php index 6f312529c12b40eaacc9d815411d4f065999b2d3..850d64b14ae0cd7efc4c067f919eb99245ba0414 100644 --- a/lib/internal/Magento/Framework/Module/Plugin/DbStatusValidator.php +++ b/lib/internal/Magento/Framework/Module/Plugin/DbStatusValidator.php @@ -1,22 +1,24 @@ <?php /** - * Validation of DB up to date state - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Framework\Module\Plugin; -use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Cache\FrontendInterface as FrontendCacheInterface; use Magento\Framework\Module\DbVersionInfo; +use Magento\Framework\App\FrontController; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; +/** + * Validation of DB up to date state + */ class DbStatusValidator { /** - * @var FrontendInterface + * @var FrontendCacheInterface */ private $cache; @@ -26,47 +28,40 @@ class DbStatusValidator private $dbVersionInfo; /** - * @param FrontendInterface $cache + * @param FrontendCacheInterface $cache * @param DbVersionInfo $dbVersionInfo */ - public function __construct( - FrontendInterface $cache, - DbVersionInfo $dbVersionInfo - ) { + public function __construct(FrontendCacheInterface $cache, DbVersionInfo $dbVersionInfo) + { $this->cache = $cache; $this->dbVersionInfo = $dbVersionInfo; } /** - * @param \Magento\Framework\App\FrontController $subject - * @param \Closure $proceed - * @param \Magento\Framework\App\RequestInterface $request + * Perform check if DB is up to date + * + * @param FrontController $subject + * @param RequestInterface $request + * @return void + * @throws LocalizedException * - * @throws \Magento\Framework\Exception\LocalizedException - * @return \Magento\Framework\App\ResponseInterface * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundDispatch( - \Magento\Framework\App\FrontController $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { + public function beforeDispatch(FrontController $subject, RequestInterface $request) + { if (!$this->cache->load('db_is_up_to_date')) { $errors = $this->dbVersionInfo->getDbVersionErrors(); + if ($errors) { - $formattedErrors = $this->formatErrors($errors); - throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase( - 'Please upgrade your database: Run "bin/magento setup:upgrade" from the Magento root directory.' - . ' %1The following modules are outdated:%2%3', - [PHP_EOL, PHP_EOL, implode(PHP_EOL, $formattedErrors)] - ) - ); + $message = 'Please upgrade your database: ' + . "Run \"bin/magento setup:upgrade\" from the Magento root directory.\n" + . "The following modules are outdated:\n%1"; + + throw new LocalizedException(new Phrase($message, [implode("\n", $this->formatErrors($errors))])); } else { $this->cache->save('true', 'db_is_up_to_date'); } } - return $proceed($request); } /** @@ -78,12 +73,13 @@ class DbStatusValidator private function formatErrors($errorsData) { $formattedErrors = []; + foreach ($errorsData as $error) { - $formattedErrors[] = $error[DbVersionInfo::KEY_MODULE] . - ' ' . $error[DbVersionInfo::KEY_TYPE] . - ': current version - ' . $error[DbVersionInfo::KEY_CURRENT ] . - ', required version - ' . $error[DbVersionInfo::KEY_REQUIRED]; + $formattedErrors[] = $error[DbVersionInfo::KEY_MODULE] . ' ' . $error[DbVersionInfo::KEY_TYPE] + . ': current version - ' . $error[DbVersionInfo::KEY_CURRENT] + . ', required version - ' . $error[DbVersionInfo::KEY_REQUIRED]; } + return $formattedErrors; } } diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/Plugin/DbStatusValidatorTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/Plugin/DbStatusValidatorTest.php index fee050560815c293a1f7a724de0653e606e21fc8..c0563020110daa8b4ef5a4e7cd3824dee2a5d3b0 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/Plugin/DbStatusValidatorTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/Plugin/DbStatusValidatorTest.php @@ -21,11 +21,6 @@ class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase */ protected $_cacheMock; - /** - * @var \Closure - */ - protected $closureMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -49,9 +44,6 @@ class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->_cacheMock = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); - $this->closureMock = function () { - return 'Expected'; - }; $this->requestMock = $this->getMock(\Magento\Framework\App\RequestInterface::class); $this->subjectMock = $this->getMock(\Magento\Framework\App\FrontController::class, [], [], '', false); $moduleList = $this->getMockForAbstractClass(\Magento\Framework\Module\ModuleListInterface::class); @@ -85,8 +77,8 @@ class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase ->will($this->returnValueMap($returnMap)); $this->assertEquals( - 'Expected', - $this->_model->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) + null, + $this->_model->beforeDispatch($this->subjectMock, $this->requestMock) ); } @@ -101,8 +93,8 @@ class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase $this->moduleManager->expects($this->never()) ->method('isDbDataUpToDate'); $this->assertEquals( - 'Expected', - $this->_model->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) + null, + $this->_model->beforeDispatch($this->subjectMock, $this->requestMock) ); } @@ -125,7 +117,7 @@ class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase ->method('getDbVersionErrors') ->will($this->returnValue($dbVersionErrors)); - $this->_model->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock); + $this->_model->beforeDispatch($this->subjectMock, $this->requestMock); } /** diff --git a/lib/internal/Magento/Framework/Test/Unit/Module/Plugin/DbStatusValidatorTest.php b/lib/internal/Magento/Framework/Test/Unit/Module/Plugin/DbStatusValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f22192639f77e62f52ccae93906b096b733934ba --- /dev/null +++ b/lib/internal/Magento/Framework/Test/Unit/Module/Plugin/DbStatusValidatorTest.php @@ -0,0 +1,137 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Test\Unit\Module\Plugin; + +use Magento\Framework\Module\Plugin\DbStatusValidator as DbStatusValidatorPlugin; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\Cache\FrontendInterface as FrontendCacheInterface; +use Magento\Framework\Module\DbVersionInfo; +use Magento\Framework\App\FrontController; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Exception\LocalizedException; + +class DbStatusValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var DbStatusValidatorPlugin + */ + private $plugin; + + /** + * @var ObjectManagerHelper + */ + private $objectManagerHelper; + + /** + * @var FrontendCacheInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheMock; + + /** + * @var DbVersionInfo|\PHPUnit_Framework_MockObject_MockObject + */ + private $dbVersionInfoMock; + + /** + * @var FrontController|\PHPUnit_Framework_MockObject_MockObject + */ + private $frontControllerMock; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + protected function setUp() + { + $this->cacheMock = $this->getMockBuilder(FrontendCacheInterface::class) + ->getMockForAbstractClass(); + $this->dbVersionInfoMock = $this->getMockBuilder(DbVersionInfo::class) + ->disableOriginalConstructor() + ->getMock(); + $this->frontControllerMock = $this->getMockBuilder(FrontController::class) + ->disableOriginalConstructor() + ->getMock(); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->getMockForAbstractClass(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->plugin = $this->objectManagerHelper->getObject( + DbStatusValidatorPlugin::class, + [ + 'cache' => $this->cacheMock, + 'dbVersionInfo' => $this->dbVersionInfoMock + ] + ); + } + + public function testBeforeDispatchUpToDate() + { + $this->cacheMock->expects(static::any()) + ->method('load') + ->with('db_is_up_to_date') + ->willReturn('cache_data'); + $this->dbVersionInfoMock->expects(static::never()) + ->method('getDbVersionErrors'); + $this->cacheMock->expects(static::never()) + ->method('save'); + + $this->plugin->beforeDispatch($this->frontControllerMock, $this->requestMock); + } + + public function testBeforeDispatchOutOfDateNoErrors() + { + $this->cacheMock->expects(static::any()) + ->method('load') + ->with('db_is_up_to_date') + ->willReturn(false); + $this->dbVersionInfoMock->expects(static::once()) + ->method('getDbVersionErrors') + ->willReturn([]); + $this->cacheMock->expects(static::once()) + ->method('save') + ->with('true', 'db_is_up_to_date', [], null) + ->willReturn(true); + + $this->plugin->beforeDispatch($this->frontControllerMock, $this->requestMock); + } + + public function testBeforeDispatchOutOfDateWithErrors() + { + $errors = [ + [ + DbVersionInfo::KEY_MODULE => 'Magento_Module1', + DbVersionInfo::KEY_TYPE => 'schema', + DbVersionInfo::KEY_CURRENT => '3.3.3', + DbVersionInfo::KEY_REQUIRED => '4.4.4' + ], + [ + DbVersionInfo::KEY_MODULE => 'Magento_Module2', + DbVersionInfo::KEY_TYPE => 'data', + DbVersionInfo::KEY_CURRENT => '2.8.7', + DbVersionInfo::KEY_REQUIRED => '5.1.6' + ] + ]; + $message = 'Please upgrade your database: ' + . "Run \"bin/magento setup:upgrade\" from the Magento root directory.\n" + . "The following modules are outdated:\n" + . "Magento_Module1 schema: current version - 3.3.3, required version - 4.4.4\n" + . "Magento_Module2 data: current version - 2.8.7, required version - 5.1.6"; + + $this->cacheMock->expects(static::any()) + ->method('load') + ->with('db_is_up_to_date') + ->willReturn(false); + $this->dbVersionInfoMock->expects(static::once()) + ->method('getDbVersionErrors') + ->willReturn($errors); + $this->cacheMock->expects(static::never()) + ->method('save'); + + $this->setExpectedException(LocalizedException::class, $message); + $this->plugin->beforeDispatch($this->frontControllerMock, $this->requestMock); + } +}