CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

PrivilegeSet.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: PrivilegeSet.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
16 class PrivilegeSet
17 {
18
19 # used as a field ID in conditions to test whether a resources is
20 # available as part of the privilege check
21 const HAVE_RESOURCE = -1;
22
30 public function __construct($Data = NULL)
31 {
32 # if privilege data supplied
33 if ($Data !== NULL)
34 {
35 # if data is in legacy form (an array of privileges)
36 if (is_array($Data))
37 {
38 # set internal privilege set from array
39 $this->Privileges = $Data;
40 }
41 else
42 {
43 # set internal values from data
44 $this->LoadFromData($Data);
45 }
46 }
47 }
48
58 public function Data($NewValue = NULL)
59 {
60 # if new data supplied
61 if ($NewValue !== NULL)
62 {
63 # unpack privilege data and load
64 $this->LoadFromData($NewValue);
65 }
66
67 # serialize current data and return to caller
68 $Data = array();
69 if (count($this->Privileges))
70 {
71 foreach ($this->Privileges as $Priv)
72 {
73 $Data["Privileges"][] = is_object($Priv)
74 ? array("SUBSET" => $Priv->Data())
75 : $Priv;
76 }
77 }
78 $Data["Logic"] = $this->Logic;
79 return serialize($Data);
80 }
81
92 public function MeetsRequirements(CWUser $User, $Resource = self::NO_RESOURCE)
93 {
94 # when there are no requirements, then every user meets them
95 $Satisfied = TRUE;
96
97 # for each privilege requirement
98 foreach ($this->Privileges as $Priv)
99 {
100 # if privilege is actually a privilege subgroup
101 if (is_object($Priv))
102 {
103 # check if the subgroup is satisfied
104 $Satisfied = $Priv->MeetsRequirements($User, $Resource);
105 }
106 # else if privilege is actually a condition
107 elseif (is_array($Priv))
108 {
109 # check if condition is satisfied for the given resource
110 $Satisfied = $this->MeetsCondition($Priv, $Resource, $User);
111 }
112 # else privilege is actually a privilege
113 else
114 {
115 # check if user has the spcified privilege
116 $Satisfied = $User->HasPriv( $Priv );
117 }
118
119 # for AND logic, we can bail as soon as the first
120 # condition is not met
121 if ($this->Logic == "AND")
122 {
123 if (!$Satisfied)
124 {
125 break;
126 }
127 }
128 # conversely, for OR logic, we can bail as soon as any
129 # condition is met
130 else
131 {
132 if ($Satisfied)
133 {
134 break;
135 }
136 }
137 }
138
139 # report result of the test back to caller
140 return $Satisfied;
141 }
142
149 public function AddPrivilege($Privileges)
150 {
151 # convert incoming value to array if needed
152 if (!is_array($Privileges))
153 {
154 $Privileges = array($Privileges);
155 }
156
157 # for each privilege passed in
158 foreach ($Privileges as $Privilege)
159 {
160 # add privilege if not currently in set
161 if (!$this->IncludesPrivilege($Privilege))
162 {
163 if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
164 $this->Privileges[] = $Privilege;
165 }
166 }
167 }
168
175 public function RemovePrivilege($Privilege)
176 {
177 # remove privilege if currently in set
178 if ($this->IncludesPrivilege($Privilege))
179 {
180 if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
181 $Index = array_search($Privilege, $this->Privileges);
182 unset($this->Privileges[$Index]);
183 }
184 }
185
191 public function IncludesPrivilege($Privilege)
192 {
193 # check whether privilege is in our list and report to caller
194 if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
195 return $this->IsInPrivilegeData($Privilege) ? TRUE : FALSE;
196 }
197
206 public function GetPrivilegeInfo()
207 {
208 # grab privilege information and add logic
209 $Info = $this->Privileges;
210 $Info["Logic"] = $this->Logic;
211
212 # return privilege info array to caller
213 return $Info;
214 }
215
222 public function GetPrivilegeList()
223 {
224 # create list of privileges with conditions stripped out
225 $List = array();
226 foreach ($this->Privileges as $Priv)
227 {
228 if (!is_array($Priv)) { $List[] = $Priv; }
229 }
230
231 # return list of privileges to caller
232 return $List;
233 }
234
249 public function AddCondition($Field, $Value = NULL, $Operator = "==")
250 {
251 # get field ID
252 $FieldId = is_object($Field) ? $Field->Id() : $Field;
253
254 # set up condition array
255 $Condition = array(
256 "FieldId" => intval($FieldId),
257 "Operator" => trim($Operator),
258 "Value" => $Value);
259
260 # if condition is not already in set
261 if (!$this->IsInPrivilegeData($Condition))
262 {
263 # add condition to privilege set
264 $this->Privileges[] = $Condition;
265 return TRUE;
266 }
267 return FALSE;
268 }
269
281 public function RemoveCondition($Field, $Value = NULL, $Operator = "==")
282 {
283 # get field ID
284 $FieldId = is_object($Field) ? $Field->Id() : $Field;
285
286 # set up condition array
287 $Condition = array(
288 "FieldId" => intval($FieldId),
289 "Operator" => trim($Operator),
290 "Value" => $Value);
291
292 # if condition is in set
293 if ($this->IsInPrivilegeData($Condition))
294 {
295 # remove condition from privilege set
296 $Index = array_search($Condition, $this->Privileges);
297 unset($this->Privileges[$Index]);
298 return TRUE;
299 }
300 return FALSE;
301 }
302
307 public function AddSet(PrivilegeSet $Set)
308 {
309 # if subgroup is not already in set
310 if (!$this->IsInPrivilegeData($Set))
311 {
312 # add subgroup to privilege set
313 $this->Privileges[] = $Set;
314 }
315 }
316
326 public function AllRequired($NewValue = NULL)
327 {
328 if ($NewValue !== NULL)
329 {
330 $this->Logic = $NewValue ? "AND" : "OR";
331 }
332 return ($this->Logic == "AND") ? TRUE : FALSE;
333 }
334
340 public function PrivilegeFlagsChecked()
341 {
342 $Info = $this->GetPrivilegeInfo();
343 unset ($Info["Logic"]);
344
345 $Result = array();
346 foreach ($Info as $Item)
347 {
348 if (is_object($Item))
349 {
350 $Result = array_merge($Result, $Item->PrivilegeFlagsChecked() );
351 }
352 elseif (!is_array($Item))
353 {
354 $Result[]= $Item;
355 }
356 }
357 return array_unique($Result);
358 }
359
366 public function FieldsWithUserComparisons($ComparisonType)
367 {
368 $Info = $this->GetPrivilegeInfo();
369 unset ($Info["Logic"]);
370
371 $Result = array();
372 foreach ($Info as $Item)
373 {
374 if (is_object($Item))
375 {
376 $Result = array_merge(
377 $Result,
378 $Item->FieldsWithUserComparisons( $ComparisonType ) );
379 }
380 elseif (is_array($Item))
381 {
382 if ($Item["Operator"] == $ComparisonType &&
383 $Item["FieldId"] > 0 )
384 {
385 $Field = new MetadataField($Item["FieldId"]);
386
387 if ($Field->Type() == MetadataSchema::MDFTYPE_USER)
388 {
389 $Result[]= $Item["FieldId"];
390 }
391 }
392 }
393 }
394
395 return array_unique($Result);
396 }
397
398 # ---- PRIVATE INTERFACE -------------------------------------------------
399
400 private $Privileges = array();
401 private $Logic = "OR";
402
403 const NO_RESOURCE = "XXX NO RESOURCE XXX";
404
409 private function LoadFromData($Serialized)
410 {
411 # save calling context in case load causes out-of-memory crash
412 $GLOBALS["AF"]->RecordContextInCaseOfCrash();
413
414 # unpack new data
415 $Data = unserialize($Serialized);
416
417 # unpack privilege data (if available) and load
418 if (array_key_exists("Privileges", $Data))
419 {
420 $this->Privileges = array();
421 foreach ($Data["Privileges"] as $Priv)
422 {
423 if (is_array($Priv) && array_key_exists("SUBSET", $Priv))
424 {
425 $Subset = new PrivilegeSet();
426 $Subset->LoadFromData($Priv["SUBSET"]);
427 $this->Privileges[] = $Subset;
428 }
429 else
430 {
431 $this->Privileges[] = $Priv;
432 }
433 }
434 }
435
436 # load logic if available
437 if (array_key_exists("Logic", $Data))
438 {
439 $this->Logic = $Data["Logic"];
440 }
441 }
442
450 private function MeetsCondition($Condition, $Resource, $User)
451 {
452 # if condition is a check for whether a resource is available
453 if ($Condition["FieldId"] == self::HAVE_RESOURCE)
454 {
455 # return a result based on whether a resource is available
456 return ((bool)($Resource == self::NO_RESOURCE)
457 != (bool)$Condition["Value"]) ? TRUE : FALSE;
458 }
459 # else if no resource is available
460 elseif ($Resource == self::NO_RESOURCE)
461 {
462 # return a result that in effect ignores the condition
463 return ($this->Logic == "AND") ? TRUE : FALSE;
464 }
465 # else if resource is valid
466 elseif ($Resource instanceof Resource)
467 {
468 # pre-process condition parameters based on type of field
469 try
470 {
471 $Field = new MetadataField($Condition["FieldId"]);
472 }
473 catch (Exception $e)
474 {
475 # if the field in a condition was invalid, the condition fails
476 return FALSE;
477 }
478
479 $Operator = $Condition["Operator"];
480 $Value = $Condition["Value"];
481 $FieldValue = $Resource->Get($Field, TRUE);
482 switch ($Field->Type())
483 {
484 case MetadataSchema::MDFTYPE_USER:
485 # if supplied value is NULL
486 if ($Value === NULL)
487 {
488 $Value = $User->Id();
489 }
490
491 # get the UserIds contained in this field
492 $FieldValue = array_keys($FieldValue);
493 break;
494
495 case MetadataSchema::MDFTYPE_DATE:
496 case MetadataSchema::MDFTYPE_TIMESTAMP:
497 # date field values are Date objects, so handle those
498 if ($FieldValue instanceof Date)
499 {
500 $FieldValue = strtotime($FieldValue->Formatted());
501 }
502
503 # timestamp field values are just the date/time string
504 else
505 {
506 $FieldValue = strtotime($FieldValue);
507 }
508
509 # use the current time for the value if it's NULL
510 if ($Value === NULL)
511 {
512 $Value = time();
513 }
514
515 # otherwise, parse the value to get a numeric timestamp
516 else
517 {
518 $Value = strtotime($Value);
519 }
520 break;
521
522 case MetadataSchema::MDFTYPE_NUMBER:
523 case MetadataSchema::MDFTYPE_FLAG:
524 break;
525
526 case MetadataSchema::MDFTYPE_OPTION:
527 # for options, construct a list of the CNIDs in this field
528 $NewValue = array();
529 foreach ($FieldValue as $CName)
530 {
531 $NewValue[]= $CName->Id();
532 }
533 $FieldValue = $NewValue;
534 break;
535
536 default:
537 throw new Exception("Unsupported metadata field type ("
538 .print_r($Field->Type(), TRUE)
539 .") for condition in privilege set.");
540 break;
541 }
542
543 # compare field value and supplied value using specified operator
544 switch ($Operator)
545 {
546 case "==":
547 if (is_array($FieldValue))
548 {
549 # equality against an option field is a 'contains' condition,
550 # true if the specified value is one of those set
551 $Result = FALSE;
552 foreach ($FieldValue as $FieldValue_i)
553 {
554 $Result |= ($FieldValue_i == $Value);
555 }
556 }
557 else
558 {
559 $Result = ($FieldValue == $Value);
560 }
561 break;
562
563 case "!=":
564 if (is_array($FieldValue))
565 {
566 # not equal against an option field is 'does not contains',
567 # true as long as the spcified value is not one of those set
568 $Result = TRUE;
569 foreach ($FieldValue as $FieldValue_i)
570 {
571 $Result &= ($FieldValue_i != $Value);
572 }
573 }
574 else
575 {
576 $Result = ($FieldValue != $Value);
577 }
578 break;
579
580 case "<":
581 $Result = ($FieldValue < $Value);
582 break;
583
584 case ">":
585 $Result = ($FieldValue > $Value);
586 break;
587
588 case "<=":
589 $Result = ($FieldValue <= $Value);
590 break;
591
592 case ">=":
593 $Result = ($FieldValue >= $Value);
594 break;
595
596 default:
597 throw new Exception("Unsupported condition operator ("
598 .print_r($Operator, TRUE).") in privilege set.");
599 break;
600 }
601
602 # report to caller whether condition was met
603 return $Result ? TRUE : FALSE;
604 }
605 else
606 {
607 # error out because resource was illegal
608 throw new Exception("Invalid Resource passed in for privilege"
609 ." set comparison.");
610 }
611 }
612
621 private function IsInPrivilegeData($Item)
622 {
623 # step through privilege data
624 foreach ($this->Privileges as $Priv)
625 {
626 # report to caller if item is found
627 if (is_object($Item))
628 {
629 if (is_object($Priv) && ($Item == $Priv)) { return TRUE; }
630 }
631 elseif (is_array($Item))
632 {
633 if (is_array($Priv) && ($Item == $Priv)) { return TRUE; }
634 }
635 elseif ($Item == $Priv) { return TRUE; }
636 }
637
638 # report to caller that item is not in privilege data
639 return FALSE;
640 }
641 }
MetadataSchema\MDFTYPE_TIMESTAMP
const MDFTYPE_TIMESTAMP
Definition: MetadataSchema.php:25
PrivilegeSet\AddSet
AddSet(PrivilegeSet $Set)
Add subgroup of privileges/conditions to set.
Definition: PrivilegeSet.php:307
MetadataSchema\MDFTYPE_NUMBER
const MDFTYPE_NUMBER
Definition: MetadataSchema.php:23
CWUser\HasPriv
HasPriv($Privilege, $Privileges=NULL)
Determine if a user has a given privilege, or satisfies the conditions specified by a given privilege...
Definition: CWUser.php:104
PrivilegeSet\NO_RESOURCE
const NO_RESOURCE
Definition: PrivilegeSet.php:403
PrivilegeSet
Set of privileges used to access resource information or other parts of the system.
Definition: PrivilegeSet.php:16
PrivilegeSet\MeetsRequirements
MeetsRequirements(CWUser $User, $Resource=self::NO_RESOURCE)
Determine if a given user meets the requirements specified by this PrivilegeSet.
Definition: PrivilegeSet.php:92
Date
Definition: Date.php:18
MetadataSchema\MDFTYPE_OPTION
const MDFTYPE_OPTION
Definition: MetadataSchema.php:29
MetadataSchema\MDFTYPE_FLAG
const MDFTYPE_FLAG
Definition: MetadataSchema.php:26
PrivilegeSet\__construct
__construct($Data=NULL)
Class constructor, used to create a new set or reload an existing set from previously-constructed dat...
Definition: PrivilegeSet.php:30
PrivilegeSet\IncludesPrivilege
IncludesPrivilege($Privilege)
Check whether this privilege set includes the specified privilege.
Definition: PrivilegeSet.php:191
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:206
PrivilegeSet\AddPrivilege
AddPrivilege($Privileges)
Add specified privilege to set.
Definition: PrivilegeSet.php:149
PrivilegeSet\PrivilegeFlagsChecked
PrivilegeFlagsChecked()
List which privilege flags (e.g.
Definition: PrivilegeSet.php:340
PrivilegeSet\GetPrivilegeList
GetPrivilegeList()
Get list of privileges.
Definition: PrivilegeSet.php:222
MetadataField
Object representing a locally-defined type of metadata field.
Definition: MetadataField.php:13
MetadataSchema\MDFTYPE_DATE
const MDFTYPE_DATE
Definition: MetadataSchema.php:24
PrivilegeSet\Data
Data($NewValue=NULL)
Get/set privilege set data, in the form of an opaque string.
Definition: PrivilegeSet.php:58
Resource
Represents a "resource" in CWIS.
Definition: Resource.php:13
MetadataSchema\MDFTYPE_USER
const MDFTYPE_USER
Definition: MetadataSchema.php:30
PrivilegeSet\FieldsWithUserComparisons
FieldsWithUserComparisons($ComparisonType)
List which fields in this privset are involved in UserIs or UserIsNot comparisons for this privilege ...
Definition: PrivilegeSet.php:366
CWUser
CWIS-specific user class.
Definition: CWUser.php:13
PrivilegeSet\AddCondition
AddCondition($Field, $Value=NULL, $Operator="==")
Add condition to privilege set.
Definition: PrivilegeSet.php:249
PrivilegeSet\RemovePrivilege
RemovePrivilege($Privilege)
Remove specified privilege from set.
Definition: PrivilegeSet.php:175
PrivilegeSet\HAVE_RESOURCE
const HAVE_RESOURCE
Definition: PrivilegeSet.php:21
PrivilegeSet\AllRequired
AllRequired($NewValue=NULL)
Get/set whether all privileges/conditions in set are required (i.e.
Definition: PrivilegeSet.php:326
PrivilegeSet\RemoveCondition
RemoveCondition($Field, $Value=NULL, $Operator="==")
Remove condition from privilege set.
Definition: PrivilegeSet.php:281