Magento – Adding a new method to an Abstract Class in Magento 2

dependency-injectionmagento2overrides

Like this thread said: Override abstract class in Magento 2 in Magento 1,

I can just create a fully new class.
In Magento 2, we need to use plugins, but plugins only allow me to modify existing methods. What do I have to do if I want to add a new method?

Example:

This class vendor/magento/module-ui/Component/AbstractComponent.php, has an array of components: $components, there is no function to unset/delete elements for that array. So how can I create that function?

Best Answer

I don't see how you can do that without completely overriding the class. In the case of your example, you can disable individual components by setting the "disabled" item to the "data" argument in the XML. For instance:

<?xml version="1.0" encoding="UTF-8"?>

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="general">
        <field name="title">
            <argument name="data" xsi:type="array">
                <item name="disabled" xsi:type="boolean">true</item>
            </argument>
        </field>
    </fieldset>
</form>

This effectively removes 'title' from the $components array.

This is due to the createChildComponent method in the Magento\Framework\View\Element\UiComponentFactory class:

 protected function createChildComponent(
        array $bundleComponents,
        ContextInterface $renderContext,
        $identifier
    ) {
        list($className, $arguments) = $this->argumentsResolver($identifier, $bundleComponents);
        if (isset($arguments['data']['disabled']) && (int)$arguments['data']['disabled']) {
            return null;
        }
        $components = [];
        foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) {
            $children = $this->createChildComponent(
                $childrenData,
                $renderContext,
                $childrenIdentifier
            );
            $components[$childrenIdentifier] = $children;
        }
        $components = array_filter($components);
        $arguments['components'] = $components;
        if (!isset($arguments['context'])) {
            $arguments['context'] = $renderContext;
        }

        return $this->objectManager->create($className, $arguments);
    }