Laurent Clouet's blog

Https + Magento Cache + Internet Explorer = No image

Magento uses by default an advanced cache system in order to display templates content faster. But default configuration of this cache can sometime creates some issues.

Recently, we had some images that were not displayed in the top menu when we switch from an http page to a https page using Internet Explorer browser. Images in this menu still have a non secured (http) URI. Internet Explorer is not pleased with such content. By default, this browser does not display unsecured content on a secured page. We have this security warning displayed when some image have http URI on a https page:

Internet Explorer Security Warning

Block displaying top menu was using cache system but this cache was not regenerated when we switch from a http to a https page. That's why images were still having http URI.

For fixing this problem, we must rewrite getCacheKey method from Mage_Catalog_Block_Navigation class. A new parameter telling if page use http or https should be included in cache key. Cache will then be different for this 2 types of pages. This parameter is added with getSkinUrl method

Default code of getCacheKey

public function getCacheKey()
{
    return 'CATALOG_NAVIGATION_' . Mage::app()->getStore()->getId()
        . '_' . Mage::getDesign()->getPackageName()
        . '_' . Mage::getDesign()->getTheme('template')
        . '_' . Mage::getSingleton('customer/session')->getCustomerGroupId()
        . '_' . md5($this->getTemplate() . $this->getCurrenCategoryKey());
}

is then replaced by following code

public function getCacheKey()
{
    return 'CATALOG_NAVIGATION_' . Mage::app()->getStore()->getId()
        . '_' . Mage::getDesign()->getPackageName()
        . '_' . Mage::getDesign()->getTheme('template')
        . '_' . Mage::getSingleton('customer/session')->getCustomerGroupId()
        . '_' . md5($this->getTemplate() . $this->getCurrenCategoryKey())
        . '_' . md5($this->getSkinUrl()); /*** FIX IN THIS LINE ***/
}

This is it. You can now use peacefully https on Internet Explorer.

For more details about Magento cache system you can read this article.

Bargento 4 announced

Bargento

Bargento 4 was announced. The event will take place Monday 22nd March Friday 28th March 2010 at Paris.

Program and Bargento place will be revealed soon.

Official announce in bargento.fr site (in french)

Magento orders: states and statuses

Magento orders have different states for following their process (billed, shipped, refunded...) in the order Workflow. These states are not visible in Magento back office. In fact, it is orders statuses that are displayed in back office and not their states.

Each state can have one or several statuses and a status can have only one state. By default, statuses and states have often the same name, that is why it is a little confusing. Here is the list of statuses and states available by default.

State code State name Status code Status name
new New pending Pending
pending_payment Pending Payment pending_paypal
pending_amazon_asp
Pending PayPal
Pending Amazon Simple Pay
processing Processing processing Processing
complete Complete complete Complete
closed Closed closed Closed
canceled Canceled canceled Canceled
holded On Hold holded On Hold

For adding new status to a state, you just need to declare it in config.xml file

<config>
    ...
    <global>
        <sales>
            <order>
                <!-- Statuses declaration -->
                <statuses>
                    <my_processing_status translate="label"><label>My Processing Status</label></my_processing_status>
                </statuses>
                <!-- Linking Status to a state -->
                <states>
                    <processing>
                        <statuses>
                            <my_processing_status />
                        </statuses>
                    </processing>
                </states>
            </order>
        </sales>  
    </global>
</config>

When we want to modify order status in some code, we have to be sure that current order state allows status wanted. It is possible to change both state and status with setState method

$order = Mage::getModel('sales/order')->loadByIncrementId('100000001');
$state = 'processing';
$status = 'my_processing_status';
$comment = 'Changing state to Processing and status to My Processing Status';
$isCustomerNotified = false;
$order->setState($state, $status, $comment, $isCustomerNotified);
$order->save();

$status can also take false value in order to only set order state, or true value for setting status by taking first status associated to this state.

You can now adjust as you wish your order workflow in Magento.

Magento 1.3.2.4 : Remember to update your Magento installation

Like all softwares, e-commerce solution Magento is not bug free. These bugs are quickly noticed and fixed by Varien.

Wednesday 23 Septembre, version 1.3.2.4 of Magento was released. It is strongly advised to update your Magento installation because this version fixes a possible XSS issue on customer registration page.

Here are different ways for updating Magento:

1. Update with diff file

For each new version, Magento provides a .diff file to download at this url: http://www.magentocommerce.com/download/diff. All that we must do then is download this file in our Magaento main directory and type command:

patch -p0 < 1.3.2.3-1.3.2.4.diff

2. Update with Magento Connect Manager

In admin part of your site, go to System > Magento Connect > Magento Connect Manager. Update then extension  Mage_Core_Modules. If this extension is not installed, key for installing it is  magento-core/Mage_Core_Modules.

More information:

Magento module: Create your own controller

Respect my authoritahMagento is based on MVC model. This model helps for defining models, view (layout + templates) and controllers. Despite big amount of modules available by default in Magento and on Magento Connect, you may want to create your own module and define your controller for you Magento website. No problem, this tutorial will explain you how to create your own controller and how to make it respect its authoritah to layouts and templates.

Purpose of this example controller will be to give result of two integers multiplication (very useful if you lost your calculator). Integers will be provided through a basic form. Result will be displayed in a Magento notification.

Before starting creation of your module, please turn off the cache management in order to see immediately every change.

Creating your module

Our extension will be named arithmetic. Folders needed for this extension are created.

$ mkdir -p app/code/local/Baobaz/Arithmetic/controllers
$ mkdir -p app/code/local/Baobaz/Arithmetic/etc

We create file app/code/local/Baobaz/Arithmetic/etc/config.xml, in order to register this extension

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <baobaz_arithmetic>
            <version>0.0.1</version>
        </baobaz_arithmetic>
    </modules>
</config>

And a file app/etc/modules/Baobaz_Arithmetic.xml for its activation:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Baobaz_Arithmetic>
            <active>true</active>
            <codePool>local</codePool>
        </Baobaz_Arithmetic>
    </modules>
</config>

For more informations about creation of a new extension, please check Wojtek's post "Developing module for Magento Tutorial - Where to Begin [Part 1]".

Creating a controller

You need now to create file app/code/local/Baobaz/Arithmetic/controllers/IntegerController.php and write method that will be used for multiplication.

Controller files must always follow pattern xxxxxController.php (xxxxx will be used after in url for calling this controller) and put in controllers folder.
Controllers methods names must follow pattern yyyyyAction (yyyyy will also be used in url for calling this controller). For the moment content of our file is:

class Baobaz_Arithmetic_IntegerController extends Mage_Core_Controller_Front_Action
{
    public function multiplyAction(){
    }
}

We need to indicate now that some controllers are available in Arithmetic modules. For doing that, we add the following content in app/code/local/Baobaz/Arithmetic/etc/config.xml file:

<config>
    ...
    <frontend>
        <routers>
            <arithmetic>
                <use>standard</use>
                <args>
                    <module>Baobaz_Arithmetic</module>
                    <frontName>arithmetic</frontName>
                </args>
            </arithmetic>
        </routers>  
    </frontend>
</config>

Let see how this router declaration works:

  • <frontend> indicates that router will be use in front part of website
  • <routers> is where you declare all your routers
  • <arithmetic> is identifier of this router
  • <use>standard</use> can take value standard (for front part) or admin (for admin part).
  • <module>Baobaz_Arithmetic</module> indicates which module contain controller that handles this router
  • <frontName>arithmetic</frontName> is router name that will be used in url

We can now modify multiplyAction method for making it displaying a message:

public function multiplyAction(){
    echo "Respect my authoritah";
}

When you call now url http://monsitemagento/arithmetic/integer/multiply message "Respect my authoritah" will be displayed. Let dissect this url:

  • arithmetic tells that controller is in Baobaz_Arithmetic module
  • integer tells that controllers/integerController.php file must be cehcked
  • multiply tells that multiplyAction method must be chosen in this file

Displaying a template

We define which layout file will be used in the module:

<config>
    ...
    <frontend>
        ...
        <layout>
            <updates>
                <arithmetic>
                    <file>arithmetic.xml</file>
                </arithmetic>
            </updates>
        </layout>
    </frontend>
</config>

We create app/design/frontend/default/default/layout/arithmetic.xml file in order to define which blocks will be used for controller that was just made.

