0

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;
    }
}


0

1 Answer 1

0

I found a solution. In this case aroundSave plugin should be used. 'extension_attributes' are populated with values before CategoryRepository::save method. Then after CategoryRepository::save method 'extension_attributes' are extracted and saved to a custom table.

/**
     * @param CategoryRepositoryInterface $subject
     * @param CategoryInterface $category
     * @return CategoryInterface
     */
    public function aroundSave(
        CategoryRepositoryInterface $subject,
        callable $proceed,
        CategoryInterface $category
    ): CategoryInterface {
//        $categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
//        $categoryCollection = $this->categoryFactory->create()->getAttributesCollection();

        $extensionAttributes = $category->getExtensionAttributes()/* ?: $this->categoryExtensionInterfaceFactory->create()*/;
/*        if ($extensionAttributes !== null && $extensionAttributes->getApiUploadedImage() !==null) {*/
//            $extensionAttributes->setApiUploadedImage($extensionAttributes->getApiUploadedImage());

        $category->setExtensionAttributes($extensionAttributes);

        $result = $proceed($category);

        $extensionAttributes = $category->getExtensionAttributes();

            $attributesEntity = $this->attributesFactory->create();
            $attributesEntity->setCategoryId((int) $category->getId());
            $attributesEntity->setApiUploadedImage($extensionAttributes->getApiUploadedImage());

            $this->logger->debug('api_image' . $extensionAttributes->getApiUploadedImage());
            $this->management->save($attributesEntity);
//            $this->attributesRepository->save($attributesEntity);
//            $this->$subject->save();
/*        }*/
//        $extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
//        $extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());

//        $category->setExtensionAttributes($extensionAttributes);

        return $result;
    }

I hope my researches will be helpful for a community.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.