22 February 2010

magento-css-buttons-pure-css-buttons
Many developers and store owners don’t like to use images as buttons simply because they do not wish their users to wait until the images load. Image buttons gives the flexibility to display images as per store’s requirement but these days lots and lots of stores are opting to create CSS image buttons rather than image buttons. With a very little tweak you can get rid of image buttons in your theme and switch to CSS buttons. If you are willing to change your image buttons to CSS powered buttons then follow the steps given below:

Take a nice background image which is blank and nothing written on it. We will use this background image to generate text over it. Basically, if you follow CSS buttons you don’t have to create separate images for each button. Download the background image given below for an example (you can create your own image background).

btn-proceed-to-checkout-bg btn-proceed-to-checkout-rad

In your theme template you will find various instances where you have to change image button to CSS button. For an example we will take “Proceed to Checkout” button code app/design/frontend/default/Your_theme/template/checkout/onepage/link.phtml

By default you will see something like this (if you are using default theme)

1
<a href="<?=$this->getCheckoutUrl()?>"><img src="<?=$this->getSkinUrl('images/btn_proceed_to_checkout.gif')?>" alt="<?=__('Proceed to Checkout')?>"/></a>

Now, we will use CSS and HTML to tweak and change the background for this button.

1
<a class="css-button btn-checkout" href="<?php echo $this->getCheckoutUrl()?>"><span><?php echo Mage::helper('checkout')->__('Proceed to Checkout');?></span></a>

Note: if you are using v 1.7 then change like this

1
<a class="css-button btn-checkout" href="<?php echo $this->getCheckoutUrl()?>"><span><?php echo $this->__('Proceed to Checkout')?></span></a>

You will notice that we have called css-button class along with btn-checkout which will enable us to change font color or size later if needed. Your CSS button is ready. Now, lets write the CSS for this button

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.btn-checkout {
display:block;
float:right;
background:transparent url(../images/btn_proceed_to_checkout_rad.gif) no-repeat 100% 0;
font-size:15px;
font-weight:bold;
padding-right:8px;
}
.btn-checkout, .btn-checkout:hover {
color:#fef5e5;
text-decoration:none;
}
.btn-checkout span {
display:block;
padding:0 17px 0 25px;
background:transparent url(../images/btn_proceed_to_checkout_bg.gif) no-repeat;
line-height:40px;
}

You are done, your CSS button is ready, just clear your cache and see the CSS button.

Similarly, you can change the buttons of other instances like Add To Cart etc. E.g. app/design/frontend/default/your_theme/template/checkout/onepage/review.phtml

change this

1
<input type="image" src="<?php echo $this->getSkinUrl('images/btn_place_order.gif') ?>" onclick="review.save();" value="<?php echo $this->__('Place Order') ?>" />

To

1
<a class="css-button btn-checkout" href="#" onclick="review.save();"><span><?php echo $this->__('Place Order') ;?></span></a>

Changing image buttons to CSS buttons is an easy task if you follow the steps given above but make sure that you switch to all instances of image buttons to CSS one’s otherwise your store might look awkward. Please leave me a comment and let me know if this trick helped you to convert your Magento store image buttons to CSS buttons. Don’t forget to subscribe our RSS to receive latest updates delivered to your mailbox.


29 January 2010

delete-magento-test-orders

Are you wondering how to delete all test orders you have made in Magento while testing? In Sandbox mode store owners performs many transactions to make sure that their Magento powered store is capable of handling payment transactions. You can use any Payment Gateways like PayPal, Authorize.net, PayFlow or Amazon Simple Pay. But all the test orders remain in system even when your store goes into production.
Unfortunately, there is no way in Magento to delete those test orders which were made while testing the Magento store. You can only process these order and set their status as “Cancelled” but you can’t really delete those test orders from your store. I am sure that you would love to see a “Delete selected Orders” button in Magento Admin panel; unfortunately you won’t find such functionality. In order to delete these test orders you have to log in to your PhpmyAdmin using full access and run few queries to get rid of those test orders.

How To Delete A Single Test Order Using PhpMyAdmin

You need to run the following query on your database using PhpMyAdmin:

1
2
3
4
  set @increment_id='200000111';
  select @order_id:=entity_id from prefix_sales_order_entity where increment_id=@increment_id;
  delete from prefix_sales_order_entity where entity_id=@order_id or parent_id=@order_id;
  delete from prefix_sales_order where increment_id=@increment_id;

In the above example we are trying to delete test order # ‘200000111′. Generally people use prefix so change the “prefix_” in the above query with the prefix you have chosen for your Magento store.

The above query will delete the single test order or even an actual order from your Magento store. All you have to do is provide an order number and database prefix. Rest will be taken care of automatically.

