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 }