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 SlCategoryImageApiUploadPlugin;
use MagentoCatalogApiDataCategoryExtensionFactory;
use SlCategoryImageApiUploadApiManagementInterface;
use MagentoCatalogApiDataCategoryInterface;
use MagentoCatalogApiDataCategorySearchResultsInterface;
use MagentoCatalogApiCategoryRepositoryInterface;
use SlCategoryImageApiUploadModelAttributesFactory;
use SlCategoryImageApiUploadModelAttributesResource;
use PsrLogLoggerInterface;
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;
}
}