<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title><![CDATA[Blog]]></title>
    <link>http://turnkeye.com/blog/</link>
    <description><![CDATA[Blog]]></description>
    <pubDate>Thu, 23 May 2013 14:55:10 +0000</pubDate>
    <generator>Zend_Feed</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title><![CDATA[Images re-size in Magento]]></title>
      <link>http://turnkeye.com/blog/images-resize-in-magento/</link>
      <description><![CDATA[<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/banners/resize_wide.jpg"/></p>

<h3>In this article I will show how to use re-size parameters of default Magento images re-size feature.</h3>

<p>By default the re-size of the product images working in the following way:</p>

<pre class="brush:php">
&lt;?php echo $this->helper('catalog/image')
            ->init($_product, 'small_image')->resize(135); ?>
</pre>

<p>The code generate the 135х135px image.

There are a number of additional parameters that control the image output, here is a list of these parameters with default values:
</p>

<pre class="brush:php">
&lt;?php
    echo  $this->helper('catalog/image')->init($_product, 'small_image')
            ->constrainOnly(false)
            ->keepAspectRatio(true)
            ->keepFrame(true)
            ->keepTransparency(true)
            ->backgroundColor(array(255,255,255))
            ->resize(135, 135);
?>
</pre>

<h2>1 - "Small image" parameter.</h2>
<p>
There are three types of product images in Magento:
<ul>
<li>Thumbnail</li>
<li>Small Image</li>
<li>Base Image</li>
</ul>
Each type have its own image, it allows to load different images for small thumbnail or for big image.
</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/images_types_magento.jpg"/></p>

<h2>2 - "constrainOnly" parameter.</h2>
<p>If the "constrainOnly" parameter is set to true, in this case the images which are smaller than specified value will be not enlarged by Magento.
Only border of such images will increase. This is useful if you have small product images and you don't like when Magento pixelate them.
This option will not effect images which are bigger than specified value.
Example:</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/constrainOnly.jpg"/></p>

<h2>3 - "keepAspectRatio" parameter.</h2>
<p>If the "keepAspectRatio" parameter is set to true, in this case the proportions of the image will not be modified.
Example:</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/keepAspectRatio.jpg"/></p>

<h2>4 - "keepFrame" parameter.</h2>
<p>The "keepFrame" parameter guarantees that the image will be not cropped. When "keepAspectRatio" is false the "keepFrame" will not work.
Example:</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/keepFrame.jpg"/></p>

<h2>5 - "keepTransparency" parameter.</h2>
<p>The "keepTransparency" parameter keep the transparent background of the images. If the "keepTransparency" parameter is set to false, in this case such images will have white background (by default). 
You can set any color for the background using the backgroundColor parameter.
Example:</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/keepTransparency.jpg"/></p>

<h2>6 - "backgroundColor" parameter.</h2>
<p>The "backgroundColor" allows to set any color as image background. You can enter a color as a RGB code, example: backgroundColor(array(255,255,255)).
If the "keepTransparency" parameter is set to true, in this case the background will be not applied to the images with transparency. 
Example:</p>
<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/backgroundColor.jpg"/></p>

<h2>7 - "resize" parameter.</h2>
<p>Using the "resize" parameter you can set a fixed width and height size for the image.
If only one size value is entered and "keepFrame" parameter is set to true, in this case the image height will be equal to the image width.</p>

<h2>Examples of the parameters.</h2>

<p>
1) Fixed height, the width will be calculated automatically:

<pre class="brush:php">
    ->constrainOnly(true)
    ->keepAspectRatio(true)
    ->keepFrame(false)
    ->resize(null, 135);
</pre>

Please note that the "keepFrame" parameter is set to false, otherwise all images will be 135х135px.
</p>

<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/example1.jpg"/></p>

</p>
2) Fixed width, the height will be calculated automatically:

<pre class="brush:php">
    ->constrainOnly(true)
    ->keepAspectRatio(true)
    ->keepFrame(false)
    ->resize(135, null);
</pre>
</p>

<p><img title="Images re-size in Magento" src="http://turnkeye.com/media/wysiwyg/blog/2013/05/example2.jpg"/></p>

<h2>Other useful methods.</h2>

</p>
The following methods also could be useful:

<pre class="brush:php">
&lt;?php
    echo $this->helper('catalog/image')
        ->init($_product, 'small_image')->getOriginalWidth();
    echo $this->helper('catalog/image')
        ->init($_product, 'small_image')->getOriginalHeight();
?>
</pre>

