Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PAC-252 - Only generate category product rewrites if enabled in backend #23

Merged
merged 7 commits into from
Oct 26, 2020
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# TBA

## Bugfixes

* None

## Features

* PAC-252 - Only generate category product rewrites if enabled in backend

# Version 24.0.0

## Bugfixes
Expand Down
71 changes: 56 additions & 15 deletions src/Observers/UrlRewriteObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

namespace TechDivision\Import\Product\UrlRewrite\Observers;

use TechDivision\Import\Product\UrlRewrite\Utils\CoreConfigDataKeys;
use TechDivision\Import\Utils\StoreViewCodes;
use TechDivision\Import\Product\Utils\VisibilityKeys;
use TechDivision\Import\Product\Utils\CoreConfigDataKeys;
use TechDivision\Import\Product\Observers\AbstractProductImportObserver;
use TechDivision\Import\Product\UrlRewrite\Utils\ColumnKeys;
use TechDivision\Import\Product\UrlRewrite\Utils\MemberNames;
Expand Down Expand Up @@ -405,20 +405,8 @@ protected function resolveCategoryIds($categoryId, $topLevel = false, $storeView
// load the data of the category with the passed ID
$category = $this->getCategory($categoryId, $storeViewCode);

// query whether or not the product has already been related
if (!in_array($categoryId, $this->productCategoryIds)) {
if ($topLevel) {
// relate it, if the category is top level
$this->productCategoryIds[] = $categoryId;
} elseif ((integer) $category[MemberNames::IS_ANCHOR] === 1) {
// also relate it, if the category is not top level, but has the anchor flag set
$this->productCategoryIds[] = $categoryId;
} else {
$this->getSubject()
->getSystemLogger()
->debug(sprintf('Don\'t create URL rewrite for category "%s" because of missing anchor flag', $category[MemberNames::PATH]));
}
}
// create the product category relation for the current category
$this->createProductCategoryRelation($category, $topLevel);

// load the root category
$rootCategory = $this->getRootCategory();
Expand All @@ -429,6 +417,59 @@ protected function resolveCategoryIds($categoryId, $topLevel = false, $storeView
}
}

/**
* Adds the entity product relation if necessary.
*
* @param array $category The category to create the relation for
* @param boolean $topLevel Whether or not the category has top level
*
* @return void
*/
protected function createProductCategoryRelation($category, $topLevel)
{

// query whether or not the product has already been related
if (in_array($category[MemberNames::ENTITY_ID], $this->productCategoryIds)) {
return;
}

// load the backend configuration value for whether or not the catalog product rewrites should be generated
$generateCategoryRewrites = $this->getGenerateCategoryProductRewritesOptionValue();

// abort if generating product categories is disabled and category is not root
if ($generateCategoryRewrites === false && $this->isRootCategory($category) === false) {
return;
}

// create relation if the category is top level or has the anchor flag set
if ($topLevel || (integer) $category[MemberNames::IS_ANCHOR] === 1) {
$this->productCategoryIds[] = $category[MemberNames::ENTITY_ID];
return;
}

$this->getSubject()
->getSystemLogger()
->debug(
sprintf(
'Don\'t create URL rewrite for category "%s" because of missing anchor flag',
$category[MemberNames::PATH]
)
);
}

/**
* Returns the option value for whether or not to generate product catalog rewrites as well.
*
* @return bool
*/
protected function getGenerateCategoryProductRewritesOptionValue()
{
return (bool) $this->getSubject()->getCoreConfigData(
CoreConfigDataKeys::CATALOG_SEO_GENERATE_CATEGORY_PRODUCT_REWRITES,
true
);
}

/**
* Prepare the attributes of the entity that has to be persisted.
*
Expand Down
31 changes: 31 additions & 0 deletions src/Utils/CoreConfigDataKeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* TechDivision\Import\Product\UrlRewrite\Utils\CoreConfigDataKeys
*
* @author Marcus Döllerer <m.doellerer@techdivision.com>
* @copyright 2020 TechDivision GmbH <info@techdivision.com>
* @link https://www.techdivision.com
*/

namespace TechDivision\Import\Product\UrlRewrite\Utils;

/**
* Utility class containing the keys Magento uses to persist values in the "core_config_data table".
*
* @author Marcus Döllerer <m.doellerer@techdivision.com>
* @copyright 2020 TechDivision GmbH <info@techdivision.com>
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @link https://github.com/techdivision/import-product-url-rewrite
* @link https://www.techdivision.com
*/
class CoreConfigDataKeys extends \TechDivision\Import\Product\Utils\CoreConfigDataKeys
{

/**
* Name for the column 'catalog/seo/generate_category_product_rewrites'.
*
* @var string
*/
const CATALOG_SEO_GENERATE_CATEGORY_PRODUCT_REWRITES = 'catalog/seo/generate_category_product_rewrites';
}
81 changes: 72 additions & 9 deletions tests/unit/Observers/UrlRewriteObserverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
namespace TechDivision\Import\Product\UrlRewrite\Observers;

