CWIS Developer Documentation

- Home
- Main Page
- 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 SPTSearchEngine()
13 {
14 # pass database handle and config values to real search engine object
15 $this->SearchEngine("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 = ResourceNameInts.ControlledNameId "
158 ."AND ControlledNames.FieldId = ".$Field->Id();
159 break;
160
161 case MetadataSchema::MDFTYPE_TREE:
162 $QueryString = "SELECT DISTINCT ResourceClassInts.ResourceId "
163 ."FROM ResourceClassInts, Classifications "
164 ."WHERE POSITION('".$SearchPhrase."' IN LOWER(ClassificationName)) "
165 ."AND Classifications.ClassificationId = ResourceClassInts.ClassificationId "
166 ."AND Classifications.FieldId = ".$Field->Id();
167 break;
168
169 case MetadataSchema::MDFTYPE_USER:
170 $UserId = $this->DB->Query("SELECT UserId FROM APUsers "
171 ."WHERE POSITION('".$SearchPhrase."' IN LOWER(UserName)) "
172 ."OR POSITION('".$SearchPhrase."' IN LOWER(RealName))", "UserId");
173 if ($UserId != NULL)
174 {
175 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
176 ."WHERE `".$Field->DBFieldName()."` = ".$UserId;
177 }
178 break;
179
180 case MetadataSchema::MDFTYPE_NUMBER:
181 if ($SearchPhrase > 0)
182 {
183 $QueryString = "SELECT DISTINCT ResourceId FROM Resources "
184 ."WHERE `".$Field->DBFieldName()."` = ".(int)$SearchPhrase;
185 }
186 break;
187
188 case MetadataSchema::MDFTYPE_FLAG:
189 case MetadataSchema::MDFTYPE_DATE:
190 case MetadataSchema::MDFTYPE_TIMESTAMP:
191 case MetadataSchema::MDFTYPE_REFERENCE:
192 # (these types not yet handled by search engine for phrases)
193 break;
194 }
195
196 # build match list based on results returned from DB
197 if (isset($QueryString))
198 {
199 $this->DMsg(7, "Performing phrase search query (<i>".$QueryString."</i>)");
200 if ($this->DebugLevel > 9) { $StartTime = microtime(TRUE); }
201 $this->DB->Query($QueryString);
202 if ($this->DebugLevel > 9)
203 {
204 $EndTime = microtime(TRUE);
205 if (($StartTime - $EndTime) > 0.1)
206 {
207 printf("SE: Query took %.2f seconds<br>\n",
208 ($EndTime - $StartTime));
209 }
210 }
211 $MatchList = $this->DB->FetchColumn("ResourceId");
212 if (isset($SecondQueryString))
213 {
214 $this->DMsg(7, "Performing second phrase search query"
215 ." (<i>".$SecondQueryString."</i>)");
216 if ($this->DebugLevel > 9) { $StartTime = microtime(TRUE); }
217 $this->DB->Query($SecondQueryString);
218 if ($this->DebugLevel > 9)
219 {
220 $EndTime = microtime(TRUE);
221 if (($StartTime - $EndTime) > 0.1)
222 {
223 printf("SE: query took %.2f seconds<br>\n",
224 ($EndTime - $StartTime));
225 }
226 }
227 $MatchList = $MatchList + $this->DB->FetchColumn("ResourceId");
228 }
229 }
230 else
231 {
232 $MatchList = array();
233 }
234
235 # return list of matching resources to caller
236 return $MatchList;
237 }
238
239 # search field for records that meet comparison
240 function SearchFieldsForComparisonMatches($FieldNames, $Operators, $Values)
241 {
242 # use SQL keyword appropriate to current search logic for combining operations
243 $CombineWord = ($this->DefaultSearchLogic == self::LOGIC_AND) ? " AND " : " OR ";
244
245 # for each comparison
246 foreach ($FieldNames as $Index => $FieldName)
247 {
248 $Operator = $Operators[$Index];
249 $Value = $Values[$Index];
250
251 # determine query based on field type
252 $Field = $this->Schema->GetFieldByName($FieldName);
253 if ($Field != NULL)
254 {
255 switch ($Field->Type())
256 {
257 case MetadataSchema::MDFTYPE_TEXT:
258 case MetadataSchema::MDFTYPE_PARAGRAPH:
259 case MetadataSchema::MDFTYPE_NUMBER:
260 case MetadataSchema::MDFTYPE_FLAG:
261 case MetadataSchema::MDFTYPE_USER:
262 case MetadataSchema::MDFTYPE_URL:
263 if (isset($Queries["Resources"]))
264 {
265 $Queries["Resources"] .= $CombineWord;
266 }
267 else
268 {
269 $Queries["Resources"] = "SELECT DISTINCT ResourceId FROM Resources WHERE ";
270 }
271 if ($Field->Type() == MetadataSchema::MDFTYPE_USER)
272 {
273 $User = new CWUser($Value);
274 $Value = $User->Id();
275 }
276 $Queries["Resources"] .= "`".$Field->DBFieldName()."` ".$Operator." '".addslashes($Value)."' ";
277 break;
278
279 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
280 $QueryIndex = "ResourceNameInts".$Field->Id();
281 if (!isset($Queries[$QueryIndex]["A"]))
282 {
283 $Queries[$QueryIndex]["A"] =
284 "SELECT DISTINCT ResourceId"
285 ." FROM ResourceNameInts, ControlledNames "
286 ." WHERE ControlledNames.FieldId = ".$Field->Id()
287 ." AND ( ";
288 $CloseQuery[$QueryIndex]["A"] = TRUE;
289 $ComparisonCount[$QueryIndex]["A"] = 1;
290 $ComparisonCountField[$QueryIndex]["A"] = "ControlledName";
291 }
292 else
293 {
294 $Queries[$QueryIndex]["A"] .= " OR ";
295 $ComparisonCount[$QueryIndex]["A"]++;
296 }
297 $Queries[$QueryIndex]["A"] .=
298 "((ResourceNameInts.ControlledNameId"
299 ." = ControlledNames.ControlledNameId"
300 ." AND ControlledName "
301 .$Operator." '".addslashes($Value)."'))";
302 if (!isset($Queries[$QueryIndex]["B"]))
303 {
304 $Queries[$QueryIndex]["B"] =
305 "SELECT DISTINCT ResourceId"
306 . " FROM ResourceNameInts, ControlledNames,"
307 ." VariantNames "
308 ." WHERE ControlledNames.FieldId = ".$Field->Id()
309 ." AND ( ";
310 $CloseQuery[$QueryIndex]["B"] = TRUE;
311 $ComparisonCount[$QueryIndex]["B"] = 1;
312 $ComparisonCountField[$QueryIndex]["B"] = "ControlledName";
313 }
314 else
315 {
316 $Queries[$QueryIndex]["B"] .= " OR ";
317 $ComparisonCount[$QueryIndex]["B"]++;
318 }
319 $Queries[$QueryIndex]["B"] .=
320 "((ResourceNameInts.ControlledNameId"
321 ." = ControlledNames.ControlledNameId"
322 ." AND ResourceNameInts.ControlledNameId"
323 ." = VariantNames.ControlledNameId"
324 ." AND VariantName "
325 .$Operator." '".addslashes($Value)."'))";
326 break;
327
328 case MetadataSchema::MDFTYPE_OPTION:
329 $QueryIndex = "ResourceNameInts".$Field->Id();
330 if (!isset($Queries[$QueryIndex]))
331 {
332 $Queries[$QueryIndex] =
333 "SELECT DISTINCT ResourceId FROM ResourceNameInts, ControlledNames "
334 ." WHERE ControlledNames.FieldId = ".$Field->Id()
335 ." AND ( ";
336 $CloseQuery[$QueryIndex] = TRUE;
337 $ComparisonCount[$QueryIndex] = 1;
338 $ComparisonCountField[$QueryIndex] = "ControlledName";
339 }
340 else
341 {
342 $Queries[$QueryIndex] .= " OR ";
343 $ComparisonCount[$QueryIndex]++;
344 }
345 $Queries[$QueryIndex] .= "(ResourceNameInts.ControlledNameId = ControlledNames.ControlledNameId"
346 ." AND ControlledName ".$Operator." '".addslashes($Value)."')";
347 break;
348
349 case MetadataSchema::MDFTYPE_TREE:
350 $QueryIndex = "ResourceClassInts".$Field->Id();
351 if (!isset($Queries[$QueryIndex]))
352 {
353 $Queries[$QueryIndex] = "SELECT DISTINCT ResourceId FROM ResourceClassInts, Classifications "
354 ." WHERE ResourceClassInts.ClassificationId = Classifications.ClassificationId"
355 ." AND Classifications.FieldId = ".$Field->Id()." AND ( ";
356 $CloseQuery[$QueryIndex] = TRUE;
357 $ComparisonCount[$QueryIndex] = 1;
358 $ComparisonCountField[$QueryIndex] = "ClassificationName";
359 }
360 else
361 {
362 $Queries[$QueryIndex] .= " OR ";
363 $ComparisonCount[$QueryIndex]++;
364 }
365 $Queries[$QueryIndex] .= " ClassificationName ".$Operator." '".addslashes($Value)."'";
366 break;
367
368 case MetadataSchema::MDFTYPE_TIMESTAMP:
369 # if value appears to have time component or text description
370 if (strpos($Value, ":")
371 || strstr($Value, "day")
372 || strstr($Value, "week")
373 || strstr($Value, "month")
374 || strstr($Value, "year")
375 || strstr($Value, "hour")
376 || strstr($Value, "minute"))
377 {
378 if (isset($Queries["Resources"]))
379 {
380 $Queries["Resources"] .= $CombineWord;
381 }
382 else
383 {
384 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
385 ." FROM Resources WHERE ";
386 }
387
388 # flip operator if necessary
389 if (strstr($Value, "ago"))
390 {
391 $OperatorFlipMap = array(
392 "<" => ">=",
393 ">" => "<=",
394 "<=" => ">",
395 ">=" => "<",
396 );
397 $Operator = isset($OperatorFlipMap[$Operator])
398 ? $OperatorFlipMap[$Operator] : $Operator;
399 }
400
401 # use strtotime method to build condition
402 $TimestampValue = strtotime($Value);
403 if (($TimestampValue !== FALSE) && ($TimestampValue != -1))
404 {
405 if ((date("H:i:s", $TimestampValue) == "00:00:00")
406 && (strpos($Value, "00:00") === FALSE)
407 && ($Operator == "<="))
408 {
409 $NormalizedValue =
410 date("Y-m-d", $TimestampValue)." 23:59:59";
411 }
412 else
413 {
414 $NormalizedValue = date("Y-m-d H:i:s", $TimestampValue);
415 }
416 }
417 else
418 {
419 $NormalizedValue = addslashes($Value);
420 }
421 $Queries["Resources"] .=
422 " ( `".$Field->DBFieldName()."` "
423 .$Operator
424 ." '".$NormalizedValue."' ) ";
425 }
426 else
427 {
428 # use Date object method to build condition
429 $Date = new Date($Value);
430 if ($Date->Precision())
431 {
432 if (isset($Queries["Resources"]))
433 {
434 $Queries["Resources"] .= $CombineWord;
435 }
436 else
437 {
438 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
439 ." FROM Resources WHERE ";
440 }
441 $Queries["Resources"] .= " ( ".$Date->SqlCondition(
442 $Field->DBFieldName(), NULL, $Operator)." ) ";
443 }
444 }
445 break;
446
447 case MetadataSchema::MDFTYPE_DATE:
448 $Date = new Date($Value);
449 if ($Date->Precision())
450 {
451 if (isset($Queries["Resources"]))
452 {
453 $Queries["Resources"] .= $CombineWord;
454 }
455 else
456 {
457 $Queries["Resources"] = "SELECT DISTINCT ResourceId"
458 ." FROM Resources WHERE ";
459 }
460 $Queries["Resources"] .= " ( ".$Date->SqlCondition(
461 $Field->DBFieldName()."Begin",
462 $Field->DBFieldName()."End", $Operator)." ) ";
463 }
464 break;
465
466 case MetadataSchema::MDFTYPE_REFERENCE:
467 $QueryIndex = "ReferenceInts".$Field->Id();
468 if (!isset($Queries[$QueryIndex]))
469 {
470 if (!isset($NameField))
471 {
472 $NameField =
473 $this->Schema->GetFieldByMappedName(
474 "Title");
475 }
476 $Queries[$QueryIndex] =
477 "SELECT DISTINCT RI.SrcResourceId AS ResourceId"
478 ." FROM ReferenceInts AS RI, Resources AS R "
479 ." WHERE RI.FieldId = ".$Field->Id()
480 ." AND (";
481 $CloseQuery[$QueryIndex] = TRUE;
482 $ComparisonCount[$QueryIndex] = 1;
483 $ComparisonCountField[$QueryIndex] =
484 "R.`".$NameField->DBFieldName()."`";
485 }
486 else
487 {
488 $Queries[$QueryIndex] .= $CombineWord;
489 $ComparisonCount[$QueryIndex]++;
490 }
491 $Queries[$QueryIndex] .= "(R.`".$NameField->DBFieldName()."` "
492 .$Operator." '".addslashes($Value)."'"
493 ." AND R.ResourceId = RI.DstResourceId)";
494 break;
495
496 case MetadataSchema::MDFTYPE_IMAGE:
497 case MetadataSchema::MDFTYPE_FILE:
498 # (these types not yet handled by search engine for comparisons)
499 break;
500 }
501 }
502 }
503
504 # if queries found
505 if (isset($Queries))
506 {
507 # for each assembled query
508 foreach ($Queries as $QueryIndex => $Query)
509 {
510 # if query has multiple parts
511 if (is_array($Query))
512 {
513 # for each part of query
514 $ResourceIds = array();
515 foreach ($Query as $PartIndex => $PartQuery)
516 {
517 # add closing paren if query was flagged to be closed
518 if (isset($CloseQuery[$QueryIndex][$PartIndex]))
519 {
520 $PartQuery .= ") ";
521 if (($this->DefaultSearchLogic == self::LOGIC_AND)
522 && ($ComparisonCount[$QueryIndex][$PartIndex] > 1))
523 {
524 $PartQuery .= "GROUP BY ResourceId"
525 ." HAVING COUNT(DISTINCT "
526 .$ComparisonCountField[$QueryIndex][$PartIndex]
527 .") = "
528 .$ComparisonCount[$QueryIndex][$PartIndex];
529 }
530 }
531
532 # perform query and retrieve IDs
533 $this->DMsg(5, "Performing comparison query <i>"
534 .$PartQuery."</i>");
535 $this->DB->Query($PartQuery);
536 $ResourceIds = $ResourceIds
537 + $this->DB->FetchColumn("ResourceId");
538 $this->DMsg(5, "Comparison query produced <i>"
539 .count($ResourceIds)."</i> results");
540 }
541 }
542 else
543 {
544 # add closing paren if query was flagged to be closed
545 if (isset($CloseQuery[$QueryIndex]))
546 {
547 $Query .= ") ";
548 if (($this->DefaultSearchLogic == self::LOGIC_AND)
549 && ($ComparisonCount[$QueryIndex] > 1))
550 {
551 $Query .= "GROUP BY ResourceId"
552 ." HAVING COUNT(DISTINCT "
553 .$ComparisonCountField[$QueryIndex]
554 .") = "
555 .$ComparisonCount[$QueryIndex];
556 }
557 }
558
559 # perform query and retrieve IDs
560 $this->DMsg(5, "Performing comparison query <i>".$Query."</i>");
561 $this->DB->Query($Query);
562 $ResourceIds = $this->DB->FetchColumn("ResourceId");
563 $this->DMsg(5, "Comparison query produced <i>"
564 .count($ResourceIds)."</i> results");
565 }
566
567 # if we already have some results
568 if (isset($Results))
569 {
570 # if search logic is set to AND
571 if ($this->DefaultSearchLogic == self::LOGIC_AND)
572 {
573 # remove anything from results that was not returned from query
574 $Results = array_intersect($Results, $ResourceIds);
575 }
576 else
577 {
578 # add values returned from query to results
579 $Results = array_unique(array_merge($Results, $ResourceIds));
580 }
581 }
582 else
583 {
584 # set results to values returned from query
585 $Results = $ResourceIds;
586 }
587 }
588 }
589 else
590 {
591 # initialize results to empty list
592 $Results = array();
593 }
594
595 # return results to caller
596 return $Results;
597 }
598
599 static function GetItemIdsSortedByField($FieldName, $SortDescending)
600 {
601 $RFactory = new ResourceFactory();
602 return $RFactory->GetResourceIdsSortedBy($FieldName, !$SortDescending);
603 }
604
605 static function QueueUpdateForItem($ItemId,
606 $TaskPriority = ApplicationFramework::PRIORITY_LOW)
607 {
608 $Item = new Resource($ItemId);
609 $TaskDescription = "Update search data for"
610 ." <a href=\"r".$ItemId."\"><i>"
611 .$Item->GetMapped("Title")."</i></a>";
612 $GLOBALS["AF"]->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"),
613 array(intval($ItemId)), $TaskPriority, $TaskDescription);
614 }
615
616 static function RunUpdateForItem($ItemId)
617 {
618 # check that resource still exists
619 $RFactory = new ResourceFactory();
620 if (!$RFactory->ItemExists($ItemId)) { return; }
621
622 # update search data for resource
623 $SearchEngine = new SPTSearchEngine();
624 $SearchEngine->UpdateForItem($ItemId);
625 }
626
634 static function GetResultFacets($SearchResults, $User)
635 {
636 # classifications and names associated with these search results
637 $SearchClasses = array();
638 $SearchNames = array();
639
640 # disable DB cache for the search suggestions process,
641 # this avoids memory exhaustion.
642 $DB = new Database();
643 $DB->Caching(FALSE);
644
645 if (count($SearchResults)>0)
646 {
647 foreach (array_chunk($SearchResults, 1000, TRUE) as $Chunk)
648 {
649 # pull out all the Classifications that were associated with our search results
650 $DB->Query("SELECT ResourceId,ClassificationId FROM ResourceClassInts "
651 ."WHERE ResourceId IN "
652 ."(".implode(",", array_keys($Chunk)).")");
653 foreach ($DB->FetchRows() as $Row)
654 {
655 $SearchClasses[ $Row["ClassificationId"] ] []= $Row["ResourceId"] ;
656 }
657
658 # similarly with controlled names
659 $DB->Query("SELECT ResourceId,ControlledNameId FROM ResourceNameInts "
660 ."WHERE ResourceId in "
661 ."(".implode(",", array_keys($Chunk)).")");
662 foreach ($DB->FetchRows() as $Row)
663 {
664 $SearchNames[ $Row["ControlledNameId"] ] []= $Row["ResourceId"];
665 }
666 }
667 }
668
669 # generate a map of FieldId -> Field Names for all of the generated facets:
670 $SuggestionsById = array();
671
672 # pull relevant Classification names out of the DB
673 if (count($SearchClasses)>0)
674 {
675 foreach (array_chunk($SearchClasses, 1000, TRUE) as $Chunk)
676 {
677 $DB->Query("SELECT FieldId,ClassificationId,ClassificationName FROM Classifications "
678 ."WHERE ClassificationId IN (".implode(",", array_keys($Chunk)).")");
679 foreach ($DB->FetchRows() as $Row)
680 {
681 $SuggestionsById[$Row["FieldId"]] []=
682 array("Id" => $Row["ClassificationId"],
683 "Name" => $Row["ClassificationName"],
684 "Count" => count( $SearchClasses[ $Row["ClassificationId"] ] ) );
685 }
686 }
687 }
688
689 # pull relevant ControlledNames out of the DB
690 if (count($SearchNames)>0)
691 {
692 foreach (array_chunk($SearchNames, 1000, TRUE) as $Chunk)
693 {
694 $DB->Query("SELECT FieldId,ControlledNameId,ControlledName FROM ControlledNames "
695 ."WHERE ControlledNameId IN (".implode(",", array_keys($SearchNames)).")");
696 foreach ($DB->FetchRows() as $Row)
697 {
698 $SuggestionsById[$Row["FieldId"]] []=
699 array("Id" => $Row["ControlledNameId"],
700 "Name" => $Row["ControlledName"],
701 "Count" => count( $SearchNames[ $Row["ControlledNameId"] ] ) );
702 }
703 }
704 }
705
706 # translate the suggestions that we have in terms of the
707 # FieldIds to suggestions in terms of the field names
708 $SuggestionsByFieldName = array();
709
710 # if we have suggestions to offer
711 if (count($SuggestionsById)>0)
712 {
713 $Schema = new MetadataSchema();
714
715 # gill in an array that maps FieldNames to search links
716 # which would be appropriate for that field
717 foreach ($SuggestionsById as $FieldId => $FieldValues)
718 {
719 $ThisField = $Schema->GetField($FieldId);
720
721 # bail on fields that didn't exist
722 # and on fields that the current user cannot view, and on fields that are disabled
723 # for advanced searching:
724 if (is_object($ThisField) &&
725 $ThisField->Status() == MetadataSchema::MDFSTAT_OK &&
726 $ThisField->IncludeInFacetedSearch() &&
727 $ThisField->Enabled() &&
728 $User->HasPriv($ThisField->ViewingPrivileges()))
729 {
730 $SuggestionsByFieldName[ $ThisField->Name() ] = array();
731
732 foreach ($FieldValues as $Value)
733 $SuggestionsByFieldName [ $ThisField->Name() ] [$Value["Id"]] =
734 array("Name" => $Value["Name"], "Count" => $Value["Count"] );
735 }
736 }
737 }
738
739 ksort($SuggestionsByFieldName);
740
741 return $SuggestionsByFieldName;
742 }
743
744 private $Schema;
745
746 # functions for backward compatability w/ old SPT code
747 function UpdateForResource($ItemId) { $this->UpdateForItem($ItemId); }
748 }
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:857
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
ApplicationFramework\PRIORITY_LOW
const PRIORITY_LOW
Lower priority.
Definition: ApplicationFramework.php:1724
SPTSearchEngine\SPTSearchEngine
SPTSearchEngine()
Definition: SPTSearchEngine.php:12
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:747
MetadataSchema\MDFSTAT_OK
const MDFSTAT_OK
Definition: MetadataSchema.php:42
MetadataSchema\MDFTYPE_NUMBER
const MDFTYPE_NUMBER
Definition: MetadataSchema.php:22
SearchEngine\SearchEngine
SearchEngine($ItemTableName, $ItemIdFieldName)
Object constructor.
Definition: SearchEngine.php:38
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: OAIClient.php:39
SPTSearchEngine\RunUpdateForItem
static RunUpdateForItem($ItemId)
Definition: SPTSearchEngine.php:616
MetadataSchema\MDFTYPE_PARAGRAPH
const MDFTYPE_PARAGRAPH
Definition: MetadataSchema.php:21
SPTSearchEngine\SearchFieldsForComparisonMatches
SearchFieldsForComparisonMatches($FieldNames, $Operators, $Values)
Definition: SPTSearchEngine.php:240
MetadataSchema\MDFTYPE_DATE
const MDFTYPE_DATE
Definition: MetadataSchema.php:23
SearchEngine\DMsg
DMsg($Level, $Msg)
Definition: SearchEngine.php:2099
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:634
MetadataSchema\MDFTYPE_TEXT
const MDFTYPE_TEXT
Definition: MetadataSchema.php:20
SPTSearchEngine\GetItemIdsSortedByField
static GetItemIdsSortedByField($FieldName, $SortDescending)
Definition: SPTSearchEngine.php:599
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:359
SearchEngine\DebugLevel
DebugLevel($NewValue)
Set debug output level.
Definition: SearchEngine.php:97
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
SearchEngine\UpdateForItem
UpdateForItem($ItemId)
Update search database for the specified item.
Definition: SearchEngine.php:450
SPTSearchEngine\QueueUpdateForItem
static QueueUpdateForItem($ItemId, $TaskPriority=ApplicationFramework::PRIORITY_LOW)
Definition: SPTSearchEngine.php:605