Tag Archives: PHP

Magento reindexer issue and very bad fix

On a big website, while Magento (this was a Professional 1.10.something) is reindexing (work done by a cron job) every page (viewed from the browser) seems to try to reindex the products it shows, that ends in a duplicate key error on an index temporary table (catalog_product_index_price_tmp), I needed a rough and quickfix I openedĀ app\code\core\Mage\Index\Model\Resource\Helper\Abstract.php and added a try/catch to theĀ insertFromSelect method, making it become:

public function insertFromSelect($select, $destTable, array $columns, $readToIndex = true)
    {
		try {
        if ($readToIndex) {
            $from   = $this->_getWriteAdapter();
            $to     = $this->_getIndexAdapter();
        } else {
            $from   = $this->_getIndexAdapter();
            $to     = $this->_getWriteAdapter();
        }

        if ($this->useDisableKeys()) {
            $to->disableTableKeys($destTable);
        }
        if ($from === $to) {
            $query = $select->insertFromSelect($destTable, $columns);
            $to->query($query);
        } else {
            $stmt = $from->query($select);
            $data = array();
            $counter = 0;
            while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
                $data[] = $row;
                $counter++;
                if ($counter>2000) {
                    $to->insertArray($destTable, $columns, $data);
                    $data = array();
                    $counter = 0;
                }
            }
            if (!empty($data)) {
                $to->insertArray($destTable, $columns, $data);
            }
        }
        if ($this->useDisableKeys()) {
            $to->enableTableKeys($destTable);
        }
		} catch (Exception $e) {}
        return $this;
    }

It is bad but now it’s working, oh god.

Programmatically delete all Magento attribute sets

You’re developing a Magento importer and you want to clean your DB after some tests? Here you have:

require_once dirname(__FILE__) . '/app/Mage.php';
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));

$resource = Mage::getSingleton('core/resource');
$db_read = $resource->getConnection('core_read');

$attribute_sets = $db_read->fetchCol("SELECT attribute_set_id FROM " . $resource->getTableName("eav_attribute_set") . " WHERE attribute_set_id<> 4 AND entity_type_id=4");
foreach ($attribute_sets as $attribute_set_id) {
	try {
		Mage::getModel("eav/entity_attribute_set")->load($attribute_set_id)->delete();
	} catch (Exception $e) {
		echo $e->getMessage() . "\n";
	}
}

Note that only products’ attribute sets are deleted, those are often generated automatically during imports.

Programmatically delete all Magento categories

You’re developing a Magento importer and you want to clean your DB after some tests? Here you have:

require_once dirname(__FILE__) . '/app/Mage.php';
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));

$resource = Mage::getSingleton('core/resource');
$db_read = $resource->getConnection('core_read');

$categories = $db_read->fetchCol("SELECT entity_id FROM " . $resource->getTableName("catalog_category_entity") . " WHERE entity_id>1 ORDER BY entity_id DESC");
foreach ($categories as $category_id) {
	try {
		Mage::getModel("catalog/category")->load($category_id)->delete();
	} catch (Exception $e) {
		echo $e->getMessage() . "\n";
	}
}

Create a custom category attribute in Magento

I’ve run into a few posts about this thing but none of them was working out of the box so I took all the info and glued them together so…

if you’ve to create a custom attribute for a Magento category but you don’t have a module (and its installer script) simply create a php file in the project’s root with this code:

require_once('app/Mage.php');
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$installer = new Mage_Sales_Model_Mysql4_Setup;
$attribute  = array(
	'type' => 'int',
	'label'=> 'Your attribute label',
	'input' => 'text',
	'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
	'visible' => true,
	'required' => false,
	'user_defined' => true,
	'default' => "",
	'group' => "General Information"
);
$installer->addAttribute('catalog_category', 'your_attribute_code', $attribute);
$installer->endSetup();

This attribute is a “text”, more info may come in comments if you need.

Magento Professional customer’s password hashing

