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 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 );
548
549 # set characters used to indicate literal strings
550 $LiteralStart = $IncludeHtml ? "<i>" : "\"";
551 $LiteralEnd = $IncludeHtml ? "</i>" : "\"";
552 $LiteralBreak = $IncludeHtml ? "<br>\n" : "\n";
553 $Indent .= $IncludeHtml ? "&nbsp;&nbsp;&nbsp;&nbsp;" : " ";
554
555 # for each keyword search string
556 $Descriptions = array();
557 foreach ($this->KeywordSearchStrings as $SearchString)
558 {
559 # escape search string if appropriate
560 if ($IncludeHtml)
561 {
562 $SearchString = defaulthtmlentities($SearchString);
563 }
564
565 # add string to list of descriptions
566 $Descriptions[] = $LiteralStart.$SearchString.$LiteralEnd;
567 }
568
569 # for each field with search strings
570 foreach ($this->SearchStrings as $FieldId => $SearchStrings)
571 {
572 # retrieve field name
573 $FieldName = call_user_func(self::$PrintableFieldFunction, $FieldId);
574
575 # for each search string
576 foreach ($SearchStrings as $SearchString)
577 {
578 # extract operator from search string
579 $MatchResult = preg_match('/^([=><!^$]+)(.+)/',
580 $SearchString, $Matches);
581
582 # determine operator phrase
583 if (($MatchResult == 1) && isset($OperatorPhrases[$Matches[1]]))
584 {
585 $OpPhrase = $OperatorPhrases[$Matches[1]];
586 $SearchString = $Matches[2];
587 }
588 else
589 {
590 $OpPhrase = "contains";
591 }
592
593 # escape field name and search string if appropriate
594 if ($IncludeHtml)
595 {
596 $FieldName = defaulthtmlentities($FieldName);
597 $SearchString = defaulthtmlentities($SearchString);
598 }
599
600 # assemble field and operator and value into description
601 $Descriptions[] = $FieldName." ".$OpPhrase." "
602 .$LiteralStart.$SearchString.$LiteralEnd;
603 }
604 }
605
606 # for each subgroup
607 foreach ($this->Subgroups as $Subgroup)
608 {
609 # retrieve description for subgroup
610 if ($Subgroup->ParameterCount() == 1)
611 {
612 $Descriptions[] = $Subgroup->TextDescription($IncludeHtml,
613 $StartWithBreak, $TruncateLongWordsTo, $Indent);
614 }
615 elseif ($Subgroup->ParameterCount() > 1)
616 {
617 $Descriptions[] = "(".$Subgroup->TextDescription($IncludeHtml,
618 $StartWithBreak, $TruncateLongWordsTo, $Indent).")";
619 }
620 }
621
622 # join descriptions with appropriate conjunction
623 $Descrip = join($LiteralBreak.$Indent." ".strtolower($this->Logic)." ",
624 $Descriptions);
625
626 # if caller requested that long words be truncated
627 if ($TruncateLongWordsTo > 4)
628 {
629 # break description into words
630 $Words = explode(" ", $Descrip);
631
632 # for each word
633 $NewDescrip = "";
634 foreach ($Words as $Word)
635 {
636 # if word is longer than specified length
637 if (strlen(strip_tags($Word)) > $TruncateLongWordsTo)
638 {
639 # truncate word and add ellipsis
640 $Word = NeatlyTruncateString($Word, $TruncateLongWordsTo - 3);
641 }
642
643 # add word to new description
644 $NewDescrip .= " ".$Word;
645 }
646
647 # set description to new description
648 $Descrip = $NewDescrip;
649 }
650
651 # return description to caller
652 return $Descrip;
653 }
654
655
656 /*@)*/
657 # ---- BACKWARD COMPATIBILITY ---------------------------------------------
658 /*@(*/
659
668 public function GetAsLegacyArray()
669 {
670 $Legacy = array();
671
672 $Group = $this->ConvertToLegacyGroup();
673 if (count($Group))
674 {
675 $Legacy["MAIN"] = $Group;
676 }
677
678 # for each subgroup
679 foreach ($this->Subgroups as $Subgroup)
680 {
681 # skip empty search groups
682 if (count($Subgroup->SearchStrings)==0)
683 {
684 continue;
685 }
686
687 $SubLegacy = $Subgroup->ConvertToLegacyGroup();
688
689 # give an index based on the FieldId of the first
690 # element in the SearchStrings
691 $FieldId = call_user_func(
692 self::$CanonicalFieldFunction,
693 current(array_keys($SubLegacy["SearchStrings"])) );
694
695 # add groups from legacy array to our array
696 if (!isset($Legacy[$FieldId]))
697 {
698 $Legacy[$FieldId] = $SubLegacy;
699 }
700 else
701 {
702 $Num = count($Legacy[$FieldId]);
703 $Legacy[$FieldId."-".$Num] = $SubLegacy;
704 }
705
706 if (count($Subgroup->Subgroups))
707 {
708 throw new Exception(
709 "Attempt to convert SearchParameterSet containing nested subgroups "
710 ."to legacy format");
711 }
712 }
713
714 # return array to caller
715 return $Legacy;
716 }
717
722 public function SetFromLegacyArray($SearchGroups)
723 {
724 # clear current settings
725 $this->KeywordSearchStrings = array();
726 $this->SearchStrings = array();
727 $this->Subgroups = array();
728
729 # iterate over legacy search groups
730 foreach ($SearchGroups as $GroupId => $SearchGroup)
731 {
732 if ($GroupId == "MAIN")
733 {
734 # add terms from the main search group to ourself
735 $this->LoadFromLegacyGroup($SearchGroup);
736 }
737 else
738 {
739 # create subgroups for other groups
740 $Subgroup = new SearchParameterSet();
741 $Subgroup->LoadFromLegacyGroup($SearchGroup);
742
743 # add any non-empty groups
744 if ($Subgroup->ParameterCount())
745 {
746 $this->AddSet($Subgroup);
747 }
748 }
749 }
750 }
751
756 public function SetFromLegacyUrl($ParameterString)
757 {
758 # clear current settings
759 $this->KeywordSearchStrings = array();
760 $this->SearchStrings = array();
761 $this->Subgroups = array();
762
763 # extact array of parameters from passed string
764 $GetVars = ParseQueryString($ParameterString);
765
766 # iterate over the provided parameters
767 foreach ($GetVars as $Key => $Val)
768 {
769 # if this param gives search information
770 if (preg_match("/^([FGH])(K|[0-9]+)$/", $Key, $Matches))
771 {
772 # extract what kind of search it was which field
773 $Type = $Matches[1];
774 $FieldId = $Matches[2];
775
776 # for 'contains' searches
777 if ($Type == "F")
778 {
779 # add this to our search strings
780 $this->AddParameter( $Val,
781 ($FieldId == "K" ? NULL : $FieldId) );
782 }
783 else
784 {
785 # otherwise, create a subgroup for this parameter
786 $Subgroup = new SearchParameterSet();
787
788 # set logic based on the search type
789 $Subgroup->Logic($Type=="H" ? "AND" : "OR");
790
791 # extract the values and add them to a subgroup
792 $Values = explode("-", $Val);
793 $Subgroup->AddParameter(
794 self::TranslateLegacySearchValues($FieldId, $Values),
795 $FieldId );
796
797 # if subgroup was non-empty, slurp it up
798 if ($Subgroup->ParameterCount())
799 {
800 $this->AddSet($Subgroup);
801 }
802 }
803 }
804 }
805 }
806
812 public static function IsLegacyUrl($ParameterString)
813 {
814 $QueryVars = ParseQueryString($ParameterString);
815
816 return (array_key_exists("Q", $QueryVars) &&
817 $QueryVars["Q"] == "Y") ? TRUE : FALSE ;
818 }
819
825 public static function ConvertLegacyUrl($ParameterString)
826 {
827 $SearchParams = new SearchParameterSet();
828 $SearchParams->SetFromLegacyUrl($ParameterString);
829
830 return $SearchParams->UrlParameterString();
831 }
832
839 public static function SetLegacyUrlTranslationFunction($Func)
840 {
841 if (is_callable($Func))
842 {
843 self::$LegacyUrlTranslationFunction = $Func;
844 }
845 else
846 {
847 throw new InvalidArgumentException("Invalid function supplied.");
848 }
849 }
850
857 public static function TranslateLegacySearchValues($Field, $Values)
858 {
859 if (($Field !== NULL) && isset(self::$LegacyUrlTranslationFunction))
860 {
861 $Values = call_user_func(self::$LegacyUrlTranslationFunction,
862 $Field, $Values);
863 }
864 return $Values;
865 }
866
867 /*@)*/
868 # ---- PRIVATE INTERFACE -------------------------------------------------
869
870 private $KeywordSearchStrings = array();
871 private $ItemTypes = NULL;
872 private $Logic = self::DEFAULT_LOGIC;
873 private $SearchStrings = array();
874 private $Subgroups = array();
875
876 static private $CanonicalFieldFunction;
877 static private $PrintableFieldFunction;
878 static private $LegacyUrlTranslationFunction;
879 static private $UrlParameterPrefix = "F";
880
881 const DEFAULT_LOGIC = "AND";
882 const URL_KEYWORDFREE_RANGE = "A-JL-Z";
883 const URL_KEYWORD_INDICATOR = "K";
884 const URL_LOGIC_INDICATOR = "00";
885
891 private function LoadFromData($Serialized)
892 {
893 # unpack new data
894 $Data = unserialize($Serialized);
895 if (!is_array($Data))
896 {
897 throw new InvalidArgumentException("Incoming set data"
898 ." appears invalid.");
899 }
900
901 # load logic
902 $this->Logic = isset($Data["Logic"]) ? $Data["Logic"] : "AND";
903
904 # load search strings
905 $this->SearchStrings = isset($Data["SearchStrings"])
906 ? $Data["SearchStrings"] : array();
907 $this->KeywordSearchStrings = isset($Data["KeywordSearchStrings"])
908 ? $Data["KeywordSearchStrings"] : array();
909
910 # load any subgroups
911 $this->Subgroups = array();
912 if (isset($Data["Subgroups"]))
913 {
914 foreach ($Data["Subgroups"] as $SubgroupData)
915 {
916 $this->Subgroups[] = new SearchParameterSet($SubgroupData);
917 }
918 }
919 }
920
925 private function ConvertToLegacyGroup()
926 {
927 $Group = array();
928 # for each set of search strings
929 foreach ($this->SearchStrings as $Field => $Strings)
930 {
931 # get text name of field
932 $FieldName = call_user_func(self::$PrintableFieldFunction, $Field);
933
934 # add set to group
935 $Group["SearchStrings"][$FieldName] = $Strings;
936 }
937
938 # for each keyword search string
939 foreach ($this->KeywordSearchStrings as $String)
940 {
941 # add string to keyword entry in group
942 $Group["SearchStrings"]["XXXKeywordXXX"][] = $String;
943 }
944
945 # if we had any search terms
946 if (count($Group))
947 {
948 # smash single-value arrays to a scalar
949 foreach ($Group["SearchStrings"] as &$Tgt)
950 {
951 if (count($Tgt) == 1)
952 {
953 $Tgt = current($Tgt);
954 }
955 }
956
957 # set logic for search group
958 $Group["Logic"] = ($this->Logic == "OR")
959 ? SearchEngine::LOGIC_OR : SearchEngine::LOGIC_AND;
960 }
961
962 return $Group;
963 }
964
969 private function LoadFromLegacyGroup($Group)
970 {
971 # set logic appropriately
972 $this->Logic(
973 ($Group["Logic"] == SearchEngine::LOGIC_OR) ?
974 "OR" : "AND" );
975
976 # if this group had no search strings, we're done
977 if (!isset($Group["SearchStrings"]))
978 {
979 return;
980 }
981
982 # otherwise, load the search strings
983 foreach ($Group["SearchStrings"] as $Field => $Params)
984 {
985 # skip empty groups
986 if (count($Params)==0)
987 {
988 continue;
989 }
990
991 $this->AddParameter( $Params,
992 ($Field == "XXXKeywordXXX" ? NULL : $Field) );
993
994 }
995 }
996
1002 private function GetAsUrlParameters($SetPrefix = "")
1003 {
1004 # for each search string group in set
1005 $Params = array();
1006 foreach ($this->SearchStrings as $FieldId => $Values)
1007 {
1008 # get numeric version of field ID if not already numeric
1009 if (!is_numeric($FieldId))
1010 {
1011 $FieldId = call_user_func(self::$CanonicalFieldFunction, $FieldId);
1012 }
1013
1014 # for each search string in group
1015 $ParamSuffix = "";
1016 foreach ($Values as $Value)
1017 {
1018 # check for too many search strings for this field
1019 if ($ParamSuffix == "Z")
1020 {
1021 throw new Exception("Maximum search parameter complexity"
1022 ." exceeded: more than 26 search parameters for"
1023 ." field ID ".$FieldId.".");
1024 }
1025
1026 # add search string to URL
1027 $Params[self::$UrlParameterPrefix.$SetPrefix
1028 .$FieldId.$ParamSuffix] = $Value;
1029 $ParamSuffix = ($ParamSuffix == "") ? "A"
1030 : chr(ord($ParamSuffix) + 1);
1031 }
1032 }
1033
1034 # for each keyword search string
1035 $ParamSuffix = "";
1036 foreach ($this->KeywordSearchStrings as $Value)
1037 {
1038 # check for too many keyword search strings
1039 if ($ParamSuffix == "Z")
1040 {
1041 throw new Exception("Maximum search parameter complexity"
1042 ." exceeded: more than 26 keyword search parameters.");
1043 }
1044
1045 # add search string to URL
1046 $Params[self::$UrlParameterPrefix.$SetPrefix
1047 .self::URL_KEYWORD_INDICATOR.$ParamSuffix] = $Value;
1048 $ParamSuffix = ($ParamSuffix == "") ? "A"
1049 : chr(ord($ParamSuffix) + 1);
1050 }
1051
1052 # add logic if not default
1053 if ($this->Logic != self::DEFAULT_LOGIC)
1054 {
1055 $Params[self::$UrlParameterPrefix.$SetPrefix
1056 .self::URL_LOGIC_INDICATOR] = $this->Logic;
1057 }
1058
1059 # for each search parameter subgroup
1060 $SetLetter = "A";
1061 foreach ($this->Subgroups as $Subgroup)
1062 {
1063 # check for too many subgroups
1064 if ($SetLetter == "Z")
1065 {
1066 throw new Exception("Maximum search parameter complexity"
1067 ." exceeded: more than 24 search parameter subgroups.");
1068 }
1069
1070 # retrieve URL string for subgroup and add it to URL
1071 $Params = array_merge($Params, $Subgroup->GetAsUrlParameters(
1072 $SetPrefix.$SetLetter));
1073
1074 # move to next set letter
1075 $SetLetter = ($SetLetter == chr(ord(self::URL_KEYWORD_INDICATOR) - 1))
1076 ? chr(ord(self::URL_KEYWORD_INDICATOR) + 1)
1077 : chr(ord($SetLetter) + 1);
1078 }
1079
1080 # return constructed URL parameter string to caller
1081 return $Params;
1082 }
1083
1090 private function SetFromUrlParameters($UrlParameters)
1091 {
1092 # if string was passed in
1093 if (is_string($UrlParameters))
1094 {
1095 # split string into parameter array
1096 $Params = explode("&", $UrlParameters);
1097
1098 # pare down parameter array to search parameter elements
1099 # and strip off search parameter prefix
1100 $NewUrlParameters = array();
1101 foreach ($Params as $Param)
1102 {
1103 if (strpos($Param, self::$UrlParameterPrefix) === 0)
1104 {
1105 list($Index, $Value) = explode("=", $Param);
1106 $NewUrlParameters[$Index] = urldecode($Value);
1107 }
1108 }
1109 $UrlParameters = $NewUrlParameters;
1110 }
1111
1112 # for each search parameter
1113 foreach ($UrlParameters as $ParamName => $SearchString)
1114 {
1115 # strip off standard search parameter prefix
1116 $ParamName = substr($ParamName, strlen(self::$UrlParameterPrefix));
1117
1118 # split parameter into component parts
1119 $SplitResult = preg_match("/^([".self::URL_KEYWORDFREE_RANGE."]*)"
1120 ."([0-9".self::URL_KEYWORD_INDICATOR."]+)([A-Z]*)$/",
1121 $ParamName, $Matches);
1122
1123 # if split was successful
1124 if ($SplitResult === 1)
1125 {
1126 # pull components from split pieces
1127 $SetPrefix = $Matches[1];
1128 $FieldId = $Matches[2];
1129 $ParamSuffix = $Matches[3];
1130
1131 # if set prefix indicates parameter is part of our set
1132 if ($SetPrefix == "")
1133 {
1134 switch ($FieldId)
1135 {
1136 case self::URL_LOGIC_INDICATOR:
1137 # set logic
1138 $this->Logic($SearchString);
1139 break;
1140
1141 case self::URL_KEYWORD_INDICATOR:
1142 # add string to keyword searches
1143 $this->KeywordSearchStrings[] = $SearchString;
1144 break;
1145
1146 default:
1147 # add string to searches for appropriate field
1148 $this->SearchStrings[$FieldId][] = $SearchString;
1149 break;
1150 }
1151 }
1152 else
1153 {
1154 # add parameter to array for subgroup
1155 $SubgroupIndex = $SetPrefix[0];
1156 $SubgroupPrefix = (strlen($SetPrefix) > 1)
1157 ? substr($SetPrefix, 1) : "";
1158 $SubgroupParamIndex = self::$UrlParameterPrefix
1159 .$SubgroupPrefix.$FieldId.$ParamSuffix;
1160 $SubgroupParameters[$SubgroupIndex][$SubgroupParamIndex]
1161 = $SearchString;
1162 }
1163 }
1164 }
1165
1166 # if subgroups were found
1167 if (isset($SubgroupParameters))
1168 {
1169 # for each identified subgroup
1170 foreach ($SubgroupParameters as $SubgroupIndex => $Parameters)
1171 {
1172 # create subgroup and set parameters
1173 $Subgroup = new SearchParameterSet();
1174 $Subgroup->SetFromUrlParameters($Parameters);
1175
1176 # add subgroup to our set
1177 $this->Subgroups[] = $Subgroup;
1178 }
1179 }
1180 }
1181
1187 private static function NormalizeField($Field)
1188 {
1189 if (($Field !== NULL) && isset(self::$CanonicalFieldFunction))
1190 {
1191 $Field = call_user_func(self::$CanonicalFieldFunction, $Field);
1192 }
1193 return $Field;
1194 }
1195 }
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:857
SearchParameterSet\SetFromLegacyArray
SetFromLegacyArray($SearchGroups)
Set search parameters from legacy array format.
Definition: SearchParameterSet.php:722
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:883
SearchParameterSet\URL_KEYWORDFREE_RANGE
const URL_KEYWORDFREE_RANGE
Definition: SearchParameterSet.php:882
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:839
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:756
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:825
SearchParameterSet\GetAsLegacyArray
GetAsLegacyArray()
Retrieve search parameters in legacy array format.
Definition: SearchParameterSet.php:668
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:812
SearchParameterSet\GetKeywordSearchStrings
GetKeywordSearchStrings()
Get keyword search strings in set.
Definition: SearchParameterSet.php:391
SearchParameterSet\DEFAULT_LOGIC
const DEFAULT_LOGIC
Definition: SearchParameterSet.php:881
SearchParameterSet\URL_LOGIC_INDICATOR
const URL_LOGIC_INDICATOR
Definition: SearchParameterSet.php:884
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