<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
    <arithmetic_integer_multiply>
        <reference name="root">
            <action method="setTemplate">
                <template>page/1column.phtml</template>
            </action>
        </reference>
        <reference name="content">
            <block type="core/template" name="arithmetic_integer_multiply" template="arithmetic/integer/multiply.phtml"></block>
        </reference>
    </arithmetic_integer_multiply>
</layout>

Main template used by arithmetic/integer/multiply is page/1column.phtml. For "content" part of this template, only arithmetic_integer_multiply block will be displayed. This block does not need any particular management. It is then set with core/template type that is default type. Template file used will be arithmetic/integer/multiply.phtml.

Our template is defined, app/design/frontend/default/default/template/arithmetic/integer/multiply.phtml must then be created. This file will be empty for the moment..

For displaying correctly layout, it must be loaded in controller

public function multiplyAction(){
    $this->loadLayout();
    $this->renderLayout();
}

Interaction between template and controller

Our template will just have a basic form for providing integers to multiply

<form action="<?php echo Mage::getUrl('arithmetic/integer/multiply') ?>" method="post">
    <fieldset>
        <ul>
            <li>
                <label for="int1">Integer 1</label>
                <input type="text" id="int1" name="int1" />
            </li>
            <li>
                <label for="int2">Integer 2</label>
                <input type="text" id="int2" name="int2" />
            </li>
            <li><input type="submit" value="Multiply" /></li>
        </ul>
    </fieldset>
</form>

Action form url is again arithmetic/integer/multiply. Controller action must then be modified in order to manage data from form and to give result.

public function multiplyAction(){
    if ($this->getRequest()->isPost()){
        $int1 = $this->getRequest()->getPost('int1');
        $int2 = $this->getRequest()->getPost('int2');
        $result = $int1 * $int2;
    Mage::getSingleton('customer/session')->addSuccess("$int1 * $int2 = $result");
    }
    $this->loadLayout();
    $this->_initLayoutMessages('customer/session');
    $this->renderLayout();
}

In order to know if controller is called after using form, following instruction is used:

$this->getRequest()->isPost()

Result is put in 'customer/session' session. For being able to display this result in template, message template must be loaded in multiplyAction method:

$this->_initLayoutMessages('customer/session');

Add then in you template the following line where you want to display the result

echo $this->getMessagesBlock()->getGroupedHtml();

And here we are: we have now a new controller that displays result of a multiplication.

All files used in this tutorial are available in baobaz_arithmetic.tar.gz archive.

This post was inspired by Alan Storm's post Magento Front Controller. Take a look at his very interesting blog.

Magento SPPLUS Extension: bug for calculating HMAC key

SP PLUSMagento E-commerce solution allows you to integrate several payment platforms with Magento module system.

SPPLUS extension was created for using SP PLUS payment platform used in a French bank: "La Caisse d'Épargne". This extension is available in Magento Connect.

However, this extension has quite an annoying bug: orders with customer's email address containing '_' character are not dealt correctly. This bug is caused by a wrong way of calculating HMAC key.

For your information: HMAC key is an authentication code send by SP PLUS. nthmac function from spplus.so library (given by SP PLUS) must be used for calculating this key and then comparing it to the received key.  This calculation takes several parameters including customer's email address. However, to use the function correctly, special characters, like '_', must be replaced by their equivalent hexadecimal code.

To correct this bug, ipnPostSubmit method from app/code/community/Mage/Spplus/Model/Method/Spplus.php file must be modified. The following lines:

$chaineParam = str_replace(":", "&#x3A;", $chaineParam);
$chaineParam = str_replace("/", "&#x2F;", $chaineParam);
$chaineParam = str_replace("_", "&#x5F;", $chaineParam);
$chaineParam = str_replace("@", "&#x40;", $chaineParam);

must be exchanged by:

$chaineParam = str_replace(":", "%3A", $chaineParam);
$chaineParam = str_replace("/", "%2F", $chaineParam);
$chaineParam = str_replace("_", "%5F", $chaineParam);
$chaineParam = str_replace("@", "%40", $chaineParam);

This bug was reported on extension forum and should be fixed in version 1.1.5.