Magento – Magento 2 Override Model using Plugin

magento-2.2.5modelmoduleplugin

I have to override magento 2 code model file in the custom module.

I have to override below method from Magento\Quote\Model\Quote\Address to my custom module and I have to change value of $amount.

public function validateMinimumAmount()
{
    $storeId = $this->getQuote()->getStoreId();
    $validateEnabled = $this->_scopeConfig->isSetFlag(
        'sales/minimum_order/active',
        \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
        $storeId
    );
    if (!$validateEnabled) {
        return true;
    }

    if (!$this->getQuote()->getIsVirtual() xor $this->getAddressType() == self::TYPE_SHIPPING) {
        return true;
    }

    $amount = $this->_scopeConfig->getValue(
        'sales/minimum_order/amount',
        \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
        $storeId
    );
    $taxInclude = $this->_scopeConfig->getValue(
        'sales/minimum_order/tax_including',
        \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
        $storeId
    );
    $taxes = $taxInclude ? $this->getBaseTaxAmount() : 0;

    return ($this->getBaseSubtotalWithDiscount() + $taxes >= $amount);
} 

app/code/vendor/module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Quote\Model\Quote\Address">
        <plugin name="my_address_plugin" type="vendor\module\Plugin\AddressPlugin" sortOrder="1" />
    </type>    
</config>

can anyone please help? I'm not sure which method to use before, after or around and how to set custom value for $amount using my plugin.

Best Answer

Ok, here is how to accomplish this with argument replacement. Essentially, we are replacing the current instance of Magento\Framework\App\Config\ScopeConfigInterface but ONLY for the one specific class. This is the preferred method because we don't want to do a full class override like some commenters suggest, that would just be greedy. In this case, we accomplish our goal with minimal interference to the rest of the code.

In your di.xml

<type name="Magento\Quote\Model\Quote\Address">
    <arguments>
        <argument name="scopeConfig" xsi:type="object">Vendorname\Modulename\Model\ScopeConfig</argument>
    </arguments>
</type>

Create a model at Model/ScopeConfig.php

<?php

namespace Vendorname\Modulename\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;

class ScopeConfig extends \Magento\Framework\App\Config
{
    /**
     * @param null|string $path
     * @param string      $scope
     * @param null|string $scopeCode
     *
     * @return mixed|string
     */
    public function getValue(
        $path = null,
        $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
        $scopeCode = null
    ) {
        $result = parent::getValue($path, $scope, $scopeCode);

        if ($path === 'sales/minimum_order/amount') {
            $result = 'do your logic and return some special value here';
        }

        return $result;
    }
}
Related Topic