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