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 = FALSE)
272 {
273 if ($ItemTypes !== FALSE)
274 {
275 if (!is_array($ItemTypes))
276 {
277 $ItemTypes = array($ItemTypes);
278 }
279 $this->ItemTypes = $ItemTypes;
280 }
281 return $this->ItemTypes;
282 }
283
288 public function AddSet(SearchParameterSet $Set)
289 {
290 if ($Set->ParameterCount()==0)
291 {
292 throw new Exception("Attempt to add empty subgroup");
293 }
294
295 # add subgroup to privilege set
296 $this->Subgroups[] = $Set;
297 }
298
299
300 /*@)*/
301 # ---- DATA RETRIEVAL -----------------------------------------------------
302 /*@(*/
303
308 public function ParameterCount()
309 {
310 $Count = count($this->KeywordSearchStrings);
311 foreach ($this->SearchStrings as $Field => $Strings)
312 {
313 $Count += count($Strings);
314 }
315 foreach ($this->Subgroups as $Group)
316 {
317 $Count += $Group->ParameterCount();
318 }
319 return $Count;
320 }
321
329 public function GetSearchStrings($IncludeSubgroups = FALSE)
330 {
331 $SearchStrings = $this->SearchStrings;
332 if ($IncludeSubgroups)
333 {
334 foreach ($this->Subgroups as $Group)
335 {
336 $SubStrings = $Group->GetSearchStrings(TRUE);
337 foreach ($SubStrings as $Field => $Strings)
338 {
339 if (isset($SearchStrings[$Field]))
340 {
341 $SearchStrings[$Field] = array_merge(
342 $SearchStrings[$Field], $Strings);
343 }
344 else
345 {
346 $SearchStrings[$Field] = $Strings;
347 }
348 }
349 }
350 }
351 return $SearchStrings;
352 }
353
362 public function GetSearchStringsForField($Field, $IncludeSubgroups = TRUE)
363 {
364 # normalize field value
365 $Field = self::NormalizeField($Field);
366
367 # start with our string values
368 $Strings = isset($this->SearchStrings[$Field])
369 ? $this->SearchStrings[$Field] : array();
370
371 # if strings from subgroups should also be returned
372 if ($IncludeSubgroups)
373 {
374 # for each subgroup
375 foreach ($this->Subgroups as $Group)
376 {
377 # add any strings from that subgroup
378 $Strings = array_merge($Strings,
379 $Group->GetSearchStringsForField($Field));
380 }
381 }
382
383 # return all strings found to caller
384 return $Strings;
385 }
386
391 public function GetKeywordSearchStrings()
392 {
393 return $this->KeywordSearchStrings;
394 }
395
400 public function GetSubgroups()
401 {
402 return $this->Subgroups;
403 }
404
409 public function GetFields()
410 {
411 # retrieve our fields
412 $Fields = array_keys($this->SearchStrings);
413
414 # for each subgroup
415 foreach ($this->Subgroups as $Group)
416 {
417 # add fields from subgroup to the list
418 $Fields = array_merge($Fields, $Group->GetFields());
419 }
420
421 # filter out duplicates and sort to ensure consistency
422 $Fields = array_unique($Fields);
423 sort($Fields);
424
425 # return list of field identifiers to caller
426 return $Fields;
427 }
428
429
430 /*@)*/
431 # ---- DATA TRANSLATION ---------------------------------------------------
432 /*@(*/
433
444 public function Data($NewValue = NULL)
445 {
446 # if new data supplied
447 if ($NewValue !== NULL)
448 {
449 # unpack set data and load
450 $this->LoadFromData($NewValue);
451 }
452
453 # serialize current data and return to caller
454 $Data = array();
455 if ($this->Logic !== "AND") { $Data["Logic"] = $this->Logic; }
456 if (count($this->SearchStrings))
457 { $Data["SearchStrings"] = $this->SearchStrings; }
458 if (count($this->KeywordSearchStrings))
459 {
460 $Data["KeywordSearchStrings"] = $this->KeywordSearchStrings;
461 }
462 if (count($this->Subgroups))
463 {
464 foreach ($this->Subgroups as $Subgroup)
465 {
466 $Data["Subgroups"][] = $Subgroup->Data();
467 }
468 }
469 return serialize($Data);
470 }
471
478 public function UrlParameters($NewValue = NULL)
479 {
480 # if new value supplied
481 if ($NewValue !== NULL)
482 {
483 # set new parameters
484 $this->SetFromUrlParameters($NewValue);
485 }
486
487 # get existing search parameters as URL parameters
488 $Params = $this->GetAsUrlParameters();
489
490 # sort parameters by parameter name to normalize result
491 ksort($Params);
492
493 # return parameters to caller
494 return $Params;
495 }
496
503 public function UrlParameterString($NewValue = NULL)
504 {
505 # get/set parameters
506 $Params = $this->UrlParameters($NewValue);
507
508 # combine values into string
509 $ParamString = "";
510 $Separator = "";
511 foreach ($Params as $Index => $Value)
512 {
513 $ParamString .= $Separator.$Index."=".urlencode($Value);
514 $Separator = "&";
515 }
516
517 # return string to caller
518 return $ParamString;
519 }
520
532 public function TextDescription($IncludeHtml = TRUE, $StartWithBreak = TRUE,
533 $TruncateLongWordsTo = 0, $Indent = "")
534 {
535 # define list of phrases used to represent logical operators
536 $OperatorPhrases = array(
537 "=" => "is",
538 "==" => "is",
539 ">" => "is greater than",
540 "<" => "is less than",
541 ">=" => "is at least",
542 "<=" => "is no more than",
543 "!" => "is not",
544 "!=" => "is not",
545 "^" => "begins with",
546 "$" => "ends with",
547 "@" => "was last modified on or after",
548 "@>" => "was last modified after",
549 "@>=" => "was last modified on or after",
550 "@<" => "was last modified before",
551 "@<=" => "was last modified on or before",
552 );
553 $AgoOperatorPhrases = array(
554 "@>" => "was last modified more than",
555 "@>=" => "was last modified at least or more than",
556 "@<" => "was last modified less than",
557 "@<=" => "was last modified at most or less than",
558 );
559
560 # set characters used to indicate literal strings
561 $LiteralStart = $IncludeHtml ? "<i>" : "\"";
562 $LiteralEnd = $IncludeHtml ? "</i>" : "\"";
563 $LiteralBreak = $IncludeHtml ? "<br>\n" : "\n";
564 $Indent .= $IncludeHtml ? "&nbsp;&nbsp;&nbsp;&nbsp;" : " ";
565
566 # for each keyword search string
567 $Descriptions = array();
568 foreach ($this->KeywordSearchStrings as $SearchString)
569 {
570 # escape search string if appropriate
571 if ($IncludeHtml)
572 {
573 $SearchString = defaulthtmlentities($SearchString);
574 }
575
576 # add string to list of descriptions
577 $Descriptions[] = $LiteralStart.$SearchString.$LiteralEnd;
578 }
579
580 # for each field with search strings
581 foreach ($this->SearchStrings as $FieldId => $SearchStrings)
582 {
583 # retrieve field name
584 $FieldName = call_user_func(self::$PrintableFieldFunction, $FieldId);
585
586 # for each search string
587 foreach ($SearchStrings as $SearchString)
588 {
589 # extract operator from search string
590 $MatchResult = preg_match('/^([=><!^$@]+)(.+)/',
591 $SearchString, $Matches);
592
593 # determine operator phrase
594 if (($MatchResult == 1) && isset($OperatorPhrases[$Matches[1]]))
595 {
596 if (isset($AgoOperatorPhrases[$Matches[1]])
597 && strstr($SearchString, "ago"))
598 {
599 $OpPhrase = $AgoOperatorPhrases[$Matches[1]];
600 }
601 else
602 {
603 $OpPhrase = $OperatorPhrases[$Matches[1]];
604 }
605 $SearchString = $Matches[2];
606 }
607 else
608 {
609 $OpPhrase = "contains";
610 }
611
612 # escape field name and search string if appropriate
613 if ($IncludeHtml)
614 {
615 $FieldName = defaulthtmlentities($FieldName);
616 $SearchString = defaulthtmlentities($SearchString);
617 }
618
619 # assemble field and operator and value into description
620 $Descriptions[] = $FieldName." ".$OpPhrase." "
621 .$LiteralStart.$SearchString.$LiteralEnd;
622 }
623 }
624
625 # for each subgroup
626 foreach ($this->Subgroups as $Subgroup)
627 {
628 # retrieve description for subgroup
629 if ($Subgroup->ParameterCount() == 1)
630 {
631 $Descriptions[] = $Subgroup->TextDescription($IncludeHtml,
632 $StartWithBreak, $TruncateLongWordsTo, $Indent);
633 }
634 elseif ($Subgroup->ParameterCount() > 1)
635 {
636 $Descriptions[] = "(".$Subgroup->TextDescription($IncludeHtml,
637 $StartWithBreak, $TruncateLongWordsTo, $Indent).")";
638 }
639 }
640
641 # join descriptions with appropriate conjunction
642 $Descrip = join($LiteralBreak.$Indent." ".strtolower($this->Logic)." ",
643 $Descriptions);
644
645 # if caller requested that long words be truncated
646 if ($TruncateLongWordsTo > 4)
647 {
648 # break description into words
649 $Words = explode(" ", $Descrip);
650
651 # for each word
652 $NewDescrip = "";
653 foreach ($Words as $Word)
654 {
655 # if word is longer than specified length
656 if (strlen(strip_tags($Word)) > $TruncateLongWordsTo)
657 {
658 # truncate word and add ellipsis
659 $Word = NeatlyTruncateString($Word, $TruncateLongWordsTo - 3);
660 }
661
662 # add word to new description
663 $NewDescrip .= " ".$Word;
664 }
665
666 # set description to new description
667 $Descrip = $NewDescrip;
668 }
669
670 # return description to caller
671 return $Descrip;
672 }
673
674
675 /*@)*/
676 # ---- UTILITY METHODS ----------------------------------------------------
677 /*@(*/
678
684 public function ReplaceSearchString($Pattern, $Replacement)
685 {
686 # modify our fielded search strings
687 foreach ($this->SearchStrings as $Field => $Strings)
688 {
689 $this->SearchStrings[$Field] =
690 preg_replace($Pattern, $Replacement, $Strings);
691 }
692
693 # modify our keyword search strings
694 if (count($this->KeywordSearchStrings))
695 {
696 $this->KeywordSearchStrings =
697 preg_replace($Pattern, $Replacement, $this->KeywordSearchStrings);
698 }
699
700 # modify any subgroups
701 foreach ($this->Subgroups as $Group)
702 {
703 $Group->ReplaceSearchString($Pattern, $Replacement);
704 }
705 }
706
707
708 /*@)*/
709 # ---- BACKWARD COMPATIBILITY ---------------------------------------------
710 /*@(*/
711
720 public function GetAsLegacyArray()
721 {
722 $Legacy = array();
723
724 $Group = $this->ConvertToLegacyGroup();
725 if (count($Group))
726 {
727 $Legacy["MAIN"] = $Group;
728 }
729
730 # for each subgroup
731 foreach ($this->Subgroups as $Subgroup)
732 {
733 # skip empty search groups
734 if (count($Subgroup->SearchStrings)==0)
735 {
736 continue;
737 }
738
739 $SubLegacy = $Subgroup->ConvertToLegacyGroup();
740
741 # give an index based on the FieldId of the first
742 # element in the SearchStrings
743 $FieldId = call_user_func(
744 self::$CanonicalFieldFunction,
745 current(array_keys($SubLegacy["SearchStrings"])) );
746
747 # add groups from legacy array to our array
748 if (!isset($Legacy[$FieldId]))
749 {
750 $Legacy[$FieldId] = $SubLegacy;
751 }
752 else
753 {
754 $Num = count($Legacy[$FieldId]);
755 $Legacy[$FieldId."-".$Num] = $SubLegacy;
756 }
757
758 if (count($Subgroup->Subgroups))
759 {
760 throw new Exception(
761 "Attempt to convert SearchParameterSet containing nested subgroups "
762 ."to legacy format");
763 }
764 }
765
766 # return array to caller
767 return $Legacy;
768 }
769
774 public function SetFromLegacyArray($SearchGroups)
775 {
776 # clear current settings
777 $this->KeywordSearchStrings = array();
778 $this->SearchStrings = array();
779 $this->Subgroups = array();
780
781 # iterate over legacy search groups
782 foreach ($SearchGroups as $GroupId => $SearchGroup)
783 {
784 if ($GroupId == "MAIN")
785 {
786 # add terms from the main search group to ourself
787 $this->LoadFromLegacyGroup($SearchGroup);
788 }
789 else
790 {
791 # create subgroups for other groups
792 $Subgroup = new SearchParameterSet();
793 $Subgroup->LoadFromLegacyGroup($SearchGroup);
794
795 # add any non-empty groups
796 if ($Subgroup->ParameterCount())
797 {
798 $this->AddSet($Subgroup);
799 }
800 }
801 }
802 }
803
808 public function SetFromLegacyUrl($ParameterString)
809 {
810 # clear current settings
811 $this->KeywordSearchStrings = array();
812 $this->SearchStrings = array();
813 $this->Subgroups = array();
814
815 # extact array of parameters from passed string
816 $GetVars = ParseQueryString($ParameterString);
817
818 # iterate over the provided parameters
819 foreach ($GetVars as $Key => $Val)
820 {
821 # if this param gives search information
822 if (preg_match("/^([FGH])(K|[0-9]+)$/", $Key, $Matches))
823 {
824 # extract what kind of search it was which field
825 $Type = $Matches[1];
826 $FieldId = $Matches[2];
827
828 # for 'contains' searches
829 if ($Type == "F")
830 {
831 # add this to our search strings
832 $this->AddParameter( $Val,
833 ($FieldId == "K" ? NULL : $FieldId) );
834 }
835 else
836 {
837 # otherwise, create a subgroup for this parameter
838 $Subgroup = new SearchParameterSet();
839
840 # set logic based on the search type
841 $Subgroup->Logic($Type=="H" ? "AND" : "OR");
842
843 # extract the values and add them to a subgroup
844 $Values = explode("-", $Val);
845 $Subgroup->AddParameter(
846 self::TranslateLegacySearchValues($FieldId, $Values),
847 $FieldId );
848
849 # if subgroup was non-empty, slurp it up
850 if ($Subgroup->ParameterCount())
851 {
852 $this->AddSet($Subgroup);
853 }
854 }
855 }
856 }
857 }
858
864 public static function IsLegacyUrl($ParameterString)
865 {
866 $QueryVars = ParseQueryString($ParameterString);
867
868 return (array_key_exists("Q", $QueryVars) &&
869 $QueryVars["Q"] == "Y") ? TRUE : FALSE ;
870 }
871
877 public static function ConvertLegacyUrl($ParameterString)
878 {
879 $SearchParams = new SearchParameterSet();
880 $SearchParams->SetFromLegacyUrl($ParameterString);
881
882 return $SearchParams->UrlParameterString();
883 }
884
891 public static function SetLegacyUrlTranslationFunction($Func)
892 {
893 if (is_callable($Func))
894 {
895 self::$LegacyUrlTranslationFunction = $Func;
896 }
897 else
898 {
899 throw new InvalidArgumentException("Invalid function supplied.");
900 }
901 }
902
909 public static function TranslateLegacySearchValues($Field, $Values)
910 {
911 if (($Field !== NULL) && isset(self::$LegacyUrlTranslationFunction))
912 {
913 $Values = call_user_func(self::$LegacyUrlTranslationFunction,
914 $Field, $Values);
915 }
916 return $Values;
917 }
918
919 /*@)*/
920 # ---- PRIVATE INTERFACE -------------------------------------------------
921
922 private $KeywordSearchStrings = array();
923 private $ItemTypes = NULL;
924 private $Logic = self::DEFAULT_LOGIC;
925 private $SearchStrings = array();
926 private $Subgroups = array();
927
928 static private $CanonicalFieldFunction;
929 static private $PrintableFieldFunction;
930 static private $LegacyUrlTranslationFunction;
931 static private $UrlParameterPrefix = "F";
932
933 const DEFAULT_LOGIC = "AND";
934 const URL_KEYWORDFREE_RANGE = "A-JL-Z";
935 const URL_KEYWORD_INDICATOR = "K";
936 const URL_LOGIC_INDICATOR = "00";
937
943 private function LoadFromData($Serialized)
944 {
945 # unpack new data
946 $Data = unserialize($Serialized);
947 if (!is_array($Data))
948 {
949 throw new InvalidArgumentException("Incoming set data"
950 ." appears invalid.");
951 }
952
953 # load logic
954 $this->Logic = isset($Data["Logic"]) ? $Data["Logic"] : "AND";
955
956 # load search strings
957 $this->SearchStrings = isset($Data["SearchStrings"])
958 ? $Data["SearchStrings"] : array();
959 $this->KeywordSearchStrings = isset($Data["KeywordSearchStrings"])
960 ? $Data["KeywordSearchStrings"] : array();
961
962 # load any subgroups
963 $this->Subgroups = array();
964 if (isset($Data["Subgroups"]))
965 {
966 foreach ($Data["Subgroups"] as $SubgroupData)
967 {
968 $this->Subgroups[] = new SearchParameterSet($SubgroupData);
969 }
970 }
971 }
972
977 private function ConvertToLegacyGroup()
978 {
979 $Group = array();
980 # for each set of search strings
981 foreach ($this->SearchStrings as $Field => $Strings)
982 {
983 # get text name of field
984 $FieldName = call_user_func(self::$PrintableFieldFunction, $Field);
985
986 # add set to group
987 $Group["SearchStrings"][$FieldName] = $Strings;
988 }
989
990 # for each keyword search string
991 foreach ($this->KeywordSearchStrings as $String)
992 {
993 # add string to keyword entry in group
994 $Group["SearchStrings"]["XXXKeywordXXX"][] = $String;
995 }
996
997 # if we had any search terms
998 if (count($Group))
999 {
1000 # smash single-value arrays to a scalar
1001 foreach ($Group["SearchStrings"] as &$Tgt)
1002 {
1003 if (count($Tgt) == 1)
1004 {
1005 $Tgt = current($Tgt);
1006 }
1007 }
1008
1009 # set logic for search group
1010 $Group["Logic"] = ($this->Logic == "OR")
1011 ? SearchEngine::LOGIC_OR : SearchEngine::LOGIC_AND;
1012 }
1013
1014 return $Group;
1015 }
1016
1021 private function LoadFromLegacyGroup($Group)
1022 {
1023 # set logic appropriately
1024 $this->Logic(
1025 ($Group["Logic"] == SearchEngine::LOGIC_OR) ?
1026 "OR" : "AND" );
1027
1028 # if this group had no search strings, we're done
1029 if (!isset($Group["SearchStrings"]))
1030 {
1031 return;
1032 }
1033
1034 # otherwise, load the search strings
1035 foreach ($Group["SearchStrings"] as $Field => $Params)
1036 {
1037 # skip empty groups
1038 if (count($Params)==0)
1039 {
1040 continue;
1041 }
1042
1043 $this->AddParameter( $Params,
1044 ($Field == "XXXKeywordXXX" ? NULL : $Field) );
1045
1046 }
1047 }
1048
1054 private function GetAsUrlParameters($SetPrefix = "")
1055 {
1056 # for each search string group in set
1057 $Params = array();
1058 foreach ($this->SearchStrings as $FieldId => $Values)
1059 {
1060 # get numeric version of field ID if not already numeric
1061 if (!is_numeric($FieldId))
1062 {
1063 $FieldId = call_user_func(self::$CanonicalFieldFunction, $FieldId);
1064 }
1065
1066 # for each search string in group
1067 $ParamSuffix = "";
1068 foreach ($Values as $Value)
1069 {
1070 # check for too many search strings for this field
1071 if ($ParamSuffix == "Z")
1072 {
1073 throw new Exception("Maximum search parameter complexity"
1074 ." exceeded: more than 26 search parameters for"
1075 ." field ID ".$FieldId.".");
1076 }
1077
1078 # add search string to URL
1079 $Params[self::$UrlParameterPrefix.$SetPrefix
1080 .$FieldId.$ParamSuffix] = $Value;
1081 $ParamSuffix = ($ParamSuffix == "") ? "A"
1082 : chr(ord($ParamSuffix) + 1);
1083 }
1084 }
1085
1086 # for each keyword search string
1087 $ParamSuffix = "";
1088 foreach ($this->KeywordSearchStrings as $Value)
1089 {
1090 # check for too many keyword search strings
1091 if ($ParamSuffix == "Z")
1092 {
1093 throw new Exception("Maximum search parameter complexity"
1094 ." exceeded: more than 26 keyword search parameters.");
1095 }
1096
1097 # add search string to URL
1098 $Params[self::$UrlParameterPrefix.$SetPrefix
1099 .self::URL_KEYWORD_INDICATOR.$ParamSuffix] = $Value;
1100 $ParamSuffix = ($ParamSuffix == "") ? "A"
1101 : chr(ord($ParamSuffix) + 1);
1102 }
1103
1104 # add logic if not default
1105 if ($this->Logic != self::DEFAULT_LOGIC)
1106 {
1107 $Params[self::$UrlParameterPrefix.$SetPrefix
1108 .self::URL_LOGIC_INDICATOR] = $this->Logic;
1109 }
1110
1111 # for each search parameter subgroup
1112 $SetLetter = "A";
1113 foreach ($this->Subgroups as $Subgroup)
1114 {
1115 # check for too many subgroups
1116 if ($SetLetter == "Z")
1117 {
1118 throw new Exception("Maximum search parameter complexity"
1119 ." exceeded: more than 24 search parameter subgroups.");
1120 }
1121
1122 # retrieve URL string for subgroup and add it to URL
1123 $Params = array_merge($Params, $Subgroup->GetAsUrlParameters(
1124 $SetPrefix.$SetLetter));
1125
1126 # move to next set letter
1127 $SetLetter = ($SetLetter == chr(ord(self::URL_KEYWORD_INDICATOR) - 1))
1128 ? chr(ord(self::URL_KEYWORD_INDICATOR) + 1)
1129 : chr(ord($SetLetter) + 1);
1130 }
1131
1132 # return constructed URL parameter string to caller
1133 return $Params;
1134 }
1135
1142 private function SetFromUrlParameters($UrlParameters)
1143 {
1144 # if string was passed in
1145 if (is_string($UrlParameters))
1146 {
1147 # split string into parameter array
1148 $Params = explode("&", $UrlParameters);
1149
1150 # pare down parameter array to search parameter elements
1151 # and strip off search parameter prefix
1152 $NewUrlParameters = array();
1153 foreach ($Params as $Param)
1154 {
1155 if (strpos($Param, self::$UrlParameterPrefix) === 0)
1156 {
1157 list($Index, $Value) = explode("=", $Param);
1158 $NewUrlParameters[$Index] = urldecode($Value);
1159 }
1160 }
1161 $UrlParameters = $NewUrlParameters;
1162 }
1163
1164 # for each search parameter
1165 foreach ($UrlParameters as $ParamName => $SearchString)
1166 {
1167 # strip off standard search parameter prefix
1168 $ParamName = substr($ParamName, strlen(self::$UrlParameterPrefix));
1169
1170 # split parameter into component parts
1171 $SplitResult = preg_match("/^([".self::URL_KEYWORDFREE_RANGE."]*)"
1172 ."([0-9".self::URL_KEYWORD_INDICATOR."]+)([A-Z]*)$/",
1173 $ParamName, $Matches);
1174
1175 # if split was successful
1176 if ($SplitResult === 1)
1177 {
1178 # pull components from split pieces
1179 $SetPrefix = $Matches[1];
1180 $FieldId = $Matches[2];
1181 $ParamSuffix = $Matches[3];
1182
1183 # if set prefix indicates parameter is part of our set
1184 if ($SetPrefix == "")
1185 {
1186 switch ($FieldId)
1187 {
1188 case self::URL_LOGIC_INDICATOR:
1189 # set logic
1190 $this->Logic($SearchString);
1191 break;
1192
1193 case self::URL_KEYWORD_INDICATOR:
1194 # add string to keyword searches
1195 $this->KeywordSearchStrings[] = $SearchString;
1196 break;
1197
1198 default:
1199 # add string to searches for appropriate field
1200 $this->SearchStrings[$FieldId][] = $SearchString;
1201 break;
1202 }
1203 }
1204 else
1205 {
1206 # add parameter to array for subgroup
1207 $SubgroupIndex = $SetPrefix[0];
1208 $SubgroupPrefix = (strlen($SetPrefix) > 1)
1209 ? substr($SetPrefix, 1) : "";
1210 $SubgroupParamIndex = self::$UrlParameterPrefix
1211 .$SubgroupPrefix.$FieldId.$ParamSuffix;
1212 $SubgroupParameters[$SubgroupIndex][$SubgroupParamIndex]
1213 = $SearchString;
1214 }
1215 }
1216 }
1217
1218 # if subgroups were found
1219 if (isset($SubgroupParameters))
1220 {
1221 # for each identified subgroup
1222 foreach ($SubgroupParameters as $SubgroupIndex => $Parameters)
1223 {
1224 # create subgroup and set parameters
1225 $Subgroup = new SearchParameterSet();
1226 $Subgroup->SetFromUrlParameters($Parameters);
1227
1228 # add subgroup to our set
1229 $this->Subgroups[] = $Subgroup;
1230 }
1231 }
1232 }
1233
1239 private static function NormalizeField($Field)
1240 {
1241 if (($Field !== NULL) && isset(self::$CanonicalFieldFunction))
1242 {
1243 $Field = call_user_func(self::$CanonicalFieldFunction, $Field);
1244 }
1245 return $Field;
1246 }
1247 }
SearchParameterSet\TextDescription
TextDescription($IncludeHtml=TRUE, $StartWithBreak=TRUE, $TruncateLongWordsTo=0, $Indent="")
Get text description of search parameter set.
Definition: SearchParameterSet.php:532
SearchParameterSet\Data
Data($NewValue=NULL)
Get/set search parameter set data, in the form of an opaque string.
Definition: SearchParameterSet.php:444
SearchParameterSet\TranslateLegacySearchValues
static TranslateLegacySearchValues($Field, $Values)
Translate legacy search values to modern equivalents if possible.
Definition: SearchParameterSet.php:909
SearchParameterSet\SetFromLegacyArray
SetFromLegacyArray($SearchGroups)
Set search parameters from legacy array format.
Definition: SearchParameterSet.php:774
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:288
SearchParameterSet\UrlParameterString
UrlParameterString($NewValue=NULL)
Get/set search parameter set, in the form of an URL parameter string.
Definition: SearchParameterSet.php:503
SearchParameterSet\UrlParameters
UrlParameters($NewValue=NULL)
Get/set search parameter set, in the form of URL parameters.
Definition: SearchParameterSet.php:478
SearchParameterSet\URL_KEYWORD_INDICATOR
const URL_KEYWORD_INDICATOR
Definition: SearchParameterSet.php:935
SearchParameterSet\URL_KEYWORDFREE_RANGE
const URL_KEYWORDFREE_RANGE
Definition: SearchParameterSet.php:934
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:409
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:891
SearchParameterSet\GetSearchStringsForField
GetSearchStringsForField($Field, $IncludeSubgroups=TRUE)
Get search strings for specified field.
Definition: SearchParameterSet.php:362
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\ItemTypes
ItemTypes($ItemTypes=FALSE)
Get/set allowed item types.
Definition: SearchParameterSet.php:271
SearchParameterSet\SetFromLegacyUrl
SetFromLegacyUrl($ParameterString)
Set search parameters from legacy URL string.
Definition: SearchParameterSet.php:808
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:877
SearchParameterSet\GetAsLegacyArray
GetAsLegacyArray()
Retrieve search parameters in legacy array format.
Definition: SearchParameterSet.php:720
SearchParameterSet\GetSearchStrings
GetSearchStrings($IncludeSubgroups=FALSE)
Get search strings in set.
Definition: SearchParameterSet.php:329
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:864
SearchParameterSet\GetKeywordSearchStrings
GetKeywordSearchStrings()
Get keyword search strings in set.
Definition: SearchParameterSet.php:391
SearchParameterSet\ReplaceSearchString
ReplaceSearchString($Pattern, $Replacement)
Modify all search strings with the specified regular expression.
Definition: SearchParameterSet.php:684
SearchParameterSet\DEFAULT_LOGIC
const DEFAULT_LOGIC
Definition: SearchParameterSet.php:933
SearchParameterSet\URL_LOGIC_INDICATOR
const URL_LOGIC_INDICATOR
Definition: SearchParameterSet.php:936
SearchParameterSet\GetSubgroups
GetSubgroups()
Get parameter subgroups.
Definition: SearchParameterSet.php:400
SearchParameterSet\ParameterCount
ParameterCount()
Get number of search parameters in set, including those in subgroups.
Definition: SearchParameterSet.php:308