Magento – Filter product collection by multiple categories

Magento providing verious type of filter that can be used directly from product collection. Including category filter,

$_category = Mage::getModel('catalog/category')->load($category_id);
$collection= Mage::getResourceModel('catalog/product')->getCollection()->addCategoryFilter($_category);

But the issue is with multiple categories to filter. You can use bellow code to overcome this problem,

$collection = Mage::getModel('catalog/product')->getCollection()
             ->addAttributeToSelect('*')
             ->addFieldToFilter('is_saleable',1)
             ->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
             ->addAttributeToFilter('category_id', array(
                 array('finset' => '4'),
                 array('finset' => '8'))
               )
             ->addAttributeToSort('created_at', 'desc');

How magento store password and validate password – Magento

Magento uses MD5 and salt algorithems to store password for customer as well admin user.

How magento create encrypted password

Magento create encrypted password with,

Mage::getModel('core/encryption')->decrypt($password);

Here is the logic of decrypt($password) function,

 $password = "12345678";
 $salt = "at";
 $encyPasswod = md5($salt.$pass).":".$salt;

In above function, $salt is randomly generated string of two alphanumeric character.

How magento validate password

Bellow functiona will validate the user password,

Mage::getModel('customer/customer')->authenticate($email, $password);

Logic behind above function is,

 $email = "techbandhus@gmail.com";
 $password = "123456";

 //Load a customer by email address
 $customer = Mage::getModel('customer/customer')
 ->setWebsiteId(Mage::app()->getStore()->getWebsiteId())
 ->loadByEmail($email);

 // if loaded! get stored password from database
 $hash = $customer->getData("password_hash");

 // Get last two digits separate by :";
 $hashArr = explode(':', $hash);

 public function validateHash($password, $hash)
 {
     $hashArr = explode(':', $hash);
     switch (count($hashArr)) {
         case 1:
             return $this->hash($password) === $hash;
         case 2:
             return $this->hash($hashArr[1] . $password) === $hashArr[0];
     }
     Mage::throwException('Invalid hash.');
  }

So, it simply means that even if you have not added salt key and only MD5 text as password, login will work.

Android : Write app directory without worrying anything

TL;DR : this

Almost all of us who has developed in android for decent amount of time has faced a situation where we have to export a data of our application to a file in sd-card (or better say technically external storage). And I bet too many people faced the challenge to make this thing working in every device. Sometimes (y)our app is writing a file where there is no external storage, some times we use hard-coded path, because at some point of history, sd cards were mounted on that path and all devices follow this ritual. At some point of time the external storage is not available for us to write a file because of various reasons. And after crossing all these hurdles, we want to save all our app-created files in directory named after our app. For better organization and/or for any kind of branding purpose.

Many of us faced this problem, many of us are facing this right now. I have faced this issue too. This is a general operation that we have done n times and will do n+n times. What if there is a kind of plugin or library developed for this, That automates all the process, without worrying little details and with giving us proper errors whenever we face?

That’s where AppExternalFileWriter comes into the picture. I am talking about a class I have recently developed that (I believe) mostly automates the process said above. Doing some things automatically, as well let us(the programmers) do some extra cherry-picking at will.

Interested? Want to use? If not, you are not forced to read anything after this line. If yes, these are the droids you are looking for.

First of all, let me tell you how to work with the class.

1. Create an object of AppExternalFileWriter, to do that you need a Context object to pass to.

2. If you want to create a subfolder use suitable createSubDirectory variants.

3. use writeDataToFile or writeDataToTimeStampedFile variants as per your wish.

4. If you want to write a data where a file name should be a time stamp use writeDataToTimeStampedFile variants.

5. Apart from all I nearly forgot to add that, If anything is wrong with external storage, like storage not mounted, corrupt,  shared as mass storage, not enough space available, or even trying to create a library already created. The class will throw ExternalFileWriterException with the message stating what happened. Thus giving you the power to handle some crappy situations.

Here are some important variants you may want to use.

  1. writeDataToFile – Without parent directories
    writeDataToFile(String fileName, byte[] data);
    writeDataToFile(String fileName, String data);

    Writes data to desired file in Application directory.

  2. writeDataToFile – With parent directories
    writeDataToFile(File parent, String fileName, byte[] data);
    writeDataToFile(File parent, String fileName, String data);

    Writes data to desired file in other directory.

  3. writeDataToTimeStampedFile variants – Without parent directories
    writeDataToTimeStampedFile(String extension, byte[] data)
    writeDataToTimeStampedFile(String extension, String data)

    Writes data to desired file with timestamp with extension in Application directory.

  4. writeDataToTimeStampedFile variants – With parent directories
    writeDataToTimeStampedFile(String extension, byte[] data)
    writeDataToTimeStampedFile(String extension, String data)

    Writes data to desired file with timestamp with extension in other directory.

  5. createSubDirectory variants
    createSubDirectory(File parent, String directoryName)

    Creates subdirectory in application directory

    createSubDirectory(String directoryName)

    Creates subdirectory in any other directory

