/** * Экранирование строки в SQL запросе LIKE * @see: http://stackoverflow.com/a/3683868/2323306 * * @param DocumentParser $modx * @param string $field поле по которому осуществляется поиск * @param string $value искомое значение * @param string $escape экранирующий символ * @param string $tpl шаблон подстановки значения в SQL запрос * @return string строка для подстановки в SQL запрос */ public static function LikeEscape($modx, $field, $value, $escape = '=', $tpl = '%[+value+]%') { $str = ''; $escaped = false; if (!empty($field) && is_string($field) && is_scalar($value) && $value !== '') { $field = sqlHelper::tildeField($field); if (is_scalar($escape) && !empty($escape) && !in_array($escape, array("_", "%", "'"))) { $str = str_replace(array($escape, '_', '%'), array($escape . $escape, $escape . '_', $escape . '%'), $value); $escaped = true; } $str = $modx->db->escape($str); $str = str_replace('[+value+]', $str, $tpl); if ($escaped) { $str = "{$field} LIKE '{$str}' ESCAPE '{$escape}'"; } else { $str = "{$field} LIKE '{$str}'"; } } return $str; }
$action = "regexp"; $char = "^[{$char}]"; } else { $char = null; } } } if (is_null($char)) { $modx->sendErrorPage(); } $p =& $modx->event->params; if (!is_array($p)) { $p = array(); } if (!empty($loadfilter)) { $field = explode(".", $field); $field = end($field); if (!empty($p['filters'])) { $p['filters'] = rtrim(trim($p['filters']), ";") . ";"; } $p['filters'] = "AND({$loadfilter}:{$field}:{$action}:{$char})"; } else { $field = sqlHelper::tildeField($field); if ($action == 'regexp') { $where = $field . " REGEXP '" . $modx->db->escape($char) . "'"; } else { $where = sqlHelper::LikeEscape($modx, $field, $char, '=', '[+value+]%'); } $p['addWhereList'] = empty($p['addWhereList']) ? $where : sqlHelper::trimLogicalOp($p['addWhereList']) . " AND " . $where; } return $modx->runSnippet("DocLister", $p);
/** * Конструктор условий для WHERE секции * * @param $table_alias алиас таблицы * @param $field поле для фильтрации * @param $operator оператор сопоставления * @param $value искомое значение * @return string */ protected function build_sql_where($table_alias, $field, $operator, $value) { $this->DocLister->debug->debug('Build SQL query for filters: ' . $this->DocLister->debug->dumpData(func_get_args()), 'buildQuery', 2); $output = sqlHelper::tildeField($field, $table_alias); switch ($operator) { case '=': case 'eq': case 'is': $output .= " = '" . $this->modx->db->escape($value) . "'"; break; case '!=': case 'no': case 'isnot': $output .= " != '" . $this->modx->db->escape($value) . "'"; break; case '>': case 'gt': $output .= ' > ' . str_replace(',', '.', floatval($value)); break; case '<': case 'lt': $output .= ' < ' . str_replace(',', '.', floatval($value)); break; case '<=': case 'elt': $output .= ' <= ' . str_replace(',', '.', floatval($value)); break; case '>=': case 'egt': $output .= ' >= ' . str_replace(',', '.', floatval($value)); break; case '%': case 'like': $output = $this->DocLister->LikeEscape($output, $value); break; case 'like-r': $output = $this->DocLister->LikeEscape($output, $value, '=', '[+value+]%'); break; case 'like-l': $output = $this->DocLister->LikeEscape($output, $value, '=', '%[+value+]'); break; case 'regexp': $output .= " REGEXP '" . $this->modx->db->escape($value) . "'"; break; case 'against': /** content:pagetitle,description,content,introtext:against:искомая строка */ if (trim($value) != '') { $field = explode(",", $this->field); $field = implode(",", $this->DocLister->renameKeyArr($field, $this->getTableAlias())); $output = "MATCH ({$field}) AGAINST ('{$this->modx->db->escape($value)}*')"; } break; case 'containsOne': $words = explode($this->DocLister->getCFGDef('filter_delimiter', ','), $value); $word_arr = array(); foreach ($words as $word) { /** * $word оставляю без trim, т.к. мало ли, вдруг важно найти не просто слово, а именно его начало * Т.е. хочется найти не слово содержащее $word, а начинающееся с $word. Для примера: * искомый $word = " когда". С trim найдем "...мне некогда..." и "...тут когда-то..."; * Без trim будт обнаружено только "...тут когда-то..." */ $word_arr[] = $this->DocLister->LikeEscape($output, $word); } if (!empty($word_arr)) { $output = '(' . implode(' OR ', $word_arr) . ')'; } else { $output = ''; } break; case 'in': $output .= ' IN(' . $this->DocLister->sanitarIn($value, ',', true) . ')'; break; case 'notin': $output .= ' NOT IN(' . $this->DocLister->sanitarIn($value, ',', true) . ')'; break; default: $output = ''; } $this->DocLister->debug->debugEnd("buildQuery"); return $output; }