Situação de quinta-feira à noite: o módulo de frete que a loja comprou tem um plugin no processador de layout do checkout, e esse plugin some com um campo que você precisa. O resto do módulo funciona. Você não vai editar vendor/, porque o próximo composer update apaga. E module:disable derruba o frete inteiro.
O Magento tem uma saída para exatamente isso, e ela cabe num atributo. A documentação da Adobe diz em uma linha: para desativar um plugin, coloque disabled como true na declaração dele. O padrão é false.
Ache o nome exato do plugin
O name do plugin é uma string que o fornecedor inventou. Ela é a chave de merge do di.xml, então você precisa dela igualzinha. Comece grepando o módulo do fornecedor:
grep -rn "<plugin " vendor/fornecedor/*/etc/ --include="di.xml"Ou pergunte ao próprio Magento quem está pendurado na classe:
php bin/magento dev:di:info 'Magento\Checkout\Block\Checkout\LayoutProcessor' frontendO segundo argumento é a área, e ele é posicional: frontend, adminhtml, webapi_rest, crontab. Sem passar nada, o comando olha só o escopo global, e plugin de checkout simplesmente não aparece na lista.
Anote três coisas antes de escrever qualquer arquivo: o valor de <type name="...">, o name do plugin e em qual arquivo ele mora — etc/di.xml ou etc/frontend/di.xml. A área importa mais do que parece, e volto nisso no fim.
O módulo de três arquivos
Não precisa de classe PHP nenhuma. Só isso:
app/code/Loja/DesligaPlugin/registration.php
app/code/Loja/DesligaPlugin/etc/module.xml
app/code/Loja/DesligaPlugin/etc/frontend/di.xmlNo etc/module.xml, declare o módulo do fornecedor dentro de <sequence>. Segundo a Adobe, o sequence é o que garante que os arquivos de configuração daquele componente já estejam carregados quando o seu entrar:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Loja_DesligaPlugin">
<sequence>
<module name="Fornecedor_Modulo"/>
</sequence>
</module>
</config>E o etc/frontend/di.xml, que é a parte que faz o trabalho. Repare que não tem type do plugin: você só cita o nome e desliga.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
<plugin name="ProcessPaymentConfiguration" disabled="true"/>
</type>
</config>Esse exemplo não é inventado: é o que o Magento_Vault faz com o plugin ProcessPaymentConfiguration, que o Magento_Payment declara no etc/frontend/di.xml dele. E sim, o Vault tem o Magento_Payment no sequence. Copiar o core costuma ser um bom plano.
Para valer:
php bin/magento module:enable Loja_DesligaPlugin
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:flushEm modo developer o setup:di:compile não é obrigatório, mas apague o generated/ antes de testar. Interceptor velho em cache já me fez perder uma tarde jurando que o disabled não funcionava.
Os quatro tropeços
1. Nome errado é silêncio. Se você digitar ProcessPaymentConfig em vez de ProcessPaymentConfiguration, o Magento cria um nó novo, desligado, que não corresponde a plugin nenhum. Ninguém reclama e o plugin original continua rodando. Copie e cole do arquivo do fornecedor.
2. Área errada. Plugin declarado em etc/frontend/di.xml se desliga em etc/frontend/di.xml. Se ele está no etc/di.xml global, o seu também vai no global. Espelhe o caminho do arquivo do fornecedor e você não erra.
3. O nome da classe no type. A própria documentação da Adobe avisa: a classe pode ser escrita com barra inicial ou sem, e você precisa usar o mesmo formato que foi usado na declaração. Copie a linha inteira.
4. Desligar plugin não é desligar módulo. module:disable tira rotas, tabelas e configuração do ar; o disabled="true" só cala aquele interceptor. Se o que te incomoda é a ordem em que dois plugins rodam, não desligue nada — mexa no sortOrder, que existe para isso.
Um aviso que eu dou para todo cliente: plugin de módulo pago quase sempre está fazendo alguma coisa que o resto do módulo espera. Desligar um after que grava dado no quote pode quebrar o pedido lá na frente, e o suporte do fornecedor vai olhar o seu app/code e encerrar o chamado. Teste em homologação com pedido de ponta a ponta antes de subir. Se você ainda está montando o esqueleto do módulo, o guia de desenvolvimento de módulos tem o registration.php e o module.xml prontos.
Perguntas rápidas
Preciso repetir o type do plugin para desligar?
Não. Basta o nome e o atributo disabled. O tipo já veio na declaração original e o merge do di.xml junta os dois nós pelo nome.
Isso sobrevive ao composer update do módulo do fornecedor?
Sim, porque o seu código está em app/code e não em vendor. O único risco é o fornecedor renomear o plugin numa versão nova. Aí o seu disabled deixa de casar e volta a rodar, em silêncio.
Dá para desligar um plugin do próprio core do Magento?
Dá, é o mesmo procedimento. Só tenha em mente que muita coisa do core depende desses interceptors, então a chance de quebrar outra funcionalidade é bem maior do que com módulo de terceiro.
Pra conferir na fonte
- Plugins (interceptors) — Adobe Developer
- Component load order — Adobe Developer
- Magento_Vault etc/frontend/di.xml — GitHub
- Magento_Payment etc/frontend/di.xml — GitHub