Magento 2: Add a REST API for bulk updating category-product relationships

Magento 2: Add a REST API for bulk updating category-product relationships

Add a REST API for bulk updating category-product relationships: 

1.  app/code/DMTQ/Catalog/etc/webapi.xml





2. app/code/DMTQ/Catalog/Api/Data/CategoryProductIdLinkInterface.php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace DMTQ\Catalog\Api\Data;

use Magento\Framework\Api\ExtensibleDataInterface;

/**
* @api
* @since 100.0.2
*/
interface CategoryProductIdLinkInterface extends ExtensibleDataInterface
{
/**
* @return int|null
*/
public function getProductId();

/**
* @param int $productId
* @return $this
*/
public function setProductId($productId);

/**
* @return int|null
*/
public function getPosition();

/**
* @param int $position
* @return $this
*/
public function setPosition($position);

}

3. app/code/DMTQ/Catalog/Api/CategoryProductLinkManagementInterface.php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace DMTQ\Catalog\Api;

use DMTQ\Catalog\Api\Data\CategoryProductIdLinkInterface;

/**
* @api
* @since 100.0.2
*/
interface CategoryProductLinkManagementInterface
{
/**
* Assign products link to category
*
* @param int $categoryId
* @param CategoryProductIdLinkInterface [] $items
* @return bool
*/
public function setCategoryProductLinks(int $categoryId, array $items);
}

4. app/code/DMTQ/Catalog/Model/Api/CategoryProductIdLink.php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace DMTQ\Catalog\Model\Api;

/**
* @codeCoverageIgnore
*/
class CategoryProductIdLink extends \Magento\Framework\Api\AbstractExtensibleObject implements
\DMTQ\Catalog\Api\Data\CategoryProductIdLinkInterface
{
/**#@+
* Constant for confirmation status
*/
const KEY_PRODUCT_ID = 'product_id';
const KEY_POSITION = 'position';
/**#@-*/

/**
* {@inheritdoc}
*/
public function getProductId()
{
return $this->_get(self::KEY_PRODUCT_ID);
}

/**
* {@inheritdoc}
*/
public function getPosition()
{
return $this->_get(self::KEY_POSITION);
}


/**
* @param int $productId
* @return $this
*/
public function setProductId($productId)
{
return $this->setData(self::KEY_PRODUCT_ID, $productId);
}

/**
* @param int $position
* @return $this
*/
public function setPosition($position)
{
return $this->setData(self::KEY_POSITION, $position);
}

}

5. app/code/DMTQ/Catalog/Model/Api/CategoryProductLinkManagement.php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace DMTQ\Catalog\Model\Api;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Catalog\Model\Indexer\Product\Category;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Indexer\IndexerRegistry;
use DMTQ\Catalog\Api\CategoryProductLinkManagementInterface;

/**
* Represents Category Product Link Management class
*/
class CategoryProductLinkManagement implements CategoryProductLinkManagementInterface
{
/**
* @var CategoryRepositoryInterface
*/
protected CategoryRepositoryInterface $categoryRepository;

/**
* @var IndexerRegistry
*/
protected IndexerRegistry $indexerRegistry;

/**
* CategoryLinkManagement constructor.
*
* @param CategoryRepositoryInterface $categoryRepository
* @param IndexerRegistry $indexerRegistry
*/
public function __construct(
CategoryRepositoryInterface $categoryRepository,
IndexerRegistry $indexerRegistry,
) {
$this->categoryRepository = $categoryRepository;
$this->indexerRegistry = $indexerRegistry;
}

/**
* @param $categoryId
* @param array $items
* @return true
* @throws CouldNotSaveException|NoSuchEntityException
*/
public function setCategoryProductLinks($categoryId, array $items): true
{
$category = $this->categoryRepository->get($categoryId);
//$productPositions = $category->getProductsPosition();
$productPositions = [];
foreach ($items as $item) {
$productPositions[$item->getProductId()] = $item->getPosition();
}
$category->setPostedProducts($productPositions);
try {
$category->save();
} catch (\Exception $e) {
throw new CouldNotSaveException(
__(
'Could not save product to category %1',
$category->getId()
),
$e
);
}

$productCategoryIndexer = $this->indexerRegistry->get(Category::INDEXER_ID);
if (!$productCategoryIndexer->isScheduled()) {
foreach ($items as $item) {
$productCategoryIndexer->reindexRow($item->getProductId());
}
}else {
$productCategoryIndexer->invalidate();
}
return true;
}

}

6. POST /V1/categories/{categoryId}/assign-products

Path Param: categoryId

Body json: 

{
"items": [
{
"product_id": 201,
"position": 1
},
{
"product_id": 202,
"position": 2
},
{
"product_id": 203,
"position": 3
},
{
"product_id": 204,
"position": 4
}
]
}

 



Copyright © 2013-present Magento, Inc. All rights reserved.