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">'.($Depth==0?'Top-Level Logic: ':'Subgroup with ')
121 .'<select name="'.$this->EditFormName.'[]" '
122 .'class="logic">'
123 .'<option value="AND" '
124 .($FieldRow["Logic"]=="AND" ? "selected ":"")
125 .'>AND</option>'
126 .'<option value="OR" '
127 .($FieldRow["Logic"]=="OR" ? "selected ":"")
128 .'>OR</option>'
129 .'</select>'.($Depth>0?' Logic':'').'</td></tr>');
130 }
131 elseif (is_array($FieldRow) && isset($FieldRow["FieldId"]) )
132 {
133 $FieldId = $FieldRow["FieldId"];
134 $Values = $FieldRow["Values"];
135 foreach ($Values as $CurVal)
136 {
137 print('<tr class="field-row '.$this->EditFormName.'""
138 ." style="white-space: nowrap;">'
139 ."<td><span class=\"cw-button cw-button-elegant "
140 ."cw-button-constrained cw-speui-delete\">X</span>"
141 ."</td><td>");
142
143 # for selectable fields, we need to generate all the
144 # html elements that we might need and then depend on
145 # javascript to display only those that are relevant
146
147 # each field will have four elements
148
149 # 1. a field selector
150 $this->PrintFieldSelector($FieldId);
151
152 # 2. a value selector (for option and flag values)
153 $this->PrintValueSelector($FieldId, $CurVal);
154
155 $SearchText = (mb_strpos($CurVal, "=")===0) ?
156 mb_substr($CurVal, 1) : $CurVal;
157
158 # 3. a text entry
159 print('<input type="text" class="field-value-edit" '
160 .'name="'.$this->EditFormName.'[]" '
161 .'placeholder="(search terms)" '
162 .'value="'.defaulthtmlentities($SearchText).'">');
163
164 # 4. an ajax search box
165 $this->PrintQuicksearch($FieldId, $SearchText);
166
167 print("</td></tr>");
168 }
169 }
170 }
171
172 # add a template row, used for adding new fields
173 $this->PrintTemplateRow();
174 }
175
181 public function GetValuesFromFormData()
182 {
183 if (!isset($_POST[$this->EditFormName]))
184 {
185 $Result = new SearchParameterSet();
186 }
187 else
188 {
189 # set up our result
190 $GroupStack = array();
191 array_push($GroupStack, new SearchParameterSet() );
192
193 # extract the array of data associated with our EditFormName
194 $FormData = $_POST[$this->EditFormName];
195
196 # extract and set the search logic, which is always the first
197 # element in the HTML that we generate
198 $Logic = array_shift($FormData);
199 end($GroupStack)->Logic($Logic);
200
201 while (count($FormData))
202 {
203 # first element of each row is a field id
204 $FieldId = array_shift($FormData);
205
206 if ($FieldId == "X-BEGIN-SUBGROUP-X")
207 {
208 # add a new subgroup to our stack of subgroups
209 array_push($GroupStack, new SearchParameterSet());
210 # extract and set the search logic
211 $Logic = array_shift($FormData);
212 end($GroupStack)->Logic($Logic);
213 }
214 elseif ($FieldId == "X-END-SUBGROUP-X")
215 {
216 $Subgroup = array_pop($GroupStack);
217 end($GroupStack)->AddSet($Subgroup);
218 }
219 else
220 {
221 # for selectable fields, we'll have all possible
222 # elements and will need to grab the correct ones for
223 # the currently selected field
224 $SelectVal = array_shift($FormData);
225 $TextVal = array_shift($FormData);
226 $SearchVal = array_shift($FormData);
227
228 if ($FieldId == "X-KEYWORD-X")
229 {
230 $Val = $TextVal;
231 $Field = NULL;
232
233 if (strlen($TextVal)==0)
234 {
235 continue;
236 }
237 }
238 else
239 {
240 $Field = new MetadataField($FieldId);
241
242 # make sure we have factories for field types that need them
243 switch ($Field->Type())
244 {
245 case MetadataSchema::MDFTYPE_TREE:
246 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
247 case MetadataSchema::MDFTYPE_OPTION:
248 if (!isset($this->Factories[$FieldId]))
249 {
250 $this->Factories[$FieldId] = $Field->GetFactory();
251 }
252 break;
253
254 default:
255 break;
256 }
257
258 # verify that we actually have a value for our selected field
259 switch ($Field->Type())
260 {
261 case MetadataSchema::MDFTYPE_PARAGRAPH:
262 case MetadataSchema::MDFTYPE_URL:
263 case MetadataSchema::MDFTYPE_TEXT:
264 case MetadataSchema::MDFTYPE_NUMBER:
265 case MetadataSchema::MDFTYPE_DATE:
266 case MetadataSchema::MDFTYPE_TIMESTAMP:
267 case MetadataSchema::MDFTYPE_USER:
268 # if we have no value for this field, skip displaying it
269 if (strlen($TextVal)==0)
270 {
271 continue 2;
272
273 }
274 break;
275
276 case MetadataSchema::MDFTYPE_TREE:
277 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
278 # if we have no value for this field, skip displaying it
279 if (strlen($SearchVal)==0)
280 {
281 continue 2;
282 }
283 break;
284
285 # no need to check the types where there's
286 # a SelectVal, as that cannot be left empty
287 default:
288 break;
289 }
290
291 # extract the value for our field
292 switch ($Field->Type())
293 {
294 case MetadataSchema::MDFTYPE_PARAGRAPH:
295 case MetadataSchema::MDFTYPE_URL:
296 case MetadataSchema::MDFTYPE_TEXT:
297 case MetadataSchema::MDFTYPE_NUMBER:
298 case MetadataSchema::MDFTYPE_DATE:
299 case MetadataSchema::MDFTYPE_TIMESTAMP:
300 $Val = $TextVal;
301 break;
302
303 case MetadataSchema::MDFTYPE_USER:
304 $Val = "=".$TextVal;
305 break;
306
307 case MetadataSchema::MDFTYPE_TREE:
308 $Item = $this->Factories[$FieldId]->GetItem(
309 $SearchVal);
310
311 # for tree fields, use the same 'is X
312 # or a child of X' construction that we
313 # use when generating search facets
314 $Val = new SearchParameterSet();
315 $Val->Logic("OR");
316 $Val->AddParameter(array(
317 "=".$Item->Name(),
318 "^".$Item->Name()." -- "), $Field);
319 break;
320
321 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
322 $Item = $this->Factories[$FieldId]->GetItem(
323 $SearchVal);
324 $Val = "=".$Item->Name();
325 break;
326
327 case MetadataSchema::MDFTYPE_OPTION:
328 $Item = $this->Factories[$FieldId]->GetItem(
329 $SelectVal);
330 $Val = "=".$Item->Name();
331 break;
332
333 case MetadataSchema::MDFTYPE_FLAG:
334 $Val = $SelectVal;
335 break;
336
337 default:
338 throw new Exception("Unsupported field type");
339 }
340 }
341
342 # add our value to the search parameters
343 if ($Val instanceof SearchParameterSet)
344 {
345 end($GroupStack)->AddSet($Val);
346 }
347 else
348 {
349 end($GroupStack)->AddParameter($Val, $Field);
350 }
351 }
352 }
353
354 $Result = array_pop($GroupStack);
355 }
356
357 # set internal search params to the "Display" version, as these
358 # are the ones we shall use for display
359 $this->SearchParams = SPTSearchEngine::ConvertToDisplayParameters($Result);
360 return $Result;
361 }
362
368 public function SearchParameters($SearchParams = NULL)
369 {
370 if ($SearchParams !== NULL)
371 {
372 $this->SearchParams = clone $SearchParams;
373 }
374
375 return clone $this->SearchParams;
376 }
377
378 # ---- PRIVATE INTERFACE -------------------------------------------------
379
380 private $EditFormName;
381 private $SearchParams;
382 private $MFields;
383 private $AllSchemas;
384 private $Factories;
385
397 private function FlattenSearchParams($SearchParams)
398 {
399 $Result = array();
400
401 $Result[]= array(
402 "Logic" => $SearchParams->Logic() );
403
404 $SearchStrings = $SearchParams->GetSearchStrings();
405 foreach ($SearchStrings as $FieldId => $Values)
406 {
407 $Result[]= array(
408 "FieldId" => $FieldId,
409 "Values" => $Values);
410 }
411
412 $KeywordStrings = $SearchParams->GetKeywordSearchStrings();
413 if (count($KeywordStrings))
414 {
415 $Result[]= array(
416 "FieldId" => "X-KEYWORD-X",
417 "Values" => $KeywordStrings);
418 }
419
420 $Subgroups = $SearchParams->GetSubgroups();
421 if (count($Subgroups))
422 {
423 foreach ($Subgroups as $Subgroup)
424 {
425 $Result[]= "(";
426 $SubgroupItems = $this->FlattenSearchParams($Subgroup);
427 foreach ($SubgroupItems as $Item)
428 {
429 $Result[] = $Item;
430 }
431 $Result[]= ")";
432 }
433 }
434
435 return $Result;
436 }
437
442 private function PrintFieldSelector($FieldId)
443 {
444 # field-subject css class required by our javascript
445 print('<select name="'.$this->EditFormName.'[]" '
446 .'class="field-subject">'
447 .'<option class="field-type-keyword" '
448 .($FieldId == "X-KEYWORD-X" ? "selected ":"")
449 .'value="X-KEYWORD-X">Keyword</option>');
450
451 foreach ($this->MFields as $MField)
452 {
453 $TypeName = defaulthtmlentities(
454 str_replace(' ', '', strtolower($MField->TypeAsName())));
455
456 if (!$MField->Optional())
457 {
458 $TypeName .= " required";
459 }
460
461 $FieldName = $MField->Name();
462 if ($MField->SchemaId() != MetadataSchema::SCHEMAID_DEFAULT)
463 {
464 $FieldName = $this->AllSchemas[$MField->SchemaId()]->Name()
465 .": ".$FieldName;
466 }
467
468 print('<option class="field-type-'.$TypeName.'" '
469 .($FieldId == $MField->Id() ? "selected ":"")
470 .'value="'.$MField->Id().'">'
471 .defaulthtmlentities($FieldName).'</option>');
472 }
473 print('</select>');
474 }
475
476
482 private function PrintValueSelector($FieldId, $CurVal)
483 {
484 # field-value-select class required by our javascript
485 print('<select name="'.$this->EditFormName.'[]" '
486 .'class="field-value-select">');
487 foreach ($this->MFields as $MField)
488 {
489 if ($MField->Type() == MetadataSchema::MDFTYPE_FLAG ||
490 $MField->Type() == MetadataSchema::MDFTYPE_OPTION)
491 {
492 foreach ($MField->GetPossibleValues() as $Id => $Val)
493 {
494 $IsSelected = $MField->Id() == $FieldId &&
495 strlen($CurVal) > 1 && $CurVal[0] == "=" &&
496 substr($CurVal, 1) == $Val ;
497
498 print('<option value="'.$Id.'" '
499 .'class="field-id-'.$MField->Id().'" '
500 .($IsSelected ? " selected" : "")
501 .'>'.defaulthtmlentities($Val)
502 .'</option>'."\n");
503 }
504 }
505 }
506 print('</select>');
507 }
508
514 private function PrintQuicksearch($FieldId, $CurVal)
515 {
516 if ($FieldId !== NULL && $FieldId != "X-KEYWORD-X")
517 {
518 if (!isset($this->Factories[$FieldId]))
519 {
520 $Field = new MetadataField($FieldId);
521 $Factory = $Field->GetFactory();
522
523 $this->Factories[$FieldId] =
524 ($Factory !== NULL) ? $Factory : FALSE;
525 }
526
527 $ItemId = ($this->Factories[$FieldId] !== FALSE) ?
528 $this->Factories[$FieldId]->GetItemIdByName($CurVal) : "" ;
529 }
530 else
531 {
532 $ItemId = "";
533 }
534
535 # field-value-qs css class required by our javascript.
536 # various cw-quicksearch classes required by the quicksearch javascript
537 # and ui-front class required by jquery-ui, used by qs js
538 print('<div class="field-value-qs cw-quicksearch '
539 . 'cw-quicksearch-template">'
540 .'<input class="cw-quicksearch-display '
541 .'cw-resourceeditor-metadatafield" '
542 .'placeholder="(enter some text to begin searching)" '
543 .'value="'.defaulthtmlentities($CurVal).'" />'
544 .'<input name="'.$this->EditFormName.'[]" '
545 .'class="cw-quicksearch-value" type="hidden" '
546 .'value="'.defaulthtmlentities($ItemId).'" />'
547 .'<div style="display: none;" '
548 .'class="cw-quicksearch-menu">'
549 .'<div class="cw-quicksearch-message ui-front"></div>'
550 .'</div></div>');
551 }
552
556 private function PrintTemplateRow()
557 {
558 # field-row, template-row, field-value-edit, cw-speui-add, and
559 # cw-speui-add-subgroup css classes required by our javascript
560 print(
561 "<tr class=\"field-row template-row ".$this->EditFormName."\""
562 ." style=\"white-space: nowrap;\">"
563 ."<td>"
564 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
565 ."cw-speui-delete\">X</span>"
566 ."</td><td>");
567 $this->PrintFieldSelector(NULL);
568 $this->PrintValueSelector(NULL, "");
569 print("<input type=\"text\" class=\"field-value-edit\" "
570 ."name=\"".$this->EditFormName."[]\" placeholder=\"(search terms)\" "
571 ."value=\"\">");
572 $this->PrintQuicksearch(NULL, "");
573 print("</td></tr>");
574 print("<tr><td colspan=2>"
575 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
576 ."cw-speui-add\">Add Field</span>"
577 ."<span class=\"cw-button cw-button-elegant cw-button-constrained "
578 ."cw-speui-add-subgroup\">Add Subgroup</span>"
579 ."</td></tr>");
580 }
581 }
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:181
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:368
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
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
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:950
MetadataSchema\MDFTYPE_USER
const MDFTYPE_USER
Definition: MetadataSchema.php:30
MetadataSchema\GetAllSchemas
static GetAllSchemas()
Get all existing metadata schemas.
Definition: MetadataSchema.php:1797
SearchParameterSetEditingUI
Class to create a user interface for editing SearchParameterSets.
Definition: SearchParameterSetEditingUI.php:13