📄 expr.inc.php.svn-base
字号:
if ($this->isDBonly() || $this->isTextOnly()) { $this->clearPoint(); $point = 'point'; } } } if ($point == 'point') { if ($this->isDBandText()) { $point = 'merge'; $left->setPoint('point'); $right->setPoint('point'); } } if (is_null($point) && !DefaultOpCollection::isBoolean($op)) { $point = 'point'; } $this->setPoint($point); } private function isDBonly() { return $this->getHasDb() && !$this->getHasText(); } private function isTextOnly() { return !$this->getHasDb() && $this->getHasText(); } private function isDBandText() { return $this->getHasDb() && $this->getHasText(); } public function appliesToContext() { return $this->left()->appliesToContext() | $this->right()->appliesToContext(); } /** * Enter description here... * * @param OpExpr $expr */ protected function clearPoint() { if (DefaultOpCollection::isBoolean($this)) { $this->left()->clearPoint(); $this->right()->clearPoint(); } if ($this->isMergePoint()) { $this->setPoint(null); } } protected function isMergePoint() { return in_array($this->getPoint(), array('merge','point')); } /** * Returns the operator on the expression * * @return ExprOp */ public function op() { return $this->op; } /** * Returns true if the negative of the operator should be used in evaluation * * @param boolean $not * @return boolean */ public function not($not=null) { if (!is_null($not)) { $this->not = $not; } return $this->not; } /** * The left side of the expression * * @return Expr */ public function &left() { return $this->left_expr; } /** * The right side of the expression * * @return Expr */ public function &right() { return $this->right_expr; } /** * Converts the expression to a string * * @return string */ public function __toString() { // _kt may not translate well here. $expr = $this->left_expr . ' ' . _kt($this->op) .' ' . $this->right_expr; if (is_null($this->parent)) { if ($this->not()) { $expr = _kt('NOT') . $expr; } return $expr; } if ($this->parent->isOpExpr()) { if ($this->parent->op != $this->op && in_array($this->op, DefaultOpCollection::$boolean)) { $expr = "($expr)"; } } if ($this->not()) { $expr = "!($expr)"; } return $expr; } /** * Is the expression valid * * @return boolean */ public function is_valid() { $left = $this->left(); $right = $this->right(); return $left->is_valid() && $right->is_valid(); } /** * Finds the results that are in both record sets. * * @param array $leftres * @param array $rightres * @return array */ protected static function _intersect($leftres, $rightres) { if (empty($leftres) || empty($rightres)) { return array(); // small optimisation } $result = array(); foreach($leftres as $item) { $document_id = $item->Id; if (!$item->IsLive) { continue; } if (array_key_exists($document_id, $rightres)) { $check = $rightres[$document_id]; $result[$document_id] = ($item->Rank < $check->Rank)?$check:$item; } } return $result; } protected static function intersect($leftres, $rightres) { return array( 'docs'=>self::_intersect($leftres['docs'],$rightres['docs']), 'folders'=>self::_intersect($leftres['folders'],$rightres['folders']) ); } protected static function union($leftres, $rightres) { return array( 'docs'=>self::_union($leftres['docs'],$rightres['docs']), 'folders'=>self::_union($leftres['folders'],$rightres['folders']) ); } /** * The objective of this function is to merge the results so that there is a union of the results, * but there should be no duplicates. * * @param array $leftres * @param array $rightres * @return array */ protected static function _union($leftres, $rightres) { if (empty($leftres)) { return $rightres; // small optimisation } if (empty($rightres)) { return $leftres; // small optimisation } $result = array(); foreach($leftres as $item) { if ($item->IsLive) { $result[$item->Id] = $item; } } foreach($rightres as $item) { if (!array_key_exists($item->Id, $result) || $item->Rank > $result[$item->Id]->Rank) { $result[$item->Id] = $item; } } return $result; } /** * Enter description here... * * @param OpExpr $left * @param ExprOp $op * @param OpExpr $right * @param boolean $not */ public function transform(& $left, & $op, & $right, & $not) { if (!$left->isOpExpr() || !$right->isOpExpr() || !DefaultOpCollection::isBoolean($op)) { return; } if ($left->isTextOnly() && $right->isDBonly()) { // we just swap the items around, to ease other transformations $tmp = $left; $left = $right; $right = $tmp; return; } if ($op != $right->op() || !DefaultOpCollection::isBoolean($right)) { return; } if ($op == ExprOp::OP_OR && ($not || $right->not())) { // NOTE: we can't transform. e.g. // db or !(db or txt) => db or !db and !txt // so nothing to do // BUT: db and !(db and txt) => db and !db and !txt return; } $rightLeft = $right->left(); $rightRight = $right->right(); if ($left->isDBonly() && $rightLeft->isDBonly()) { $newLeft = new OpExpr( $left, $op, $rightLeft ); $right = $rightRight; $left = $newLeft; return; } if ($left->isTextOnly() && $rightRight->isTextOnly()) { $newRight = new OpExpr($left, $op, $rightRight); $left = $rightLeft; $right = $newRight; return; } } private function findDBNode($start, $op, $what) { if ($start->op() != $op) { return null; } switch($what) { case 'db': if ($start->isDBonly()) { return $start; } break; case 'txt': if ($start->isTextOnly()) { return $start; } break; } $node = $this->findDBNode($start->left(), $op, $what); if (is_null($left)) { $node = $this->findDBNode($start->right(), $op, $what); } return $node; } public function traverse($object, $method, $param) { if ($this->isOpExpr()) { $object->$method($param); } } private function exploreItem($item, & $group, $interest) { if (($interest == 'db' && $item->getHasDb()) || ($interest == 'text' && $item->getHasText())) { if (in_array($item->op(), array(ExprOp::OP_OR, ExprOp::OP_AND))) { $this->exploreItem($item->left(), $group, $interest); $this->exploreItem($item->right(), $group, $interest); } else { $group[] = $item; } } } private function explore($left, $right, & $group, $interest) { $this->exploreItem($left, $group, $interest); $this->exploreItem($right, $group, $interest); } private function exec_db_query($op, $group) { if (empty($group)) { return array(); } $exprbuilder = new SQLQueryBuilder($this->getContext()); if (count($group) == 1) { $sql = $exprbuilder->buildComplexQuery($group[0]); } else { $sql = $exprbuilder->buildSimpleQuery($op, $group); } if (empty($sql)) { return array(); } $results = array(); global $default; $default->log->debug("SEARCH SQL: $sql"); $rs = DBUtil::getResultArray($sql); if (PEAR::isError($rs)) { throw new Exception($rs->getMessage()); } foreach($rs as $item) { $id = $item['id']; $rank = $exprbuilder->getRanking($item); if (!array_key_exists($id, $results) || $rank > $results[$id]->Rank) { if ($this->context == ExprContext::DOCUMENT) { $results[$id] = new DocumentResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item)); } else { $results[$id] = new FolderResultItem($id, $rank, $item['title'], $exprbuilder->getResultText($item)); } } } return $results; } private function exec_text_query($op, $group) { if (($this->getContext() != ExprContext::DOCUMENT) || empty($group)) { return array(); } $exprbuilder = new TextQueryBuilder(); if (count($group) == 1) { $query = $exprbuilder->buildComplexQuery($group[0]); } else { $query = $exprbuilder->buildSimpleQuery($op, $group); } if (empty($query)) { return array(); } $indexer = Indexer::get(); global $default; $default->log->debug("SEARCH LUCENE: $query"); $results = $indexer->query($query); foreach($results as $item) { $item->Rank = $exprbuilder->getRanking($item); $exprbuilder->setQuery($query); //$item->Text = $exprbuilder->getResultText($item); ?? wipe - done at indexer level } return $results; } public function evaluate($context = ExprContext::DOCUMENT_AND_FOLDER) { if ($context == ExprContext::DOCUMENT_AND_FOLDER) { $docs = $this->evaluate(ExprContext::DOCUMENT); $folders = $this->evaluate(ExprContext::FOLDER); return array( 'docs' => $docs['docs'], 'folders' => $folders['folders']); } $this->setContext($context); $left = $this->left(); $right = $this->right(); $op = $this->op(); $point = $this->getPoint(); $result = array(); if (empty($point)) { $point = 'point'; } $resultContext = ($this->getContext() == ExprContext::DOCUMENT)?'docs':'folders'; if ($point == 'merge') { $leftres = $left->evaluate($context); $rightres = $right->evaluate($context); switch ($op) { case ExprOp::OP_AND: if ($this->debug) print "\n\nmerge: intersect\n\n"; $result = OpExpr::intersect($leftres, $rightres); break; case ExprOp::OP_OR: if ($this->debug) print "\n\nmerge: union\n\n"; $result = OpExpr::union($leftres, $rightres); break; default: throw new Exception("this condition should not happen"); } } elseif ($point == 'point') { if ($this->isDBonly()) { $result[$resultContext] = $this->exec_db_query($op, array($this)); } elseif ($this->isTextOnly()) { $result[$resultContext] = $this->exec_text_query($op, array($this)); } elseif (in_array($op, array(ExprOp::OP_OR, ExprOp::OP_AND))) { // do we get to this??? // TODO: remove me please.... the simpleQuery stuff should go??? $db_group = array(); $text_group = array(); $this->explore($left, $right, $db_group, 'db'); $this->explore($left, $right, $text_group, 'text'); $db_result[$resultContext] = $this->exec_db_query($op, $db_group); $text_result[$resultContext] = $this->exec_text_query($op, $text_group); switch ($op) { case ExprOp::OP_AND: if ($this->debug) print "\n\npoint: intersect\n\n"; $result[$resultContext] = OpExpr::intersect($db_result, $text_result); break; case ExprOp::OP_OR: if ($this->debug) print "\n\nmerge: union\n\n"; $result[$resultContext] = OpExpr::union($db_result, $text_result); break; default: throw new Exception('how did this happen??'); } } else { throw new Exception('and this?'); } } else { // we don't have to do anything //throw new Exception('Is this reached ever?'); } $permResults = array(); foreach($result[$resultContext] as $idx=>$item) { $permResults[$resultContext][$idx] = $item; } return $permResults; } public function toViz(&$str, $phase) { $expr_id = $this->getExprId(); $left = $this->left(); $right = $this->right(); $hastext = $this->getHasText()?'TEXT':''; $hasdb = $this->getHasDb()?'DB':''; switch ($phase) { case 0: $not = $this->not()?'NOT':''; $str .= "struct$expr_id [style=box, label=\"$expr_id: $not $this->op $this->point $hastext$hasdb\"]\n"; break; case 1: $left_id = $left->getExprId(); $str .= "struct$expr_id -> struct$left_id\n"; $right_id = $right->getExprId(); $str .= "struct$expr_id -> struct$right_id\n"; break; } $left->toViz($str, $phase); $right->toViz($str, $phase); }}?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -