Magento – Overwriting adminhtml block template for a products advanced pricing

adminhtmlmagento2override-block

—- EDIT #3 :

Please ignore the code in this question. The template tier.phtml is not used by magento 2.2.x (see edit #2)

The working code can be found here: Extra column in catalog_product_entity_tier_price not saving/updating in observer

—- EDIT #2 :

The problem I have found is that the tier.phtml doesn't seem to be used to create the advanced prices. Probably due to the following fact:

In Magento version 2.1, the product creation form was completely refactored, and implemented using the form UI component.

see: https://devdocs.magento.com/guides/v2.2/howdoi/customize_product.html

It is instead created via the /module-catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php, specifically the getTierPriceStructure method. This is the reason none of the below code ever worked. No var_dump() or die()'s ever had any effect anywhere. I've not found out where the tier.phtml is ever used.

I'll post an answer once I was able to modify the form.

// —- END EDIT #2 :

I'm trying to overwrite the following template in the adminhtml backend:

module-catalog/view/adminhtml/templates/catalog/product/edit/price/tier.phtml

I first tried overwriting the template in a single module, this however did not work as expected. I then found the following post: How to override adminhtml phtml in magento 2?

which claims a custom admin theme is required, hence my code is as follows:

What I've done is the following on a clean install of magento 2.2.3

files view

  1. Create custom module under app/code/Vendor/CustomModule/

app/code/Vendor/CustomModule/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_CustomModule',
    __DIR__
);

Make sure my module is loaded after the theme in

app/code/Vendor/CustomModule/etc/module.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_CustomModule" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

Overwrite the Tier.php to set my custom template path:

app/code/Vendor/CustomModule/Block/Adminhtml/Product/Edit/Tab/Price/Tier.php

<?php

namespace Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price;


/**
 * Adminhtml tier price item renderer
 */
class Tier extends \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price\Tier
{
    /**
     * @var string
     */
    protected $_template = 'Vendor_CustomModule::catalog/product/edit/price/tier.phtml';

}

Set preference in my di.xml and set my custom admin theme (created in point 2.)

app/code/Vendor/CustomModule/etc/adminhtml/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">
    <preference for="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price\Tier"
                type="Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price\Tier" />

    <!-- Admin theme. Start -->
    <type name="Magento\Theme\Model\View\Design">
        <arguments>
            <argument name="themes" xsi:type="array">
                <item name="adminhtml" xsi:type="string">Vendor/CustomAdminTheme</item>
            </argument>
        </arguments>
    </type>
    <!-- Admin theme. End -->
</config>
  1. Create custom admin theme

app/design/adminhtml/Vendor/CustomAdminTheme/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'adminhtml/Vendor/CustomAdminTheme',
    __DIR__
);

app/design/adminhtml/Vendor/CustomAdminTheme/theme.xml

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Vendor Custom Admin Theme</title>
    <parent>Magento/backend</parent>
</theme>

and create my custom tier-price template for testing:

app/design/adminhtml/Vendor/CustomAdminTheme/Magento_Catalog/templates/catalog/product/edit/price/tier.phtml

<?php

// @codingStandardsIgnoreFile

/* @var $block \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price\Tier */
$element = $block->getElement();
?>


THIS IS A TEST TEMPLATE!!

I have set 'MAGE_MODE' => 'developer' and run setup:upgrade and setup:di:compile, yet my backend 'advanced pricing' template in Catalog -> new Product does not update.

Any ideas where I went wrong?

Official Documentation Used:

  1. http://devdocs.magento.com/guides/v2.2/frontend-dev-guide/themes/admin_theme_create.html
  2. http://devdocs.magento.com/guides/v2.2/frontend-dev-guide/themes/admin_theme_apply.html

—- EDIT

As per @murtuza-zabuawala I've removed the custom admin theme, created a Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price.php,Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Attributes, Vendor\CustomModule\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes and overwritten the hardcoded class name to use mine instead:

Vendor/CustomModule/Block/Adminhtml/Product/Edit/Tab/Price.php

<?php

namespace Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab;


