Commit edf7173b743643d42e52f0327ec1299a4a8a3fe3
1 parent
da2d9b44
Added a few docblock comments and other explanatory comments to search code
Showing
1 changed file
with
226 additions
and
41 deletions
search2/search/expr.inc.php
| @@ -40,7 +40,6 @@ | @@ -40,7 +40,6 @@ | ||
| 40 | 40 | ||
| 41 | /** | 41 | /** |
| 42 | * This is the ideal case, but more complex | 42 | * This is the ideal case, but more complex |
| 43 | - * | ||
| 44 | */ | 43 | */ |
| 45 | 44 | ||
| 46 | // TODO: search expression evaluation needs some optimisation | 45 | // TODO: search expression evaluation needs some optimisation |
| @@ -49,6 +48,14 @@ require_once('indexing/indexerCore.inc.php'); | @@ -49,6 +48,14 @@ require_once('indexing/indexerCore.inc.php'); | ||
| 49 | require_once('search/fieldRegistry.inc.php'); | 48 | require_once('search/fieldRegistry.inc.php'); |
| 50 | require_once('search/exprConstants.inc.php'); | 49 | require_once('search/exprConstants.inc.php'); |
| 51 | 50 | ||
| 51 | +/** | ||
| 52 | + * | ||
| 53 | + * | ||
| 54 | + * This class handles the ranking of search results | ||
| 55 | + * | ||
| 56 | + * @author KnowledgeTree Team | ||
| 57 | + * @package Search | ||
| 58 | + */ | ||
| 52 | class RankManager | 59 | class RankManager |
| 53 | { | 60 | { |
| 54 | /** | 61 | /** |
| @@ -76,6 +83,12 @@ class RankManager | @@ -76,6 +83,12 @@ class RankManager | ||
| 76 | */ | 83 | */ |
| 77 | private $text; | 84 | private $text; |
| 78 | 85 | ||
| 86 | + /** | ||
| 87 | + * Builds the RankManager object from the database | ||
| 88 | + * | ||
| 89 | + * @author KnowledgeTree Team | ||
| 90 | + * @access private | ||
| 91 | + */ | ||
| 79 | private function __construct() | 92 | private function __construct() |
| 80 | { | 93 | { |
| 81 | $this->dbfields=array(); | 94 | $this->dbfields=array(); |
| @@ -107,9 +120,11 @@ class RankManager | @@ -107,9 +120,11 @@ class RankManager | ||
| 107 | } | 120 | } |
| 108 | 121 | ||
| 109 | /** | 122 | /** |
| 110 | - * Enter description here... | 123 | + * Gets the RankManager object |
| 111 | * | 124 | * |
| 112 | - * @return RankManager | 125 | + * @author KnowledgeTree Team |
| 126 | + * @access public | ||
| 127 | + * @return object RankManager | ||
| 113 | */ | 128 | */ |
| 114 | public static function get() | 129 | public static function get() |
| 115 | { | 130 | { |
| @@ -121,6 +136,15 @@ class RankManager | @@ -121,6 +136,15 @@ class RankManager | ||
| 121 | return $singleton; | 136 | return $singleton; |
| 122 | } | 137 | } |
| 123 | 138 | ||
| 139 | + /** | ||
| 140 | + * Applies the appropriate score to a matched field | ||
| 141 | + * | ||
| 142 | + * @author KnowledgeTree Team | ||
| 143 | + * @access public | ||
| 144 | + * @param string $groupname The group to which the field belongs | ||
| 145 | + * @return int The score for this field or 0 if not matched with | ||
| 146 | + * any score | ||
| 147 | + */ | ||
| 124 | public function scoreField($groupname, $type='T', $itemname='') | 148 | public function scoreField($groupname, $type='T', $itemname='') |
| 125 | { | 149 | { |
| 126 | switch($type) | 150 | switch($type) |
| @@ -145,7 +169,12 @@ class RankManager | @@ -145,7 +169,12 @@ class RankManager | ||
| 145 | } | 169 | } |
| 146 | } | 170 | } |
| 147 | 171 | ||
| 148 | - | 172 | +/** |
| 173 | + * This is the base class for parsing search expressions | ||
| 174 | + * | ||
| 175 | + * @author KnowledgeTree Team | ||
| 176 | + * @package Search | ||
| 177 | + */ | ||
| 149 | class Expr | 178 | class Expr |
| 150 | { | 179 | { |
| 151 | /** | 180 | /** |
| @@ -317,6 +346,12 @@ class Expr | @@ -317,6 +346,12 @@ class Expr | ||
| 317 | } | 346 | } |
| 318 | } | 347 | } |
| 319 | 348 | ||
| 349 | +/** | ||
| 350 | + * This is the base class for Field expressions | ||
| 351 | + * | ||
| 352 | + * @author KnowledgeTree Team | ||
| 353 | + * @package Search | ||
| 354 | + */ | ||
| 320 | class FieldExpr extends Expr | 355 | class FieldExpr extends Expr |
| 321 | { | 356 | { |
| 322 | /** | 357 | /** |
| @@ -428,6 +463,12 @@ class FieldExpr extends Expr | @@ -428,6 +463,12 @@ class FieldExpr extends Expr | ||
| 428 | } | 463 | } |
| 429 | } | 464 | } |
| 430 | 465 | ||
| 466 | +/** | ||
| 467 | + * This class defines the contexts to which a search expression may apply | ||
| 468 | + * | ||
| 469 | + * @author KnowledgeTree Team | ||
| 470 | + * @package Search | ||
| 471 | + */ | ||
| 431 | class ExprContext | 472 | class ExprContext |
| 432 | { | 473 | { |
| 433 | const DOCUMENT = 1; | 474 | const DOCUMENT = 1; |
| @@ -435,7 +476,12 @@ class ExprContext | @@ -435,7 +476,12 @@ class ExprContext | ||
| 435 | const DOCUMENT_AND_FOLDER = 3; | 476 | const DOCUMENT_AND_FOLDER = 3; |
| 436 | } | 477 | } |
| 437 | 478 | ||
| 438 | - | 479 | +/** |
| 480 | + * This is the base class for Database Field Expressions | ||
| 481 | + * | ||
| 482 | + * @author KnowledgeTree Team | ||
| 483 | + * @package Search | ||
| 484 | + */ | ||
| 439 | class DBFieldExpr extends FieldExpr | 485 | class DBFieldExpr extends FieldExpr |
| 440 | { | 486 | { |
| 441 | /** | 487 | /** |
| @@ -515,6 +561,12 @@ class DBFieldExpr extends FieldExpr | @@ -515,6 +561,12 @@ class DBFieldExpr extends FieldExpr | ||
| 515 | } | 561 | } |
| 516 | } | 562 | } |
| 517 | 563 | ||
| 564 | +/** | ||
| 565 | + * This is the base class for Metadata Field Expressions | ||
| 566 | + * | ||
| 567 | + * @author KnowledgeTree Team | ||
| 568 | + * @package Search | ||
| 569 | + */ | ||
| 518 | class MetadataField extends DBFieldExpr | 570 | class MetadataField extends DBFieldExpr |
| 519 | { | 571 | { |
| 520 | protected $fieldset; | 572 | protected $fieldset; |
| @@ -561,6 +613,12 @@ class MetadataField extends DBFieldExpr | @@ -561,6 +613,12 @@ class MetadataField extends DBFieldExpr | ||
| 561 | 613 | ||
| 562 | } | 614 | } |
| 563 | 615 | ||
| 616 | +/** | ||
| 617 | + * This is the base class for Text Expressions | ||
| 618 | + * | ||
| 619 | + * @author KnowledgeTree Team | ||
| 620 | + * @package Search | ||
| 621 | + */ | ||
| 564 | class SearchableText extends FieldExpr | 622 | class SearchableText extends FieldExpr |
| 565 | { | 623 | { |
| 566 | } | 624 | } |
| @@ -782,8 +840,6 @@ class ValueListExpr extends Expr | @@ -782,8 +840,6 @@ class ValueListExpr extends Expr | ||
| 782 | } | 840 | } |
| 783 | } | 841 | } |
| 784 | 842 | ||
| 785 | - | ||
| 786 | - | ||
| 787 | public function rewrite(&$left, &$op, &$right, &$not) | 843 | public function rewrite(&$left, &$op, &$right, &$not) |
| 788 | { | 844 | { |
| 789 | if (count($this->values) == 1) | 845 | if (count($this->values) == 1) |
| @@ -813,7 +869,6 @@ class ValueListExpr extends Expr | @@ -813,7 +869,6 @@ class ValueListExpr extends Expr | ||
| 813 | 869 | ||
| 814 | } | 870 | } |
| 815 | 871 | ||
| 816 | - | ||
| 817 | class BetweenValueExpr extends ValueExpr | 872 | class BetweenValueExpr extends ValueExpr |
| 818 | { | 873 | { |
| 819 | protected $endvalue; | 874 | protected $endvalue; |
| @@ -893,6 +948,12 @@ interface QueryBuilder | @@ -893,6 +948,12 @@ interface QueryBuilder | ||
| 893 | 948 | ||
| 894 | } | 949 | } |
| 895 | 950 | ||
| 951 | +/** | ||
| 952 | + * This class builds queries for text content searches | ||
| 953 | + * | ||
| 954 | + * @author KnowledgeTree Team | ||
| 955 | + * @package Search | ||
| 956 | + */ | ||
| 896 | class TextQueryBuilder implements QueryBuilder | 957 | class TextQueryBuilder implements QueryBuilder |
| 897 | { | 958 | { |
| 898 | private $text; | 959 | private $text; |
| @@ -984,6 +1045,12 @@ class TextQueryBuilder implements QueryBuilder | @@ -984,6 +1045,12 @@ class TextQueryBuilder implements QueryBuilder | ||
| 984 | } | 1045 | } |
| 985 | } | 1046 | } |
| 986 | 1047 | ||
| 1048 | +/** | ||
| 1049 | + * This class builds queries for database searches | ||
| 1050 | + * | ||
| 1051 | + * @author KnowledgeTree Team | ||
| 1052 | + * @package Search | ||
| 1053 | + */ | ||
| 987 | class SQLQueryBuilder implements QueryBuilder | 1054 | class SQLQueryBuilder implements QueryBuilder |
| 988 | { | 1055 | { |
| 989 | private $used_tables; | 1056 | private $used_tables; |
| @@ -994,6 +1061,14 @@ class SQLQueryBuilder implements QueryBuilder | @@ -994,6 +1061,14 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 994 | private $context; | 1061 | private $context; |
| 995 | private $incl_status = true; | 1062 | private $incl_status = true; |
| 996 | 1063 | ||
| 1064 | + /** | ||
| 1065 | + * Constructor for the SQL query builder | ||
| 1066 | + * Sets the database tables to be used in the search query | ||
| 1067 | + * | ||
| 1068 | + * @author KnowledgeTree Team | ||
| 1069 | + * @access public | ||
| 1070 | + * @param string $context The context to which the search applies | ||
| 1071 | + */ | ||
| 997 | public function __construct($context) | 1072 | public function __construct($context) |
| 998 | { | 1073 | { |
| 999 | $this->context = $context; | 1074 | $this->context = $context; |
| @@ -1016,7 +1091,7 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1016,7 +1091,7 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1016 | 'tag_words'=>'tw', | 1091 | 'tag_words'=>'tw', |
| 1017 | 'document_fields_link'=>'pdfl' | 1092 | 'document_fields_link'=>'pdfl' |
| 1018 | ); | 1093 | ); |
| 1019 | - break; | 1094 | + break; |
| 1020 | case ExprContext::FOLDER: | 1095 | case ExprContext::FOLDER: |
| 1021 | $this->used_tables = array( | 1096 | $this->used_tables = array( |
| 1022 | 'folders'=>1, | 1097 | 'folders'=>1, |
| @@ -1025,7 +1100,7 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1025,7 +1100,7 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1025 | $this->aliases = array( | 1100 | $this->aliases = array( |
| 1026 | 'folders'=>'f', | 1101 | 'folders'=>'f', |
| 1027 | ); | 1102 | ); |
| 1028 | - break; | 1103 | + break; |
| 1029 | default: | 1104 | default: |
| 1030 | throw new Exception('This was not expected - Context = ' . $context); | 1105 | throw new Exception('This was not expected - Context = ' . $context); |
| 1031 | } | 1106 | } |
| @@ -1035,6 +1110,14 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1035,6 +1110,14 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1035 | $this->metadata = array(); | 1110 | $this->metadata = array(); |
| 1036 | } | 1111 | } |
| 1037 | 1112 | ||
| 1113 | + /** | ||
| 1114 | + * Sets the value which determines whether archived/deleted documents | ||
| 1115 | + * are to be included in search results | ||
| 1116 | + * | ||
| 1117 | + * @author KnowledgeTree Team | ||
| 1118 | + * @access public | ||
| 1119 | + * @param bool $incl | ||
| 1120 | + */ | ||
| 1038 | public function setIncludeStatus($incl) | 1121 | public function setIncludeStatus($incl) |
| 1039 | { | 1122 | { |
| 1040 | $this->incl_status = $incl; | 1123 | $this->incl_status = $incl; |
| @@ -1043,6 +1126,7 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1043,6 +1126,7 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1043 | /** | 1126 | /** |
| 1044 | * This looks up a table name to find the appropriate alias. | 1127 | * This looks up a table name to find the appropriate alias. |
| 1045 | * | 1128 | * |
| 1129 | + * @access private | ||
| 1046 | * @param string $tablename | 1130 | * @param string $tablename |
| 1047 | * @return string | 1131 | * @return string |
| 1048 | */ | 1132 | */ |
| @@ -1055,6 +1139,15 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1055,6 +1139,15 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1055 | throw new Exception("Unknown tablename '$tablename'"); | 1139 | throw new Exception("Unknown tablename '$tablename'"); |
| 1056 | } | 1140 | } |
| 1057 | 1141 | ||
| 1142 | + /** | ||
| 1143 | + * This method parses an expression into simpler individual expressions | ||
| 1144 | + * (if not already as simple as possible) | ||
| 1145 | + * evaluates each individually to determine the query content and table usage | ||
| 1146 | + * | ||
| 1147 | + * @access private | ||
| 1148 | + * @param object $expr | ||
| 1149 | + * @param object $parent | ||
| 1150 | + */ | ||
| 1058 | private function exploreExprs($expr, $parent=null) | 1151 | private function exploreExprs($expr, $parent=null) |
| 1059 | { | 1152 | { |
| 1060 | if ($expr->isMetadataField()) | 1153 | if ($expr->isMetadataField()) |
| @@ -1091,6 +1184,11 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1091,6 +1184,11 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1091 | } | 1184 | } |
| 1092 | } | 1185 | } |
| 1093 | 1186 | ||
| 1187 | + /** | ||
| 1188 | + * Determine table usage for a simple (metadata) query | ||
| 1189 | + * | ||
| 1190 | + * @param array $group | ||
| 1191 | + */ | ||
| 1094 | private function exploreGroup($group) | 1192 | private function exploreGroup($group) |
| 1095 | { | 1193 | { |
| 1096 | // split up metadata and determine table usage | 1194 | // split up metadata and determine table usage |
| @@ -1114,6 +1212,15 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1114,6 +1212,15 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1114 | } | 1212 | } |
| 1115 | } | 1213 | } |
| 1116 | 1214 | ||
| 1215 | + /** | ||
| 1216 | + * Determines the field to be checked for an expression | ||
| 1217 | + * If joins are defined for this expression the function will | ||
| 1218 | + * modify the fieldname accordingly | ||
| 1219 | + * | ||
| 1220 | + * @access private | ||
| 1221 | + * @param string $expr | ||
| 1222 | + * @return string $fieldname | ||
| 1223 | + */ | ||
| 1117 | private function getFieldnameFromExpr($expr) | 1224 | private function getFieldnameFromExpr($expr) |
| 1118 | { | 1225 | { |
| 1119 | $field = $expr->left(); | 1226 | $field = $expr->left(); |
| @@ -1133,9 +1240,15 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1133,9 +1240,15 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1133 | return $fieldname; | 1240 | return $fieldname; |
| 1134 | } | 1241 | } |
| 1135 | 1242 | ||
| 1243 | + /** | ||
| 1244 | + * Builds the part of the SQL query used for a particular simple expression | ||
| 1245 | + * | ||
| 1246 | + * @access private | ||
| 1247 | + * @param string $expr | ||
| 1248 | + * @return string $query | ||
| 1249 | + */ | ||
| 1136 | private function getSQLEvalExpr($expr) | 1250 | private function getSQLEvalExpr($expr) |
| 1137 | { | 1251 | { |
| 1138 | - | ||
| 1139 | $left = $expr->left(); | 1252 | $left = $expr->left(); |
| 1140 | $right = $expr->right(); | 1253 | $right = $expr->right(); |
| 1141 | $isNot = $expr->not(); | 1254 | $isNot = $expr->not(); |
| @@ -1178,6 +1291,11 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1178,6 +1291,11 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1178 | return $query; | 1291 | return $query; |
| 1179 | } | 1292 | } |
| 1180 | 1293 | ||
| 1294 | + /** | ||
| 1295 | + * Builds the main SQL query | ||
| 1296 | + * | ||
| 1297 | + * @return string $sql | ||
| 1298 | + */ | ||
| 1181 | private function buildCoreSQL() | 1299 | private function buildCoreSQL() |
| 1182 | { | 1300 | { |
| 1183 | if (count($this->metadata) + count($this->db) == 0) | 1301 | if (count($this->metadata) + count($this->db) == 0) |
| @@ -1186,8 +1304,7 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1186,8 +1304,7 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1186 | return ''; | 1304 | return ''; |
| 1187 | } | 1305 | } |
| 1188 | 1306 | ||
| 1189 | - $sql = | ||
| 1190 | - 'SELECT ' . "\n"; | 1307 | + $sql = 'SELECT ' . "\n"; |
| 1191 | 1308 | ||
| 1192 | if ($this->context == ExprContext::DOCUMENT) | 1309 | if ($this->context == ExprContext::DOCUMENT) |
| 1193 | { | 1310 | { |
| @@ -1197,16 +1314,19 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1197,16 +1314,19 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1197 | $this->used_tables['document_metadata_version']++; | 1314 | $this->used_tables['document_metadata_version']++; |
| 1198 | } | 1315 | } |
| 1199 | 1316 | ||
| 1200 | - $sql .= | ||
| 1201 | - ' DISTINCT d.id, dmv.name as title'; | 1317 | + $sql .= ' DISTINCT d.id, dmv.name as title'; |
| 1202 | } | 1318 | } |
| 1203 | else | 1319 | else |
| 1204 | { | 1320 | { |
| 1205 | - $sql .= | ||
| 1206 | - ' DISTINCT f.id, f.name as title'; | 1321 | + $sql .= ' DISTINCT f.id, f.name as title'; |
| 1207 | } | 1322 | } |
| 1208 | 1323 | ||
| 1209 | - | 1324 | + /* |
| 1325 | + * This section of code builds the part of the query which is used to | ||
| 1326 | + * determine ranking for db fields | ||
| 1327 | + * | ||
| 1328 | + * 0 = "does not match" | ||
| 1329 | + */ | ||
| 1210 | $offset=0; | 1330 | $offset=0; |
| 1211 | foreach($this->db as $expr) | 1331 | foreach($this->db as $expr) |
| 1212 | { | 1332 | { |
| @@ -1214,14 +1334,19 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1214,14 +1334,19 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1214 | $sql .= ", ifnull(" . $this->getSQLEvalExpr($expr) . ",0) as expr$offset "; | 1334 | $sql .= ", ifnull(" . $this->getSQLEvalExpr($expr) . ",0) as expr$offset "; |
| 1215 | } | 1335 | } |
| 1216 | 1336 | ||
| 1337 | + /* | ||
| 1338 | + * This section of code builds the part of the query which is used to | ||
| 1339 | + * determine ranking for metadata fields | ||
| 1340 | + * | ||
| 1341 | + * 0 = "does not match" | ||
| 1342 | + */ | ||
| 1217 | foreach($this->metadata as $expr) | 1343 | foreach($this->metadata as $expr) |
| 1218 | { | 1344 | { |
| 1219 | $offset++; | 1345 | $offset++; |
| 1220 | $sql .= ", ifnull(" . $this->getSQLEvalExpr($expr) . ",0) as expr$offset "; | 1346 | $sql .= ", ifnull(" . $this->getSQLEvalExpr($expr) . ",0) as expr$offset "; |
| 1221 | } | 1347 | } |
| 1222 | 1348 | ||
| 1223 | - $sql .= | ||
| 1224 | - "\n" . 'FROM ' ."\n"; | 1349 | + $sql .= "\n" . 'FROM ' ."\n"; |
| 1225 | 1350 | ||
| 1226 | if ($this->context == ExprContext::DOCUMENT) | 1351 | if ($this->context == ExprContext::DOCUMENT) |
| 1227 | { | 1352 | { |
| @@ -1243,10 +1368,6 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1243,10 +1368,6 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1243 | // out below. | 1368 | // out below. |
| 1244 | // if ($this->used_tables['document_fields_link'] > 0) | 1369 | // if ($this->used_tables['document_fields_link'] > 0) |
| 1245 | // { | 1370 | // { |
| 1246 | -// // NOTE this is a bit of a hack, maybe? or maybe it really is the best way? | ||
| 1247 | -// // ...what about using the loop below which checks the expression | ||
| 1248 | -// // for a join table rather than this up here? - otherwise this only | ||
| 1249 | -// // affects this particular query type - then again maybe that's what we want... | ||
| 1250 | // for ($i = 0; $i < $this->used_tables['document_fields_link']; ++$i) | 1371 | // for ($i = 0; $i < $this->used_tables['document_fields_link']; ++$i) |
| 1251 | // { | 1372 | // { |
| 1252 | // if ($i > 0) $counter = $i; | 1373 | // if ($i > 0) $counter = $i; |
| @@ -1259,8 +1380,8 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1259,8 +1380,8 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1259 | 1380 | ||
| 1260 | if ($this->used_tables['tag_words'] > 0) | 1381 | if ($this->used_tables['tag_words'] > 0) |
| 1261 | { | 1382 | { |
| 1262 | - $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" . | ||
| 1263 | - ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n"; | 1383 | + $sql .= ' LEFT OUTER JOIN document_tags dt ON dt.document_id=d.id ' . "\n" |
| 1384 | + . ' LEFT OUTER JOIN tag_words tw ON dt.tag_id = tw.id ' . "\n"; | ||
| 1264 | } | 1385 | } |
| 1265 | } | 1386 | } |
| 1266 | else | 1387 | else |
| @@ -1269,10 +1390,21 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1269,10 +1390,21 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1269 | $sql .= ' folders f ' ."\n"; | 1390 | $sql .= ' folders f ' ."\n"; |
| 1270 | } | 1391 | } |
| 1271 | 1392 | ||
| 1393 | + /* | ||
| 1394 | + * This builds the JOINs required to correctly select on multiple tables. | ||
| 1395 | + * | ||
| 1396 | + * NOTE This is explicitly required for multi-selecting from the same table using multiple | ||
| 1397 | + * joins with different offset naming. | ||
| 1398 | + * This multi-selecting is necessary to avoid issues with complex queries | ||
| 1399 | + * requiring different results from a single column within a database table. | ||
| 1400 | + * | ||
| 1401 | + * For an example of how the field classes need to be set up to take advantage of this code | ||
| 1402 | + * look at the constructors for the AnyMetadataField class or the MimeTypeField class. | ||
| 1403 | + */ | ||
| 1272 | $offset = 0; | 1404 | $offset = 0; |
| 1273 | foreach($this->db as $expr) | 1405 | foreach($this->db as $expr) |
| 1274 | { | 1406 | { |
| 1275 | - $field = $expr->left(); | 1407 | + $field = $expr->left(); |
| 1276 | $jointable=$field->getJoinTable(); | 1408 | $jointable=$field->getJoinTable(); |
| 1277 | if (!is_null($jointable)) | 1409 | if (!is_null($jointable)) |
| 1278 | { | 1410 | { |
| @@ -1360,6 +1492,13 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1360,6 +1492,13 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1360 | throw new Exception('join field not found'); | 1492 | throw new Exception('join field not found'); |
| 1361 | } | 1493 | } |
| 1362 | 1494 | ||
| 1495 | + /** | ||
| 1496 | + * Creates the core SQL expression for a search expression | ||
| 1497 | + * | ||
| 1498 | + * @access private | ||
| 1499 | + * @param string $expr | ||
| 1500 | + * @return string $query | ||
| 1501 | + */ | ||
| 1363 | private function buildCoreSQLExpr($expr) | 1502 | private function buildCoreSQLExpr($expr) |
| 1364 | { | 1503 | { |
| 1365 | $left = $expr->left(); | 1504 | $left = $expr->left(); |
| @@ -1383,6 +1522,15 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1383,6 +1522,15 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1383 | return $query; | 1522 | return $query; |
| 1384 | } | 1523 | } |
| 1385 | 1524 | ||
| 1525 | + /** | ||
| 1526 | + * Creates the complex SQL query using the other query building functions | ||
| 1527 | + * to create the individual parts of the query and combining into the final | ||
| 1528 | + * query to be run on the database | ||
| 1529 | + * | ||
| 1530 | + * @access private | ||
| 1531 | + * @param string $expr | ||
| 1532 | + * @return string $sql | ||
| 1533 | + */ | ||
| 1386 | public function buildComplexQuery($expr) | 1534 | public function buildComplexQuery($expr) |
| 1387 | { | 1535 | { |
| 1388 | $this->exploreExprs($expr); | 1536 | $this->exploreExprs($expr); |
| @@ -1404,6 +1552,13 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1404,6 +1552,13 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1404 | return $sql; | 1552 | return $sql; |
| 1405 | } | 1553 | } |
| 1406 | 1554 | ||
| 1555 | + /** | ||
| 1556 | + * Builds a simple database query | ||
| 1557 | + * | ||
| 1558 | + * @param string $op | ||
| 1559 | + * @param array $group | ||
| 1560 | + * @return string $sql | ||
| 1561 | + */ | ||
| 1407 | public function buildSimpleQuery($op, $group) | 1562 | public function buildSimpleQuery($op, $group) |
| 1408 | { | 1563 | { |
| 1409 | $this->exploreGroup($group); | 1564 | $this->exploreGroup($group); |
| @@ -1421,18 +1576,17 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1421,18 +1576,17 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1421 | $field = $expr->left(); | 1576 | $field = $expr->left(); |
| 1422 | 1577 | ||
| 1423 | if (is_null($field->getJoinTable())) | 1578 | if (is_null($field->getJoinTable())) |
| 1424 | - { | ||
| 1425 | - $alias = $this->resolveTableToAlias($field->getTable()); | ||
| 1426 | - $fieldname = $alias . '.' . $field->getField(); | ||
| 1427 | - } | ||
| 1428 | - else | ||
| 1429 | - { | ||
| 1430 | - $offset = $this->resolveJoinOffset($expr); | ||
| 1431 | - $matching = $field->getMatchingField(); | ||
| 1432 | - $tablename = $field->getJoinTable(); | ||
| 1433 | - $fieldname = "$tablename$offset.$matching"; | ||
| 1434 | - } | ||
| 1435 | - | 1579 | + { |
| 1580 | + $alias = $this->resolveTableToAlias($field->getTable()); | ||
| 1581 | + $fieldname = $alias . '.' . $field->getField(); | ||
| 1582 | + } | ||
| 1583 | + else | ||
| 1584 | + { | ||
| 1585 | + $offset = $this->resolveJoinOffset($expr); | ||
| 1586 | + $matching = $field->getMatchingField(); | ||
| 1587 | + $tablename = $field->getJoinTable(); | ||
| 1588 | + $fieldname = "$tablename$offset.$matching"; | ||
| 1589 | + } | ||
| 1436 | 1590 | ||
| 1437 | $value = $expr->right(); | 1591 | $value = $expr->right(); |
| 1438 | $sql .= $value->getSQL($field, $left->modifyName($fieldname), $expr->op(), $expr->not()); | 1592 | $sql .= $value->getSQL($field, $left->modifyName($fieldname), $expr->op(), $expr->not()); |
| @@ -1464,6 +1618,16 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1464,6 +1618,16 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1464 | return $sql; | 1618 | return $sql; |
| 1465 | } | 1619 | } |
| 1466 | 1620 | ||
| 1621 | + /** | ||
| 1622 | + * Utilises the RankManager object to determine rankings for each result | ||
| 1623 | + * returned from the search query, based on the values returned by the | ||
| 1624 | + * sub-parts of the query as built in buildCoreSQL() | ||
| 1625 | + * (see comments in that function for the code sections responsible | ||
| 1626 | + * for setting these values) | ||
| 1627 | + * | ||
| 1628 | + * @param array $result | ||
| 1629 | + * @return int $score | ||
| 1630 | + */ | ||
| 1467 | public function getRanking($result) | 1631 | public function getRanking($result) |
| 1468 | { | 1632 | { |
| 1469 | $ranker = RankManager::get(); | 1633 | $ranker = RankManager::get(); |
| @@ -1527,8 +1691,6 @@ class SQLQueryBuilder implements QueryBuilder | @@ -1527,8 +1691,6 @@ class SQLQueryBuilder implements QueryBuilder | ||
| 1527 | } | 1691 | } |
| 1528 | } | 1692 | } |
| 1529 | 1693 | ||
| 1530 | - | ||
| 1531 | - | ||
| 1532 | class OpExpr extends Expr | 1694 | class OpExpr extends Expr |
| 1533 | { | 1695 | { |
| 1534 | /** | 1696 | /** |
| @@ -2164,6 +2326,15 @@ class OpExpr extends Expr | @@ -2164,6 +2326,15 @@ class OpExpr extends Expr | ||
| 2164 | $this->exploreItem($right, $group, $interest); | 2326 | $this->exploreItem($right, $group, $interest); |
| 2165 | } | 2327 | } |
| 2166 | 2328 | ||
| 2329 | + /** | ||
| 2330 | + * Executes a database query | ||
| 2331 | + * | ||
| 2332 | + * @access private | ||
| 2333 | + * @global object $default Default config settings | ||
| 2334 | + * @param string $op The operation to perform | ||
| 2335 | + * @param array $group | ||
| 2336 | + * @return array $results | ||
| 2337 | + */ | ||
| 2167 | private function exec_db_query($op, $group) | 2338 | private function exec_db_query($op, $group) |
| 2168 | { | 2339 | { |
| 2169 | if (empty($group)) { return array(); } | 2340 | if (empty($group)) { return array(); } |
| @@ -2216,6 +2387,14 @@ class OpExpr extends Expr | @@ -2216,6 +2387,14 @@ class OpExpr extends Expr | ||
| 2216 | 2387 | ||
| 2217 | } | 2388 | } |
| 2218 | 2389 | ||
| 2390 | + /** | ||
| 2391 | + * Executes a text search query against the Lucene indexer | ||
| 2392 | + * | ||
| 2393 | + * @global object $default Default config settings | ||
| 2394 | + * @param string $op The operation to perform | ||
| 2395 | + * @param array $group | ||
| 2396 | + * @return array $results | ||
| 2397 | + */ | ||
| 2219 | private function exec_text_query($op, $group) | 2398 | private function exec_text_query($op, $group) |
| 2220 | { | 2399 | { |
| 2221 | global $default; | 2400 | global $default; |
| @@ -2262,6 +2441,12 @@ class OpExpr extends Expr | @@ -2262,6 +2441,12 @@ class OpExpr extends Expr | ||
| 2262 | return $results; | 2441 | return $results; |
| 2263 | } | 2442 | } |
| 2264 | 2443 | ||
| 2444 | + /** | ||
| 2445 | + * Evaluate a search query | ||
| 2446 | + * | ||
| 2447 | + * @param int $context The context to which the query applies (document/folder/both) | ||
| 2448 | + * @return array $permResults | ||
| 2449 | + */ | ||
| 2265 | public function evaluate($context = ExprContext::DOCUMENT_AND_FOLDER) | 2450 | public function evaluate($context = ExprContext::DOCUMENT_AND_FOLDER) |
| 2266 | { | 2451 | { |
| 2267 | if ($context == ExprContext::DOCUMENT_AND_FOLDER) | 2452 | if ($context == ExprContext::DOCUMENT_AND_FOLDER) |