Question

During the course of work, I ran into some issues with the visibility attribute in Magento 1.8 and decided to write a test script. Unfortunately, the results have only made me MORE confused. Basically, I test having an installer script use addAttribute() and updateAttribute(), targeting the is_visible attribute.

Code:

<?php 
ini_set('include_path', ini_get('include_path').PATH_SEPARATOR.dirname(__FILE__).'/app'.PATH_SEPARATOR.dirname(__FILE__));
ini_set('include_path', ini_get('include_path').PATH_SEPARATOR.dirname(__FILE__).'/tests');
ini_set('memory_limit', '512M'); //so coverage generation don't barf
require_once 'Mage.php';         //so autoloading and all work...
//require_once 'tools.php';
Mage::app('default');            //create the app

function assertTrue($assertion)
{
    if ($assertion) {
        echo "Passed\n";
    } else {
        echo "Failed\n";
    }
    return $assertion;
}

// your own installer
$installer = Mage::getModel('eav/entity_setup', 'catalog_setup');

/*
    Test these cases:

    Models: customer/customer, catalog/product
    addAttribute(visible = true), addAttribute(visible = false)
    updateAttribute(is_visible = 1), updateAttribute(is_visible = 0)

 */

$customerResource = Mage::getModel('customer/customer')->getResource();
$productResource = Mage::getModel('catalog/product')->getResource();

$installer->removeAttribute('customer','test_attr_1');
$installer->removeAttribute('customer','test_attr_2');
$installer->removeAttribute('catalog_product','test_attr_1');
$installer->removeAttribute('catalog_product','test_attr_2');

echo "Customer addAttribute(visible=false)...";
$installer->addAttribute('customer', 'test_attr_1', array(
    'label'         => 'Test Attribute 1',
    'visible'       => false
));
assertTrue($customerResource->getAttribute('test_attr_1')->getIsVisible() == 0);

echo "Customer updateAttribute(visible=true)...";
$installer->updateAttribute('customer', 'test_attr_1', 'is_visible', 1);
assertTrue($customerResource->getAttribute('test_attr_1')->getIsVisible() == 1);


echo "Customer addAttribute(visible=true)...";
$installer->addAttribute('customer', 'test_attr_2', array(
    'label'         => 'Test Attribute 2',
    'visible'       => true
));
assertTrue($customerResource->getAttribute('test_attr_2')->getIsVisible() == 1);

echo "Customer updateAttribute(visible=false)...";
$installer->updateAttribute('customer', 'test_attr_2', 'is_visible', 0);
assertTrue($customerResource->getAttribute('test_attr_2')->getIsVisible() == 0);

echo "Product addAttribute(visible=false)...";
$installer->addAttribute('catalog_product', 'test_attr_1', array(
    'label'         => 'Test Attribute 1',
    'visible'       => false
));
assertTrue($productResource->getAttribute('test_attr_1')->getIsVisible() == 0);

echo "Product updateAttribute(visible=true)...";
$installer->updateAttribute('catalog_product', 'test_attr_1', 'is_visible', 1);
assertTrue($productResource->getAttribute('test_attr_1')->getIsVisible() == 1);


echo "Product addAttribute(visible=true)...";
$installer->addAttribute('catalog_product', 'test_attr_2', array(
    'label'         => 'Test Attribute 2',
    'visible'       => true
));
assertTrue($productResource->getAttribute('test_attr_2')->getIsVisible() == 1);

echo "Product updateAttribute(visible=false)...";
$installer->updateAttribute('catalog_product', 'test_attr_2', 'is_visible', 0);
assertTrue($productResource->getAttribute('test_attr_2')->getIsVisible() == 0);

die;
?>

Output:

Customer addAttribute(visible=false)...Failed
Customer updateAttribute(visible=true)...Passed
Customer addAttribute(visible=true)...Passed
Customer updateAttribute(visible=false)...Failed
Product addAttribute(visible=false)...Failed
Product updateAttribute(visible=true)...Passed
Product addAttribute(visible=true)...Passed
Product updateAttribute(visible=false)...Failed

To muddy the waters even more, when I check the catalog_eav_attribute table and customer_eav_attribute table, is_visible=0 for test_attr_2 (which is what is expected, but the script says otherwise).

Also:

  • When at the new customer page, is_visible = 1 and Test Attribute 1 does not display in the form
  • When at the new product page, is_visible = 1 and Test Attribute 1 does display in the form

