<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Atwix &#187; development</title>
	<atom:link href="http://www.atwix.com/tag/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.atwix.com</link>
	<description>Custom Magento development, Magento modules and design</description>
	<lastBuildDate>Tue, 21 May 2013 11:30:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Source, frontend and backend models in Magento system settings</title>
		<link>http://www.atwix.com/magento/frontend-backend-source/</link>
		<comments>http://www.atwix.com/magento/frontend-backend-source/#comments</comments>
		<pubDate>Mon, 25 Feb 2013 08:37:40 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[customize]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[field]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[settings]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=2592</guid>
		<description><![CDATA[You're welcome to check our new finding on source, frontend and backend models in Magento system settings.]]></description>
				<content:encoded><![CDATA[<p>In the previous <a title="article" href="http://www.atwix.com/magento/system-settings/">article</a> we have described how the different settings can be applied to a custom extension. There&#8217;s nothing difficult for the simple settings such as text field or text area. But, if you look at the drop down, multiselect or editable items list you&#8217;ll notice that these items have additional fields, e.g. source_model, backend_model, frontend_model. Let&#8217;s focus on these models and find out more info about creating settings that require data models. <span id="more-2592"></span></p>
<p>Source Model &#8211; a model class that serves to get existing values (stored in the db or somewhere else) for further displaying inside the setting&#8217;s field.</p>
<p>Frontend Model &#8211; as a rule, it&#8217;s a block&#8217;s class. Methods of this class return html of setting&#8217;s field. To be more specific, the block had to have method _getElementHtml() described inside the class which returns the raw html of setting&#8217;s field.</p>
<p>Backend Model &#8211; a class which allows to operate with configuration data on the different stages (save, load). It contains three major methods respectively for each event: _afterLoad(), _beforeSave() and _afterSave().</p>
<p>If you are interested in, you can always find the working examples of each of them in the Magento core itself. But firstly, let&#8217;s try to look on some custom examples of these models. The following part describes how to create a drop down menu with the custom values:</p>
<p>Init setting&#8217;s field in your system.xml:</p>
<pre class="brush: xml; gutter: true">&lt;color&gt;
    &lt;label&gt;Color&lt;/label&gt;
    &lt;frontend_type&gt;select&lt;/frontend_type&gt;
    &lt;source_model&gt;Atwix_Shoppingbar_Model_Adminhtml_System_Config_Source_Color&lt;/source_model&gt;
    &lt;sort_order&gt;2&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/color&gt;</pre>
<p>Then, create the source model that was specified above:</p>
<pre class="brush: php; gutter: true">class Atwix_Shoppingbar_Model_Adminhtml_System_Config_Source_Color
{
   public function toOptionArray()
   {
       $themes = array(
           array(&#039;value&#039; =&gt; &#039;green&#039;, &#039;label&#039; =&gt; &#039;Green&#039;),
           array(&#039;value&#039; =&gt; &#039;blue&#039;, &#039;label&#039; =&gt; &#039;Blue&#039;),
           array(&#039;value&#039; =&gt; &#039;beige&#039;, &#039;label&#039; =&gt; &#039;Beige&#039;),
       );

       return $themes;
   }
}</pre>
<p>As you can see, there&#8217;s only one method toOptionArray(). It returns an array with the items (value -&gt; label) for the drop down menu. Nothing difficult is here <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Let&#8217;s look onto another example to find out how to use frontend and source models. The best point is to review editable items list setting since it has both. The setting described below operates with the text items. It allows to add/remove email addresses:</p>
<pre class="brush: xml; gutter: true">&lt;addresses&gt;
    &lt;label&gt;Blocked Email Addresses&lt;/label&gt;
    &lt;frontend_model&gt;atwix_emailblocker/adminhtml_addresses&lt;/frontend_model&gt;
    &lt;backend_model&gt;adminhtml/system_config_backend_serialized&lt;/backend_model&gt;
    &lt;sort_order&gt;2&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;0&lt;/show_in_website&gt;
    &lt;show_in_store&gt;0&lt;/show_in_store&gt;
    &lt;can_be_empty&gt;1&lt;/can_be_empty&gt;
&lt;/addresses&gt;</pre>
<p>Frontend model is a block:</p>
<pre class="brush: php; gutter: true">class Atwix_Emailblocker_Block_Adminhtml_Addresses extends Mage_Adminhtml_Block_System_Config_Form_Field
{
   protected $_addRowButtonHtml = array();
   protected $_removeRowButtonHtml = array();

   /**
    * Returns html part of the setting
    *
    * @param Varien_Data_Form_Element_Abstract $element
    * @return string
    */
   protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
   {
       $this-&gt;setElement($element);

       $html = &#039;&lt;div id=&quot;emailblocker_addresses_template&quot; style=&quot;display:none&quot;&gt;&#039;;
       $html .= $this-&gt;_getRowTemplateHtml();
       $html .= &#039;&lt;/div&gt;&#039;;

       $html .= &#039;&lt;ul id=&quot;emailblocker_addresses_container&quot;&gt;&#039;;
       if ($this-&gt;_getValue(&#039;addresses&#039;)) {
           foreach ($this-&gt;_getValue(&#039;addresses&#039;) as $i =&gt; $f) {
               if ($i) {
                   $html .= $this-&gt;_getRowTemplateHtml($i);
               }
           }
       }
       $html .= &#039;&lt;/ul&gt;&#039;;
       $html .= $this-&gt;_getAddRowButtonHtml(&#039;emailblocker_addresses_container&#039;,
           &#039;emailblocker_addresses_template&#039;, $this-&gt;__(&#039;Add New Email&#039;));

       return $html;
   }

   /**
    * Retrieve html template for setting
    *
    * @param int $rowIndex
    * @return string
    */
   protected function _getRowTemplateHtml($rowIndex = 0)
   {
       $html = &#039;&lt;li&gt;&#039;;

       $html .= &#039;&lt;div style=&quot;margin:5px 0 10px;&quot;&gt;&#039;;
       $html .= &#039;&lt;input style=&quot;width:100px;&quot; name=&quot;&#039;
           . $this-&gt;getElement()-&gt;getName() . &#039;[addresses][]&quot; value=&quot;&#039;
           . $this-&gt;_getValue(&#039;addresses/&#039; . $rowIndex) . &#039;&quot; &#039; . $this-&gt;_getDisabled() . &#039;/&gt; &#039;;

       $html .= $this-&gt;_getRemoveRowButtonHtml();
       $html .= &#039;&lt;/div&gt;&#039;;
       $html .= &#039;&lt;/li&gt;&#039;;

       return $html;
   }

   protected function _getDisabled()
   {
       return $this-&gt;getElement()-&gt;getDisabled() ? &#039; disabled&#039; : &#039;&#039;;
   }

   protected function _getValue($key)
   {
       return $this-&gt;getElement()-&gt;getData(&#039;value/&#039; . $key);
   }

   protected function _getSelected($key, $value)
   {
       return $this-&gt;getElement()-&gt;getData(&#039;value/&#039; . $key) == $value ? &#039;selected=&quot;selected&quot;&#039; : &#039;&#039;;
   }

   protected function _getAddRowButtonHtml($container, $template, $title=&#039;Add&#039;)
   {
       if (!isset($this-&gt;_addRowButtonHtml[$container])) {
           $this-&gt;_addRowButtonHtml[$container] = $this-&gt;getLayout()-&gt;createBlock(&#039;adminhtml/widget_button&#039;)
               -&gt;setType(&#039;button&#039;)
               -&gt;setClass(&#039;add &#039; . $this-&gt;_getDisabled())
               -&gt;setLabel($this-&gt;__($title))
               -&gt;setOnClick(&quot;Element.insert($(&#039;&quot; . $container . &quot;&#039;), {bottom: $(&#039;&quot; . $template . &quot;&#039;).innerHTML})&quot;)
               -&gt;setDisabled($this-&gt;_getDisabled())
               -&gt;toHtml();
       }
       return $this-&gt;_addRowButtonHtml[$container];
   }

   protected function _getRemoveRowButtonHtml($selector = &#039;li&#039;, $title = &#039;Delete&#039;)
   {
       if (!$this-&gt;_removeRowButtonHtml) {
           $this-&gt;_removeRowButtonHtml = $this-&gt;getLayout()-&gt;createBlock(&#039;adminhtml/widget_button&#039;)
               -&gt;setType(&#039;button&#039;)
               -&gt;setClass(&#039;delete v-middle &#039; . $this-&gt;_getDisabled())
               -&gt;setLabel($this-&gt;__($title))
               -&gt;setOnClick(&quot;Element.remove($(this).up(&#039;&quot; . $selector . &quot;&#039;))&quot;)
               -&gt;setDisabled($this-&gt;_getDisabled())
               -&gt;toHtml();
       }
       return $this-&gt;_removeRowButtonHtml;
   }
}</pre>
<p>It&#8217;s pretty huge. We have described the full version to show what&#8217;s going on there. You can simple extend your block from Mage_GoogleCheckout_Block_Adminhtml_Shipping_Merchant and override the necessary methods.</p>
<p>Backend model, in this case, it&#8217;s a standard Magento model:</p>
<pre class="brush: php; gutter: true">class Mage_Adminhtml_Model_System_Config_Backend_Serialized extends Mage_Core_Model_Config_Data
{
    protected function _afterLoad()
    {
        if (!is_array($this-&gt;getValue())) {
            $value = $this-&gt;getValue();
            $this-&gt;setValue(empty($value) ? false : unserialize($value));
        }
    }

    protected function _beforeSave()
    {
        if (is_array($this-&gt;getValue())) {
            $this-&gt;setValue(serialize($this-&gt;getValue()));
        }
    }
}</pre>
<p>As you can see, it simply unserializes/serializes field&#8217;s values before load/save respectively. That&#8217;s all. You are always able to improvise with the models described below to get the best result. If you want non-trivial form element &#8211; use your own fronted model. To get available values for settings you should use the source model. And if you need to save/load data in your format or make some other actions on these events &#8211; feel free to use the backend model.<br />
Good luck and graceful solutions <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/frontend-backend-source/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Magento system settings overview</title>
		<link>http://www.atwix.com/magento/system-settings/</link>
		<comments>http://www.atwix.com/magento/system-settings/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 08:26:59 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[customize]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[menus]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=2542</guid>
		<description><![CDATA[Our new article includes helpful snippets which contain xml code of the most recent settings used in Magento admin.]]></description>
				<content:encoded><![CDATA[<p>From time to time  Magento developers face with a need to add settings for their extensions. As it&#8217;s hard to remember all necessary details for each setting, so we would like to share our snippets which contain xml code of the most recent settings used in Magento admin.<span id="more-2542"></span></p>
<p>First of all, we would recommend you always place everything, that refers to Magento system settings, in the system.xml file, since it&#8217;s the main and the only role of this file.<br />
If you need to create your own tab in the admin system settings, you should simply add the following lines to the file:</p>
<pre class="brush: xml; gutter: true">&lt;config&gt;
    &lt;tabs&gt;
        &lt;atwix translate=&quot;label&quot;&gt;
            &lt;label&gt;Atwix Extensions&lt;/label&gt;
            &lt;sort_order&gt;150&lt;/sort_order&gt;
        &lt;/atwix&gt;
    &lt;/tabs&gt;    
&lt;/config&gt;</pre>
<p>As a result, you&#8217;ll get the new group (tab) in the admin settings. When you need to complete the procedure of adding settings you should add the following items: section, settings groups and the settings (fields) themselves:</p>
<pre class="brush: xml; gutter: true">&lt;config&gt;
    &lt;sections&gt;
        &lt;atwix_shoppingbar translate=&quot;label&quot; module=&quot;atwix_shoppingbar&quot;&gt;
            &lt;class&gt;separator-top&lt;/class&gt;
            &lt;label&gt;Shopping Bar&lt;/label&gt;
            &lt;tab&gt;atwix&lt;/tab&gt;
            &lt;sort_order&gt;130&lt;/sort_order&gt;
            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
            &lt;groups&gt;
                &lt;quicksearch&gt;
                    &lt;label&gt;Quick search&lt;/label&gt;
                    &lt;frontend_type&gt;text&lt;/frontend_type&gt;
                    &lt;sort_order&gt;20&lt;/sort_order&gt;
                    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                    &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                    &lt;fields&gt;
                        &lt;quicksearch_enabled translate=&quot;label comment&quot;&gt;
                            &lt;label&gt;Enable Quick Search&lt;/label&gt;
                            &lt;comment&gt;&lt;![CDATA[Enable quick search block]]&gt;&lt;/comment&gt;
                            &lt;frontend_type&gt;select&lt;/frontend_type&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_yesno&lt;/source_model&gt;
                            &lt;sort_order&gt;1&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                        &lt;/quicksearch_enabled&gt;
                        &lt;results_count translate=&quot;label comment&quot;&gt;
                            &lt;label&gt;Results count&lt;/label&gt;
                            &lt;comment&gt;&lt;![CDATA[Quick search results count (min 1, max 20)]]&gt;&lt;/comment&gt;
                            &lt;frontend_type&gt;text&lt;/frontend_type&gt;
                            &lt;sort_order&gt;5&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                        &lt;/results_count&gt;
                    &lt;/fields&gt;
                &lt;/quicksearch&gt;
            &lt;/groups&gt;
        &lt;/atwix_shoppingbar&gt;
    &lt;/sections&gt;
&lt;/config&gt;</pre>
<p>Here is an illustration what means each of these terms:</p>
<p><img class="alignnone size-full wp-image-2557" alt="sections" src="http://www.atwix.com/wp-content/uploads/2013/01/sections.png" width="1250" height="556" /></p>
<p>Next question is how will the different settings in the xml config look like. As you already know, each setting is placed in the &lt;fields&gt; node, then follows the unique setting&#8217;s id and finally &#8211; setting&#8217;s attributes. Here is a small review of the most useful settings:</p>
<p><strong>Text field</strong></p>
<p>Simple input field for short text values:</p>
<p><img class="size-full wp-image-2556 alignnone" alt="text_field" src="http://www.atwix.com/wp-content/uploads/2013/01/text_field.png" width="609" height="31" /></p>
<pre class="brush: xml; gutter: true"> &lt;text_field translate=&quot;label&quot;&gt;
    &lt;label&gt;Text Field&lt;/label&gt;
    &lt;frontend_type&gt;text&lt;/frontend_type&gt;
    &lt;sort_order&gt;10&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/text_field&gt;</pre>
<p><strong>Textarea</strong></p>
<p>Wide input field for long text values:</p>
<p><img class="alignnone size-full wp-image-2555" alt="textarea" src="http://www.atwix.com/wp-content/uploads/2013/01/textarea.png" width="606" height="201" /></p>
<pre class="brush: xml; gutter: true">&lt;textarea translate=&quot;label&quot;&gt;
    &lt;label&gt;Textarea&lt;/label&gt;
    &lt;frontend_type&gt;textarea&lt;/frontend_type&gt;
    &lt;sort_order&gt;20&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/textarea&gt;</pre>
<p><strong>Drop down with Yes/No values</strong></p>
<p>Drop down menu with the values &#8220;Yes&#8221; and &#8220;No&#8221;. Commonly it is used as a flag for enabling/disabling something:</p>
<p><img class="alignnone size-full wp-image-2554" alt="dropdown_yesno" src="http://www.atwix.com/wp-content/uploads/2013/01/dropdown_yesno.png" width="582" height="31" /></p>
<pre class="brush: xml; gutter: true">&lt;enabled translate=&quot;label&quot;&gt;
    &lt;label&gt;Enabled&lt;/label&gt;
    &lt;frontend_type&gt;select&lt;/frontend_type&gt;
    &lt;source_model&gt;adminhtml/system_config_source_yesno&lt;/source_model&gt;
    &lt;sort_order&gt;1&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/enabled&gt;</pre>
<p><strong>Drop down with Enable/Disable values</strong></p>
<p>Almost the same as previous one, but instead of &#8220;Yes&#8221; and &#8220;No&#8221; you will get &#8220;Enable&#8221; and &#8220;Disable&#8221;:</p>
<p><img class="alignnone size-full wp-image-2551" alt="enableddisabled" src="http://www.atwix.com/wp-content/uploads/2013/01/enableddisabled.png" width="606" height="34" /></p>
<pre class="brush: xml; gutter: true">&lt;active translate=&quot;label&quot;&gt;
    &lt;label&gt;Enable/Disable&lt;/label&gt;
    &lt;frontend_type&gt;select&lt;/frontend_type&gt;
    &lt;sort_order&gt;40&lt;/sort_order&gt;
    &lt;source_model&gt;adminhtml/system_config_source_enabledisable&lt;/source_model&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/active&gt;</pre>
<p><strong>Drop down with custom values</strong></p>
<p>Drop down with the custom set of values, generated by source model:</p>
<p><img class="alignnone size-full wp-image-2553" alt="custom_dropdown" src="http://www.atwix.com/wp-content/uploads/2013/01/custom_dropdown.png" width="607" height="35" /></p>
<pre class="brush: xml; gutter: true">&lt;default translate=&quot;label&quot;&gt;
    &lt;label&gt;Select&lt;/label&gt;
    &lt;frontend_type&gt;select&lt;/frontend_type&gt;
    &lt;!-- Source model for countries list. For custom list you need to use your own source model --&gt;
    &lt;source_model&gt;adminhtml/system_config_source_country&lt;/source_model&gt;
    &lt;sort_order&gt;50&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/default&gt;</pre>
<p><strong>Multiselect with custom values</strong></p>
<p>Field with the ability to select few items at the same time:</p>
<p><img class="alignnone size-full wp-image-2550" alt="multiselect" src="http://www.atwix.com/wp-content/uploads/2013/01/multiselect.png" width="590" height="228" /></p>
<pre class="brush: xml; gutter: true">&lt;multiselect translate=&quot;label&quot;&gt;
    &lt;label&gt;Multiselect&lt;/label&gt;
    &lt;frontend_type&gt;multiselect&lt;/frontend_type&gt;
    &lt;!-- Source model for countries list. For custom list you need to use your own source model --&gt;
    &lt;source_model&gt;adminhtml/system_config_source_country&lt;/source_model&gt;
    &lt;sort_order&gt;60&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
    &lt;can_be_empty&gt;1&lt;/can_be_empty&gt;
&lt;/multiselect&gt;</pre>
<p><strong>File</strong></p>
<p>Allows to choose a file for uploading. In this example the file will be saved in var/uploads directory:</p>
<p><img class="alignnone size-full wp-image-2548" alt="file" src="http://www.atwix.com/wp-content/uploads/2013/01/file.png" width="601" height="52" /></p>
<pre class="brush: xml; gutter: true">&lt;file translate=&quot;label comment&quot;&gt;
    &lt;label&gt;File&lt;/label&gt;
    &lt;frontend_type&gt;file&lt;/frontend_type&gt;
    &lt;backend_model&gt;adminhtml/system_config_backend_file&lt;/backend_model&gt;
    &lt;upload_dir&gt;var/uploads&lt;/upload_dir&gt;
    &lt;sort_order&gt;70&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;0&lt;/show_in_website&gt;
    &lt;show_in_store&gt;0&lt;/show_in_store&gt;
&lt;/file&gt;</pre>
<p><strong>Time</strong></p>
<p>Is used to create three drop down menus for setting up the hours, minutes and seconds respectively:</p>
<p><img class="alignnone size-full wp-image-2552" alt="time" src="http://www.atwix.com/wp-content/uploads/2013/01/time.png" width="609" height="28" /></p>
<pre class="brush: xml; gutter: true">&lt;time translate=&quot;label comment&quot;&gt;
    &lt;label&gt;Time&lt;/label&gt;
    &lt;frontend_type&gt;time&lt;/frontend_type&gt;
    &lt;sort_order&gt;80&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/time&gt;</pre>
<p><strong>Editable items list</strong></p>
<p>Allows to add/remove text values for the setting:</p>
<p><img class="alignnone size-full wp-image-2547" alt="editable_list" src="http://www.atwix.com/wp-content/uploads/2013/01/editable_list.png" width="577" height="113" /></p>
<pre class="brush: xml; gutter: true">&lt;addresses&gt;
    &lt;label&gt;Blocked Email Addresses&lt;/label&gt;
    &lt;frontend_model&gt;atwix_emailblocker/adminhtml_addresses&lt;/frontend_model&gt;
    &lt;backend_model&gt;adminhtml/system_config_backend_serialized&lt;/backend_model&gt;
    &lt;sort_order&gt;90&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
    &lt;can_be_empty&gt;1&lt;/can_be_empty&gt;
&lt;/addresses&gt;</pre>
<p><strong>Heading</strong></p>
<p>Is used to entitle some settings inside the group:</p>
<p><img class="alignnone size-full wp-image-2549" alt="heading" src="http://www.atwix.com/wp-content/uploads/2013/01/heading.png" width="604" height="63" /></p>
<pre class="brush: xml; gutter: true">&lt;heading translate=&quot;label&quot;&gt;
    &lt;label&gt;Heading&lt;/label&gt;
    &lt;frontend_model&gt;adminhtml/system_config_form_field_heading&lt;/frontend_model&gt;
    &lt;sort_order&gt;90&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/heading&gt;</pre>
<p><strong>Dependent field</strong></p>
<p>It can be any field. The main purpose of this one &#8211; it&#8217;s to hide/show the field depending on the state of  some other field. In the following example the field depends on the field&#8217;s <em>enablemethod</em> state. If <em>enablemethod</em> value is 1 &#8211; dependent_field will appear and vice versa:</p>
<pre class="brush: xml; gutter: true">&lt;dependent_field translate=&quot;label&quot;&gt;
    &lt;label&gt;Dependent Field&lt;/label&gt;
    &lt;frontend_type&gt;textarea&lt;/frontend_type&gt;
    &lt;sort_order&gt;100&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
    &lt;depends&gt;
        &lt;enablemethod&gt;1&lt;/enablemethod&gt;
    &lt;/depends&gt;
&lt;/dependent_field&gt;</pre>
<p>There is also one interesting cheat. You are able to use javascript inside of the &lt;comment&gt;&lt;/comment&gt; node:</p>
<pre class="brush: xml; gutter: true">&lt;specificerrmsg translate=&quot;label&quot;&gt;
    &lt;label&gt;Displayed Error Message&lt;/label&gt;
    &lt;frontend_type&gt;textarea&lt;/frontend_type&gt;
    &lt;comment&gt;
    &lt;![CDATA[
        &lt;script type=&quot;text/javascript&quot;&gt;
            Event.observe(&#039;carriers_flatrate_active&#039;, &#039;change&#039;, function() {
                alert(&#039;Be careful with this one&#039;);
            })
        &lt;/script&gt;
    ]]&gt;
    &lt;/comment&gt;
    &lt;sort_order&gt;2013&lt;/sort_order&gt;
    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
&lt;/specificerrmsg&gt;</pre>
<p>It might be useful for changing field&#8217;s value depending on different credentials. We would not recommend you to use it very often there, especially for the big javascript code.</p>
<p>Moreover, as you might have noticed, there are some attributes like source_model for the custom drop downs or, all the more so, frontend model for editable list which may disappoint a bit. We are going to describe how to operate with these models in our next article, which will see the light in the nearest future. Thank you for reading us <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/system-settings/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating CSV files in Magento</title>
		<link>http://www.atwix.com/magento/create-csv-files/</link>
		<comments>http://www.atwix.com/magento/create-csv-files/#comments</comments>
		<pubDate>Tue, 15 Jan 2013 09:00:26 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[magento]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=2319</guid>
		<description><![CDATA[We would like to demonstrate the small example of the ability to generate and download CSV files in Magento.]]></description>
				<content:encoded><![CDATA[<p>There are many tools in Magento which allow you to view or generate and download different reports. So, we can conclude that Magento system has integrated tools for CSV and XML files generation. It might help in the situation when you need to generate a report for some feed or just export a list of structured data. We would like to demonstrate the small example that adds an ability to generate and download CSV files.<br />
Let&#8217;s assume that you have already created your custom extension and wish to add a CSV export functionality. If it&#8217;s not the case and you can&#8217;t guess how to create an extension, then you can always find the light in our previous articles, for example <a href="http://www.atwix.com/magento/add-category-attribute/">this one</a>. We called our extension Atwix_Tweaks so in the code examples below we will use this title.<br />
<span id="more-2319"></span><br />
As we said before, the file is being downloaded within some URL. Well, then we need to create the controller and corresponded method-action. In config.xml file add the section which will tell the system where our controller is located:</p>
<pre class="brush: xml; gutter: true">
   &lt;frontend&gt;
        &lt;routers&gt;
            &lt;atwix_tweaks&gt;
                &lt;use&gt;standard&lt;/use&gt;
                &lt;args&gt;
                    &lt;module&gt;Atwix_Tweaks&lt;/module&gt;
                    &lt;frontName&gt;mln&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/atwix_tweaks&gt;
        &lt;/routers&gt;
    &lt;/frontend&gt;
</pre>
<p>On the next step, we should create the controller itself (app/code/local/Atwix/Tweaks/controllers/IndexController.php):</p>
<pre class="brush: php; gutter: true">
class Atwix_Tweaks_IndexController extends Mage_Core_Controller_Front_Action
{
    /**
     * Returns generated CSV file
     */
    public function mlnProductsListAction()
    {
        $filename = &#039;mln.csv&#039;;
        $content = Mage::helper(&#039;atwix_tweaks/mln&#039;)-&gt;generateMlnList();

        $this-&gt;_prepareDownloadResponse($filename, $content);
    }
}
</pre>
<p>As you can see, the controller calls method generateMlnList() from helper &#8216;atwix_tweaks/mln&#8217;. What are we going to do next? Right, create the helper (app/code/local/Atwix/Tweaks/Helper/Mln.php):</p>
<pre class="brush: php; gutter: true">
class Atwix_Tweaks_Helper_Mln extends Mage_Core_Helper_Abstract
{
    /**
     * Contains current collection
     * @var string
     */
    protected $_list = null;

    public function __construct()
    {
        $collection = Mage::getModel(&#039;catalog/product&#039;)-&gt;getCollection()
            -&gt;addAttributeToSelect(&#039;*&#039;)
            -&gt;addAttributeToFilter(array(&#039;attribute&#039; =&gt; &#039;wight&#039;, &#039;gt&#039; =&gt; 2));

        $this-&gt;setList($collection);
    }

    /**
     * Sets current collection
     * @param $query
     */
    public function setList($collection)
    {
        $this-&gt;_list = $collection;
    }

    /**
     * Returns indexes of the fetched array as headers for CSV
     * @param array $products
     * @return array
     */
    protected function _getCsvHeaders($products)
    {
        $product = current($products);
        $headers = array_keys($product-&gt;getData());

        return $headers;
    }

    /**
     * Generates CSV file with product&#039;s list according to the collection in the $this-&gt;_list
     * @return array
     */
    public function generateMlnList()
    {
        if (!is_null($this-&gt;_list)) {
            $items = $this-&gt;_list-&gt;getItems();
            if (count($items) &gt; 0) {

                $io = new Varien_Io_File();
                $path = Mage::getBaseDir(&#039;var&#039;) . DS . &#039;export&#039; . DS;
                $name = md5(microtime());
                $file = $path . DS . $name . &#039;.csv&#039;;
                $io-&gt;setAllowCreateFolders(true);
                $io-&gt;open(array(&#039;path&#039; =&gt; $path));
                $io-&gt;streamOpen($file, &#039;w+&#039;);
                $io-&gt;streamLock(true);

                $io-&gt;streamWriteCsv($this-&gt;_getCsvHeaders($items));
                foreach ($items as $product) {
                    $io-&gt;streamWriteCsv($product-&gt;getData());
                }

                return array(
                    &#039;type&#039;  =&gt; &#039;filename&#039;,
                    &#039;value&#039; =&gt; $file,
                    &#039;rm&#039;    =&gt; true // can delete file after use
                );
            }
        }
    }
}
</pre>
<p>The helper uses Varien_Io_File class, integrated in Magento, to generate a custom CSV file. Generated file will be stored in the media folder and deleted before the controller sends header to the client side. If you don&#8217;t want to delete file, you can set parameter rm to false in the return statement. In the constructor (method __construct) you can use any collection you want (customers, orders, custom collections etc.). Also, you are able to pass the collection behind the constructor using method setList().<br />
I hope this small example will help you in your further development. If you have some suggestions or questions you can always place them here ⇩ <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/create-csv-files/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Filter products by attribute on a Magento CMS page</title>
		<link>http://www.atwix.com/magento/products-list-cms/</link>
		<comments>http://www.atwix.com/magento/products-list-cms/#comments</comments>
		<pubDate>Fri, 21 Dec 2012 08:30:58 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[customize]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[module]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=2165</guid>
		<description><![CDATA[Our article describes how to add products list that is filtered by some attribute to Magento CMS page.]]></description>
				<content:encoded><![CDATA[<p>Ability to create pages with custom content is a great feature provided by Magento. You can easily create a new page for your store and add text, html, images, different widgets there. But sometimes people want to have something non-trivial on their pages. Usually it means that you need to operate some knowledge before you&#8217;ll get an appropriate result. In this article we would like to suggest you a simple solution on how to place a products list, prefiltered by some specific attribute, on your CMS page. The example below describes how to create a simple extension for this purpose.<br />
<span id="more-2165"></span><br />
Let&#8217;s call the extension <em>Atwix_Cmsattr</em>. First, you need to add the init file for you extension. The path is app/etc/modules/Atwix_Cmsattr.xml . The file&#8217;s content is:</p>
<pre class="brush: xml; gutter: true">&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_Cmsattr&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Atwix_Cmsattr&gt;
    &lt;/modules&gt;
&lt;/config&gt;</pre>
<p>The extension contains one block class and one model, therefore the config file, which you should have by the following path: <em>app/code/local/Atwix/Cmsattr/etc/config.xml</em>, is pretty simple and consists of a few records:</p>
<pre class="brush: xml; gutter: true">&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_Cmsattr&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Atwix_Cmsattr&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;atwix_cmsattr&gt;
                &lt;class&gt;Atwix_Cmsattr_Block&lt;/class&gt;
            &lt;/atwix_cmsattr&gt;
        &lt;/blocks&gt;
        &lt;models&gt;
            &lt;atwix_cmsattr&gt;
                &lt;class&gt;Atwix_Cmsattr_Model&lt;/class&gt;
            &lt;/atwix_cmsattr&gt;
        &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;</pre>
<p>After that, create the block class <em>app/code/local/Atwix/Cmsattr/Block/List.php</em>:</p>
<pre class="brush: php; gutter: true">&lt;?php
class Atwix_Cmsattr_Block_List extends Mage_Catalog_Block_Product_Abstract
{
    protected $_itemCollection = null;

    public function getItems()
    {
        $color = $this-&gt;getColor();
        if (!$color)
            return false;
        if (is_null($this-&gt;_itemCollection)) {
            $this-&gt;_itemCollection = Mage::getModel(&#039;atwix_cmsattr/products&#039;)-&gt;getItemsCollection($color);
        }

        return $this-&gt;_itemCollection;
    }
}</pre>
<p>and the model class <em>app/code/local/Atwix/Cmsattr/Model/Products.php</em>:</p>
<pre class="brush: php; gutter: true">&lt;?php
class Atwix_Cmsattr_Model_Products extends Mage_Catalog_Model_Product
{
    public function getItemsCollection($valueId)
    {
        $collection = $this-&gt;getCollection()
            -&gt;addAttributeToSelect(&#039;*&#039;)
            -&gt;addAttributeToFilter(&#039;color&#039;, array(&#039;eq&#039; =&gt; $valueId));
        Mage::getSingleton(&#039;cataloginventory/stock&#039;)-&gt;addInStockFilterToCollection($collection);
        return $collection;
    }
}</pre>
<p>The next file is the most personal thing. You need the template file with your own mockup corresponding to your design. Here is an example for a simple list (<em>app/design/frontend/base/default/template/atwix/cmsattr/list.phtml</em>):</p>
<pre class="brush: php; gutter: true">&lt;?php $_items = $this-&gt;getItems() ?&gt;
&lt;div class=&quot;block&quot;&gt;
    &lt;div class=&quot;block-title&quot;&gt;
        &lt;strong&gt;&lt;span&gt;&lt;?php echo $this-&gt;__(&#039;Red Products&#039;) ?&gt;&lt;/span&gt;&lt;/strong&gt;
    &lt;/div&gt;
    &lt;div class=&quot;block-content&quot;&gt;
        &lt;ol class=&quot;mini-products-list&quot;&gt;
        &lt;?php foreach ($_items as $_item): ?&gt;
            &lt;li class=&quot;item&quot;&gt;
                &lt;div class=&quot;product&quot;&gt;
                    &lt;a href=&quot;&lt;?php echo $_item-&gt;getProductUrl() ?&gt;&quot; title=&quot;&lt;?php echo $this-&gt;htmlEscape($_item-&gt;getName()) ?&gt;&quot; class=&quot;product-image&quot;&gt;&lt;img src=&quot;&lt;?php echo $this-&gt;helper(&#039;catalog/image&#039;)-&gt;init($_item, &#039;thumbnail&#039;)-&gt;resize(50) ?&gt;&quot; width=&quot;50&quot; height=&quot;50&quot; alt=&quot;&lt;?php echo $this-&gt;htmlEscape($_item-&gt;getName()) ?&gt;&quot; /&gt;&lt;/a&gt;
                    &lt;div class=&quot;product-details&quot;&gt;
                        &lt;p class=&quot;product-name&quot;&gt;&lt;a href=&quot;&lt;?php echo $_item-&gt;getProductUrl() ?&gt;&quot;&gt;&lt;?php echo $this-&gt;htmlEscape($_item-&gt;getName()) ?&gt;&lt;/a&gt;&lt;/p&gt;
                        &lt;?php echo $this-&gt;getPriceHtml($_item, true) ?&gt;
                        &lt;?php if ($this-&gt;helper(&#039;wishlist&#039;)-&gt;isAllow()) : ?&gt;
                        &lt;a href=&quot;&lt;?php echo $this-&gt;getAddToWishlistUrl($_item) ?&gt;&quot; class=&quot;link-wishlist&quot;&gt;&lt;?php echo $this-&gt;__(&#039;Add to Wishlist&#039;) ?&gt;&lt;/a&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/li&gt;
        &lt;?php endforeach; ?&gt;
        &lt;/ol&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>The last thing you need to do is to create a CMS page and insert the products list where you want to show it on the page. So, go to Admin-&gt;CMS-&gt;Pages-&gt;Add New Page. Fill the page with the necessary content and connect our products block anywhere in the content by putting the following string:</p>
<pre class="brush: php; gutter: true">{{block type=&quot;atwix_cmsattr/list&quot; name=&quot;cmsattr&quot; template=&quot;atwix/cmsattr/list.phtml&quot; color=&quot;26&quot;}}</pre>
<p>Note, that you need to pass the attribute value for color here. The product list on this page is filtered by this value. If you going to filter product by text attribute, such as &#8220;<em>name</em>&#8221; for example, you can pass the text value directly like <em>name=&#8221;Apple&#8221;</em>. But current example describes how to filter by attribute with type <em>select</em>. There are many ways to get value id from attribute&#8217;s value text. One of the simple (non programmatically) ways to do this is to inspect attributes values form using your browser. The example below describes how to do it within Google Chrome:</p>

<a href='http://www.atwix.com/magento/products-list-cms/attachment/screen-shot-2012-12-12-at-4-02-48-pm/' title='Screen Shot 2012-12-12 at 4.02.48 PM'><img width="150" height="150" src="http://www.atwix.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-12-at-4.02.48-PM-150x150.png" class="attachment-thumbnail" alt="Screen Shot 2012-12-12 at 4.02.48 PM" /></a>
<a href='http://www.atwix.com/magento/products-list-cms/attachment/screen-shot-2012-12-12-at-4-03-01-pm/' title='Screen Shot 2012-12-12 at 4.03.01 PM'><img width="150" height="70" src="http://www.atwix.com/wp-content/uploads/2012/12/Screen-Shot-2012-12-12-at-4.03.01-PM-150x70.png" class="attachment-thumbnail" alt="Screen Shot 2012-12-12 at 4.03.01 PM" /></a>

<p>Also you can extend your model&#8217;s logic with the new method, which would transform attribute value text into it&#8217;s id, but this small article doesn&#8217;t describe how to do it <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
In the next articles we are going to tell how to use layered navigation (filters) for products on CMS pages.<br />
Feel free to ask the questions and good luck in your coding experiments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/products-list-cms/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Grid filter for columns with complex values</title>
		<link>http://www.atwix.com/magento/grid-filter-for-columns/</link>
		<comments>http://www.atwix.com/magento/grid-filter-for-columns/#comments</comments>
		<pubDate>Mon, 10 Dec 2012 09:51:44 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[customize]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[order]]></category>
		<category><![CDATA[request]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=2066</guid>
		<description><![CDATA[When you need to add column with complex value processed by renderer it will be useful to look throught our new article which offers some tips according to this topic.]]></description>
				<content:encoded><![CDATA[<p>In previous <a href="http://www.atwix.com/tag/grid/" title="grids">articles</a> we told you how to operate with columns in adminhtml grids. Usually the process is quite fast, for example, if you want to add simple column from the database. But sometimes you need to add column with complex value, processed by renderer. You say: &#8220;<em>it&#8217;s not a big deal to use renderers…</em>&#8221; Right, until you face with sort and filter..<br />
<span id="more-2066"></span><br />
By default Magento applies grid filter directly to the corresponding column. But renderer might contain data from separate columns. At this point we need to choose right way to make filter and sort work correctly.<br />
For example, we are going to add a new column &#8220;<em>Address</em>&#8221; to the orders grid which consists of the values from few columns: <em>city, street, postcode</em>.<br />
First of all, we should join address table to the collection:</p>
<pre class="brush: php; gutter: true">
$collection-&gt;joinLeft(
                array(&#039;sales_flat_order_address&#039;),
                &#039;sales_flat_order.billing_address_id = sales_flat_order_address.entity_id&#039;,
                array(&#039;postcode&#039;, &#039;street&#039;, &#039;city&#039;);
</pre>
<p>The second step is to add address column to the grid:</p>
<pre class="brush: php; gutter: true">
addColumn(&#039;address&#039;, array(
          &#039;header&#039;=&gt; Mage::helper(&#039;sales&#039;)-&gt;__(&#039;Address&#039;),
          &#039;type&#039;  =&gt; &#039;text&#039;,
));
</pre>
<p>Here we should connect column with the data. Let&#8217;s add &#8216;<em>renderer</em>&#8216; param:</p>
<pre class="brush: php; gutter: true">
addColumn(&#039;address&#039;, array(
          &#039;header&#039;=&gt; Mage::helper(&#039;sales&#039;)-&gt;__(&#039;Address&#039;),
          &#039;type&#039;  =&gt; &#039;text&#039;,
          &#039;index&#039; =&gt; &#039;city&#039;
	  &#039;renderer&#039; =&gt; &#039;Atwix_Ordersgrid_Block_Adminhtml_Sales_Order_Renderer_Address&#039;
));
</pre>
<p>Third, create the renderer: </p>
<pre class="brush: php; gutter: true">
class Atwix_Ordersgrid_Block_Adminhtml_Sales_Order_Renderer_Address
    extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
    public function render(Varien_Object $row)
    {
        $value = $row-&gt;getData(&#039;city&#039;) . &#039;,&#039; .
            $row-&gt;getData(&#039;street&#039;) . &#039;,&#039; .
            $row-&gt;getData(&#039;postcode&#039;);

        return $value;
    }
}
</pre>
<p>After these steps we are able to see the new column in the orders grid. But when you try to use filter on this column &#8211; you will get the result, filtered by &#8216;city&#8217; db column, since we have added <em>city</em> as an index. To solve the problem we need to do one more thing: create callback method for the filter. The final view of <em>addColumn</em> calling is going to be like the following one: </p>
<pre class="brush: php; gutter: true">
$this-&gt;addColumn(&#039;address&#039;, array(
            &#039;header&#039;=&gt; Mage::helper(&#039;sales&#039;)-&gt;__(&#039;Address&#039;),
            &#039;type&#039;  =&gt; &#039;text&#039;,
		    &#039;renderer&#039; =&gt; &#039;Atwix_Ordersgrid_Block_Adminhtml_Sales_Order_Renderer_Address&#039;,
            &#039;filter_condition_callback&#039; =&gt; array($this, &#039;_addressFilter&#039;),
));
</pre>
<p>Note, that we have removed index field &#8211; we don&#8217;t need it anymore. And then, we create callback method which is described below:</p>
<pre class="brush: php; gutter: true">
protected function _addressFilter($collection, $column)
    {
        if (!$value = $column-&gt;getFilter()-&gt;getValue()) {
            return $this;
        }

        $this-&gt;getCollection()-&gt;getSelect()-&gt;where(
            &quot;sales_flat_order_address.city like ?
            OR sales_flat_order_address.street like ?
            OR sales_flat_order_address.postcode like ?&quot;
        , &quot;%$value%&quot;);


        return $this;
    }
</pre>
<p>As you can see, we are using simple db query condition to filter query results by the columns. This way you can create your own filters for columns with complex values or custom renderers.<br />
Feel free to ask any questions and suggest your own improvements. <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/grid-filter-for-columns/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Advices and Best Practices for Magento developers &#124; Part 2</title>
		<link>http://www.atwix.com/magento/best-practices-2/</link>
		<comments>http://www.atwix.com/magento/best-practices-2/#comments</comments>
		<pubDate>Mon, 26 Nov 2012 10:37:12 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[modules]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=1966</guid>
		<description><![CDATA[Magento is one of the most powerful and flexible shopping cart engines and we continue to share our best practices with the Magento community.]]></description>
				<content:encoded><![CDATA[<p>We continue to share our experience with Magento developers by publishing the next set of Best Practices in Magento coding. If you missed our previous article, <a href="http://www.atwix.com/magento/best-practices/">here it is</a>.<br />
<span id="more-1966"></span></p>
<p><strong><em>Local or community code pool.</em></strong></p>
<p>Pretty often we face with the discussion about choosing a proper code pool. So, let&#8217;s talk about the difference. Local pool has the highest load priority and code in this pool can&#8217;t be overridden as easy as in community or core pools. But depending on the Magento ideology, local pool was primarily designed for local changes. If you own a website and make modifications for that website, then your modifications are classified as local and your changes should be made in the app/code/local folder. Also, when you do some custom work on the website &#8211; local code pool is for you. However, if the extension is used by many other customers, this extension is not local but shared with a (limited) community. Therefore, the extension belongs to the community pool.<br />
Provided that you are an extension developer, you shouldn&#8217;t prevent overriding your files by other developers for the purpose of making some small changes. That can always be done by using the local pool.</p>
<p><strong><em>Where to store the JS files in Magento?</em></strong></p>
<p>Usually developers choose one of the following paths to store JS files (we are talking about frontend):</p>
<pre class="brush: bash; gutter: true">
js
</pre>
<p>or</p>
<pre class="brush: bash; gutter: true">
skin/frontend/package/theme/js
</pre>
<p>Actually, you should think twice at this point. As we&#8217;ve told above, one of the major Magento ideas is modularity. Therefore, as a good developer you should allow third party developers to make small changes/customizations without a need to edit your code wherever it&#8217;s possible. If your JS files are located in the skins folder, other developers are always able to change something by copying JS files into their own theme&#8217;s folder. But if you use the root JS directory, they won&#8217;t be able to do that.</p>
<p><strong><em>Controllers and common logic.</em></strong></p>
<p>One of the common Magento problems is tons of logic in the controllers where it shouldn&#8217;t be. For exemple, let&#8217;s explore the core file <em>app/code/core/Mage/Customer/controllers/AccountController.php</em>. Look at the <em>createPostAction()</em> method and you will see a lot of operations there. Why not to use a helper to store this logic or some abstract class? It allows other developers to extend the logic for their own purposes easily. For example, if you need to add a new customer programmatically and you want to use a standard set of methods for this, you won&#8217;t be able to do it, because most of the logic is located in the controller. Hence, we think it would be a good practice to use more extendable structures for common logic instead of hardcoding it in the controllers.</p>
<p><strong><em>Dispatched events.</em></strong></p>
<p>There&#8217;s yet another way to improve the quality of your extensions using dispatched events. Dispatcher is a Magento integrated system, which allows you to set some &#8220;point&#8221; with the unique name and some necessary parameters where you can integrate our logic &#8220;on the fly&#8221;. In other words, you can create your own events in your logic. Then, you or other developers are able to catch these events and connect some handlers to the events. It&#8217;s always useful to have dispatched events in the extensions, because it provides you an ability to extend your code more effectively in the future and allows other developers to interact with your logic in intelligent way. Events are usually dispatched in models and controllers. It is good to know, that it is enough to use the following construction in your code to dispatch an event:</p>
<pre class="brush: php; gutter: true">
Mage::dispatchEvent(&#039;the_unique_name&#039;, array(&#039;var&#039; =&gt; $data));
</pre>
<p>As the second argument, you should pass the data, that you want to send to the observer&#8217;s method (some id or some object instance for example).</p>
<p><strong><em>DB queries profiler:</em></strong></p>
<p>Magento provides an ability for developers to track database queries. For this purpose you should use a built in DB resource profiler. It can help you to inspect database queries, detect the longest query, detect the slowest query, etc.. Here is a small example on how to use a DB profiler for your own needs :</p>
<pre class="brush: php; gutter: true">
$profiler = Mage::getSingleton(&#039;core/resource&#039;)-&gt;getConnection(&#039;core_write&#039;)-&gt;getProfiler();
foreach ($profiler-&gt;getQueryProfiles() as $query) {
    $queryTime[] = $query-&gt;getElapsedSecs(); // Get the query execution time
    $queryRaw[] = $query-&gt;getQuery(); // Get the query text
}
</pre>
<p>We would be glad to read your suggestions in the comments, so feel free to post them <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/best-practices-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adding a column to the customers grid in Magento admin. Alternative way</title>
		<link>http://www.atwix.com/magento/add-column-to-customers-grid-alternative-way/</link>
		<comments>http://www.atwix.com/magento/add-column-to-customers-grid-alternative-way/#comments</comments>
		<pubDate>Wed, 07 Nov 2012 09:27:24 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[customize]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[magento]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=1856</guid>
		<description><![CDATA[This article presents the alternative way of adding a column to the customers grid in Magento admin.]]></description>
				<content:encoded><![CDATA[<p>Pretty often we face a task, where we need to add a custom column to the customers/orders grid in Magento admin. The solution is simple and if you google for it, you will get tons of solutions. However, pretty much all of them describe the same way, which isn&#8217;t always proper. <span id="more-1856"></span><br />
Nick described the simple and trivial way of adding columns in his article <a title="Adding a custom attribute/column to the orders grid in Magento admin" href="http://www.atwix.com/magento/customize-orders-grid/" target="_blank">Adding a custom attribute/column to the orders grid in Magento admin</a> and you are always able to follow it, except the cases, when some other extension already overrides the <em>_prepareColumns()</em> method. At that point, we need some universal solution that won&#8217;t conflict with other extensions that may potentially be overwriting the grid block. So, let&#8217;s use an observer for our task.<br />
First of all, you need to add your own extension for registering the observer. Create config files and other necessary stuff:</p>
<p>&nbsp;</p>
<p>Config to load the extension (<em>app/etc/modules/Atwix_CustomGrid.xml</em>):</p>
<pre class="brush: xml; gutter: true">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_CustomGrid&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Atwix_CustomGrid&gt;
    &lt;/modules&gt;
&lt;/config&gt;</pre>
<p>&nbsp;</p>
<p>The extension config file (<em>app/code/local/Atwix/CustomGrid/etc/config.xml</em>):</p>
<pre class="brush: xml; gutter: true">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_CustomGrid&gt;
            &lt;version&gt;0.4.0&lt;/version&gt;
        &lt;/Atwix_CustomGrid&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;atwix_customgrid&gt;
                &lt;class&gt;Atwix_CustomGrid_Model&lt;/class&gt;
            &lt;/atwix_customgrid&gt;
        &lt;/models&gt;
    &lt;/global&gt;
    &lt;adminhtml&gt;
        &lt;events&gt;
            &lt;core_block_abstract_prepare_layout_before&gt;
                &lt;observers&gt;
                    &lt;customgrid_column_append&gt;
                        &lt;type&gt;model&lt;/type&gt;
                        &lt;class&gt;Atwix_CustomGrid_Model_Observer&lt;/class&gt;
                        &lt;method&gt;appendCustomColumn&lt;/method&gt;
                    &lt;/customgrid_column_append&gt;
                &lt;/observers&gt;
            &lt;/core_block_abstract_prepare_layout_before&gt;
        &lt;/events&gt;
    &lt;/adminhtml&gt;
&lt;/config&gt;</pre>
<p>&nbsp;</p>
<p>The observer itself (<em>app/code/local/Atwix/CustomGrid/Model/Observer.php</em>):</p>
<pre class="brush: php; gutter: true">class Atwix_CustomGrid_Model_Observer extends Varien_Event_Observer
{
    /**
     * Adds column to admin customers grid
     *
     * @param Varien_Event_Observer $observer
     * @return Atwix_CustomGrid_Model_Observer
     */
    public function appendCustomColumn(Varien_Event_Observer $observer)
    {
        $block = $observer-&gt;getBlock();
        if (!isset($block)) {
            return $this;
        }

        if ($block-&gt;getType() == &#039;adminhtml/customer_grid&#039;) {
            /* @var $block Mage_Adminhtml_Block_Customer_Grid */
            $block-&gt;addColumnAfter(&#039;middlename&#039;, array(
                &#039;header&#039;    =&gt; &#039;Middle Name&#039;,
                &#039;type&#039;      =&gt; &#039;text&#039;,
                &#039;index&#039;     =&gt; &#039;middlename&#039;,
            ), &#039;email&#039;);
        }
    }
}</pre>
<p>&nbsp;</p>
<p>As you can see, the observer retrieves the customer grid block and executes its method addColumnAfter for adding a new column. The column type is &#8220;text&#8221; and the index is &#8220;middlename&#8221;. &#8220;Middlename&#8221; &#8211; it&#8217;s standard customer&#8217;s attribute in Magento, but you are able to add any custom attribute using this way.<br />
The advantage of this method: your code won&#8217;t conflict with other third party solutions that also add custom columns. You can use the observer for adding a column to almost any grid in Magento admin. All you need is to change the following condition:</p>
<pre class="brush: php; gutter: true">$block-&gt;getType() == &#039;adminhtml/customer_grid&#039;)</pre>
<p>depending on your grid block. For example, order&#8217;s grid block is <em>adminhtml/sales_order_grid</em>.<br />
Good luck and do not hesitate to ask your questions in comments below <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/add-column-to-customers-grid-alternative-way/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Proper way of adding tabs to the Magento Product Page</title>
		<link>http://www.atwix.com/magento/adding-tabs-on-the-product-page/</link>
		<comments>http://www.atwix.com/magento/adding-tabs-on-the-product-page/#comments</comments>
		<pubDate>Tue, 16 Oct 2012 11:36:44 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=1685</guid>
		<description><![CDATA[The product page is one of the most important parts of your store and this article describes how to add a tabs functionality to it.]]></description>
				<content:encoded><![CDATA[<p>The product page is one of the most important parts of your store. That&#8217;s why so much attention is paid to make this page look perfect.<br />
Tabs is a good way to display a lot of data inside a compact block. It helps to avoid huge scroll bars and also looks much nicer on portable devices. You can find tons of Magento templates with tabs on the product view page and we are going to tell you the easiest way to add them there. All examples are applicable to the default Magento theme, but with practice you can use following methods to customize your own theme. <span id="more-1685"></span>First, go to your store theme folder and find there the following file <em>app/design/frontend/default/yourtheme/layout/catalog.xml</em>. If the file does not exist, you can always copy it from <em>app/design/frontend/base/default/layout/</em>. Note that your own theme can be located within a different path. In the file <em>catalog.xml</em>, find the section:</p>
<pre class="brush: xml; gutter: true">
&lt;!--
Product view
--&gt;

&lt;catalog_product_view translate=&quot;label&quot;&gt;
    &lt;block type=&quot;catalog/product_view&quot; name=&quot;product.info.options.wrapper.bottom&quot; as=&quot;product_options_wrapper_bottom&quot; template=&quot;catalog/product/view/options/wrapper/bottom.phtml&quot; translate=&quot;label&quot;&gt;
       &lt;label&gt;Bottom Block Options Wrapper&lt;/label&gt;
            &lt;action method=&quot;insert&quot;&gt;&lt;block&gt;product.tierprices&lt;/block&gt;&lt;/action&gt;
            &lt;block type=&quot;catalog/product_view&quot; name=&quot;product.clone_prices&quot; as=&quot;prices&quot; template=&quot;catalog/product/view/price_clone.phtml&quot;/&gt;
            &lt;action method=&quot;append&quot;&gt;&lt;block&gt;product.info.addtocart&lt;/block&gt;&lt;/action&gt;
            &lt;action method=&quot;append&quot;&gt;&lt;block&gt;product.info.addto&lt;/block&gt;&lt;/action&gt;
        &lt;/block&gt;
</pre>
<p>&nbsp;</p>
<p>After this section, insert the block below:</p>
<pre class="brush: xml; gutter: true">
&lt;block type=&quot;catalog/product_view_tabs&quot; name=&quot;product.info.tabs&quot; as=&quot;info_tabs&quot; template=&quot;catalog/product/view/tabs.phtml&quot;&gt;
    &lt;action method=&quot;addTab&quot; translate=&quot;title&quot; module=&quot;catalog&quot;&gt;
        &lt;alias&gt;description&lt;/alias&gt;
        &lt;title&gt;Description&lt;/title&gt;
        &lt;block&gt;catalog/product_view_description&lt;/block&gt;
        &lt;template&gt;catalog/product/view/description.phtml&lt;/template&gt;
    &lt;/action&gt;
    &lt;action method=&quot;addTab&quot; translate=&quot;title&quot; module=&quot;catalog&quot;&gt;
        &lt;alias&gt;additional&lt;/alias&gt;
        &lt;title&gt;Additional Information&lt;/title&gt;
        &lt;block&gt;catalog/product_view_attributes&lt;/block&gt;
        &lt;template&gt;catalog/product/view/attributes.phtml&lt;/template&gt;
    &lt;/action&gt;
&lt;/block&gt;
</pre>
<p>&nbsp;</p>
<p>As you can see the tabs are being added within the built in method &#8216;<em>addTab</em>&#8216;. In the <action> node, you can select your own block and phtml file which you expect to see inside the tab.<br />
In our example, we have added two tabs &#8216;Description&#8217; and &#8216;Additional Information&#8217;. Magento installation contains both phtml files so if you can&#8217;t find them in your own theme you can copy it from <em>app/design/frontend/base/default/template/catalog/product/view/</em>. First tab will contain the description of the product and second tab will be a list of additional product&#8217;s attributes. As we&#8217;ve already said you can add your own blocks as the tabs. Don&#8217;t forget to clean Magento cache after this operation. </p>
<p>Second, you need to copy the following file <em>app/design/frontend/default/modern/template/catalog/product/view/tabs.phtml</em> into <em>app/design/frontend/default/yourtheme/template/catalog/product/view/</em> . This file contains mockup for the tabs section.<br />
Third, you should add styles for the tabs. Go to your general css file (usually <em>skin/frontend/default/yourtheme/css/styles.css</em>) and add the lines below: </p>
<pre class="brush: css; gutter: true">
/* Product Tabs */
.product-tabs { margin-bottom:15px; border-bottom:1px solid #666; background:#f2f2f2 url(../images/bkg_tabs.gif) 0 100% repeat-x; height: 25px;}
.product-tabs li { float:left; border-right:1px solid #a4a4a4; border-left:1px solid #fff; font-size:1.1em; line-height:1em; }
.product-tabs li.first { border-left:0; }
.product-tabs li.last { border-right:0; }
.product-tabs a { display:block; padding:6px 15px; color:#444; }
.product-tabs a:hover { background-color:#ddd; text-decoration:none; color:#444; }
.product-tabs li.active a,
.product-tabs li.active a:hover { background-color:#666; font-weight:bold; color:#fff; }
.product-tabs-content h2 { display:none; font-size:12px; font-weight:bold; }
</pre>
<p>&nbsp;</p>
<p>Finally we have got to the last step. Go to the file <em>app/design/frontend/base/default/template/catalog/product/view.phtml</em> (if there&#8217;s no such file you should already know where to get it) and insert the following line somewhere you would like to see the tabs section: </p>
<pre class="brush: php; gutter: true">
&lt;?php echo $this-&gt;getChildHtml(&#039;info_tabs&#039;) ?&gt;
</pre>
<p>&nbsp;</p>
<p>That&#8217;s all. To be sure that everything going well try to clean up the cache after every step. Good luck and feel free to ask any of your questions. <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/adding-tabs-on-the-product-page/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using Mage Run tool to speed up development</title>
		<link>http://www.atwix.com/magento/using-mage-run-to-speed-up-development/</link>
		<comments>http://www.atwix.com/magento/using-mage-run-to-speed-up-development/#comments</comments>
		<pubDate>Tue, 02 Oct 2012 07:37:13 +0000</pubDate>
		<dc:creator>Alexander Turiak</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=1670</guid>
		<description><![CDATA[Mage Run is a command line tool which will greatly speed up your Magento development efforts]]></description>
				<content:encoded><![CDATA[<p>When starting Magento development, first thing you find out that in order to see the changes you have to clear the cache. There is also an option to disable the cache completely, but performance wise &#8211; it&#8217;s not a very smart move. As your experience on the system grows you are getting to know which exact cache to clear to see the changes, be it config, layout, FPC cache or any other. Nevertheless, these operations are pretty cumbersome as admin session times out from time to time. You may also know that enabling template hints is not a quick operation either.<br />
<span id="more-1670"></span><br />
Let me introduce a great tool which will simplify your life as a Magento developer and make it enjoyable: <a href="http://netz98.github.com/n98-magerun/" title="Mage Run" target="_blank">Mage Run</a>, which is being developed by Christian Münch. Installation of the tool is <a href="https://github.com/netz98/n98-magerun/wiki/Installation-and-Update" title="fairly easy" target="_blank">fairly easy</a>. This tool has loads of useful commands and when you get used to it you will not believe you&#8217;ve been doing all the actions from your Magento backend. There is <a href="https://github.com/netz98/n98-magerun/wiki/Commands" title="a list of all available commands" target="_blank">a list of all available commands</a> (which can be also displayed from tool itself by using command <code>n98-magerun.phar list</code>), but here we want to describe a few favourite combos from our own work flow.</p>
<p>&nbsp;</p>
<p>First one is useful when creating install and upgrade scripts. As you know, Magento checks if setup scripts need to be ran by checking module&#8217;s version which is in turn cached in the config cache. To test my newly created script we increase version of the module then issue <code>n98-magerun.phar cache:clean config</code> followed by <code>n98-magerun.phar system:run-setup-scripts</code>. If there are some errors or exceptions they will be displayed in the console, otherwise you will see &#8220;done.&#8221; and feel proud of yourself. <img src='http://www.atwix.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
<p>Next time-saving command is <code>n98-magerun.phar dev:module:create</code> which allows you in a matter of seconds to create module skeleton and register it in the system. That could take you good five minutes creating folders and configs manually.</p>
<p>&nbsp;</p>
<p>We also quite liked <code>n98-magerun.phar install</code> command, which allows quick installation of required Magento version together with appropriate sample data.</p>
<p>&nbsp;</p>
<p>Several useful commands were added just recently, they are <code>dev:module:rewrite:list</code> and <code>dev:module:rewrite:conflicts</code>. Modules rewrite conflicts &#8211; it was pretty hot topic on last <a href="http://mageconf.com" title="MageConf" target="_blank">MageConf</a> and now there is a simple way to diagnose your system for the rewrite issues.</p>
<p>&nbsp;</p>
<p>And here are a few toggler commands for the desert: <code>n98-magerun.phar dev:template-hints</code> and <code>n98-magerun.phar dev:profiler</code></p>
<p>&nbsp;</p>
<p>We&#8217;re now quite confident you have already downloaded the tool by this sentence or way earlier. Please, post your use-cases or questions in the comments below. Thanks to Christian for sharing this awesome tool and here is hoping that by using it your Magento team is getting more productive and happy!</p>
<p>&nbsp;</p>
<p>Afterword: to unlock new features and badges in the tool issue <code>n98-magerun.phar self-update</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/using-mage-run-to-speed-up-development/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Login as a customer from Magento admin</title>
		<link>http://www.atwix.com/magento/login-as-customer-from-admin/</link>
		<comments>http://www.atwix.com/magento/login-as-customer-from-admin/#comments</comments>
		<pubDate>Wed, 26 Sep 2012 06:10:16 +0000</pubDate>
		<dc:creator>Yaroslav Rogoza</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[grid]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[universal password]]></category>

		<guid isPermaLink="false">http://www.atwix.com/?p=1196</guid>
		<description><![CDATA[Often there are situations where customer has some issues while placing orders or making operations from the "My Account" section. At that point, an ability for admin to login as a customer and see what is wrong becomes very useful.]]></description>
				<content:encoded><![CDATA[<p>Often there are situations where customer has some issues while placing orders or making operations from the &#8220;My Account&#8221; section. At that point, an ability for admin to login as a customer and see what is wrong becomes very useful. <span id="more-1196"></span><br />
Sure, you can make a universal password logic, but that method has heavy security risks. Not so long ago, we&#8217;ve noticed that Magento has ability to load and use customer&#8217;s sessions different way. We will tell you how to create a simple extension for logging in as a customer from Magento admin.</p>
<p><strong><em>Step 1</em></strong></p>
<p>For example, let&#8217;s call our module <strong>Atwix_Ulogin</strong>. As always we must start by creating a module descriptor in <strong>app/etc/modules</strong> folder. So put the <strong>Atwix_Ulogin.xml</strong> file into this directory. The file will be with the following content:</p>
<pre class="brush: xml; gutter: true">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_Ulogin&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;community&lt;/codePool&gt;
        &lt;/Atwix_Ulogin&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</pre>
<p><strong><em>Step 2</em></strong></p>
<p>On the next step, we need to create a configuration file for our extension: </p>
<pre class="brush: xml; gutter: true">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Atwix_Ulogin&gt;
            &lt;version&gt;0.4.0&lt;/version&gt;
        &lt;/Atwix_Ulogin&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;adminhtml&gt;
                &lt;rewrite&gt;
                    &lt;customer_grid&gt;Atwix_Ulogin_Block_Adminhtml_Customer_Grid&lt;/customer_grid&gt;
                &lt;/rewrite&gt;
            &lt;/adminhtml&gt;
        &lt;/blocks&gt;
        &lt;helpers&gt;
            &lt;ulogin&gt;
                &lt;class&gt;Atwix_Ulogin_Helper&lt;/class&gt;
            &lt;/ulogin&gt;
        &lt;/helpers&gt;
    &lt;/global&gt;
    &lt;frontend&gt;
        &lt;routers&gt;
            &lt;ulogin&gt;
                &lt;use&gt;standard&lt;/use&gt;
                &lt;args&gt;
                    &lt;module&gt;Atwix_Ulogin&lt;/module&gt;
                    &lt;frontName&gt;ulogin&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/ulogin&gt;
        &lt;/routers&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</pre>
<p>Save this file as <strong>app/etc/community/Atwix/Ulogin/etc/config.xml</strong>.<br />
As you can see, we override customers grid block for admin panel to add new column. Then we tell system to use our custom router &#8216;ulogin&#8217; as an entry point for the user login.</p>
<p><strong><em>Step 3</em></strong></p>
<p>Now we need to create a controller. This controller will check allowed IP&#8217;s for autologin, register customer session and redirect to customer account. File should be placed into <strong>app/code/community/Atwix/Ulogin/controllers</strong>. The filename is <strong>LoginController.php</strong>.<br />
The content is:</p>
<pre class="brush: php; gutter: true">
&lt;?php
class Atwix_Ulogin_LoginController extends Mage_Core_Controller_Front_Action
{
    /**
     * Processes login action
     * @return bool
     * @throws Exception
     */
    public function autologinAction()
    {
        $session = $this-&gt;_getSession();
        if (!$this-&gt;_isAllowed()) {
            $message = $this-&gt;__(&#039;You have no pemission to use this option&#039;);
            $session-&gt;addError($message);
            $this-&gt;_redirect(&#039;customer/account/login&#039;);
        }
        else {
            $id = (int) trim($this-&gt;getRequest()-&gt;getParam(&#039;customerid&#039;));
            try{
                if($id){
                    $customer = Mage::getModel(&#039;customer/customer&#039;)-&gt;load($id);
                    $session-&gt;setCustomerAsLoggedIn($customer);
                    $message = $this-&gt;__(&#039;You are now logged in as %s&#039;, $customer-&gt;getName());
                    $session-&gt;addNotice($message);
                    Mage::log($message);
                }else{
                    throw new Exception ($this-&gt;__(&#039;The login attempt was unsuccessful. Some parameter is missing&#039;));
                }
            }catch (Exception $e){
                $session-&gt;addError($e-&gt;getMessage());
            }
            $this-&gt;_redirect(&#039;customer/account&#039;);
        }
    }

    /**
     * Gets customer session
     * @return Mage_Core_Model_Abstract
     */
    protected function _getSession()
    {
        return Mage::getSingleton(&#039;customer/session&#039;);
    }

    /**
     * Checks if ip is allowed for autologin
     * @return mixed
     */
    protected function _isAllowed()
    {
        $allowedIps = Mage::helper(&#039;ulogin&#039;)-&gt;getAllowedIps();
        return Mage::helper(&#039;ulogin&#039;)-&gt;checkAllowedIp($allowedIps);
    }
}
</pre>
<p>Also we need to create a helper file with useful methods </p>
<pre class="brush: php; gutter: true">
&lt;?php
class Atwix_Ulogin_Helper_Data extends Mage_Core_Helper_Abstract
{
    /**
     * Gets allowed ip-addresses from configuration
     * @return array
     */
    public function getAllowedIps()
    {
        $ipsList = array();
        $ipsText = &#039;127.0.0.1, 181.40.55.32&#039;; // Comma separated list of allowed IP  
        $ipsList = explode(&#039;,&#039;, $ipsText);
        array_walk($ipsList, &#039;trim&#039;);
        
        return $ipsList;
    }
    /**
     * Checks if remote ip is allowed
     * @param array $allowedList
     * @return bool
     */
    public function checkAllowedIp($allowedList)
    {
        if (count($allowedList) &gt; 0) {
            $remoteIp = Mage::helper(&#039;core/http&#039;)-&gt;getRemoteAddr();
            if (in_array($remoteIp, $allowedList))
                return true;
        }
        return false;
    }
}
</pre>
<p><strong>$ipsText</strong> variable contains comma separated list of IP addresses with allowed access to universal login ability.</p>
<p><strong><em>Step 4</em></strong></p>
<p>The last, but important step is to create an override for customers grid block in admin panel. Create file <strong>Grid.php</strong> at the location <strong>/app/code/community/Atwix/Ulogin/Block/Adminhtml/Customer</strong> with the following content:</p>
<pre class="brush: php; gutter: true">
class Atwix_Ulogin_Block_Adminhtml_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid
{
    protected function _prepareColumns()
    {
        parent::_prepareColumns();

        $column = $this-&gt;getColumn(&#039;action&#039;);
        $actions = $column-&gt;getActions();
        $actions[] = array(
            &#039;caption&#039; =&gt; &#039;Log in&#039;,
            &#039;popup&#039; =&gt; true,
            &#039;url&#039; =&gt; array(
             &#039;base&#039; =&gt; &#039;ulogin/login/autologin&#039;),
            &#039;field&#039; =&gt; &#039;customerid&#039;
        );
        $column-&gt;setActions( $actions );

        return $this;
    }
}
</pre>
<p>This method tells Magento to add one more item to Actions column &#8220;Login&#8221;.<br />
That&#8217;s all. You can try to go to <strong>Admin->Customers->Manage Customers</strong>. There will be a new action &#8216;Login&#8217; in Actions column. Choose this action brings a new popup window where you will be logged in as a customer.<br />
Do not forget to clean up Magento cache. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.atwix.com/magento/login-as-customer-from-admin/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
