File indexing completed on 2024-06-23 05:55:39
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Search_Lucene 0017 * @subpackage Search 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** Zend_Search_Lucene_FSM */ 0025 // require_once 'Zend/Search/Lucene/FSM.php'; 0026 0027 /** 0028 * @category Zend 0029 * @package Zend_Search_Lucene 0030 * @subpackage Search 0031 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0032 * @license http://framework.zend.com/license/new-bsd New BSD License 0033 */ 0034 class Zend_Search_Lucene_Search_BooleanExpressionRecognizer extends Zend_Search_Lucene_FSM 0035 { 0036 /** State Machine states */ 0037 const ST_START = 0; 0038 const ST_LITERAL = 1; 0039 const ST_NOT_OPERATOR = 2; 0040 const ST_AND_OPERATOR = 3; 0041 const ST_OR_OPERATOR = 4; 0042 0043 /** Input symbols */ 0044 const IN_LITERAL = 0; 0045 const IN_NOT_OPERATOR = 1; 0046 const IN_AND_OPERATOR = 2; 0047 const IN_OR_OPERATOR = 3; 0048 0049 0050 /** 0051 * NOT operator signal 0052 * 0053 * @var boolean 0054 */ 0055 private $_negativeLiteral = false; 0056 0057 /** 0058 * Current literal 0059 * 0060 * @var mixed 0061 */ 0062 private $_literal; 0063 0064 0065 /** 0066 * Set of boolean query conjunctions 0067 * 0068 * Each conjunction is an array of conjunction elements 0069 * Each conjunction element is presented with two-elements array: 0070 * array(<literal>, <is_negative>) 0071 * 0072 * So, it has a structure: 0073 * array( array( array(<literal>, <is_negative>), // first literal of first conjuction 0074 * array(<literal>, <is_negative>), // second literal of first conjuction 0075 * ... 0076 * array(<literal>, <is_negative>) 0077 * ), // end of first conjuction 0078 * array( array(<literal>, <is_negative>), // first literal of second conjuction 0079 * array(<literal>, <is_negative>), // second literal of second conjuction 0080 * ... 0081 * array(<literal>, <is_negative>) 0082 * ), // end of second conjuction 0083 * ... 0084 * ) // end of structure 0085 * 0086 * @var array 0087 */ 0088 private $_conjunctions = array(); 0089 0090 /** 0091 * Current conjuction 0092 * 0093 * @var array 0094 */ 0095 private $_currentConjunction = array(); 0096 0097 0098 /** 0099 * Object constructor 0100 */ 0101 public function __construct() 0102 { 0103 parent::__construct( array(self::ST_START, 0104 self::ST_LITERAL, 0105 self::ST_NOT_OPERATOR, 0106 self::ST_AND_OPERATOR, 0107 self::ST_OR_OPERATOR), 0108 array(self::IN_LITERAL, 0109 self::IN_NOT_OPERATOR, 0110 self::IN_AND_OPERATOR, 0111 self::IN_OR_OPERATOR)); 0112 0113 $emptyOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'emptyOperatorAction'); 0114 $emptyNotOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'emptyNotOperatorAction'); 0115 0116 $this->addRules(array( array(self::ST_START, self::IN_LITERAL, self::ST_LITERAL), 0117 array(self::ST_START, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR), 0118 0119 array(self::ST_LITERAL, self::IN_AND_OPERATOR, self::ST_AND_OPERATOR), 0120 array(self::ST_LITERAL, self::IN_OR_OPERATOR, self::ST_OR_OPERATOR), 0121 array(self::ST_LITERAL, self::IN_LITERAL, self::ST_LITERAL, $emptyOperatorAction), 0122 array(self::ST_LITERAL, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR, $emptyNotOperatorAction), 0123 0124 array(self::ST_NOT_OPERATOR, self::IN_LITERAL, self::ST_LITERAL), 0125 0126 array(self::ST_AND_OPERATOR, self::IN_LITERAL, self::ST_LITERAL), 0127 array(self::ST_AND_OPERATOR, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR), 0128 0129 array(self::ST_OR_OPERATOR, self::IN_LITERAL, self::ST_LITERAL), 0130 array(self::ST_OR_OPERATOR, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR), 0131 )); 0132 0133 $notOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'notOperatorAction'); 0134 $orOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'orOperatorAction'); 0135 $literalAction = new Zend_Search_Lucene_FSMAction($this, 'literalAction'); 0136 0137 0138 $this->addEntryAction(self::ST_NOT_OPERATOR, $notOperatorAction); 0139 $this->addEntryAction(self::ST_OR_OPERATOR, $orOperatorAction); 0140 $this->addEntryAction(self::ST_LITERAL, $literalAction); 0141 } 0142 0143 0144 /** 0145 * Process next operator. 0146 * 0147 * Operators are defined by class constants: IN_AND_OPERATOR, IN_OR_OPERATOR and IN_NOT_OPERATOR 0148 * 0149 * @param integer $operator 0150 */ 0151 public function processOperator($operator) 0152 { 0153 $this->process($operator); 0154 } 0155 0156 /** 0157 * Process expression literal. 0158 * 0159 * @param integer $operator 0160 */ 0161 public function processLiteral($literal) 0162 { 0163 $this->_literal = $literal; 0164 0165 $this->process(self::IN_LITERAL); 0166 } 0167 0168 /** 0169 * Finish an expression and return result 0170 * 0171 * Result is a set of boolean query conjunctions 0172 * 0173 * Each conjunction is an array of conjunction elements 0174 * Each conjunction element is presented with two-elements array: 0175 * array(<literal>, <is_negative>) 0176 * 0177 * So, it has a structure: 0178 * array( array( array(<literal>, <is_negative>), // first literal of first conjuction 0179 * array(<literal>, <is_negative>), // second literal of first conjuction 0180 * ... 0181 * array(<literal>, <is_negative>) 0182 * ), // end of first conjuction 0183 * array( array(<literal>, <is_negative>), // first literal of second conjuction 0184 * array(<literal>, <is_negative>), // second literal of second conjuction 0185 * ... 0186 * array(<literal>, <is_negative>) 0187 * ), // end of second conjuction 0188 * ... 0189 * ) // end of structure 0190 * 0191 * @return array 0192 * @throws Zend_Search_Lucene_Exception 0193 */ 0194 public function finishExpression() 0195 { 0196 if ($this->getState() != self::ST_LITERAL) { 0197 // require_once 'Zend/Search/Lucene/Exception.php'; 0198 throw new Zend_Search_Lucene_Exception('Literal expected.'); 0199 } 0200 0201 $this->_conjunctions[] = $this->_currentConjunction; 0202 0203 return $this->_conjunctions; 0204 } 0205 0206 0207 0208 /********************************************************************* 0209 * Actions implementation 0210 *********************************************************************/ 0211 0212 /** 0213 * default (omitted) operator processing 0214 */ 0215 public function emptyOperatorAction() 0216 { 0217 /** Zend_Search_Lucene_Search_QueryParser */ 0218 // require_once 'Zend/Search/Lucene/Search/QueryParser.php'; 0219 0220 if (Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() == Zend_Search_Lucene_Search_QueryParser::B_AND) { 0221 // Do nothing 0222 } else { 0223 $this->orOperatorAction(); 0224 } 0225 0226 // Process literal 0227 $this->literalAction(); 0228 } 0229 0230 /** 0231 * default (omitted) + NOT operator processing 0232 */ 0233 public function emptyNotOperatorAction() 0234 { 0235 /** Zend_Search_Lucene_Search_QueryParser */ 0236 // require_once 'Zend/Search/Lucene/Search/QueryParser.php'; 0237 0238 if (Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() == Zend_Search_Lucene_Search_QueryParser::B_AND) { 0239 // Do nothing 0240 } else { 0241 $this->orOperatorAction(); 0242 } 0243 0244 // Process NOT operator 0245 $this->notOperatorAction(); 0246 } 0247 0248 0249 /** 0250 * NOT operator processing 0251 */ 0252 public function notOperatorAction() 0253 { 0254 $this->_negativeLiteral = true; 0255 } 0256 0257 /** 0258 * OR operator processing 0259 * Close current conjunction 0260 */ 0261 public function orOperatorAction() 0262 { 0263 $this->_conjunctions[] = $this->_currentConjunction; 0264 $this->_currentConjunction = array(); 0265 } 0266 0267 /** 0268 * Literal processing 0269 */ 0270 public function literalAction() 0271 { 0272 // Add literal to the current conjunction 0273 $this->_currentConjunction[] = array($this->_literal, !$this->_negativeLiteral); 0274 0275 // Switch off negative signal 0276 $this->_negativeLiteral = false; 0277 } 0278 }