some other useful methods

  1. getAppDirectory()

    get File object of created app directory

  2. getExternalStorageDirectory()

    get File object of external storage directory

The full code with Sample is shared at this repository, fork and use it at your will.

May the force be with you.

Magento – Show Product Reviews on Product detail Page

Product review is one of the good feature of magento but with default magento theme product review listed on separate page. Usually  customer like to see all detail on same page instead redirect to another page. With this though we would like to show the product reviews  on product detail page only.

Bellow are steps which can help you to show product reviews on product detail page.

Step-1
Call product review block on product detail page, you can add bellow code to local.xml

<catalog_product_view>
    <reference name="content">
        <block type="review/product_view_list" name="product.info.product_additional_data" as="reviews" template="review/product/view/review_summary.phtml" />
    </reference name="content">
</catalog_product_view>

step-2
Create new template file review_summary.phtml, under template/review/product/view/ folder

<?php 
    $_items = $this->getReviewsCollection()->getItems();
    if( count( $_items ) )
    {
        foreach( $_items as $_review ){
        // Get the Review Title
        echo $this->htmlEscape( $_review->getTitle() );
        // Get the Review Content
        echo $this->htmlEscape( $_review->getDetail() );
        // Get the Review Author
        echo $this->htmlEscape( $_review->getNickname() );
        } 
    } 
?>

Step-3
Call review block on view.phtml, where you need the block to be show based on your design.

<?php echo $this->getChildHtml('reviews') ?>

Magento – Show custom option on product list page

Its good to show all the product options on list page also, This would be more comfortable to customer for product selection when all options are available product list page, instead togo on product detail page.

magento-show-custom-option

Just add bellow code to template/catalog/product/list.phtml, to show custom options on product list page

After product collection loop, foreach ($_productCollection as $_product):

load($_product->getId());
	$prodAtts   = $product->getOptions();
?>

Before add to cart button, that would be near about

 $optionVal)
	{
		$optStr .= "getId()."]'>";
		foreach($optionVal->getValues() as $valuesKey => $valuesVal)
		{
			$optStr .= "getId()."'>".$valuesVal->getTitle()."";
		}
		$optStr .= "";
	}
	echo($optStr);
?>

Magento – Get current module name, route name, controller name and action name

Many time we required to get current controller or action name or module name. Its very easy job to get get route name, module name, controller and action name for magento from current URL, anywhere in controller or even with template files.

Mage::app()->getRequest()->getControllerName(); // return controller name

Mage::app()->getRequest()->getActionName(); // return action name

Mage::app()->getRequest()->getRouteName(); // return routes name

Mage::app()->getRequest()->getModuleName(); // return module name

Magento – Delete all cancelled magento orders

There are many plug-ins are available that would add option to delete order in grid actions drop-down. But I had some requirement toset a cron job that would delete all canceled orders. We know well how to create cron job, if not this post will help you to create cron job in magento.

You can add bellow code to your model funtion that would be run by the cron job,

$collection = Mage::getResourceModel('sales/order_collection')
            ->addAttributeToSelect('*')
            ->setPageSize(1000)
            ->addFieldToFilter('status', 'canceled')
	    ->load();

foreach ($collection as $col) {
  Mage::log($col->getIncrementId() . ' order deleted ');
    try {
         $col->delete();
    } catch (Exception $e) {
        throw $e;
    }
}

Magento – Find customer who have purchased only one time

Once I had to find out the list of all costume who have purchased one one or have only one order placed.
Bellow query would be that list,

SELECT * FROM sales_flat_order GROUP BY customer_id HAVING COUNT(customer_id) = 1

One of my friend need the same with magento module only, I had given bellow solution.

$collection = Mage::getModel('customer/customer')->getCollection();
foreach ($collection as $user){
    $orders = Mage::getModel('sales/order')
                ->getCollection()
                ->addFieldToSelect('increment_id')
                ->addFieldToFilter('customer_id',$user->getId());
    if($orders->getSize() == 1){
        echo $user->getId();
    }
}

If you found some alternate solution you can suggest me, post your valuable comments.

Magento – Get all the velues of EAV attribute from attribute code

Many time we do required to get the all values of attribute or lets sey all option values of EAV attribue, while code a custom module or functionality. Bellow code would help you get all option values of EAV attribue,

// get the list of all gender type
public function getGenderList()
{
      $genders = array();
      $attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', 'gender'); // "gender" is attribute_code
      $allOptions = $attribute->getSource()->getAllOptions(true, true);
      foreach ($allOptions as $instance) {
           $genders[$instance['value']] = $instance['label'];
      }
      return $genders;
}

above function will returns array of gender type, gender is attribute of catalog_product.

Magento: get current CMS page identifier

Below function will returns page identifier, if the current page is CMS page.

public function getCurrentCmsPage() {
    $dataCurrentPage = $this->getHelper('cms/page')->getPage()->getData();
    if ($dataCurrentPage) {
        $identifierCurrentPage = $dataCurrentPage['identifier'];
        return $identifierCurrentPage;  
    } 
    return;     
}