Tuesday, June 28, 2011

Replicate Category Tree from one Magento to Other Magento (Import category in Magento)

Recently I was working on Magento migration where I have to migrate magento shop from one server to other and create an identical shop on other server. Here time was the concern. So instead of creating categories manually I decided to create to replicate whole category tree with same category ids on other server. As next turn was to import product and keep in the same category. I used Magento API to get category tree from old Magento and traversed through it to create categories in new Magento. Check the following code.

I used recursive function to traverse the whole tree.


$flag = 1;
$client=new SoapClient('http://www.oldmagentodomain.com/api/soap/?wsdl');
$sessionId = $client->login('myAPIUserName','myApiKey');

$categoryTree= $client->call($sessionId, 'category.tree');

$currentCategory = $categoryTree['children'];


importCategory($currentCategory,$client); //This starts the import.



function importCategory($currentCategory,$client)
{

      $count= count($currentCategory);
      for($i=0; $i<$count; $i++)
      {
           $categoryId = $currentCategory[$i]['category_id'];
           $categoryInfo = $client->call($sessionId, 'category.info',$id);
   
           if($flag == 1)
           {
               $rootParentCategory = 1;
               $flag = 0;
           }
           else
           {
                $rootCategory = $categoryInfo ['parent_id'];
           }

                             
           $newCategory = new Mage_Catalog_Model_Category();                      
           $newCategory ->setName($categoryInfo ['name']);
           $newCategory ->setUrlKey($categoryInfo ['url_key']);
           $newCategory ->setLevel($categoryInfo ['level']);
           $newCategory ->setIsActive($categoryInfo ['is_active']);
           $newCategory ->setIsAnchor($categoryInfo ['is_anchor']);
           $newCategory ->setId($categoryInfo ['category_id']);

                               
           $parentCategory = Mage::getModel('catalog/category')->load($rootCategory);
           if($parentCategory)
           {
                $newCategory ->setPath($parentCategory->getPath()."/");                              
           }
            else
           {      
                 $newCategory ->setPath('');                                
            }

           $newCategory ->save(); 

           $childCategories = $currentCategory[$i]['children'];

           if($childCategories)
           {
               importCategory($childCategories,$client);
           }



     }
}

I hope this will help you. Now next post would be about importing products via Magento API. Stay tuned.

Thanks.

Saturday, June 25, 2011

Small Tips for ExtJs Programming

Hello,

Here I am sharing some tips that would be useful for you while working with ExtJs. These tips are about issues I faced while working on ExtJs projects.

1) Get-Set ExtJs Panel HTML

I don't know how many of you faced this issue. While working on one project, requirement was to set panel HTML dynamically. If you check Panel class there is not any method like getHtml() setHtml(). Following is the solution for it.

var dynamicHtml = '<div> This is dynamic HTML</div>';
myPanelObj.body.dom.innerHTML = dynamicHtml;

This will set panel HTML. Same way you can get panel HTML using myPanelObj.body.dom.innerHTML.

2) ExtJs Window me.Events are undefined error

If you are extending ExtJs window and on creating object of extended control, if you get above error then you forgot to call base class constructor. Call the base class constructor using following code.

ExtendedWindowObject.superclass.constructor.call(this, config);

3) Set padding while using ExtJs panel table layout.

When you use table layout in ExtJs panel layout. All the controls are arranged in a table. Sometimes it does not look good if you don't give padding to it. It looks very clumsy. So to give padding give id to panel and create a class in CSS with name of that id. See the example below.


#myPanelObj td{
    padding:5px;
},

4) Use renderer to format data in ExtJs grid cell.

If you want to format your data in grid cell use renderer. For example if you are displaying currency in ExtJs grid and you want to append $ sign to it. 

renderer: function(value, cell, record, rowIndex, colIndex, store)
{
          return value + '$';
}

5) Dynamically add event to ExtJs controls. 

Sometimes it may happen that you have to sue some ExtJs controls and you are not allowed to change the control and you need to add some listeners. Following is the code to add listeners dynamically.

myExtJsObj.on('hide',function(){ 
//function body.
});

6) Add Panel Click event

ExtJs panel does not support click event directly. However using following code you can make clickable panel.

listeners: {
                    render: function(p) {                                                                            
                                          p.getEl().on('click', handleProductPanelClick.createDelegate(null, p, true,this.id));
                     }
}

7) Another use of renderer to give style.

You can also use renderer  to give some styles to cells.

renderer: function(value, metaData, r) { 
                  metaData.attr = ' style="color:red;" ';
                  return value;
}

This will assign red color to cell.

That's it for now. I will update this post whenever I will have some more tips.

Monday, June 20, 2011

ExtJs Grid Paging - Go To Last Page After Inserting New Record

Hello,

Recently I was working on a ExtJs editor grid where user can enter new row by pressing button in the top toolbar. A row is inserted at bottom of grid and user can insert data in row. When user tab out or click on Save, the data goes to database and grid store reloaded. See the image below.


Now here is the issue. Consider grid page size as 25 and number of records are 35 and you are on page 1. That means you are viewing record 1 to 25. Now when you insert the row and when grid is refreshed, newly inserted record is in page 2 and you are still on page 1 so sometimes user feels that data is not inserted. So how to overcome this. I will describe solution that I have used. There may be other better solution. If you have any suggestion please add a comment.

First you need to add afteredit event in you grid. See the code below.


listeners:{
            afteredit:function(e){                       
                         Ext.Ajax.request({
                                    url : 'http://www.example.com/insertData.php',
                                    method:'GET',
                                    params:{                                 
                                        id : e.record.id,
                                        value : e.value
                                    },
                                    success:function(resp,opt){                                     
                                    },
                                    failure:function(resp,opt){
                                       
                                    }
                                });
             }
}


When you tab out of editor or Click on Save this event will be fired and it will send data to database using ajax request. Now we all know that for paging in MySql we have to use start and limit. For example.

select * from myTable limit 0,25

Above query will give first 25 records. to fetch next page use following query

select * from myTable limit 25,25

here first 25 indicates first row number of second page. So my trick was to return first row index of last page of table in which new record is inserted. Check the following code.


$start = 25;
$result = $start;


$output[ 'success' ] = true;
$output[ 'result' ] = $result; 
echo json_encode($output);

Above code will return JSON data back to browser. Now use that to reload the store. Following code will come in Success methods of Ajax Request mentioned in above code.


var returnValue= eval('(' + resp.responseText + ')');                                  
var start = returnValue.result;
if(start){
              myGrid.store.baseParams.start = start;                                      
}
myGrid.getView().refresh();
myGrid.store.reload();

ExtJs grid store uses start and limit parameter along with paging toolbar. So trick was to set start in base parameters of grid store and reload the grid. This will lead you to the last page in grid after inserting new record so user can see newly added record.