protected function searchPrepare($query, $auto_title = true)
 {
     $query = urldecode($query);
     $i = $offset = 0;
     $query_parts = array();
     while (($j = strpos($query, '&', $offset)) !== false) {
         // escaped &
         if ($query[$j - 1] != '\\') {
             $query_parts[] = str_replace('\\&', '&', substr($query, $i, $j - $i));
             $i = $j + 1;
         }
         $offset = $j + 1;
     }
     $query_parts[] = str_replace('\\&', '&', substr($query, $i));
     $model = $this->getModel();
     $title = array();
     foreach ($query_parts as $part) {
         if (!($part = trim($part))) {
             continue;
         }
         $parts = preg_split("/(\\\$=|\\^=|\\*=|==|!=|>=|<=|=|>|<)/uis", $part, 2, PREG_SPLIT_DELIM_CAPTURE);
         if ($parts) {
             if ($parts[0] == 'category_id') {
                 if ($parts[1] == '==' && $parts[2] == 'null') {
                     $this->where[] = 'p.category_id IS NULL';
                     $title[] = 'without category';
                 } else {
                     $this->addJoin('shop_category_products', null, ':table.category_id' . $this->getExpression($parts[1], $parts[2]));
                     $title[] = "category_id " . $parts[1] . $parts[2];
                 }
             } elseif ($parts[0] == 'query') {
                 $search = new shopIndexSearch();
                 $word_ids = $search->getWordIds($parts[2], true);
                 if ($word_ids) {
                     $this->joins[] = array('table' => 'shop_search_index', 'alias' => 'si');
                     $this->where[] = 'si.word_id IN (' . implode(",", $word_ids) . ')';
                     if (count($word_ids) > 1) {
                         $this->fields[] = "SUM(si.weight) AS weight";
                         $this->order_by = 'weight DESC';
                         $this->group_by = 'p.id';
                     } else {
                         $this->fields[] = "si.weight";
                         $this->order_by = 'si.weight DESC';
                     }
                 } elseif ($parts[2]) {
                     $this->where[] = '0';
                 }
                 $this->prepared = true;
                 // if not found try find by name
                 if (!$this->count()) {
                     $this->count = null;
                     $this->joins = $this->where = $this->having = $this->fields = array();
                     if ($this->is_frontend) {
                         if ($this->filtered) {
                             $this->filtered = false;
                         }
                         $this->frontendConditions();
                     }
                     $this->order_by = 'p.create_datetime DESC';
                     $this->group_by = null;
                     $q = $model->escape($parts[2], 'like');
                     $this->addJoin('shop_product_skus', null, "(p.name LIKE '%" . $q . "%' OR :table.name LIKE '%" . $q . "%' OR :table.sku LIKE '%" . $q . "%')");
                     $this->group_by = 'p.id';
                     return;
                 } elseif ($word_ids) {
                     $result = $this->getProducts('*', 0, 1);
                     $p = array_shift($result);
                     $w = str_replace(',', '.', 0.3 * $p['weight']);
                     if (count($word_ids) > 1) {
                         $this->having[] = 'SUM(si.weight) >= ' . $w;
                     } else {
                         $this->where[] = 'weight >= ' . $w;
                     }
                     $this->count = null;
                 }
                 $title[] = $parts[0] . $parts[1] . $parts[2];
             } elseif ($parts[0] == 'tag') {
                 $tag_model = $this->getModel('tag');
                 if (strpos($parts[2], '||') !== false) {
                     $tags = explode('||', $parts[2]);
                     $tag_ids = $tag_model->getIds($tags);
                 } else {
                     $sql = "SELECT id FROM " . $tag_model->getTableName() . " WHERE name" . $this->getExpression($parts[1], $parts[2]);
                     $tag_ids = $tag_model->query($sql)->fetchAll(null, true);
                 }
                 if ($tag_ids) {
                     $this->addJoin('shop_product_tags', null, ":table.tag_id IN ('" . implode("', '", $tag_ids) . "')");
                 } else {
                     $this->where[] = "0";
                 }
             } elseif ($model->fieldExists($parts[0])) {
                 $title[] = $parts[0] . $parts[1] . $parts[2];
                 $this->where[] = 'p.' . $parts[0] . $this->getExpression($parts[1], $parts[2]);
             } elseif ($parts[1] == '=') {
                 $code = $parts[0];
                 $is_value_id = false;
                 if (substr($code, -9) == '.value_id') {
                     $code = substr($code, 0, -9);
                     $is_value_id = true;
                 }
                 $feature_model = $this->getModel('feature');
                 $f = $feature_model->getByCode($code);
                 if ($f) {
                     if ($is_value_id) {
                         $value_id = $parts[2];
                     } else {
                         $values_model = $feature_model->getValuesModel($f['type']);
                         $value_id = $values_model->getValueId($f['id'], $parts[2]);
                     }
                     $this->addJoin('shop_product_features', null, ':table.feature_id = ' . $f['id'] . ' AND :table.feature_value_id = ' . (int) $value_id);
                     $this->group_by = 'p.id';
                 }
             }
         }
     }
     if ($title) {
         $title = implode(', ', $title);
         // Strip slashes from search title.
         $bs = '\\\\';
         $title = preg_replace("~{$bs}(_|%|&|{$bs})~", '\\1', $title);
     }
     if ($auto_title) {
         $this->addTitle($title, ' ');
     }
 }