CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

SearchParameterSet.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: SearchParameterSet.php
4 #
5 # Part of the ScoutLib application support library
6 # Copyright 2015-2016 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu
8 #
9
13 class SearchParameterSet
14 {
15
16 # ---- SETUP / CONFIGURATION ---------------------------------------------
17 /*@(*/
18
26 public function __construct($Data = NULL)
27 {
28 # if set data supplied
29 if ($Data !== NULL)
30 {
31 # set internal values from data
32 $this->LoadFromData($Data);
33 }
34 }
35
40 public function __clone()
41 {
42 foreach ($this->Subgroups as &$Group)
43 {
44 $Group = clone $Group;
45 }
46 }
47
55 public static function SetCanonicalFieldFunction($Func)
56 {
57 if (is_callable($Func))
58 {
59 self::$CanonicalFieldFunction = $Func;
60 }
61 else
62 {
63 throw new InvalidArgumentException("Invalid function supplied.");
64 }
65 }
66
74 public static function SetPrintableFieldFunction($Func)
75 {
76 if (is_callable($Func))
77 {
78 self::$PrintableFieldFunction = $Func;
79 }
80 else
81 {
82 throw new InvalidArgumentException("Invalid function supplied.");
83 }
84 }
85
91 /*@)*/
92 # ---- SET CONSTRUCTION ---------------------------------------------------
93 /*@(*/
94
105 public function AddParameter($SearchStrings, $Field = NULL)
106 {
107 # normalize field value if supplied
108 $Field = self::NormalizeField($Field);
109
110 # make sure search strings are an array
111 if (!is_array($SearchStrings))
112 { $SearchStrings = array($SearchStrings); }
113
114 # for each search string
115 foreach ($SearchStrings as $String)
116 {
117 # if field specified
118 if ($Field !== NULL)
119 {
120 # add strings to search values for field
121 $this->SearchStrings[$Field][] = $String;
122 }
123 else
124 {
125 # add strings to keyword search values
126 $this->KeywordSearchStrings[] = $String;
127 }
128 }
129 }
130
139 public function RemoveParameter($SearchStrings, $Field = NULL)
140 {
141 # normalize field value if supplied
142 $Field = self::NormalizeField($Field);
143
144 # if search strings specified
145 if ($SearchStrings != NULL)
146 {
147 # make sure search strings are an array
148 if (!is_array($SearchStrings))
149 { $SearchStrings = array($SearchStrings); }
150
151 # for each search string
152 foreach ($SearchStrings as $String)
153 {
154 # if field specified
155 if ($Field !== NULL)
156 {
157 # if there are search parameters for this field
158 if (isset($this->SearchStrings[$Field]))
159 {
160 # remove any matching search parameters
161 $NewSearchStrings = array();
162 foreach ($this->SearchStrings[$Field] as $Value)
163 {
164 if ($Value != $String)
165 {
166 $NewSearchStrings[] = $Value;
167 }
168 }
169 if (count($NewSearchStrings))
170 {
171 $this->SearchStrings[$Field] = $NewSearchStrings;
172 }
173 else
174 {
175 unset($this->SearchStrings[$Field]);
176 }
177 }
178 }
179 else
180 {
181 # remove any matching keyword search parameters
182 $NewSearchStrings = array();
183 foreach ($this->KeywordSearchStrings as $Value)
184 {
185 if ($Value != $String)
186 {
187 $NewSearchStrings[] = $Value;
188 }
189 }
190 $this->KeywordSearchStrings = $NewSearchStrings;
191 }
192 }
193 }
194 else
195 {
196 # if field specified
197 if ($Field !== NULL)
198 {
199 # clear any search strings for this field
200 if (isset($this->SearchStrings[$Field]))
201 {
202 unset($this->SearchStrings[$Field]);
203 }
204 }
205 else
206 {
207 # clear all keyword search parameters
208 $this->KeywordSearchStrings = array();
209 }
210 }
211
212 # for each parameter subgroup
213 $NewSubgroups = array();
214 foreach ($this->Subgroups as $Group)
215 {
216 # remove parameter from subgroup
217 $Group->RemoveParameter($SearchStrings, $Field);
218
219 # if the subgroup is not empty
220 if ($Group->ParameterCount())
221 {
222 # keep subgroup
223 $NewSubgroups[] = $Group;
224 }
225 }
226 $this->Subgroups = $NewSubgroups;
227 }
228
236 public function Logic($NewValue = NULL)
237 {
238 # if new value supplied
239 if ($NewValue !== NULL)
240 {
241 # normalize value
242 $NormValue = ($NewValue == SearchEngine::LOGIC_OR)
243 ? "OR"
244 : (($NewValue == SearchEngine::LOGIC_AND)
245 ? "AND"
246 : strtoupper($NewValue));
247
248 # error out if value appears invalid
249 if (($NormValue !== "AND") && ($NormValue !== "OR"))
250 {
251 throw new InvalidArgumentException("New logic setting"
252 ." is invalid (".$NewValue.").");
253 }
254
255 # save new setting
256 $this->Logic = $NormValue;
257 }
258
259 # return current logic setting to caller
260 return $this->Logic;
261 }
262
271 public function ItemTypes($ItemTypes = NULL)
272 {
273 if ($ItemTypes !== NULL)
274 {
275 if ($ItemTypes === FALSE)
276 {
277 $this->ItemTypes = FALSE;
278 }
279 else
280 {
281 if (!is_array($ItemTypes))
282 {
283 $ItemTypes = array($ItemTypes);
284 }
285 $this->ItemTypes = $ItemTypes;
286 }
287 }
288 return $this->ItemTypes;
289 }
290
300 public function SortBy($NewValue = NULL)
301 {
302 if ($NewValue !== NULL)
303 {
304 $this->SortBy = $NewValue;
305 }
306 return $this->SortBy;
307 }
308
320 public function SortDescending($NewValue = NULL)
321 {
322 if ($NewValue !== NULL)
323 {
324 $this->SortDescending = $NewValue;
325 }
326 return $this->SortDescending;
327 }
328
333 public function AddSet(SearchParameterSet $Set)
334 {
335 if ($Set->ParameterCount())
336 {
337 $this->Subgroups[] = $Set;
338 }
339 }
340
341
342 /*@)*/
343 # ---- DATA RETRIEVAL -----------------------------------------------------
344 /*@(*/
345
350 public function ParameterCount()
351 {
352 $Count = count($this->KeywordSearchStrings);
353 foreach ($this->SearchStrings as $Field => $Strings)
354 {
355 $Count += count($Strings);
356 }
357 foreach ($this->Subgroups as $Group)
358 {
359 $Count += $Group->ParameterCount();
360 }
361 return $Count;
362 }
363
371 public function GetSearchStrings($IncludeSubgroups = FALSE)
372 {
373 $SearchStrings = $this->SearchStrings;
374 if ($IncludeSubgroups)
375 {
376 foreach ($this->Subgroups as $Group)
377 {
378 $SubStrings = $Group->GetSearchStrings(TRUE);
379 foreach ($SubStrings as $Field => $Strings)
380 {
381 if (isset($SearchStrings[$Field]))
382 {
383 $SearchStrings[$Field] = array_merge(
384 $SearchStrings[$Field], $Strings);
385 }
386 else
387 {
388 $SearchStrings[$Field] = $Strings;
389 }
390 }
391 }
392 }
393 return $SearchStrings;
394 }
395
404 public function GetSearchStringsForField($Field, $IncludeSubgroups = TRUE)
405 {
406 # normalize field value
407 $Field = self::NormalizeField($Field);
408
409 # start with our string values
410 $Strings = isset($this->SearchStrings[$Field])
411 ? $this->SearchStrings[$Field] : array();
412
413 # if strings from subgroups should also be returned
414 if ($IncludeSubgroups)
415 {
416 # for each subgroup
417 foreach ($this->Subgroups as $Group)
418 {
419 # add any strings from that subgroup
420 $Strings = array_merge($Strings,
421 $Group->GetSearchStringsForField($Field));
422 }
423 }
424
425 # return all strings found to caller
426 return $Strings;
427 }
428
433 public function GetKeywordSearchStrings()
434 {
435 return $this->KeywordSearchStrings;
436 }
437
442 public function GetSubgroups()
443 {
444 return $this->Subgroups;
445 }
446
451 public function GetFields()
452 {
453 # retrieve our fields
454 $Fields = array_keys($this->SearchStrings);
455
456 # for each subgroup
457 foreach ($this->Subgroups as $Group)
458 {
459 # add fields from subgroup to the list
460 $Fields = array_merge($Fields, $Group->GetFields());
461 }
462
463 # filter out duplicates and sort to ensure consistency
464 $Fields = array_unique($Fields);
465 sort($Fields);
466
467 # return list of field identifiers to caller
468 return $Fields;
469 }
470
471
472 /*@)*/
473 # ---- DATA TRANSLATION ---------------------------------------------------
474 /*@(*/
475
486 public function Data($NewValue = NULL)
487 {
488 # if new data supplied
489 if ($NewValue !== NULL)
490 {
491 # unpack set data and load
492 $this->LoadFromData($NewValue);
493 }
494
495 # serialize current data and return to caller
496 $Data = array();
497 if ($this->Logic !== "AND") { $Data["Logic"] = $this->Logic; }
498 if (count($this->SearchStrings))
499 { $Data["SearchStrings"] = $this->SearchStrings; }
500 if (count($this->KeywordSearchStrings))
501 {
502 $Data["KeywordSearchStrings"] = $this->KeywordSearchStrings;
503 }
504 if (count($this->Subgroups))
505 {
506 foreach ($this->Subgroups as $Subgroup)
507 {
508 $Data["Subgroups"][] = $Subgroup->Data();
509 }
510 }
511 return serialize($Data);
512 }
513
520 public function UrlParameters($NewValue = NULL)
521 {
522 # if new value supplied
523 if ($NewValue !== NULL)
524 {
525 # set new parameters
526 $this->SetFromUrlParameters($NewValue);
527 }
528
529 # get existing search parameters as URL parameters
530 $Params = $this->GetAsUrlParameters();
531
532 # sort parameters by parameter name to normalize result
533 ksort($Params);
534
535 # return parameters to caller
536 return $Params;
537 }
538
545 public function UrlParameterString($NewValue = NULL)
546 {
547 # get/set parameters
548 $Params = $this->UrlParameters($NewValue);
549
550 # combine values into string
551 $ParamString = "";
552 $Separator = "";
553 foreach ($Params as $Index => $Value)
554 {
555 $ParamString .= $Separator.$Index."=".urlencode($Value);
556 $Separator = "&";
557 }
558
559 # return string to caller
560 return $ParamString;
561 }
562
574 public function TextDescription($IncludeHtml = TRUE, $StartWithBreak = TRUE,
575 $TruncateLongWordsTo = 0, $Indent = "")
576 {
577 # define list of phrases used to represent logical operators
578 $OperatorPhrases = array(
579 "=" => "is",
580 "==" => "is",
581 ">" => "is greater than",
582 "<" => "is less than",
583 ">=" => "is at least",
584 "<=" => "is no more than",
585 "!" => "is not",
586 "!=" => "is not",
587 "^" => "begins with",
588 "$" => "ends with",
589 "@" => "was last modified on or after",
590 "@>" => "was last modified after",
591 "@>=" => "was last modified on or after",
592 "@<" => "was last modified before",
593 "@<=" => "was last modified on or before",
594 );
595 $AgoOperatorPhrases = array(
596 "@>" => "was last modified more than",
597 "@>=" => "was last modified at least or more than",
598 "@<" => "was last modified less than",
599 "@<=" => "was last modified at most or less than",
600 );
601
602 # set characters used to indicate literal strings
603 $LiteralStart = $IncludeHtml ? "<i>" : "\"";
604 $LiteralEnd = $IncludeHtml ? "</i>" : "\"";
605 $LiteralBreak = $IncludeHtml ? "<br>\n" : "\n";
606 $Indent .= $IncludeHtml ? "&nbsp;&nbsp;&nbsp;&nbsp;" : " ";
607
608 # for each keyword search string
609 $Descriptions = array();
610 foreach ($this->KeywordSearchStrings as $SearchString)
611 {
612 # escape search string if appropriate
613 if ($IncludeHtml)
614 {
615 $SearchString = defaulthtmlentities($SearchString);
616 }
617
618 # add string to list of descriptions
619 $Descriptions[] = $LiteralStart.$SearchString.$LiteralEnd;
620 }
621
622 # for each field with search strings
623 foreach ($this->SearchStrings as $FieldId => $SearchStrings)
624 {
625 # retrieve field name
626 $FieldName = call_user_func(self::$PrintableFieldFunction, $FieldId);
627
628 # for each search string
629 foreach ($SearchStrings as $SearchString)
630 {
631 # extract operator from search string
632 $MatchResult = preg_match('/^([=><!^$@]+)(.+)/',
633 $SearchString, $Matches);
634
635 # determine operator phrase
636 if (($MatchResult == 1) && isset($OperatorPhrases[$Matches[1]]))
637 {
638 if (isset($AgoOperatorPhrases[$Matches[1]])
639 && strstr($SearchString, "ago"))
640 {
641 $OpPhrase = $AgoOperatorPhrases[$Matches[1]];
642 }
643 else
644 {
645 $OpPhrase = $OperatorPhrases[$Matches[1]];
646 }
647 $SearchString = $Matches[2];
648 }
649 else
650 {
651 $OpPhrase = "contains";
652 }
653
654 # escape field name and search string if appropriate
655 if ($IncludeHtml)
656 {
657 $FieldName = defaulthtmlentities($FieldName);
658 $SearchString = defaulthtmlentities($SearchString);
659 }
660
661 # assemble field and operator and value into description
662 $Descriptions[] = $FieldName." ".$OpPhrase." "
663 .$LiteralStart.$SearchString.$LiteralEnd;
664 }
665 }
666
667 # for each subgroup
668 foreach ($this->Subgroups as $Subgroup)
669 {
670 # retrieve description for subgroup
671 if ($Subgroup->ParameterCount() == 1)
672 {
673 $Descriptions[] = $Subgroup->TextDescription($IncludeHtml,
674 $StartWithBreak, $TruncateLongWordsTo, $Indent);
675 }
676 elseif ($Subgroup->ParameterCount() > 1)
677 {
678 $Descriptions[] = "(".$Subgroup->TextDescription($IncludeHtml,
679 $StartWithBreak, $TruncateLongWordsTo, $Indent).")";
680 }
681 }
682
683 # join descriptions with appropriate conjunction
684 $Descrip = join($LiteralBreak.$Indent." ".strtolower($this->Logic)." ",
685 $Descriptions);
686
687 # if caller requested that long words be truncated
688 if ($TruncateLongWordsTo > 4)
689 {
690 # break description into words
691 $Words = explode(" ", $Descrip);
692
693 # for each word
694 $NewDescrip = "";
695 foreach ($Words as $Word)
696 {
697 # if word is longer than specified length
698 if (strlen(strip_tags($Word)) > $TruncateLongWordsTo)
699 {
700 # truncate word and add ellipsis
701 $Word = StdLib::NeatlyTruncateString($Word, $TruncateLongWordsTo - 3);
702 }
703
704 # add word to new description
705 $NewDescrip .= " ".$Word;
706 }
707
708 # set description to new description
709 $Descrip = $NewDescrip;
710 }
711
712 if (isset(self::$TextDescriptionFilterFunction))
713 {
714 $Descrip = call_user_func_array(
715 self::$TextDescriptionFilterFunction,
716 [$Descrip]);
717 }
718
719 # return description to caller
720 return trim($Descrip);
721 }
722
723
724 /*@)*/
725 # ---- UTILITY METHODS ----------------------------------------------------
726 /*@(*/
727
733 public function ReplaceSearchString($Pattern, $Replacement)
734 {
735 # modify our fielded search strings
736 foreach ($this->SearchStrings as $Field => $Strings)
737 {
738 $this->SearchStrings[$Field] =
739 preg_replace($Pattern, $Replacement, $Strings);
740 }
741
742 # modify our keyword search strings
743 if (count($this->KeywordSearchStrings))
744 {
745 $this->KeywordSearchStrings =
746 preg_replace($Pattern, $Replacement, $this->KeywordSearchStrings);
747 }
748
749 # modify any subgroups
750 foreach ($this->Subgroups as $Group)
751 {
752 $Group->ReplaceSearchString($Pattern, $Replacement);
753 }
754 }
755
756
757 /*@)*/
758 # ---- BACKWARD COMPATIBILITY ---------------------------------------------
759 /*@(*/
760
769 public function GetAsLegacyArray()
770 {
771 $Legacy = array();
772
773 $Group = $this->ConvertToLegacyGroup();
774 if (count($Group))
775 {
776 $Legacy["MAIN"] = $Group;
777 }
778
779 # for each subgroup
780 foreach ($this->Subgroups as $Subgroup)
781 {
782 # skip empty search groups
783 if (count($Subgroup->SearchStrings)==0)
784 {
785 continue;
786 }
787
788 $SubLegacy = $Subgroup->ConvertToLegacyGroup();
789
790 # give an index based on the FieldId of the first
791 # element in the SearchStrings
792 $FieldId = call_user_func(
793 self::$CanonicalFieldFunction,
794 current(array_keys($SubLegacy["SearchStrings"])) );
795
796 # add groups from legacy array to our array
797 if (!isset($Legacy[$FieldId]))
798 {
799 $Legacy[$FieldId] = $SubLegacy;
800 }
801 else
802 {
803 $Num = count($Legacy[$FieldId]);
804 $Legacy[$FieldId."-".$Num] = $SubLegacy;
805 }
806
807 if (count($Subgroup->Subgroups))
808 {
809 throw new Exception(
810 "Attempt to convert SearchParameterSet containing nested subgroups "
811 ."to legacy format");
812 }
813 }
814
815 # return array to caller
816 return $Legacy;
817 }
818
823 public function SetFromLegacyArray($SearchGroups)
824 {
825 # clear current settings
826 $this->KeywordSearchStrings = array();
827 $this->SearchStrings = array();
828 $this->Subgroups = array();
829
830 # iterate over legacy search groups
831 foreach ($SearchGroups as $GroupId => $SearchGroup)
832 {
833 if ($GroupId == "MAIN")
834 {
835 # add terms from the main search group to ourself
836 $this->LoadFromLegacyGroup($SearchGroup);
837 }
838 else
839 {
840 # create subgroups for other groups
841 $Subgroup = new SearchParameterSet();
842 $Subgroup->LoadFromLegacyGroup($SearchGroup);
843
844 # add any non-empty groups
845 if ($Subgroup->ParameterCount())
846 {
847 $this->AddSet($Subgroup);
848 }
849 }
850 }
851 }
852
857 public function SetFromLegacyUrl($ParameterString)
858 {
859 # clear current settings
860 $this->KeywordSearchStrings = array();
861 $this->SearchStrings = array();
862 $this->Subgroups = array();
863
864 # extact array of parameters from passed string
865 $GetVars = ParseQueryString($ParameterString);
866
867 # iterate over the provided parameters
868 foreach ($GetVars as $Key => $Val)
869 {
870 # if this param gives search information
871 if (preg_match("/^([FGH])(K|[0-9]+)$/", $Key, $Matches))
872 {
873 # extract what kind of search it was which field
874 $Type = $Matches[1];
875 $FieldId = $Matches[2];
876
877 # for 'contains' searches
878 if ($Type == "F")
879 {
880 # add this to our search strings
881 $this->AddParameter( $Val,
882 ($FieldId == "K" ? NULL : $FieldId) );
883 }
884 else
885 {
886 # otherwise, create a subgroup for this parameter
887 $Subgroup = new SearchParameterSet();
888
889 # set logic based on the search type
890 $Subgroup->Logic($Type=="H" ? "AND" : "OR");
891
892 # extract the values and add them to a subgroup
893 $Values = explode("-", $Val);
894 $Subgroup->AddParameter(
895 self::TranslateLegacySearchValues($FieldId, $Values),
896 $FieldId );
897
898 # if subgroup was non-empty, slurp it up
899 if ($Subgroup->ParameterCount())
900 {
901 $this->AddSet($Subgroup);
902 }
903 }
904 }
905 }
906 }
907
913 public static function IsLegacyUrl($ParameterString)
914 {
915 $QueryVars = ParseQueryString($ParameterString);
916
917 return (array_key_exists("Q", $QueryVars) &&
918 $QueryVars["Q"] == "Y") ? TRUE : FALSE ;
919 }
920
926 public static function ConvertLegacyUrl($ParameterString)
927 {
928 $SearchParams = new SearchParameterSet();
929 $SearchParams->SetFromLegacyUrl($ParameterString);
930
931 return $SearchParams->UrlParameterString();
932 }
933
940 public static function SetLegacyUrlTranslationFunction($Func)
941 {
942 if (is_callable($Func))
943 {
944 self::$LegacyUrlTranslationFunction = $Func;
945 }
946 else
947 {
948 throw new InvalidArgumentException("Invalid function supplied.");
949 }
950 }
951
959 public static function SetTextDescriptionFilterFunction($Func)
960 {
961 if (is_callable($Func))
962 {
963 self::$TextDescriptionFilterFunction = $Func;
964 }
965 else
966 {
967 throw new InvalidArgumentException("Invalid function supplied.");
968 }
969 }
970
977 public static function TranslateLegacySearchValues($Field, $Values)
978 {
979 if (($Field !== NULL) && isset(self::$LegacyUrlTranslationFunction))
980 {
981 $Values = call_user_func(self::$LegacyUrlTranslationFunction,
982 $Field, $Values);
983 }
984 return $Values;
985 }
986
987 /*@)*/
988 # ---- PRIVATE INTERFACE -------------------------------------------------
989
990 private $KeywordSearchStrings = array();
991 private $ItemTypes = FALSE;
992 private $Logic = self::DEFAULT_LOGIC;
993 private $SearchStrings = array();
994 private $SortBy = FALSE;
995 private $SortDescending = TRUE;
996 private $Subgroups = array();
997
998 static private $CanonicalFieldFunction;
999 static private $PrintableFieldFunction;
1000 static private $LegacyUrlTranslationFunction;
1001 static private $TextDescriptionFilterFunction;
1002 static private $UrlParameterPrefix = "F";
1003
1004 const DEFAULT_LOGIC = "AND";
1005 const URL_KEYWORDFREE_RANGE = "A-JL-Z";
1006 const URL_KEYWORD_INDICATOR = "K";
1007 const URL_LOGIC_INDICATOR = "00";
1008
1014 private function LoadFromData($Serialized)
1015 {
1016 # unpack new data
1017 $Data = unserialize($Serialized);
1018 if (!is_array($Data))
1019 {
1020 throw new InvalidArgumentException("Incoming set data"
1021 ." appears invalid.");
1022 }
1023
1024 # load logic
1025 $this->Logic = isset($Data["Logic"]) ? $Data["Logic"] : "AND";
1026
1027 # load search strings
1028 $this->SearchStrings = isset($Data["SearchStrings"])
1029 ? $Data["SearchStrings"] : array();
1030 $this->KeywordSearchStrings = isset($Data["KeywordSearchStrings"])
1031 ? $Data["KeywordSearchStrings"] : array();
1032
1033 # load any subgroups
1034 $this->Subgroups = array();
1035 if (isset($Data["Subgroups"]))
1036 {
1037 foreach ($Data["Subgroups"] as $SubgroupData)
1038 {
1039 $this->Subgroups[] = new SearchParameterSet($SubgroupData);
1040 }
1041 }
1042 }
1043
1048 private function ConvertToLegacyGroup()
1049 {
1050 $Group = array();
1051 # for each set of search strings
1052 foreach ($this->SearchStrings as $Field => $Strings)
1053 {
1054 # get text name of field
1055 $FieldName = call_user_func(self::$PrintableFieldFunction, $Field);
1056
1057 # add set to group
1058 $Group["SearchStrings"][$FieldName] = $Strings;
1059 }
1060
1061 # for each keyword search string
1062 foreach ($this->KeywordSearchStrings as $String)
1063 {
1064 # add string to keyword entry in group
1065 $Group["SearchStrings"]["XXXKeywordXXX"][] = $String;
1066 }
1067
1068 # if we had any search terms
1069 if (count($Group))
1070 {
1071 # smash single-value arrays to a scalar
1072 foreach ($Group["SearchStrings"] as &$Tgt)
1073 {
1074 if (count($Tgt) == 1)
1075 {
1076 $Tgt = current($Tgt);
1077 }
1078 }
1079
1080 # set logic for search group
1081 $Group["Logic"] = ($this->Logic == "OR")
1082 ? SearchEngine::LOGIC_OR : SearchEngine::LOGIC_AND;
1083 }
1084
1085 return $Group;
1086 }
1087
1092 private function LoadFromLegacyGroup($Group)
1093 {
1094 # set logic appropriately
1095 $this->Logic(
1096 ($Group["Logic"] == SearchEngine::LOGIC_OR) ?
1097 "OR" : "AND" );
1098
1099 # if this group had no search strings, we're done
1100 if (!isset($Group["SearchStrings"]))
1101 {
1102 return;
1103 }
1104
1105 # otherwise, load the search strings
1106 foreach ($Group["SearchStrings"] as $Field => $Params)
1107 {
1108 # skip empty groups
1109 if (count($Params)==0)
1110 {
1111 continue;
1112 }
1113
1114 $this->AddParameter( $Params,
1115 ($Field == "XXXKeywordXXX" ? NULL : $Field) );
1116
1117 }
1118 }
1119
1125 private function GetAsUrlParameters($SetPrefix = "")
1126 {
1127 # for each search string group in set
1128 $Params = array();
1129 foreach ($this->SearchStrings as $FieldId => $Values)
1130 {
1131 # get numeric version of field ID if not already numeric
1132 if (!is_numeric($FieldId))
1133 {
1134 $FieldId = call_user_func(self::$CanonicalFieldFunction, $FieldId);
1135 }
1136
1137 # for each search string in group
1138 $ParamSuffix = "";
1139 foreach ($Values as $Value)
1140 {
1141 # check for too many search strings for this field
1142 if ($ParamSuffix == "Z")
1143 {
1144 throw new Exception("Maximum search parameter complexity"
1145 ." exceeded: more than 26 search parameters for"
1146 ." field ID ".$FieldId.".");
1147 }
1148
1149 # add search string to URL
1150 $Params[self::$UrlParameterPrefix.$SetPrefix
1151 .$FieldId.$ParamSuffix] = $Value;
1152 $ParamSuffix = ($ParamSuffix == "") ? "A"
1153 : chr(ord($ParamSuffix) + 1);
1154 }
1155 }
1156
1157 # for each keyword search string
1158 $ParamSuffix = "";
1159 foreach ($this->KeywordSearchStrings as $Value)
1160 {
1161 # check for too many keyword search strings
1162 if ($ParamSuffix == "Z")
1163 {
1164 throw new Exception("Maximum search parameter complexity"
1165 ." exceeded: more than 26 keyword search parameters.");
1166 }
1167
1168 # add search string to URL
1169 $Params[self::$UrlParameterPrefix.$SetPrefix
1170 .self::URL_KEYWORD_INDICATOR.$ParamSuffix] = $Value;
1171 $ParamSuffix = ($ParamSuffix == "") ? "A"
1172 : chr(ord($ParamSuffix) + 1);
1173 }
1174
1175 # add logic if not default
1176 if ($this->Logic != self::DEFAULT_LOGIC)
1177 {
1178 $Params[self::$UrlParameterPrefix.$SetPrefix
1179 .self::URL_LOGIC_INDICATOR] = $this->Logic;
1180 }
1181
1182 # for each search parameter subgroup
1183 $SetLetter = "A";
1184 foreach ($this->Subgroups as $Subgroup)
1185 {
1186 # check for too many subgroups
1187 if ($SetLetter == "Z")
1188 {
1189 throw new Exception("Maximum search parameter complexity"
1190 ." exceeded: more than 24 search parameter subgroups.");
1191 }
1192
1193 # retrieve URL string for subgroup and add it to URL
1194 $Params = array_merge($Params, $Subgroup->GetAsUrlParameters(
1195 $SetPrefix.$SetLetter));
1196
1197 # move to next set letter
1198 $SetLetter = ($SetLetter == chr(ord(self::URL_KEYWORD_INDICATOR) - 1))
1199 ? chr(ord(self::URL_KEYWORD_INDICATOR) + 1)
1200 : chr(ord($SetLetter) + 1);
1201 }
1202
1203 # return constructed URL parameter string to caller
1204 return $Params;
1205 }
1206
1213 private function SetFromUrlParameters($UrlParameters)
1214 {
1215 # if string was passed in
1216 if (is_string($UrlParameters))
1217 {
1218 # split string into parameter array
1219 $Params = explode("&", $UrlParameters);
1220
1221 # pare down parameter array to search parameter elements
1222 # and strip off search parameter prefix
1223 $NewUrlParameters = array();
1224 foreach ($Params as $Param)
1225 {
1226 if (strpos($Param, self::$UrlParameterPrefix) === 0)
1227 {
1228 list($Index, $Value) = explode("=", $Param);
1229 $NewUrlParameters[$Index] = urldecode($Value);
1230 }
1231 }
1232 $UrlParameters = $NewUrlParameters;
1233 }
1234
1235 # for each search parameter
1236 foreach ($UrlParameters as $ParamName => $SearchString)
1237 {
1238 # strip off standard search parameter prefix
1239 $ParamName = substr($ParamName, strlen(self::$UrlParameterPrefix));
1240
1241 # split parameter into component parts
1242 $SplitResult = preg_match("/^([".self::URL_KEYWORDFREE_RANGE."]*)"
1243 ."([0-9".self::URL_KEYWORD_INDICATOR."]+)([A-Z]*)$/",
1244 $ParamName, $Matches);
1245
1246 # if split was successful
1247 if ($SplitResult === 1)
1248 {
1249 # pull components from split pieces
1250 $SetPrefix = $Matches[1];
1251 $FieldId = $Matches[2];
1252 $ParamSuffix = $Matches[3];
1253
1254 # if set prefix indicates parameter is part of our set
1255 if ($SetPrefix == "")
1256 {
1257 switch ($FieldId)
1258 {
1259 case self::URL_LOGIC_INDICATOR:
1260 # set logic
1261 $this->Logic($SearchString);
1262 break;
1263
1264 case self::URL_KEYWORD_INDICATOR:
1265 # add string to keyword searches
1266 $this->KeywordSearchStrings[] = $SearchString;
1267 break;
1268
1269 default:
1270 # add string to searches for appropriate field
1271 $this->SearchStrings[$FieldId][] = $SearchString;
1272 break;
1273 }
1274 }
1275 else
1276 {
1277 # add parameter to array for subgroup
1278 $SubgroupIndex = $SetPrefix[0];
1279 $SubgroupPrefix = (strlen($SetPrefix) > 1)
1280 ? substr($SetPrefix, 1) : "";
1281 $SubgroupParamIndex = self::$UrlParameterPrefix
1282 .$SubgroupPrefix.$FieldId.$ParamSuffix;
1283 $SubgroupParameters[$SubgroupIndex][$SubgroupParamIndex]
1284 = $SearchString;
1285 }
1286 }
1287 }
1288
1289 # if subgroups were found
1290 if (isset($SubgroupParameters))
1291 {
1292 # for each identified subgroup
1293 foreach ($SubgroupParameters as $SubgroupIndex => $Parameters)
1294 {
1295 # create subgroup and set parameters
1296 $Subgroup = new SearchParameterSet();
1297 $Subgroup->SetFromUrlParameters($Parameters);
1298
1299 # add subgroup to our set
1300 $this->Subgroups[] = $Subgroup;
1301 }
1302 }
1303 }
1304
1310 private static function NormalizeField($Field)
1311 {
1312 if (($Field !== NULL) && isset(self::$CanonicalFieldFunction))
1313 {
1314 $Field = call_user_func(self::$CanonicalFieldFunction, $Field);
1315 }
1316 return $Field;
1317 }
1318 }
SearchParameterSet\TextDescription
TextDescription($IncludeHtml=TRUE, $StartWithBreak=TRUE, $TruncateLongWordsTo=0, $Indent="")
Get text description of search parameter set.
Definition: SearchParameterSet.php:574
SearchParameterSet\Data
Data($NewValue=NULL)
Get/set search parameter set data, in the form of an opaque string.
Definition: SearchParameterSet.php:486
SearchParameterSet\TranslateLegacySearchValues
static TranslateLegacySearchValues($Field, $Values)
Translate legacy search values to modern equivalents if possible.
Definition: SearchParameterSet.php:977
SearchParameterSet\SetFromLegacyArray
SetFromLegacyArray($SearchGroups)
Set search parameters from legacy array format.
Definition: SearchParameterSet.php:823
SearchParameterSet\SetCanonicalFieldFunction
static SetCanonicalFieldFunction($Func)
Register function used to retrieve a canonical value for a field.
Definition: SearchParameterSet.php:55
SearchParameterSet
Set of parameters used to perform a search.
Definition: SearchParameterSet.php:13
SearchParameterSet\AddSet
AddSet(SearchParameterSet $Set)
Add subgroup of search parameters to set.
Definition: SearchParameterSet.php:333
SearchParameterSet\UrlParameterString
UrlParameterString($NewValue=NULL)
Get/set search parameter set, in the form of an URL parameter string.
Definition: SearchParameterSet.php:545
SearchParameterSet\UrlParameters
UrlParameters($NewValue=NULL)
Get/set search parameter set, in the form of URL parameters.
Definition: SearchParameterSet.php:520
SearchParameterSet\URL_KEYWORD_INDICATOR
const URL_KEYWORD_INDICATOR
Definition: SearchParameterSet.php:1006
SearchParameterSet\URL_KEYWORDFREE_RANGE
const URL_KEYWORDFREE_RANGE
Definition: SearchParameterSet.php:1005
SearchParameterSet\Logic
Logic($NewValue=NULL)
Get/set logic for set.
Definition: SearchParameterSet.php:236
SearchParameterSet\GetFields
GetFields()
Get fields used in search parameters (including subgroups).
Definition: SearchParameterSet.php:451
SearchParameterSet\SetLegacyUrlTranslationFunction
static SetLegacyUrlTranslationFunction($Func)
Register function used to converrt values from the format used in a Legacy URL string to the modern v...
Definition: SearchParameterSet.php:940
SearchParameterSet\ItemTypes
ItemTypes($ItemTypes=NULL)
Get/set allowed item types.
Definition: SearchParameterSet.php:271
SearchParameterSet\GetSearchStringsForField
GetSearchStringsForField($Field, $IncludeSubgroups=TRUE)
Get search strings for specified field.
Definition: SearchParameterSet.php:404
SearchEngine\LOGIC_OR
const LOGIC_OR
Definition: SearchEngine.php:20
SearchParameterSet\SetPrintableFieldFunction
static SetPrintableFieldFunction($Func)
Register function used to retrieve a printable value for a field.
Definition: SearchParameterSet.php:74
SearchParameterSet\SetFromLegacyUrl
SetFromLegacyUrl($ParameterString)
Set search parameters from legacy URL string.
Definition: SearchParameterSet.php:857
SearchEngine\LOGIC_AND
const LOGIC_AND
Definition: SearchEngine.php:19
PHP
PHP
Definition: RSSClient--Test.php:12
SearchParameterSet\__clone
__clone()
Class clone handler, implemented so that clones will be deep copies rather than PHP5&#39;s default shallo...
Definition: SearchParameterSet.php:40
SearchParameterSet\AddParameter
AddParameter($SearchStrings, $Field=NULL)
Add search parameter to set.
Definition: SearchParameterSet.php:105
SearchParameterSet\ConvertLegacyUrl
static ConvertLegacyUrl($ParameterString)
Convert legacy URL to the current URL format.
Definition: SearchParameterSet.php:926
SearchParameterSet\GetAsLegacyArray
GetAsLegacyArray()
Retrieve search parameters in legacy array format.
Definition: SearchParameterSet.php:769
SearchParameterSet\GetSearchStrings
GetSearchStrings($IncludeSubgroups=FALSE)
Get search strings in set.
Definition: SearchParameterSet.php:371
StdLib\NeatlyTruncateString
static NeatlyTruncateString($String, $MaxLength, $BreakAnywhere=FALSE)
Attempt to truncate a string as neatly as possible with respect to word breaks, punctuation, and HTML tags.
Definition: StdLib.php:239
SearchParameterSet\__construct
__construct($Data=NULL)
Class constructor, used to create a new set or reload an existing set from previously-constructed dat...
Definition: SearchParameterSet.php:26
SearchParameterSet\RemoveParameter
RemoveParameter($SearchStrings, $Field=NULL)
Remove search parameter from set.
Definition: SearchParameterSet.php:139
SearchParameterSet\IsLegacyUrl
static IsLegacyUrl($ParameterString)
Determine if a URL uses legacy format.
Definition: SearchParameterSet.php:913
SearchParameterSet\GetKeywordSearchStrings
GetKeywordSearchStrings()
Get keyword search strings in set.
Definition: SearchParameterSet.php:433
SearchParameterSet\ReplaceSearchString
ReplaceSearchString($Pattern, $Replacement)
Modify all search strings with the specified regular expression.
Definition: SearchParameterSet.php:733
SearchParameterSet\SortBy
SortBy($NewValue=NULL)
Get/set field to sort results by.
Definition: SearchParameterSet.php:300
SearchParameterSet\DEFAULT_LOGIC
const DEFAULT_LOGIC
Definition: SearchParameterSet.php:1004
SearchParameterSet\SortDescending
SortDescending($NewValue=NULL)
Get/set whether to sort results will be sorted in descending (as opposed to ascending) order...
Definition: SearchParameterSet.php:320
SearchParameterSet\URL_LOGIC_INDICATOR
const URL_LOGIC_INDICATOR
Definition: SearchParameterSet.php:1007
SearchParameterSet\GetSubgroups
GetSubgroups()
Get parameter subgroups.
Definition: SearchParameterSet.php:442
SearchParameterSet\ParameterCount
ParameterCount()
Get number of search parameters in set, including those in subgroups.
Definition: SearchParameterSet.php:350
SearchParameterSet\SetTextDescriptionFilterFunction
static SetTextDescriptionFilterFunction($Func)
Register function used to filter text descriptions of searches prior to display.
Definition: SearchParameterSet.php:959