use PHPUnit\Framework\TestCase;
use ReflectionClass;
use TechDivision\Import\Utils\EntityStatus;
use TechDivision\Import\Utils\StoreViewCodes;
use TechDivision\Import\Product\Utils\VisibilityKeys;
Expand Down Expand Up @@ -74,8 +75,71 @@ protected function setUp()
$this->observer = new UrlRewriteObserver($this->mockProductUrlRewriteProcessor);
}

protected function createAndInvokeObserver($generateCategoryProductRewrites = true, $productCategoryIds = [], $category = [])
{
$observer = $this->getMockBuilder('TechDivision\Import\Product\UrlRewrite\Observers\UrlRewriteObserver')
->setConstructorArgs([$this->mockProductUrlRewriteProcessor])
->setMethods(['getGenerateCategoryProductRewritesOptionValue', 'isRootCategory'])
->getMock();

$observer->expects($this->any())
->method('getGenerateCategoryProductRewritesOptionValue')
->willReturn($generateCategoryProductRewrites);

$observer->expects($this->any())
->method('isRootCategory')
->willReturn(false);

// prepare protected properties of observer
$reflection = new ReflectionClass('TechDivision\Import\Product\UrlRewrite\Observers\UrlRewriteObserver');
$property = $reflection->getProperty('productCategoryIds');
$property->setAccessible(true);
$property->setValue($observer, $productCategoryIds);

// invoke the method to test
$method = $reflection->getMethod('createProductCategoryRelation');
$method->setAccessible(true);
$method->invoke($observer, $category, true);

return $property->getValue($observer);
}

public function testCreateProductCategoryRelationWithChildCategoryAndSettingEnabled()
{

// initialize method arguments
$generateCategoryProductRewrites = true;
$productCategoryIds = ['2'];
$category = [
'entity_id' => '10',
'is_anchor' => '0'
];

// create and invoke the partially mocked observer
$productCategoryIds = $this->createAndInvokeObserver($generateCategoryProductRewrites, $productCategoryIds, $category);

$this->assertSame($productCategoryIds, ['2', '10']);
}

public function testCreateProductCategoryRelationWithChildCategoryAndSettingDisabled()
{

// initialize method arguments
$generateCategoryProductRewrites = false;
$productCategoryIds = ['2'];
$category = [
'entity_id' => '10',
'is_anchor' => '0'
];

// create and invoke the partially mocked observer
$productCategoryIds = $this->createAndInvokeObserver($generateCategoryProductRewrites, $productCategoryIds, $category);

$this->assertSame($productCategoryIds, ['2']);
}

/**
* Test's the handle() method with a successfull URL rewrite persist.
* Test's the handle() method with a successful URL rewrite persist.
*
* @return void
*/
Expand Down Expand Up @@ -210,7 +274,7 @@ public function testHandleWithSuccessfullCreateWithoutCategories()
}

/**
* Test's the handle() method with a successfull URL rewrite persist when using the same categories.
* Test's the handle() method with a successful URL rewrite persist when using the same categories.
*
* @return void
*/
Expand Down Expand Up @@ -392,14 +456,13 @@ public function testHandleWithSuccessfullUpdateAndSameCategories()
$mockSubject->expects($this->any())
->method('getRowStoreId')
->willReturn($storeId = 1);
$mockSubject->expects($this->exactly(3))
$mockSubject->expects($this->any())
->method('getCoreConfigData')
->withConsecutive(
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html')
)
->willReturnOnConsecutiveCalls('.html', '.html', '.html');
->will(
$this->returnCallback(function ($arg1, $arg2) {
return $arg2;
})
);
$mockSubject->expects(($this->exactly(4)))
->method('getImportAdapter')
->willReturn($mockImportAdapter);
Expand Down
19 changes: 6 additions & 13 deletions tests/unit/Observers/UrlRewriteUpdateObserverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,20 +298,13 @@ public function testHandleWithSuccessfullUpdateAndDifferentCategories()
$mockSubject->expects($this->any())
->method('getRowStoreId')
->willReturn($storeId = 1);
$mockSubject->expects($this->exactly(9))
$mockSubject->expects($this->any())
->method('getCoreConfigData')
->withConsecutive(
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_SAVE_REWRITES_HISTORY, true),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_SAVE_REWRITES_HISTORY, true),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html'),
array(CoreConfigDataKeys::CATALOG_SEO_SAVE_REWRITES_HISTORY, true),
array(CoreConfigDataKeys::CATALOG_SEO_PRODUCT_URL_SUFFIX, '.html')
)
->willReturnOnConsecutiveCalls('.html', '.html', '.html', true, '.html', true, '.html', true, '.html', '.html');
->will(
$this->returnCallback(function ($arg1, $arg2) {
return $arg2;
})
);
$mockSubject->expects($this->exactly(4))
->method('getImportAdapter')
->willReturn($mockImportAdapter);
Expand Down