class Price extends \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price
{
    /**
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    protected function _prepareForm()
    {
        $product = $this->_coreRegistry->registry('product');

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();
        $fieldset = $form->addFieldset('tiered_price', ['legend' => __('Tier Pricing')]);

        $fieldset->addField(
            'default_price',
            'label',
            [
                'label' => __('Default Price'),
                'title' => __('Default Price'),
                'name' => 'default_price',
                'bold' => true,
                'value' => $product->getPrice()
            ]
        );

        $fieldset->addField(
            'tier_price',
            'text',
            ['name' => 'tier_price', 'class' => 'requried-entry', 'value' => $product->getData('tier_price')]
        );

        $form->getElement(
            'tier_price'
        )->setRenderer(
            $this->getLayout()->createBlock(\Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price\Tier::class)
        );

        $this->setForm($form);
    }

}

Vendor/CustomModule/Block/Adminhtml/Product/Edit/Tab/Attributes.php

<?php


namespace Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab;

/**
 * @SuppressWarnings(PHPMD.DepthOfInheritance)
 */
class Attributes extends \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Attributes
{

    protected function _prepareForm()
    {
        /** @var $group \Magento\Eav\Model\Entity\Attribute\Group */
        $group = $this->getGroup();
        if ($group) {
            /** @var \Magento\Framework\Data\Form $form */
            $form = $this->_formFactory->create();
            $product = $this->_coreRegistry->registry('product');
            $isWrapped = $this->_coreRegistry->registry('use_wrapper');
            if (!isset($isWrapped)) {
                $isWrapped = true;
            }
            $isCollapsable = $isWrapped && $group->getAttributeGroupCode() == 'product-details';
            $legend = $isWrapped ? __($group->getAttributeGroupName()) : null;
            // Initialize product object as form property to use it during elements generation
            $form->setDataObject($product);

            $fieldset = $form->addFieldset(
                'group-fields-' . $group->getAttributeGroupCode(),
                ['class' => 'user-defined', 'legend' => $legend, 'collapsable' => $isCollapsable]
            );

            $attributes = $this->getGroupAttributes();

            $this->_setFieldset($attributes, $fieldset, ['gallery']);

            $tierPrice = $form->getElement('tier_price');
            if ($tierPrice) {
                $tierPrice->setRenderer(
                    $this->getLayout()->createBlock(\Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price\Tier::class)
                );
            }

            // Add new attribute controls if it is not an image tab
            if (!$form->getElement(
                'media_gallery'
            ) && $this->_authorization->isAllowed(
                'Magento_Catalog::attributes_attributes'
            ) && $isWrapped
            ) {
                $attributeCreate = $this->getLayout()->createBlock(
                    \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Attributes\Create::class
                );

                $attributeCreate->getConfig()->setAttributeGroupCode(
                    $group->getAttributeGroupCode()
                )->setTabId(
                    'group_' . $group->getId()
                )->setGroupId(
                    $group->getId()
                )->setStoreId(
                    $form->getDataObject()->getStoreId()
                )->setAttributeSetId(
                    $form->getDataObject()->getAttributeSetId()
                )->setTypeId(
                    $form->getDataObject()->getTypeId()
                )->setProductId(
                    $form->getDataObject()->getId()
                );

                $attributeSearch = $this->getLayout()->createBlock(
                    \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Attributes\Search::class
                )->setGroupId(
                    $group->getId()
                )->setGroupCode(
                    $group->getAttributeGroupCode()
                );

                $attributeSearch->setAttributeCreate($attributeCreate->toHtml());

                $fieldset->setHeaderBar($attributeSearch->toHtml());
            }

            $values = $product->getData();

            // Set default attribute values for new product or on attribute set change
            if (!$product->getId() || $product->dataHasChangedFor('attribute_set_id')) {
                foreach ($attributes as $attribute) {
                    if (!isset($values[$attribute->getAttributeCode()])) {
                        $values[$attribute->getAttributeCode()] = $attribute->getDefaultValue();
                    }
                }
            }

            if ($product->hasLockedAttributes()) {
                foreach ($product->getLockedAttributes() as $attribute) {
                    $element = $form->getElement($attribute);
                    if ($element) {
                        $element->setReadonly(true, true);
                        $element->lock();
                    }
                }
            }

            $form->addValues($values);
            $form->setFieldNameSuffix('product');

            $this->_eventManager->dispatch(
                'adminhtml_catalog_product_edit_prepare_form',
                ['form' => $form, 'layout' => $this->getLayout()]
            );

            $this->setForm($form);
        }
    }

}

Vendor/CustomModule/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes.php

<?php

namespace Vendor\CustomModule\Block\Adminhtml\Catalog\Product\Edit\Tab;


class Attributes extends \Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes
{

