Add custom image field for custom options

We had a request from a client who wanted to display images for custom options. In this article, I’ll explain how to add the image field to the custom option in admin.

Create new module Inchoo_ProductCustomOptionsFile

app/etc/modules/Inchoo_ProductCustomOptionsFile.xml

  1. <?xml version="1.0"?>
    <config>
        <modules>
            <Inchoo_ProductCustomOptionsFile>
                <active>true</active>
                <codePool>local</codePool>
            </Inchoo_ProductCustomOptionsFile>
        </modules>
    </config>

Configuration file

To add your custom field it is necessary to rewrite class         Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Options_Type_Select and set your template. To fill custom option image filed with new image’s names it is necessary to rewrite the class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Options_Option.

/app/code/local/Inchoo/ProductCustomOptionsFile/etc/config.xml

<?xml version="1.0"?>
<config>
	<modules>
		<Inchoo_ProductCustomOptionsFile>
			<version>1.0.0</version>
		</Inchoo_ProductCustomOptionsFile>
	</modules>
	<global>
		<blocks>
			<adminhtml>
				<rewrite>
					<catalog_product_edit_tab_options_type_select>Inchoo_ProductCustomOptionsFile_Block_Adminhtml_Rewrite_Catalog_Product_Edit_Type_Select</catalog_product_edit_tab_options_type_select>
					<catalog_product_edit_tab_options_option>Inchoo_ProductCustomOptionsFile_Block_Adminhtml_Rewrite_Catalog_Product_Edit_Tab_Options_Option</catalog_product_edit_tab_options_option>
				</rewrite>
			</adminhtml>
			<inchoo_file>
				<class>Inchoo_ProductCustomOptionsFile_Block</class>
			</inchoo_file>
		</blocks>
		<resources>
			<inchoo_productcustomoptionsfile_setup>
				<setup>
					<module>Inchoo_ProductCustomOptionsFile</module>
				</setup>
			</inchoo_productcustomoptionsfile_setup>
		</resources>
	</global>
	<admin>
		<routers>
			<adminhtml>
				<args>
					<modules>
						<inchoo_product before="Mage_Adminhtml">Inchoo_ProductCustomOptionsFile_Adminhtml</inchoo_product>
					</modules>
				</args>
			</adminhtml>
		</routers>
	</admin>
</config>

 Blocks

/app/code/local/Inchoo/ProductCustomOptionsFile/Block/Adminhtml/Rewrite/Catalog/Product/Edit/Type/Select.php

We want to use our template instead default one for custom option.

<?php
class Inchoo_ProductCustomOptionsFile_Block_Adminhtml_Rewrite_Catalog_Product_Edit_Type_Select extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Options_Type_Select
{
	public function __construct()
	{
		parent::__construct();
		$this->setTemplate('catalog/product/edit/options/type/select-with-file.phtml');
		$this->setCanEditPrice(true);
		$this->setCanReadPrice(true);
	}
 
}

Create a template file and copy content of /app/design/adminhtml/default/default/template/catalog/product/edit/options/type/select.phtml into our new template file /app/design/adminhtml/default/default/template/catalog/product/edit/options/type/select-with-file.phtml

Add code between Inchoo into select-with-file.phtml template

<!---...-->
 
OptionTemplateSelect =
<!---...-->
        '<th class="type-sku"><?php echo Mage::helper('core')->jsQuoteEscape(Mage::helper('catalog')->__('SKU')) ?></th>'+
            // Inchoo
        '<th class="type-title"><?php echo Mage::helper('core')->jsQuoteEscape(Mage::helper('catalog')->__('Image Name')) ?></th>'+
        '<th class="type-title"><?php echo Mage::helper('core')->jsQuoteEscape(Mage::helper('catalog')->__('Upload New Image')) ?></th>'+
            // Inchoo
        '<th class="type-title"><?php echo Mage::helper('core')->jsQuoteEscape(Mage::helper('catalog')->__('Sort Order')) ?></th>'+
<!---...-->
 
OptionTemplateSelectRow =
<!---...-->
        '<td><input type="text" class="input-text" name="product[options][{{id}}][values][{{select_id}}][sku]" value="{{sku}}"></td>'+
            // Inchoo
        '<td><input type="text" class="select-type-image" id="product_option_{{id}}_select_{{select_id}}_image" name="product[options][{{id}}][values][{{select_id}}][image]" value="{{image}}">{{checkboxScopeTitle}}</td>'+
        '<td><input type="file" class="input-text select-type-image" id="image" name="{{id}}-{{select_id}}"></td>'+
            // Inchoo
        '<td><input type="text" class="validate-zero-or-greater input-text" name="product[options][{{id}}][values][{{select_id}}][sort_order]" value="{{sort_order}}"></td>'+