Is there anyone that can make any sense of this behavior? Is my test wrong in any way?

Was it helpful?

Solution

Change:

$installer = Mage::getModel('eav/entity_setup', 'catalog_setup'); 

To:

$installer = Mage::getModel('catalog/resource_setup', 'core_setup');

Your problem is that you loaded the default EAV-setup model, since product attributes have different settings then other attributes, they override the _prepareValues() function in:

/app/code/core/Mage/Catalog/Model/Resource/Setup.php

protected function _prepareValues($attr)
{
    $data = parent::_prepareValues($attr);
    $data = array_merge($data, array(
        'frontend_input_renderer'       => $this->_getValue($attr, 'input_renderer'),
        'is_global'                     => $this->_getValue(
            $attr,
            'global',
            Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL
        ),
        'is_visible'                    => $this->_getValue($attr, 'visible', 1),
        'is_searchable'                 => $this->_getValue($attr, 'searchable', 0),
        'is_filterable'                 => $this->_getValue($attr, 'filterable', 0),
        'is_comparable'                 => $this->_getValue($attr, 'comparable', 0),
        'is_visible_on_front'           => $this->_getValue($attr, 'visible_on_front', 0),
        'is_wysiwyg_enabled'            => $this->_getValue($attr, 'wysiwyg_enabled', 0),
        'is_html_allowed_on_front'      => $this->_getValue($attr, 'is_html_allowed_on_front', 0),
        'is_visible_in_advanced_search' => $this->_getValue($attr, 'visible_in_advanced_search', 0),
        'is_filterable_in_search'       => $this->_getValue($attr, 'filterable_in_search', 0),
        'used_in_product_listing'       => $this->_getValue($attr, 'used_in_product_listing', 0),
        'used_for_sort_by'              => $this->_getValue($attr, 'used_for_sort_by', 0),
        'apply_to'                      => $this->_getValue($attr, 'apply_to'),
        'position'                      => $this->_getValue($attr, 'position', 0),
        'is_configurable'               => $this->_getValue($attr, 'is_configurable', 1),
        'is_used_for_promo_rules'       => $this->_getValue($attr, 'used_for_promo_rules', 0)
    ));
    return $data;
}

See difference from default _prepareValues() in:

/app/code/core/Mage/Eav/Model/Enitity/Setup.php

protected function _prepareValues($attr)
{
    $data = array(
        'backend_model'   => $this->_getValue($attr, 'backend'),
        'backend_type'    => $this->_getValue($attr, 'type', 'varchar'),
        'backend_table'   => $this->_getValue($attr, 'table'),
        'frontend_model'  => $this->_getValue($attr, 'frontend'),
        'frontend_input'  => $this->_getValue($attr, 'input', 'text'),
        'frontend_label'  => $this->_getValue($attr, 'label'),
        'frontend_class'  => $this->_getValue($attr, 'frontend_class'),
        'source_model'    => $this->_getValue($attr, 'source'),
        'is_required'     => $this->_getValue($attr, 'required', 1),
        'is_user_defined' => $this->_getValue($attr, 'user_defined', 0),
        'default_value'   => $this->_getValue($attr, 'default'),
        'is_unique'       => $this->_getValue($attr, 'unique', 0),
        'note'            => $this->_getValue($attr, 'note'),
        'is_global'       => $this->_getValue($attr, 'global', 1),
    );

    return $data;
}

OTHER TIPS

Did you have a look into getAttribute() ?

The attributes are cached inside of the Resource model, therefore you need to use all the time a new resource model, then your tests should pass.

public function getAttribute($attribute)
{
    if (is_numeric($attribute)) {
        $attributeId = $attribute;

        if (isset($this->_attributesById[$attributeId])) {
            return $this->_attributesById[$attributeId];
        }
        // ... 
    } else if (is_string($attribute)) {
        $attributeCode = $attribute;

        if (isset($this->_attributesByCode[$attributeCode])) {
            return $this->_attributesByCode[$attributeCode];
        }
        // ...         } else if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) {

        $attributeInstance = $attribute;
        $attributeCode = $attributeInstance->getAttributeCode();
        if (isset($this->_attributesByCode[$attributeCode])) {
            return $this->_attributesByCode[$attributeCode];
        }
    }
    // ... 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top