00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 class Mage_CatalogSearch_Model_Mysql4_Search_Collection
00029 extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
00030 {
00031 protected $_attributesCollection;
00032 protected $_searchQuery;
00033
00034
00035
00036
00037
00038
00039
00040 public function addSearchFilter($query)
00041 {
00042 $this->_searchQuery = '%'.$query.'%';
00043 $this->addFieldToFilter('entity_id', array('in'=>new Zend_Db_Expr($this->_getSearchEntityIdsSql($query))));
00044 return $this;
00045 }
00046
00047
00048
00049
00050
00051
00052 protected function _getAttributesCollection()
00053 {
00054 if (!$this->_attributesCollection) {
00055 $this->_attributesCollection = Mage::getResourceModel('eav/entity_attribute_collection')
00056 ->setEntityTypeFilter($this->getEntity()->getTypeId())
00057 ->load();
00058
00059 foreach ($this->_attributesCollection as $attribute) {
00060 $attribute->setEntity($this->getEntity());
00061 }
00062 }
00063 return $this->_attributesCollection;
00064 }
00065
00066 protected function _isAttributeTextAndSearchable($attribute)
00067 {
00068 if (($attribute->getIsSearchable() && !in_array($attribute->getFrontendInput(), array('select', 'multiselect')))
00069 && (in_array($attribute->getBackendType(), array('varchar', 'text')) || $attribute->getBackendType() == 'static')) {
00070 return true;
00071 }
00072 return false;
00073 }
00074
00075 protected function _hasAttributeOptionsAndSearchable($attribute)
00076 {
00077 if ($attribute->getIsSearchable() && in_array($attribute->getFrontendInput(), array('select', 'multiselect'))) {
00078 return true;
00079 }
00080
00081 return false;
00082 }
00083
00084 protected function _getSearchEntityIdsSql($query)
00085 {
00086 $tables = array();
00087 $selects = array();
00088
00089
00090
00091 foreach ($this->_getAttributesCollection() as $attribute) {
00092 if ($this->_isAttributeTextAndSearchable($attribute)) {
00093 $table = $attribute->getBackend()->getTable();
00094 if (!isset($tables[$table]) && $attribute->getBackendType() != 'static') {
00095 $tables[$table] = array();
00096 }
00097
00098 if ($attribute->getBackendType() == 'static') {
00099 $param = $attribute->getAttributeCode().'_search_query';
00100 $selects[] = $this->getConnection()->select()
00101 ->from($table, 'entity_id')
00102 ->where($attribute->getAttributeCode().' LIKE :'.$param);
00103 $this->addBindParam($param, $this->_searchQuery);
00104 } else {
00105 $tables[$table][] = $attribute->getId();
00106 }
00107 }
00108 }
00109
00110 foreach ($tables as $table => $attributeIds) {
00111 $param = $table.'_search_query';
00112 $selects[] = $this->getConnection()->select()
00113 ->from(array('t1' => $table), 'entity_id')
00114 ->joinLeft(
00115 array('t2' => $table),
00116 $this->getConnection()->quoteInto('t1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id=?', $this->getStoreId()),
00117 array()
00118 )
00119 ->where('t1.attribute_id IN (?)', $attributeIds)
00120 ->where('t1.store_id = ?', 0)
00121 ->where('IFNULL(t2.value, t1.value) LIKE :'.$param);
00122 $this->addBindParam($param, $this->_searchQuery);
00123 }
00124
00125 if ($sql = $this->_getSearchInOptionSql($query)) {
00126 $selects[] = "SELECT * FROM ({$sql}) AS inoptionsql";
00127 }
00128 $sql = implode(' UNION ', $selects);
00129 return $sql;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 protected function _getSearchInOptionSql($query)
00139 {
00140 $attributeIds = array();
00141 $attributeTables = array();
00142 $storeId = (int)$this->getStoreId();
00143
00144
00145
00146
00147 foreach ($this->_getAttributesCollection() as $attribute) {
00148 if ($this->_hasAttributeOptionsAndSearchable($attribute)) {
00149 $attributeTables[$attribute->getFrontendInput()] = $attribute->getBackend()->getTable();
00150 $attributeIds[] = $attribute->getId();
00151 }
00152 }
00153 if (empty($attributeIds)) {
00154 return false;
00155 }
00156
00157 $resource = Mage::getSingleton('core/resource');
00158 $optionTable = $resource->getTableName('eav/attribute_option');
00159 $optionValueTable = $resource->getTableName('eav/attribute_option_value');
00160 $attributesTable = $resource->getTableName('eav/attribute');
00161
00162
00163
00164
00165 $select = $this->getConnection()->select()
00166 ->from(array('default'=>$optionValueTable), array('option_id','option.attribute_id', 'store_id'=>'IFNULL(store.store_id, default.store_id)', 'a.frontend_input'))
00167 ->joinLeft(array('store'=>$optionValueTable),
00168 $this->getConnection()->quoteInto('store.option_id=default.option_id AND store.store_id=?', $storeId),
00169 array())
00170 ->join(array('option'=>$optionTable),
00171 'option.option_id=default.option_id',
00172 array())
00173 ->join(array('a' => $attributesTable), 'option.attribute_id=a.attribute_id', array())
00174 ->where('default.store_id=0')
00175 ->where('option.attribute_id IN (?)', $attributeIds)
00176 ->where('IFNULL(store.value, default.value) LIKE :search_query');
00177 $options = $this->getConnection()->fetchAll($select, array('search_query'=>$this->_searchQuery));
00178 if (empty($options)) {
00179 return false;
00180 }
00181
00182
00183 $select = array();
00184 foreach (array(
00185 'select' => 'value = %d',
00186 'multiselect' => 'FIND_IN_SET(%d, value)')
00187 as $frontendInput => $condition) {
00188 if (isset($attributeTables[$frontendInput])) {
00189 $where = array();
00190 foreach ($options as $option) {
00191 if ($frontendInput === $option['frontend_input']) {
00192 $where[] = sprintf("attribute_id=%d AND store_id=%d AND {$condition}", $option['attribute_id'], $option['store_id'], $option['option_id']);
00193 }
00194 }
00195 if ($where) {
00196 $select[$frontendInput] = (string)$this->getConnection()->select()
00197 ->from($attributeTables[$frontendInput], 'entity_id')
00198 ->where(implode(' OR ', $where));
00199 }
00200 }
00201 }
00202
00203
00204 $where = array();
00205 foreach ($options as $option) {
00206 $where[] = sprintf('attribute_id=%d AND value=%d', $option['attribute_id'], $option['option_id']);
00207 }
00208 if ($where) {
00209 $select[] = (string)$this->getConnection()->select()
00210 ->from($resource->getTableName('catalogindex/eav'), 'entity_id')
00211 ->where(implode(' OR ', $where))
00212 ->where("store_id={$storeId}");
00213 }
00214
00215 return implode(' UNION ', $select);
00216 }
00217 }