Description
Preconditions
Magento version: 2.1.4 community edition
PHP version 7.0.15
Steps to reproduce
Try to assign some products to categories programmatically using a CategoryLinkManagement object. The code looks something like this:
$this
->categoryLinkManagement
->assignProductToCategories(
$someValidProduct->getSku(),
[$someValidCategory->getId()]
);
where the categoryLinkManagement
property is injected via DI into the current class.
Expected result
The product gets assigned to the category.
Actual result
I get an error telling me that "Could not save product "2048" with position 0 to category 42"
What I think
After digging around in the code, it seems that the issue stems from this piece of code in the Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator
class, the isCategoryProperForGenerating
method:
if ($category->getParentId() != \Magento\Catalog\Model\Category::TREE_ROOT_ID) {
list(, $rootCategoryId) = $category->getParentIds();
return $rootCategoryId == $this->storeManager->getStore($storeId)->getRootCategoryId();
}
more specific,
list(, $rootCategoryId) = $category->getParentIds();
From what I can tell, the code simply tries to get the first element from the array of category parent ids and assign it to $rootCategoryId
, but it does that by relying on php 5 or less behavior. Here is what the php manual says about list
:
Warning
In PHP 5, list() assigns the values starting with the right-most parameter. In PHP 7, list() starts with the left-most parameter.
They are even warning that list
is unpredictable:
Generally speaking, it is advisable to avoid relying on a specific order of operation, as this may change again in the future.
So this code fails to get the root category in php 7 and it even generates a notice if the parent ids array has less than 2 elements, since there is no element with an index of 1.
Exception: Notice: Undefined offset: 1 in vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php on line 195
(here is a related issue detailing this: #7916)