How To Delete All Magento Test Orders In One Go

This step is done only on new store which are ready forproduction and don’t have any “Actual Orders” in the system. I would highly recommend taking a full backup before you proceed. Basically when you run the following queries on your Magento database it will complete wipe out all the records and reset the order counters. If you are about to indulge, then please make sure that you know what you are doing.

Beware: The following steps can’t be reversed.

Go to your PhpMyAdmin and run SQL Query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  SET FOREIGN_KEY_CHECKS=0;
 
  TRUNCATE `sales_order`;
  TRUNCATE `sales_order_datetime`;
  TRUNCATE `sales_order_decimal`;
  TRUNCATE `sales_order_entity`;
  TRUNCATE `sales_order_entity_datetime`;
  TRUNCATE `sales_order_entity_decimal`;
  TRUNCATE `sales_order_entity_int`;
  TRUNCATE `sales_order_entity_text`;
  TRUNCATE `sales_order_entity_varchar`;
  TRUNCATE `sales_order_int`;
  TRUNCATE `sales_order_text`;
  TRUNCATE `sales_order_varchar`;
  TRUNCATE `sales_flat_quote`;
  TRUNCATE `sales_flat_quote_address`;
  TRUNCATE `sales_flat_quote_address_item`;
  TRUNCATE `sales_flat_quote_item`;
  TRUNCATE `sales_flat_quote_item_option`;
  TRUNCATE `sales_flat_order_item`;
  TRUNCATE `sendfriend_log`;
  TRUNCATE `tag`;
  TRUNCATE `tag_relation`;
  TRUNCATE `tag_summary`;
  TRUNCATE `wishlist`;
  TRUNCATE `log_quote`;
  TRUNCATE `report_event`;
 
  ALTER TABLE `sales_order` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_int` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_text` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_address` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_address_item` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_item` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_item_option` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_order_item` AUTO_INCREMENT=1;
  ALTER TABLE `sendfriend_log` AUTO_INCREMENT=1;
  ALTER TABLE `tag` AUTO_INCREMENT=1;
  ALTER TABLE `tag_relation` AUTO_INCREMENT=1;
  ALTER TABLE `tag_summary` AUTO_INCREMENT=1;
  ALTER TABLE `wishlist` AUTO_INCREMENT=1;
  ALTER TABLE `log_quote` AUTO_INCREMENT=1;
  ALTER TABLE `report_event` AUTO_INCREMENT=1;
 
  -- lets reset customers
  TRUNCATE `customer_address_entity`;
  TRUNCATE `customer_address_entity_datetime`;
  TRUNCATE `customer_address_entity_decimal`;
  TRUNCATE `customer_address_entity_int`;
  TRUNCATE `customer_address_entity_text`;
  TRUNCATE `customer_address_entity_varchar`;
  TRUNCATE `customer_entity`;
  TRUNCATE `customer_entity_datetime`;
  TRUNCATE `customer_entity_decimal`;
  TRUNCATE `customer_entity_int`;
  TRUNCATE `customer_entity_text`;
  TRUNCATE `customer_entity_varchar`;
  TRUNCATE `log_customer`;
  TRUNCATE `log_visitor`;
  TRUNCATE `log_visitor_info`;
 
  ALTER TABLE `customer_address_entity` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `log_customer` AUTO_INCREMENT=1;
  ALTER TABLE `log_visitor` AUTO_INCREMENT=1;
  ALTER TABLE `log_visitor_info` AUTO_INCREMENT=1;
 
  -- Now, lets Reset all ID counters
  TRUNCATE `eav_entity_store`;
  ALTER TABLE  `eav_entity_store` AUTO_INCREMENT=1;
 
  SET FOREIGN_KEY_CHECKS=1;

Optional: If you are looking to set appropriate prefixes for orders, invoices, shipments, credit memos then run the following query as well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
 INSERT INTO  `YOUR_DB_NAME`.`eav_entity_store` (`entity_store_id` ,`entity_type_id` ,`store_id` ,`increment_prefix` ,`increment_last_id`) VALUES ('1',  '11',  '1',  '1',  '000000000');
 update `eav_entity_store` set `increment_prefix`= 1 where `entity_type_id`='4' and `store_id`='1';
 update `eav_entity_store` set `increment_last_id`= '000000000' where `entity_type_id`='4' and `store_id`='1';
 
 INSERT INTO  `YOUR_DB_NAME`.`eav_entity_store` (`entity_store_id` ,`entity_type_id` ,`store_id` ,`increment_prefix` ,`increment_last_id`) VALUES ('2',  '16',  '1',  '2',  '000000000');
 update `eav_entity_store` set `increment_prefix`= 2 where `entity_type_id`='18' and `store_id`='1';
 update `eav_entity_store` set `increment_last_id`= '000000000' where `entity_type_id`='18' and `store_id`='1';
 
 INSERT INTO  `YOUR_DB_NAME`.`eav_entity_store` (`entity_store_id` ,`entity_type_id` ,`store_id` ,`increment_prefix` ,`increment_last_id`) VALUES ('3',  '19',  '1',  '3',  '000000000');
 update `eav_entity_store` set `increment_prefix`= 3 where `entity_type_id`='24' and `store_id`='1';
 update `eav_entity_store` set `increment_last_id`= '000000000' where `entity_type_id`='24' and `store_id`='1';
 
 INSERT INTO  `YOUR_DB_NAME`.`eav_entity_store` (`entity_store_id` ,`entity_type_id` ,`store_id` ,`increment_prefix` ,`increment_last_id`) VALUES ('4',  '23',  '1',  '4',  '000000000');
 update `eav_entity_store` set `increment_prefix`= 4 where `entity_type_id`='28' and `store_id`='1';
 update `eav_entity_store` set `increment_last_id`= '000000000' where `entity_type_id`='28' and `store_id`='1';

Now, all the test orders, customer orders, logs etc are all gone from your Magento store and it will be in a clean state to start over.

Should you run into any trouble? Please leave me a comment and let me know. Don’t forget to subscribe our RSS to receive latest updates delivered to your mailbox for Free.


19 January 2010

Magento powered stores or any other Ecommerce stores rely on the fact that no matter how many products they can display on their home page people will surely search for their desired products in order to purchase online. Default search box which comes with the Magento installation is quite powerful in searching and showing product catalogue but still many store owners prefers to use Google Site Search in their Magento powered stores.

Google Site Search Advantages For Magento Stores

Google Site Search saves you from the overhead of heavy searches on your site making your site go slow. If Google site search is used you won’t be computing any results on your store rather showing what is already indexed in Google.

Google Site Search Disadvantages For Magento Stores

Google indexes the entire page and not just the main content area which is the core of the problem while using Google Site Search. However, you can exclude certain phrases that distort the results (through the minus – switch). You can use Google appliance which supports excluding parts of page content from indexing with the googleon/googleoff tags. Find out more in the docs here

How To Generate Google Site Search Code

There are two variants of Google Site Search

  1. Paid (starts from $100/year)
  2. Free

In this example we will concentrate on Creating Free Google Site search code which can be found at http://www.google.com/cse

In order to generate Google Site Search code you need to follow few steps:

1. Signup or login to google.com/cse to generate Google Site search code for your magento powered store.

Google-cse

2. Setup search engine by filling up the form. See the screenshot given below

Google-cse_2

3. Try searching something to verify that it is searching properly.

Google-cse_3
4. Now, click finish and go to your Search engine control panel.
5. Click on “Look & Feel” and optimize your search engine to match with your store layout.
6. Once all the customization etc. are done click on “Get Code” you will see a small code which you should copy (we will paste this code in our Magento powered store). e.g. code

1
2
3
4
5
6
7
8
9
10
11
<div id="cse" style="width: 100%;">Loading</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
  google.load('search', '1', {language : 'en'});
  google.setOnLoadCallback(function(){
    var customSearchControl = new google.search.CustomSearchControl('016670295340374400304:b3-qspp3ozs');
    customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
    customSearchControl.draw('cse');
  }, true);
</script>
<link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" />

How To Embed Google Site Search Code In Magento Powered Store

Magento static blocks are perfect for placing Google Site Search code. Log into your Magento admin panel and do the followings:

1. Create a Static block – Go to CMS -> Static Block and click “Add New Block”
2. Fill the form but make sure to provide the identifier with “google-site-search” as value.
3. Optional – If you have multiple stores then you need to select under which store you would like to add Google Site Search.
4. Once done, create a CMS page by going to CMS -> Manage Pages and clicking “Add New Page”
5. Create this new page by giving SEF URL identifier as “search-site”
6. Place this code {{block type=”cms/block” block_id=”google-site-search”}} in the content area.
7. You are done, just check this new page by typing http://www.yourstorename/site-search in the url and see if the Google search is showing correctly.
8. Optional- You can make necessary layout related adjustments from Google site search control panel.
9. FYI: Google Paid search can also be embedded in this same manner.

I would love to hear your thoughts and experiences of adding Google Site Search to a Magento powered stores. Please leave me a comment and let me know. Subscribe our RSS to receive latest Magento updates in your mailbox.


23 November 2009

magento-product-comparison

Product comparison feature is loved by many customers as it gives them a precise idea about the interesting products in one place but this feature is not apt for few stores who do not wish to have product comparison feature. If you run a music store then comparing between two different music albums or songs would be of no real use.

Developer around the world scratch their head when it comes to getting rid of Product Comparison feature (RHS box) from their site layout. Although, this feature is default in Magento but their are options which will help you to remove this feature from your Magento store.

With a little bit of PHP knowledge and Magento customization you can easily get rid of Magento Product comparison functionality from your site. Most of the magento installation run cache which will not let you see your changes as you edit the files. It is advised to turn your cache off before induging yourself into the act and turn the cache on once you are satisfied with your changes i.e. removing Magento Product Comparison. You can enable/disable your cache from System -> Cache Management option given in Magento admin panel.

Getting rid of Product Comparison Box and feature

In order to achieve this you need to make changes in 6 different places which are given below:

  1. catalog.xml
  2. reports.xml
  3. customer.xml
  4. addto.phtml
  5. list.phtml
  6. crosssell.phtml

In order to make changes in your catalog.xml file you should open app/design/frontend/deafult/YourTheme/layout/catalog.xml in your favorite PHP editor and delete the following lines of code and save the file.

1
<block type="core/template" before="cart_sidebar" name="catalog.compare.sidebar" template="catalog/product/compare/sidebar.phtml"/>

Now open reports.xml file by opening app/design/frontend/deafult/YourTheme/layout/reports.xml in your favorite PHP editor and delete the two lines in am mentioning below. You can search the two lines and delete both of them from reports.xml file.

1
<block type="reports/product_viewed" before="right.permanent.callout" name="right.reports.product.viewed" template="reports/product_viewed.phtml" />
1
<block type="reports/product_compared" before="right.permanent.callout" name="right.reports.product.compared" template="reports/product_compared.phtml" />

Open customer.xml by editing app/design/frontend/default/YourTheme/layout/customer.xml in your favorite editor and delete the following line of code then save the file.

1
2
3
4
5
<action method="addItemRender">
 <type>grouped</type>
 <block>checkout/cart_item_renderer_grouped</block>
 <template>checkout/cart/sidebar/default.phtml</template>
</action>

Now, save the file and refresh your page and see if the box is still there. Hopefully you should not see the box. There is few more thing left to be done to entirely remove the “Add To Compare” link.

Open addto.phtml by opening app/design/frontend/default/YourTheme/template/catalog/product/view/addto.phtml in your favorite PHP editor and delete the following lines of code and save the file.

1
2
3
4
5
6
< ?php if($_compareUrl=$this->helper('catalog/product_compare')->getAddUrl($_product) ): ?>
 <li>
  <span class="pipe">|</span> 
  <a href="<?php echo $_compareUrl ?>">< ?php echo $this->__('Add to Compare') ?></a>
 </li>
< ?php endif; ?>

Open list.phtml by editing app/design/frontend/default/YourTheme/catalog/product/list.phtml in your favorite PHP editor and delete the following 2 code blocks.

1
2
3
4
<?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
  <span class="pipe">|</span>
  <a href="<?php echo $_compareUrl ?>"><?php echo $this->__('Add to Compare') ?></a>
<?php endif; ?>
1
<a href="<?php echo $_compareUrl ?>"><?php echo $this->__('Add to Compare') ?></a>

Finally open crosssell.phtml by editing app\design\frontend\default\default\template\checkout\cart in your favorite PHP editor and delete the following lines of code.

1
2
3
4
<?php if($_compareUrl=$this->getAddToCompareUrl($_item)): ?>
 <br/>
 <small><a href="<?php echo $_compareUrl ?>"><?php echo $this->__('Add to Compare') ?></a></small>
<?php endif; ?>

Now, refresh the page and you won’t see Product comparison instance or its link anywhere on your store. Please leave me a comment and share your experiences of removing Product comparison feature from your Magento powered store. Don’t forget to subscribe to our RSS to receive latest updates delivered to your mailbox for Free!


22 September 2009

magento_ecommerce
You must have noticed that sometimes you can’t use default Magento Models and require changes due to certain business logic you are about to follow. These changes are done to implement new functionality which are not part of existing Magento Installation. Overriding Controller is not difficult as you can copy the code from core in controller and keep the file in local directory. Now you can edit the class as per your requirement which will pretty much do the trick. You might know better and efficient way of doing this but that’s not a point here. I wanted to elaborate on how to override default Magento’s model class without even changing the core files. Tricky isn’t it?

In this article I am going to write a short code which will help you in overriding default Magento model without changing its core files. We have to create an extension which will do the trick. Simple difference between this extension and original class will be class name var_dump.

Now, we will choose any model class from core of Magento, in our case we will choose Mage_Wishlist_Model_Item which you can locate under app/code/core/Wishlist/Model/Item.php

In order to add new functionality in this class we will create a new module. What we are going to do now is to take a random model class from Magento core.
Let it be Mage_Wishlist_Model_Item located in app/code/core/Mage/Wishlist/Model/Item.php

What we want to do is to add new functionality to that class, so let’s make new module called as MagentoMagik_Wishlist (you can change the name as per your requirement)

Create app/code/local/MagentoMagik/Wishlist/model/ directory and copy app/code/core/Mage/Wishlist/Model/Item.php in that particular location.

Let’s rename class Mage_Wishlist_Model_Item to MagentoMagik_Wishlist_Model_Item.

Now, we have to add the line given below:

1
var_dump(get_class($this)); exit();

in loadByProductWishlist method

Now, let’s create MagentoMagik_Wishlist.xml in app/etc/modules/
and write the following code it in:

1
2
3
4
5
6
7
8
9
< ?xml version="1.0"?>
  <config>
    <modules>
       <magentomagik_wishlist>
          <active>true</active>
          <codepool>local</codepool>
      </magentomagik_wishlist>
    </modules>
 </config>

Now, create app/code/local/MagentoMagik/Wishlist/etc/Config.xml file and write the following code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< ?xml version="1.0"?>
  <config>
    <modules>
        <magentomagik_wishlist>
            <version>0.1</version>
        </magentomagik_wishlist>
    </modules>
    <global>
       <models>
          <wishlist>
              <rewrite>
                  <item>MagentoMagik_Wishlist_Model_Item</item>
              </rewrite>
          </wishlist>
       </models>
    </global>
</config>

This is merely an example of overriding the default Magento’s Model files and you can change the other model in similar way. All you have to do is plan what change you require and don’t hurt any Model which is required by Magento. I hope this example must have helped you in changing the default behavior. Please leave me a comment and share your experiences, problems with us.


01 September 2009

jquery
People who love jQuery must not feel disappointed with Magento 1.2.1 simply because it does not support jQuery by default. Those interested in Magento customization often complain that jQuery is throwing an error and how they can install and use jQuery as their preferred JavaScript Library.

In this article i am going to tell you how you can use jQuery within your Magento 1.2.1 installation. Lets take an example of default Magento Product Zoom feature which we switch to jQuery version.

Default Files:

1. app/design/frontend/default/portero/layout/page.xml
2. app/design/frontend/default/portero/layout/catalog.xml
3. app/design/frontend/default/portero/template/catalog/product/view.phtml
4. app/design/frontend/default/portero/template/catalog/product/view/media.phtml

New jQuery Files:

1. js/jquery/jquery.js
2. js/jquery/jquery.jqzoom.js
3. skin/frontend/default/portero/css/jqzoom.css
4. skin/frontend/default/portero/images/zoomloader.gif

I would recommend to create different directories for your magento customization so that your existing customization won’t get overwritten while upgrading to newer version of Magento.

Steps (Follow them in exact sequence):

  1. Create a new custom directory called portero under app/design/frontend/default.
  2. Create a new custom directory called portero under skin/frontend/default.
  3. Copy all the directories and files within app/design/frontend/default/default into the new directory at app/design/frontend/default/portero. You should end up with 3 directories under portero. The directories are layout, locale, template.
  4. Copy all the directories and files within skin/frontend/default/default into the new directory at skin/frontend/default/portero. You should end up with 3 directories and a favicon.ico file under portero. The directories are css, images, js.
  5. We need to tell Magento to reference the 2 custom directories we just created. For that we need to log into Magento’s Admin Panel. Go to System → Configuration. Under the General category, click on Design. Under the section Themes, make sure you provide the name of the custom directory for the input field Default. In our example, the value for the field would be portero. This will set the default theme directory to our custom directory. If you would not like to set the default theme directory to the custom directory; simply set 3 fields to their respective custom directory, these fields include: Templates, Skin, and Layout. Please refer to the screenshot below for all the possible fields that can be set.
  6. admin_design

  7. Download the jQuery zoom plugin from http://www.mind-projects.it/projects/jqzoom/. This article assumes you have experience with jQuery plugins before. Create a new directory under the js directory of your Magento installation. We decided to name it jquery, but you can obviously name it anything you want. Copy jquery.js and jquery.jqzoom.js that you downloaded into the new jquery directory.
  8. Copy the jqzoom.css file into the existing directory: skin/frontend/default/portero/css. Copy the zoomloader.gif file into the existing directory: skin/frontend/default/portero/images.
  9. We now need to include the new files we just added. Open up: app/design/frontend/default/portero/layout/page.xml.

    Add the reference to jquery.js within the default/root/head block

  10. 1
    2
    3
    
    <action method="addItem"><type>skin_css</type><name>css/ie7minus.css</name><params/><if>lt IE 7</if></action>
    <action method="addItem"><type>skin_css</type><name>css/jqzoom.css</name><params/></action>
    <action method="addItem"><type>js</type><name>lib/ds-sleight.js</name><params/><if>lt IE 7</if></action>



    Add the reference to jqzoom.css within the print/root/head block:

    1
    2
    3
    
    <action method="addItem"><type>skin_css</type><name>css/ie7minus.css</name><params/><if>lt IE 7</if></action>
    <action method="addItem"><type>skin_css</type><name>css/jqzoom.css</name><params/></action>
    <action method="addItem"><type>js</type><name>lib/ds-sleight.js</name><params/><if>lt IE 7</if></action>
  11. Finally we need to include jquery.jqzoom.js. We could have included it in page.xml; but since the purpose of the script is to provide a zoom feature for products; it can also be included in catalog.xml. Open up: app/design/frontend/default/portero/layout/catalog.xml.

    Add the reference to jquery.jqzoom.js within the catalog_product_view/root/head block:

  12. 1
    2
    3
    4
    5
    6
    7
    8
    9
    
    <catalog_product_view>
      <reference name="root">
        <action method="setTemplate"><template>page/2columns-right.phtml</template></action>
      </reference>
      <reference name="head">
        <action method="addJs"><script>jquery/jquery.jqzoom.js</script></action>
        <action method="addJs"><script>varien/product.js</script></action>
          ...
          ...
  13. Finally we are ready to write some actual code. Since jQuery and Prototype use the same selectors like “$”, scripts containing those selectors will conflict with each other. To resolve this problem, we have to apply the jQuery No Conflict function to the end of jquery.js and jquery.jqzoom.js.
    Open js/jquery/jquery.js.

    Go all the way to the last line and add the following:

  14. 1
    2
    
     });})();
      jQuery.noConflict();

    Open js/jquery/jquery.jqzoom.js.

    Add the following near the end of the file:

    1
    2
    3
    
    })(jQuery);
    jQuery.noConflict();
    function trim(stringa) {
  15. Open app/design/frontend/default/portero/template/catalog/product/view.phtml.

    Add the following jQuery code:

  16. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    <div class="product-img-box">
     <?php echo $this->getChildHtml('media') ?>
       <script type="text/javascript">
           jQuery(document).ready(function(){
            var options = 
            {
                 zoomWidth: 265,
                 zoomHeight: 265,
                 showEffect: 'show',
                 hideEffect: 'fadeout',
                 fadeoutSpeed: 'slow',
                 title: true
             }
          jQuery(".jqzoom").jqzoom(options);
          });
      </script>
    </div>
  17. Open app/design/frontend/default/portero/template/catalog/product/view/media.phtml.

    Since we are replacing Magento’s default product image zoom widget; we need to comment out the code that renders it

  18. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    <!--
     <p class="a-center" id="track_hint"><?php echo $this->__('Double click on above image to view full picture') ?></p>
      <div class="image-zoom" id="track_outer">
      <img id="zoom_out" src="<?php echo $this->getSkinUrl('images/slider_btn_zoom_out.gif') ?>" alt="<?php echo $this->__('Zoom Out') ?>" class="btn-zoom-out" />
      <div id="track">
      <div id="handle"></div>
     </div>
     <img id="zoom_in" src="<?php echo $this->getSkinUrl('images/slider_btn_zoom_in.gif') ?>" alt="<?php echo $this->__('Zoom In') ?>" class="btn-zoom-in" />
    </div>
    <script type="text/javascript">
     Event.observe(window, 'load', function() {
     product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
     });
    </script>
      -->

    Next we need to replace the following code:

    1
    2
    3
    4
    5
    6
    
      <p class="product-image-zoom">
       <?php
         $_img = '<img id="image" src="'.$this->helper('catalog/image')->init($_product, 'image').'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
        echo $_helper->productAttribute($_product, $_img, 'image')
        ?>
     </p>

    With the following lines of code:

    1
    2
    3
    4
    5
    6
    
     <p class="product-image-zoom">
     <?php
       $_img = '<a href="'.$this->helper('catalog/image')->init($_product, 'image').'" class="jqzoom" title="Magnified Image"><img id="image" src="'.$this->helper('catalog/image')->init($_product, 'image')->resize(265).'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'"/></a>';
     echo $_helper->productAttribute($_product, $_img, 'image')
    ?>
    </p>

All set. Now, if you place your mouse over product image it will show you the desired jQuery effect. Please leave me a comment and let me know if you run into any trouble getting the jQuery installed within Magento 1.2.1 version.


24 August 2009

magento-shipping-module

You must have wondered how to add a new Shipping Module in Magento especially if you don’t find your preferred payment module in existing Magento installation with your preferred Shipping Module. Adding a new Magento Shipping Module in not difficult but requires little bit of programming at your end. In this article i am going to elaborate on how to add a new Shipping module to your existing Magento Installation.

Few Notes:

  1. Just Replace all instances of ‘YourCompany’ with your company name.
  2. Replace ‘NewModule’ with the Payment Module name.
  3. Ensure that the path of the PHP include_path is /app/code/local/
  4. Clean your cache after modifying the config xml files.

Now, you are all set to create a new shipping module of your own. Following is a step by step guide to build your own shipping module, just follow them in exact order and make sure that the above requirements are taken care of.

Set The Configuration

You need to create app/code/local/YourCompany/NewModule/etc/config.xml file and write the following lines of code in it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0"?>
<config>
  <modules>
<!-- declare module's version information -->
    <YourCompany_NewModule>
<!-- this version number will be used for database upgrades -->
      <version>0.1.0</version>
    </YourCompany_NewModule>
  </modules>
 
  <global>
<!-- declare model group for new module -->
    <models>
<!-- model group alias to be used in Mage::getModel() -->
      <newmodule>
<!-- base class name for the model group -->
        <class>YourCompany_NewModule_Model</class>
      </newmodule>
    </models>
 
<!-- declare resource setup for new module -->
    <resources>
<!-- resource identifier -->
      <newmodule_setup>
<!-- specify that this resource is a setup resource and used for upgrades -->
        <setup>
<!-- which module to look for install/upgrade files in -->
          <module>YourCompany_NewModule</module>
        </setup>
<!-- specify database connection for this resource -->
        <connection>
<!-- do not create new connection, use predefined core setup connection -->
          <use>core_setup</use>
        </connection>
      </newmodule_setup>
    </resources>
  </global>
</config>

Now, edit app/etc/modules/YourCompany_NewModule.xml file

1
2
3
4
5
6
7
8
9
10
11
12
13
<config>
<!-- ... -->
  <modules>
<!-- ... -->
<!-- declare YourCompany_NewModule module -->
    <YourCompany_NewModule>
      <active>true</active>
      <codePool>local</codePool>
    </YourCompany_NewModule>
<!-- ... -->
  </modules>
<!-- ... -->
</config>

Now, the Magento installation is aware that there is a new Module but nothing will happen as there is no Database selected for this.

manage-mysql-databases-magento

Adding Information Into Adapter

Now, create app/code/local/YourCompany/NewModule/Model/Carrier/ShippingMethod.php file and put the following code in it. You can always set the ShippingMethod name of your choice, depending upon for which Payment Gateway you are making a module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php
 
/**
 * Our test shipping method module adapter
 */
class YourCompany_NewModule_Model_Carrier_ShippingMethod extends Mage_Shipping_Model_Carrier_Abstract
{
  /**
   * unique internal shipping method identifier
   * 
   * @var string [a-z0-9_]
   */
  protected $_code = 'newmodule';
 
    /**
     * Collect rates for this shipping method based on information in $request
     *
     * @param Mage_Shipping_Model_Rate_Request $data
     * @return Mage_Shipping_Model_Rate_Result
     */
  public function collectRates(Mage_Shipping_Model_Rate_Request $request)
  {
    // skip if not enabled
    if (!Mage::getStoreConfig('carriers/'.$this->_code.'/active')) {
        return false;
    }
 
    /**
     * here we are retrieving shipping rates from external service
     * or using internal logic to calculate the rate from $request
     * you can see an example in Mage_Usa_Model_Shipping_Carrier_Ups::setRequest()
     */
 
    // get necessary configuration values
    $handling = Mage::getStoreConfig('carriers/'.$this->_code.'/handling');
 
    // this object will be returned as result of this method
    // containing all the shipping rates of this method
    $result = Mage::getModel('shipping/rate_result');
 
    // $response is an array that we have 
    foreach ($response as $rMethod) {
      // create new instance of method rate
      $method = Mage::getModel('shipping/rate_result_method');
 
      // record carrier information
      $method->setCarrier($this->_code);
      $method->setCarrierTitle(Mage::getStoreConfig('carriers/'.$this->_code.'/title'));
 
      // record method information
      $method->setMethod($rMethod['code']);
      $method->setMethodTitle($rMethod['title']);
 
      // rate cost is optional property to record how much it costs to vendor to ship
      $method->setCost($rMethod['amount']);
 
      // in our example handling is fixed amount that is added to cost 
      // to receive price the customer will pay for shipping method.
      // it could be as well percentage: 
      /// $method->setPrice($rMethod['amount']*$handling/100);
      $method->setPrice($rMethod['amount']+$handling);
 
      // add this rate to the result
      $result->append($method);
    }
 
    return $result;
  }
}

Soon after you have created a Model, just give admin an option to configure it and let checkout process made aware of this (it will show up in checkout process which your users can choose to pay).

How To Develop Admin Module For Shipping Customizations

Once, you are done with the above steps, you need to inform Magento that there is a new Payment Module which needs to be configured and displayed in admin. In order to do so, you need to create app/code/local/YourCompany/NewModule/etc/system.xml file and put the following lines of code in it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
 
<?xml version="1.0"?>
<config>
   <sections>
    <carriers>
        <groups>
            <newmodule translate="label" module="shipping">
                <label>Carrier Name</label>
                <frontend_type>text</frontend_type>
                <sort_order>13</sort_order>
                <show_in_default>1</show_in_default>
                <show_in_website>1</show_in_website>
                <show_in_store>1</show_in_store>
                   <fields>
                      <account translate="label">
                            <label>Account number</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>7</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </account>
                        <active translate="label">
                            <label>Enabled</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <sort_order>1</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </active>
                        <contentdesc translate="label">
                            <label>Package Description</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>12</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </contentdesc>
                        <!--
                        If the free_shipping_enable flag enable, the system will check free_shipping_subtotal to give free shipping
                        otherwise will use shopping cart price rule behaviour
                        -->
                        <free_shipping_enable translate="label">
                            <label>Free shipping with minimum order amount</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_enabledisable</source_model>
                            <sort_order>21</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </free_shipping_enable>
                        <free_shipping_subtotal translate="label">
                            <label>Minimum order amount for free shipping</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>22</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </free_shipping_subtotal>
                        <dutiable translate="label">
                            <label>Shipment Dutiable</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <sort_order>13</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </dutiable>
                        <gateway_url translate="label">
                            <label>Gateway URL</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>2</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </gateway_url>
                        <handling_type translate="label">
                            <label>Calculate Handling Fee</label>
                            <frontend_type>select</frontend_type>
                            <source_model>shipping/source_handlingType</source_model>
                            <sort_order>10</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </handling_type>
                        <handling_action translate="label">
                            <label>Handling Applied</label>
                            <frontend_type>select</frontend_type>
                            <source_model>shipping/source_handlingAction</source_model>
                            <sort_order>11</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </handling_action>
                        <handling_fee translate="label">
                            <label>Handling fee</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>12</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </handling_fee>
                        <max_package_weight translate="label">
                            <label>Maximum Package Weight (Please consult your shipping carrier for maximum supported shipping weight)</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>13</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </max_package_weight>
                        <id translate="label">
                            <label>Access ID</label>
                            <frontend_type>text</frontend_type>
                            <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
                            <sort_order>5</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </id>
                        <password translate="label">
                            <label>Password</label>
                            <frontend_type>text</frontend_type>
                            <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
                            <sort_order>6</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </password>
                        <shipping_intlkey translate="label">
                            <label>Shipping key (International)</label>
                            <frontend_type>text</frontend_type>
                            <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
                            <sort_order>8</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </shipping_intlkey>
                        <shipping_key translate="label">
                            <label>Shipping key</label>
                            <frontend_type>text</frontend_type>
                            <backend_model>adminhtml/system_config_backend_encrypted</backend_model>
                            <sort_order>8</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </shipping_key>
                        <sort_order translate="label">
                            <label>Sort order</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>100</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </sort_order>
                        <title translate="label">
                            <label>Title</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>2</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </title>
                        <sallowspecific translate="label">
                            <label>Ship to applicable countries</label>
                            <frontend_type>select</frontend_type>
                            <sort_order>90</sort_order>
                            <frontend_class>shipping-applicable-country</frontend_class>
                            <source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </sallowspecific>
                        <specificcountry translate="label">
                            <label>Ship to Specific countries</label>
                            <frontend_type>multiselect</frontend_type>
                            <sort_order>91</sort_order>
                            <source_model>adminhtml/system_config_source_country</source_model>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </specificcountry>
                        <showmethod translate="label">
                            <label>Show method if not applicable</label>
                            <frontend_type>select</frontend_type>
                            <sort_order>92</sort_order>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </showmethod>
                        <specificerrmsg translate="label">
                            <label>Displayed Error Message</label>
                            <frontend_type>textarea</frontend_type>
                            <sort_order>80</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </specificerrmsg>
                    </fields>
                </newmodule>
            </groups>
        </carriers>
    </sections>
</config>

Once this file is saved you will find your new Payment Module under System> Configuration > Shipping Methods. It’s now up to you to add your custom fields in the fields tag, and subsequently make your configuration do something constructive.

Please leave me a comment and let me know if you run into any problems implementing the above code.