<!---...-->

To pass our new custom option value to template we need to rewrite Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Options_Option class. Create block /app/code/local/Inchoo/ProductCustomOptionsFile/Block/Adminhtml/Rewrite/Catalog/Product/Edit/Tab/Options/Option.php Add code between Inchoo comment. Function getOptionValues() returns all product custom options to javascript object which fills custom options fields.

class Inchoo_ProductCustomOptionsFile_Block_Adminhtml_Rewrite_Catalog_Product_Edit_Tab_Options_Option extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Options_Option
{
	public function getOptionValues()
	{
 
// ...
	$i = 0;
	$itemCount = 0;
	foreach ($option->getValues() as $_value) {
	/* @var $_value Mage_Catalog_Model_Product_Option_Value */
		$value['optionValues'][$i] = array(
		'item_count' => max($itemCount, $_value->getOptionTypeId()),
		'option_id' => $_value->getOptionId(),
		'option_type_id' => $_value->getOptionTypeId(),
		'title' => $this->escapeHtml($_value->getTitle()),
		'price' => ($showPrice)
		? $this->getPriceValue($_value->getPrice(), $_value->getPriceType()) : '',
		'price_type' => ($showPrice) ? $_value->getPriceType() : 0,
		'sku' => $this->escapeHtml($_value->getSku()),
		'sort_order' => $_value->getSortOrder(),
		// Inchoo
		'image' => $_value->getImage(),
		// Inchoo
		);
// ...

Now we have our custom fields Image Name and Upload New Images :

Saving images

To save images into database, we need to create setup script and rewrite Mage_Adminhtml_Catalog_ProductController. Then create setup script /app/code/local/Inchoo/ProductCustomOptionsFile/sql/inchoo_productcustomoptionsfile_setup/install-1.0.0.php

<?php
/* @var $installer Mage_Core_Model_Resource_Setup */
 
$installer = $this;
 
$installer->getConnection()
->addColumn($installer->getTable('catalog/product_option_type_value'), 'image', 'VARCHAR(255) NULL');
$installer->endSetup();

Rewrite class Mage_Adminhtml_Catalog_ProductController and add code between Inchoo to save images name into table catalog_product_option_type_value and upload images.

 

<?php
require_once(Mage::getModuleDir('controllers','Mage_Adminhtml').DS.'Catalog'.DS.'ProductController.php');
 
class Inchoo_ProductCustomOptionsFile_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Catalog_ProductController
{
	/**
	 * Initialize product before saving
	 */
	protected function _initProductSave()
	{
 
// ..
 
		$product->setCanSaveConfigurableAttributes(
			(bool) $this->getRequest()->getPost('affect_configurable_product_attributes')
			&& !$product->getConfigurableReadonly()
		);
// Inchoo
		$skuImageName=trim($product->getSku());
		$imagesFiles=$_FILES;
		$path = Mage::getBaseDir('media') . DS . 'catalog' . DS . 'customoption' .DS. 'images';
 
		foreach ($imagesFiles as $key=>$value)
		{
			$optionsValue = explode('-',$key);
			foreach ($value as $key2=>$value2)
			{
				if($key2=='name' && $value2!="") {
					try {
						$uploader = new Varien_File_Uploader($key);
						$uploader->setAllowedExtensions(array('jpg','jpeg','gif','png','svg'));
						$uploader->setAllowRenameFiles(false);
						$uploader->setFilesDispersion(false);
						$optionTitle = trim($productData['options'][$optionsValue[0]]['title']);
						$optionValueTitle = trim($productData['options'][$optionsValue[0]]['values'][$optionsValue[1]]['title']);
						$imageExtension = pathinfo($value2,PATHINFO_EXTENSION);
						$newImageName =$skuImageName.'_'.$optionTitle.'_'.$optionValueTitle.'.'.$imageExtension;
						$uploader->save($path, $newImageName);
						$productData['options'][$optionsValue[0]]['values'][$optionsValue[1]]['image']=$uploader->getUploadedFileName();
					} catch(Exception $e) {
						Mage::log('Unable to save custom option image. ' . $e->getMessage(), null, null, true);
					}
 
				}
			}
		}
// Inchoo

And that’s it. If you have any questions, feel free to post them in comments.