CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

SearchParameterSetEditingUI.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: SearchParameterSetEditingUI.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2016 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
13 class SearchParameterSetEditingUI
14 {
24 public function __construct($FormFieldName, $SearchParams = NULL)
25 {
26 $this->EditFormName = $FormFieldName;
27
28 if ($SearchParams !== NULL)
29 {
30 $this->SearchParams = $SearchParams;
31 }
32 else
33 {
34 $this->SearchParams = new SearchParameterSet();
35 }
36
37 # get the list of fields that are allowed in searches for all schemas
38 $this->MFields = array();
39 $this->AllSchemas = MetadataSchema::GetAllSchemas();
40 foreach ($this->AllSchemas as $SCId => $Schema)
41 {
42 foreach ($Schema->GetFields(NULL, MetadataSchema::MDFORDER_ALPHABETICAL)
43 as $FId => $Field)
44 {
45 if ($Field->IncludeInAdvancedSearch() ||
46 $Field->IncludeInKeywordSearch() )
47 {
48 $this->MFields[]= $Field;
49 }
50 }
51 }
52
53 $this->Factories = array();
54 }
55
64 public function DisplayAsTable($TableId = NULL, $TableStyle = NULL)
65 {
66 print('<table id="'.defaulthtmlentities($TableId).'" '
67 .'class="'.defaulthtmlentities($TableStyle).'" '
68 .'style="width: 100%">');
69 $this->DisplayAsRows();
70 print('</table>');
71 }
72
77 public function DisplayAsRows()
78 {
79
80 $Fields = $this->FlattenSearchParams(
81 $this->SearchParams);
82
83 # make sure the necessary javascript is required
84 $GLOBALS["AF"]->RequireUIFile("jquery-ui.js");
85 $GLOBALS["AF"]->RequireUIFile("CW-QuickSearch.js");
86 $GLOBALS["AF"]->RequireUIFile("SearchParameterSetEditingUI.js");
87
88 # note that all of the fields we create for these rows will be named
89 # $this->EditFormName.'[]' , combining them all into an array of results per
90 # http://php.net/manual/en/faq.html.php#faq.html.arrays
91
92 # css classes required by our javascript are logic_row
93 # field-row, and field-value-edit
94
95 $Depth = 0;
96
97 foreach ($Fields as $FieldRow)
98 {
99 if (is_string($FieldRow) && $FieldRow == "(")
100 {
101 $Depth++;
102 print('<tr><td colspan=2 style="padding-left: 2em;">'
103 .'<input type="hidden" name="'.$this->EditFormName.'[]" '
104 .'value="X-BEGIN-SUBGROUP-X"/>'
105 .'<table class="cw-speui-subgroup">');
106 }
107 elseif (is_string($FieldRow) && $FieldRow == ")")
108 {
109 $Depth--;
110 $this->PrintTemplateRow();
111 print('<input type="hidden" name="'.$this->EditFormName.'[]" '
112 .'value="X-END-SUBGROUP-X"/></table></td></tr>');
113 }
114 elseif (is_array($FieldRow) && isset($FieldRow["Logic"]))
115 {
116 print('<tr class="logic_row '.$this->EditFormName.'">'
117 .'<td colspan="3">'
118 .($Depth==0?'Top-Level Logic: ':'Subgroup with '));
119
120 $ListName = $this->EditFormName."[]";
121 $Options = array("AND"=>"AND", "OR"=>"OR");
122 $SelectedValue = $FieldRow["Logic"];
123
124 $OptList = new HtmlOptionList($ListName, $Options, $SelectedValue);
125 $OptList->ClassForList("logic");
126 $OptList->PrintHtml();
127
128 print (($Depth>0?' Logic':'').'</td></tr>');
129 }
130 elseif (is_array($FieldRow) && isset($FieldRow["FieldId"]) )
131 {
132 $FieldId = $FieldRow["FieldId"];
133 $Values = $FieldRow["Values"];
134 foreach ($Values as $CurVal)
135 {
136 print('<tr class="field-row '.$this->EditFormName.'""
137 ." style="white-space: nowrap;">'
138 ."<td><span class=\"cw-button cw-button-elegant "
139 ."cw-button-constrained cw-speui-delete\">X</span>"
140 ."</td><td>");
141
142 # for selectable fields, we need to generate all the
143 # html elements that we might need and then depend on
144 # javascript to display only those that are relevant
145
146 # each field will have four elements
147
148 # 1. a field selector
149 $this->PrintFieldSelector($FieldId);
150
151 # 2. a value selector (for option and flag values)
152 $this->PrintValueSelector($FieldId, $CurVal);
153
154 $SearchText = (StdLib::strpos($CurVal, "=")===0) ?
155 StdLib::substr($CurVal, 1) : $CurVal;
156
157 # 3. a text entry
158 print('<input type="text" class="field-value-edit" '
159 .'name="'.$this->EditFormName.'[]" '
160 .'placeholder="(search terms)" '
161 .'value="'.defaulthtmlentities($SearchText).'">');
162
163 # 4. an ajax search box
164 $this->PrintQuicksearch($FieldId, $SearchText);
165
166 print("</td></tr>");
167 }
168 }
169 }
170
171 # add a template row, used for adding new fields
172 $this->PrintTemplateRow();
173 }
174
180 public function GetValuesFromFormData()
181 {
182 if (!isset($_POST[$this->EditFormName]))
183 {
184 $Result = new SearchParameterSet();
185 }
186 else
187 {
188 # set up our result
189 $GroupStack = array();
190 array_push($GroupStack, new SearchParameterSet() );
191
192 # extract the array of data associated with our EditFormName
193 $FormData = $_POST[$this->EditFormName];
194
195 # extract and set the search logic, which is always the first
196 # element in the HTML that we generate
197 $Logic = array_shift($FormData);
198 end($GroupStack)->Logic($Logic);
199
200 while (count($FormData))
201 {
202 # first element of each row is a field id
203 $FieldId = array_shift($FormData);
204
205 if ($FieldId == "X-BEGIN-SUBGROUP-X")
206 {
207 # add a new subgroup to our stack of subgroups
208 array_push($GroupStack, new SearchParameterSet());
209 # extract and set the search logic
210 $Logic = array_shift($FormData);
211 end($GroupStack)->Logic($Logic);
212 }
213 elseif ($FieldId == "X-END-SUBGROUP-X")
214 {
215 $Subgroup = array_pop($GroupStack);
216 end($GroupStack)->AddSet($Subgroup);
217 }
218 else
219 {
220 # for selectable fields, we'll have all possible
221 # elements and will need to grab the correct ones for
222 # the currently selected field
223 $SelectVal = array_shift($FormData);
224 $TextVal = array_shift($FormData);
225 $SearchVal = array_shift($FormData);
226
227 if ($FieldId == "X-KEYWORD-X")
228 {
229 $Val = $TextVal;
230 $Field = NULL;
231
232 if (strlen($TextVal)==0)
233 {
234 continue;
235 }
236 }
237 else
238 {
239 $Field = new MetadataField($FieldId);
240
241 # make sure we have factories for field types that need them
242 switch ($Field->Type())
243 {
244 case MetadataSchema::MDFTYPE_TREE:
245 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
246 case MetadataSchema::MDFTYPE_OPTION:
247 if (!isset($this->Factories[$FieldId]))
248 {
249 $this->Factories[$FieldId] = $Field->GetFactory();
250 }
251 break;
252
253 default:
254 break;
255 }
256
257 # verify that we actually have a value for our selected field
258 switch ($Field->Type())
259 {
260 case MetadataSchema::MDFTYPE_PARAGRAPH:
261 case MetadataSchema::MDFTYPE_URL:
262 case MetadataSchema::MDFTYPE_TEXT:
263 case MetadataSchema::MDFTYPE_NUMBER:
264 case MetadataSchema::MDFTYPE_DATE:
265 case MetadataSchema::MDFTYPE_TIMESTAMP:
266 case MetadataSchema::MDFTYPE_USER:
267 # if we have no value for this field, skip displaying it
268 if (strlen($TextVal)==0)
269 {
270 continue 2;
271
272 }
273 break;
274
275 case MetadataSchema::MDFTYPE_TREE:
276 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
277 # if we have no value for this field, skip displaying it
278 if (strlen($SearchVal)==0)
279 {
280 continue 2;
281 }
282 break;
283
284 # no need to check the types where there's
285 # a SelectVal, as that cannot be left empty
286 default:
287 break;
288 }
289
290 # extract the value for our field
291 switch ($Field->Type())
292 {
293 case MetadataSchema::MDFTYPE_PARAGRAPH:
294 case MetadataSchema::MDFTYPE_URL:
295 case MetadataSchema::MDFTYPE_TEXT:
296 case MetadataSchema::MDFTYPE_NUMBER:
297 case MetadataSchema::MDFTYPE_DATE:
298 case MetadataSchema::MDFTYPE_TIMESTAMP:
299 $Val = $TextVal;
300 break;
301
302 case MetadataSchema::MDFTYPE_USER:
303 $Val = "=".$TextVal;
304 break;
305
306 case MetadataSchema::MDFTYPE_TREE:
307 $Item = $this->Factories[$FieldId]->GetItem(
308 $SearchVal);
309
310 # for tree fields, use the same 'is X
311 # or a child of X' construction that we
312 # use when generating search facets
313 $Val = new SearchParameterSet();
314 $Val->Logic("OR");
315 $Val->AddParameter(array(
316 "=".$Item->Name(),
317 "^".$Item->Name()." -- "), $Field);
318 break;
319
320 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
321 $Item = $this->Factories[$FieldId]->GetItem(
322 $SearchVal);
323 $Val = "=".$Item->Name();
324 break;
325
326 case MetadataSchema::MDFTYPE_OPTION:
327 list($InputId, $InputVal) = explode("-", $SelectVal, 2);
328 $Item = $this->Factories[$FieldId]->GetItem(
329 $InputVal);
330 $Val = "=".$Item->Name();
331 break;
332
333 case MetadataSchema::MDFTYPE_FLAG:
334 list($InputId, $InputVal) = explode("-", $SelectVal, 2);
335 $Val = "=".$InputVal;
336 break;
337
338 default:
339 throw new Exception("Unsupported field type");
340 }
341 }
342
343 # add our value to the search parameters
344 if ($Val instanceof SearchParameterSet)
345 {
346 end($GroupStack)->AddSet($Val);
347 }
348 else
349 {
350 end($GroupStack)->AddParameter($Val, $Field);
351 }
352 }
353 }
354
355 $Result = array_pop($GroupStack);
356 }
357
358 $this->SearchParams = $Result;
359 return $Result;
360 }
361
367 public function SearchParameters($SearchParams = NULL)
368 {
369 if ($SearchParams !== NULL)
370 {
371 $this->SearchParams = clone $SearchParams;
372 }
373
374 return clone $this->SearchParams;
375 }
376
387 public function MaxFieldLabelLength($NewValue = NULL)
388 {
389 if (!is_null($NewValue))
390 {
391 $this->MaxFieldLabelLength = $NewValue;
392 }
393 return $this->MaxFieldLabelLength;
394 }
395
406 public function MaxValueLabelLength($NewValue = NULL)
407 {
408 if (!is_null($NewValue))
409 {
410 $this->MaxValueLabelLength = $NewValue;
411 }
412 return $this->MaxValueLabelLength;
413 }
414
415
416 # ---- PRIVATE INTERFACE -------------------------------------------------
417
418 private $EditFormName;
419 private $SearchParams;
420 private $MFields;
421 private $AllSchemas;
422 private $Factories;
423 private $MaxFieldLabelLength = 0;
424 private $MaxValueLabelLength = 0;
425
437 private function FlattenSearchParams($SearchParams)
438 {
439 $Result = array();
440
441 $Result[]= array(
442 "Logic" => $SearchParams->Logic() );
443
444 $SearchStrings = $SearchParams->GetSearchStrings();
445 foreach ($SearchStrings as $FieldId => $Values)
446 {
447 $Result[]= array(
448 "FieldId" => $FieldId,
449 "Values" => $Values);
450 }
451
452 $KeywordStrings = $SearchParams->GetKeywordSearchStrings();
453 if (count($KeywordStrings))
454 {
455 $Result[]= array(
456 "FieldId" => "X-KEYWORD-X",
457 "Values" => $KeywordStrings);
458 }
459
460 $Subgroups = $SearchParams->GetSubgroups();
461 if (count($Subgroups))
462 {
463 foreach ($Subgroups as $Subgroup)
464 {
465 $Result[]= "(";
466 $SubgroupItems = $this->FlattenSearchParams($Subgroup);
467 foreach ($SubgroupItems as $Item)
468 {
469 $Result[] = $Item;
470 }
471 $Result[]= ")";
472 }
473 }
474
475 return $Result;
476 }
477
482 private function PrintFieldSelector($FieldId)
483 {
484 $ListName = $this->EditFormName."[]";
485 $SelectedValue = array();
486
487 # "Keyword" option is always here
488 $Options["X-KEYWORD-X"] = "Keyword";
489 $OptionClass["X-KEYWORD-X"] = "field-type-keyword";
490 if ($FieldId == "X-KEYWORD-X")
491 {
492 $SelectedValue[] = "X-KEYWORD-X";
493 }
494
495 # prepare options for print
496 foreach ($this->MFields as $MField)
497 {
498 $TypeName = defaulthtmlentities(
499 str_replace(' ', '', strtolower($MField->TypeAsName())));
500
501 if (!$MField->Optional())
502 {
503 $TypeName .= " required";
504 }
505
506 $FieldName = $MField->Name();
507 if ($MField->SchemaId() != MetadataSchema::SCHEMAID_DEFAULT)
508 {
509 $FieldName = $this->AllSchemas[$MField->SchemaId()]->Name()
510 .": ".$FieldName;
511 }
512
513 $Options[$MField->Id()] = defaulthtmlentities($FieldName);
514 $OptionClass[$MField->Id()] = "field-type-".$TypeName;
515
516 if ($FieldId == $MField->Id())
517 {
518 $SelectedValue[] = $MField->Id();
519 }
520 }
521
522 # instantiate option list and print
523 $OptList = new HtmlOptionList($ListName, $Options, $SelectedValue);
524 $OptList->ClassForList("field-subject");
525 $OptList->ClassForOptions($OptionClass);
526 $OptList->MaxLabelLength($this->MaxFieldLabelLength);
527 $OptList->PrintHtml();
528 }
529
530
536 private function PrintValueSelector($FieldId, $CurVal)
537 {
538 # parameters of the option list
539 $ListName = $this->EditFormName."[]";
540 $Options = array();
541 $OptionClass = array();
542 $SelectedValue = array();
543
544 # prepare options for print
545 foreach ($this->MFields as $MField)
546 {
547 if ($MField->Type() == MetadataSchema::MDFTYPE_FLAG ||
548 $MField->Type() == MetadataSchema::MDFTYPE_OPTION)
549 {
550 foreach ($MField->GetPossibleValues() as $Id => $Val)
551 {
552 $IsSelected = FALSE;
553 $Key = $MField->Id()."-".$Id;
554
555 if ($MField->Id() == $FieldId)
556 {
557 $TgtVal = ($MField->Type() == MetadataSchema::MDFTYPE_FLAG) ?
558 "=".$Id : "=".$Val ;
559 $IsSelected = ($CurVal == $TgtVal) ? TRUE : FALSE ;
560 }
561
562 $Options[$Key] = defaulthtmlentities($Val);
563 $OptionClass[$Key] = "field-id-".$MField->Id();
564
565 if ($IsSelected)
566 {
567 $SelectedValue[] = $Key;
568 }
569 }
570 }
571 }
572
573 # instantiate an option list and print
574 $OptList = new HtmlOptionList($ListName, $Options, $SelectedValue);
575 $OptList->ClassForList("field-value-select");
576 $OptList->ClassForOptions($OptionClass);
577 $OptList->MaxLabelLength($this->MaxValueLabelLength);
578 $OptList->PrintHtml();
579 }
580
586 private function PrintQuicksearch($FieldId, $CurVal)
587 {
588 if ($FieldId !== NULL && $FieldId != "X-KEYWORD-X")
589 {
590 if (!isset($this->Factories[$FieldId]))
591 {
592 $Field = new MetadataField($FieldId);
593 $Factory = $Field->GetFactory();
594
595 $this->Factories[$FieldId] =
596 ($Factory !== NULL) ? $Factory : FALSE;
597 }
598
599 $ItemId = ($this->Factories[$FieldId] !== FALSE) ?
600 $this->Factories[$FieldId]->GetItemIdByName($CurVal) : "" ;
601 }
602 else
603 {
604 $ItemId = "";
605 }
606
607 # field-value-qs css class required by our javascript.
608 # various cw-quicksearch classes required by the quicksearch javascript
609 # and ui-front class required by jquery-ui, used by qs js
610 print('<div class="field-value-qs cw-quicksearch '
611 . 'cw-quicksearch-template">'
612 .'<input class="cw-quicksearch-display '
613 .'cw-resourceeditor-metadatafield" '
614 .'placeholder="(enter some text to begin searching)" '
615 .'value="'.defaulthtmlentities($CurVal).'" />'
616 .'<input name="'.$this->EditFormName.'[]" '
617 .'class="cw-quicksearch-value" type="hidden" '
618 .'value="'.defaulthtmlentities($ItemId).'" />'
619 .'<div style="display: none;" '
620 .'class="cw-quicksearch-menu">'
621 .'<div class="cw-quicksearch-message ui-front"></div>'
622 .'</div></div>');
623 }
624
628 private function PrintTemplateRow()
629 {
630 # field-row, template-row, field-value-edit, cw-speui-add, and
631 # cw-speui-add-subgroup css classes required by our javascript
632 print(
633 "<tr class=\"field-row template-row ".$this->EditFormName."\""
634 ." style=\"white-space: nowrap;\">"
635 ."<td>"
636 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
637 ."cw-speui-delete\">X</span>"
638 ."</td><td>");
639 $this->PrintFieldSelector(NULL);
640 $this->PrintValueSelector(NULL, "");
641 print("<input type=\"text\" class=\"field-value-edit\" "
642 ."name=\"".$this->EditFormName."[]\" placeholder=\"(search terms)\" "
643 ."value=\"\">");
644 $this->PrintQuicksearch(NULL, "");
645 print("</td></tr>");
646 print("<tr><td colspan=2>"
647 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
648 ."cw-speui-add\">Add Field</span>"
649 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
650 ."cw-speui-add-subgroup\">Add Subgroup</span>"
651 ."</td></tr>");
652 }
653 }
MetadataSchema\MDFTYPE_TIMESTAMP
const MDFTYPE_TIMESTAMP
Definition: MetadataSchema.php:25
SearchParameterSetEditingUI\GetValuesFromFormData
GetValuesFromFormData()
Extract values from a dynamics field edit/modification form.
Definition: SearchParameterSetEditingUI.php:180
SearchParameterSetEditingUI\DisplayAsRows
DisplayAsRows()
Display the table rows for the editing form, without the surrounding.
Definition: SearchParameterSetEditingUI.php:77
SearchParameterSetEditingUI\SearchParameters
SearchParameters($SearchParams=NULL)
Get/Set search parameters.
Definition: SearchParameterSetEditingUI.php:367
MetadataSchema\MDFORDER_ALPHABETICAL
const MDFORDER_ALPHABETICAL
Definition: MetadataSchema.php:40
SearchParameterSet
Set of parameters used to perform a search.
Definition: SearchParameterSet.php:13
SearchParameterSetEditingUI\DisplayAsTable
DisplayAsTable($TableId=NULL, $TableStyle=NULL)
Display editing form elements enclosed in a.
Definition: SearchParameterSetEditingUI.php:64
SearchParameterSetEditingUI\MaxValueLabelLength
MaxValueLabelLength($NewValue=NULL)
Get/set the max number of characters a label of a value option list will be displayed.
Definition: SearchParameterSetEditingUI.php:406
StdLib\strpos
static strpos()
Multibyte-aware (if supported in PHP) version of strpos().
Definition: StdLib.php:532
MetadataSchema\MDFTYPE_NUMBER
const MDFTYPE_NUMBER
Definition: MetadataSchema.php:23
SearchParameterSetEditingUI\__construct
__construct($FormFieldName, $SearchParams=NULL)
Create a UI for specifing edits to SearchParameterSets.
Definition: SearchParameterSetEditingUI.php:24
MetadataSchema\MDFTYPE_TREE
const MDFTYPE_TREE
Definition: MetadataSchema.php:27
MetadataSchema\MDFTYPE_OPTION
const MDFTYPE_OPTION
Definition: MetadataSchema.php:29
MetadataSchema\MDFTYPE_FLAG
const MDFTYPE_FLAG
Definition: MetadataSchema.php:26
MetadataSchema\MDFTYPE_CONTROLLEDNAME
const MDFTYPE_CONTROLLEDNAME
Definition: MetadataSchema.php:28
StdLib\substr
static substr()
Multibyte-aware (if supported in PHP) version of substr().
Definition: StdLib.php:523
SearchParameterSetEditingUI\MaxFieldLabelLength
MaxFieldLabelLength($NewValue=NULL)
Get/set the max number of characters a label of a field option list will be displayed.
Definition: SearchParameterSetEditingUI.php:387
PHP
PHP
Definition: RSSClient--Test.php:12
MetadataSchema\SCHEMAID_DEFAULT
const SCHEMAID_DEFAULT
Definition: MetadataSchema.php:53
MetadataField
Object representing a locally-defined type of metadata field.
Definition: MetadataField.php:13
MetadataSchema\MDFTYPE_PARAGRAPH
const MDFTYPE_PARAGRAPH
Definition: MetadataSchema.php:22
MetadataSchema\MDFTYPE_DATE
const MDFTYPE_DATE
Definition: MetadataSchema.php:24
MetadataSchema\MDFTYPE_URL
const MDFTYPE_URL
Definition: MetadataSchema.php:33
MetadataSchema\MDFTYPE_TEXT
const MDFTYPE_TEXT
Definition: MetadataSchema.php:21
MetadataSchema\MDFTYPE_USER
const MDFTYPE_USER
Definition: MetadataSchema.php:30
MetadataSchema\GetAllSchemas
static GetAllSchemas()
Get all existing metadata schemas.
Definition: MetadataSchema.php:1844
HtmlOptionList
Convenience class for generating an HTML select/option form element.
Definition: HtmlOptionList.php:13
SearchParameterSetEditingUI
Class to create a user interface for editing SearchParameterSets.
Definition: SearchParameterSetEditingUI.php:13