Skip to content

Instantly share code, notes, and snippets.

@sergant210
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sergant210/aa7a50d2b0ce882b2f3a to your computer and use it in GitHub Desktop.
Save sergant210/aa7a50d2b0ce882b2f3a to your computer and use it in GitHub Desktop.
Класс mSearch2ext
<?php
/**
* The extended class for mSearch2.
* Feature: search in found
*/
require_once 'mSearch2.class.php';
class mSearch2ext extends mSearch2 {
/** @var array $resources */
public $resources = array();
/**
* Search and return array with resources ids as a key and sum of weight as value
*
* @param $query
* @return array
*/
public function Search($query) {
$string = preg_replace('/[^_-а-яёa-z0-9\s\.\/]+/iu', ' ', $this->modx->stripTags($query));
$this->log('Filtered search query: "'.mb_strtolower($query.'"', 'UTF-8'));
$string = $this->query = $this->addAliases($string);
$this->log('Search query with processed aliases: "'.mb_strtolower($string.'"', 'UTF-8'));
$words = $this->getBaseForms($string, false);
$result = $all_words = $found_words = array();
// Search by words index
if (!empty($words)) {
$q = $this->modx->newQuery('mseWord');
$q->select($this->modx->getSelectColumns('mseWord', 'mseWord'));
$q->where(array('word:IN' => array_keys($words), 'field:IN' => array_keys($this->fields)));
// Search in found
if (!empty($this->resources) && is_array($this->resources)) $q->where(array('resource:IN' => $this->resources));
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
$this->modx->queryTime += microtime(true) - $tstart;
$this->modx->executedQueries++;
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($result[$row['resource']])) {
$result[$row['resource']] += $this->fields[$row['field']] * $row['count'];
}
else {
$result[$row['resource']] = $this->fields[$row['field']] * $row['count'];
}
if (isset($words[$row['word']])) {
$all_words[$row['resource']][$words[$row['word']]] = 1;
$found_words[$words[$row['word']]] = 1;
}
}
}
}
$added = 0;
if (!empty($found_words)) {
$this->log('Found results by words INDEX ('.implode(',',array_keys($words)).'): '.count($result));
}
else {
$this->log('Nothing found by words INDEX');
}
// Add bonuses
if (empty($this->config['onlyIndex'])) {
$bulk_words = $this->getBulkWords($query);
$tmp_words = preg_split($this->config['split_words'], $query, -1, PREG_SPLIT_NO_EMPTY);
if (count($bulk_words) > 1 || count($tmp_words) > 1 || empty($result)) {
if (!empty($this->config['exact_match_bonus']) || !empty($this->config['all_words_bonus'])) {
$exact = $this->simpleSearch($query);
// Exact match bonus
if (!empty($this->config['exact_match_bonus'])) {
foreach ($exact as $v) {
if (isset($result[$v])) {
$result[$v] += $this->config['exact_match_bonus'];
//$this->log('Added "exact match bonus" for a resource '.$v.' for words "'.implode(', ', $words).'": +'.$this->config['exact_match_bonus']);
}
else {
$result[$v] = $this->config['exact_match_bonus'];
//$this->log('Found resource '.$v.' by LIKE search with all words "'.implode(', ',$words).'": +'.$this->config['exact_match_bonus']);
$added ++;
}
}
}
if (!empty($this->config['all_words_bonus'])) {
if (count($bulk_words) > 1) {
// All words bonus
foreach ($all_words as $k => $v) {
if (count($bulk_words) == count($v)) {
$result[$k] += $this->config['all_words_bonus'];
//$this->log('Added "all words bonus" for a resource '.$k.' for words "'.implode(', ', $words).'": +'.$this->config['all_words_bonus']);
}
}
}
}
}
}
elseif (!empty($this->config['like_match_bonus'])) {
// Add the whole possible results for query
$all_results = $this->simpleSearch($query);
foreach ($all_results as $v) {
if (!isset($result[$v])) {
$weight = round($this->config['like_match_bonus']);
$result[$v] = $weight;
//$this->log('Found resource '.$v.' by LIKE search with all words "'.$query.'": +'.$weight);
$added ++;
}
}
}
// Add matches by %LIKE% search
if (!empty($this->config['like_match_bonus']) && $not_found = array_diff($bulk_words, $words)) {
foreach ($not_found as $word) {
$found = $this->simpleSearch($word);
foreach ($found as $v) {
$weight = round($this->config['like_match_bonus']);
if (!isset($result[$v])) {
$result[$v] = $weight;
//$this->log('Found resource '.$v.' by LIKE search with single word "'.$word.'": +'.$weight);
$added ++;
}
else {
$result[$v] += $weight;
//$this->log('Added "LIKE bonus" for a resource '.$v.' for word "'.$word.'": +'.$weight);
}
}
}
}
$this->log('Added resources by LIKE search: '.$added);
}
// Log the search query
/** @var mseQuery $object */
if ($object = $this->modx->getObject('mseQuery', array('query' => $query))) {
$object->set('quantity', $object->get('quantity') + 1);
}
else {
$object = $this->modx->newObject('mseQuery');
$object->set('query', $query);
$object->set('quantity', 1);
}
$object->set('found', count($result));
$object->save();
arsort($result);
return $result;
}
/**
* Search and return array with resources that matched for LIKE search
*
* @param $query
*
* @return array
*/
public function simpleSearch($query) {
$string = preg_replace('/[^_-а-яёa-z0-9\s\.\/]+/iu', ' ', $this->modx->stripTags($query));
$result = array();
$q = $this->modx->newQuery('mseIntro');
$q->select('`resource`');
//Search in found
if (!empty($this->resources) && is_array($this->resources)) $q->where(array('resource:IN' => $this->resources));
$q->where(array('intro:LIKE' => '%'.$string.'%'));
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
$this->modx->queryTime += microtime(true) - $tstart;
$this->modx->executedQueries++;
$result = $q->stmt->fetchAll(PDO::FETCH_COLUMN);
}
return $result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment