From 1e055fb848f4a9214fea293f12642b3fbe5344a2 Mon Sep 17 00:00:00 2001 From: Maksym Aposov Date: Thu, 4 Jun 2015 15:45:35 +0300 Subject: [PATCH] MAGETWO-36369: [GitHub] Unable to save product per website wise #1245 --- .../Model/ProductUrlPathGenerator.php | 50 ++++++++++++- .../Model/ProductUrlPathGeneratorTest.php | 74 +++++++++++++++++-- .../Eav/Model/Entity/AbstractEntity.php | 2 +- 3 files changed, 115 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php index 0f6b98df7a716..cd798278fc9c6 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php @@ -5,6 +5,8 @@ */ namespace Magento\CatalogUrlRewrite\Model; +use Magento\Store\Model\Store; + class ProductUrlPathGenerator { const XML_PATH_PRODUCT_URL_SUFFIX = 'catalog/seo/product_url_suffix'; @@ -25,19 +27,25 @@ class ProductUrlPathGenerator /** @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator */ protected $categoryUrlPathGenerator; + /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ + protected $productRepository; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param CategoryUrlPathGenerator $categoryUrlPathGenerator + * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator + \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator, + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { $this->storeManager = $storeManager; $this->scopeConfig = $scopeConfig; $this->categoryUrlPathGenerator = $categoryUrlPathGenerator; + $this->productRepository = $productRepository; } /** @@ -52,12 +60,34 @@ public function getUrlPath($product, $category = null) { $path = $product->getData('url_path'); if ($path === null) { - $path = $this->generateUrlKey($product); + $path = $product->getUrlKey() === false + ? $this->_prepareProductDefaultUrlKey($product) + : $this->_prepareProductUrlKey($product); } - return $category === null ? $path + return $category === null + ? $path : $this->categoryUrlPathGenerator->getUrlPath($category) . '/' . $path; } + /** + * Prepare URL Key with stored product data (fallback for "Use Default Value" logic) + * + * @param \Magento\Catalog\Model\Product $product + * @return mixed|null|string + */ + protected function _prepareProductDefaultUrlKey(\Magento\Catalog\Model\Product $product) + { + $storedProduct = $this->productRepository->getById($product->getId(), false, Store::DEFAULT_STORE_ID); + $storedUrlKey = $storedProduct->getUrlKey(); + $result = null; + if ($storedUrlKey !== false) { + $result = $storedUrlKey; + } else { + $result = $product->formatUrlKey($storedProduct->getName()); + } + return $result; + } + /** * Retrieve Product Url path with suffix * @@ -91,6 +121,20 @@ public function getCanonicalUrlPath($product, $category = null) * @return string */ public function generateUrlKey($product) + { + if ($product->getUrlKey() === false) { + return false; + } + return $this->_prepareProductUrlKey($product); + } + + /** + * Prepare url key for product + * + * @param \Magento\Catalog\Model\Product $product + * @return string + */ + protected function _prepareProductUrlKey(\Magento\Catalog\Model\Product $product) { $urlKey = $product->getUrlKey(); return $product->formatUrlKey($urlKey === '' || $urlKey === null ? $product->getName() : $urlKey); diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php index 64a88b42b8d76..7b733303bf4d4 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php @@ -5,10 +5,9 @@ */ namespace Magento\CatalogUrlRewrite\Test\Unit\Model; -use \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; - -use Magento\Store\Model\ScopeInterface; +use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\ScopeInterface; class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase { @@ -27,13 +26,26 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ protected $product; + /** @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $productRepository; + /** @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject */ protected $category; protected function setUp() { $this->category = $this->getMock('Magento\Catalog\Model\Category', [], [], '', false); - $productMethods = ['__wakeup', 'getData', 'getUrlKey', 'getName', 'formatUrlKey', 'getId']; + $productMethods = [ + '__wakeup', + 'getData', + 'getUrlKey', + 'getName', + 'formatUrlKey', + 'getId', + 'load', + 'setStoreId', + ]; + $this->product = $this->getMock('Magento\Catalog\Model\Product', $productMethods, [], '', false); $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface'); $this->scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); @@ -44,13 +56,16 @@ protected function setUp() '', false ); + $this->productRepository = $this->getMock('Magento\Catalog\Api\ProductRepositoryInterface'); + $this->productRepository->expects($this->any())->method('getById')->willReturn($this->product); $this->productUrlPathGenerator = (new ObjectManager($this))->getObject( 'Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator', [ 'storeManager' => $this->storeManager, 'scopeConfig' => $this->scopeConfig, - 'categoryUrlPathGenerator' => $this->categoryUrlPathGenerator + 'categoryUrlPathGenerator' => $this->categoryUrlPathGenerator, + 'productRepository' => $this->productRepository, ] ); } @@ -64,6 +79,7 @@ public function getUrlPathDataProvider() 'path based on url key' => ['url-key', null, 'url-key'], 'path based on product name 1' => ['', 'product-name', 'product-name'], 'path based on product name 2' => [null, 'product-name', 'product-name'], + 'path based on product name 3' => [false, 'product-name', 'product-name'] ]; } @@ -77,13 +93,34 @@ public function testGenerateUrlPath($urlKey, $productName, $result) { $this->product->expects($this->once())->method('getData')->with('url_path') ->will($this->returnValue(null)); - $this->product->expects($this->once())->method('getUrlKey')->will($this->returnValue($urlKey)); + $this->product->expects($this->any())->method('getUrlKey')->will($this->returnValue($urlKey)); $this->product->expects($this->any())->method('getName')->will($this->returnValue($productName)); $this->product->expects($this->once())->method('formatUrlKey')->will($this->returnArgument(0)); $this->assertEquals($result, $this->productUrlPathGenerator->getUrlPath($this->product, null)); } + /** + * @param $productUrlKey + * @param $expectedUrlKey + * + * @dataProvider generateUrlKeyDataProvider + */ + public function testGenerateUrlKey($productUrlKey, $expectedUrlKey) + { + $this->product->expects($this->any())->method('getUrlKey')->will($this->returnValue($productUrlKey)); + $this->product->expects($this->any())->method('formatUrlKey')->will($this->returnValue($productUrlKey)); + $this->assertEquals($expectedUrlKey, $this->productUrlPathGenerator->generateUrlKey($this->product)); + } + + public function generateUrlKeyDataProvider() + { + return [ + 'URL Key use default' => [false, false], + 'URL Key empty' => ['product-url', 'product-url'], + ]; + } + public function testGetUrlPath() { $this->product->expects($this->once())->method('getData')->with('url_path') @@ -93,6 +130,29 @@ public function testGetUrlPath() $this->assertEquals('url-path', $this->productUrlPathGenerator->getUrlPath($this->product, null)); } + /** + * + * @dataProvider getUrlPathDefaultUrlKeyDataProvider + */ + public function testGetUrlPathDefaultUrlKey($storedUrlKey, $productName, $expectedUrlKey) + { + $this->product->expects($this->once())->method('getData')->with('url_path') + ->will($this->returnValue(null)); + $this->product->expects($this->any())->method('getUrlKey')->willReturnOnConsecutiveCalls(false, $storedUrlKey); + $this->product->expects($this->any())->method('getName')->will($this->returnValue($productName)); + $this->product->expects($this->any())->method('formatUrlKey')->will($this->returnArgument(0)); + $this->assertEquals($expectedUrlKey, $this->productUrlPathGenerator->getUrlPath($this->product, null)); + } + + public function getUrlPathDefaultUrlKeyDataProvider() + { + return [ + ['default-store-view-url-key', null, 'default-store-view-url-key'], + [false, 'default-store-view-product-name', 'default-store-view-product-name'] + ]; + + } + public function testGetUrlPathWithCategory() { $this->product->expects($this->once())->method('getData')->with('url_path') @@ -124,7 +184,7 @@ public function testGetUrlPathWithSuffix() ); } - public function testGetUrlPathWithSuffixAndCategoryAnsStore() + public function testGetUrlPathWithSuffixAndCategoryAndStore() { $storeId = 1; $this->product->expects($this->once())->method('getData')->with('url_path') diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index c8fa8214eab58..74aaa7396e116 100755 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -13,8 +13,8 @@ use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend; use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource; use Magento\Framework\App\Config\Element; -use Magento\Framework\Model\AbstractModel; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\Resource\Db\ObjectRelationProcessor; use Magento\Framework\Model\Resource\Db\TransactionManagerInterface;