So you want to import customer accounts but you’ve to generate the password hash? here you’ve the algorithm used by Magento Professional (which is different from Magento Community, but you can easily find that one in the net):

$passhash = hash("sha256", $salt . $password) . ":$salt";

By the way, for the community it’s

$passhash = md5($salt . $password) . ":$salt";

Create a custom order attribute in Magento

I’ve run into a few posts about this thing but none of them was working out of the box so I took all the info and glued them together so…

if you’ve to create a custom attribute for a Magento order but you don’t have a module (and its installer script) simply create a php file in the project’s root with this code:

require_once('app/Mage.php');
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$installer = new Mage_Sales_Model_Mysql4_Setup;
$attribute  = array(
        'type'          => 'text',
        'backend_type'  => 'text',
        'frontend_input' => 'text',
        'is_user_defined' => true,
        'label'         => 'Your attribute label',
        'visible'       => true,
        'required'      => false,
        'user_defined'  => false,   
        'searchable'    => false,
        'filterable'    => false,
        'comparable'    => false,
        'default'       => ''
);
$installer->addAttribute('order', 'your_attribute_code', $attribute);
$installer->endSetup();

This attribute is a “text” and it’s made not to be visible but just to use it as a container for some data you may need in your custom development, more info may come in comments if you need.

P4A 3.8.4 is out!

Another maintenance release for our beloved project, here you’ve the changelog:

– “meta viewport” tag was added to mask’s HTML for a better mobile rendering
– P4A::getMetaViewport() and setMetaViewport() methods were added
– p4a_center_elements() javascript funcion now removes marginLeft/paddingLeft
from the first visible column of the first P4A_Frame widget
– a bug with P4A_Frame and multiple CSS classes was solved
– P4A_Table’s arrow symbols were because the past ones weren’t shown on mobile
devices
– an ob_clean() call was added to P4A_Thumbnail_Generator::outputThumbnail()
method
– Zend Framework was updated to 1.11.10
– P4A_Table’s image cols do not throw exception anymore if the image
does not exist
– P4A_Field_loadSelectByArray helper now supports a second parameter to specify
the array’s primary key field name

Download P4A 3.8.4

P4A 3.8.3 is out!

A few improvements on different areas, here you’ve the changelog:

– P4A_DB_Navigator now supports query defined sources
– a bug with P4A_Data_Source::saveUploads() was solved
– a bug with P4A_Table’s image cols (without GD installed) was solved
– P4A_DB_Navigator now triggers a beforeclick event
– all p4a_load_js calls were migrated to require.js
– a bug with P4A_DB_Source::deleteRow() called when in newRow state was solved
– p4a_ajax_enable javascript function was added
– a bug with P4A_GD constant default definition was solved
– P4A_Mask::restart() method was added
– Zend Framework was updated to 1.11.7
– translations were updated
– P4A_DB_Source::load() method now checks for duplicate calls and throws an error

Download P4A 3.8.3

P4A 3.8.2 is out!

This is a minor release but it contains really a lot of great upgrades and fixes, here you’ve the changelog:

– Zend Framework was updated to 1.11.6
– CKEditor was updated to 3.6.0
– jQuery UI was updated to 1.8.11
– requirejs was added
– P4A_Dir_Source automatically sorts files
– P4A_Dir_Source::setPageLimit() calling was disabled
– P4A_Dir_Source’s page limit is now set to 0 (disabled)
– autocomplete values are now sorted and unique
– P4A_Field::getSource() method was added
– p4a_load_js now uses requirejs
– P4A_Field and P4A_Data_Fields now support the “datetime” type
– P4A_Field and P4A_Data_Fields now support the “time” type
– P4A_Object::dropImplement() now turns the action to lowercase
– deprecated method P4A_Object::dropMethod() was removed
– a javascript bug with P4A_DB_Navigator’s drag&drop functionalities was solved
– P4A_DB_Navigator now correctly supports source with non-default DSN

Download P4A 3.8.2