<?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>Magento Design and Development &#187; Magento</title>
	<atom:link href="http://inchoo.net/category/ecommerce/magento/feed/" rel="self" type="application/rss+xml" />
	<link>http://inchoo.net</link>
	<description>Magento Design and Magento Development Professionals - Inchoo</description>
	<lastBuildDate>Thu, 09 Feb 2012 23:57:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>No, this mail is not Junk, or how to properly configure Magento mailing</title>
		<link>http://inchoo.net/ecommerce/magento/fight-spam-emails/</link>
		<comments>http://inchoo.net/ecommerce/magento/fight-spam-emails/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 22:15:01 +0000</pubDate>
		<dc:creator>Branko Toic</dc:creator>
				<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[eMail]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=12451</guid>
		<description><![CDATA[First of all I&#8217;m not really a Magento developer nor its power user or any sort of user for that matter. My primary function is server administration and configuration for hosted web sites, Magento included. Like any good developer you &#8230;<p><a href="http://inchoo.net/ecommerce/magento/fight-spam-emails/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>First of all I&#8217;m not really a Magento developer nor its power user or any sort of user for that matter. My primary function is server administration and configuration for hosted web sites, Magento included. Like any good developer you will be handling all the nifty custom code and the web site itself. However, when it comes to mailing, your application will format the mail message and forward it to the system based software to transfer your message via SMTP to its destination.<br />
<span id="more-12451"></span><br />
Whatever your mail is containing, I&#8217;m pretty sure it is important that this mail reach its destination regardless who you are; a web site owner, developer or its end user.</p>
<p>From my perspective, and years of mail delivery debugging I will try to share some helpful tips on how to properly configure your Magento and server environment so that your mails do arrive on its destination.</p>
<h2>Configuring Magento</h2>
<p>Ok, let&#8217;s start with easy part, the part that you as a developers are most comfortable and familiar with. Magento by default is using built in PHP <em>mail()</em> function to send e-mails. Commonly some important settings are left at their default values in Magento admin, and are often overlooked or forgotten.  By default most people are just configuring default mail sending address in Magento, and stop at that. This will only set the <em>&lt;from: &gt;</em> e-mail address in <em>$additional_headers</em> field for <em>mail()</em> function. This will indeed put a mail from address in recipients inbox to your mail address but if we inspect the mail headers and server logs actual sending e-mail address will be something like <em>apache@servername.com</em>. This alone will be reason enough for some spam filters to classify that mail as spam since <em>mail-from</em> and <em>envelope-from</em> will be <em>apache@servername.com</em> and <em>&lt;from:&gt;</em> headers will be your configured e-mail address.</p>
<p>In this case I&#8217;ve used <em>apache@servername.com</em> as a &#8220;true&#8221; senders address but this may vary, depending on how your web server is configured.</p>
<p>Additionally, <strong>you will not receive bounced undeliverable mails</strong>. They will be forwarded to the actual sending user, and you will not know what mails you need to remove from your mailing list, what mails you should resend etc. In the former case if you continue to send mails to undeliverable e-mail addresses, <strong>some systems may interpret this as a dictionary spam attack attempts and may stop receiving even legitimate mails from your servers IP.</strong></p>
<p>To correct this problem PHP <em>mail()</em> function is accepting <em>$additional_parameters</em> in which we can set <em>mail-from</em> and <em>envelope-from</em> mail headers to same address as <em>&lt;from:&gt;</em> mail headers. Magento has this configuration option in its admin interface. Just log-in to your admin and navigate to <strong>advanced -&gt; system config</strong> and look for option set return path just set it on yes and Magento will add in <em>$additional_parameters</em> your configured mail address and this will corrects the <em>mail-from</em> and <em>envelope-from</em> mail headers.</p>
<h2>Configuring the server &#8211; part 1 (trusted users) </h2>
<p>Depending on your server setup, your Magento web may be running under apache/nobody user or under Unix user you have been assigned by your server admin. In either case you must ensure that this user is trusted by your mail server software.</p>
<p>What do I mean by this? Well just sending the <em>$additional_parameters</em> to <em>mail()</em> function is <strong>not enough</strong>. Most mail servers have built in protection for mail forgery and are by default disallowing overrides on <em>mail-from</em> and <em>envelope-from</em> headers via <em>$additional_parameters</em>. You must make sure that user under which Magento is run is in mail servers <strong>trusted users list</strong>. Only then this method of setting return path in Magento admin will work.</p>
<p>If you are by some chance on some <strong>cPanel</strong> powered server, this will be by default turned on. But if you are hosted on somewhat custom configured dedicated server this option must be set by your system administrator.</p>
<p>I&#8217;m not saying necessarily that <strong>cPanel</strong> hosting is in this case better choice for your Magento, some custom dedicated server setups can be and are more configurable and tunable for performance.</p>
<p>In any case, if you are running <strong>Exim</strong> as your MTA you will need to configure:</p>
<pre class="brush: php; title: ; notranslate">
trusted_users = apache
</pre>
<p>in <strong>/etc/exim/exim.conf</strong>. You can add additional trusted users by separating them with:</p>
<pre class="brush: php; title: ; notranslate">trusted_users = apache : unixuser : unixuser2</pre>
<p>For <strong>Sendmail</strong> MTA you can add trusted users in <strong>/etc/mail/trusted-users</strong></p>
<p>Your mail server may vary so please consult your manual or your system administrator. At this point you should have mail headers sorted out.</p>
<h2>Configuring the server &#8211; part 2 (mail limits)</h2>
<p>On most hosting systems or rented dedicated servers you will by default have some sort of <strong>hourly mail limit</strong>. This is nowadays common practice among system administrators, especially for shared hosting servers, to limit the bulk spam mailing either from users itself or from malicious scripts which are unauthorized on the system. Limits work on principle of limiting each user account on how many mails they can send in one hour. If for example this limit is set to <strong>100 mails/h</strong> and you have <strong>200 purchases/h</strong>, last <strong>100</strong> of your users <strong>will not get their mail</strong>. This will be instead bounced to your sending address (now this is why we need to configure return path correctly). Try to find out with your provider and/or system administrator if there is such limit in place, and if it can be customized for your site. This should be pretty trivial thing to do. Further more <strong>keep track of your mails sent per hour</strong> and if you are close to the hourly limit, talk to your administrator again.</p>
<h2>Configuring the server &#8211; part 3 (sending address)</h2>
<p><img src="http://inchoo.net/wp-content/uploads/2012/02/junk-email.jpg" alt="Junk eMails" title="Is your address valid?" width="300" height="200" class="alignright size-full wp-image-12479" />Ensure that e-mail address from which you are sending your mails <strong>actually exists</strong> on your server. Some of the remote mail servers will try to perform &#8220;<strong>Sender verification call-out</strong>&#8220;.</p>
<p>What does this means? When your mail arrives on its destination mail server, the receiving server, before accepting that mail, will communicate with your sending server and will try to determine <strong>if your mail address actually exists</strong>. If it does not, remote server will just <strong>discard</strong> this mail and<strong> it will bounce back</strong> to your address. Well, if it doesn&#8217;t exists, you won&#8217;t get this bounce and will not even be aware there is a problem until some end user reports this as an issue.</p>
<h2>Configuring the server &#8211; part 4 (server domain)</h2>
<p>As one of the spam filtering rules, most remote mail servers will check your server&#8217;s IP address and its DNS records.</p>
<p>Make sure your server&#8217;s FQDN is properly configured, both in your mail server and in your DNS. Additionally make sure that your server&#8217;s PTR records are set strait.</p>
<p>PTR records are reverse IP to hostname DNS records and should point to your hostname. Your hostname DNS record should also point to the same IP address so that circle is complete. <strong>Some remote mail servers which cannot verify your PTR and hostname will just refuse to accept your mails.</strong></p>
<h2>Configuring your domain</h2>
<p>In recent years as additional spam protection several new methods are implemented to verify sender&#8217;s identity. SPF domain records are one of them and most of the biggest mail providers (including Google, Yahoo and Hotmail) are checking them.</p>
<p>Not having the SPF records <strong>will not hurt your mail delivery</strong>, but having them configured will help in delivering your mails to inbox and not SPAM folders.</p>
<p>SPF is just a TXT DNS record which looks something like this (in a single line):</p>
<pre class="brush: php; title: ; notranslate">google.com descriptive text &quot;v=spf1 include:_netblocks.google.com
ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all&quot;
</pre>
<p>In this TXT record is a list of permitted mail servers for your domain. Meaning if mail claiming to be from your domain <strong>is not coming</strong> from this trusted list of mail servers, it&#8217;s not valid mail and <strong>is discarded</strong>.  But if mail claiming to be from your domain <strong>is coming</strong> from the listed servers, then this mail <strong>is verified</strong> as authentic and <strong>will not be classified as SPAM</strong>.</p>
<p>For some help in how to configure properly your SPF records you can use the online wizard at: <a title="SPF wizard" href="http://spfwizard.com/">http://spfwizard.com/</a></p>
<p>Besides SPF you may consider publishing DKIM records, but configuring them are is a topic for another post.</p>
<h2>Tracking your mail server reputation</h2>
<p>In addition to all above mentioned it is a good practice to track your mail server&#8217;s <strong>IP reputation</strong> at various RBL blacklists and <strong>respond quickly to any listings</strong>.</p>
<p>Having your mail server listed in some RBL lists <strong>will most definitely</strong> classify your mails as <strong>spam</strong> or even bounce them to the sender address.</p>
<p>You can query the RBL list database for your mail server IP at: <a title="RBL list check" href="http://www.dnsbl.info/dnsbl-database-check.php">http://www.dnsbl.info/dnsbl-database-check.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/fight-spam-emails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting selected simple product id in configurable product on client side.</title>
		<link>http://inchoo.net/ecommerce/magento/getting-selected-simple-product-id-in-configurable-product-on-client-side/</link>
		<comments>http://inchoo.net/ecommerce/magento/getting-selected-simple-product-id-in-configurable-product-on-client-side/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 09:23:11 +0000</pubDate>
		<dc:creator>Goran Sambolic</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[catalog]]></category>
		<category><![CDATA[configurable]]></category>
		<category><![CDATA[product]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=12355</guid>
		<description><![CDATA[If you need to get id of selected simple product in configurable product on client side you can do it in many different ways. Here is simple function how to achieve that with no code modification, new templates or even &#8230;<p><a href="http://inchoo.net/ecommerce/magento/getting-selected-simple-product-id-in-configurable-product-on-client-side/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>If you need to get id of selected simple product in configurable product on client side you can do it in many different ways.</p>
<p>Here is simple function how to achieve that with no code modification, new templates or even modules.<br />
Just one Javascript file and layout update.</p>
<p><span id="more-12355"></span></p>
<pre class="brush: jscript; title: ; notranslate">
Product.Config.prototype.getIdOfSelectedProduct = function()
{
     var existingProducts = new Object();

     for(var i=this.settings.length-1;i&gt;=0;i--)
     {
         var selected = this.settings[i].options[this.settings[i].selectedIndex];
         if(selected.config)
         {
         	for(var iproducts=0;iproducts&lt;selected.config.products.length;iproducts++)
         	{
         		var usedAsKey = selected.config.products[iproducts]+&quot;&quot;;
         		if(existingProducts[usedAsKey]==undefined)
         		{
         			existingProducts[usedAsKey]=1;
         		}
         		else
         		{
         			existingProducts[usedAsKey]=existingProducts[usedAsKey]+1;
         		}
             }
         }
     }

     for (var keyValue in existingProducts)
     {
     	for ( var keyValueInner in existingProducts)
         {
         	if(Number(existingProducts[keyValueInner])&lt;Number(existingProducts[keyValue]))
         	{
         		delete existingProducts[keyValueInner];
         	}
         }
     }

     var sizeOfExistingProducts=0;
     var currentSimpleProductId = &quot;&quot;;
     for ( var keyValue in existingProducts)
     {
     	currentSimpleProductId = keyValue;
     	sizeOfExistingProducts=sizeOfExistingProducts+1
     }

     if(sizeOfExistingProducts==1)
     {
    	 alert(&quot;Selected product is: &quot;+currentSimpleProductId)
     }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/getting-selected-simple-product-id-in-configurable-product-on-client-side/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding magento attribute with custom input renderer</title>
		<link>http://inchoo.net/ecommerce/magento/adding-magento-attribute-with-custom-input-renderer/</link>
		<comments>http://inchoo.net/ecommerce/magento/adding-magento-attribute-with-custom-input-renderer/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 10:33:31 +0000</pubDate>
		<dc:creator>Domagoj Potkoc</dc:creator>
				<category><![CDATA[Administration]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[frontend input renderer]]></category>
		<category><![CDATA[renderer]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=12250</guid>
		<description><![CDATA[This is example which will explain you, how to add new attribute with custom input render. You will be able to modify existing functionality, add javascript, some other option or change default input renderer by your wishes. You probably will &#8230;<p><a href="http://inchoo.net/ecommerce/magento/adding-magento-attribute-with-custom-input-renderer/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>This is example which will explain you, how to add new attribute with custom input render. You will be able to modify existing functionality, add javascript, some other option or change default input renderer by your wishes.<br />
<span id="more-12250"></span><br />
You probably will ask yourself, what is magento input renderer and I will explain. This is Magento php class which is in charge for &#8220;rendering&#8221; html form elements. In magento there are different classes for rendering, you can find them in next folder: <strong>/lib/Varien/Data/Form/Element</strong>. In this folder you will notice next classes for rendering: price, date, image and so on. </p>
<p>Let&#8217;s go with our example.</p>
<p>First of all, you should create magento setup file which will add new product attribute with custom frontend input render, example is below:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$installer = $this;

$installer-&gt;startSetup();

$installer-&gt;addAttribute(Mage_Catalog_Model_Product::ENTITY, 'example_field', array(
    'group'             =&gt; 'General',
    'type'              =&gt; 'text',
    'backend'           =&gt; '',
    'input_renderer'    =&gt; 'test/catalog_product_helper_form_example',//definition of renderer
    'label'             =&gt; 'Example field',
    'class'             =&gt; '',
    'global'            =&gt; Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE,
    'visible'           =&gt; true,
    'required'          =&gt; false,
    'user_defined'      =&gt; true,
    'searchable'        =&gt; false,
    'filterable'        =&gt; false,
    'comparable'        =&gt; false,
    'visible_on_front'  =&gt; false,
    'unique'            =&gt; false,
    'apply_to'          =&gt; 'simple,configurable,bundle,grouped',
    'is_configurable'   =&gt; false,
));

$installer-&gt;endSetup();
</pre>
<p>You can see that we are adding attribute with method <strong>&#8220;addAttribute&#8221;</strong>, variable <strong>&#8220;$installer&#8221;</strong> is instance of <strong>&#8220;Mage_Catalog_Model_Resource_Setup&#8221;</strong>, and frontend input rendere is defined in array <strong>&#8216;input_renderer&#8217; => &#8216;test/catalog_product_helper_form_example&#8217;</strong></p>
<p>Next step, you have to create your own input renderer. My example of renderer class (<strong>Inchoo_Test_Block_Catalog_Product_Helper_Form_Price</strong>) is below, this is very simple class, only for demonstration purpose.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class Inchoo_Test_Block_Catalog_Product_Helper_Form_Example extends Varien_Data_Form_Element_Text
{
    public function getAfterElementHtml()
    {
        $html = parent::getAfterElementHtml();
        return $html.&quot;  &lt;script&gt;
        				$('&quot;.$this-&gt;getHtmlId().&quot;').disable();
        				&lt;/script&gt;&quot;;
    }

}
</pre>
<p>In my example you can see that I added javascript code which disable input element, admin user can&#8217;t edit this field.<br />
I hope that is helpful <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/adding-magento-attribute-with-custom-input-renderer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Backorders Report Magento Extension</title>
		<link>http://inchoo.net/ecommerce/magento/backorders-report-magento-extension/</link>
		<comments>http://inchoo.net/ecommerce/magento/backorders-report-magento-extension/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 07:02:38 +0000</pubDate>
		<dc:creator>Dejan Radic</dc:creator>
				<category><![CDATA[Administration]]></category>
		<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Orders]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=12167</guid>
		<description><![CDATA[Recently, i had a request to display a list of all backorders. Backorders have to be grouped by Manufacturers, also should be option to filter backorders by manufacturers. In this article, I will present you the extension, which solved the &#8230;<p><a href="http://inchoo.net/ecommerce/magento/backorders-report-magento-extension/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Recently, i had a request to display a list of all backorders. Backorders have to be grouped by Manufacturers, also should be option to filter backorders by manufacturers.</p>
<p>In this article, I will present you the extension, which solved the above requirement.<br />
<span id="more-12167"></span><br />
Backorder report is placed under Reports menu.</p>
<p>Backorder report contains information about order such as: Order id, Purchased on, Customer, Order total. Backorder report also contains information about the order items such as: Name, Quantity on stock, Quantity in order, Undelivered quantity etc.</p>
<pre class="brush: php; title: ; notranslate">
public function getBackorderItems($orderId)
{
    $backOrderItems = Mage::getModel('sales/order_item')-&gt;getCollection()
        -&gt;addFieldToFilter('order_id', $orderId);

    $backOrderItems-&gt;getSelect()-&gt;join(
        array('sales_product_stock' =&gt; 'cataloginventory_stock_item'),
        'main_table.product_id = sales_product_stock.product_id',
        'qty'
        );

    $conditionsVarchar = array(
        'main_table.product_id = sales_product_manufacturer_varchar.entity_id',
        'sales_product_manufacturer_varchar.attribute_id = 102'
    );

    $backOrderItems-&gt;getSelect()-&gt;joinLeft(
        array('sales_product_manufacturer_varchar' =&gt; 'catalog_product_entity_varchar'),
        implode(' AND ', $conditionsVarchar),
        array('value_varchar' =&gt; 'value')
        );

    $conditionsInt = array(
        'main_table.product_id = sales_product_manufacturer_int.entity_id',
        'sales_product_manufacturer_int.attribute_id = 102'
    );

    $backOrderItems-&gt;getSelect()-&gt;joinLeft(
        array('sales_product_manufacturer_int' =&gt; 'catalog_product_entity_int'),
        implode(' AND ', $conditionsInt),
        array('value_int' =&gt; 'value')
        );

    return $backOrderItems;
}
</pre>
<p>For example:<br />
The customer has made an order that contains:<br />
Product name: “a”; Manufacturer: “x”; Qty: 10 (Qty on stock 20);<br />
Product name: “b”; Manufacturer: “y”; Qty: 10 (Qty on stock 5);<br />
Product name: “c”; Manufacturer: “z”; Qty: 10 (Qty on stock 15);</p>
<p>Backorder will be displayed on three place. In the group of manufacturer “x”, in the group of manufacturer “y” and in the group of manufacturer “z”.</p>
<p><a href="http://inchoo.net/wp-content/uploads/2012/01/backorder_report2.jpg"><img src="http://inchoo.net/wp-content/uploads/2012/01/backorder_report2-600x237.jpg" alt="backorder_report" title="backorder_report" width="600" height="237" class="alignnone size-medium wp-image-12178" /></a></p>
<p>Note: As you can assume, this extension will only work if your store allows backorders. To allow backorders go to: System &gt; Configuration &gt; Catalog &gt; Inventory &gt; Product Stock Options, and set Backorders =&gt; “Allow Qty bellow 0” or “Allow Qty bellow 0 and notify Customer”.</p>
<p>Extension is tested on Magento 1.6.2.0 CE. <a href="http://inchoo.net/wp-content/uploads/2012/01/Inchoo_Backorderreport.zip">Download extension</a>.</p>
<p>Cheers.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/backorders-report-magento-extension/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Custom Magento Events: Customer First Order</title>
		<link>http://inchoo.net/ecommerce/magento/custom-magento-events-customer-first-order/</link>
		<comments>http://inchoo.net/ecommerce/magento/custom-magento-events-customer-first-order/#comments</comments>
		<pubDate>Sat, 28 Jan 2012 11:09:20 +0000</pubDate>
		<dc:creator>Branko Ajzele</dc:creator>
				<category><![CDATA[Events & Observers]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[custom event]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[observer]]></category>
		<category><![CDATA[order]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=12190</guid>
		<description><![CDATA[Often you will stumble upon a case where Magento lacks certain events that you can easily observe. Various business cases can sometimes truly stretch the boundaries of even the best shopping carts like Magento. Luckily, creating or more properly said &#8230;<p><a href="http://inchoo.net/ecommerce/magento/custom-magento-events-customer-first-order/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Often you will stumble upon a case where Magento lacks certain events that you can easily observe. Various business cases can sometimes truly stretch the boundaries of even the best shopping carts like Magento. Luckily, creating or more properly said dispatching your own event in Magento is pretty straight forward task.<span id="more-12190"></span></p>
<p>Imagine the following business case, where your client, the merchant says: <em><strong>I need to give some reward points to Customer A who invited Customer B. These reward points will be assigned one time only and at the moment when Customer B creates it&#8217;s first order in the system</strong></em>.</p>
<p>Ideal scenario would be if you had the built in Magento event like &#8220;customer_first_order&#8221; or if you need more finer tuning to target the very state of the order, for example &#8220;customer_first_order_that_reached_state_complete&#8221;. Following along with the client requirement above, I will show you how you can easily make additional events with just some basic thinking invested into the whole process.</p>
<p>So where do we start? I will start from the built in &#8220;sales_order_save_after&#8221; event. Logically I need to do something after the order is created. From there I will do the logic that checks if this is customers first order or not. If you are new to Magento and you do a lookup/search on entire Magento installation code you will not find the expression <em>Mage::dispatchEvent(&#8216;sales_order_save_after&#8217;, array(&#8216;object&#8217;=>$this));</em> anywhere.</p>
<p>However you will find the defined values for <em>$_eventPrefix</em> and <em>$_eventObject</em> properties under the <em>Mage_Sales_Model_Order</em> class. Since <em>Mage_Sales_Model_Order</em> somewere down the line inherits from <em>Mage_Core_Model_Abstract</em> you can check it&#8217;s <em>_afterSave()</em> method and easily conclude that <em>sales_order_save_after</em> event comes from the expression <em>Mage::dispatchEvent($this->_eventPrefix.&#8217;_save_after&#8217;, $this->_getEventData());</em>.</p>
<p>The most important thing here for us is to &#8220;catch&#8221; the parameters that are passed to event. Function call <em>$this->_getEventData())</em> basically returns the array of <em>array(&#8216;data_object&#8217; => $this, $this->_eventObject => $this);</em>. As we mentioned previously <em>$_eventObject</em> property has the value of &#8220;<em>order</em>&#8221; set under the <em>Mage_Sales_Model_Order</em> class. What this means that all we need to do in our &#8220;<em>sales_order_save_after</em>&#8221; event observer in order to grab the order passed to the event is an expression like <em>$observer->getEvent()->Order();</em>.</p>
<p>From there on, we will start implementing the code for our specific client requirement. Before we do so, here is the actual code you need in order to have your <em>sales_order_save_after</em> event observer functional.</p>
<p><strong>config.xml</strong> from within your extension:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;config&gt;
//...
	&lt;frontend&gt;
		&lt;events&gt;
            &lt;sales_order_save_after&gt;
                &lt;observers&gt;
                    &lt;customer_first_order&gt;
                        &lt;class&gt;myClassGroup/observer&lt;/class&gt;
                        &lt;method&gt;handleCustomerFirstOrder&lt;/method&gt;
                    &lt;/customer_first_order&gt;
                &lt;/observers&gt;
            &lt;/sales_order_save_after&gt;
		&lt;/events&gt;
	&lt;/frontend&gt;
//...
&lt;/config&gt;
</pre>
<p><strong>Observer.php</strong> from within your extension:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

class MyCompany_MyExtension_Model_Observer
{
	public function handleCustomerFirstOrder($observer)
	{

	}
}
</pre>
<p>Now we need to add the necessary logic that implements client&#8217;s specific requirement, which transforms the above Observer.php into something like this:</p>
<pre class="brush: php; title: ; notranslate">
class MyCompany_MyExtension_Model_Observer
{
    private static $_handleCustomerFirstOrderCounter = 1;

	public function handleCustomerFirstOrder($observer)
	{
        $orders = Mage::getModel('sales/order')
                    -&gt;getCollection()
                    -&gt;addFieldToSelect('increment_id')
                    -&gt;addFieldToFilter('customer_id', array('eq' =&gt; $observer-&gt;getEvent()-&gt;getOrder()-&gt;getCustomerId()));

        //$orders-&gt;getSelect()-&gt;limit(2);

        //if ($orders-&gt;count() == 1) {
        if ($orders-&gt;getSize() == 1) {
            if (self::$_handleCustomerFirstOrderCounter &gt; 1) {
                return $this;
            }

            self::$_handleCustomerFirstOrderCounter++;

			Mage::dispatchEvent('customer_first_order', array('order' =&gt; $observer-&gt;getEvent()-&gt;getOrder()));
		}		

		return $this;
	}
}
</pre>
<p>Several things to explain here. </p>
<p>First the use of <em>$_handleCustomerFirstOrderCounter</em>. I have noticed that during the same page request on order after save action, depending on possible other existing event observers that might do order re-save action, etc. my code within <em>handleCustomerFirstOrder($observer)</em> method can get executed twice or more times, thus I used static variable in a form of counter to specifically allow it to execute only once.</p>
<p>Second, you will notice the limit I put on the colelction, <em>$orders->getSelect()->limit(2);</em>. Reason for this is the logic that says &#8220;check if this is customers first order&#8221;. In order to do that, I need to know if there are other order in the system for the same customer. Since there is no need to fetch/load or even query for all of the order&#8217;s of the same customers I merely said &#8220;tray to grab two orders from this customer&#8221; then with <em>if ($orders->count() == 1)</em> expression I merely said, if total count of grabbed orders is one then this is the first order by this customer. Now you will notice that I commented out the <em>$orders->getSelect()->limit(2);</em> and <em>if ($orders->count() == 1)</em> expressions at the end and went with the use of getSize() method on the collection. Looks nicer and does the same thing. Method getSize() comes from the Varien_Data_Collection_Db class and internally it actually calls the getSelectCountSql() method that specifically executes count on the database, <em>$countSelect->columns(&#8216;COUNT(*)&#8217;);</em> ,and returns just the count value. Thus making it even faster.</p>
<p>And finally, in place of implementing my reward points logic code directly there, I decided to trigger the <em>customer_first_order</em> event for this case. Reason is simply, maybe other developers in the system would like do do something else on this event, so why not dispatch it.</p>
<p>To conclude the client&#8217;s request I simply implement one more observer that handles the <em>customer_first_order</em> event and within that observer I give customer A it&#8217;s earned reward points.</p>
<p>Hopefully this article was helpful for some.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/custom-magento-events-customer-first-order/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What is base64 encoding and how can we benefit from it</title>
		<link>http://inchoo.net/ecommerce/magento/what-is-base64-encoding-and-how-can-we-benefit-from-it/</link>
		<comments>http://inchoo.net/ecommerce/magento/what-is-base64-encoding-and-how-can-we-benefit-from-it/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 11:00:09 +0000</pubDate>
		<dc:creator>Ivan Galambos</dc:creator>
				<category><![CDATA[Administration]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[encode]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=9809</guid>
		<description><![CDATA[What is base64 encoding/decoding and how we can benefit from this representation Base64 schemes represent binary data in an ASCII string format (English alphabet, common punctuation chars, control chars) by translating it into a base-64 representation. This basically means that &#8230;<p><a href="http://inchoo.net/ecommerce/magento/what-is-base64-encoding-and-how-can-we-benefit-from-it/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>What is base64 encoding/decoding and how we can benefit from this representation</p>
<p>Base64 schemes represent binary data in an ASCII string format (English alphabet, common punctuation chars, control chars) by translating it into a base-64 representation.<span id="more-9809"></span> This basically means that all kind of characters (ASCII, UTF8, UTF16&#8230;) with control characters can be mapped for example in English alphabet a-z, A-Z, 0-9 and you would be able to read them all on screen, or even print them out.<br />
First of all, Magento is using base64 encode/decode each time you want to add product in your cart. Magento will redirect you to something like this: <a href="http://loc.magento.com/checkout/cart/add/uenc/aHR0cDovL2xvYy5tYWdlbnRvLmNvbS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1s/product/93/">&#8220;http://loc.magento.com/checkout/cart/add/uenc/aHR0cDovL2xvYy5tYWdlbn&#8230;93/&#8221;</a> with some POST data (product=93&amp;related_product=&amp;super_attribute[502]=37&amp;qty=2).</p>
<p>These chars &#8220;aHR0cDovL2xvYy5tYWdlbnRvLmNvbS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1s&#8221; are base64 encoded strings and POST data you can see (HTTP header traffic) with Firebug, LiveHTTPHeaders (addon for FF), Charles proxy,&#8230;</p>
<p>If you don&#8217;t know what does it mean (encoded chars) and how they are generated &#8211; <strong>keep reading</strong>.</p>
<p>Additionally, if you have any useful example where did you use base64 encode/decode, feel free to share your ideas with others.</p>
<p>From wiki: &#8220;Base64 encoding schemes are commonly used when there is a need to encode binary data that needs be stored and transferred over media that are designed to deal with textual data. This is to ensure that the data remains intact without modification during transport&#8221;.</p>
<p>In our case uenc = url encoded = aHR0cDovL2xvYy5tYWdlbnRvLmNvbS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1s = http://loc.magento.com/asics-men-s-gel-kayano-xii.html.</p>
<p>What do you think why doesn&#8217;t Magento use normal strings in URL instead of base64 which is <strong>around 33%</strong> longer? Hint: you&#8217;ll get this later in the article&#8230;</p>
<p>As you can see we can&#8217;t put char &#8220;/&#8221; in URL if we want to send last visited URL as parameter because we would break attribute/value rule for &#8220;MOD rewrite&#8221; &#8211; GET parameter.<br />
A full example would be: &#8220;http://loc.magento.com/checkout/cart/add/uenc/http://loc.magento.com/asics-men-s-gel-kayano-xii.html/product/93/&#8221; &#8211; sure it&#8217;s wrong.</p>
<p>This is just one example where you can use base64. Also in administration part when you search in grid in some column some value you can see that Magento is using base64 to encode your filter(s). In other words, you don&#8217;t need to worry about which character sets client&#8217;s browser can accept. You are sure that all characters will be transferred over the wire with base64!</p>
<p><strong>So, what do I need to do to convert characters into base64 encoded schema?</strong> Just a little bit of math or you can use any trusted code which will do that for you. You have bunch of &#8220;<strong>online base64 decode/encode</strong>&#8221; scripts on web, just google them. What programming language to use to develop scripts for such of things? Sure, javascript to send &#8220;safe&#8221; data over the wire and you can use PHP to decode them, vice-versa.</p>
<p>Additionally, you can find base64 encoding algorithms in javascript in Magento&#8217;s folder <strong>webroot/js/mage/adminhtml/hash.js</strong> around line 57, function encode_base64( what ) {&#8230;</p>
<p><strong>Another example</strong> could be the following: you have a web service that accept only ASCII chars. You want to save and then transfer user&#8217;s data to some other location (API) but recipient want receive untouched data. Again base64 is for that also. The only downside is that base64 encoding will require <strong>around 33%</strong>  more space than regular strings.</p>
<p>So with base64 you can encode and transfer any sets of binary data through any system and then decode them to original binary data. Cool, right?</p>
<p>Does gmail use base64? Sure!</p>
<p>Instead of &#8220;<strong>reinventing the wheel</strong>&#8221; and showing you how base64 works please take a look this pdf where you can see nice examples and table with ASCII chars. <a title="Base64" href="http://www.aardwulf.com/tutor/base64/base64.pdf">http://www.aardwulf.com/tutor/base64/base64.pdf</a></p>
<p>You can also build your own base64 algorithm for your specific needs!</p>
<p>For the end, did you maybe buy some extension that has weird characters in it and you didn&#8217;t know how to see source code? If your answer is yes, while reading this article did you maybe recognize that the code you have is probably base64 encoded? And can you perhaps see &#8220;eval()&#8221; function in that code?</p>
<p>If the answer is yes, then in my next article I&#8217;ll show you how to do &#8220;<strong>reverse engineering</strong>&#8221; and see your source code for bunch of extensions,&#8230; which you can buy and which are base64 encoded.</p>
<p>Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/what-is-base64-encoding-and-how-can-we-benefit-from-it/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Multiple configurable products with options on one page in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/display-multiple-configurable-products-with-options-on-one-page-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/display-multiple-configurable-products-with-options-on-one-page-in-magento/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 11:36:51 +0000</pubDate>
		<dc:creator>Goran Sambolic</dc:creator>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[configurable]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[options]]></category>
		<category><![CDATA[product]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11973</guid>
		<description><![CDATA[Displaying configurable products with options on one page can be problem because Javascript in Magento is setup to work only with one configurable product. You can write your own Javascript or U can reuse Magento code. To accomplish that we &#8230;<p><a href="http://inchoo.net/ecommerce/magento/display-multiple-configurable-products-with-options-on-one-page-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Displaying configurable products with options on one page can be problem because Javascript in Magento is setup to work only with one configurable product.<br />
You can write your own Javascript or U can reuse Magento code.<br />
<span id="more-11973"></span></p>
<p>To accomplish that we need to modify product Javascript (js/varien/product.js) and configurable (catalog\product\view\type\options\configurable.phtml) select element template.</p>
<p>In configurable.phtml call our new JS class (we will create that class later in article) and add product id to configurable select element class.</p>
<p>configurable.phtml:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$_product    = $this-&gt;getProduct();
$_attributes = Mage::helper('core')-&gt;decorateArray($this-&gt;getAllowAttributes());
?&gt;
&lt;?php if ($_product-&gt;isSaleable() &amp;&amp; count($_attributes)):?&gt;
    &lt;dl&gt;
    &lt;?php foreach($_attributes as $_attribute): ?&gt;
        &lt;dt&gt;&lt;label class=&quot;required&quot;&gt;&lt;em&gt;*&lt;/em&gt;&lt;?php echo $_attribute-&gt;getLabel() ?&gt;&lt;/label&gt;&lt;/dt&gt;
        &lt;dd&lt;?php if ($_attribute-&gt;decoratedIsLast){?&gt; class=&quot;last&quot;&lt;?php }?&gt;&gt;
            &lt;div class=&quot;input-box&quot;&gt;
                &lt;select name=&quot;super_attribute[&lt;?php echo $_attribute-&gt;getAttributeId() ?&gt;]&quot; id=&quot;attribute&lt;?php echo $_attribute-&gt;getAttributeId() ?&gt;&quot; class=&quot;required-entry super-attribute-select_&lt;?php echo $_product-&gt;getId()?&gt;  &quot;&gt;
                    &lt;option&gt;&lt;?php echo $this-&gt;__('Choose an Option...') ?&gt;&lt;/option&gt;
                  &lt;/select&gt;
              &lt;/div&gt;
        &lt;/dd&gt;
    &lt;?php endforeach; ?&gt;
    &lt;/dl&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
        var spConfig_&lt;?php echo $_product-&gt;getId()?&gt; = new Inchoo_Product.Config(&lt;?php echo $this-&gt;getJsonConfig() ?&gt;);
    &lt;/script&gt;
&lt;?php endif;?&gt;
</pre>
<p>Then create Javascript file and Javascript class.<br />
Copy javascript code from js/varien/product.js for configurable product (use own namespace to avoid JS collision with Magento).</p>
<pre class="brush: jscript; title: ; notranslate">
if(typeof Inchoo_Product =='undefined') {
    var Inchoo_Product  = {};
}

/**************************** CONFIGURABLE PRODUCT **************************/
Inchoo_Product.Config = Class.create();
Inchoo_Product.Config.prototype = {
</pre>
<p>Because we change selector name we have to modify our JS code to work with new selector.</p>
<pre class="brush: jscript; title: ; notranslate">
var settingsClassToSelect = '.super-attribute-select_'+this.config.productId;
this.settings   = $$(settingsClassToSelect);
</pre>
<p>Magento code is stripping &#8220;attribute&#8221; string from class of configurable select element but we also have to strip product id (we added product id to class name in configurable.phtml).</p>
<pre class="brush: jscript; title: ; notranslate">
        // fill state
        this.settings.each(function(element){
            var attributeId = element.id.replace(/[a-z]*/, '');
            attributeId = attributeId.replace(/_.*/, '');

            ........

        fillSelect: function(element){
        var attributeId = element.id.replace(/[a-z]*/, '');
        attributeId = attributeId.replace(/_.*/, '');
</pre>
<p>Now we can have multiple configurable products with options on same page.</p>
<p><strong>Update, as requested complete JS file </strong></p>
<p>product.js:</p>
<pre class="brush: jscript; title: ; notranslate">

if(typeof Inchoo_Product =='undefined') {
    var Inchoo_Product  = {};
}

/**************************** CONFIGURABLE PRODUCT **************************/
Inchoo_Product.Config = Class.create();
Inchoo_Product.Config.prototype = {
    initialize: function(config){
        this.config     = config;
        this.taxConfig  = this.config.taxConfig;
        var settingsClassToSelect = '.super-attribute-select_'+this.config.productId;
        this.settings   = $$(settingsClassToSelect);
        this.state      = new Hash();
        this.priceTemplate = new Template(this.config.template);
        this.prices     = config.prices;

        this.settings.each(function(element){
            Event.observe(element, 'change', this.configure.bind(this))
        }.bind(this));

        // fill state
        this.settings.each(function(element){
            var attributeId = element.id.replace(/[a-z]*/, '');
            attributeId = attributeId.replace(/_.*/, '');
            if(attributeId &amp;&amp; this.config.attributes[attributeId]) {
                element.config = this.config.attributes[attributeId];
                element.attributeId = attributeId;
                this.state[attributeId] = false;
            }
        }.bind(this))

        // Init settings dropdown
        var childSettings = [];
        for(var i=this.settings.length-1;i&gt;=0;i--){
            var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
            var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
            if(i==0){
                this.fillSelect(this.settings[i])
            }
            else {
                this.settings[i].disabled=true;
            }
            $(this.settings[i]).childSettings = childSettings.clone();
            $(this.settings[i]).prevSetting   = prevSetting;
            $(this.settings[i]).nextSetting   = nextSetting;
            childSettings.push(this.settings[i]);
        }

        // Set default values - from config and overwrite them by url values
        if (config.defaultValues) {
            this.values = config.defaultValues;
        }

        var separatorIndex = window.location.href.indexOf('#');
        if (separatorIndex != -1) {
            var paramsStr = window.location.href.substr(separatorIndex+1);
            var urlValues = paramsStr.toQueryParams();
            if (!this.values) {
                this.values = {};
            }
            for (var i in urlValues) {
                this.values[i] = urlValues[i];
            }
        }

        this.configureForValues();
        document.observe(&quot;dom:loaded&quot;, this.configureForValues.bind(this));
    },

    configureForValues: function () {
        if (this.values) {
            this.settings.each(function(element){
                var attributeId = element.attributeId;
                element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId];
                this.configureElement(element);
            }.bind(this));
        }
    },

    configure: function(event){
        var element = Event.element(event);
        this.configureElement(element);
    },

    configureElement : function(element) {
        this.reloadOptionLabels(element);
        if(element.value){
            this.state[element.config.id] = element.value;
            if(element.nextSetting){
                element.nextSetting.disabled = false;
                this.fillSelect(element.nextSetting);
                this.resetChildren(element.nextSetting);
            }
        }
        else {
            this.resetChildren(element);
        }
        //this.reloadPrice();
//      Calculator.updatePrice();
    },

    reloadOptionLabels: function(element){
        var selectedPrice;
        if(element.options[element.selectedIndex].config){
            selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
        }
        else{
            selectedPrice = 0;
        }
        for(var i=0;i&lt;element.options.length;i++){
            if(element.options[i].config){
                element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
            }
        }
    },

    resetChildren : function(element){
        if(element.childSettings) {
            for(var i=0;i&lt;element.childSettings.length;i++){
                element.childSettings[i].selectedIndex = 0;
                element.childSettings[i].disabled = true;
                if(element.config){
                    this.state[element.config.id] = false;
                }
            }
        }
    },

    fillSelect: function(element){
        var attributeId = element.id.replace(/[a-z]*/, '');
        attributeId = attributeId.replace(/_.*/, '');
        var options = this.getAttributeOptions(attributeId);
        this.clearSelect(element);
        element.options[0] = new Option(this.config.chooseText, '');

        var prevConfig = false;
        if(element.prevSetting){
            prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
        }

        if(options) {
            var index = 1;
            for(var i=0;i&lt;options.length;i++){
                var allowedProducts = [];
                if(prevConfig) {
                    for(var j=0;j&lt;options[i].products.length;j++){
                        if(prevConfig.config.allowedProducts
                            &amp;&amp; prevConfig.config.allowedProducts.indexOf(options[i].products[j])&gt;-1){
                            allowedProducts.push(options[i].products[j]);
                        }
                    }
                } else {
                    allowedProducts = options[i].products.clone();
                }

                if(allowedProducts.size()&gt;0){
                    options[i].allowedProducts = allowedProducts;
                    element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
                    element.options[index].config = options[i];
                    index++;
                }
            }
        }
    },

    getOptionLabel: function(option, price){
        var price = parseFloat(price);
        if (this.taxConfig.includeTax) {
            var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
            var excl = price - tax;
            var incl = excl*(1+(this.taxConfig.currentTax/100));
        } else {
            var tax = price * (this.taxConfig.currentTax / 100);
            var excl = price;
            var incl = excl + tax;
        }

        if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
            price = incl;
        } else {
            price = excl;
        }

        var str = option.label;
        if(price){
            if (this.taxConfig.showBothPrices) {
                str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
            } else {
                str+= ' ' + this.formatPrice(price, true);
            }
        }
        return str;
    },

    formatPrice: function(price, showSign){
        var str = '';
        price = parseFloat(price);
        if(showSign){
            if(price&lt;0){
                str+= '-';
                price = -price;
            }
            else{
                str+= '+';
            }
        }

        var roundedPrice = (Math.round(price*100)/100).toString();

        if (this.prices &amp;&amp; this.prices[roundedPrice]) {
            str+= this.prices[roundedPrice];
        }
        else {
            str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
        }
        return str;
    },

    clearSelect: function(element){
        for(var i=element.options.length-1;i&gt;=0;i--){
            element.remove(i);
        }
    },

    getAttributeOptions: function(attributeId){
        if(this.config.attributes[attributeId]){
            return this.config.attributes[attributeId].options;
        }
    },

    reloadPrice: function(){
        var price    = 0;
        var oldPrice = 0;
        for(var i=this.settings.length-1;i&gt;=0;i--){
            var selected = this.settings[i].options[this.settings[i].selectedIndex];
            if(selected.config){
                price    += parseFloat(selected.config.price);
                oldPrice += parseFloat(selected.config.oldPrice);
            }
        }

        optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
        optionsPrice.reload();

        return price;

        if($('product-price-'+this.config.productId)){
            $('product-price-'+this.config.productId).innerHTML = price;
        }
        this.reloadOldPrice();
    },

    reloadOldPrice: function(){
        if ($('old-price-'+this.config.productId)) {

            var price = parseFloat(this.config.oldPrice);
            for(var i=this.settings.length-1;i&gt;=0;i--){
                var selected = this.settings[i].options[this.settings[i].selectedIndex];
                if(selected.config){
                    price+= parseFloat(selected.config.price);
                }
            }
            if (price &lt; 0)
                price = 0;
            price = this.formatPrice(price);

            if($('old-price-'+this.config.productId)){
                $('old-price-'+this.config.productId).innerHTML = price;
            }

        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/display-multiple-configurable-products-with-options-on-one-page-in-magento/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Snowflakes Magento Extension</title>
		<link>http://inchoo.net/ecommerce/magento/snowflakes-magento-extension/</link>
		<comments>http://inchoo.net/ecommerce/magento/snowflakes-magento-extension/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 10:08:22 +0000</pubDate>
		<dc:creator>Davor Budimcic</dc:creator>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Fun & Events]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[christmas]]></category>
		<category><![CDATA[extension]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11925</guid>
		<description><![CDATA[Happy holidays everyone. As you could notice, we have a new holiday header, new holiday wallpapers, and today we have something new. Creative sparks did their magic making us proud to present you Inchoo Snowflakes Magento Extension. Demo Update: As &#8230;<p><a href="http://inchoo.net/ecommerce/magento/snowflakes-magento-extension/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Happy holidays everyone. As you could notice, we have a new holiday header, new <a href="/fun-zone/inchooers-wallpaper-christmas-edition/" title="Inchoo Christmas Wallpaper">holiday wallpapers</a>, and today we have something new. Creative sparks did their magic making us proud to present you <strong>Inchoo Snowflakes Magento Extension</strong>.<br />
<span id="more-11925"></span></p>
<h2>Demo</h2>
<p><a href="http://inchoo.net/wp-content/uploads/2011/12/InchooSnowflakes/snow.html" target="_blank"><img src="http://inchoo.net/wp-content/uploads/2011/12/ISdemo.png" alt="" title="ISdemo" width="581" height="258" class="alignnone size-full wp-image-11966" /></a></p>
<p><strong>Update:</strong> As you requested, we added a few &#8220;live&#8221; variations that you can archieve with this extension to <a href="http://inchoo.net/wp-content/uploads/2011/12/InchooSnowflakes/snow.html" target="_blank">Snowflakes Demo</a>.</p>
<h2>Screenshots</h2>
<p style="text-align: center;">&#8220;Look Ma&#8217;, it&#8217;s snowing on frontend!&#8221;<br />
<img class="alignnone size-medium wp-image-11936" style="background: #fff; padding: 4px; border: 1px solid #C3D16F;" title="front1" src="http://inchoo.net/wp-content/uploads/2011/12/front1-600x300.jpg" alt="" width="600" height="300" /></p>
<p style="text-align: center;">If you feel cold from all that snow, add some stars instead&#8230;<br />
<img class="alignnone size-medium wp-image-11937" style="background: #fff; padding: 4px; border: 1px solid #C3D16F;" title="front2" src="http://inchoo.net/wp-content/uploads/2011/12/front2-600x300.jpg" alt="" width="600" height="300" /></p>
<p style="text-align: center;">&#8230;or write your own message to customers<br />
<img class="alignnone size-medium wp-image-11938" style="background: #fff; padding: 4px; border: 1px solid #C3D16F;" title="front3" src="http://inchoo.net/wp-content/uploads/2011/12/front3-600x300.jpg" alt="" width="600" height="300" /></p>
<p style="text-align: center;">Configuration options are located in<br />
System -&gt; Configuration -&gt; Inchoo Snowflakes Config<br />
<img class="alignnone size-medium wp-image-11935" style="background: #fff; padding: 4px; border: 1px solid #C3D16F;" title="admin" src="http://inchoo.net/wp-content/uploads/2011/12/admin-600x300.jpg" alt="" width="600" height="300" /></p>
<h2>Download</h2>
<p>Just download <a href="http://inchoo.net/wp-content/uploads/2011/12/InchooSnowflakes.zip">InchooSnowflakes.zip</a>, extract files following directory structure, reload cache and let it snow! <img src='http://inchoo.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/snowflakes-magento-extension/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Inchooers Wallpaper &#8211; Christmas Edition</title>
		<link>http://inchoo.net/fun-zone/inchooers-wallpaper-christmas-edition/</link>
		<comments>http://inchoo.net/fun-zone/inchooers-wallpaper-christmas-edition/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 15:00:57 +0000</pubDate>
		<dc:creator>Hrvoje Jurisic</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Fun & Events]]></category>
		<category><![CDATA[inchooers]]></category>
		<category><![CDATA[magento wallpaper]]></category>
		<category><![CDATA[wallpaper]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11917</guid>
		<description><![CDATA[Christmas is near, and the Inchooers are already in Holidays mood. Feel free to join us. Download the wallpaper and enjoy Holidays even on your desktops Christmas Day 1920&#215;1080 &#124; 1680&#215;1050]]></description>
			<content:encoded><![CDATA[<p>Christmas is near, and the Inchooers are already in Holidays mood. Feel free to join us. Download the wallpaper and enjoy Holidays even on your desktops <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-11917"></span></p>
<p style="text-align: center;">
<img src="http://inchoo.net/wp-content/uploads/2011/12/christmas_night_thumb.jpg" alt="Christmas night wallpaper" style="background: #fff; padding: 4px; border: 1px solid #C3D16F; title="christmas_night_thumb" width="350" height="221" class="alignnone size-full wp-image-11920" /></p>
<p style="text-align: center;"><strong>Christmas Night</strong><br />
<a href="http://inchoo.net/wp-content/uploads/2011/12/christmas_night_1920x1080.jpg#" target="_blank">1920&#215;1080</a> | <a href="http://inchoo.net/wp-content/uploads/2011/12/christmas_night_1680x1050.jpg#" target="_blank">1680&#215;1050</a></p>
<p style="text-align: center;">
<img src="http://inchoo.net/wp-content/uploads/2011/12/christmas_wallpaper_thumb.jpg" style="background: #fff; padding: 4px; border: 1px solid #C3D16F; alt="Christmas wallpaper" title="christmas_wallpaper_thumb" width="350" height="221" class="alignnone size-full wp-image-11923" /></p>
<p style="text-align: center;"><strong>Christmas Day</strong><br />
<a href="http://inchoo.net/wp-content/uploads/2011/12/christmas_wallpaper.jpg#" target="_blank">1920&#215;1080</a> | <a href="http://inchoo.net/wp-content/uploads/2011/12/christmas_wallpaper_1680x1050.jpg#" target="_blank">1680&#215;1050</a></p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/fun-zone/inchooers-wallpaper-christmas-edition/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Facebook Connect Magento Extension</title>
		<link>http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/</link>
		<comments>http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 21:56:43 +0000</pubDate>
		<dc:creator>Ivan Weiler</dc:creator>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[facebook]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=4133</guid>
		<description><![CDATA[We&#8217;re proud to present free Facebook Connect Magento extension which enables customers fast and easy registration and login with their Facebook identity. And it&#8217;s just been updated! Important Facebook updated it&#8217;s authentication mechanism but so did we, so please update &#8230;<p><a href="http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re proud to present <strong>free Facebook Connect Magento extension</strong> which enables customers fast and easy registration and login with their Facebook identity. And it&#8217;s <strong>just been updated</strong>!</p>
<p><span id="more-4133"></span></p>
<h2>Important</h2>
<p>Facebook updated it&#8217;s authentication mechanism but so did we, so please update your extension to the newest version since older versions won&#8217;t work anymore.<br />
Also, if you&#8217;re getting &#8220;An error occurred. Please try again later.&#8221; message in connect popup, you need to get <strong>new &#8220;App ID/API Key&#8221;</strong> from Facebook and enter it into Magento. Check your Application Secret along the way.</p>
<h2>Download</h2>
<p>Download <a href="http://inchoo.net/wp-content/uploads/2011/05/Inchoo_Facebook-0.9.9.zip" target="_blank"><strong>Inchoo_Facebook-0.9.9.zip</strong></a>, extract files to appropriate place following directory structure and reload cache.<br />
Latest pre-relase versions can always be downloaded on <a href="https://github.com/ivanweiler/Inchoo_Facebook" target="_blank">my github project page</a>.</p>
<h2>About</h2>
<p>Facebook Connect Magento extension enables customers one click registration and login with their Facebook identity. It automatically registers new users and logs in existing ones.</p>
<p>Current extension is compatible with latest Magento CE 1.6, but also with older 1.5, 1.4 and 1.3.2.x versions. It&#8217;s using brand new Facebook thingies like open graph protocol and open source JavaScript SDK.</p>
<p>If you&#8217;re interested to see additional languages in future releases, <a href="http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/comment-page-3/#comment-20942">help us translate it by following instructions</a>.</p>
<h2>Facebook App</h2>
<p>For Facebook Connect to work you need to <a href="http://www.facebook.com/developers/createapp.php" target="_blank">Setup Application on Facebook</a> and obtain its App ID/API Key and Application Secret.</p>
<p>Use your store name as application name and read and accept terms of service. On second screen set App Domain and Site URL(under checked Web Site tab), both to the store domain where you plan to implement Facebook Connect. Save Changes. Other Connect settings are optional, but you might want to add store logo for example.</p>

<a href='http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/attachment/facebook-setup-1/' title='facebook-setup-1'><img width="300" height="182" src="http://inchoo.net/wp-content/uploads/2011/05/facebook-setup-1-300x182.png" class="attachment-thumbnail" alt="facebook-setup-1" title="facebook-setup-1" /></a>
<a href='http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/attachment/facebook-setup-2/' title='facebook-setup-2'><img width="300" height="199" src="http://inchoo.net/wp-content/uploads/2011/05/facebook-setup-2-300x199.png" class="attachment-thumbnail" alt="facebook-setup-2" title="facebook-setup-2" /></a>
<a href='http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/attachment/facebook-setup-3/' title='facebook-setup-3'><img width="300" height="201" src="http://inchoo.net/wp-content/uploads/2011/05/facebook-setup-3-300x201.png" class="attachment-thumbnail" alt="facebook-setup-3" title="facebook-setup-3" /></a>
<a href='http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/attachment/facebook-setup-4/' title='facebook-setup-4'><img width="300" height="201" src="http://inchoo.net/wp-content/uploads/2011/05/facebook-setup-4-300x201.png" class="attachment-thumbnail" alt="facebook-setup-4" title="facebook-setup-4" /></a>

<h2>Magento Setup</h2>
<p>Once you obtain two keys navigate to Magento Administration, copy/paste them to appropriate fields under Configuration-&gt;Customer-&gt;Facebook Connect, set Enabled to Yes and you&#8217;re good to go. If you&#8217;re updating from previous releases, you also need to Enable it to work.</p>
<p>Default template files (frontend/default/default/template/facebook/*) and layout (layout/facebook.xml) makes Facebook Connect work out of the box with default theme, but we tried to make customizations as easy as possible so all you need to do is add button or link with &#8220;facebook-connect&#8221; rel attribute set anywhere in the theme, static block or cms page, for example:</p>
<p>&lt;button rel=&#8221;facebook-connect&#8221; class=&#8221;form-button&#8221; type=&#8221;submit&#8221;&gt;&lt;span&gt;Connect with Facebook&lt;/span&gt;&lt;/button&gt;<br />
&lt;a rel=&#8221;facebook-connect&#8221;&gt;Connect with Facebook&lt;/a&gt;</p>
<h2>Latest Changes</h2>
<p>v.0.9.9<br />
- Client and javascript compatible with new Facebook authentication changes.<br />
- Event.fire changed to document object to avoid javascript conflicts.<br />
- Asking for user_birthday permission from now on.<br />
- Norwegian translation added thanks to Magnus Alexander.</p>
<p>v.0.9.8<br />
- Version fix, licenses added, connect release.</p>
<p>v.0.9.7<br />
- Estonian, Swedish, Czech, Turkish and Korean translations added thanks to Sir Mull, Andreas Karlsson, Pavel Hrdlicka, ea and COBAY.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/facebook-connect-magento-extension/feed/</wfw:commentRss>
		<slash:comments>406</slash:comments>
		</item>
		<item>
		<title>Geocoding Customer Addresses in Magento via Google Maps</title>
		<link>http://inchoo.net/ecommerce/magento/geocoding-customer-addresses-in-magento-via-google-maps/</link>
		<comments>http://inchoo.net/ecommerce/magento/geocoding-customer-addresses-in-magento-via-google-maps/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 14:35:22 +0000</pubDate>
		<dc:creator>Branko Ajzele</dc:creator>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[map]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11874</guid>
		<description><![CDATA[Geocoding is the process of finding associated geographic coordinates (often expressed as latitude and longitude) from other geographic data, such as street addresses, or zip codes (postal codes)&#8230; so says Wikipedia. Geocoding an address is pretty simple if you are &#8230;<p><a href="http://inchoo.net/ecommerce/magento/geocoding-customer-addresses-in-magento-via-google-maps/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Geocoding is the process of finding associated geographic coordinates (often expressed as latitude and longitude) from other geographic data, such as street addresses, or zip codes (postal codes)&#8230; so says Wikipedia. Geocoding an address is pretty simple if you are using Google Maps API. Since all we do here is Magento, let me show you how easily you can geocode customer address.<span id="more-11874"></span></p>
<p>We will start with adding the Gmap.php helper to our extension:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * @author Branko Ajzele &lt;ajzele@gmail.com&gt;
 */
class Inchoo_Extension_Helper_Gmap extends Mage_Core_Helper_Abstract
{
    const GOOGLE_MAPS_HOST = 'maps.google.com';
    const CONFIG_PATH_GOOGLE_MAPS_API_KEY = 'inchoo_google/maps/api_key';

    public function getGoogleMapsApiKey()
    {
        return Mage::getStoreConfig(self::CONFIG_PATH_GOOGLE_MAPS_API_KEY);
    }

    /**
     *
     * @param Mage_Customer_Model_Address $address
     * @param boolean $saveCoordinatesToAddress
     * @param boolean $forceLookup
     * @return array Returns the array of float values like {[0] =&gt; float(18.4438156) [1] =&gt; float(45.5013644)}
     */
    public function fetchAddressGeoCoordinates(Mage_Customer_Model_Address $address, $saveCoordinatesToAddress = true, $forceLookup = false)
    {
        /**
         * USAGE EXAMPLE

            $customer = Mage::getModel('customer/customer');
            $customer-&gt;setWebsiteId(Mage::app()-&gt;getWebsite()-&gt;getId());
            $customer-&gt;loadByEmail('some-email@domain.com');

            Mage::helper('inchoo/gmap')-&gt;fetchAddressGeoCoordinates($customer-&gt;getDefaultBillingAddress())

         */

        $coordinates = array();

        if ($address-&gt;getId() &amp;&amp; $address-&gt;getGmapCoordinatePointX() &amp;&amp; $address-&gt;getGmapCoordinatePointY() &amp;&amp; $forceLookup == false) {
            $coordinates = array($address-&gt;getGmapCoordinatePointX(), $address-&gt;getGmapCoordinatePointY());
        } else if (!$address-&gt;getGmapCoordinatePointX() &amp;&amp; !$address-&gt;getGmapCoordinatePointY())
            OR ($address-&gt;getId() &amp;&amp; $address-&gt;getGmapCoordinatePointX() &amp;&amp; $address-&gt;getGmapCoordinatePointY() &amp;&amp; $forceLookup == true)) {

            $lineAddress = $address-&gt;getStreet1(). ', '.$address-&gt;getPostcode().' '.$address-&gt;getCity().', '.$address-&gt;getCountry();

            $client = new Zend_Http_Client();
            $client-&gt;setUri('http://'.self::GOOGLE_MAPS_HOST.'/maps/geo');
            $client-&gt;setMethod(Zend_Http_Client::GET);
            $client-&gt;setParameterGet('output', 'json');
            $client-&gt;setParameterGet('key', $this-&gt;getGoogleMapsApiKey());
            $client-&gt;setParameterGet('q', $lineAddress);

            $response = $client-&gt;request();

            if ($response-&gt;isSuccessful() &amp;&amp; $response-&gt;getStatus() == 200) {
                $_response = json_decode($response-&gt;getBody());
                $_coordinates = @$_response-&gt;Placemark[0]-&gt;Point-&gt;coordinates;

                if (is_array($_coordinates) &amp;&amp; count($_coordinates) &gt;= 2) {

                    $coordinates = array_slice($_coordinates, 0, 2);

                    if ($saveCoordinatesToAddress) {
                        try {
                            $address-&gt;setGmapLng($coordinates[0]);
                            $address-&gt;setGmapLat($coordinates[1]);

                            $address-&gt;save();
                        } catch (Exception $e) {
                            Mage::logException($e);
                        }
                    }
                }
            }
        }

        return $coordinates;
    }
}
</pre>
<p>As you can see above in the code, function getGoogleMapsApiKey() pulls the API key info from my system configuration. I will not show you that part here. So for the sake of simplicity if you do not know how to code a configuration for your module you can just return a raw API key string here (surely this approach is then just for testing/playing not on production).</p>
<p>Since this helper references the two non-defualt-existing attributes on the address we will need to add those attributes. We do so trough install/upgrade scripts (you know, the files under app/code/{codePool}/Company/Extension/sql/extension_setup/ folder). I will not give you the full example of the file and it&#8217;s corresponding config.xml entry, as you should know how to do it yourself already, rather just the partial code that goes into the install/upgrade script in order to add the two missing customer address attributes:</p>
<pre class="brush: php; title: ; notranslate">
//Add attribute that will be used for Google Maps as a coordinate lng
$installer-&gt;addAttribute('customer_address', 'gmap_lng', array(
    'type'     =&gt; 'varchar',
    'input'    =&gt; 'hidden',
    'visible'  =&gt; false,
    'required' =&gt; false
));
//Add attribute that will be used for Google Maps as a coordinate lat
$installer-&gt;addAttribute('customer_address', 'gmap_lat', array(
    'type'     =&gt; 'varchar',
    'input'    =&gt; 'hidden',
    'visible'  =&gt; false,
    'required' =&gt; false
));
</pre>
<p>Next, we will add the observer to the proper _beforeSave() dispatched event of the Mage_Customer_Model_Address model class. Since Mage_Customer_Model_Address extends the Mage_Customer_Model_Address_Abstract which defines the &#8220;protected $_eventPrefix = &#8216;customer_address&#8217;;&#8221; we can easily conclude the all it takes is to create observer for &#8220;customer_address_save_before&#8221; event (Mage_Core_Model_Abstract::_beforeSave() &#8230; we have Mage::dispatchEvent($this-&gt;_eventPrefix.&#8217;_save_before&#8217;, $this-&gt;_getEventData());).</p>
<p>So we add something like this to the config.xml file of our extension:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;global&gt;

    &lt;events&gt;
        &lt;customer_address_save_before&gt;
            &lt;observers&gt;
                &lt;inchoo_observer_customer_address_save_before&gt;
                    &lt;type&gt;singleton&lt;/type&gt;
                    &lt;class&gt;Inchoo_Extension_Model_Observer&lt;/class&gt;
                    &lt;method&gt;geocodeAddress&lt;/method&gt;
                &lt;/inchoo_observer_customer_address_save_before&gt;
            &lt;/observers&gt;
        &lt;/customer_address_save_before&gt;
    &lt;/events&gt;

&lt;/global&gt;
</pre>
<p>Then we create the observer Inchoo_Extension_Model_Observer with something like:</p>
<p>Within that observer we simply need to call something like:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class Inchoo_Extension_Model_Observer
{
	public function geocodeAddress()
	{
		Mage::helper('inchoo/gmap')
			-&gt;fetchAddressGeoCoordinates($observer-&gt;getEvent()-&gt;getCustomerAddress());

		return $this;
	}
}
</pre>
<p>Basically that&#8217;s it. Now each time an address is saved in Magento, there should be a lookup on Google Maps API in order to fetch the longitude and latitude coordinates. Please note, that all of this is just to fetch the coordinates and save them under the address. Showing the actual map somewhere on the frontend or backend requires a bit more input.</p>
<p>To show the Google Map on the frontend with the proper location marker shown on the map you need two things. First we need to add the script like shown below to the head part of the page:</p>
<pre class="brush: php; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.googleapis.com/maps/api/js?key=&lt;?php echo Mage::helper('inchoo/gmap')-&gt;getGoogleMapsApiKey() ?&gt;&amp;sensor=false&quot;&gt;&lt;/script&gt;
</pre>
<p>Then finally we need to add something like:</p>
<pre class="brush: php; title: ; notranslate">

&lt;div id=&quot;address&lt;?php echo $_address-&gt;getId() ?&gt;-gmap&quot; style=&quot;width:480px; height:480px;&quot;&gt;&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
//&lt;![CDATA[

	Event.observe(window, 'load', function() {

			  var myLatlng = new google.maps.LatLng(&lt;?php echo $_address-&gt;getGmapLat() ?&gt;,&lt;?php echo $_address-&gt;getGmapLng() ?&gt;);
			  var myOptions = {
				zoom: 4,
				center: myLatlng,
				mapTypeId: google.maps.MapTypeId.ROADMAP
			  }
			  var map = new google.maps.Map(document.getElementById(&quot;address&lt;?php echo $_address-&gt;getId() ?&gt;-gmap&quot;), myOptions);

			  var marker = new google.maps.Marker({
				  position: myLatlng,
				  map: map,
				  title:&quot;Address Location&quot;
			  });

	});
//]]&gt;
&lt;/script&gt;
</pre>
<p>And that&#8217;s it. Please note, the code above might not be fully copy paste, check the JavaScript when you implement it, and test if your customer address attributes are installed correctly. This article is not for Magento beginners so if you experience some difficulties implementing this approach, please consult the <a href="http://www.magentocommerce.com/knowledge-base">Magento Knowledge Base</a> first.</p>
<p><em>P.S. I was playing with this on Magento CE 1.6.1.0.</em></p>
<p>Hope this was helpful. Cheers.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/geocoding-customer-addresses-in-magento-via-google-maps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Delete test orders in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/delete-test-orders-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/delete-test-orders-in-magento/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 13:27:49 +0000</pubDate>
		<dc:creator>Dejan Radic</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[Orders]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[orders]]></category>
		<category><![CDATA[reports]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=250</guid>
		<description><![CDATA[You got a Magento project to develop, you created a Magento theme, you placed initial products and categories and you also placed some test orders to see if Shipping and Payment methods work as expected. Everything seems to be cool &#8230;<p><a href="http://inchoo.net/ecommerce/magento/delete-test-orders-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>You got a Magento project to develop, you created a Magento theme, you placed initial products and categories and you also placed some test orders to see if Shipping and Payment methods work as expected. Everything seems to be cool and the client wishes to launch the site. You launch it. When you enter the administration for the first time after the launch, you will see all your test orders there. You know those should be deleted. But how?<br />
<strong>This is a new version of the same article.</strong><br />
<span id="more-250"></span></p>
<p>If you try to delete orders in the backend, you will find out that you can only set the status to “cancelled” and the order is still there.  Unfortunately, Magento doesn&#8217;t enable us to delete those via administration, so you will not see any &#8220;Delete order&#8221; button. This can be quite frustrating both to developers and the merchants. People coming from an SAP world find the inability to delete to have some merit but there should be a status that removes the sales count from the reports i.e. sales, inventory, etc.</p>
<p><strong>So, what to do?</strong></p>
<p>You need to create php script in Magento root folder, copy this code into script and run script.</p>
<pre class="brush: php; title: ; notranslate">
/**
 * @author Dejan Radic &lt;dejan.radic@inchoo.net&gt;
 */

if (version_compare(phpversion(), '5.2.0', '&lt;')===true) {
    echo  '&lt;div style=&quot;font:12px/1.35em arial, helvetica, sans-serif;&quot;&gt;&lt;div style=&quot;margin:0 0 25px 0; border-bottom:1px solid #ccc;&quot;&gt;&lt;h3 style=&quot;margin:0; font-size:1.7em; font-weight:normal; text-transform:none; text-align:left; color:#2f2f2f;&quot;&gt;Whoops, it looks like you have an invalid PHP version.&lt;/h3&gt;&lt;/div&gt;&lt;p&gt;Magento supports PHP 5.2.0 or newer. &lt;a href=&quot;http://www.magentocommerce.com/install&quot; target=&quot;&quot;&gt;Find out&lt;/a&gt; how to install&lt;/a&gt; Magento using PHP-CGI as a work-around.&lt;/p&gt;&lt;/div&gt;';
    exit;
}

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

$mageFilename = 'app/Mage.php';

if (!file_exists($mageFilename)) {
    echo $mageFilename.&quot; was not found&quot;;
    exit;
}

require_once $mageFilename;

Mage::app();

$executionPath = null;

/*
 * determine Magento Edition
 */
if (file_exists('LICENSE_EE.txt')) {
    $edition = 'EE';
}elseif (file_exists('LICENSE_PRO.html')) {
    $edition = 'PE';
} else {
    $edition = 'CE';
}

if(($edition=='EE' &amp;&amp; version_compare(Mage::getVersion(), '1.11.0.0.', '&lt;')===true)
        || ($edition=='PE' &amp;&amp; version_compare(Mage::getVersion(), '1.11.0.0.', '&lt;')===true)
        || ($edition=='CE' &amp;&amp; version_compare(Mage::getVersion(), '1.6.0.0.', '&lt;')===true)
  ){
   $executionPath = 'old';
} else {
   $executionPath = 'new';
}

$xpathEntity = 'global/models/sales_entity/entities//table';

if ($executionPath == 'old') {
    $xpathResource = 'global/models/sales_mysql4/entities//table';
} else {
    $xpathResource = 'global/models/sales_resource/entities//table';
}

$salesEntitiesConf = array_merge(
    Mage::getSingleton('core/config')-&gt;init()-&gt;getXpath($xpathEntity),
    Mage::getSingleton('core/config')-&gt;init()-&gt;getXpath($xpathResource)
);

$resource = Mage::getSingleton('core/resource');
$connection = $resource-&gt;getConnection('core_write');

/*
 * If you want delete System/Order Statuses (Status and State) you
 * should comments below lines (46-51)
 */
$skipTables = array (
        $resource-&gt;getTableName('sales_order_status'),
        $resource-&gt;getTableName('sales_order_status_state'),
        $resource-&gt;getTableName('sales_order_status_label')
    );
$salesEntitiesConf = array_diff($salesEntitiesConf, $skipTables);

/*

Multiple RDBMS Support in Magento CE 1.6+ / EE 1.11+

http://www.magentocommerce.com/images/uploads/RDBMS_Guide2.pdf

2.2. Adapters:

... The new Varien_DB_Adapter_Interface was added to sign a contract that all
developed adapters must execute in order to get Magento working on an actual
database. The interface describes the list of methods and constants that can be used by resource models...

Used below in the loop:

 * If $executionPath == 'old'
    * Varien_Db_Adapter_Pdo_Mysql::showTableStatus()
    * Varien_Db_Adapter_Pdo_Mysql::truncate()
 * Else
    * Varien_Db_Adapter_Interface::isTableExists()
    * Varien_Db_Adapter_Interface::truncateTable()

*/

while ($table = current($salesEntitiesConf) ){
    $table = $resource-&gt;getTableName($table);

    if ($executionPath == 'old') {
        $isTableExists = $connection-&gt;showTableStatus($table);
    } else {
        $isTableExists = $connection-&gt;isTableExists($table);
    }
    if ($isTableExists) {
        try {
            if ($executionPath == 'old') {
                $connection-&gt;truncate($table);
            } else {
                $connection-&gt;truncateTable($table);
            }

            printf('Successfully truncated the &lt;i style=&quot;color:green;&quot;&gt;%s&lt;/i&gt; table.&lt;br /&gt;', $table);
        } catch(Exception $e) {
            printf('Error &lt;i style=&quot;color:red;&quot;&gt;%s&lt;/i&gt; occurred truncating the &lt;i style=&quot;color:red;&quot;&gt;%s&lt;/i&gt; table.&lt;br /&gt;', $e-&gt;getMessage(), $table);
        }
    }

    next($salesEntitiesConf);
}

exit('All done...');
</pre>
<p>After you have it executed, the test orders will not be in the database any more. Keep in mind that this will <strong>delete ALL orders</strong>, in the database. So, you should execute this queries immediately after launch.</p>
<p>This script is tested on following Magento versions: 1.6.1.0 CE, 1.6.0.0 CE, 1.5.1.0. CE, 1.11.0.2 EE, 1.10.0.2 EE, 1.9.0.0 EE, 1.11.0.0 PE, 1.10.0.2 PE and 1.9.0.0 PE.<br />
You can <a href="http://inchoo.net/wp-content/uploads/2011/12/deletetestorders.zip">download script here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/delete-test-orders-in-magento/feed/</wfw:commentRss>
		<slash:comments>102</slash:comments>
		</item>
		<item>
		<title>Display HTML code (block) of product options in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/display-html-code-blocks-of-product-options-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/display-html-code-blocks-of-product-options-in-magento/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 12:30:05 +0000</pubDate>
		<dc:creator>Goran Sambolic</dc:creator>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[option]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[type]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11834</guid>
		<description><![CDATA[This simple helper will help you to display html code of your product options. It works with simple, virtual and configurable products. I believe you can use the same approach for other product types as well. Getting HTML code for options &#8230;<p><a href="http://inchoo.net/ecommerce/magento/display-html-code-blocks-of-product-options-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>This simple helper will help you to display html code of your product options. It works with simple, virtual and configurable products. I believe you can use the same approach for other product types as well.</p>
<p>Getting HTML code for options of configurable products its little different from simple and virtual (well they are more or less same).<br />
<strong><br />
Update: for all types in configurable product.</strong></p>
<p><span id="more-11834"></span><br />
With simple products we have a very &#8220;clean approach&#8221;.</p>
<p>First we are setting a block for product options, then we add item renderers (template and type) to product options block. And the last step is to take the product, create iteration over options and display it with our product options block.</p>
<p>We are seeing here some nice loose coupling. Nice separation of code.</p>
<p>On the other hand, getting html code of options in configurable product is not that flexible.</p>
<p>Instance of block, product instance and we are getting html for options.</p>
<p>Sample:</p>
<pre class="brush: php; title: ; notranslate">
echo Mage::helper(&quot;inchoo_checkout&quot;)-&gt;getProductOptionsHtml(Mage::getModel(&quot;catalog/product&quot;)-&gt;load(171));
</pre>
<p>Helper:</p>
<pre class="brush: php; title: ; notranslate">
&lt;!--?php &lt;br ?--&gt;/**
 * @category    Inchoo
 * @package     Inchoo_Checkout
 * @author      Inchoo
 */
class Inchoo_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
{
	/**
	 *
	 * getting html for options of products
	 * @param Mage_Catalog_Model_Product $product
	 */
	public function getProductOptionsHtml(Mage_Catalog_Model_Product $product)
	{
		$blockOption = Mage::app()-&gt;getLayout()-&gt;createBlock(&quot;Mage_Catalog_Block_Product_View_Options&quot;);
        $blockOption-&gt;addOptionRenderer(&quot;default&quot;,&quot;catalog/product_view_options_type_default&quot;,&quot;catalog/product/view/options/type/default.phtml&quot;);
		$blockOption-&gt;addOptionRenderer(&quot;text&quot;,&quot;catalog/product_view_options_type_text&quot;,&quot;inchoo_catalog/product/view/options/type/text.phtml&quot;);
		$blockOption-&gt;addOptionRenderer(&quot;file&quot;,&quot;catalog/product_view_options_type_file&quot;,&quot;catalog/product/view/options/type/file.phtml&quot;);
		$blockOption-&gt;addOptionRenderer(&quot;select&quot;,&quot;inchoo_checkout/product_view_options_type_select&quot;,&quot;catalog/product/view/options/type/select.phtml&quot;);
		$blockOption-&gt;addOptionRenderer(&quot;date&quot;,&quot;catalog/product_view_options_type_date&quot;,&quot;catalog/product/view/options/type/date.phtml&quot;) ;

		$blockOptionsHtml = null;

		 if($product-&gt;getTypeId()==&quot;simple&quot;||$product-&gt;getTypeId()==&quot;virtual&quot;||$product-&gt;getTypeId()==&quot;configurable&quot;)
		 {
		 	$blockOption-&gt;setProduct($product);
			if($product-&gt;getOptions())
			{
				foreach ($product-&gt;getOptions() as $o)
	    		{
	    			$blockOptionsHtml .= $blockOption-&gt;getOptionHtml($o);
	    		};
			}
		 }  

		 if($product-&gt;getTypeId()==&quot;configurable&quot;)
		 {
		 	$blockViewType = Mage::app()-&gt;getLayout()-&gt;createBlock(&quot;Mage_Catalog_Block_Product_View_Type_Configurable&quot;);
		 	$blockViewType-&gt;setProduct($product);
		 	$blockViewType-&gt;setTemplate(&quot;inchoo_catalog/product/view/type/options/configurable.phtml&quot;);
			$blockOptionsHtml .= $blockViewType-&gt;toHtml();
		 }
		 return $blockOptionsHtml;
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/display-html-code-blocks-of-product-options-in-magento/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reusing Magento&#8217;s calendar control</title>
		<link>http://inchoo.net/ecommerce/magento/reusing-magento-calendar-control/</link>
		<comments>http://inchoo.net/ecommerce/magento/reusing-magento-calendar-control/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 09:13:58 +0000</pubDate>
		<dc:creator>Branko Ajzele</dc:creator>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[block]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[control]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11783</guid>
		<description><![CDATA[One of the cool things in Magento is that there is so many controls (widgets, blocks), etc. that you can reuse on the frontend or on the backend. One such control is the calendar control. Calendar control is mostly just &#8230;<p><a href="http://inchoo.net/ecommerce/magento/reusing-magento-calendar-control/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>One of the cool things in Magento is that there is so many controls (widgets, blocks), etc. that you can reuse on the frontend or on the backend. One such control is the calendar control. Calendar control is mostly just used on the backend, aka &#8220;adminhtml&#8221; area. You can easily figure that one out if you do a quick search for a &#8220;Calendar.setup&#8221; string on &#8220;app/design&#8221; folder, in which case you would get several search results but all from &#8220;app/design/adminhtml/&#8221; folder.<span id="more-11783"></span></p>
<p><a href="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.06_09h39m21s_001_.png"><img src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.06_09h39m21s_001_-300x191.png" alt="" title="Snap_2011.12.06_09h39m21s_001_" width="300" height="191" class="alignnone size-thumbnail wp-image-11790" /></a></p>
<p>So the question is how to get the calendar (from image above) to show on the frontend area? Easily, all you need is to include some CSS, few JavaScript&#8217;s, image and you are done. To make things more flexible, I wrote a little block class that does this for you.</p>
<pre class="brush: php; title: ; notranslate">
class Inchoo_Module_Block_Calendar extends Mage_Core_Block_Template
{
    protected function _construct()
    {
        parent::_construct();
        $this-&gt;setTemplate('inchoo/calendar.phtml');
    }

    protected function _prepareLayout()
    {
        $this-&gt;_injectCalendarControlJsCSSInHTMLPageHead();

        return parent::_prepareLayout();
    }    

    private function _injectCalendarControlJsCSSInHTMLPageHead()
    {
        $this-&gt;getLayout()-&gt;getBlock('head')-&gt;append(
            $this-&gt;getLayout()-&gt;createBlock(
                'Mage_Core_Block_Html_Calendar',
                'html_calendar',
                array('template' =&gt; 'page/js/calendar.phtml')
            )
        );

        $this-&gt;getLayout()-&gt;getBlock('head')
                -&gt;addItem('js_css', 'calendar/calendar-win2k-1.css')
                -&gt;addJs('calendar/calendar.js')
                -&gt;addJs('calendar/calendar-setup.js');

        return $this;
    }
}
</pre>
<p>Please note that I placed this block class under the Inchoo/Module namespace, where you can easily make fully new YourCompany/Calendar extension and just put this in it, if you wish your entire extension just for calendar control.</p>
<p>Hopefully, _construct() method is clear to everyone in this case?! If not, then please skip this article entirely and jumo to the <a href="http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-4-magento-layouts-blocks-and-templates">Magento Wiki</a> <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The core of the functionality here lies in the _injectCalendarControlJsCSSInHTMLPageHead() method which is called by _prepareLayout() method. If you study it closely you will see that _injectCalendarControlJsCSSInHTMLPageHead() adds the necessary CSS and JS to the head portion of the HTML page that gets rendered. </p>
<p>With this approach, all we need to do later in our XML layout files is just call our Calendar block like:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;block type=&quot;inchoo/calendar&quot; name=&quot;inchoo.calendar&quot; /&gt;
</pre>
<p>And finally the content of your app/design/frontedn/SOMEPACKAGE/SOMETHEME/template/inchoo/calendar.phtml file should look like:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;span&gt;
    &lt;img style=&quot;&quot; title=&quot;Select Date&quot; id=&quot;date_select_trig&quot; class=&quot;v-middle&quot; alt=&quot;&quot; src=&quot;&lt;?php echo $this-&gt;getSkinUrl(&quot;images/calendar.gif&quot;);?&gt; &quot;/&gt;
    &lt;input type=&quot;text&quot; style=&quot;width: 120px;&quot; class=&quot;input-text&quot; value=&quot;&quot; id=&quot;selected_date&quot; name=&quot;selected_date&quot;/&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
    //&lt;![CDATA[
        Calendar.setup({
            inputField: &quot;selected_date&quot;,
            ifFormat: &quot;%m/%e/%Y %H:%M:%S&quot;,
            showsTime: true,
            button: &quot;date_select_trig&quot;,
            align: &quot;Bl&quot;,
            singleClick : true
        });
    //]]&gt;
    &lt;/script&gt;
&lt;/span&gt;
</pre>
<p>If all of the three files are in place then you should be able to see something like shown on image below.</p>
<p><a href="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.06_09h58m20s_002_.png"><img src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.06_09h58m20s_002_-300x207.png" alt="" title="Snap_2011.12.06_09h58m20s_002_" width="300" height="207" class="alignnone size-thumbnail wp-image-11788" /></a></p>
<p>Additionally, please keep in mind that this is really basic approach. You could do a bit more abstraction to it so that XML layout block accepts few more parameters that would be passed to a Calendar.php block class, like show a bit different calendar, do a bit different format pickup, etc. so that you can truly reuse the same control in various ways.</p>
<p><em>P.S. If Magento is having trouble loading calendar/calendar.js, calendar/calendar-setup.js, calendar/calendar-win2k-1.css then try doing a seach on entire installation and moving them to your theme then modify the addItem, addJs in your Calendar.php block class.</em></p>
<p>Hope this was helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/reusing-magento-calendar-control/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Creating an EAV based model(s) in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/#comments</comments>
		<pubDate>Sun, 04 Dec 2011 12:58:14 +0000</pubDate>
		<dc:creator>Branko Ajzele</dc:creator>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[eav]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[model]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11755</guid>
		<description><![CDATA[Magento database heavily utilizes an Entity-Attribute-Value (EAV) data model. However, the cost of flexibility is often complexity. The process of manipulating EAV data in Magento is often more difficult than manipulating flat relational tables. All Magento Models inherit from the &#8230;<p><a href="http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>Magento database heavily utilizes an Entity-Attribute-Value (EAV) data model. However, the cost of flexibility is often complexity. The process of manipulating EAV data in Magento is often more difficult than manipulating flat relational tables.</p>
<p>All Magento Models inherit from the Mage_Core_Model_Abstract. Difference between simple Model or an EAV Model is its Model Resource. </p>
<p>To build a model with proper collection object in Magento you need 4 things<span id="more-11755"></span>:</p>
<ul>
<li>model class</li>
<li>resource class</li>
<li>collection class</li>
<li>install script (the one found under mymodule_setup folder of your extension)</li>
</ul>
<style>
.gist-highlight .line {
	height:auto!important;
	float:none!important;
	float:none!important;
	background:none!important;
}
</style>
<p>To extend this little further there is one more file you would most likely need when building an EAV based model, the Setup.php which extends from Mage_Eav_Model_Entity_Setup. You would need to implement the getDefaultEntities() method in it as this is what&#8217;s called during the extension installation in Magento.</p>
<p>Imagine your module is called Phonebook and put into the /Inchoo namespace under the local code pool. Logically you would need a model class like User which represents single entry into the phonebook. With this in mind you already need a structure like:</p>
<ul>
<li>app/etc/modules/Inchoo_Phonebook.xml</li>
<li>app/code/local/Inchoo/Phonebook/etc/config.xml</li>
<li>app/code/local/Inchoo/Phonebook/Model/User.php</li>
<li>app/code/local/Inchoo/Phonebook/Model/Resource/User.php</li>
<li>app/code/local/Inchoo/Phonebook/Model/Resource/User/Collection.php</li>
<li>app/code/local/Inchoo/Phonebook/Model/Resource/Setup.php</li>
<li>app/code/local/Inchoo/Phonebook/sql/inchoo_phonebook_setup/install-1.0.0.0.php</li>
</ul>
<p>Now that we outlined the file structure, let&#8217;s get down to it and see what the content of files should look like in order for it to work.</p>
<p>app/etc/modules/Inchoo_Phonebook.xml<br />
<script src="https://gist.github.com/1430081.js?file=gistfile1.xml"></script></p>
<p>app/code/local/Inchoo/Phonebook/etc/config.xml<br />
<script src="https://gist.github.com/1430085.js?file=gistfile1.xml"></script></p>
<p>app/code/local/Inchoo/Phonebook/Model/User.php<br />
<script src="https://gist.github.com/1430086.js?file=gistfile1.aw"></script></p>
<p>app/code/local/Inchoo/Phonebook/Model/Resource/User.php<br />
<script src="https://gist.github.com/1430090.js?file=gistfile1.aw"></script></p>
<p>app/code/local/Inchoo/Phonebook/Model/Resource/User/Collection.php<br />
<script src="https://gist.github.com/1430091.js?file=gistfile1.aw"></script></p>
<p>app/code/local/Inchoo/Phonebook/Model/Resource/Setup.php<br />
<script src="https://gist.github.com/1430096.js?file=gistfile1.aw"></script></p>
<p>app/code/local/Inchoo/Phonebook/sql/inchoo_phonebook_setup/install-1.0.0.0.php<br />
<script src="https://gist.github.com/1430098.js?file=gistfile1.aw"></script></p>
<p>For each attribute type like &#8220;varchar&#8221;, &#8220;text&#8221;, &#8220;int&#8221;&#8230; you need to create a corresponding table like inchoo_phonebook_user_entity_varchar, inchoo_phonebook_user_entity_text, inchoo_phonebook_user_entity_int. Study the install-1.0.0.0.php and the config.xml file to see how to get that one done.</p>

<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h06m02s_001_/' title='Snap_2011.12.04_13h06m02s_001_'><img width="300" height="165" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h06m02s_001_-300x165.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h06m02s_001_" title="Snap_2011.12.04_13h06m02s_001_" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h07m00s_003_core-resource-blog-localhost-table/' title='Snap_2011.12.04_13h07m00s_003_core-resource -blog -localhost- - Table'><img width="300" height="235" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h07m00s_003_core-resource-blog-localhost-Table-300x235.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h07m00s_003_core-resource -blog -localhost- - Table" title="Snap_2011.12.04_13h07m00s_003_core-resource -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h07m34s_004_-nibccapture-02f1dcaf-8f72-4627-b675-014a58d4f832/' title='Snap_2011.12.04_13h07m34s_004_-nibCCapture-02f1dcaf-8f72-4627-b675-014a58d4f832'><img width="300" height="176" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h07m34s_004_-nibCCapture-02f1dcaf-8f72-4627-b675-014a58d4f832-300x176.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h07m34s_004_-nibCCapture-02f1dcaf-8f72-4627-b675-014a58d4f832" title="Snap_2011.12.04_13h07m34s_004_-nibCCapture-02f1dcaf-8f72-4627-b675-014a58d4f832" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h08m10s_005_eav-entity-type-blog-localhost-table/' title='Snap_2011.12.04_13h08m10s_005_eav-entity-type -blog -localhost- - Table'><img width="300" height="157" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h08m10s_005_eav-entity-type-blog-localhost-Table-300x157.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h08m10s_005_eav-entity-type -blog -localhost- - Table" title="Snap_2011.12.04_13h08m10s_005_eav-entity-type -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h11m03s_006_inchoo-phonebook-user-entity-blog-localhost-table/' title='Snap_2011.12.04_13h11m03s_006_inchoo-phonebook-user-entity -blog -localhost- - Table'><img width="300" height="199" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h11m03s_006_inchoo-phonebook-user-entity-blog-localhost-Table-300x199.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h11m03s_006_inchoo-phonebook-user-entity -blog -localhost- - Table" title="Snap_2011.12.04_13h11m03s_006_inchoo-phonebook-user-entity -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h11m18s_007_inchoo-phonebook-user-entity-int-blog-localhost-table/' title='Snap_2011.12.04_13h11m18s_007_inchoo-phonebook-user-entity-int -blog -localhost- - Table'><img width="300" height="204" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h11m18s_007_inchoo-phonebook-user-entity-int-blog-localhost-Table-300x204.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h11m18s_007_inchoo-phonebook-user-entity-int -blog -localhost- - Table" title="Snap_2011.12.04_13h11m18s_007_inchoo-phonebook-user-entity-int -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h11m32s_008_inchoo-phonebook-user-entity-text-blog-localhost-table/' title='Snap_2011.12.04_13h11m32s_008_inchoo-phonebook-user-entity-text -blog -localhost- - Table'><img width="300" height="215" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h11m32s_008_inchoo-phonebook-user-entity-text-blog-localhost-Table-300x215.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h11m32s_008_inchoo-phonebook-user-entity-text -blog -localhost- - Table" title="Snap_2011.12.04_13h11m32s_008_inchoo-phonebook-user-entity-text -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/snap_2011-12-04_13h11m42s_009_inchoo-phonebook-user-entity-varchar-blog-localhost-table/' title='Snap_2011.12.04_13h11m42s_009_inchoo-phonebook-user-entity-varchar -blog -localhost- - Table'><img width="300" height="181" src="http://inchoo.net/wp-content/uploads/2011/12/Snap_2011.12.04_13h11m42s_009_inchoo-phonebook-user-entity-varchar-blog-localhost-Table-300x181.png" class="attachment-thumbnail" alt="Snap_2011.12.04_13h11m42s_009_inchoo-phonebook-user-entity-varchar -blog -localhost- - Table" title="Snap_2011.12.04_13h11m42s_009_inchoo-phonebook-user-entity-varchar -blog -localhost- - Table" /></a>
<a href='http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/attachment/model-4/' title='model'><img width="300" height="118" src="http://inchoo.net/wp-content/uploads/2011/12/model-e1323080904528-300x118.jpg" class="attachment-thumbnail" alt="model" title="model" /></a>

<p>Finally, you can test your model and it’s collection by running the following somewhere in your code:<br />
<script src="https://gist.github.com/1430101.js?file=gistfile1.aw"></script></p>
<p>And that&#8217;s it. Although simple, there is some typing to be done in order to get the EAV based model functional. Hope it helps someone. </p>
<p>Cheers.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Simple Helper class for Previous/Next Products in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/simple-helper-class-for-previous-next-products-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/simple-helper-class-for-previous-next-products-in-magento/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 13:15:04 +0000</pubDate>
		<dc:creator>Vedran Subotic</dc:creator>
				<category><![CDATA[Frontend]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[magento helper]]></category>
		<category><![CDATA[magento product]]></category>
		<category><![CDATA[previous next product]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11724</guid>
		<description><![CDATA[One of the common requirements in Magento is to have prev/next product on Product Information page. Development logic there is simple, fetch current product id and take the one before and after that one and now you have previous and &#8230;<p><a href="http://inchoo.net/ecommerce/magento/simple-helper-class-for-previous-next-products-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>One of the common requirements in Magento is to have prev/next product on Product Information page. Development logic there is simple, fetch current product id and take the one before and after that one and now you have previous and next products <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Remember that this will work per category only, since you will get list of products in current category.</p>
<p><span id="more-11724"></span></p>
<p>So how will next code work?<br />
If you dump next line of code in your catalog/product/view.phtml:</p>
<pre class="brush: php; title: ; notranslate">
Mage::registry('current_category')-&gt;getProductsPosition();
</pre>
<p>You will get array with keys of product id&#8217;s and product positions as values of that current category.</p>
<p>I&#8217;m not going to put full module here since you can use this helper in any other module, you just need to call it with right name in your template file.</p>
<p>Here comes the helper class:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * INCHOO's FREE EXTENSION DISCLAIMER
 *
 * Please do not edit or add to this file if you wish to upgrade Magento
 * or this extension to newer versions in the future.
 *
 * Inchoo developers (Inchooer's) give their best to conform to
 * &quot;non-obtrusive, best Magento practices&quot; style of coding.
 * However, Inchoo does not guarantee functional accuracy of specific
 * extension behavior. Additionally we take no responsibility for any
 * possible issue(s) resulting from extension usage.
 *
 * We reserve the full right not to provide any kind of support for our free extensions.
 *
 * You are encouraged to report a bug, if you spot any,
 * via sending an email to bugreport@inchoo.net. However we do not guaranty
 * fix will be released in any reasonable time, if ever,
 * or that it will actually fix any issue resulting from it.
 *
 * Thank you for your understanding.
 */

/**
 * @category Inchoo
 * @package Inchoo_Catalog
 * @author Vedran Subotic &lt;vedran@inchoo.net&gt;
 * @copyright Inchoo &lt;http://inchoo.net&gt;
 * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
class Inchoo_Catalog_Helper_Data extends Mage_Core_Helper_Abstract
{
	public function getPreviousProduct()
    {
        $prodId = Mage::registry('current_product')-&gt;getId();

        $catArray = Mage::registry('current_category');

        if($catArray){
            $catArray = $catArray-&gt;getProductsPosition();
            $keys = array_flip(array_keys($catArray));
            $values = array_keys($catArray);

            $productId = $values[$keys[$prodId]-1];

            $product = Mage::getModel('catalog/product');

            if($productId){
                $product-&gt;load($productId);
                return $product-&gt;getProductUrl();
            }
            return false;
        }

        return false;

    }

    public function getNextProduct()
    {
        $prodId = Mage::registry('current_product')-&gt;getId();

        $catArray = Mage::registry('current_category');

        if($catArray){
            $catArray = $catArray-&gt;getProductsPosition();
            $keys = array_flip(array_keys($catArray));
            $values = array_keys($catArray);

            $productId = $values[$keys[$prodId]-1];

            $product = Mage::getModel('catalog/product');

            if($productId){
                $product-&gt;load($productId);
                return $product-&gt;getProductUrl();
            }
            return false;
        }

        return false;
    }

}
</pre>
<p>All you need is to generate new links on product view page:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php $_prev = $this-&gt;helper('inchoo_catalog')-&gt;getPreviousProduct(); ?&gt;
&lt;?php $_next = $this-&gt;helper('inchoo_catalog')-&gt;getNextProduct(); ?&gt;

&lt;?php if($_prev): ?&gt;&lt;a class=&quot;product-prev&quot; href=&quot;&lt;?php echo $_prev;?&gt;&quot;&gt;&lt;?php echo $this-&gt;__('&lt; Previous')?&gt;&lt;/a&gt;&lt;?php endif; ?&gt;
&lt;?php if($_next): ?&gt;&lt;a class=&quot;product-next&quot; href=&quot;&lt;?php echo $_next;?&gt;&quot;&gt;&lt;?php echo $this-&gt;__('Next &gt;')?&gt;&lt;/a&gt;&lt;?php endif; ?&gt;
</pre>
<p>Note: this will not work for all cases in layered navigation, since layered navigation doesn&#8217;t work that way and may consist of product collection from different categories.</p>
<p>Enjoy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/simple-helper-class-for-previous-next-products-in-magento/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>View product in frontend from Magento admin</title>
		<link>http://inchoo.net/ecommerce/magento/view-product-in-frontend-from-magento-admin/</link>
		<comments>http://inchoo.net/ecommerce/magento/view-product-in-frontend-from-magento-admin/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 12:26:51 +0000</pubDate>
		<dc:creator>Ivica Tadic</dc:creator>
				<category><![CDATA[Administration]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[magento administration]]></category>
		<category><![CDATA[products]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11641</guid>
		<description><![CDATA[When you are editing some product in Magento admin and want to check it out in frontend of your Magento project, how do you find this particular product? Do you search for it, navigate to it using product url key &#8230;<p><a href="http://inchoo.net/ecommerce/magento/view-product-in-frontend-from-magento-admin/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>When you are editing some product in Magento admin and want to check it out in frontend of your Magento project, how do you find this particular product? Do you search for it, navigate to it using product url key or just browse to it? Well, however you do it, I’m going to give you the easiest way to get to your desired product in the frontend &#8211; view product link.<br />
<span id="more-11641"></span><br />
<a href="http://inchoo.net/wp-content/uploads/2011/11/Tadic_AVP-screenshot.png"><img src="http://inchoo.net/wp-content/uploads/2011/11/Tadic_AVP-screenshot.png" alt="Tadic_AVP screenshot" title="Tadic_AVP-screenshot" width="620" height="203" class="aligncenter size-full wp-image-11642" /></a></p>
<p>Here’s an extremely lightweight Magento extension which will provide you with a simple <em>view product</em> link next to a product name, in Magento admin. It will point to a product view page in the frontend of your Magento project. Simple and easy.</p>
<p><a href="https://github.com/ivicatadic/Tadic_AVP" title="https://github.com/ivicatadic/Tadic_AVP" target="_blank">https://github.com/ivicatadic/Tadic_AVP</a><br />
or for donwload<br />
<a href='http://inchoo.net/wp-content/uploads/2011/11/Tadic_AVP.zip'>Tadic_AVP</a></p>
<p>All you have to do is copy the content of Tadic_AVP extension (app folder) to a root folder of your Magento project &#8211; and that’s it. I hope this simple extension will prove to be useful to you.<br />
Thanks to <a href="http://inchoo.net/author/branko/">Branko Ajzele</a> for an idea.</p>
<p>Cheers</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/view-product-in-frontend-from-magento-admin/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Executing Magento Indexer From Shell</title>
		<link>http://inchoo.net/ecommerce/magento/executing-magento-indexer-from-shell/</link>
		<comments>http://inchoo.net/ecommerce/magento/executing-magento-indexer-from-shell/#comments</comments>
		<pubDate>Fri, 11 Nov 2011 08:43:55 +0000</pubDate>
		<dc:creator>Domagoj Potkoc</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[indexer]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11488</guid>
		<description><![CDATA[In some situation when you want to re-index Magento catalog you will get an error message or reindex process will be broken. This problem is appearing when you have a lot of products in database and limited server resource. You &#8230;<p><a href="http://inchoo.net/ecommerce/magento/executing-magento-indexer-from-shell/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>In some situation when you want to re-index Magento catalog you will get an error message or reindex process will be broken. This problem is appearing when you have a lot of products in database and limited server resource. You can try to reindex from command line or shell.<span id="more-11488"></span><br />
In Magento there is folder with name &#8220;<strong>shell</strong>&#8221; in this folder you will find file with name &#8220;<strong>indexer.php</strong>&#8221; this is shell script for reindexing. You will ask yourself how to call this script, and take a look on my examples below and everything will be clear. </p>
<p>First of all you need to have access to linux commnad line or shell, and then go to your &#8220;<strong>MAGENTO_ROOT_FOLDER/shell</strong>&#8220;. </p>
<pre class="brush: php; title: ; notranslate">
-jailshell-3.2$ pwd
/home/mcomerce
-jailshell-3.2$ ls
access-logs            etc   perl5    public_ftp   ssl  www
cpbackup-exclude.conf  mail  php.ini  public_html  tmp
-jailshell-3.2$ cd public_html/
-jailshell-3.2$ cd shell/
-jailshell-3.2$ ls
abstract.php  compiler.php  indexer.php  log.php
-jailshell-3.2$
</pre>
<p>Our first example is how to get help from &#8220;indexer.php&#8221; script, you need to execute next comand<br />
&#8220;<strong>php -f indexer.php help</strong>&#8221; and you will get response as in example below.</p>
<pre class="brush: php; title: ; notranslate">
$ php -f indexer.php help
  --status &lt;indexer&gt;            Show Indexer(s) Status
  --mode &lt;indexer&gt;              Show Indexer(s) Index Mode
  --mode-realtime &lt;indexer&gt;     Set index mode type &quot;Update on Save&quot;
  --mode-manual &lt;indexer&gt;       Set index mode type &quot;Manual Update&quot;
  --reindex &lt;indexer&gt;           Reindex Data
  info                          Show allowed indexers
  reindexall                    Reindex Data by all indexers
  help                          This help

  &lt;indexer&gt;     Comma separated indexer codes or value &quot;all&quot; for all indexers
</pre>
<p>You can see that you can make reindexall but <strong>I don&#8217;t recommend that you execute full reindex in one step</strong>, beacuse you can cause MySql/Server overload. Reindexall calls 8 indexers in a row and process of reindexing can cause database LOCK on some database tables.</p>
<p>I recommend that you execute one by one indexer. You process will be faster and load of database will be smaller.</p>
<p>In Magento there are 8 indexers, you can get list of indexers if you call next command:<br />
<strong>php -f indexer.php info</strong></p>
<pre class="brush: php; title: ; notranslate">
-jailshell-3.2$ php -f indexer.php info
catalog_product_attribute     Product Attributes
catalog_product_price         Product Prices
catalog_url                   Catalog Url Rewrites
catalog_product_flat          Product Flat Data
catalog_category_flat         Category Flat Data
catalog_category_product      Category Products
catalogsearch_fulltext        Catalog Search Index
cataloginventory_stock        Stock status
-jailshell-3.2$
</pre>
<p>For example if you want to reindex &#8220;<strong>catalog_url</strong>&#8221; you need to execute next command:<br />
<strong>php -f indexer.php &#8212; -reindex catalog_url</strong>, below is example</p>
<pre class="brush: php; title: ; notranslate">
-jailshell-3.2$ php -f indexer.php -- -reindex catalog_url
Catalog URL Rewrites index was rebuilt successfully
-jailshell-3.2$
</pre>
<p>I recommend that you use indexer from shell because this process isn&#8217;t executing over web server/Apache and makes smaller impact on server resources <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p><strong>One note:</strong> I had problem with php memory limit, error message: &#8220;<strong>Fatal error:  Allowed memory size of 67108864 bytes exhausted (tried to allocate 88 bytes)</strong>&#8220;. I increased memory size to 128Mb, I added next statement on beginning of script:<strong>ini_set(&#8216;memory_limit&#8217;, &#8217;128M&#8217;);</strong> .<br />
That&#8217;s all for now <img src='http://inchoo.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/executing-magento-indexer-from-shell/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Playing with customer collection in Magento</title>
		<link>http://inchoo.net/ecommerce/magento/playing-with-customer-collection-in-magento/</link>
		<comments>http://inchoo.net/ecommerce/magento/playing-with-customer-collection-in-magento/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 12:21:25 +0000</pubDate>
		<dc:creator>Dejan Radic</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[customer]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11390</guid>
		<description><![CDATA[In this article I&#8217;ll give you some example how to get different collection of customers. For example, how to get latest 5 customers, unconfirmed customers, latest 5 customers who purchased something etc. I&#8217;ll create few objects that are instances of &#8230;<p><a href="http://inchoo.net/ecommerce/magento/playing-with-customer-collection-in-magento/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>In this article I&#8217;ll give you some example how to get different collection of customers.<br />
For example, how to get latest 5 customers, unconfirmed customers, latest 5 customers who purchased something etc.<br />
<span id="more-11390"></span></p>
<p>I&#8217;ll create few objects that are instances of <strong>Mage_Customer_Model_Resource_Customer_Collection</strong> class and few objects that are instances of <strong>Inchoo_CustomerCollection_Model_Resource_Customer_Totals_Collection</strong> class.<br />
Class <strong>Inchoo_CustomerCollection_Model_Resource_Customer_Totals_Collection</strong> extends <strong>Mage_Reports_Model_Resource_Customer_Totals_Collection</strong> class.</p>
<p>Let&#8217;s take a look.</p>
<p><strong>How to get Not confirmed customers?</strong></p>
<pre class="brush: php; title: ; notranslate">
$collection = Mage::getResourceModel('customer/customer_collection')
    -&gt;addNameToSelect()
    -&gt;joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left')
    -&gt;joinField('notconfirmed',
        'customer_entity_varchar',
        'attribute_id',
        'entity_id=entity_id',
        &quot;{{table}}.attribute_id='831'&quot;);

$this-&gt;setCollection($collection);
return parent::_prepareCollection();
</pre>
<p>The last parameter of joinField is string which contain table, field and value &#8220;831&#8243;. Value &#8220;831&#8243; is &#8216;attribute_id&#8217; from &#8216;eav_attribute&#8217; table where &#8216;attribute_code&#8217; is equal &#8220;confirmation&#8221;.</p>
<p><strong>How to get customers with Gmail account?</strong></p>
<pre class="brush: php; title: ; notranslate">
$collection = Mage::getResourceModel('customer/customer_collection')
    -&gt;addNameToSelect()
    -&gt;joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
    -&gt;joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left')
    -&gt;addFieldToFilter('email',array('like'=&gt;'%@gmail.com'));

$this-&gt;setCollection($collection);
return parent::_prepareCollection();
</pre>
<p><strong>How to get customer with the largest purchased amount?</strong></p>
<p>$collection is instance of <strong>Inchoo_CustomerCollection_Model_Resource_Customer_Totals_Collection</strong>. Methods: addTotalOrderAmount(), addBillingData() and addCustomerData() are declared in <strong>Inchoo_CustomerCollection_Model_Resource_Customer_Totals_Collection</strong> class.</p>
<pre class="brush: php; title: ; notranslate">
public function __construct()
{
    parent::__construct();
    $this-&gt;setId('customerGrid');
    $this-&gt;setPagerVisibility(false);
    $this-&gt;setFilterVisibility(false);
    $this-&gt;setDefaultLimit(1);
}

protected function _prepareCollection()
{
    $collection = Mage::getResourceModel('customercollection/customer_totals_collection');
    $collection-&gt;joinCustomerName()
         -&gt;groupByCustomer()
         -&gt;addTotalOrderAmount()
         -&gt;addBillingData()
         -&gt;addCustomerData()
         -&gt;orderByTotalAmount();

    $this-&gt;setCollection($collection);
    return parent::_prepareCollection();
}
</pre>
<p>These collections of customers, You can see under Customer-&gt;Customer Collection.</p>
<p><a href="http://inchoo.net/wp-content/uploads/2011/11/playing-with-customer-collections-menu.jpg"><img class="aligncenter size-medium wp-image-11395" title="Menu" src="http://inchoo.net/wp-content/uploads/2011/11/playing-with-customer-collections-menu-150x150.jpg" alt="Menu" width="150" height="150" /></a></p>
<p>As you can see on the picture bellow, I decided to disable filtering options, sorting by column and Massaction Block.</p>
<p><a href="http://inchoo.net/wp-content/uploads/2011/11/playing-with-customer-collections-grid.jpg"><img class="aligncenter size-medium wp-image-11396" title="Latest 5 Customers who purchased something" src="http://inchoo.net/wp-content/uploads/2011/11/playing-with-customer-collections-grid-600x113.jpg" alt="Latest 5 Customers who purchased something" width="600" height="113" /></a></p>
<p>CustomerCollection extension is tested on Magento CE 1.6.1.0. You can <a href="http://inchoo.net/wp-content/uploads/2011/11/Inchoo_CustomerCollection.zip">download extension here</a>.</p>
<p>Cheers.</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/playing-with-customer-collection-in-magento/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Magento Lite experiment</title>
		<link>http://inchoo.net/ecommerce/magento/magento-lite-experiment/</link>
		<comments>http://inchoo.net/ecommerce/magento/magento-lite-experiment/#comments</comments>
		<pubDate>Sun, 06 Nov 2011 20:11:22 +0000</pubDate>
		<dc:creator>Ivan Weiler</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[lite]]></category>

		<guid isPermaLink="false">http://inchoo.net/?p=11330</guid>
		<description><![CDATA[No, it&#8217;s not April Fools&#8217; Day, it&#8217;s November, no Inchoo pranks. We played with something new this time. You all heard that Magento is modular platform a hundred times. It just needs a little push sometimes, so we pushed it &#8230;<p><a href="http://inchoo.net/ecommerce/magento/magento-lite-experiment/">Read more</a><p>]]></description>
			<content:encoded><![CDATA[<p>No, it&#8217;s not April Fools&#8217; Day, it&#8217;s November, no Inchoo pranks. We played with something new this time. You all heard that Magento is modular platform a hundred times. It just needs a little push sometimes, so we pushed it <img src='http://inchoo.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  First of all ..<br />
<span id="more-11330"></span><br />
<strong style="font-size:15px;">Don&#8217;t use in production environments, this is only an experiment!</strong></p>
<p>We wanted to show what can be done and how great Magento really is. We don&#8217;t have any plans other than use some of the code presented here for our custom projects and learning purposes, so no updates guaranteed.</p>
<h2>About</h2>
<p>Magento Lite is extension that compensates module dependency and makes Magento truly modular.<br />
By default it fully disables over 35 default Magento modules, there are over 120 DB tables less and over 2000 files can be safely deleted from Magento.</p>
<p>Any single disabled module can be enabled and restored again.</p>
<p>It removes &#8220;system&#8221; flag from most not needed attributes and creates optional Lite product attribute set.<br />
It hides non-active modules in &#8220;Disable Modules Output&#8221;.<br />
It optionally hides Recurrent Billing, Billing Agreements, Related, Upsell, Crosssell products from system (WIP).</p>
<h2>Goal</h2>
<p>To have only basic e-commerce functionalities like catalog, cart, checkout, etc. in Magento.<br />
To have fully upgradable platform ideal for custom projects and learning purposes.</p>
<h2>Compatibility</h2>
<p>Magento CE >= 1.6.0.0. Tested on 1.6.0.0 and 1.6.1.0.</p>
<h2>Instalation</h2>
<p>Download Magento and unpack, copy/paste Weiler_Lite module in it, install Magento.</p>
<p>It&#8217;s tested only on fresh/clean installations. In theory it should work on already set store, but then database has unneeded tables and attributes since this module doesn&#8217;t remove them and probably never will. It&#8217;s not tested with sample data, but it probably works.</p>
<p>To enable any disabled module edit app/etc/modules/Weiler_Lite.xml and set its &lt;active&gt; to true.</p>
<h2>Notes</h2>
<p>Mage_CatalogRule and Mage_Rule can also be safely disabled/removed, but there is no way to do that without touching Mage_All.xml since there is no way to rewrite &lt;depends&gt; definitions. There is Mage_All.xml.lite file if someone wants to experiment.</p>
<p>Mage_Dataflow can also be disabled this way, but that module shouldn&#8217;t be deleted since Eav is extending few classes from there.</p>
<p>I also wanted to disable Mage_Reports and Mage_Log but 30% of Magento is broken then.</p>
<p>Rss, Weee, Wishlist and GiftMessage helpers are rewritten to avoid changing tons of theme phtml files.<br />
It was just easier this way, method is highly questionable. Otherwise we need lite frontend theme.<br />
Current frontend lite theme is just experimental, it can be removed.</p>
<p>Some block are deliberately rewritten instead of using hooks, it&#8217;s easier to maintain updates that way.</p>
<h2>Download</h2>
<p><a href="http://inchoo.net/wp-content/uploads/2011/11/Magento_Lite.zip" target="_blank">Magento_Lite_1.6.1.0.zip</a></p>
<h2>Screenshots</h2>

<a href='http://inchoo.net/ecommerce/magento/magento-lite-experiment/attachment/magento-lite-product-edit/' title='magento-lite-product-edit'><img width="300" height="167" src="http://inchoo.net/wp-content/uploads/2011/11/magento-lite-product-edit-300x167.jpg" class="attachment-thumbnail" alt="magento-lite-product-edit" title="magento-lite-product-edit" /></a>
<a href='http://inchoo.net/ecommerce/magento/magento-lite-experiment/attachment/magento-lite-attribute-set/' title='magento-lite-attribute-set'><img width="300" height="182" src="http://inchoo.net/wp-content/uploads/2011/11/magento-lite-attribute-set-300x182.jpg" class="attachment-thumbnail" alt="magento-lite-attribute-set" title="magento-lite-attribute-set" /></a>
<a href='http://inchoo.net/ecommerce/magento/magento-lite-experiment/attachment/magento-lite-disable-modules-output/' title='magento-lite-disable-modules-output'><img width="300" height="238" src="http://inchoo.net/wp-content/uploads/2011/11/magento-lite-disable-modules-output-300x238.jpg" class="attachment-thumbnail" alt="magento-lite-disable-modules-output" title="magento-lite-disable-modules-output" /></a>
<a href='http://inchoo.net/ecommerce/magento/magento-lite-experiment/attachment/magento-lite-editor-modules/' title='magento-lite-editor-modules'><img width="142" height="300" src="http://inchoo.net/wp-content/uploads/2011/11/magento-lite-editor-modules-142x300.jpg" class="attachment-thumbnail" alt="magento-lite-editor-modules" title="magento-lite-editor-modules" /></a>

<p>Make sure to comment, thx!<br />
&#8211;Ivan</p>
]]></content:encoded>
			<wfw:commentRss>http://inchoo.net/ecommerce/magento/magento-lite-experiment/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.558 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-10 05:07:16 -->

