loadConfig(); $this->culture = sfContext::getInstance()->getUser()->getCulture(); $analyzer = stTextAnalyzer::getInstance($this->culture); $this->query = $query; $this->query_keywords = array_keys($analyzer->analyze($query)); $this->initSearch(); } protected function loadConfig() { $this->config = stConfig::getInstance(sfContext::getInstance(), 'stSearchBackend'); $this->limit = $this->config->get('items_per_page'); } public function getQueryKeywords() { if (count($this->query_keywords)==0) $this->query_keywords = explode(' ',str_replace(array("\n","\t","\r"," "),array(' ', ' ', ' ',' '), $this->query)); return $this->query_keywords; } public function getQuery() { return $this->query; } public function getPageLimit() { return $this->limit; } public function setPage($page) { $this->page = $page; } public function initSearch() { $config = stConfig::getInstance('stProduct'); $config->load(); $this->criteria = new Criteria(); ProductPeer::addFilterCriteria(sfContext::getInstance(), $this->criteria); $this->criteria->remove(ProductPeer::PRODUCER_ID); ProductPeer::addSearchCriteria($this->criteria, $this->query_keywords, sfContext::getInstance()->getUser()->getCulture()); stEventDispatcher::getInstance()->notify(new sfEvent($this, 'stNewSearch.postAddCriteria', array('criteria' => $this->criteria))); } public function setLimit($limit) { $this->limit = $limit; } public function setOrderColumn($column, $direction = 'ASC') { if ($direction == 'ASC') $this->criteria->addAscendingOrderByColumn($column); else $this->criteria->addDescendingOrderByColumn($column); } public function getCriteria() { return $this->criteria; } public function countResults() { if (!$this->query_keywords) { return 0; } return ProductPeer::doCount($this->criteria); } public function getResults() { if (!$this->query_keywords) { return array(); } $this->criteria->setLimit($this->limit); $this->criteria->setOffset($this->limit*$this->page); return ProductPeer::doSelect($this->criteria); } // Keywords generation part public static function buildIndexAllLanguages(Product $product) { foreach (LanguagePeer::doSelectActive() as $language) { $product->setCulture($language->getOriginalLanguage()); self::buildIndex($product, true); } } public static function buildIndex(Product $product, $cleanup = false) { $tags = array(); if (!$cleanup) { $c = new Criteria(); $c->add(ProductHasProductSearchTagPeer::PRODUCT_ID, $product->getId()); $c->add(ProductHasProductSearchTagPeer::CULTURE, $product->getCulture()); if (ProductHasProductSearchTagPeer::doCount($c) > 0) { return false; } } $analyzer = stTextAnalyzer::getInstance($product->getCulture()); $config = stConfig::getInstance('stSearchBackend'); $tags = $analyzer->analyze($product->getName(), $tags, 100); if ($config->get('code')) { $tags = $analyzer->analyze($product->getCode(), $tags, 100); } if ($config->get('category')) { $names = self::getCategoryNames($product); if ($names) { $tags = $analyzer->analyze($names, $tags); } } if ($config->get('producer') && $product->getProducerId()) { $tags = $analyzer->analyze(self::getProducerName($product), $tags); } if ($config->get('description') && $product->getDescription()) { $tags = $analyzer->analyze($product->getDescription(), $tags); } if ($config->get('short_description') && $product->getShortDescription()) { $tags = $analyzer->analyze($product->getShortDescription(), $tags); } if ($config->get('additional_description') && $product->getDescription2()) { $tags = $analyzer->analyze($product->getDescription2(), $tags); } if ($config->get('producer_code') && $product->getManCode()) { $tags = $analyzer->analyze($product->getManCode(), $tags); } if ($config->get('options') && $product->getOptHasOptions() > 1) { $tags = $analyzer->analyze(self::getProductOptions($product), $tags); } if ($config->get('search_keywords') && $product->getSearchKeywords()) { $tags = $analyzer->analyze($product->getSearchKeywords(), $tags); } $tags = stEventDispatcher::getInstance()->filter(new sfEvent($product, 'stNewSearch.buildIndex'), $tags)->getReturnValue(); if ($cleanup) { self::cleanupTags($product); } if ($tags) { self::insertTags($product, $tags); } } public static function cleanupTags($product) { $c = new Criteria(); $c->add(ProductHasProductSearchTagPeer::PRODUCT_ID, $product->getId()); $c->add(ProductHasProductSearchTagPeer::CULTURE, $product->getCulture()); ProductHasProductSearchTagPeer::doDelete($c); } public static function insertTags($product, $tags) { $con = Propel::getConnection(); $sql = sprintf("INSERT IGNORE %s (%s) VALUES", ProductSearchTagPeer::TABLE_NAME, ProductSearchTagPeer::TAG); $values = array(); if (version_compare(PHP_VERSION, '7.0.0', '<')) { foreach ($tags as $tag => $weight) { $values[] = '(\''.mysql_real_escape_string($tag, $con->getResource()).'\')'; } } else { foreach ($tags as $tag => $weight) { $values[] = '(\''.mysqli_real_escape_string($con->getResource(), $tag).'\')'; } } $con->executeQuery($sql.implode(',', $values)); $c = new Criteria(); $c->addSelectColumn(ProductSearchTagPeer::ID); $c->addSelectColumn(ProductSearchTagPeer::TAG); $c->add(ProductSearchTagPeer::TAG, array_keys($tags), Criteria::IN); $rs = ProductSearchTagPeer::doSelectRS($c); $values = array(); $sql = sprintf("INSERT INTO %s (%s, %s, %s, %s) VALUES", ProductHasProductSearchTagPeer::TABLE_NAME, ProductHasProductSearchTagPeer::PRODUCT_ID, ProductHasProductSearchTagPeer::PRODUCT_SEARCH_TAG_ID, ProductHasProductSearchTagPeer::CULTURE, ProductHasProductSearchTagPeer::TAG_VALUE ); $product_id = $product->getId(); $culture = $product->getCulture(); while($rs->next()) { list($id, $tag) = $rs->getRow(); $values[] = '('.$product_id.','.$id.',\''.$culture.'\','.$tags[$tag].')'; } if ($values) { $con->executeQuery($sql.implode(',', $values)); } } public static function str_highlight($text, $needle, $options = null, $highlight = null) { if ($highlight === null) { $highlight = '\1'; } $pattern = '#(?!<.*?)(%s)(?![^<>]*?>)#'; $pattern .= 'i'; $needle = explode(' ',$needle); foreach ($needle as $needle_s) { if (!empty($needle_s)) { $needle_s = preg_quote($needle_s); $regex = sprintf($pattern, $needle_s); $text = preg_replace($regex, $highlight, $text); } } return $text; } public static function productPostSave(sfEvent $event) { $config = stConfig::getInstance('stSearchBackend'); $product = $event['modelInstance']; if ($config->get('enable_new')) { self::buildIndex($product, true); } } protected static function getCategoryNames(Product $product) { $ids = array(); $c = new Criteria(); $c->addSelectColumn(CategoryPeer::ID); $c->addSelectColumn(CategoryPeer::LFT); $c->addSelectColumn(CategoryPeer::RGT); $c->addSelectColumn(CategoryPeer::SCOPE); $c->addJoin(ProductHasCategoryPeer::CATEGORY_ID, CategoryPeer::ID); $c->add(ProductHasCategoryPeer::PRODUCT_ID, $product->getId()); $rs = CategoryPeer::doSelectRs($c); $ranges = array(); while($rs->next()) { $row = $rs->getRow(); if ($row[0] != $row[3]) { $ranges[] = sprintf("%s < %d AND %s > %d AND %s = %d", CategoryPeer::LFT, $row[1], CategoryPeer::RGT, $row[2], CategoryPeer::SCOPE, $row[3] ); } $ids[$row[0]] = $row[0]; } if (!$ranges) { return null; } $c = new Criteria(); $c->add(CategoryPeer::LFT, implode(" OR ", $ranges), Criteria::CUSTOM); $c->addSelectColumn(CategoryPeer::ID); $c->addSelectColumn(CategoryPeer::SCOPE); $rs = CategoryPeer::doSelectRs($c); while($rs->next()) { $row = $rs->getRow(); $ids[$row[0]] = $row[0]; } if (!$ids) { return null; } $c = new Criteria(); $c->addSelectColumn(CategoryI18nPeer::NAME); $c->addSelectColumn(CategoryPeer::OPT_NAME); $c->add(CategoryPeer::ID, $ids, Criteria::IN); $c->add(CategoryPeer::IS_ACTIVE, true); CategoryPeer::setHydrateMethod(array('stNewSearch', 'hydrateI18nName')); $tags = CategoryPeer::doSelectWithI18n($c, $product->getCulture()); CategoryPeer::setHydrateMethod(null); return $tags ? implode(' ', $tags) : null; } protected static function getProducerName(Product $product) { $c = new Criteria(); $c->addSelectColumn(ProducerI18nPeer::NAME); $c->addSelectColumn(ProducerPeer::OPT_NAME); $c->add(ProducerPeer::ID, $product->getProducerId()); ProducerPeer::setHydrateMethod(array('stNewSearch', 'hydrateI18nName')); $names = ProducerPeer::doSelectWithI18n($c, $product->getCulture()); ProducerPeer::setHydrateMethod(null); return $names ? $names[0] : null; } protected static function getProductOptions(Product $product) { $c = new Criteria(); $c->addAsColumn('con1', sprintf("GROUP_CONCAT(DISTINCT IFNULL(%s, %s) SEPARATOR ' ')", ProductOptionsValueI18nPeer::VALUE, ProductOptionsValuePeer::OPT_VALUE)); $c->addAsColumn('con2', sprintf("GROUP_CONCAT(DISTINCT %s SEPARATOR ' ')", ProductOptionsValuePeer::USE_PRODUCT)); $c->addAsColumn('con3', sprintf("GROUP_CONCAT(DISTINCT %s SEPARATOR ' ')", ProductOptionsValuePeer::MAN_CODE)); $c->addSelectColumn(ProductOptionsValuePeer::ID); $c->add(ProductOptionsValuePeer::PRODUCT_ID, $product->getId()); $c->add(ProductOptionsValuePeer::PRODUCT_OPTIONS_VALUE_ID, null, Criteria::ISNOTNULL); $c->addGroupByColumn(ProductOptionsValuePeer::PRODUCT_ID); ProductOptionsValuePeer::setHydrateMethod(function(ResultSet $rs) { if ($rs->next()) { $row = $rs->getRow(); return $row[1] . ' ' . $row[2] . ' ' . $row[3]; } return ''; }); $result = ProductOptionsValuePeer::doSelectWithI18n($c, $product->getCulture()); ProductOptionsValuePeer::setHydrateMethod(null); return $result; } public static function hydrateI18nName(ResultSet $rs) { $tags = array(); while($rs->next()) { $row = $rs->getRow(); $tags[] = $row[0] ? $row[0] : $row[1]; } return $tags; } }