CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

PrivilegeEditingUI.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: PrivilegeEditingUI.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2015-2016 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
14 class PrivilegeEditingUI
15 {
26 public function __construct($Schemas = NULL, $MetadataFields = array())
27 {
28 $this->Fields = array();
29
30 # if Schemas was NULL, use all schemas
31 if ($Schemas === NULL)
32 {
33 $Schemas = MetadataSchema::GetAllSchemas();
34 }
35 else
36 {
37 # ensure incoming value is an array
38 if (!is_array($Schemas))
39 {
40 $Schemas = array($Schemas);
41 }
42
43 # if we have an array of ints, convert to an array of MetadataSchema objects
44 if (is_numeric(reset($Schemas)))
45 {
46 $NewSchemas = array();
47 foreach ($Schemas as $SchemaId)
48 {
49 $NewSchemas[$SchemaId] = new MetadataSchema($SchemaId);
50 }
51 $Schemas = $NewSchemas;
52 }
53 }
54
55 # ensure incoming value is an array
56 if (!is_array($MetadataFields))
57 {
58 $MetadataFields = array($MetadataFields);
59 }
60
61 # if we have an array of ints, convert to an array of MetadataField objects
62 if (is_numeric(reset($MetadataFields)))
63 {
64 $NewMetadataFields = array();
65 foreach ($MetadataFields as $FieldId)
66 {
67 $NewMetadataFields[$FieldId] = new MetadataField($FieldId);
68 }
69 $MetadataFields = $NewMetadataFields;
70 }
71
72 # types we support, in the order they should be displayed
73 $SupportedFieldTypesInOrder = array(
74 MetadataSchema::MDFTYPE_USER,
75 MetadataSchema::MDFTYPE_FLAG,
76 MetadataSchema::MDFTYPE_OPTION,
77 MetadataSchema::MDFTYPE_TIMESTAMP,
78 MetadataSchema::MDFTYPE_NUMBER);
79
80 # add all requested Schemas
81 foreach ($Schemas as $SchemaId => $Schema)
82 {
83 # iterate over the supported types so that fields are
84 # returned grouped by type
85 foreach ($SupportedFieldTypesInOrder as $Type)
86 {
87 $this->Fields += $Schema->GetFields($Type);
88 }
89 }
90
91 # and add requested fields
92 foreach ($MetadataFields as $FieldId => $Field)
93 {
94 if (!in_array($Field->Type(), $SupportedFieldTypesInOrder))
95 {
96 throw new Exception(
97 "Field ".$Field->Name()." (Id=".$Field->Id().")"
98 ." is invalid for PrivilegeEditing -- ".$Field->TypeAsName()
99 ." fields are not supported.");
100 }
101 $this->Fields[$FieldId] = $Field;
102 }
103 }
104
111 public function DisplaySet($Identifier, PrivilegeSet $PrivilegeSet,
112 $IsNested = FALSE)
113 {
114 # include needed JavaScript
115 $GLOBALS["AF"]->RequireUIFile(__CLASS__.".js");
116
117 # build form field prefix
118 $FFPrefix = "F_Priv_".$Identifier."_";
119
120 # retrieve privilege info as an array
121 $PrivilegeInfo = $PrivilegeSet->GetPrivilegeInfo();
122
123 # add "Top-Level Logic" option list if we are at the top of the hierarchy
124 if (!$IsNested)
125 {
126 $Logic = $PrivilegeInfo["Logic"];
127
128 print '<div class="priv-set">'
129 .'<fieldset class="priv-fieldset priv-logic">'
130 .'<label for="'.$FFPrefix.'Logic">Top-Level Logic:</label>';
131
132 $OptList = new HtmlOptionList($FFPrefix."Logic",
133 array("AND" => "AND", "OR" => "OR"), $Logic);
134 $OptList->PrintHtml();
135
136 print '</fieldset>';
137 }
138
139 # discard logic so that the rest of the array can be iterated over
140 unset($PrivilegeInfo["Logic"]);
141
142 # if there are no conditions set
143 if (count($PrivilegeInfo) == 0)
144 {
145 # print out message indicating no conditions yet set
146 print("<i>(no requirements)</i><br/>");
147 }
148 else
149 {
150 # print out each condition
151 foreach ($PrivilegeInfo as $Condition)
152 {
153 ?>
154 <fieldset class="priv-fieldset cw-peui-fieldset">
155 <?PHP
156
157 # if condition tests against a user privilege
158 if (is_numeric($Condition))
159 {
160 $this->DisplaySubjectField($FFPrefix, "current_user");
161 $this->DisplayOperatorField($FFPrefix);
162 $this->DisplayValueField($FFPrefix, $Condition);
163 }
164 # else if condition tests against a metadata field value
165 else if (is_array($Condition))
166 {
167 $this->DisplaySubjectField($FFPrefix, $Condition["FieldId"]);
168 $this->DisplayOperatorField($FFPrefix, $Condition["Operator"]);
169
170 try
171 {
172 $Field = new MetadataField($Condition["FieldId"]);
173 }
174 catch (Exception $e)
175 {
176 # do nothing here, but we'd like to continue
177 }
178
179 if (isset($Field) && $Field->Type() == MetadataSchema::MDFTYPE_OPTION)
180 {
181 # Option fields use the selector menu, rather than a
182 # form field.
183 # Values are ControlledName Ids, prefixed with a "C"
184 # to distinguish them from privilge flag numbers.
185 $this->DisplayValueField($FFPrefix,
186 "C".$Condition["Value"], "NULL");
187 }
188 else
189 {
190 $this->DisplayValueField($FFPrefix, NULL, $Condition["Value"]);
191 }
192 }
193 # else if condition is a privilege subset
194 else if ($Condition instanceof PrivilegeSet)
195 {
196 $this->DisplaySubjectField($FFPrefix, "set_entry");
197 $this->DisplayOperatorField($FFPrefix);
198 $this->DisplayValueField($FFPrefix,
199 $Condition->AllRequired() ? "AND" : "OR");
200
201 # end the fieldset for the set entry row
202 ?></fieldset><?PHP
203
204 # print the nested fields
205 $this->DisplaySet($Identifier, $Condition, TRUE);
206
207 # begin a new fieldset for the set exit row
208 ?><fieldset class="priv-fieldset cw-peui-fieldset"><?PHP
209
210 $this->DisplaySubjectField($FFPrefix, "set_exit");
211 $this->DisplayOperatorField($FFPrefix);
212 $this->DisplayValueField($FFPrefix);
213 }
214
215 ?></fieldset><?PHP
216 }
217 }
218
219 # if we are at the top level
220 if (!$IsNested)
221 {
222 $NumBlankRows = 6;
223
224 # print a number of blank rows to be used if JavaScript is disabled
225 for ($Index = 0; $Index < $NumBlankRows; $Index++)
226 {
227 ?><fieldset class="priv-fieldset cw-peui-fieldset priv-extra"><?PHP
228 $this->DisplaySubjectField($FFPrefix);
229 $this->DisplayOperatorField($FFPrefix);
230 $this->DisplayValueField($FFPrefix);
231 ?></fieldset><?PHP
232 }
233
234 # print a blank row for cloning within JavaScript
235 ?><fieldset class="priv-fieldset cw-peui-fieldset priv-js-clone_target"><?PHP
236 $this->DisplaySubjectField($FFPrefix);
237 $this->DisplayOperatorField($FFPrefix);
238 $this->DisplayValueField($FFPrefix);
239 ?></fieldset><?PHP
240
241 # print the button to add a new row when using JavaScript
242 ?><button class="cw-button cw-button-elegant cw-button-constrained
243 priv-js-add">Add Condition</button>
244 <?PHP
245
246 # print the closing div for the set
247 ?></div><?PHP
248 }
249 }
250
255 public function GetPrivilegeSetsFromForm()
256 {
257 # for each form field
258 $Sets = array();
259 $Logics = array();
260 foreach ($_POST as $FieldName => $FieldValue)
261 {
262 # if field looks like privilege set data
263 if (preg_match("/^F_Priv_/", $FieldName))
264 {
265 # extract identifier from field name
266 $Pieces = explode("_", $FieldName);
267 $Identifier = $Pieces[2];
268
269 # if field looks like privilege set top-level logic
270 if (preg_match("/_Logic\$/", $FieldName))
271 {
272 # save logic for later use
273 $Logics[$Identifier] = $FieldValue;
274 }
275 else
276 {
277 # retrieve privilege set from field
278 $Sets[$Identifier] =
279 $this->ExtractPrivilegeSetFromFormData($FieldValue);
280 }
281 }
282 }
283
284 # for each top-level logic found
285 foreach ($Logics as $Identifier => $Logic)
286 {
287 # if no corresponding privilege set was found
288 if (!isset($Sets[$Identifier]))
289 {
290 # load empty set for this identifier
291 $Sets[$Identifier] = new PrivilegeSet();
292 }
293
294 # set logic in corresponding privilege set
295 $Sets[$Identifier]->AllRequired(($Logic == "AND") ? TRUE : FALSE);
296 }
297
298 # return any privilege sets found to caller
299 return $Sets;
300 }
301
308 public function GetPrivilegeSetFromForm($Identifier)
309 {
310 $Sets = $this->GetPrivilegeSetsFromForm();
311 return isset($Sets[$Identifier]) ? $Sets[$Identifier] : FALSE;
312 }
313
314 # ---- PRIVATE INTERFACE -------------------------------------------------
315
316 private $Fields;
317 private $OptionValues;
318
326 private function DisplaySubjectField($FFPrefix, $Selected=NULL)
327 {
328 # construct the list of options to present for this field
329 # present all the metadata fields using their FieldIds
330 $ValidSelections = array_keys($this->Fields);
331
332 # represent other elements as strings, which need to match the
333 # values in GetPrivilegeSetFromFormData()
334 $ValidSelections[] = "current_user";
335 $ValidSelections[] = "set_entry";
336 $ValidSelections[] = "set_exit";
337
338 $AllSchemas = MetadataSchema::GetAllSchemas();
339
340 # construct 2d array of our fields keyed by schemaid
341 $Fields = array();
342 foreach ($this->Fields as $Id => $Field)
343 {
344 $Fields[$Field->SchemaId()][$Id]= $Field;
345 }
346
347 # build up the list options to included
348 $Options = array();
349 $OptionCSS = array();
350
351 foreach ($Fields as $ScId => $ScFields)
352 {
353 $FieldOptions = array();
354 foreach ($ScFields as $Id => $Field)
355 {
356 $SafeClassType = strtolower($Field->TypeAsName());
357 $FieldOptions[$Id] = "[".$AllSchemas[$ScId]->AbbreviatedName()."] "
358 .$Field->GetDisplayName();
359 $OptionCSS[$Id] = "priv priv-option priv-field-subject "
360 ."priv-type-".$SafeClassType."_field";
361 }
362
363 $OptLabel = $AllSchemas[$ScId]->Name();
364 $Options[$OptLabel] = $FieldOptions;
365 }
366
367 # add Current User entry
368 $Options["current_user"] = "Current User";
369 $OptionCSS["current_user"] = "priv priv-option priv-field-subject "
370 ."priv-type-privilege";
371
372 # add subgroup begin marker
373 $Options["set_entry"] = "(";
374 $OptionCSS["set_entry"] = "priv priv-option priv-field-subject "
375 ."priv-type-set_entry";
376
377 # add subgroup end marker
378 $Options["set_exit"] = ")";
379 $OptionCSS["set_exit"] = "priv priv-option priv-field-subject "
380 ."priv-type-set_exit";
381
382 # check if the data we were given contains an invalid field,
383 # and if so complain
384 if (!is_null($Selected) && !in_array($Selected, $ValidSelections, TRUE))
385 {
386 $Options[$Selected] = "INVALID FIELD";
387 $OptionCSS[$Selected] = "priv priv-option priv-field-subject "
388 ."priv-type-user_field";
389 }
390
391
392 $OptionList = new HtmlOptionList($FFPrefix."[]", $Options, $Selected);
393 $OptionList->ClassForOptions($OptionCSS);
394 $OptionList->ClassForList(
395 "priv priv-field priv-select priv-field-subject priv-type-user_field "
396 ."priv-type-flag_field priv-type-option_field priv-type-timestamp_field "
397 ."priv-type-date_field priv-type-number_field priv-type-set_entry "
398 ."priv-type-set_exit");
399
400 $OptionList->PrintHtml();
401 }
402
408 private function DisplayOperatorField($FFPrefix, $Selected=NULL)
409 {
410 $Options = array();
411 $OptionCSS = array();
412 $CommonStyles = "priv priv-option priv-field-operator";
413
414 # use css styles on each option to indicate which fields it applies to
415
416 # equal and not equal work for User, Flag, Option, and Number fields
417 foreach (array("==", "!=") as $Op)
418 {
419 $Options[$Op] = $Op;
420 $OptionCSS[$Op] = $CommonStyles." priv-type-user_field "
421 ."priv-type-flag_field priv-type-option_field priv-type-number_field";
422 }
423
424 # less and greater work for Timestamp, Date, and Number fields
425 foreach (array("<", ">") as $Op)
426 {
427 $Options[$Op] = $Op;
428 $OptionCSS[$Op] = $CommonStyles
429 ." priv-type-timestamp_field priv-type-date_field priv-type-number_field";
430 }
431
432 $OptionList = new HtmlOptionList($FFPrefix."[]", $Options, $Selected);
433 $OptionList->ClassForOptions($OptionCSS);
434 $OptionList->ClassForList(
435 "priv priv-field priv-select priv-field-operator priv-type-user_field "
436 ."priv-type-flag_field priv-type-option_field priv-type-timestamp_field "
437 ."priv-type-date_field priv-type-number_field");
438
439 $OptionList->PrintHtml();
440 }
441
448 private function DisplayValueField($FFPrefix, $Selected=NULL, $Value=NULL)
449 {
450 $this->PrintPrivilegeValueSelectorField($FFPrefix, $Selected);
451 $this->PrintPrivilegeValueInputField($FFPrefix, $Value);
452 }
453
465 private function ExtractPrivilegeSetFromFormData(array &$FormData)
466 {
467 $NewPrivilegeSet = new PrivilegeSet();
468 $Privileges = $this->GetPrivileges();
469 $SupportedOperators = array("==", "!=", "<", ">");
470
471 while (count($FormData))
472 {
473 # extract the form fields
474 $SubjectField = array_shift($FormData);
475 $OperatorField = array_shift($FormData);
476 $ValueSelectField = array_shift($FormData);
477 $ValueInputField = array_shift($FormData);
478
479 # privilege condition
480 if ($SubjectField == "current_user")
481 {
482 # invalid privilege ID
483 if (!isset($Privileges[$ValueSelectField])
484 || is_null($ValueSelectField))
485 {
486 throw new Exception("Invalid privilege (".$ValueSelectField.")");
487 }
488
489 $NewPrivilegeSet->AddPrivilege($ValueSelectField);
490 }
491
492 # metadata field condition
493 else if (is_numeric($SubjectField))
494 {
495 # invalid field ID
496 if (!isset($this->Fields[$SubjectField]) || is_null($SubjectField))
497 {
498 throw new Exception("Invalid or unsupported field ("
499 .$SubjectField.")");
500 }
501
502 # invalid operator
503 if (!in_array($OperatorField, $SupportedOperators))
504 {
505 throw new Exception("Invalid or unsupported operator ("
506 .$OperatorField.")");
507 }
508
509 $MetadataField = $this->Fields[$SubjectField];
510
511 switch ($MetadataField->Type())
512 {
513 case MetadataSchema::MDFTYPE_USER:
514 $Value = NULL;
515 break;
516
517 case MetadataSchema::MDFTYPE_FLAG:
518 $Value = 1;
519 break;
520
521 case MetadataSchema::MDFTYPE_TIMESTAMP:
522 case MetadataSchema::MDFTYPE_DATE:
523 case MetadataSchema::MDFTYPE_NUMBER:
524 $Value = $ValueInputField;
525 break;
526
527 case MetadataSchema::MDFTYPE_OPTION:
528 # strip the "C" prefix used to distinguish controlled
529 # names from priv flags
530 $Value = intval( substr( $ValueSelectField, 1));
531 break;
532
533 default:
534 $Value = NULL;
535 break;
536 }
537
538 $NewPrivilegeSet->AddCondition($MetadataField, $Value, $OperatorField);
539 }
540
541 # entering a nested privilege set
542 else if ($SubjectField == "set_entry")
543 {
544 # the logic is invalid
545 if ($ValueSelectField != "AND" && $ValueSelectField != "OR")
546 {
547 throw new Exception("Invalid privilege set logic ("
548 .$ValueSelectField.")");
549 }
550
551 $NestedPrivilegeSet = $this->ExtractPrivilegeSetFromFormData($FormData);
552
553 # only add the nested privilege set if it's not empty. use 1
554 # because the logic is in the privilege info array
555 if (count($NestedPrivilegeSet->GetPrivilegeInfo()) > 1)
556 {
557 $NestedPrivilegeSet->AllRequired($ValueSelectField == "AND");
558 $NewPrivilegeSet->AddSet($NestedPrivilegeSet);
559 }
560 }
561
562 # exiting a privilege set
563 else if ($SubjectField == "set_exit")
564 {
565 break;
566 }
567
568 # unknown condition type
569 else
570 {
571 throw new Exception("Unknown condition type: ".$SubjectField);
572 }
573 }
574
575 return $NewPrivilegeSet;
576 }
577
583 private function PrintPrivilegeValueSelectorField($FFPrefix, $Selected=NULL)
584 {
585 # build up the list of options
586 $Options = array();
587 $OptionCSS = array();
588 $OptionData = array();
589
590 # add entries for each user privilege flag
591 $Privileges = $this->GetPrivileges();
592 foreach ($Privileges as $Id => $Privilege)
593 {
594 $Options[$Id] = $Privilege->Name();
595 $OptionCSS[$Id] = "priv priv-option priv-field-value priv-type-privilege";
596 }
597
598 $OptionValues = $this->GetOptionValuesForPrivset();
599 foreach ($OptionValues as $FieldId => $Values)
600 {
601 foreach ($Values as $CNId => $CName)
602 {
603 $Options["C".$CNId] = $CName;
604 $OptionCSS["C".$CNId] = "priv priv-option priv-field-value "
605 ."priv-type-option_field";
606 $OptionData["C".$CNId]["field-id"] = $FieldId;
607 }
608 }
609
610 $Options["AND"] = "AND";
611 $OptionCSS["AND"] = "priv priv-option priv-field-value priv-type-set_entry";
612
613 $Options["OR"] = "OR";
614 $OptionCSS["OR"] = "priv priv-option priv-field-value priv-type-set_entry";
615
616 $OptionList = new HtmlOptionList($FFPrefix."[]", $Options, $Selected);
617 $OptionList->ClassForOptions($OptionCSS);
618 $OptionList->DataForOptions($OptionData);
619 $OptionList->ClassForList(
620 "priv priv-field priv-select priv-field-value priv-type-option_field "
621 ."priv-type-privilege priv-type-set_entry priv-type-set_exit");
622
623 $OptionList->PrintHtml();
624 }
625
631 private function PrintPrivilegeValueInputField($FFPrefix, $Value=NULL)
632 {
633 $SafeValue = defaulthtmlentities($Value);
634 ?>
635 <input name="<?PHP print $FFPrefix; ?>[]"
636 type="text"
637 class="priv priv-field priv-input priv-field-value
638 priv-type-timestamp_field priv-type-date_field
639 priv-type-number_field"
640 value="<?PHP print $SafeValue; ?>" />
641 <?PHP
642 }
643
650 private function GetOptionValuesForPrivset()
651 {
652 if (!isset($this->OptionValues))
653 {
654 $this->OptionValues = array();
655
656 foreach ($this->Fields as $FieldId => $Field)
657 {
658 if ($Field->Type() == MetadataSchema::MDFTYPE_OPTION)
659 {
660 $this->OptionValues[$Field->Id()] = $Field->GetPossibleValues();
661 }
662 }
663 }
664
665 return $this->OptionValues;
666 }
667
672 private function GetPrivileges()
673 {
674 static $Privileges;
675
676 if (!isset($Privileges))
677 {
678 $PrivilegeFactory = new PrivilegeFactory();
679 $Privileges = $PrivilegeFactory->GetPrivileges();
680 }
681
682 return $Privileges;
683 }
684 }
MetadataSchema\MDFTYPE_TIMESTAMP
const MDFTYPE_TIMESTAMP
Definition: MetadataSchema.php:25
MetadataSchema
Metadata schema (in effect a Factory class for MetadataField).
Definition: MetadataSchema.php:13
PrivilegeFactory
Factory which extracts all defined privileges from the database.
Definition: PrivilegeFactory.php:14
MetadataSchema\MDFTYPE_NUMBER
const MDFTYPE_NUMBER
Definition: MetadataSchema.php:23
PrivilegeEditingUI\GetPrivilegeSetFromForm
GetPrivilegeSetFromForm($Identifier)
Retrieve privilege set from specified form ($_POST) data fields.
Definition: PrivilegeEditingUI.php:308
PrivilegeEditingUI
User interface element for editing PrivilegeSets.
Definition: PrivilegeEditingUI.php:14
PrivilegeEditingUI\__construct
__construct($Schemas=NULL, $MetadataFields=array())
Constructor for privilege editing UI.
Definition: PrivilegeEditingUI.php:26
PrivilegeSet
Set of privileges used to access resource information or other parts of the system.
Definition: PrivilegeSet.php:16
MetadataSchema\MDFTYPE_OPTION
const MDFTYPE_OPTION
Definition: MetadataSchema.php:29
PrivilegeEditingUI\GetPrivilegeSetsFromForm
GetPrivilegeSetsFromForm()
Construct new privilege sets from available form ($_POST) data.
Definition: PrivilegeEditingUI.php:255
MetadataSchema\MDFTYPE_FLAG
const MDFTYPE_FLAG
Definition: MetadataSchema.php:26
PHP
PHP
Definition: RSSClient--Test.php:12
PrivilegeSet\GetPrivilegeInfo
GetPrivilegeInfo()
Get privilege information as an array, with numerical indexes except for the logic, which is contained in a element with the index "Logic".
Definition: PrivilegeSet.php:210
MetadataField
Object representing a locally-defined type of metadata field.
Definition: MetadataField.php:13
MetadataSchema\MDFTYPE_DATE
const MDFTYPE_DATE
Definition: MetadataSchema.php:24
MetadataSchema\MDFTYPE_USER
const MDFTYPE_USER
Definition: MetadataSchema.php:30
PrivilegeEditingUI\DisplaySet
DisplaySet($Identifier, PrivilegeSet $PrivilegeSet, $IsNested=FALSE)
Display interface for editing specified privilege set.
Definition: PrivilegeEditingUI.php:111
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