CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

SPTSearchEngine.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: SPTSearchEngine.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2011-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
10 class SPTSearchEngine extends SearchEngine {
11
12 function __construct()
13 {
14 # pass database handle and config values to real search engine object
15 parent::__construct("Resources", "ResourceId");
16
17 # for each field defined in schema
18 $this->Schema = new MetadataSchema();
19 $Fields = $this->Schema->GetFields();
20 foreach ($Fields as $Field)
21 {
22 # determine field type for searching
23 switch ($Field->Type())
24 {
25 case MetadataSchema::MDFTYPE_TEXT:
26 case MetadataSchema::MDFTYPE_PARAGRAPH:
27 case MetadataSchema::MDFTYPE_USER:
28 case MetadataSchema::MDFTYPE_TREE:
29 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
30 case MetadataSchema::MDFTYPE_OPTION:
31 case MetadataSchema::MDFTYPE_IMAGE:
32 case MetadataSchema::MDFTYPE_FILE:
33 case MetadataSchema::MDFTYPE_URL:
34 case MetadataSchema::MDFTYPE_REFERENCE:
35 $FieldType = self::FIELDTYPE_TEXT;
36 break;
37
38 case MetadataSchema::MDFTYPE_NUMBER:
39 case MetadataSchema::MDFTYPE_FLAG:
40 $FieldType = self::FIELDTYPE_NUMERIC;
41 break;
42
43 case MetadataSchema::MDFTYPE_DATE:
44 $FieldType = self::FIELDTYPE_DATERANGE;
45 break;
46
47 case MetadataSchema::MDFTYPE_TIMESTAMP:
48 $FieldType = self::FIELDTYPE_DATE;
49 break;
50
51 case MetadataSchema::MDFTYPE_POINT:
52 $FieldType = NULL;
53 break;
54
55 default:
56 exit("ERROR: unknown field type "
57 .$Field->Type()." in SPTSearchEngine.php");
58 break;
59 }
60
61 if ($FieldType !== NULL)
62 {
63 # add field to search engine
64 $this->AddField($Field->Name(), $FieldType,
65 $Field->SearchWeight(),
66 $Field->IncludeInKeywordSearch());
67 }
68 }
69 }
70
78 function GetFieldContent($ItemId, $FieldName)
79 {
80 # get resource object
81 $Resource = new Resource($ItemId);
82
83 # if this is a reference field
84 $Field = $this->Schema->GetFieldByName($FieldName);
85 if ($Field->Type() == MetadataSchema::MDFTYPE_REFERENCE)
86 {
87 # retrieve IDs of referenced items
88 $ReferredItemIds = $Resource->Get($FieldName);
89
90 # for each referred item
91 $ReturnValue = array();
92 foreach ($ReferredItemIds as $RefId)
93 {
94 # retrieve title value for item and add to returned values
95 $RefResource = new Resource($RefId);
96 $ReturnValue[] = $RefResource->GetMapped("Title");
97 }
98
99 # return referred item titles to caller
100 return $ReturnValue;
101 }
102 else
103 {
104 # retrieve text (including variants) from resource object and return to caller
105 return $Resource->Get($FieldName, FALSE, TRUE);
106 }
107 }
108
109 # overloaded version of method to retrieve resource/phrase match list
110 function SearchFieldForPhrases($FieldName, $Phrase)
111 {
112 # normalize and escape search phrase for use in SQL query
113 $SearchPhrase = strtolower(addslashes($Phrase));
114
115 # query DB for matching list based on field type
116 $Field = $this->Schema->GetFieldByName($FieldName);
117 switch ($Field->Type())
118 {
119 case MetadataSchema::MDFTYPE_TEXT:
120 case MetadataSchema::MDFTYPE_PARAGRAPH:
121 case MetadataSchema::MDFTYPE_FILE:
122 case MetadataSchema::MDFTYPE_URL:
123 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
124 ."WHERE POSITION('".$SearchPhrase."'"
125 ." IN LOWER(`".$Field->DBFieldName()."`)) ";
126 break;
127
128 case MetadataSchema::MDFTYPE_IMAGE:
129 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
130 ."WHERE POSITION('".$SearchPhrase."'"
131 ." IN LOWER(`".$Field->DBFieldName()."AltText`)) ";
132 break;
133
134 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
135 $NameTableSize = $this->DB->Query("SELECT COUNT(*) AS NameCount"
136 ." FROM ControlledNames", "NameCount");
137 $QueryString = "SELECT DISTINCT ResourceNameInts.ResourceId "
138 ."FROM ResourceNameInts, ControlledNames "
139 ."WHERE POSITION('".$SearchPhrase."' IN LOWER(ControlledName)) "
140 ."AND ControlledNames.ControlledNameId"
141 ." = ResourceNameInts.ControlledNameId "
142 ."AND ControlledNames.FieldId = ".$Field->Id();
143 $SecondQueryString = "SELECT DISTINCT ResourceNameInts.ResourceId "
144 ."FROM ResourceNameInts, ControlledNames, VariantNames "
145 ."WHERE POSITION('".$SearchPhrase."' IN LOWER(VariantName)) "
146 ."AND VariantNames.ControlledNameId"
147 ." = ResourceNameInts.ControlledNameId "
148 ."AND ControlledNames.ControlledNameId"
149 ." = ResourceNameInts.ControlledNameId "
150 ."AND ControlledNames.FieldId = ".$Field->Id();
151 break;
152
153 case MetadataSchema::MDFTYPE_OPTION:
154 $QueryString = "SELECT DISTINCT ResourceNameInts.ResourceId "
155 ."FROM ResourceNameInts, ControlledNames "
156 ."WHERE POSITION('".$SearchPhrase."' IN LOWER(ControlledName)) "
157 ."AND ControlledNames.ControlledNameId"
158 ." = ResourceNameInts.ControlledNameId "
159 ."AND ControlledNames.FieldId = ".$Field->Id();
160 break;
161
162 case MetadataSchema::MDFTYPE_TREE:
163 $QueryString = "SELECT DISTINCT ResourceClassInts.ResourceId "
164 ."FROM ResourceClassInts, Classifications "
165 ."WHERE POSITION('".$SearchPhrase
166 ."' IN LOWER(ClassificationName)) "
167 ."AND Classifications.ClassificationId"
168 ." = ResourceClassInts.ClassificationId "
169 ."AND Classifications.FieldId = ".$Field->Id();
170 break;
171
172 case MetadataSchema::MDFTYPE_USER:
173 $UserId = $this->DB->Query("SELECT UserId FROM APUsers "
174 ."WHERE POSITION('".$SearchPhrase
175 ."' IN LOWER(UserName)) "
176 ."OR POSITION('".$SearchPhrase
177 ."' IN LOWER(RealName))", "UserId");
178 if ($UserId != NULL)
179 {
180 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
181 ."WHERE `".$Field->DBFieldName()."` = ".$UserId;
182 }
183 break;
184
185 case MetadataSchema::MDFTYPE_NUMBER:
186 if ($SearchPhrase > 0)
187 {
188 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
189 ."WHERE `".$Field->DBFieldName()
190 ."` = ".(int)$SearchPhrase;
191 }
192 break;
193
194 case MetadataSchema::MDFTYPE_FLAG:
195 case MetadataSchema::MDFTYPE_DATE:
196 case MetadataSchema::MDFTYPE_TIMESTAMP:
197 case MetadataSchema::MDFTYPE_REFERENCE:
198 # (these types not yet handled by search engine for phrases)
199 break;
200 }
201
202 # build match list based on results returned from DB
203 if (isset($QueryString))
204 {
205 $this->DMsg(7, "Performing phrase search query (<i>".$QueryString."</i>)");
206 if ($this->DebugLevel > 9) { $StartTime = microtime(TRUE); }
207 $this->DB->Query($QueryString);
208 if ($this->DebugLevel > 9)
209 {
210 $EndTime = microtime(TRUE);
211 if (($StartTime - $EndTime) > 0.1)
212 {
213 printf("SE: Query took %.2f seconds<br>\n",
214 ($EndTime - $StartTime));
215 }
216 }
217 $MatchList = $this->DB->FetchColumn("ResourceId");
218 if (isset($SecondQueryString))
219 {
220 $this->DMsg(7, "Performing second phrase search query"
221 ." (<i>".$SecondQueryString."</i>)");
222 if ($this->DebugLevel > 9) { $StartTime = microtime(TRUE); }
223 $this->DB->Query($SecondQueryString);
224 if ($this->DebugLevel > 9)
225 {
226 $EndTime = microtime(TRUE);
227 if (($StartTime - $EndTime) > 0.1)
228 {
229 printf("SE: query took %.2f seconds<br>\n",
230 ($EndTime - $StartTime));
231 }
232 }
233 $MatchList = $MatchList + $this->DB->FetchColumn("ResourceId");
234 }
235 }
236 else
237 {
238 $MatchList = array();
239 }
240
241 # return list of matching resources to caller
242 return $MatchList;
243 }
244
245 # search field for records that meet comparison
246 function SearchFieldsForComparisonMatches($FieldNames, $Operators, $Values)
247 {
248 # use SQL keyword appropriate to current search logic for combining operations
249 $CombineWord = ($this->DefaultSearchLogic == self::LOGIC_AND) ? " AND " : " OR ";
250
251 # for each comparison
252 foreach ($FieldNames as $Index => $FieldName)
253 {
254 $Operator = $Operators[$Index];
255 $Value = $Values[$Index];
256
257 # determine query based on field type
258 $Field = $this->Schema->GetFieldByName($FieldName);
259 if ($Field != NULL)
260 {
261 switch ($Field->Type())
262 {
263 case MetadataSchema::MDFTYPE_TEXT:
264 case MetadataSchema::MDFTYPE_PARAGRAPH:
265 case MetadataSchema::MDFTYPE_NUMBER:
266 case MetadataSchema::MDFTYPE_FLAG:
267 case MetadataSchema::MDFTYPE_USER:
268 case MetadataSchema::MDFTYPE_URL:
269 if (isset($Queries["Resources"]))
270 {
271 $Queries["Resources"] .= $CombineWord;
272 }
273 else
274 {
275 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
276 ." FROM Resources WHERE ";
277 }
278 if ($Field->Type() == MetadataSchema::MDFTYPE_USER)
279 {
280 $User = new CWUser($Value);
281 $Value = $User->Id();
282 }
283 $Queries["Resources"] .= "`".$Field->DBFieldName()
284 ."` ".$Operator." '".addslashes($Value)."' ";
285 break;
286
287 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
288 $QueryIndex = "ResourceNameInts".$Field->Id();
289 if (!isset($Queries[$QueryIndex]["A"]))
290 {
291 $Queries[$QueryIndex]["A"] =
292 "SELECT DISTINCT ResourceId"
293 ." FROM ResourceNameInts, ControlledNames "
294 ." WHERE ControlledNames.FieldId = ".$Field->Id()
295 ." AND ( ";
296 $CloseQuery[$QueryIndex]["A"] = TRUE;
297 $ComparisonCount[$QueryIndex]["A"] = 1;
298 $ComparisonCountField[$QueryIndex]["A"] = "ControlledName";
299 }
300 else
301 {
302 $Queries[$QueryIndex]["A"] .= " OR ";
303 $ComparisonCount[$QueryIndex]["A"]++;
304 }
305 $Queries[$QueryIndex]["A"] .=
306 "((ResourceNameInts.ControlledNameId"
307 ." = ControlledNames.ControlledNameId"
308 ." AND ControlledName "
309 .$Operator." '".addslashes($Value)."'))";
310 if (!isset($Queries[$QueryIndex]["B"]))
311 {
312 $Queries[$QueryIndex]["B"] =
313 "SELECT DISTINCT ResourceId"
314 . " FROM ResourceNameInts, ControlledNames,"
315 ." VariantNames "
316 ." WHERE ControlledNames.FieldId = ".$Field->Id()
317 ." AND ( ";
318 $CloseQuery[$QueryIndex]["B"] = TRUE;
319 $ComparisonCount[$QueryIndex]["B"] = 1;
320 $ComparisonCountField[$QueryIndex]["B"] = "ControlledName";
321 }
322 else
323 {
324 $Queries[$QueryIndex]["B"] .= " OR ";
325 $ComparisonCount[$QueryIndex]["B"]++;
326 }
327 $Queries[$QueryIndex]["B"] .=
328 "((ResourceNameInts.ControlledNameId"
329 ." = ControlledNames.ControlledNameId"
330 ." AND ResourceNameInts.ControlledNameId"
331 ." = VariantNames.ControlledNameId"
332 ." AND VariantName "
333 .$Operator." '".addslashes($Value)."'))";
334 break;
335
336 case MetadataSchema::MDFTYPE_OPTION:
337 $QueryIndex = "ResourceNameInts".$Field->Id();
338 if (!isset($Queries[$QueryIndex]))
339 {
340 $Queries[$QueryIndex] =
341 "SELECT DISTINCT ResourceId"
342 ." FROM ResourceNameInts, ControlledNames "
343 ." WHERE ControlledNames.FieldId = ".$Field->Id()
344 ." AND ( ";
345 $CloseQuery[$QueryIndex] = TRUE;
346 $ComparisonCount[$QueryIndex] = 1;
347 $ComparisonCountField[$QueryIndex] = "ControlledName";
348 }
349 else
350 {
351 $Queries[$QueryIndex] .= " OR ";
352 $ComparisonCount[$QueryIndex]++;
353 }
354 $Queries[$QueryIndex] .=
355 "(ResourceNameInts.ControlledNameId"
356 ." = ControlledNames.ControlledNameId"
357 ." AND ControlledName ".$Operator
358 ." '".addslashes($Value)."')";
359 break;
360
361 case MetadataSchema::MDFTYPE_TREE:
362 $QueryIndex = "ResourceClassInts".$Field->Id();
363 if (!isset($Queries[$QueryIndex]))
364 {
365 $Queries[$QueryIndex] = "SELECT DISTINCT ResourceId"
366 ." FROM ResourceClassInts, Classifications"
367 ." WHERE ResourceClassInts.ClassificationId"
368 ." = Classifications.ClassificationId"
369 ." AND Classifications.FieldId"
370 ." = ".$Field->Id()." AND ( ";
371 $CloseQuery[$QueryIndex] = TRUE;
372 $ComparisonCount[$QueryIndex] = 1;
373 $ComparisonCountField[$QueryIndex] = "ClassificationName";
374 }
375 else
376 {
377 $Queries[$QueryIndex] .= " OR ";
378 $ComparisonCount[$QueryIndex]++;
379 }
380 $Queries[$QueryIndex] .= " ClassificationName "
381 .$Operator." '".addslashes($Value)."'";
382 break;
383
384 case MetadataSchema::MDFTYPE_TIMESTAMP:
385 # if value appears to have time component or text description
386 if (strpos($Value, ":")
387 || strstr($Value, "day")
388 || strstr($Value, "week")
389 || strstr($Value, "month")
390 || strstr($Value, "year")
391 || strstr($Value, "hour")
392 || strstr($Value, "minute"))
393 {
394 if (isset($Queries["Resources"]))
395 {
396 $Queries["Resources"] .= $CombineWord;
397 }
398 else
399 {
400 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
401 ." FROM Resources WHERE ";
402 }
403
404 # flip operator if necessary
405 if (strstr($Value, "ago"))
406 {
407 $OperatorFlipMap = array(
408 "<" => ">=",
409 ">" => "<=",
410 "<=" => ">",
411 ">=" => "<",
412 );
413 $Operator = isset($OperatorFlipMap[$Operator])
414 ? $OperatorFlipMap[$Operator] : $Operator;
415 }
416
417 # use strtotime method to build condition
418 $TimestampValue = strtotime($Value);
419 if (($TimestampValue !== FALSE) && ($TimestampValue != -1))
420 {
421 if ((date("H:i:s", $TimestampValue) == "00:00:00")
422 && (strpos($Value, "00:00") === FALSE)
423 && ($Operator == "<="))
424 {
425 $NormalizedValue =
426 date("Y-m-d", $TimestampValue)." 23:59:59";
427 }
428 else
429 {
430 $NormalizedValue = date(
431 "Y-m-d H:i:s", $TimestampValue);
432 }
433 }
434 else
435 {
436 $NormalizedValue = addslashes($Value);
437 }
438 $Queries["Resources"] .=
439 " ( `".$Field->DBFieldName()."` "
440 .$Operator
441 ." '".$NormalizedValue."' ) ";
442 }
443 else
444 {
445 # use Date object method to build condition
446 $Date = new Date($Value);
447 if ($Date->Precision())
448 {
449 if (isset($Queries["Resources"]))
450 {
451 $Queries["Resources"] .= $CombineWord;
452 }
453 else
454 {
455 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
456 ." FROM Resources WHERE ";
457 }
458 $Queries["Resources"] .= " ( ".$Date->SqlCondition(
459 $Field->DBFieldName(), NULL, $Operator)." ) ";
460 }
461 }
462 break;
463
464 case MetadataSchema::MDFTYPE_DATE:
465 $Date = new Date($Value);
466 if ($Date->Precision())
467 {
468 if (isset($Queries["Resources"]))
469 {
470 $Queries["Resources"] .= $CombineWord;
471 }
472 else
473 {
474 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
475 ." FROM Resources WHERE ";
476 }
477 $Queries["Resources"] .= " ( ".$Date->SqlCondition(
478 $Field->DBFieldName()."Begin",
479 $Field->DBFieldName()."End", $Operator)." ) ";
480 }
481 break;
482
483 case MetadataSchema::MDFTYPE_REFERENCE:
484 $QueryIndex = "ReferenceInts".$Field->Id();
485 if (!isset($Queries[$QueryIndex]))
486 {
487 if (!isset($NameField))
488 {
489 $NameField =
490 $this->Schema->GetFieldByMappedName(
491 "Title");
492 }
493 $Queries[$QueryIndex] =
494 "SELECT DISTINCT RI.SrcResourceId AS ResourceId"
495 ." FROM ReferenceInts AS RI, Resources AS R "
496 ." WHERE RI.FieldId = ".$Field->Id()
497 ." AND (";
498 $CloseQuery[$QueryIndex] = TRUE;
499 $ComparisonCount[$QueryIndex] = 1;
500 $ComparisonCountField[$QueryIndex] =
501 "R.`".$NameField->DBFieldName()."`";
502 }
503 else
504 {
505 $Queries[$QueryIndex] .= $CombineWord;
506 $ComparisonCount[$QueryIndex]++;
507 }
508 $Queries[$QueryIndex] .= "(R.`".$NameField->DBFieldName()."` "
509 .$Operator." '".addslashes($Value)."'"
510 ." AND R.ResourceId = RI.DstResourceId)";
511 break;
512
513 case MetadataSchema::MDFTYPE_IMAGE:
514 case MetadataSchema::MDFTYPE_FILE:
515 # (these types not yet handled by search engine for comparisons)
516 break;
517 }
518 }
519 }
520
521 # if queries found
522 if (isset($Queries))
523 {
524 # for each assembled query
525 foreach ($Queries as $QueryIndex => $Query)
526 {
527 # if query has multiple parts
528 if (is_array($Query))
529 {
530 # for each part of query
531 $ResourceIds = array();
532 foreach ($Query as $PartIndex => $PartQuery)
533 {
534 # add closing paren if query was flagged to be closed
535 if (isset($CloseQuery[$QueryIndex][$PartIndex]))
536 {
537 $PartQuery .= ") ";
538 if (($this->DefaultSearchLogic == self::LOGIC_AND)
539 && ($ComparisonCount[$QueryIndex][$PartIndex] > 1))
540 {
541 $PartQuery .= "GROUP BY ResourceId"
542 ." HAVING COUNT(DISTINCT "
543 .$ComparisonCountField[$QueryIndex][$PartIndex]
544 .") = "
545 .$ComparisonCount[$QueryIndex][$PartIndex];
546 }
547 }
548
549 # perform query and retrieve IDs
550 $this->DMsg(5, "Performing comparison query <i>"
551 .$PartQuery."</i>");
552 $this->DB->Query($PartQuery);
553 $ResourceIds = $ResourceIds
554 + $this->DB->FetchColumn("ResourceId");
555 $this->DMsg(5, "Comparison query produced <i>"
556 .count($ResourceIds)."</i> results");
557 }
558 }
559 else
560 {
561 # add closing paren if query was flagged to be closed
562 if (isset($CloseQuery[$QueryIndex]))
563 {
564 $Query .= ") ";
565 if (($this->DefaultSearchLogic == self::LOGIC_AND)
566 && ($ComparisonCount[$QueryIndex] > 1))
567 {
568 $Query .= "GROUP BY ResourceId"
569 ." HAVING COUNT(DISTINCT "
570 .$ComparisonCountField[$QueryIndex]
571 .") = "
572 .$ComparisonCount[$QueryIndex];
573 }
574 }
575
576 # perform query and retrieve IDs
577 $this->DMsg(5, "Performing comparison query <i>".$Query."</i>");
578 $this->DB->Query($Query);
579 $ResourceIds = $this->DB->FetchColumn("ResourceId");
580 $this->DMsg(5, "Comparison query produced <i>"
581 .count($ResourceIds)."</i> results");
582 }
583
584 # if we already have some results
585 if (isset($Results))
586 {
587 # if search logic is set to AND
588 if ($this->DefaultSearchLogic == self::LOGIC_AND)
589 {
590 # remove anything from results that was not returned from query
591 $Results = array_intersect($Results, $ResourceIds);
592 }
593 else
594 {
595 # add values returned from query to results
596 $Results = array_unique(array_merge($Results, $ResourceIds));
597 }
598 }
599 else
600 {
601 # set results to values returned from query
602 $Results = $ResourceIds;
603 }
604 }
605 }
606 else
607 {
608 # initialize results to empty list
609 $Results = array();
610 }
611
612 # return results to caller
613 return $Results;
614 }
615
616 static function GetItemIdsSortedByField($FieldName, $SortDescending)
617 {
618 $RFactory = new ResourceFactory();
619 return $RFactory->GetResourceIdsSortedBy($FieldName, !$SortDescending);
620 }
621
622 static function QueueUpdateForItem($ItemId,
623 $TaskPriority = ApplicationFramework::PRIORITY_LOW)
624 {
625 $Item = new Resource($ItemId);
626 $TaskDescription = "Update search data for"
627 ." <a href=\"r".$ItemId."\"><i>"
628 .$Item->GetMapped("Title")."</i></a>";
629 $GLOBALS["AF"]->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
630 array(intval($ItemId)), $TaskPriority, $TaskDescription);
631 }
632
633 static function RunUpdateForItem($ItemId)
634 {
635 # bail out if item ID is negative (indicating a temporary record)
636 if ($ItemId < 0) { return; }
637
638 # check that resource still exists
639 $RFactory = new ResourceFactory();
640 if (!$RFactory->ItemExists($ItemId)) { return; }
641
642 # retrieve schema ID of item to use for item type
643 $Resource = new Resource($ItemId);
644 $ItemType = $Resource->SchemaId();
645
646 # update search data for resource
647 $SearchEngine = new SPTSearchEngine();
648 $SearchEngine->UpdateForItem($ItemId, $ItemType);
649 }
650
659 static function GetResultFacets($SearchResults, $User)
660 {
661 # classifications and names associated with these search results
662 $SearchClasses = array();
663 $SearchNames = array();
664
665 # disable DB cache for the search suggestions process,
666 # this avoids memory exhaustion.
667 $DB = new Database();
668 $DB->Caching(FALSE);
669
670 if (count($SearchResults)>0)
671 {
672 foreach (array_chunk($SearchResults, 1000, TRUE) as $Chunk)
673 {
674 # pull out all the Classifications that were associated
675 # with our search results
676 $DB->Query("SELECT ResourceId,ClassificationId FROM ResourceClassInts "
677 ."WHERE ResourceId IN "
678 ."(".implode(",", array_keys($Chunk)).")");
679 foreach ($DB->FetchRows() as $Row)
680 {
681 $SearchClasses[ $Row["ClassificationId"] ] []= $Row["ResourceId"] ;
682 }
683
684 # similarly with controlled names
685 $DB->Query("SELECT ResourceId,ControlledNameId FROM ResourceNameInts "
686 ."WHERE ResourceId in "
687 ."(".implode(",", array_keys($Chunk)).")");
688 foreach ($DB->FetchRows() as $Row)
689 {
690 $SearchNames[ $Row["ControlledNameId"] ] []= $Row["ResourceId"];
691 }
692 }
693 }
694
695 # generate a map of FieldId -> Field Names for all of the generated facets:
696 $SuggestionsById = array();
697
698 # pull relevant Classification names out of the DB
699 if (count($SearchClasses)>0)
700 {
701 foreach (array_chunk($SearchClasses, 1000, TRUE) as $Chunk)
702 {
703 $DB->Query("SELECT FieldId,ClassificationId,ClassificationName"
704 ." FROM Classifications"
705 ." WHERE ClassificationId"
706 ." IN (".implode(",", array_keys($Chunk)).")");
707 foreach ($DB->FetchRows() as $Row)
708 {
709 $SuggestionsById[$Row["FieldId"]] []=
710 array("Id" => $Row["ClassificationId"],
711 "Name" => $Row["ClassificationName"],
712 "Count" => count($SearchClasses[
713 $Row["ClassificationId"]]));
714 }
715 }
716 }
717
718 # pull relevant ControlledNames out of the DB
719 if (count($SearchNames)>0)
720 {
721 foreach (array_chunk($SearchNames, 1000, TRUE) as $Chunk)
722 {
723 $DB->Query("SELECT FieldId,ControlledNameId,ControlledName"
724 ." FROM ControlledNames"
725 ." WHERE ControlledNameId"
726 ." IN (".implode(",", array_keys($SearchNames)).")");
727 foreach ($DB->FetchRows() as $Row)
728 {
729 $SuggestionsById[$Row["FieldId"]] []=
730 array("Id" => $Row["ControlledNameId"],
731 "Name" => $Row["ControlledName"],
732 "Count" => count(
733 $SearchNames[$Row["ControlledNameId"]]));
734 }
735 }
736 }
737
738 # translate the suggestions that we have in terms of the
739 # FieldIds to suggestions in terms of the field names
740 $SuggestionsByFieldName = array();
741
742 # if we have suggestions to offer
743 if (count($SuggestionsById)>0)
744 {
745 $Schema = new MetadataSchema();
746
747 # gill in an array that maps FieldNames to search links
748 # which would be appropriate for that field
749 foreach ($SuggestionsById as $FieldId => $FieldValues)
750 {
751 $ThisField = $Schema->GetField($FieldId);
752
753 # bail on fields that didn't exist and on fields that the
754 # current user cannot view, and on fields that are
755 # disabled for advanced searching
756 if (is_object($ThisField) &&
757 $ThisField->Status() == MetadataSchema::MDFSTAT_OK &&
758 $ThisField->IncludeInFacetedSearch() &&
759 $ThisField->Enabled() &&
760 $User->HasPriv($ThisField->ViewingPrivileges()))
761 {
762 $SuggestionsByFieldName[ $ThisField->Name() ] = array();
763
764 foreach ($FieldValues as $Value)
765 {
766 $SuggestionsByFieldName [ $ThisField->Name() ] [$Value["Id"]] =
767 array("Name" => $Value["Name"], "Count" => $Value["Count"] );
768 }
769 }
770 }
771 }
772
773 ksort($SuggestionsByFieldName);
774
775 return $SuggestionsByFieldName;
776 }
777
778 private $Schema;
779
780 # functions for backward compatability w/ old SPT code
781 function UpdateForResource($ItemId)
782 {
783 $this->UpdateForItem($ItemId);
784 }
785 }
MetadataSchema\MDFTYPE_IMAGE
const MDFTYPE_IMAGE
Definition: MetadataSchema.php:30
MetadataSchema\MDFTYPE_TIMESTAMP
const MDFTYPE_TIMESTAMP
Definition: MetadataSchema.php:24
SearchEngine\$DB
$DB
Definition: SearchEngine.php:904
SPTSearchEngine
Definition: SPTSearchEngine.php:10
SPTSearchEngine\SearchFieldForPhrases
SearchFieldForPhrases($FieldName, $Phrase)
Definition: SPTSearchEngine.php:110
MetadataSchema\MDFTYPE_FILE
const MDFTYPE_FILE
Definition: MetadataSchema.php:31
MetadataSchema
Metadata schema (in effect a Factory class for MetadataField).
Definition: MetadataSchema.php:13
Database
SQL database abstraction object with smart query caching.
Definition: Axis--Database.php:22
SearchEngine\AddField
AddField($FieldName, $FieldType, $Weight, $UsedInKeywordSearch)
Add field to include in searching.
Definition: SearchEngine.php:59
MetadataSchema\MDFTYPE_REFERENCE
const MDFTYPE_REFERENCE
Definition: MetadataSchema.php:34
SPTSearchEngine\UpdateForResource
UpdateForResource($ItemId)
Definition: SPTSearchEngine.php:781
MetadataSchema\MDFSTAT_OK
const MDFSTAT_OK
Definition: MetadataSchema.php:42
MetadataSchema\MDFTYPE_NUMBER
const MDFTYPE_NUMBER
Definition: MetadataSchema.php:22
SearchEngine\UpdateForItem
UpdateForItem($ItemId, $ItemType=0)
Update search database for the specified item.
Definition: SearchEngine.php:494
SPTSearchEngine\GetFieldContent
GetFieldContent($ItemId, $FieldName)
Overloaded version of method to retrieve text from DB.
Definition: SPTSearchEngine.php:78
MetadataSchema\MDFTYPE_TREE
const MDFTYPE_TREE
Definition: MetadataSchema.php:26
Date
Definition: Axis--Date.php:18
MetadataSchema\MDFTYPE_OPTION
const MDFTYPE_OPTION
Definition: MetadataSchema.php:28
MetadataSchema\MDFTYPE_FLAG
const MDFTYPE_FLAG
Definition: MetadataSchema.php:25
MetadataSchema\MDFTYPE_CONTROLLEDNAME
const MDFTYPE_CONTROLLEDNAME
Definition: MetadataSchema.php:27
PHP
PHP
Definition: RSSClient--Test.php:12
SPTSearchEngine\RunUpdateForItem
static RunUpdateForItem($ItemId)
Definition: SPTSearchEngine.php:633
MetadataSchema\MDFTYPE_PARAGRAPH
const MDFTYPE_PARAGRAPH
Definition: MetadataSchema.php:21
SPTSearchEngine\SearchFieldsForComparisonMatches
SearchFieldsForComparisonMatches($FieldNames, $Operators, $Values)
Definition: SPTSearchEngine.php:246
MetadataSchema\MDFTYPE_DATE
const MDFTYPE_DATE
Definition: MetadataSchema.php:23
SearchEngine\DMsg
DMsg($Level, $Msg)
Definition: SearchEngine.php:2178
Resource
Represents a "resource" in CWIS.
Definition: Resource.php:13
MetadataSchema\MDFTYPE_URL
const MDFTYPE_URL
Definition: MetadataSchema.php:32
SPTSearchEngine\GetResultFacets
static GetResultFacets($SearchResults, $User)
Generate a list of suggested additional search terms that can be used for faceted searching...
Definition: SPTSearchEngine.php:659
MetadataSchema\MDFTYPE_TEXT
const MDFTYPE_TEXT
Definition: MetadataSchema.php:20
SPTSearchEngine\GetItemIdsSortedByField
static GetItemIdsSortedByField($FieldName, $SortDescending)
Definition: SPTSearchEngine.php:616
SearchEngine
Core metadata archive search engine class.
Definition: SearchEngine.php:13
MetadataSchema\MDFTYPE_USER
const MDFTYPE_USER
Definition: MetadataSchema.php:29
SearchEngine\DefaultSearchLogic
DefaultSearchLogic($NewSetting=NULL)
Get/set default search logic (LOGIC_AND or LOGIC_OR).
Definition: SearchEngine.php:402
SearchEngine\DebugLevel
DebugLevel($NewValue)
Set debug output level.
Definition: SearchEngine.php:103
MetadataSchema\MDFTYPE_POINT
const MDFTYPE_POINT
Definition: MetadataSchema.php:33
ResourceFactory
Factory for Resource objects.
Definition: ResourceFactory.php:13
CWUser
CWIS-specific user class.
Definition: CWUser.php:13
SPTSearchEngine\__construct
__construct()
Definition: SPTSearchEngine.php:12
SPTSearchEngine\QueueUpdateForItem
static QueueUpdateForItem($ItemId, $TaskPriority=ApplicationFramework::PRIORITY_LOW)
Definition: SPTSearchEngine.php:622