I did it. And I would like to share my method with you. Maybe it's a very easy to do for guy who have already worked with magento, but not for newbie.
The 'CatalogSearch' module is responsible for search through product catalog. The module's path is 'DOC_ROOT/app/code/core/Mage/CatalogSearch'.
First of all, we should not edit core files (files in 'Mage' folder) and must override core classes and function.
To achieve our goal (my topic question) we should edit some function in different classes, so we need to override this functions.
The are 2 kinds of search thought product catalog in Magento: Simple and Advanced (maybe more, but I don't know another) and we'll influence on these 2 types.
Step 1:
We should tell Magento engine, that we would like to override some its core classes. Hence, we create own module. Go to '/app/etc/modules/' and create file 'YourCompany_YourModuleName.xml' with follow content:
<?xml version="1.0"?>
<config>
<modules>
<YourCompany_YourModuleName>
<active>true</active>
<codePool>local</codePool>
</YourCompany_YourModuleName>
</modules>
</config>
Step 2:
Now we should create our module. Go to '/app/code/local/YourCompany/YourModuleName/' and create folders 'etc'. Put 'config.xml' file in this 'etc' folder, we must tell magetno which files/classes we want to override.
config.xml content:
<?xml version="1.0"?>
<config>
<modules>
<yourcompany_yourmodulename>
<version>0.1.0</version>
</yourcompany_yourmodulename>
</modules>
<global>
<models>
<catalogsearch>
<rewrite>
<layer>YourCompany_YourModuleName_Model_CatalogSearch_Layer</layer>
<advanced>YourCompany_YourModuleName_CatalogSearch_Advanced</advanced>
</rewrite>
</catalogsearch>
<catalogsearch_mysql4>
<rewrite>
<fulltext_collection>YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Fulltext_Collection</fulltext_collection>
<advanced_collection>YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Advanced_Collection</advanced_collection>
</rewrite>
</catalogsearch_mysql4>
</models>
</global>
</config>
Now You may have noticed that we override 4 function in 4 classes.
Step 3:
Create 4 new files in our module with follow content:
-
'/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Advanced.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Advanced extends Mage_CatalogSearch_Model_Advanced
{
/**
* Retrieve advanced search product collection
*
* @return Mage_CatalogSearch_Model_Mysql4_Advanced_Collection
*/
public function getProductCollection(){
if (is_null($this->_productCollection)) {
$this->_productCollection = Mage::getResourceModel('catalogsearch/advanced_collection')
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addMinimalPrice()
->addTaxPercents()
->addStoreFilter();
$this->_productCollection->getSelect()->joinLeft(
array('_inventory_table'=>'cataloginventory_stock_item'),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$this->_productCollection->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
array());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($this->_productCollection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInSearchFilterToCollection($this->_productCollection);
}
return $this->_productCollection;
}
}
-
/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Layer.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Layer extends Mage_CatalogSearch_Model_Layer
{
public function prepareProductCollection($collection)
{
$collection->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addSearchFilter(Mage::helper('catalogsearch')->getQuery()->getQueryText())
->setStore(Mage::app()->getStore())
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addStoreFilter()
->addUrlRewrite();
$collection->getSelect()->joinLeft(
array('_inventory_table'=>'cataloginventory_stock_item'),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$collection->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1)
AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0)
AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1)))
THEN 1 ELSE 0 END)',
array());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInSearchFilterToCollection($collection);
return $this;
}
}
-
/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Mysql4/Advanced/Collection.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Advanced_Collection extends
Mage_CatalogSearch_Model_Mysql4_Advanced_Collection
{
public function setOrder($attribute, $dir='desc')
{
$this->addAttributeToSort('on_top', 'desc');
parent::setOrder($attribute, $dir);
return $this;
}
}
-
'/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Mysql4/Fulltext/Collection.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Fulltext_Collection
extends Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
{
public function setOrder($attribute, $dir = 'desc')
{
if ($attribute == 'relevance') {
$this->getSelect()->order("on_top DESC")->order("relevance {$dir}");
}
else {
parent::setOrder('on_top', 'DESC');
parent::setOrder($attribute, $dir);
}
return $this;
}
}
That's it. How you can see we should just connect to 'cataloginventory_stock_item' table while getting searched data to detect what product is out of stock and add additional order for products.
Nothing special, but I've had a problem where and what should I do to achieve my goal.
p.s. if someone can offer the better way to do this - you are welcome. Yet I could not find a proper tutorial to do this.