Source of file QueryParserContext.php
Size: 13,098 Bytes - Last Modified: 2021-12-23T10:29:30+00:00
/var/www/docs.ssmods.com/process/src/thirdparty/Zend/Search/Lucene/Search/QueryParserContext.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 | <?php /** * Zend Framework * * LICENSE * * This source file is subject to the new BSD license that is bundled * with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://framework.zend.com/license/new-bsd * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * * @category Zend * @package Zend_Search_Lucene * @subpackage Search * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @version $Id: QueryParserContext.php 20096 2010-01-06 02:05:09Z bkarwin $ */ /** * Zend_Search_Lucene_Search_QueryToken */ require_once 'Zend/Search/Lucene/Search/QueryToken.php'; /** * @category Zend * @package Zend_Search_Lucene * @subpackage Search * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Search_Lucene_Search_QueryParserContext { /** * Default field for the context. * * null means, that term should be searched through all fields * Zend_Search_Lucene_Search_Query::rewriteQuery($index) transletes such queries to several * * @var string|null */ private $_defaultField; /** * Field specified for next entry * * @var string */ private $_nextEntryField = null; /** * True means, that term is required. * False means, that term is prohibited. * null means, that term is neither prohibited, nor required * * @var boolean */ private $_nextEntrySign = null; /** * Entries grouping mode */ const GM_SIGNS = 0; // Signs mode: '+term1 term2 -term3 +(subquery1) -(subquery2)' const GM_BOOLEAN = 1; // Boolean operators mode: 'term1 and term2 or (subquery1) and not (subquery2)' /** * Grouping mode * * @var integer */ private $_mode = null; /** * Entries signs. * Used in GM_SIGNS grouping mode * * @var arrays */ private $_signs = array(); /** * Query entries * Each entry is a Zend_Search_Lucene_Search_QueryEntry object or * boolean operator (Zend_Search_Lucene_Search_QueryToken class constant) * * @var array */ private $_entries = array(); /** * Query string encoding * * @var string */ private $_encoding; /** * Context object constructor * * @param string $encoding * @param string|null $defaultField */ public function __construct($encoding, $defaultField = null) { $this->_encoding = $encoding; $this->_defaultField = $defaultField; } /** * Get context default field * * @return string|null */ public function getField() { return ($this->_nextEntryField !== null) ? $this->_nextEntryField : $this->_defaultField; } /** * Set field for next entry * * @param string $field */ public function setNextEntryField($field) { $this->_nextEntryField = $field; } /** * Set sign for next entry * * @param integer $sign * @throws Zend_Search_Lucene_Exception */ public function setNextEntrySign($sign) { if ($this->_mode === self::GM_BOOLEAN) { include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('It\'s not allowed to mix boolean and signs styles in the same subquery.'); } $this->_mode = self::GM_SIGNS; if ($sign == Zend_Search_Lucene_Search_QueryToken::TT_REQUIRED) { $this->_nextEntrySign = true; } else if ($sign == Zend_Search_Lucene_Search_QueryToken::TT_PROHIBITED) { $this->_nextEntrySign = false; } else { include_once 'Zend/Search/Lucene/Exception.php'; throw new Zend_Search_Lucene_Exception('Unrecognized sign type.'); } } /** * Add entry to a query * * @param Zend_Search_Lucene_Search_QueryEntry $entry */ public function addEntry(Zend_Search_Lucene_Search_QueryEntry $entry) { if ($this->_mode !== self::GM_BOOLEAN) { $this->_signs[] = $this->_nextEntrySign; } $this->_entries[] = $entry; $this->_nextEntryField = null; $this->_nextEntrySign = null; } /** * Process fuzzy search or proximity search modifier * * @throws Zend_Search_Lucene_Search_QueryParserException */ public function processFuzzyProximityModifier($parameter = null) { // Check, that modifier has came just after word or phrase if ($this->_nextEntryField !== null || $this->_nextEntrySign !== null) { include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('\'~\' modifier must follow word or phrase.'); } $lastEntry = array_pop($this->_entries); if (!$lastEntry instanceof Zend_Search_Lucene_Search_QueryEntry) { // there are no entries or last entry is boolean operator include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('\'~\' modifier must follow word or phrase.'); } $lastEntry->processFuzzyProximityModifier($parameter); $this->_entries[] = $lastEntry; } /** * Set boost factor to the entry * * @param float $boostFactor */ public function boost($boostFactor) { // Check, that modifier has came just after word or phrase if ($this->_nextEntryField !== null || $this->_nextEntrySign !== null) { include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('\'^\' modifier must follow word, phrase or subquery.'); } $lastEntry = array_pop($this->_entries); if (!$lastEntry instanceof Zend_Search_Lucene_Search_QueryEntry) { // there are no entries or last entry is boolean operator include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('\'^\' modifier must follow word, phrase or subquery.'); } $lastEntry->boost($boostFactor); $this->_entries[] = $lastEntry; } /** * Process logical operator * * @param integer $operator */ public function addLogicalOperator($operator) { if ($this->_mode === self::GM_SIGNS) { include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('It\'s not allowed to mix boolean and signs styles in the same subquery.'); } $this->_mode = self::GM_BOOLEAN; $this->_entries[] = $operator; } /** * Generate 'signs style' query from the context * '+term1 term2 -term3 +(<subquery1>) ...' * * @return Zend_Search_Lucene_Search_Query */ public function _signStyleExpressionQuery() { include_once 'Zend/Search/Lucene/Search/Query/Boolean.php'; $query = new Zend_Search_Lucene_Search_Query_Boolean(); include_once 'Zend/Search/Lucene/Search/QueryParser.php'; if (Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() == Zend_Search_Lucene_Search_QueryParser::B_AND) { $defaultSign = true; // required } else { // Zend_Search_Lucene_Search_QueryParser::B_OR $defaultSign = null; // optional } foreach ($this->_entries as $entryId => $entry) { $sign = ($this->_signs[$entryId] !== null) ? $this->_signs[$entryId] : $defaultSign; $query->addSubquery($entry->getQuery($this->_encoding), $sign); } return $query; } /** * Generate 'boolean style' query from the context * 'term1 and term2 or term3 and (<subquery1>) and not (<subquery2>)' * * @return Zend_Search_Lucene_Search_Query * @throws Zend_Search_Lucene */ private function _booleanExpressionQuery() { /** * We treat each level of an expression as a boolean expression in * a Disjunctive Normal Form * * AND operator has higher precedence than OR * * Thus logical query is a disjunction of one or more conjunctions of * one or more query entries */ include_once 'Zend/Search/Lucene/Search/BooleanExpressionRecognizer.php'; $expressionRecognizer = new Zend_Search_Lucene_Search_BooleanExpressionRecognizer(); include_once 'Zend/Search/Lucene/Exception.php'; try { foreach ($this->_entries as $entry) { if ($entry instanceof Zend_Search_Lucene_Search_QueryEntry) { $expressionRecognizer->processLiteral($entry); } else { switch ($entry) { case Zend_Search_Lucene_Search_QueryToken::TT_AND_LEXEME: $expressionRecognizer->processOperator(Zend_Search_Lucene_Search_BooleanExpressionRecognizer::IN_AND_OPERATOR); break; case Zend_Search_Lucene_Search_QueryToken::TT_OR_LEXEME: $expressionRecognizer->processOperator(Zend_Search_Lucene_Search_BooleanExpressionRecognizer::IN_OR_OPERATOR); break; case Zend_Search_Lucene_Search_QueryToken::TT_NOT_LEXEME: $expressionRecognizer->processOperator(Zend_Search_Lucene_Search_BooleanExpressionRecognizer::IN_NOT_OPERATOR); break; default: throw new Zend_Search_Lucene('Boolean expression error. Unknown operator type.'); } } } $conjuctions = $expressionRecognizer->finishExpression(); } catch (Zend_Search_Exception $e) { // throw new Zend_Search_Lucene_Search_QueryParserException('Boolean expression error. Error message: \'' . // $e->getMessage() . '\'.' ); // It's query syntax error message and it should be user friendly. So FSM message is omitted include_once 'Zend/Search/Lucene/Search/QueryParserException.php'; throw new Zend_Search_Lucene_Search_QueryParserException('Boolean expression error.', 0, $e); } // Remove 'only negative' conjunctions foreach ($conjuctions as $conjuctionId => $conjuction) { $nonNegativeEntryFound = false; foreach ($conjuction as $conjuctionEntry) { if ($conjuctionEntry[1]) { $nonNegativeEntryFound = true; break; } } if (!$nonNegativeEntryFound) { unset($conjuctions[$conjuctionId]); } } $subqueries = array(); foreach ($conjuctions as $conjuction) { // Check, if it's a one term conjuction if (count($conjuction) == 1) { $subqueries[] = $conjuction[0][0]->getQuery($this->_encoding); } else { include_once 'Zend/Search/Lucene/Search/Query/Boolean.php'; $subquery = new Zend_Search_Lucene_Search_Query_Boolean(); foreach ($conjuction as $conjuctionEntry) { $subquery->addSubquery($conjuctionEntry[0]->getQuery($this->_encoding), $conjuctionEntry[1]); } $subqueries[] = $subquery; } } if (count($subqueries) == 0) { include_once 'Zend/Search/Lucene/Search/Query/Insignificant.php'; return new Zend_Search_Lucene_Search_Query_Insignificant(); } if (count($subqueries) == 1) { return $subqueries[0]; } include_once 'Zend/Search/Lucene/Search/Query/Boolean.php'; $query = new Zend_Search_Lucene_Search_Query_Boolean(); foreach ($subqueries as $subquery) { // Non-requirered entry/subquery $query->addSubquery($subquery); } return $query; } /** * Generate query from current context * * @return Zend_Search_Lucene_Search_Query */ public function getQuery() { if ($this->_mode === self::GM_BOOLEAN) { return $this->_booleanExpressionQuery(); } else { return $this->_signStyleExpressionQuery(); } } } |