Question

I'm trying to override the module-catalog/Block/Product/View/Options/Type/Select.php class with a new version which includes a few other bits of custom php (adding HTML classes and IDs to the containing DIVs). I am trying to achieve this by creating anew module. Unfortunately, when this new module is enabled, the select options aren't rendered to the product page. The rest of the page is fine, just without the select (checkboxes and radio buttons) options. I think everything looks fine and should work, so I can't understand why the Select.php isn't returning the select options.

Directory structure:

app/
├── Mike/
│   ├── Newselect/
│   │   ├── Block/
│   │   │   ├── Product/
│   │   │   │   ├── View/
│   │   │   │   │   ├── Options/
│   │   │   │   │   │   ├── Type/
│   │   │   │   │   │   │   ├── Select.php
│   │   ├── etc/
│   │   │   ├── di.xml
│   │   │   ├── module.xml
│   │   ├── registration.php
│   │   ├── composer.json

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\Product\View\Options\Type\Select" type="Mike\Newselect\Block\Product\View\Options\Type\Select" />
</config>

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="Mike_Newselect" setup_version="1.0.0"/>
</config>

registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Mike_Newselect',
    __DIR__    
);

composer.json

{
    "name": "Mike/Newselect",
    "description": "Update the Select module to add HTML classes and IDs",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/module-store": "100.0.*",
        "magento/module-eav": "100.0.*",
        "magento/module-cms": "100.0.*",
        "magento/module-indexer": "100.0.*",
        "magento/module-customer": "100.0.*",
        "magento/module-theme": "100.0.*",
        "magento/module-checkout": "100.0.*",
        "magento/module-backend": "100.0.*",
        "magento/module-widget": "100.0.*",
        "magento/module-wishlist": "100.0.*",
        "magento/module-tax": "100.0.*",
        "magento/module-msrp": "100.0.*",
        "magento/module-catalog-inventory": "100.0.*",
        "magento/module-directory": "100.0.*",
        "magento/module-catalog-rule": "100.0.*",
        "magento/module-product-alert": "100.0.*",
        "magento/module-url-rewrite": "100.0.*",
        "magento/module-catalog-url-rewrite": "100.0.*",
        "magento/module-page-cache": "100.0.*",
        "magento/module-quote": "100.0.*",
        "magento/module-config": "100.0.*",
        "magento/module-media-storage": "100.0.*",
        "magento/framework": "100.0.*",
        "magento/module-configurable-product": "100.0.*",
        "magento/module-ui": "100.0.*"
    },
    "suggest": {
        "magento/module-cookie": "100.0.*",
        "magento/module-catalog-sample-data": "Sample Data version:100.0.*"
    },
    "type": "magento2-module",
    "version": "100.0.5",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Magento\\Catalog\\": ""
        }
    }
}

Select.php (this just a copy of the core Select.php file – not updated yet – apart from the Namespace and extending the core class)

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

/**
 * Product options text type block
 *
 * @author     Magento Core Team <core@magentocommerce.com>
 */

namespace Mike\Newselect\Block\Product\View\Options\Type;

class Select extends \Magento\Catalog\Block\Product\View\Options\Type\Select
{
    /**
     * Return html for control element
     *
     * @return string
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function getValuesHtml()
    {
        $_option = $this->getOption();
        $configValue = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $_option->getId());
        $store = $this->getProduct()->getStore();

        $this->setSkipJsReloadPrice(1);
        // Remove inline prototype onclick and onchange events

        if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_DROP_DOWN ||
            $_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_MULTIPLE
        ) {
            $require = $_option->getIsRequire() ? ' required' : '';
            $extraParams = '';
            $select = $this->getLayout()->createBlock(
                'Magento\Framework\View\Element\Html\Select'
            )->setData(
                [
                    'id' => 'select_' . $_option->getId(),
                    'class' => $require . ' product-custom-option admin__control-select'
                ]
            );
            if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_DROP_DOWN) {
                $select->setName('options[' . $_option->getid() . ']')->addOption('', __('-- Please Select --'));
            } else {
                $select->setName('options[' . $_option->getid() . '][]');
                $select->setClass('multiselect admin__control-multiselect' . $require . ' product-custom-option');
            }
            foreach ($_option->getValues() as $_value) {
                $priceStr = $this->_formatPrice(
                    [
                        'is_percent' => $_value->getPriceType() == 'percent',
                        'pricing_value' => $_value->getPrice($_value->getPriceType() == 'percent'),
                    ],
                    false
                );
                $select->addOption(
                    $_value->getOptionTypeId(),
                    $_value->getTitle() . ' ' . strip_tags($priceStr) . '',
                    ['price' => $this->pricingHelper->currencyByStore($_value->getPrice(true), $store, false)]
                );
            }
            if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_MULTIPLE) {
                $extraParams = ' multiple="multiple"';
            }
            if (!$this->getSkipJsReloadPrice()) {
                $extraParams .= ' onchange="opConfig.reloadPrice()"';
            }
            $select->setExtraParams($extraParams);

            if ($configValue) {
                $select->setValue($configValue);
            }

            return $select->getHtml();
        }

        if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_RADIO ||
            $_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_CHECKBOX
        ) {
            $selectHtml = '<div class="options-list nested" id="options-' . $_option->getId() . '-list">';
            $require = $_option->getIsRequire() ? ' required' : '';
            $arraySign = '';
            switch ($_option->getType()) {
                case \Magento\Catalog\Model\Product\Option::OPTION_TYPE_RADIO:
                    $type = 'radio';
                    $class = 'radio admin__control-radio';
                    if (!$_option->getIsRequire()) {
                        $selectHtml .= '<div class="field choice admin__field admin__field-option">' .
                            '<input type="radio" id="options_' .
                            $_option->getId() .
                            '" class="' .
                            $class .
                            ' product-custom-option" name="options[' .
                            $_option->getId() .
                            ']"' .
                            ($this->getSkipJsReloadPrice() ? '' : ' onclick="opConfig.reloadPrice()"') .
                            ' value="" checked="checked" /><label class="label admin__field-label" for="options_' .
                            $_option->getId() .
                            '"><span>' .
                            __('None') . '</span></label></div>';
                    }
                    break;
                case \Magento\Catalog\Model\Product\Option::OPTION_TYPE_CHECKBOX:
                    $type = 'checkbox';
                    $class = 'checkbox admin__control-checkbox';
                    $arraySign = '[]';
                    break;
            }
            $count = 1;
            foreach ($_option->getValues() as $_value) {
                $count++;

                $priceStr = $this->_formatPrice(
                    [
                        'is_percent' => $_value->getPriceType() == 'percent',
                        'pricing_value' => $_value->getPrice($_value->getPriceType() == 'percent'),
                    ]
                );

                $htmlValue = $_value->getOptionTypeId();
                if ($arraySign) {
                    $checked = is_array($configValue) && in_array($htmlValue, $configValue) ? 'checked' : '';
                } else {
                    $checked = $configValue == $htmlValue ? 'checked' : '';
                }

                $selectHtml .= '<div class="field choice admin__field admin__field-option' .
                    $require .
                    '">' .
                    '<input type="' .
                    $type .
                    '" class="' .
                    $class .
                    ' ' .
                    $require .
                    ' product-custom-option"' .
                    ($this->getSkipJsReloadPrice() ? '' : ' onclick="opConfig.reloadPrice()"') .
                    ' name="options[' .
                    $_option->getId() .
                    ']' .
                    $arraySign .
                    '" id="options_' .
                    $_option->getId() .
                    '_' .
                    $count .
                    '" value="' .
                    $htmlValue .
                    '" ' .
                    $checked .
                    ' price="' .
                    $this->pricingHelper->currencyByStore($_value->getPrice(true), $store, false) .
                    '" />' .
                    '<label class="label admin__field-label" for="options_' .
                    $_option->getId() .
                    '_' .
                    $count .
                    '"><span>' .
                    $_value->getTitle() .
                    '</span> ' .
                    $priceStr .
                    '</label>';
                $selectHtml .= '</div>';
            }
            $selectHtml .= '</div>';

            return $selectHtml;
        }
    }
}

catalog_product_view.xml

<block class="Magento\Catalog\Block\Product\View\Options\Type\Select" as="select" template="product/view/options/type/select.phtml"/>
Was it helpful?

Solution

First of all, we need to add Constructor injection method to our custom select class: (Edit: we don't need to add Constructor Injection, we need to add the sequence module)

    <?php
    namespace Mike\Newselect\Block\Product\View\Options\Type;

    class Select extends \Magento\Catalog\Block\Product\View\Options\Type\Select
    {
        public function __construct(
            \Magento\Framework\View\Element\Template\Context $context,
            \Magento\Framework\Pricing\Helper\Data $pricingHelper,
            \Magento\Catalog\Helper\Data $catalogData,
            array $data = []
        )
        {
            parent::__construct($context, $pricingHelper, $catalogData, $data);
        }
        .....

We need to add the :

<?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="Mike_Newselect" setup_version="1.0.0">
            <sequence>
                <module name="Magento_Catalog"/>
            </sequence>
        </module>
</config>

http://devdocs.magento.com/guides/v2.1/extension-dev-guide/build/module-load-order.html

Second, copy vendor/magento/module-catalog/view/frontend/templates/product/view/options/type/select.phtml to our custom module app/code/Mike/Newselect/view/frontend/templates/product/view/options/type/select.phtml

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top