    protected function _prepareForm()
    {
        parent::_prepareForm();

        $specialPrice = $this->getForm()->getElement('special_price');
        if ($specialPrice) {
            $specialPrice->setRenderer(
                $this->getLayout()->createBlock(
                    \Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes\Special::class
                )->setDisableChild(
                    false
                )
            );
            $specialPrice->addClass(
                implode(
                    ' ',
                    [
                        'validate-greater-than-zero',
                        'validate-number-range',
                        'number-range-0.00-100.00'
                    ]
                )
            );
        }

        $sku = $this->getForm()->getElement('sku');
        if ($sku) {
            $sku->setRenderer(
                $this->getLayout()->createBlock(
                    \Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes\Extend::class
                )->setDisableChild(
                    false
                )
            );
        }

        $price = $this->getForm()->getElement('price');
        if ($price) {
            $price->setRenderer(
                $this->getLayout()->createBlock(
                    \Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes\Extend::class,
                    'adminhtml.catalog.product.bundle.edit.tab.attributes.price'
                )->setDisableChild(
                    true
                )
            );
        }

        $tax = $this->getForm()->getElement('tax_class_id');
        if ($tax) {
            $tax->setAfterElementHtml(
                '<script>' .
                "
                require(['prototype'], function(){
                function changeTaxClassId() {
                    if ($('price_type').value == '" .
                \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC .
                "') {
                        $('tax_class_id').disabled = true;
                        $('tax_class_id').value = '0';
                        $('tax_class_id').removeClassName('required-entry');
                        if ($('advice-required-entry-tax_class_id')) {
                            $('advice-required-entry-tax_class_id').remove();
                        }
                    } else {
                        $('tax_class_id').disabled = false;
                        " .
                ($tax->getRequired() ? "$('tax_class_id').addClassName('required-entry');" : '') .
                "
                    }
                }

                if ($('price_type')) {
                    $('price_type').observe('change', changeTaxClassId);
                    changeTaxClassId();
                }
                });
                " .
                '</script>'
            );
        }

        $weight = $this->getForm()->getElement('weight');
        if ($weight) {
            $weight->setRenderer(
                $this->getLayout()->createBlock(
                    \Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes\Extend::class
                )->setDisableChild(
                    true
                )
            );
        }

        $tier_price = $this->getForm()->getElement('tier_price');
        if ($tier_price) {
            $tier_price->setRenderer(
                $this->getLayout()->createBlock(
                    \Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price\Tier::class
                )->setPriceColumnHeader(
                    __('Percent Discount')
                )->setPriceValidation(
                    'validate-greater-than-zero validate-number-range number-range-0.00-100.00'
                )
            );
        }
    }

}

and I've added it to my di.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <preference for="Magento\Bundle\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes"
                type="Vendor\CustomModule\Block\Adminhtml\Catalog\Product\Edit\Tab\Attributes" />

    <preference for="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Attributes"
                type="Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Attributes" />

    <preference for="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price"
                type="Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price" />

    <preference for="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Price\Tier"
                type="Vendor\CustomModule\Block\Adminhtml\Product\Edit\Tab\Price\Tier" />
</config>

This however still does not seem to want to work.
The complete module file structure now looks like this:

enter image description here

Best Answer

I think you've just place your phtml in wrong destination, please place your template file in app/code/Vendor/CustomModule/view/adminhtml/templates/catalog/product/edit/price/tier.phtml and it should reflect the changes.

Also there is no need to override the template in your own theme.

Related Topic