[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 /** 3 * This class provides a parser which can construct an SQL WHERE 4 * clause from a Google-like search expression. 5 * 6 * $Horde: framework/SQL/SQL/Keywords.php,v 1.2.10.4 2006/01/01 21:28:33 jan Exp $ 7 * 8 * Copyright 2004-2006 Cronosys, LLC <http://www.cronosys.com/> 9 * 10 * See the enclosed file COPYING for license information (LGPL). If you 11 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 12 * 13 * The expression recognizes boolean "AND", "OR", and "NOT" (providing 14 * no operator between keywords implies "AND"), like so: 15 * 16 * cat and dog 17 * cat or dog 18 * cat and not dog 19 * 20 * If no operator appears between keywords or quoted strings, "AND" is 21 * assumed. A comma can be used instead of "OR": 22 * 23 * cat dog 24 * cat, dog 25 * cat not dog 26 * 27 * The parser recognizes parentheses, so complex expressions can be 28 * created: 29 * 30 * cat and not (dog or puppy) 31 * 32 * Quoted strings are also recognized, and are taken as literal 33 * keywords: 34 * 35 * "cat and dog" 36 * 37 * Parsing is designed to be as fuzzy as possible, so it shouldn't 38 * error unless people search for "AND", "OR", or "NOT" without 39 * quoting it or use unbalanced parentheses. 40 * 41 * @author Jason M. Felice <jfelice@cronosys.com> 42 * @since Horde 3.0 43 * @package Horde_SQL 44 */ 45 class Horde_SQL_Keywords { 46 47 /** 48 * Parse a keyword expression. 49 * 50 * @param string $column This is the SQL field name the resulting 51 * expression should test against. 52 * @param string $expr This is the keyword expression we want to 53 * parse. 54 * @return mixed the query expression or a PEAR_Error on failure. 55 */ 56 function parse($column, $expr) 57 { 58 /* First pass - scan the string for tokens. Bare words are 59 * tokens, or the user can quote strings to have embedded 60 * spaces, keywords, or parentheses. Parentheses can be used 61 * for grouping boolean operators, and the boolean operators 62 * AND, OR, and NOT are all recognized. 63 * 64 * The tokens are returned in the $tokens array -- an array of 65 * strings. Each string in the array starts with either a `!' 66 * or a `='. `=' is a bare word or quoted string we are 67 * searching for, and `!' indicates a boolean operator or 68 * parenthesis. A token that starts with a '.' indicates a 69 * PostgreSQL word boundary search. */ 70 $tokens = array(); 71 while (!empty($expr)) { 72 $expr = preg_replace("/^\s+/", "", $expr); 73 if (empty($expr)) { 74 break; 75 } 76 if (substr($expr,0,1) == '(') { 77 $expr = substr($expr, 1); 78 $token = '!('; 79 } elseif (substr($expr, 0, 1) == ')') { 80 $expr = substr($expr, 1); 81 $token = '!)'; 82 } elseif (substr($expr, 0, 1) == ',') { 83 $expr = substr($expr, 1); 84 $token = '!OR'; 85 } elseif (preg_match("/^(AND|OR|NOT)([^a-z].*)?$/i", $expr, 86 $matches)) { 87 $token = '!' . strtoupper($matches[1]); 88 $expr = substr($expr, strlen($matches[1])); 89 } elseif (preg_match("/^\"(([^\"]|\\[0-7]+|\\[Xx][0-9a-fA-F]+|\\[^Xx0-7])*)\"/", 90 $expr, $matches)) { 91 $token = '=' . stripcslashes($matches[1]); 92 $expr = substr($expr, strlen($matches[0])); 93 } elseif (preg_match("/^[^\\s\\(\\),]+/", $expr, $matches)) { 94 $token = '=' . $matches[0]; 95 $expr = substr($expr,strlen($token)-1); 96 } else { 97 return PEAR::raiseError(_("Syntax error in search terms")); 98 } 99 if ($token == '!AND') { 100 /* !AND is implied by concatenation. */ 101 continue; 102 } 103 $tokens[] = $token; 104 } 105 106 /* Call the expression parser. */ 107 return Horde_SQL_Keywords::_parseKeywords1($column, $tokens); 108 } 109 110 function _parseKeywords1($column, &$tokens) 111 { 112 if (count($tokens) == 0) { 113 return PEAR::raiseError(_("Empty search terms")); 114 } 115 $lhs = Horde_SQL_Keywords::_parseKeywords2($column, $tokens); 116 if (is_a($lhs, 'PEAR_Error')) { 117 return $lhs; 118 } 119 if (count($tokens) == 0 || $tokens[0] != '!OR') { 120 return $lhs; 121 } 122 array_shift($tokens); 123 $rhs = Horde_SQL_Keywords::_parseKeywords1($column, $tokens); 124 if (is_a($rhs, 'PEAR_Error')) { 125 return $rhs; 126 } 127 return "( $lhs OR $rhs )"; 128 } 129 130 function _parseKeywords2($column, &$tokens) 131 { 132 $lhs = Horde_SQL_Keywords::_parseKeywords3($column, $tokens); 133 if (is_a($lhs, 'PEAR_Error')) { 134 return $lhs; 135 } 136 if (sizeof($tokens) == 0 || $tokens[0] == '!)' || $tokens[0] == '!OR') { 137 return $lhs; 138 } 139 $rhs = Horde_SQL_Keywords::_parseKeywords2($column, $tokens); 140 if (is_a($rhs, 'PEAR_Error')) { 141 return $rhs; 142 } 143 return "( $lhs AND $rhs )"; 144 } 145 146 function _parseKeywords3($column, &$tokens) 147 { 148 if ($tokens[0] == '!NOT') { 149 array_shift($tokens); 150 $lhs = Horde_SQL_Keywords::_parseKeywords4($column, $tokens); 151 if (is_a($lhs, 'PEAR_Error')) { 152 return $lhs; 153 } 154 return "( NOT $lhs )"; 155 } 156 return Horde_SQL_Keywords::_parseKeywords4($column, $tokens); 157 } 158 159 function _parseKeywords4($column, &$tokens) 160 { 161 if ( $tokens[0] == '!(' ) { 162 array_shift($tokens); 163 $lhs = Horde_SQL_Keywords::_parseKeywords1($column, $tokens); 164 if (is_a($lhs, 'PEAR_Error')) { 165 return $lhs; 166 } 167 if (sizeof($tokens) == 0 || $tokens[0] != '!)') { 168 return PEAR::raiseError(_("Expected ')'")); 169 } 170 array_shift($tokens); 171 return $lhs; 172 } 173 if (substr($tokens[0], 0, 1) != '=' && 174 substr($tokens[0], 0, 2) != '=.') { 175 return PEAR::raiseError(_("Expected bare word or quoted search term")); 176 } 177 $val = strtolower(substr(array_shift($tokens), 1)); 178 $val = addslashes(ereg_replace("([\\%])", "\\\\1", $val)); 179 return "( LOWER($column) LIKE '%$val%' )"; 180 } 181 182 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |