I am trying to create a module that uploads Category image (as Category extension attribute) via REST API. The problem is that I can't even fetch extension attributes in afterSave method of my Plugin with the lines of code below:
$extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();
Though, obviously, extension attribute is set in my API request to https://{{magento2_root}}/rest/async/bulk/V1/categories
[
{
"category": {
"parent_id": 229,
"name": "Мобільний телефон Nokia 214100",
"is_active": true,
"position": 1,
"level": 4,
"include_in_menu": true,
"extension_attributes": {
"category_id": 456,
"api_uploaded_image": "OnsL"
},
"custom_attributes": [
{
"attribute_code": "image",
"value": "nokia_62100.jpg"
},
{
"attribute_code": "description",
"value": "Good Nokia 62100"
}
]
}
},
{
"category": {
"parent_id": 229,
"name": "Мобільний телефон Nokia 215100",
"is_active": true,
"position": 1,
"level": 4,
"include_in_menu": true,
"extension_attributes": {
"category_id": 457,
"api_uploaded_image": "OnsL"
},
"custom_attributes": [
{
"attribute_code": "image",
"value": "nokia_62100.jpg"
},
{
"attribute_code": "description",
"value": "Good Nokia 62100"
}
]
}
}
]
The server gets "extension_attributes" "api_uploaded_image" and "category_id" with empty values (detailed status of bulk action with https://{{magento2_root}}/rest/V1/bulk/d6c6c3d0-5efc-4354-b52a-4dd782592515/detailed-status):
{
"operations_list": [
{
"id": 0,
"bulk_uuid": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
"topic_name": "async.magento.catalog.api.categoryrepositoryinterface.save.post",
"serialized_data": null,
"result_serialized_data":"{\"id\":457,\"parent_id\":229,\"name\":\"\М\о\б\і\л\ь\н\и\й \т\е\л\е\ф\о\н Nokia 214100\",\"is_active\":true,\"position\":1,\"level\":4,\"children\":\"\",\"created_at\":\"2022-09-24 17:20:40\",\"updated_at\":\"2022-09-24 17:20:40\",\"path\":\"1\\/2\\/161\\/229\\/457\",\"available_sort_by\":[],\"include_in_menu\":true,\"extension_attributes\":{\"api_uploaded_image\":\"\",\"category_id\":0},\"custom_attributes\":[{\"attribute_code\":\"description\",\"value\":\"Good Nokia 62100\"},{\"attribute_code\":\"image\",\"value\":\"nokia_62100.jpg\"},{\"attribute_code\":\"is_anchor\",\"value\":\"1\"},{\"attribute_code\":\"path\",\"value\":\"1\\/2\\/161\\/229\\/457\"},{\"attribute_code\":\"children_count\",\"value\":\"0\"},{\"attribute_code\":\"url_key\",\"value\":\"mobil-nij-telefon-nokia-214100\"},{\"attribute_code\":\"url_path\",\"value\":\"telefoni1\\/nedorogi-mobil-ni-telefoni\\/mobil-nij-telefon-nokia-214100\"},{\"attribute_code\":\"use_name_in_product_search\",\"value\":\"1\"},{\"attribute_code\":\"is_virtual_category\",\"value\":\"0\"},{\"attribute_code\":\"virtual_rule\",\"value\":{\"condition\":{\"condition_type\":\"Smile\\\\ElasticsuiteVirtualCategory\\\\Model\\\\Rule\\\\Condition\\\\Combine\",\"aggregator_type\":\"all\",\"operator\":null,\"value\":true}}},{\"attribute_code\":\"use_store_positions\",\"value\":\"0\"}]}",
"status": 1,
"result_message": "Service execution success Magento\\Catalog\\Model\\CategoryRepository\\Interceptor::save",
"error_code": null
},
{
"id": 1,
"bulk_uuid": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
"topic_name": "async.magento.catalog.api.categoryrepositoryinterface.save.post",
"serialized_data": null,
"result_serialized_data":"{\"id\":458,\"parent_id\":229,\"name\":\"\М\о\б\і\л\ь\н\и\й \т\е\л\е\ф\о\н Nokia 215100\",\"is_active\":true,\"position\":1,\"level\":4,\"children\":\"\",\"created_at\":\"2022-09-24 17:20:41\",\"updated_at\":\"2022-09-24 17:20:41\",\"path\":\"1\\/2\\/161\\/229\\/458\",\"available_sort_by\":[],\"include_in_menu\":true,\"extension_attributes\":{\"api_uploaded_image\":\"\",\"category_id\":0},\"custom_attributes\":[{\"attribute_code\":\"description\",\"value\":\"Good Nokia 62100\"},{\"attribute_code\":\"image\",\"value\":\"nokia_62100.jpg\"},{\"attribute_code\":\"is_anchor\",\"value\":\"1\"},{\"attribute_code\":\"path\",\"value\":\"1\\/2\\/161\\/229\\/458\"},{\"attribute_code\":\"children_count\",\"value\":\"0\"},{\"attribute_code\":\"url_key\",\"value\":\"mobil-nij-telefon-nokia-215100\"},{\"attribute_code\":\"url_path\",\"value\":\"telefoni1\\/nedorogi-mobil-ni-telefoni\\/mobil-nij-telefon-nokia-215100\"},{\"attribute_code\":\"use_name_in_product_search\",\"value\":\"1\"},{\"attribute_code\":\"is_virtual_category\",\"value\":\"0\"},{\"attribute_code\":\"virtual_rule\",\"value\":{\"condition\":{\"condition_type\":\"Smile\\\\ElasticsuiteVirtualCategory\\\\Model\\\\Rule\\\\Condition\\\\Combine\",\"aggregator_type\":\"all\",\"operator\":null,\"value\":true}}},{\"attribute_code\":\"use_store_positions\",\"value\":\"0\"}]}",
"status": 1,
"result_message": "Service execution success Magento\\Catalog\\Model\\CategoryRepository\\Interceptor::save",
"error_code": null
}
],
"user_type": 2,
"bulk_id": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
"description": "Topic async.magento.catalog.api.categoryrepositoryinterface.save.post",
"start_time": "2022-09-24 17:20:40",
"user_id": 1,
"operation_count": 2
}
1. db_schema.xml
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="sl_category_image_via_api_attribute" resource="default" engine="innodb" comment="Category Images Sent Via API Table">
<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity ID"/>
<column xsi:type="int" name="category_id" padding="10" unsigned="true" nullable="false" identity="false" comment="Category ID"/>
<column xsi:type="varchar" name="api_uploaded_image" nullable="false" comment="Base64 Encoded Images"/>
<column xsi:type="timestamp" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Create Time"/>
<column xsi:type="timestamp" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Update Time"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="entity_id"/>
</constraint>
<constraint xsi:type="foreign" referenceId="SL_CTGRY_IMG_VIA_API_ATTR_CATEGORY_ID_CATALOG_CTGRY_ENTT_ENTT_ID"
table="sl_category_image_via_api_attribute" column="category_id" referenceTable="catalog_category_entity"
referenceColumn="entity_id" onDelete="CASCADE"/>
</table>
</schema>
In a case I set nullable="true" for name="api_uploaded_image" attribute in db_schema.xml:
<column xsi:type="varchar" name="api_uploaded_image" nullable="true" comment="Base64 Encoded Images"/>
then I can save my custom entity in a custom table with "api_uploaded_image" column and NULL value:
How can I retrive category extension attribute in a Plugin (afterSave method) and then save it to my custom table?
I will be appreciate for your help. Thanks in advance.
2. The full code of Plugin
<?php
declare(strict_types=1);
namespace Sl\CategoryImageApiUpload\Plugin;
use Magento\Catalog\Api\Data\CategoryExtensionFactory;
use Sl\CategoryImageApiUpload\Api\ManagementInterface;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\Catalog\Api\Data\CategorySearchResultsInterface;
use Magento\Catalog\Api\CategoryRepositoryInterface;
use Sl\CategoryImageApiUpload\Model\AttributesFactory;
use Sl\CategoryImageApiUpload\Model\AttributesResource;
use \Psr\Log\LoggerInterface;
class CategoryRepositoryPlugin
{
/**
* @var LoggerInterface
*/
private LoggerInterface $logger;
/**
* @var ManagementInterface
*/
private ManagementInterface $management;
/**
* @var AttributesFactory
*/
private AttributesFactory $attributesFactory;
/**
* @var AttributesResource
*/
private AttributesResource $attributesResource;
/**
* @var CategoryExtensionFactory
*/
private CategoryExtensionFactory $categoryExtensionFactory;
/**
* CategoryRepositoryPlugin constructor.
* @param AttributesFactory $attributesFactory
* @param AttributesResource $attributesResource
* @param ManagementInterface $management
* @param CategoryExtensionFactory $categoryExtensionFactory
*/
public function __construct(
AttributesFactory $attributesFactory,
AttributesResource $attributesResource,
CategoryExtensionFactory $categoryExtensionFactory,
ManagementInterface $management,
LoggerInterface $logger
) {
$this->attributesFactory = $attributesFactory;
$this->attributesResource = $attributesResource;
$this->categoryExtensionFactory = $categoryExtensionFactory;
$this->management = $management;
$this->logger = $logger;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategorySearchResultsInterface $categorySearchResult
* @return CategorySearchResultsInterface
*/
public function afterGetList(
CategoryRepositoryInterface $subject,
CategorySearchResultsInterface $categorySearchResult
): CategorySearchResultsInterface {
foreach ($categorySearchResult->getItems() as $category) {
$this->afterGet($subject, $category);
}
return $categorySearchResult;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategoryInterface $category
* @return CategoryInterface
*/
public function afterGet(
CategoryRepositoryInterface $subject,
CategoryInterface $category
): CategoryInterface {
$categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
$extensionAttributes = $category->getExtensionAttributes();
$extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
$extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());
$category->setExtensionAttributes($extensionAttributes);
return $category;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategoryInterface $category
* @return CategoryInterface
*/
public function afterSave(
CategoryRepositoryInterface $subject,
CategoryInterface $category
): CategoryInterface {
// $categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
// $categoryCollection = $this->categoryFactory->create()->getAttributesCollection();
$extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();
if ($extensionAttributes !== null && $extensionAttributes->getApiUploadedImage() !==null) {
// $extensionAttributes->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
$attributesEntity = $this->attributesFactory->create();
$attributesEntity->setCategoryId($category->getId());
$attributesEntity->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
// $this->logger->debug('valuer=' .serialize($attributesEntity));
$this->management->save($attributesEntity);
// $this->attributesRepository->save($attributesEntity);
// $this->$subject->save();
}
// $extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
// $extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());
// $category->setExtensionAttributes($extensionAttributes);
return $category;
}
}