You can get the width and height of the original image, in case if you will need to do some extra calculations or re-size the image in some different way.
</p>]]></description>
      <pubDate>Fri, 17 May 2013 08:48:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento Tips: Manual activation of the Magento mobile theme]]></title>
      <link>http://turnkeye.com/blog/mobile_theme_switcher/</link>
      <description><![CDATA[<p><img src="http://turnkeye.com/media/wysiwyg/blog/banners/magento_mobile_wide.jpg" alt="Manual activation of the Magento mobile theme"/></p>

<p>By default switching to magento mobile theme being happened automatically basing on customer user agent (i.e. browser). You can find the details about this in my <a href="http://turnkeye.com/blog/magento-mobile-theme-faq/" target="_blank">previous article</a>.</p>

<p>However, in case if you would like to test your mobile theme before publishing, this approach will not work because theme will be visible for all customers with mobile devices. In this article I will describe how to make mobile theme available for testing only for you using special link, for example:</p>

<p><i>yourstore.com?use_mobile_theme=1</i></p>

<p><strong>Important:</strong> we assume that your mobile theme is located in the same package as the desktop theme, and the name of the theme is "mobile".</p>

<p>First of all, you need to create a new custom module, lets call it Turnkeye_Switcher, there are a lot of tutorials how to create a custom module, so lets describe only module functionality itself.</p>

<p><strong>Step 1. We need to create a module config.</strong></p>

<p>File: app/code/community/Turnkeye/Switcher/etc/config.xml</p>

<pre class="brush:xml">
&lt; ?xml version="1.0"?>
&lt;config>
    &lt;modules>
        &lt;Turnkeye_Switcher>
            &lt;version>0.0.1&lt;/version>
        &lt;/Turnkeye_Switcher>
    &lt;/modules>
    &lt;global>
        &lt;models>
            &lt;core>
                &lt;rewrite>
                    &lt;design_package>Turnkeye_Switcher_RW_Core_Model_Design_Package&lt;/design_package>
                &lt;/rewrite>
            &lt;/core>
        &lt;/models>
    &lt;/global>
&lt;/config>
</pre>

<p><strong>Step 2. As you see above we rewrite a model responsible for theming, now lets create this class.</strong></p>

<p>File: app/code/community/Turnkeye/Switcher/RW/Core/Model/Design/Package.php</p>

<pre class="brush:php">
&lt; ?php

class Turnkeye_Switcher_RW_Core_Model_Design_Package extends Mage_Core_Model_Design_Package
{

    protected function _checkUserAgentAgainstRegexps($regexpsConfigPath)
    {
        /**
         * @var $cookie Mage_Core_Model_Cookie
         */
        $cookie = Mage::getSingleton('core/cookie');
        if (Mage::app()->getRequest()) {
            $use_mobile = Mage::app()->getRequest()->getParam('use_mobile_version', null);
            if (!is_null($use_mobile)) {
                $cookie->set('use_mobile_version', $use_mobile, true);
                if (!$use_mobile) {
                    return false;
                }

                return 'mobile';
            }

            if (!$cookie->get('use_mobile_version')) {
                return false;
            }

            return mage::getStoreConfig('design/mobile/theme');
        }

        return parent::_checkUserAgentAgainstRegexps($regexpsConfigPath);
    }

    /**
     * check is it mobile
     *
     * @param $regexpsConfigPath
     * @return mixed
     */

    public function checkUserAgentAgainstRegexps()
    {
        if (Mage::app()->getRequest()) {
            $use_mobile = Mage::app()->getRequest()->getParam('use_mobile_version', null);
            if (!is_null($use_mobile)) {
                return (bool)$use_mobile;
            }
        }

        $cookie = Mage::getSingleton('core/cookie');
        if ($cookie->get('use_mobile_version')) {
            return true;
        }

        return false;
    }

}
</pre>

<p>That is all, after that you can see your mobile theme using this link:<br/>
<i>http://yourstore.com?use_mobile_theme=1</i></p>

<p>And vise versa, the mobile theme view can be disabled using this command:<br/>
<i>http://yourstore.com?use_mobile_theme=1</i></p>

<p><strong>Important:</strong> As you see we rewrite a core class, it is not very good. I recommend to remove the module after the mobile theme testing.</p>]]></description>
      <pubDate>Wed, 01 May 2013 12:08:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Showcase: Magento Upgrades 2013]]></title>
      <link>http://turnkeye.com/blog/magento-upgrade-showcase-2013/</link>
      <description><![CDATA[<p><img alt="Showcase: Magento Upgrades 2013" src="http://turnkeye.com/media/wysiwyg/blog/banners/magento_upgrade_wide.jpg"/></p>

<h3>Here we will share some examples of the stores that were successfully upgraded recently by our team of certified Magento developers.</h3>
<p>We offer <a target="_blank" href="http://turnkeye.com/services/magento_upgrade.html">quality upgrade services</a> and here you can find real and live examples of Magento 1.3, 1.4, 1.5, 1.6 and Magento Professional stores which were upgraded to the latest stable Magento versions without any loss in sales and customer data.</p>
<p>Of course you can upgrade the store yourself, and we even wrote a <a href="http://turnkeye.com/blog/magento-upgrade-guide/" target="_blank">detailed step-by-step instruction</a> with explanations of each step for developers (it was even featured in <a target="_blank" href="http://www.magentocommerce.com/ecommerce-resource-library/">Magento Ecommerce Library</a>), however I think you will agree that it is better to hire professional certified Magento developer for such complex projects. Especially when you upgrade from old Magento version, Magento Professional or Enterprise platform or Magento Community with custom code.</p>
<p>Only professional developers can implement the upgrade according to best standards and with minimal downtime.</p>
<p>Here are several stores that we upgraded recently:</p>

<p>
<h2>Upgrade from Magento Professional to Magento Community.</h2>
<p>Just Kid Costumes offers the largest selection of kids costumes online at great prices.</p>
<p><a target="_blank" href="http://justkidcostumes.com/">
<img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/1justkidcostumes.jpg" alt="Upgrade from Magento Professional to Magento Community" title="Upgrade from Magento Professional to Magento Community"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.3.</h2>
<p>Boutique 1 is the ultimate luxury fashion destination online, housing some of the world's most coveted designers from around the globe.</p>
<p><a target="_blank" href="http://boutique1.com/"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/2boutique1.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>ATZEN starts with the premise that everyone deserves to have healthy skin. Our products are sold around the world. In the U.S., they are available at spas, medical spas, resorts, and online.</p>
<p><a target="_blank" href="http://www.atzen.com/"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/3atzen.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>Pool Spa Supplies has been a leader in the pool and spa parts industry for more than 30 years. Seven dedicated technicians with expertise in everything from pools and spas to baths and steam units, mean that there's not much we haven't worked on, and not many parts we haven't seen.</p>
<p>Our prices are unbeatable. Our selection is unmatched, and with distribution centers in Texas, California, Arizona, Nevada, Florida and Canada, our shipping is super-fast.</p>
<p><a target="_blank" href="http://pool-spa-supplies.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/4pss.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.5.</h2>
<p>Professional photographic equipment and camera accessories.</p>
<p><a target="_blank" href="http://studiostoreix.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/5studiostoreix.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.6.</h2>
<p>Financial, Graphing & Scientific Calculators store in Germany.</p>
<p><a target="_blank" href="http://calcuso.de"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/6calcuso.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>Bosch® Aerotwin car accessories.</p>
<p><a target="_blank" href="http://nieuweruitenwissers.nl"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/7nieuweruitenwissers.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.3.</h2>
<p>Edgemaster, which was founded by Jay Schreur in 2000, is dedicated to helping stylists and barbers avoid competitive motion injuries by teaching them how to match their hands to ergonomically-correct tools.</p>
<p><a target="_blank" href="http://edge-master.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/8edgemaster.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>CobraCraneUSA is a leading Camera Crane manufacturer with great design features and proven quality at a fair price.</p>
<p><a target="_blank" href="http://cobracraneusa.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/9cobracraneusa.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>The US number 1 electronic cigarettes online shop.</p>
<p><a target="_blank" href="http://altsmoke.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/11altsmoke.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>Germany and Switzerland Micro Scooter stores: Scootergarage.de, Scootergarage.ch</p>
<p><a target="_blank" href="http://scootergarage.de"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/10scootergarage.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.3.</h2>
<p>cu·te·ta·pe is a cute and fun stationery arts and craft space featuring the best selection of Japanese Washi Masking Tape, Korean + Japanese Stationery items and some must have crafty cuteness such as wooden stamp sets etc - just browse around and have fun!</p>
<p><a target="_blank" href="http://cutetape.com"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/12cutetape.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p>
<h2>Upgrade from Magento Community 1.4.</h2>
<p>Intimate Couture brings you the world’s finest couture lingerie. It is our pleasure to offer you exceptional quality pieces from leading Australian and International designers, some of whom we have exclusivity. We have travelled to all corners of the globe to find the most elegant and fashionable lingerie, loungewear, sleepwear and swimwear.</p>
<p><a target="_blank" href="http://intimatecouture.com.au"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/04/13intimatecouture.jpg" alt="Magento Upgrade" title="Magento Upgrade"/></a></p>
</p>

<p><strong>Further reading</strong></p>
<ul>
<li><a href="http://turnkeye.com/blog/magento-upgrade-showcase/" target="_blank">Showcase: Magento Upgrades 2012</a></li>
<li><a href="http://turnkeye.com/blog/magento-upgrade-guide/" target="_blank">Magento upgrade guide: Magento 1.3.x, 1.4.x, 1.5.x, 1.6.x and 1.7.x upgrade process.</a></li>
</ul>]]></description>
      <pubDate>Fri, 26 Apr 2013 09:51:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Multi-store capabilities for Magento newsletter]]></title>
      <link>http://turnkeye.com/blog/multi-store-magento-newsletter/</link>
      <description><![CDATA[<p><img alt="Multi-store capabilities for Magento newsletter" src="http://turnkeye.com/media/wysiwyg/blog/banners/multi_store_wide.jpg"/></p>

<h3>If you use Magento multi-store feature, you possibly know that visitors of the store cannot sign up for newsletters of all multi-stores. Store visitor will be able to sign up only for one store.</h3>

<p>Lets imagine that you have two multi-stores: one for Gifts and other for Chocolate. If some of your visitor will open Gifts store and sign up for Gifts newsletter, Magento will record it. However if the same visitor will come to Chocolate store the other day and submit his email in newsletter box, in this case Magento will remove his email from Gifts newsletter and add him to Chocolate newsletter. By default it is not possible to sign up for News of both stores.</p>
<p><img title="Multi-store capabilities for Magento newsletter" src="http://turnkeye.com/media/wysiwyg/blog/2013/04/multi-store-newsletter.jpg"/></p>
<p>In this article we will show how to overcome this limitation and allow your visitors to sign up for multi-store newsletters.</p>

<h2>Creation of multi-store newsletter module for Magento</h2>

<p>To achieve our goal, we need to create a new module.</p>

<p><strong>1 - Lets create new directory for our future module, e.g.:</strong></p>
<pre class="brush:xml">
app/code/community/Turnkeye/Newsletter
</pre>

<p>Also we will need to create configuration file that will override newsletter/subscriber resource model. Here is the content of the config.xml:</p>

<pre class="brush:xml">
&lt; ?xml version="1.0"?>
&lt;!--File: app/code/community/Turnkeye/Newsletter/etc/config.xml -->
&lt;config>
    &lt;modules>
        &lt;Turnkeye_Newsletter>
            &lt;version>0.0.1&lt;/version>
        &lt;/Turnkeye_Newsletter>
    &lt;/modules>
    &lt;global>
        &lt;models>
            &lt;newsletter_mysql4> &lt;!-- We use newsletter_mysql4 for compatibility -->
                &lt;rewrite>
                    &lt;subscriber>Turnkeye_Newsletter_RW_Newsletter_Model_Resource_Subscriber&lt;/subscriber>
                &lt;/rewrite>
            &lt;/newsletter_mysql4>
        &lt;/models>
    &lt;/global>
&lt;/config>
</pre>

<p><strong>2 - Next we need to create new class: Turnkeye_Newsletter_RW_Newsletter_Model_Resource_Subscriber.</strong></p>

<pre class="brush:php">
&lt; ?php // File: app/code/community/Turnkeye/Newsletter/RW/Newsletter/Model/Resource/Subscriber.php
 /**
 * RW Resource Model
 *
 * @category   Turnkeye
 * @package    Turnkeye_Newsletter
 * @author     Kalashnikov Evgeniy
 */
class Turnkeye_Newsletter_RW_Newsletter_Model_Resource_Subscriber extends Mage_Newsletter_Model_Mysql4_Subscriber
{
    /**
     * Load subscriber from DB by email
     *
     * @param string $subscriberEmail
     * @return array
     */
    public function loadByEmail($subscriberEmail)
    {
        /** @var $customerSession Mage_Customer_Model_Session */
        $customerSession = Mage::getSingleton('customer/session');
        $ownerId = Mage::getModel('customer/customer')
            ->setWebsiteId(Mage::app()->getStore()->getWebsiteId())
            ->loadByEmail($subscriberEmail)
            ->getId();

        $storeId = $customerSession->isLoggedIn() && $ownerId == $customerSession->getId()
            ? $customerSession->getCustomer()->getStoreId()
            : Mage::app()->getStore()->getId();

        $select = $this->_read->select()
            ->from($this->getMainTable())
            ->where('subscriber_email=:subscriber_email')
            ->where('store_id=:store_id'); // Add store ID for newsletters

        $result = $this->_read->fetchRow($select, array(
            'subscriber_email'  => $subscriberEmail,
            'store_id'          => $storeId
        ));

        if (!$result) {
            return array();
        }

        return $result;
    }

    /**
     * Load subscriber by customer
     *
     * @param Mage_Customer_Model_Customer $customer
     * @return array
     */
    public function loadByCustomer(Mage_Customer_Model_Customer $customer)
    {
        $select = $this->_read->select()
            ->from($this->getMainTable())
            ->where('customer_id=:customer_id')
            ->where('store_id=:store_id');

        $result = $this->_read->fetchRow($select, array(
            'customer_id'   => $customer->getId(),
            'store_id'      => $customer->getStoreId()
        ));

        if ($result) {
            return $result;
        }

        $select = $this->_read->select()
            ->from($this->getMainTable())
            ->where('subscriber_email=:subscriber_email')
            ->where('store_id=:store_id');

        $result = $this->_read->fetchRow($select, array(
            'subscriber_email'  => $customer->getEmail(),
            'store_id'          => $customer->getStoreId()
        ));

        if ($result) {
            return $result;
        }

        return array();
    }
}
</pre>

<p><strong>3 - The module is almost ready. The last step is to activate it.</strong></p>

<p>Create new file app/etc/modules/Turnkeye_Newsletter.xml</p>

<pre class="brush:xml">
&lt; ?xml version="1.0"?>
&lt;!-- File: app/etc/modules/Turnkeye_Newsletter.xml -->
&lt;config>
    &lt;modules>
        &lt;Turnkeye_Newsletter>
            &lt;active>true&lt;/active>
            &lt;codePool>community&lt;/codePool>
            &lt;depends>
                &lt;Mage_Newsletter />
            &lt;/depends>
        &lt;/Turnkeye_Newsletter>
    &lt;/modules>
&lt;/config>
</pre>

<p>As usual, don't forget to reset compiler cache and Magento cache. Otherwise you will don't see the module ;)</p>]]></description>
      <pubDate>Wed, 17 Apr 2013 09:31:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento upgrade guide: Magento 1.3.x, 1.4.x, 1.5.x, 1.6.x and 1.7.x upgrade process.]]></title>
      <link>http://turnkeye.com/blog/magento-upgrade-guide/</link>
      <description><![CDATA[<p><img alt="Magento upgrade" src="http://turnkeye.com/media/wysiwyg/blog/banners/magento_upgrade_wide.jpg"/></p>

<h3>This is the most comprehensive description of the Magento 1.3.x, 1.4.x, 1.5.x, 1.6.x and 1.7.x upgrade process.</h3>
<p>Additionally It contains step-by-step instructions and troubleshooting information.</p>

<h2>Prepare for Magento upgrade (this part of the article is for old 1.3.x, 1.4.x versions only)</h2>

<p>Lets imaging that you have old Magento 1.3.x - 1.4.x store and you need to upgrade it to latest Magento 1.7.x version. First of all it is highly recommended to backup your live store files/database and <a href="http://turnkeye.com/blog/disable-magento-compiler/">disable Magento compiler cache</a>.</p>

<p>Next you need to get SSH access from your hosting provider and connect to your server via SSH protocol (using Linux command shell or <a href="http://www.putty.org">Putty</a> SSH client for Windows). </p>

<p>After connection via SSH, go to your store folder and execute these commands:</p>

<p>1 - Change permissions on <em>lib/pear</em> folder to writable (recursively):</p>

<pre class="brush:xml">chmod -R 777 lib/PEAR</pre>

<p>2 - Execute this command to prepare Magento for upgrade:</p>

<pre class="brush:xml">./pear mage-setup</pre>

<p>Most likely you will see this result after command execution:</p>

<pre class="brush:xml">
Channel "connect.magentocommerce.com/core" is already initialized
</pre>

<h2>Upgrade from Magento 1.3.x, old 1.4.x to Magento 1.4.2.0</h2>

<p>Upgrade to 1.4.2.0 is required, even if you upgrade your old Magento 1.3.x store to 1.7.x version.</p>
<p>1 - Execute Magento upgrade command:</p>

<pre class="brush:xml">./pear upgrade -f magento-core/Mage_All_Latest-stable</pre>
<p>Output of the command will show you what core packages were upgraded:</p>

<pre class="brush:xml">
...
upgrade ok: channel://connect.magentocommerce.com/core/Mage_Centinel-1.4.2.0
upgrade ok: channel://connect.magentocommerce.com/core/Interface_Frontend_Base_Default-1.4.2.0
upgrade ok: channel://connect.magentocommerce.com/core/Phoenix_Moneybookers-1.2.3
upgrade ok: channel://connect.magentocommerce.com/core/Find_Feed-1.0.7
upgrade ok: channel://connect.magentocommerce.com/core/Interface_Adminhtml_Default-1.4.2.0
</pre>

<p>2 - When this part of the upgrade will be complete, enter these commands:</p>

<pre class="brush:xml">
chmod 550 ./mage
./mage mage-setup .
</pre>

<p>You will see this result after command execution:</p>

<pre class="brush:xml">Successfully added: http://connect20.magentocommerce.com/community</pre>

<p>It means that Magento connect 2.0 channel was added to the channels list successfully.</p>

<p>3 - Next, enter this command:</p>

<pre class="brush:xml">./mage sync</pre>

<p>The result will be:</p>

<pre class="brush:xml">
...
Successfully added: community/Mage_Locale_en_US-1.4.2.0
Successfully added: community/Interface_Install_Default-1.4.2.0
Successfully added: community/Phoenix_Moneybookers-1.2.3
Successfully added: community/Mage_Downloader-1.5.0.0
Successfully added: community/Lib_Google_Checkout-1.4.2.0
</pre>

<p>Upgrade to Magento 1.4.2.0 is complete and now you can proceed with upgrade to Magento 1.7.x version.</p>

<h2>Upgrade from Magento 1.4.x, 1.5.x, 1.6.x to Magento 1.7.x</h2>

<p>Now you can upgrade your store to version 1.7.0.2.</p>
<p>Before proceeding with this part of Magento upgrade, it is important to see to what version Magento upgrade scripts will upgrade your store. Enter this command to check this:</p>
<pre class="brush:xml">./mage list-upgrades</pre>
<p>If you will see this result:</p>
<pre class="brush:xml">
Updates for community:
Mage_All_Latest: 1.4.2.1 =&gt; 1.7.0.2
Lib_Js_Mage: 1.4.2.0 =&gt; 1.7.0.2
Lib_Varien: 1.4.2.0 =&gt; 1.7.0.2
</pre>
<p>It means that your Magento will be upgraded to version 1.7.0.2. If it is not what you need you can change upgrade channel to "beta" and upgrade your Magento to RC (beta) version.</p>
<p>1 - Enter this command to change the upgrade channel to stable (remember, "stable" channel will upgrade your Magento to latest 1.7.x stable version):</p>
<pre class="brush:xml">
./mage config-set preferred_state stable
</pre>
<p>After this the "<em>./mage list-upgrades</em>" command will show you this result:</p>
<pre class="brush:xml">
Updates for community:
Mage_All_Latest: 1.4.2.1 =&gt; 1.7.0.2.
Lib_Js_Mage: 1.4.2.0 =&gt; 1.7.0.2.
Lib_Varien: 1.4.2.0 =&gt; 1.7.0.2.
Lib_Phpseclib: 1.4.2.0 =&gt; 1.7.0.2.
Mage_Core_Adminhtml: 1.4.2.0 =&gt; 1.7.0.2.
Mage_Core_Modules: 1.4.2.0 =&gt; 1.7.0.2.
</pre>
<p>2 - After channel selection you can upgrade your Magento to Magento 1.7.0.2) using this command:</p>
<pre class="brush:xml">./mage upgrade-all --force</pre>
<p>If "<em>./mage upgrade-all --force</em>" will not work, you can try to execute this command:</p>
<pre class="brush:xml">./mage install http://connect20.magentocommerce.com/community Mage_All_Latest --force</pre>
<p>You will see upgraded packages on your screen:</p>

<pre class="brush:xml">
...
Package upgraded: community/Mage_Locale_en_US 1.7.0.2
Package upgraded: community/Lib_Mage 1.7.0.2
Package upgraded: community/Lib_ZF 1.11.1.0
Package upgraded: community/Lib_Js_Prototype 1.7.0.2.
Package upgraded: community/Lib_ZF_Locale 1.11.1.0
</pre>
<p>Now the upgrade is complete and you can execute database upgrade visiting your Magento store in your browser, this process will take several minutes, so be patient. If everything was upgraded correctly, you will see upgraded store in your browser. Before database upgrade it is recommended to increase time and memory limits of your PHP engine.</p>
<p>If it is not possible to increase it, you can try to execute database upgrade via SSH, e.g.:</p>
<pre class="brush:xml">php -f ./index.php</pre>
<p>When database upgrade will be finished, you can check version of your store in the footer of Magento administration panel.</p>

<h2>Need professional help with Magento upgrade?</h2>
<p><img style="margin-right: 10px; margin-left: 10px;" title="Upgrade Help" src="http://turnkeye.com/media/wysiwyg/blog/2011/07/UpgradeHelp.png" alt="" width="28" height="28" />Turnkeye.com offers professional Magento services, including <a title="Magento development" href="http://turnkeye.com/services/magento_development.html">Magento development</a> and <a href="http://turnkeye.com/services/magento_upgrade.html">Magento upgrade</a> service. Feel free to <a href="http://turnkeye.com/contact_us.html">contact our team</a>.
</p>

<h2>Troubleshooting</h2>

<p>1 - Magento upgrade script error:</p>
<pre class="brush:xml">
upgrade-all: Please check for sufficient write file permissions.
Error: upgrade-all: Your Magento folder does not have sufficient write permissions, which downloader requires.
</pre>
<p>Execute this command to fix the error:</p>
<pre class="brush:xml">
chmod -R 777 Upgrade
</pre>

<p>2 - Magento upgrade script error:</p>
<pre class="brush:xml">
upgrade-all: Invalid stability in compareStabilities argument.
</pre>
<p>Execute these commands, it will fix the issue:</p>
<pre class="brush:xml">
./mage channel-add connect20.magentocommerce.com/community
./mage channel-add connect20.magentocommerce.com/core
./mage sync
</pre>
<p>Or as a solution you can run this command:</p>
<pre class="brush:xml">
./mage install http://connect20.magentocommerce.com/community Mage_All_Latest --force
</pre>

<p>3 - Server error:</p>
<pre class="brush:xml">
"Internal Server Error" instead of Magento storefront page or administration zone pages.
</pre>
<p>Most likely issue is connected with wrong permissions.</p>
<p>Fix this issue using these recursive commands:</p>
<pre class="brush:xml">find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;</pre>

<p>4 - Magento error: Different errors in Magento database.</p>
<p>Reindex your database in Magento administration panel and clear Magento cache.</p>

<p>5 - Magento error:</p>
<pre class="brush:xml">
"Invalid mode for clean() method".
</pre>
<p>Clear Zend cache (all files, including "Backend" folder) in [magento_folder]/app/code/core/Zend/Cache/</p>

<p>6 - Magento error:</p>
<pre class="brush:xml">
"Call to a member function toHtml() on a non-object in .../Layout.php".
</pre>
<p>Open [magento_folder]/app/design/frontend/default/[your_theme]/layout/page.xml and replace this line of the code:</p>
<pre class="brush:xml">&lt;block type="core/profiler" output="toHtml"/></pre>
<p>With:</p>
<pre class="brush:xml">&lt;block type="core/profiler" output="toHtml" name="core_profiler"/></pre>

<p>7 - Magento error:</p>
<pre class="brush:xml">"Maximum key size must be smaller 32".</pre>
<p>Clear Magento cache.</p>

<p>8 - Pagination is not showing on product listing:</p>
<p>Open this file: app/code/core/Mage/Catalog/Block/Product/List/Toolbar.php</p>
<p>And replace this line of the code:</p>
<pre class="brush:xml">
class Mage_Catalog_Block_Product_List_Toolbar extends Mage_Core_Block_Template
</pre>
<p>with:</p>
<pre class="brush:xml">
class Mage_Catalog_Block_Product_List_Toolbar extends Mage_Page_Block_Html_Pager
</pre>

<p>9 - Magento error:</p>
<pre class="brush:xml">
Column not found: 1054 Unknown column 'custom_use_parent_settings' in 'where clause'
</pre>
<p>Reindex your database using Linux shell.</p>

<p>10 - Magento error:</p>
<pre class="brush:xml">
Cannot connect to the database
</pre>
<p>Check the /app/etc/local.xml and make sure that there is such code:</p>
<pre class="brush:php">&lt;model>{{db_model}}&lt;/model></pre>]]></description>
      <pubDate>Mon, 25 Mar 2013 01:47:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[How to create a single page for customers registration and login in Magento]]></title>
      <link>http://turnkeye.com/blog/magento-registration-login/</link>
      <description><![CDATA[<p><img src="http://turnkeye.com/media/wysiwyg/blog/2013/03/login_register_wide.jpg" alt="Single page for customers registration and login in Magento"/></p>

<h3>In this article I will describe how to create single page for customers registration and login.</h3>
<p>Your customers will see register and login forms on one page, without any pages reloading.</p>

<p>There only 2 simple steps to achieve this behavior in Magento:</p>

<h2>Step 1. Layout modification.</h2>

<p>Open the customer.xml file in your theme and find the customer_account_login handle. Add these blocks to the reference content:</p>

<pre class="brush:xml">
    &lt;customer_account_login translate="label">
        &lt;label>Customer Account Login Form&lt;/label>
        &lt;!-- Mage_Customer -->
        &lt;remove name="right"/>
        &lt;remove name="left"/>

        &lt;reference name="root">
            &lt;action method="setTemplate">&lt;template>page/1column.phtml&lt;/template>&lt;/action>

        &lt;/reference>
        &lt;reference name="content">
            &lt;block type="customer/form_login" name="customer_form_login" template="customer/form/login.phtml" />

            &lt;!-- block new customer register from customer_account_create-->
            &lt;block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml">
                &lt;block type="page/html_wrapper" name="customer.form.register.fields.before" as="form_fields_before" translate="label">
                    &lt;label>Form Fields Before&lt;/label>
                &lt;/block>
            &lt;/block>
            &lt;!-- block forgot password from customer_account_forgotpassword -->
            &lt;block type="customer/account_forgotpassword" name="forgotPassword" template="customer/form/forgotpassword.phtml" />
        &lt;/reference>
    &lt;/customer_account_login>
</pre>

<p>&nbsp;<br />
In the customer_account_create and customer_account_forgotpassword handles add the <update handle="customer_account_login"/> and remove the unnecessary elements.</p>
<p>Here is the code we get for these blocks:<br />
&nbsp;</p>
<pre class="brush:php">
    &lt;customer_account_create translate="label">
        &lt;label>Customer Account Registration Form&lt;/label>
        &lt;!-- Mage_Customer -->
        &lt;remove name="right"/>
        &lt;remove name="left"/>
        &lt;update handle="customer_account_login"/>
    &lt;/customer_account_create>

    &lt;customer_account_forgotpassword translate="label">
        &lt;label>Customer Forgot Password Form&lt;/label>
        &lt;remove name="right"/>
        &lt;remove name="left"/>
        &lt;update handle="customer_account_login"/>
        &lt;reference name="head">
            &lt;action method="setTitle" translate="title" module="customer">&lt;title>Forgot Your Password&lt;/title>&lt;/action>
            &lt;action method="setHeaderTitle" translate="title" module="customer">&lt;title>Password forgotten&lt;/title>&lt;/action>
        &lt;/reference>
    &lt;/customer_account_forgotpassword>
</pre>

<p>Now we have all necessary blocks on one page.</p>

<h2>Step 2. Templates modifications.</h2>

<p>Now we need to modify templates.</p>

<p>1) Open the persistent/customer/form/login.phtml and remove the New Customers block and Forgot Your Password link.<br />
(if the persistent module is disabled, you will need to modify customer/form/login.phtml).</p>

<p>2) Open the customer/form/register.phtml and customer/form/forgotpassword.phtml templates and remove this code from these templates:</p>

<pre class="brush:php">&lt;?php echo $this->getMessagesBlock()->getGroupedHtml() ?></pre>

<p>Otherwise the system messages will be shown in each block.<br />
Also you will need to remove the Back button, as it is not needed anymore.</p>
<p>The development stage is complete, now you will need to adjust the CSS according to your website design.</p>]]></description>
      <pubDate>Thu, 14 Mar 2013 14:20:15 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[How to migrate Magento Professional to Magento Community or Enterprise]]></title>
      <link>http://turnkeye.com/blog/migration-magento-professional-to-community-or-enterprise/</link>
      <description><![CDATA[<p><img src="http://turnkeye.com/media/wysiwyg/blog/2013/02/migration_magento_wide.jpg" alt="How to migrate Magento Professional to Magento Community or Enterprise"/></p>

<h3>In this article we will share universal instruction on how to migrate your Magento Professional store to Magento Community or Magento Enterprise.</h3>
<p>The migration process is quite complex, so make sure that the developers who are responsible for this migration project are certified Magento developers.</p>

<h2>1. Prepare for the migration</h2>
<p><strong>Copy your Magento Pro to a development server.</strong></p>
<p>Never upgrade live store directly!</p>
<p>On this stage we will prepare development environment for migration.
First of all copy your Magento Pro store to a separate development environment (e.g. development server).</p>
<p>It is highly recommended to make it completely separate from your live store.
Database upgrade is resource heavy operation and if you will do it on live environment, most likely your server will terminate DB upgrade process and upgrade will be half-done.</p>

<p><strong>Prepare server environment.</strong><br /></p>
<p>We recommend to change these development server settings:
<ul>
<li>Increase PHP memory</li>
<li>Increase PHP execution time</li>
<li>Increase MySQL 'wait_timeout' in my.cnf configuration file (e.g. to 28800 seconds)</li>
<li>Increase MySQL 'max_allowed_packet' in my.cnf (e.g. to 64 Mb)</li>
</ul>
</p>
<p><strong>Prepare Magento Professional copy for migration.</strong></p>
<p>We recommend to do the following before migration:
<ul>
<li>Close development copy from web access using .htaccess (you can use 'Deny from all' command)</li>
<li>Make sure that logging is activated in Magento Pro, so you can access the errors logs</li>
<li>Clear Magento Pro cache and sessions</li>
<li>Clear Magento log tables in MySQL</li>
</ul>

<h2>2. Upgrade the core</h2>
<p>Download the latest Magento Community or Magento Enterprise package and unzip it to the separate folder on development server.
Next, move the Magento CE/EE core files from unzipped distributive to Magento Professional copy that you created.
This way you will replace the Magento Pro core with Magento CE/EE core.</p>
<p>Please note that any core hacks in your Magento Professional will be lost after core replacement.
Magento is modular system and it is always recommended to customize it according to best practices via modules, instead of dirty core hacks.</p>

<h2>3. Initiate upgrade of the database</h2>
<p>This is the most important stage. The new core will start database upgrade/DB transformation process, and this is why we increased server settings values. The process should run smoothly without any server side interruptions.</p>
<p>You can execute DB upgrade process via SSH shell, example:</p>
<pre class="brush:php">php -f ./index.php &</pre>
<p>The process could take several hours so be patient and monitor the command output for unexpected errors. If you get an error, please check the 'Troubleshooting' in this article, hope it will help you to complete the migration.</p>

<h2>4. Troubleshooting</h2>
<p><strong>1. MySQL errors of this type:</strong></p>
<pre class="brush:xml">
Error on rename of './#sql-16e4_c99b' to './magento__core_url_rewrite' (errno: 150)
</pre>
<p>If you get such error during DB upgrade try the following solution:
<ul>
<li>Connect to your server via SSH, login to MySQL console and execute this command: SHOW ENGINE INNODB STATUS</li>
<li>Check the LATEST FOREIGN KEY ERROR section</li>
</ul>
</p>
<p>You will see something like this:</p>
<pre class="brush:xml">
------------------------
LATEST FOREIGN KEY ERROR
------------------------
130208  2:32:08 Error in foreign key constraint of table /magento__core_url_rewrite:
there is no index in the table which would contain the columns as the first columns, or the data types in the table do not match the ones in the referenced table or one of the ON ... SET NULL columns is declared NOT NULL. Constraint: , CONSTRAINT "magento__core_url_rewrite_ibfk_1" FOREIGN KEY ("category_id") REFERENCES "magento__catalog_category_entity" ("entity_id") ON DELETE CASCADE ON UPDATE CASCADE
</pre>
<p>To fix the error you should execute the following command in MySQL, it will fix the "magento__core_url_rewrite_ibfk_1" foreign key issue:</p>
<pre class="brush:mysql">
ALTER TABLE magento__core_url_rewrite DROP FOREIGN KEY magento__core_url_rewrite_ibfk_1;
</pre>
<p>Next, execute the DB upgrade once again. If you will get the same error (errno: 150) connected with different table, just repeat the actions for other table/foreign key.</p>

<p><strong>2. Password reset error:</strong></p>
<p>If you see such error during reset password feature testing:</p>
<pre class="brush:xml">
Fatal error: Call to a member function setCustomerId() on a non-object in /app/code/core/Mage/Customer/controllers/AccountController.php on line 601
</pre>
<p>Open the /app/design/frontend/[your_theme_package]/[your_theme_name]/layout/customer.xml file and add this section to the XML:</p>

<pre class="brush:xml">

&lt;customer_account_resetpassword translate="label">
    &lt;label>Reset a Password&lt;/label>
    &lt;remove name="right"/>
    &lt;remove name="left"/>
    &lt;reference name="head">
        &lt;action method="setTitle" translate="title" module="customer">
            &lt;title>Reset a Password&lt;/title>
        &lt;/action>
    &lt;/reference>

    &lt;reference name="root">
        &lt;action method="setTemplate">
            &lt;template>page/1column.phtml&lt;/template>
        &lt;/action>
        &lt;action method="setHeaderTitle" translate="title" module="customer">
            &lt;title>Reset a Password&lt;/title>
        &lt;/action>
    &lt;/reference>
    &lt;reference name="content">
        &lt;block type="customer/account_resetpassword" name="resetPassword" template="customer/form/resetforgottenpassword.phtml"/>
    &lt;/reference>
&lt;/customer_account_resetpassword>

</pre>

<p><strong>3. CSS/templates issues:</strong></p>
<p>Quite possible that CSS templates tweaks will be needed, since the Pro and EE/CE features are different.
It is not possible to write an article about all such issues for all stores, so just try to debug them and fix.</p>

<p><strong>4. 3-rd party modules issues:</strong></p>
<p>In most cases re-installation of the modules will be needed, since Magento Pro and CE/EE modules could be not compatible.
If you will see any 3-rd party modules related issues, request Magento CE/EE modules versions from modules vendors.</p>]]></description>
      <pubDate>Thu, 28 Feb 2013 15:43:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento mobile theme FAQ]]></title>
      <link>http://turnkeye.com/blog/magento-mobile-theme-faq/</link>
      <description><![CDATA[<p><img src="http://turnkeye.com/media/wysiwyg/blog/2013/02/magento_mobile_wide.jpg" alt="Magento mobile theme FAQ"/></p>

<h3>The amount of mobile devices keeps growing. Definitely, you should consider the mobile theme for your Magento store.</h3>
<h2>Should I use Magento mobile theme?</h2>

<p>The number of mobile-connected devices exceeded the number of people on earth in the end of 2012, people use smartphones and tablets for shopping and research, and sooner or later you will face with necessity to implement mobile theme. Thankfully, it is already included into latest versions of standard Magento (all editions).</p>

<h2>How to install?</h2>

<p>By default Magento mobile theme is located in the <i>app/design/frontend/default/iphone/</i> folder (for Community edition).</p>
<p>There is a <a target="_blank" href="http://inchoo.net/ecommerce/Magento/Magento-mobile-theme-imobile/" title="http://inchoo.net/ecommerce/Magento/Magento-mobile-theme-imobile/">great article from our friends</a> where you can find detailed description on how to setup automatic switching using design exceptions for Magento mobile theme.</p>
<p>In short, you need to add an exception for mobile user agents, that's it:</p>

<p>
<strong>exception</strong>
<pre class="brush:xml">
iPhone|iPod|BlackBerry|Palm|Googlebot-Mobile|mobile|mobi|Windows Mobile|Safari Mobile|Android|Opera Mini|Fennec
</pre>
</p>

<p>
<strong>value</strong>
<pre class="brush:xml">
iphone
</pre>
</p>

<p>Then Magento will detect customers agent type and will show him/her appropriate store view.</p>

<h2>How can I test this?</h2>

<p>Surely after configuration you need to check what you did. There are several ways to do that:</p>

<ul>
<li>Visit your store using iPhone/Android smartphone</li>
<li>Use user agent switcher browser extension (<a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/user-agent-switcher/">FireFox only</a>)</li>
<li>Use embedded agent switcher in Google Chrome browser</li>
<li>Use <a target="_blank" href="http://www.opera.com/developer/tools/mini/" title="Opera Mini">Opera Mini simulator</a></li>
</ul>

<p>You can view and test your mobile theme using any of these tools.</p>
<p>You can also validate your theme using <a target="_blank" href="http://validator.w3.org/mobile/" title="W3C mobileOK Checker">service from W3C</a>.</p>

<h2>What if I want to switch to mobile theme manually, instead of automatic redirect?</h2>

<p>If you don't need an automatic switch, the easiest way to implement manual switching is to create a separate store view in Magento and assign the mobile theme to this store view. Then you will need to insert a link to standard/mobile store view in the front-end, and customer will be able to switch between standard/mobile store views with a click.</p>

<h2>What if I want to customize the mobile theme design?</h2>

<p>The mobile theme can be modified the same way as any standard Magento theme. </p>

<p>However, there are several points you should be aware of:<br />
- There are separate CSS for retina displays, it is at the bottom of iphone.css file of your mobile theme. So if you changed something, but then you see standard header in your iPhone, it means that you forgot to change retina styles.<br />
- Your markup should have adaptive width to support all mobile devices.</p>

<h2>Some known problems</h2>

<p>There is a known problem in Magento Enterprise caused by full page cache.</p>

<p>Magento full page caching generate cache keys using store ID & design package (+ some other info), but it does not use theme for generation. Practically it means that Magento full page cache processor will not recognize different themes specified for the same store (but mobile theme works exactly this way). There are 2 ways to solve this issue:<br />
- Move mobile theme to a separate package.<br />
- Implement a <a target="_blank" href="https://github.com/benjy14/MobileFpcFix" title="Magento Enterprise FPC Fix">fix for FPC generation</a>.</p>

<p><strong>Further reading</strong></p>
<ul>
<li><a target="_blank" href="http://techcrunch.com/2012/02/14/the-number-of-mobile-devices-will-exceed-worlds-population-by-2012-other-shocking-figures/" title="TechCrunch: The Number Of Mobile Devices Will Exceed World’s Population By 2012">TechCrunch: The Number Of Mobile Devices Will Exceed World’s Population By 2012</a></li>
<li><a target="_blank" href="http://validator.w3.org/mobile/" title="W3C mobileOK Checker">W3C mobileOK Checker</a></li>
<li><a target="_blank" href="http://inchoo.net/ecommerce/Magento/Magento-mobile-theme-imobile/" title="http://inchoo.net/ecommerce/Magento/Magento-mobile-theme-imobile/">Inchoo: Magento mobile theme</a></li>
<li><a target="_blank" href="https://github.com/benjy14/MobileFpcFix" title="Magento Enterprise FPC Fix">Magento Enterprise FPC Fix</a></li>
<li><a target="_blank" href="http://www.opera.com/developer/tools/mini/" title="Opera Mini">Opera Mini simulator</a></li>
</ul>]]></description>
      <pubDate>Fri, 08 Feb 2013 15:51:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento performance: Optimization of Magento configurable products. Part 2.]]></title>
      <link>http://turnkeye.com/blog/magento-performance-optimization-configurable-products-2/</link>
      <description><![CDATA[<p><a href="http://turnkeye.com/blog/magento-performance-optimization-configurable-products-2"><img alt="Magento performance" src="http://turnkeye.com/media/wysiwyg/blog/banners/performance_magento_wide.jpg" title="Magento performance"/></a></p>

<p>In my <a target="_blank" href="http://turnkeye.com/blog/magento-perfomance-optimization-of-configurable-products/">previous article</a> I wrote about performance issues when you have many attribute options for configurable attribute. Here I will provide you with several tips on how to increase performance if you have configurable products with many associated products (100 associated products and more).</p>

<p>There are 2 possible performance issues with such products:<br />
1. Loading time of Product listing page is more than 10 seconds.<br />
2. Loading time of Product details page is more than 10 seconds.</p>

<p>If you enable Magento Profiler you will see that in both cases the Mage_Catalog_Model_Product_Type_Configurable::getUsedProducts method takes a lot of time.</p>

<p>On the product page this method is required to collect all options/prices for configurable product. But in the product list page this method used only in the Mage_Catalog_Model_Product_Type_Configurable::isSalable method to check if the product available for sale or not.</p>

<p>So you need to change the isSalable method:</p>

<pre class="brush:php">
    public function isSalable($product = null)
    {
        $salable = parent::isSalable($product);

        if ($salable !== false) {
            $salable = false;
            if (!is_null($product)) {
                $this->setStoreFilter($product->getStoreId(), $product);
            }
            foreach ($this->getUsedProducts(null, $product) as $child) {
                if ($child->isSalable()) {
                    $salable = true;
                    break;
                }
            }
        }

        return $salable;
    }
</pre>

<p>To something like this:</p>

<pre class="brush:php">
public function isSalable($product = null)
    {
        $salable = parent::isSalable($product);

        if ($salable !== false) {
            $salable = false;
            if (!is_null($product)) {
                $this->setStoreFilter($product->getStoreId(), $product);
            }

            if (!Mage::app()->getStore()->isAdmin() && $product) {
                $collection = $this->getUsedProductCollection($product)
                    ->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED)
                    ->setPageSize(1)
                    ;
                if ($collection->getFirstItem()->getId()) {
                    $salable = true;
                }
            } else {
                foreach ($this->getUsedProducts(null, $product) as $child) {
                    if ($child->isSalable()) {
                        $salable = true;
                        break;
                    }
                }
            }
        }

        return $salable;
    }
</pre>

<p>In our case we try to find first associated product with Enabled status, and it is OK for us. By default Magento also checks the stock status.</p>

<p>After this modification your product listing page should load approximately with the same time as other pages of the store.</p>

<p>To solve issue on the Product details page we need to cache products loading. You can do it by changing the Mage_Catalog_Model_Product_Type_Configurable::getUsedProducts method:</p>

<pre class="brush:php">
public function getUsedProducts($requiredAttributeIds = null, $product = null)
    {
        Varien_Profiler::start('CONFIGURABLE:'.__METHOD__);
        if (!$this->getProduct($product)->hasData($this->_usedProducts)) {
            if (is_null($requiredAttributeIds)
                and is_null($this->getProduct($product)->getData($this->_configurableAttributes))) {
                // If used products load before attributes, we will load attributes.
                $this->getConfigurableAttributes($product);
                // After attributes loading products loaded too.
                Varien_Profiler::stop('CONFIGURABLE:'.__METHOD__);
                return $this->getProduct($product)->getData($this->_usedProducts);
            }

            $use_cache = false;
            if (!Mage::app()->getStore()->isAdmin() && $product) {
                if (!is_dir(Mage::getBaseDir('cache') . DS . 'associated')) {
                    @mkdir(Mage::getBaseDir('cache') . DS . 'associated', 0777);
                }

                $file_cache = Mage::getBaseDir('cache') . DS . 'associated' . DS . $product->getId() . '.php';
                $use_cache = true;
            }

            $usedProducts = array();
            if ($use_cache && is_file($file_cache)) {
                $data = include_once($file_cache);
                foreach ($data as $k => $d) {
                    $class_name = Mage::getConfig()->getModelClassName('catalog/product');
                    $usedProducts[] = new $class_name($d);
                }
            } else {
                $collection = $this->getUsedProductCollection($product)
                    ->addAttributeToSelect('*')
                    ->addFilterByRequiredOptions();

                if (is_array($requiredAttributeIds)) {
                    foreach ($requiredAttributeIds as $attributeId) {
                        $attribute = $this->getAttributeById($attributeId, $product);
                        if (!is_null($attribute))
                            $collection->addAttributeToFilter($attribute->getAttributeCode(), array('notnull'=>1));
                    }
                }

                if ($use_cache) {
                    $cache_str = '';
                    foreach ($collection as $id => $item) {
                        $item->unsetData('stock_item');
                        $cache_str .= $id . " => " . var_export($item->getData(), true) . ",\n";
                        $usedProducts[] = $item;
                    }

                    $fd = fopen($file_cache, 'wb+');
                    fwrite($fd, "&lt;?php\nreturn array(" . $cache_str . ");\n?>");
                    fclose($fd);
                } else {
                    foreach ($collection as $item) {
                        $usedProducts[] = $item;
                    }
                }
            }

            $this->getProduct($product)->setData($this->_usedProducts, $usedProducts);
        }
        Varien_Profiler::stop('CONFIGURABLE:'.__METHOD__);
        return $this->getProduct($product)->getData($this->_usedProducts);
    }
</pre>

<p>In the code we checking the possibility to use cache. Also we create folder for cache files var/cache/associated/ (if it does not exists). The cache file name is {product_id}.php.</p>

<p>If we already have a cache file we just take information from it. We use php code in cache - it is an array with product data, so our cache file is valid PHP file.<br />
We assign  product data to Product model (without loading) from the cache. Note that we use current product model from config:<br />

<pre class="brush:php">
$class_name = Mage::getConfig()->getModelClassName('catalog/product');
$usedProducts[] = new $class_name($d);
</pre>

<p>We use standard PHP function var_export() for cache file creation.</p>

<p>Sometimes you will need to cache stock_item data - it is an object so it should be exported like product object, and should be assign to product when you load the cache. In our case it is not necessary.</p>

<p>When you complete all steps I described, the product page loading time will be much less.</p>

<p>The last thing is to clear the cache, to do it, just remove the cache file in the Mage_Catalog_Model_Product_Type_Configurable::save() method:</p>

<pre class="brush:php">
if (is_file(Mage::getBaseDir('cache') . DS . 'associated' . DS . $product->getId() . '.php')) {
    unlink(Mage::getBaseDir('cache') . DS . 'associated' . DS . $product->getId() . '.php');
}
</pre>

<p>We completed a lot of Magento speed up investigations and found that most of performance issues are connected with third party extensions which modify attributes/custom options functionality. There is no any ideal solution for all stores as each situation is unique and should be investigated.</p>

<p>You can always use Magento profiler to find critical performance issues.</p>

<p>We recommend to avoid creation of configurable products with many associations (1000+), and if possible split such configurable products to several ones.</p>]]></description>
      <pubDate>Wed, 06 Feb 2013 09:10:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Security Tips: Make sure that you applied all latest Magento Enterprise security patches]]></title>
      <link>http://turnkeye.com/blog/magento-enterprise-security-patches/</link>
      <description><![CDATA[<p><a href="http://turnkeye.com/blog/magento-enterprise-security-patches"><img src="http://turnkeye.com/media/wysiwyg/blog/2013/01/enterprise-security.png" alt="" title="enterprise-security" width="650" height="121" class="alignnone size-full wp-image-3534" /></a></p>
<p>It is very important to keep your Magento Enterprise installation patched.</p>
<p>Make sure that you applied all latest official Magento Enterprise security patches:</p>
<p><!--more--></p>
<p>&nbsp;</p>
<p><strong>For Magento Enterprise 1.8.0.0</strong><br />
Release date: 7/5/12<br />
Patch name: SUP-5109_EE_1.8.0.0_v2-2012-07-05-05-12-33.patch</p>
<p>&nbsp;</p>
<p><strong>For Magento Enterprise 1.9.0.0 - 1.9.1.1 </strong><br />
Release date: 7/5/12<br />
Patch name: SUP-5109_EE_1.9.0.0-1.9.1.1_v2-2012-07-05-05-15-47.patch</p>
<p>&nbsp;</p>
<p><strong>For Magento Enterprise 1.10.0.0 - 1.12.0.1</strong><br />
Release date: 7/5/12<br />
Patch name: SUP-5109_EE_1.10.0.0-1.12.0.1_v2-2012-07-05-05-17-23.patch</p>
<p>&nbsp;</p>
<p>You can find these patches in the "Download" section of your Magento account.</p>
<p>Also, since Magento is based on Zend framework, it is highly recommended to monitor vulnerabilities reported against Zend Framework here:<br />
<a href="http://framework.zend.com/security/advisories/">http://framework.zend.com/security/advisories/</a></p>
<p>Keep your Magento secure!</p>
<p>&nbsp;<br />
&nbsp;</p>
]]></description>
      <pubDate>Sun, 27 Jan 2013 12:46:13 +0000</pubDate>
    </item>
  </channel>
</rss>
