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