| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4: */
- // +----------------------------------------------------------------------+
- // | PHP version 4.0 |
- // +----------------------------------------------------------------------+
- // | Copyright (c) 2002 Active Fish Group |
- // +----------------------------------------------------------------------+
- // | Authors: Kelvin Jones <kelvin@kelvinjones.co.uk> |
- // +----------------------------------------------------------------------+
- //
- // $Id: vlibSearchToSQL.php 1438 2006-10-29 13:26:42Z b4rt $
- // check to avoid multiple including of class
- if (!defined('vlibSearchToSQLClassLoaded')) {
- define('vlibSearchToSQLClassLoaded', 1);
- include_once (dirname(__FILE__).'/vlibIni.php');
- /**
- * vlibSearchToSQL is a class used to turn a boolean text
- * string, i.e., "+cats -dogs" or "cats NOT dogs".. into a
- * fully qualified SQL where clause, i.e.,
- * "field1 LIKE '%cats%' AND field1 NOT LIKE '%dogs%'".
- *
- * @since 13/02/2003
- * @author Kelvin Jones <kelvin@kelvinjones.co.uk>
- * @package vLIB
- * @access public
- * @see vlibSearchToSQL.html
- */
- class vlibSearchToSQL {
- /*-------------------------------------------------------------------------------\
- | ATTENTION |
- | Do not touch the following variables. vlibSearchToSQL will not work otherwise. |
- \-------------------------------------------------------------------------------*/
- var $OPTIONS = array(
- 'MIN_WORD_LENGTH' => '',
- 'ALLOW_WILDCARDS' => '',
- 'ENCLOSE_FIELDS_WITH' => '',
- 'DEFAULT_SEPERATOR' => '',
- 'STOP_WORDS' => ''
- );
- var $stop_words = '';
- var $escapechars = "\0\r\n\t\\";
- var $words_stopped = array();
- var $words_too_short = array();
- /**
- * FUNCTION: vlibSearchToSQL
- *
- * vlibSearchToSQL constructor.
- *
- * @param array $options see above
- * @return boolean true/false
- * @access private
- */
- function vlibSearchToSQL ($options=null) {
- if (is_array(vlibIni::vlibSearchToSQL())) {
- foreach (vlibIni::vlibSearchToSQL() as $name => $val) {
- $this->OPTIONS[$name] = $val;
- }
- }
- if (is_array($options)) {
- foreach($options as $key => $val) {
- if (strtoupper($key) == 'STOP_WORDS') {
- $this->OPTIONS['STOP_WORDS'] .= ' '.$val;
- }
- else {
- $this->OPTIONS[strtoupper($key)] = $val;
- }
- }
- }
- $this->stop_words = str_replace(' ', '|', $this->OPTIONS['STOP_WORDS']);
- if (!$this->OPTIONS['allow_wildcards']) $this->escapechars .= '%_';
- return true;
- }
- /**
- * FUNCTION: convert
- *
- * converts the search string to it's SQL equivilent.
- *
- * @param array $fields, all the fields in the database that you want to search
- * @return boolean true/false
- * @access private
- */
- function convert ($fields, $str) {
- $this->reset(); // reset vars before we start, in case a search was done previous to this.
- // run regex against search string
- $rgx = "/
- \s*
- (AND|OR|NOT|\+|\-|\|\||\!)? # any inclusion exclusion identifier
- \s*
- ([\"\']?) # first quote
- \s*
- ((?<=[\"\']) # if last one was a quote
- [^\"\']+ # search for any non quote
- | # else
- [^\s]+ # search for a word
- ) # endif
- \s*
- ([\"\']?) # second quote
- /ix";
- preg_match_all($rgx, $str, $matches, PREG_SET_ORDER);
- $words_used = array();
- // convert matches to readable SQL
- $sql = '';
- foreach ($matches as $m) {
- if (strlen($m[3]) < $this->OPTIONS['MIN_WORD_LENGTH']) { // word to short
- array_push($this->words_too_short, $m[3]);
- continue;
- }
- if (in_array(strtolower($m[3]), $words_used)) { // word duplicated
- continue;
- }
- if (preg_match('/^('.$this->stop_words.')$/i', $m[3]) && $m[1] != '+') { // stop word
- array_push($this->words_stopped, $m[3]);
- continue;
- }
- $preclause = null;
- $clause = null;
- switch (strtoupper($m[1])) {
- case 'AND':
- case '+':
- if ($sql) $preclause = ' AND ';
- $clause = ' LIKE ';
- break;
- case 'OR':
- case '||':
- if ($sql) $preclause = ' OR ';
- $clause = ' LIKE ';
- break;
- case 'NOT':
- case '-':
- if ($sql) $preclause = ' AND ';
- $clause = ' IS NOT LIKE ';
- break;
- default:
- if ($sql) $preclause = ' '.$this->OPTIONS['DEFAULT_SEPERATOR'].' ';
- $clause = ' LIKE ';
- break;
- }
- $sql .= $preclause.'$fieldname$'.$clause.'\'%'.addcslashes($m[3], $this->escapechars).'%\'';
- $words_used[] = strtolower($m[3]);
- }
- // loop through Db fields, creating identical SQL for each
- $where_clauses = array();
- foreach ($fields as $f) {
- if ($this->OPTIONS['ENCLOSE_FIELDS_WITH']) {
- $f = $this->OPTIONS['ENCLOSE_FIELDS_WITH'] . $f . $this->OPTIONS['ENCLOSE_FIELDS_WITH'];
- }
- $where_clauses[] = '('.str_replace('$fieldname$', $f, $sql).')';
- }
- return '('.implode(' OR ', $where_clauses).')';
- }
- /**
- * FUNCTION: getStoppedWords
- *
- * get an array of the words that were omitted from the search because
- * they were in the stop words list.
- *
- * @return array
- * @access public
- */
- function getStoppedWords () {
- return $this->words_stopped;
- }
- /**
- * FUNCTION: getShortWords
- *
- * get an array of the words that were omitted from the search because
- * they were too short.
- *
- * @return array
- * @access public
- */
- function getShortWords () {
- return $this->words_too_short;
- }
- /**
- * FUNCTION: reset
- *
- * reset any vars before a convert.
- *
- * @return true
- * @access public
- */
- function reset () {
- $this->words_stopped = array();
- $this->words_too_short = array();
- }
- } // end of class
- }// end of if (defined)
- ?>
|