Magento Show ‘Out of stock’ simple products in the configurable product (in drop down menu)?

I need some help from advanced users with configurable products. By default Magento display on configurable product page (in drop down menu) only simple products which are “In stock”.

I want show all options, even when product is “out of stock”.

 Magento version 1.7

Relapse code in this file:  Your project/app/code/local/Mage/Catalog/Block/Product/View/Type/Configurable.php

<?php
/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @category    Mage
 * @package     Mage_Catalog
 * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */


/**
 * Catalog super product configurable part block
 *
 * @category   Mage
 * @package    Mage_Catalog
 * @author      Magento Core Team <core@magentocommerce.com>
 */
class Mage_Catalog_Block_Product_View_Type_Configurable extends Mage_Catalog_Block_Product_View_Abstract
{
    /**
     * Prices
     *
     * @var array
     */
    protected $_prices      = array();

    /**
     * Prepared prices
     *
     * @var array
     */
    protected $_resPrices   = array();

    /**
     * Get allowed attributes
     *
     * @return array
     */
    public function getAllowAttributes()
    {
        return $this->getProduct()->getTypeInstance(true)
            ->getConfigurableAttributes($this->getProduct());
    }

    /**
     * Check if allowed attributes have options
     *
     * @return bool
     */
    public function hasOptions()
    {
        $attributes = $this->getAllowAttributes();
        if (count($attributes)) {
            foreach ($attributes as $attribute) {
                /** @var Mage_Catalog_Model_Product_Type_Configurable_Attribute $attribute */
                if ($attribute->getData('prices')) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Get Allowed Products
     *
     * @return array
     */
    // Original code to modify
    /*public function getAllowProducts()
    {
        if (!$this->hasAllowProducts()) {
            $products = array();
            $skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
            $allProducts = $this->getProduct()->getTypeInstance(true)
                ->getUsedProducts(null, $this->getProduct());
            foreach ($allProducts as $product) {
                if ($product->isSaleable() || $skipSaleableCheck) {
                    $products[] = $product;
                }
            }
            $this->setAllowProducts($products);
        }
        return $this->getData('allow_products');
    }*/
    public function getAllowProducts() {
        $allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts();
        $this->setAllowProducts($allProducts);
        return $this->getData('allow_products');
    }

    /**
     * retrieve current store
     *
     * @return Mage_Core_Model_Store
     */
    public function getCurrentStore()
    {
        return Mage::app()->getStore();
    }

    /**
     * Returns additional values for js config, con be overriden by descedants
     *
     * @return array
     */
    protected function _getAdditionalConfig()
    {
        return array();
    }

    /**
     * Composes configuration for js
     *
     * @return string
     */
    // Original code to modify
//    public function getJsonConfig()
//    {
//        $attributes = array();
//        $options    = array();
//        $store      = $this->getCurrentStore();
//        $taxHelper  = Mage::helper('tax');
//        $currentProduct = $this->getProduct();

//        $preconfiguredFlag = $currentProduct->hasPreconfiguredValues();
//        if ($preconfiguredFlag) {
//            $preconfiguredValues = $currentProduct->getPreconfiguredValues();
//            $defaultValues       = array();
//        }

//        foreach ($this->getAllowProducts() as $product) {
//            $productId  = $product->getId();

//            foreach ($this->getAllowAttributes() as $attribute) {
//                $productAttribute   = $attribute->getProductAttribute();
//                $productAttributeId = $productAttribute->getId();
//                $attributeValue     = $product->getData($productAttribute->getAttributeCode());
//                if (!isset($options[$productAttributeId])) {
//                    $options[$productAttributeId] = array();
//                }

//                if (!isset($options[$productAttributeId][$attributeValue])) {
//                    $options[$productAttributeId][$attributeValue] = array();
//                }
//                $options[$productAttributeId][$attributeValue][] = $productId;
//            }
//        }

//        $this->_resPrices = array(
//            $this->_preparePrice($currentProduct->getFinalPrice())
//        );

//        foreach ($this->getAllowAttributes() as $attribute) {
 //           $productAttribute = $attribute->getProductAttribute();
//            $attributeId = $productAttribute->getId();
//            $info = array(
//                'id'        => $productAttribute->getId(),
//                'code'      => $productAttribute->getAttributeCode(),
 //               'label'     => $attribute->getLabel(),
//                'options'   => array()
 //           );

//            $optionPrices = array();
//            $prices = $attribute->getPrices();
//            if (is_array($prices)) {
//                foreach ($prices as $value) {
//                    if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
//                        continue;
//                    }
//                    $currentProduct->setConfigurablePrice(
//                        $this->_preparePrice($value['pricing_value'], $value['is_percent'])
//                    );
//                    $currentProduct->setParentId(true);
//                    Mage::dispatchEvent(
//                        'catalog_product_type_configurable_price',
//                        array('product' => $currentProduct)
//                    );
  //                  $configurablePrice = $currentProduct->getConfigurablePrice();

//                    if (isset($options[$attributeId][$value['value_index']])) {
//                        $productsIndex = $options[$attributeId][$value['value_index']];
//                    } else {
//                        $productsIndex = array();
//                    }

//                    $info['options'][] = array(
//                        'id'        => $value['value_index'],
//                        'label'     => $value['label'],
//                        'price'     => $configurablePrice,
//                        'oldPrice'  => $this->_prepareOldPrice($value['pricing_value'], $value['is_percent']),
//                        'products'  => $productsIndex,
//                    );
  //                  $optionPrices[] = $configurablePrice;
//                }
//            }
            /**
             * Prepare formated values for options choose
             */
//            foreach ($optionPrices as $optionPrice) {
//                foreach ($optionPrices as $additional) {
//                    $this->_preparePrice(abs($additional-$optionPrice));
//                }
//            }
//            if($this->_validateAttributeInfo($info)) {
//                $attributes[$attributeId] = $info;
  //          }

            // Add attribute default value (if set)
//            if ($preconfiguredFlag) {
  //              $configValue = $preconfiguredValues->getData('super_attribute/' . $attributeId);
//                if ($configValue) {
//                    $defaultValues[$attributeId] = $configValue;
//                }
//            }
//        }

//        $taxCalculation = Mage::getSingleton('tax/calculation');
//        if (!$taxCalculation->getCustomer() && Mage::registry('current_customer')) {
//            $taxCalculation->setCustomer(Mage::registry('current_customer'));
//        }

//        $_request = $taxCalculation->getRateRequest(false, false, false);
//        $_request->setProductClassId($currentProduct->getTaxClassId());
//        $defaultTax = $taxCalculation->getRate($_request);

//        $_request = $taxCalculation->getRateRequest();
//        $_request->setProductClassId($currentProduct->getTaxClassId());
//        $currentTax = $taxCalculation->getRate($_request);

//        $taxConfig = array(
//            'includeTax'        => $taxHelper->priceIncludesTax(),
//            'showIncludeTax'    => $taxHelper->displayPriceIncludingTax(),
//            'showBothPrices'    => $taxHelper->displayBothPrices(),
//            'defaultTax'        => $defaultTax,
//            'currentTax'        => $currentTax,
//            'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax')
//        );

//        $config = array(
//            'attributes'        => $attributes,
//            'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
//            'basePrice'         => $this->_registerJsPrice($this->_convertPrice($currentProduct->getFinalPrice())),
//            'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($currentProduct->getPrice())),
//            'productId'         => $currentProduct->getId(),
//            'chooseText'        => Mage::helper('catalog')->__('Choose an Option...'),
//            'taxConfig'         => $taxConfig
//        );

//        if ($preconfiguredFlag && !empty($defaultValues)) {
//            $config['defaultValues'] = $defaultValues;
//        }

    //    $config = array_merge($config, $this->_getAdditionalConfig());

    //   return Mage::helper('core')->jsonEncode($config);
    //}
    public function getJsonConfig()
    {
        $attributes = array();
        $options = array();
        $store = Mage::app()->getStore();
        foreach ($this->getAllowProducts() as $product) {
            $productId  = $product->getId();
            //var_dump(    'testo' . floor($product->getStockItem()->getQty())  );



            foreach ($this->getAllowAttributes() as $attribute) {
                $productAttribute = $attribute->getProductAttribute();
                $attributeValue = $product->getData($productAttribute->getAttributeCode());

                $options['qty'][$product -> getAttributeText($productAttribute->getName())] = floor($product->getStockItem()->getQty());


                if (!isset($options[$productAttribute->getId()])) {
                    $options[$productAttribute->getId()] = array();
                }

                if (!isset($options[$productAttribute->getId()][$attributeValue])) {
                    $options[$productAttribute->getId()][$attributeValue] = array();
                }
                $options[$productAttribute->getId()][$attributeValue][] = $productId;
            }
        }

        $this->_resPrices = array(
            $this->_preparePrice($this->getProduct()->getFinalPrice())
        );

        foreach ($this->getAllowAttributes() as $attribute) {
            $productAttribute = $attribute->getProductAttribute();
            $attributeId = $productAttribute->getId();
            $info = array(
                'id'        => $productAttribute->getId(),
                'code'      => $productAttribute->getAttributeCode(),
                'label'     => $attribute->getLabel(),
                'options'   => array()
            );

            $optionPrices = array();
            $prices = $attribute->getPrices();
            if (is_array($prices)) {
                foreach ($prices as $value) {
                    if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
                        continue;
                    }

                    $info['options'][] = array(
                        'id'    => $value['value_index'],
                        'label' => ($options['qty'][$value['label']] <= 0) ? $value['label'] . ' * out of stock' : $value['label'] . "",
                        'price' => $this->_preparePrice($value['pricing_value'], $value['is_percent']),
                        'products'   => isset($options[$attributeId][$value['value_index']]) ? $options[$attributeId][$value['value_index']] : array(),
                    );
                    $optionPrices[] = $this->_preparePrice($value['pricing_value'], $value['is_percent']);
                    //$this->_registerAdditionalJsPrice($value['pricing_value'], $value['is_percent']);
                }
            }
            /**
             * Prepare formated values for options choose
             */
            foreach ($optionPrices as $optionPrice) {
                foreach ($optionPrices as $additional) {
                    $this->_preparePrice(abs($additional-$optionPrice));
                }
            }
            if($this->_validateAttributeInfo($info)) {
                $attributes[$attributeId] = $info;
            }
        }
        /*echo '<pre>';
        print_r($this->_prices);
        echo '</pre>';die();*/

        $_request = Mage::getSingleton('tax/calculation')->getRateRequest(false, false, false);
        $_request->setProductClassId($this->getProduct()->getTaxClassId());
        $defaultTax = Mage::getSingleton('tax/calculation')->getRate($_request);

        $_request = Mage::getSingleton('tax/calculation')->getRateRequest();
        $_request->setProductClassId($this->getProduct()->getTaxClassId());
        $currentTax = Mage::getSingleton('tax/calculation')->getRate($_request);

        $taxConfig = array(
            'includeTax'        => Mage::helper('tax')->priceIncludesTax(),
            'showIncludeTax'    => Mage::helper('tax')->displayPriceIncludingTax(),
            'showBothPrices'    => Mage::helper('tax')->displayBothPrices(),
            'defaultTax'        => $defaultTax,
            'currentTax'        => $currentTax,
            'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax'),
        );

        $config = array(
            'attributes'        => $attributes,
            'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
//            'prices'          => $this->_prices,
            'basePrice'         => $this->_registerJsPrice($this->_convertPrice($this->getProduct()->getFinalPrice())),
            'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($this->getProduct()->getPrice())),
            'productId'         => $this->getProduct()->getId(),
            'chooseText'        => Mage::helper('catalog')->__('Choose option...'),
            'taxConfig'         => $taxConfig,
        );

        return Zend_Json::encode($config);
    }

    /**
     * Validating of super product option value
     *
     * @param array $attributeId
     * @param array $value
     * @param array $options
     * @return boolean
     */
    protected function _validateAttributeValue($attributeId, &$value, &$options)
    {
        if(isset($options[$attributeId][$value['value_index']])) {
            return true;
        }

        return false;
    }

    /**
     * Validation of super product option
     *
     * @param array $info
     * @return boolean
     */
    protected function _validateAttributeInfo(&$info)
    {
        if(count($info['options']) > 0) {
            return true;
        }
        return false;
    }

    /**
     * Calculation real price
     *
     * @param float $price
     * @param bool $isPercent
     * @return mixed
     */
    protected function _preparePrice($price, $isPercent = false)
    {
        if ($isPercent && !empty($price)) {
            $price = $this->getProduct()->getFinalPrice() * $price / 100;
        }

        return $this->_registerJsPrice($this->_convertPrice($price, true));
    }

    /**
     * Calculation price before special price
     *
     * @param float $price
     * @param bool $isPercent
     * @return mixed
     */
    protected function _prepareOldPrice($price, $isPercent = false)
    {
        if ($isPercent && !empty($price)) {
            $price = $this->getProduct()->getPrice() * $price / 100;
        }

        return $this->_registerJsPrice($this->_convertPrice($price, true));
    }

    /**
     * Replace ',' on '.' for js
     *
     * @param float $price
     * @return string
     */
    protected function _registerJsPrice($price)
    {
        return str_replace(',', '.', $price);
    }

    /**
     * Convert price from default currency to current currency
     *
     * @param float $price
     * @param boolean $round
     * @return float
     */
    protected function _convertPrice($price, $round = false)
    {
        if (empty($price)) {
            return 0;
        }

        $price = $this->getCurrentStore()->convertPrice($price);
        if ($round) {
            $price = $this->getCurrentStore()->roundPrice($price);
        }

        return $price;
    }
}

0 comments: