Magento Use multiple attribute swatches on product listing page

by mahmoudismail   Last Updated June 20, 2017 10:09 AM

i've create custom module to use multiple attribute swatches on product listing page :

Step 1: Create a module : ConfigurableSwatches

Step 2: /app/code/local/CompanyName/ConfigurableSwatches/etc/config.xml

<?xml version="1.0" encoding="utf-8"?>
<config>
  <modules>
    <CompanyName_ConfigurableSwatches>
        <version>1.0.0</version>
    </CompanyName_ConfigurableSwatches>
  </modules>
  <!-- start of override Customer AccountController -->
  <helpers>
    <companyname_configurableswatches>
        <class>CompanyName_ConfigurableSwatches_Helper</class>
    </companyname_configurableswatches>
  </helpers>
  <models>
    <CompanyName_ConfigurableSwatches>
      <rewrite>
        <observer>CompanyName_ConfigurableSwatches_Model_Observer</observer>
      </rewrite>
    </CompanyName_ConfigurableSwatches>
  </models>
</config>

Step 3: /app/code/local/CompanyName/ConfigurableSwatches/etc/system.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
<sections>
    <configswatches translate="label" module="configurableswatches">
        <groups>
            <general translate="label" module="configurableswatches">
                <label>General Settings</label>
                <sort_order>10</sort_order>
                <show_in_default>1</show_in_default>
                <show_in_website>1</show_in_website>
                <show_in_store>1</show_in_store>
                <fields>
                    <product_list_attribute translate="label">
                        <label>Product Attribute to Use for Swatches in Product Listing</label>
                        <frontend_type>multiselect</frontend_type>
                        <source_model>configurableswatches/system_config_source_catalog_product_configattribute_select</source_model>
                        <sort_order>30</sort_order>
                        <show_in_default>1</show_in_default>
                        <show_in_website>1</show_in_website>
                        <show_in_store>1</show_in_store>
                    </product_list_attribute>
                </fields>
            </general>
        </groups>
    </configswatches>
</sections>
</config>

Step 4:/app/code/local/CompanyName/ConfigurableSwatches/Helper/Productlist.php

class CompanyName_ConfigurableSwatches_Helper_Productlist extends Mage_Helper_Productlist
{
  protected $_swatchAttributes;

  /**
   * Get ID of the attribute that should be used for swatches on product listing
   *
   * @return string
   */
  public function getSwatchAttributeIds()
  {
      if (is_null($this->_swatchAttributeIds)) {
          $this->_swatchAttributeIds =
              Mage::getStoreConfig(Mage_ConfigurableSwatches_Helper_Data::CONFIG_PATH_LIST_SWATCH_ATTRIBUTE);
      }
      return $this->_swatchAttributeIds;
  }

  /**
   * Get model of attribute that should be used for swatches on product listing
   */
  public function getSwatchAttributes()
  {
      $attributeIds = explode(',',$this->getSwatchAttributeIds());
      $attributeCode = array();
      foreach ( $attributeIds as $attributeId ) {
          $attributeCode[] = Mage::getModel('eav/entity_attribute')
              ->load($attributeId)->getAttributeCode();
      }
      return $attributeCode;
  }
}

Step 5:/app/code/local/CompanyName/ConfigurableSwatches/Helper/Mediafallback.php

class CompanyName_ConfigurableSwatches_Helper_Mediafallback extends Mage_Helper_Mediafallback
{
    /**
   * Set child_attribute_label_mapping on products with attribute label -> product mapping
   * Depends on following product data:
   * - product must have children products attached
   *
   * @param array $parentProducts
   * @param $storeId
   * @return void
   */
  public function attachConfigurableProductChildrenAttributeMapping(array $parentProducts, $storeId)
  {
      $listSwatchAttr = Mage::helper('CompanyName_ConfigurableSwatches/configurableSwatches_productlist')
          ->getSwatchAttributeIds();
      $listSwatchAttr = explode(',',$listSwatchAttr);

      $parentProductIds = array();
      /* @var $parentProduct Mage_Catalog_Model_Product */
      foreach ($parentProducts as $parentProduct) {
          $parentProductIds[] = $parentProduct->getId();
      }

      $configAttributes = Mage::getResourceModel('configurableswatches/catalog_product_attribute_super_collection')
                              ->addParentProductsFilter($parentProductIds)
                              ->attachEavAttributes()
                              ->setStoreId($storeId)
      ;

      $optionLabels = array();
      foreach ($configAttributes as $attribute) {
          $optionLabels += $attribute->getOptionLabels();
      }

      foreach ($parentProducts as $parentProduct) {
          $mapping = array();
          $listSwatchValues = array();

          /* @var $attribute Mage_Catalog_Model_Product_Type_Configurable_Attribute */
          foreach ($configAttributes as $attribute) {
              /* @var $childProduct Mage_Catalog_Model_Product */
              if (!is_array($parentProduct->getChildrenProducts())) {
                  continue;
              }

              foreach ($parentProduct->getChildrenProducts() as $childProduct) {
                  // product has no value for attribute, we can't process it
                  if (!$childProduct->hasData($attribute->getAttributeCode())) {
                      continue;
                  }
                  $optionId = $childProduct->getData($attribute->getAttributeCode());

                  // if we don't have a default label, skip it
                  if (!isset($optionLabels[$optionId][0])) {
                      continue;
                  }

                  // normalize to all lower case before we start using them
                  $optionLabels = array_map(function ($value) {
                      return array_map('Mage_ConfigurableSwatches_Helper_Data::normalizeKey', $value);
                  }, $optionLabels);

                  // using default value as key unless store-specific label is present
                  $optionLabel = $optionLabels[$optionId][0];
                  if (isset($optionLabels[$optionId][$storeId])) {
                      $optionLabel = $optionLabels[$optionId][$storeId];
                  }

                  // initialize arrays if not present
                  if (!isset($mapping[$optionLabel])) {
                      $mapping[$optionLabel] = array(
                          'product_ids' => array(),
                      );
                  }
                  $mapping[$optionLabel]['product_ids'][] = $childProduct->getId();
                  $mapping[$optionLabel]['label'] = $optionLabel;
                  $mapping[$optionLabel]['default_label'] = $optionLabels[$optionId][0];
                  $mapping[$optionLabel]['labels'] = $optionLabels[$optionId];
                  if (in_array($attribute->getAttributeId(),$listSwatchAttr)
                      && !in_array($mapping[$optionLabel]['label'], $listSwatchValues)
                  ) {
                      $listSwatchValues[$optionId] = $mapping[$optionLabel]['label'];
                  }
              } // end looping child products
          } // end looping attributes


          foreach ($mapping as $key => $value) {
              $mapping[$key]['product_ids'] = array_unique($mapping[$key]['product_ids']);
          }

          $parentProduct->setChildAttributeLabelMapping($mapping)
                        ->setListSwatchAttrValues($listSwatchValues);
      } // end looping parent products
  }

  /**
   * Determines which product attributes should be selected
   * when children products are attached to parent products
   *
   * @return array
   */
  protected function _getChildrenProductsAttributes()
  {
      $color_size_attribute = Mage::helper('CompanyName_ConfigurableSwatches/configurableSwatches_productlist')
          ->getSwatchAttributes();
      $default_attribute = array(
          'small_image',
          'image',
          'image_label',
          'small_image_label',
      );
      return array_merge($color_size_attribute,$default_attribute);
  }

  /**
   * Attaches children product to each product via
   * ->setChildrenProducts()
   *
   * @param array $products
   * @param int $storeId
   * @return void
   */
  public function attachChildrenProducts(array $products, $storeId)
  {
      $productIds = array();
      /* @var $product Mage_Catalog_Model_Product */
      foreach ($products as $product) {
          $productIds[] = $product->getId();
      }

      $collection = Mage::getResourceModel(
          'configurableswatches/catalog_product_type_configurable_product_collection');

      $collection->setFlag('product_children', true)
                 ->addStoreFilter($storeId)
                 ->addAttributeToSelect($this->_getChildrenProductsAttributes());
      $collection->addProductSetFilter($productIds);
      $collection->load();

      $mapping = array();
      /* @var $childProduct Mage_Catalog_Model_Product */
      foreach ($collection as $childProduct) {
          foreach ($childProduct->getParentIds() as $parentId) {
              if (!isset($mapping[$parentId])) {
                  $mapping[$parentId] = array();
              }
              $mapping[$parentId][] = $childProduct;
          }
      }

      foreach ($mapping as $parentId => $childrenProducts) {
          $products[$parentId]->setChildrenProducts($childrenProducts);
      }
  }
}

Step 6:/app/code/local/CompanyName/ConfigurableSwatches/Model/Observer.php

class CompanyName_ConfigurableSwatches_Model_Observer extends Mage_Model_Observer
{
  /**
   * Attach children products after product list load
   * Observes: catalog_block_product_list_collection
   *
   * @param Varien_Event_Observer $observer
   */
  public function productListCollectionLoadAfter(Varien_Event_Observer $observer)
  {
    if (!Mage::helper('configurableswatches')->isEnabled()) { // check if functionality disabled
        return; // exit without loading swatch functionality
    }

    /* @var $helper Mage_ConfigurableSwatches_Helper_Mediafallback */
    $helper = Mage::helper('CompanyName_ConfigurableSwatches/configurableSwatches_mediafallback');

    /* @var $collection Mage_Catalog_Model_Resource_Product_Collection */
    $collection = $observer->getCollection();

    if ($collection
        instanceof Mage_ConfigurableSwatches_Model_Resource_Catalog_Product_Type_Configurable_Product_Collection) {
        // avoid recursion
        return;
    }

    $products = $collection->getItems();

    $helper->attachChildrenProducts($products, $collection->getStoreId());

    $helper->attachConfigurableProductChildrenAttributeMapping($products, $collection->getStoreId());

    $helper->attachGallerySetToCollection($products, $collection->getStoreId());

    /* @var $product Mage_Catalog_Model_Product */
    foreach ($products as $product) {
        $helper->groupMediaGalleryImages($product);
        Mage::helper('configurableswatches/productimg')
            ->indexProductImages($product, $product->getListSwatchAttrValues());
    }
  }
}

Step 7:/app/etc/modules/CompanyName_ConfigurableSwatches.xml

<?xml version="1.0"?>
<config>
    <modules>
        <CompanyName_ConfigurableSwatches>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Catalog />
             </depends>
        </CompanyName_ConfigurableSwatches>
    </modules>
</config>

Finaly in System -> Configuration -> Catalog -> Configurable Swatches under General Setting Tab i've selected multiple attribute to use for swatches in product listing ( color and size ) . But when refreshing the page on FrontEnd the color and size not appear.

My Question : Any help please to solve my problem ?



Related Questions




Change More product images on color swatch select

Updated August 06, 2015 15:04 PM