CWIS Developer Documentation
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  # used as a field ID in conditions to test whether a resources is
19  # available as part of the privilege check
20  const HAVE_RESOURCE = -1;
21 
29  function __construct($Data = NULL)
30  {
31  # if privilege data supplied
32  if ($Data !== NULL)
33  {
34  # if data is in legacy form (an array of privileges)
35  if (is_array($Data))
36  {
37  # set internal privilege set from array
38  $this->Privileges = $Data;
39  }
40  else
41  {
42  # set internal values from data
43  $this->LoadFromData($Data);
44  }
45  }
46  }
47 
57  function Data($NewValue = NULL)
58  {
59  # if new data supplied
60  if ($NewValue !== NULL)
61  {
62  # unpack privilege data and load
63  $this->LoadFromData($NewValue);
64  }
65 
66  # serialize current data and return to caller
67  $Data = array();
68  if (count($this->Privileges))
69  {
70  foreach ($this->Privileges as $Priv)
71  {
72  $Data["Privileges"][] = is_object($Priv)
73  ? array("SUBSET" => $Priv->Data())
74  : $Priv;
75  }
76  }
77  if ($this->UserId !== NULL) { $Data["UserId"] = $this->UserId; }
78  $Data["Logic"] = $this->Logic;
79  return serialize($Data);
80  }
81 
93  function IsGreaterThan(PrivilegeSet $Set, $Resource = self::NO_RESOURCE)
94  {
95  # if target set has no requirements then we must be greater
96  if (!count($Set->Privileges)) { return TRUE; }
97 
98  # for each privilege in target set
99  foreach ($Set->Privileges as $Priv)
100  {
101  # if privilege is actually a privilege subgroup
102  if (is_object($Priv))
103  {
104  # check if our privileges are greater than subgroup
105  $OursGreater = $this->IsGreaterThan($Priv, $Resource);
106  }
107  # else if privilege is actually a condition
108  elseif (is_array($Priv))
109  {
110  # check if privilege set meets that condition
111  $OursGreater = $this->MeetsCondition($Priv, $Resource, $Set->Logic);
112  }
113  # else privilege is actually a privilege
114  else
115  {
116  # check we have specified privilege
117  $OursGreater = $this->IncludesPrivilege($Priv);
118  }
119 
120  # if either set requires that all privileges must be greater
121  if (($this->Logic == "AND") || ($Set->Logic == "AND"))
122  {
123  # if our privileges were not greater
124  if (!$OursGreater)
125  {
126  # bail out and report to caller that our privileges are not greater
127  break;
128  }
129  }
130  # else if only one privilege must be greater
131  else
132  {
133  # if our privileges were greater
134  if ($OursGreater)
135  {
136  # bail out and report to caller that our privileges are greater
137  break;
138  }
139  }
140  }
141 
142  # all privileges must have been greater (if all required) or none of
143  # the privileges were greater (if only one required)
144  # so report accordingly to caller
145  return $OursGreater;
146  }
147 
156  function IsLessThan(PrivilegeSet $Set, Resource $Resource = NULL)
157  {
158  # just return inverse of IsGreaterThan()
159  return $this->IsGreaterThan($Set, $Resource) ? FALSE : TRUE;
160  }
161 
168  function AddPrivilege($Privilege)
169  {
170  # add privilege if not currently in set
171  if (!$this->IncludesPrivilege($Privilege))
172  {
173  if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
174  $this->Privileges[] = $Privilege;
175  }
176  }
177 
184  function RemovePrivilege($Privilege)
185  {
186  # remove privilege if currently in set
187  if ($this->IncludesPrivilege($Privilege))
188  {
189  if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
190  $Index = array_search($Privilege, $this->Privileges);
191  unset($this->Privileges[$Index]);
192  }
193  }
194 
200  function IncludesPrivilege($Privilege)
201  {
202  # check whether privilege is in our list and report to caller
203  if (is_object($Privilege)) { $Privilege = $Privilege->Id(); }
204  return $this->IsInPrivilegeData($Privilege) ? TRUE : FALSE;
205  }
206 
215  function GetPrivilegeInfo()
216  {
217  # grab privilege information and add logic
218  $Info = $this->Privileges;
219  $Info["Logic"] = $this->Logic;
220 
221  # return privilege info array to caller
222  return $Info;
223  }
224 
231  function GetPrivilegeList()
232  {
233  # create list of privileges with conditions stripped out
234  $List = array();
235  foreach ($this->Privileges as $Priv)
236  {
237  if (!is_array($Priv)) { $List[] = $Priv; }
238  }
239 
240  # return list of privileges to caller
241  return $List;
242  }
243 
258  function AddCondition($Field, $Value = NULL, $Operator = "==")
259  {
260  # get field ID
261  $FieldId = is_object($Field) ? $Field->Id() : $Field;
262 
263  # set up condition array
264  $Condition = array(
265  "FieldId" => intval($FieldId),
266  "Operator" => trim($Operator),
267  "Value" => $Value);
268 
269  # if condition is not already in set
270  if (!$this->IsInPrivilegeData($Condition))
271  {
272  # add condition to privilege set
273  $this->Privileges[] = $Condition;
274  }
275  }
276 
288  function RemoveCondition($Field, $Value = NULL, $Operator = "==")
289  {
290  # get field ID
291  $FieldId = is_object($Field) ? $Field->Id() : $Field;
292 
293  # set up condition array
294  $Condition = array(
295  "FieldId" => intval($FieldId),
296  "Operator" => trim($Operator),
297  "Value" => $Value);
298 
299  # if condition is in set
300  if ($this->IsInPrivilegeData($Condition))
301  {
302  # remove condition from privilege set
303  $Index = array_search($Condition, $this->Privileges);
304  unset($this->Privileges[$Index]);
305  }
306  }
307 
312  function AddSet(PrivilegeSet $Set)
313  {
314  # if subgroup is not already in set
315  if (!$this->IsInPrivilegeData($Set))
316  {
317  # add subgroup to privilege set
318  $this->Privileges[] = $Set;
319  }
320  }
321 
331  function AllRequired($NewValue = NULL)
332  {
333  if ($NewValue !== NULL)
334  {
335  $this->Logic = $NewValue ? "AND" : "OR";
336  }
337  return ($this->Logic == "AND") ? TRUE : FALSE;
338  }
339 
346  function AssociatedUserId($NewValue = NULL)
347  {
348  # if new associated user specified
349  if ($NewValue !== NULL)
350  {
351  # save ID of new associated user
352  $this->UserId = $NewValue;
353  }
354 
355  # return ID of currently associated user to caller
356  return $this->UserId;
357  }
358 
359 
360  # ---- PRIVATE INTERFACE -------------------------------------------------
361 
362  private $Privileges = array();
363  private $Logic = "OR";
364  private $UserId = NULL;
365 
366  const NO_RESOURCE = "XXX NO RESOURCE XXX";
367 
372  private function LoadFromData($Serialized)
373  {
374  # save calling context in case load causes out-of-memory crash
375  $GLOBALS["AF"]->RecordContextInCaseOfCrash();
376 
377  # unpack new data
378  $Data = unserialize($Serialized);
379 
380  # unpack privilege data (if available) and load
381  if (array_key_exists("Privileges", $Data))
382  {
383  $this->Privileges = array();
384  foreach ($Data["Privileges"] as $Priv)
385  {
386  if (is_array($Priv) && array_key_exists("SUBSET", $Priv))
387  {
388  $Subset = new PrivilegeSet();
389  $Subset->LoadFromData($Priv["SUBSET"]);
390  $this->Privileges[] = $Subset;
391  }
392  else
393  {
394  $this->Privileges[] = $Priv;
395  }
396  }
397  }
398 
399  # load associated user ID if available
400  if (array_key_exists("UserId", $Data))
401  {
402  $this->UserId = $Data["UserId"];
403  }
404 
405  # load logic if available
406  if (array_key_exists("Logic", $Data))
407  {
408  $this->Logic = $Data["Logic"];
409  }
410  }
411 
420  private function MeetsCondition($Condition, $Resource, $Logic)
421  {
422  # if condition is a check for whether a resource is available
423  if ($Condition["FieldId"] == self::HAVE_RESOURCE)
424  {
425  # return a result based on whether a resource is available
426  return ((bool)($Resource == self::NO_RESOURCE)
427  != (bool)$Condition["Value"]) ? TRUE : FALSE;
428  }
429  # else if no resource is available
430  elseif ($Resource == self::NO_RESOURCE)
431  {
432  # return a result that in effect ignores the condition
433  return ($Logic == "AND") ? TRUE : FALSE;
434  }
435  # else if resource is valid
436  elseif ($Resource instanceof Resource)
437  {
438  # pre-process condition parameters based on type of field
439  try
440  {
441  $Field = new MetadataField($Condition["FieldId"]);
442  }
443  catch (Exception $e)
444  {
445  # if the field in a condition was invalid, the condition fails
446  return FALSE;
447  }
448 
449  $Operator = $Condition["Operator"];
450  $Value = $Condition["Value"];
451  $FieldValue = $Resource->Get($Field, TRUE);
452  switch ($Field->Type())
453  {
455  # if supplied value is NULL
456  if ($Value === NULL)
457  {
458  # if local associated user ID is available
459  if ($this->UserId !== NULL)
460  {
461  # use ID of associated user
462  $Value = $this->UserId;
463  }
464  # else if global user ID available
465  elseif ($GLOBALS["G_User"]->IsLoggedIn())
466  {
467  # use global user ID
468  $Value = $GLOBALS["G_User"]->Id();
469  }
470  else
471  {
472  # report to caller that condition was not met
473  return FALSE;
474  }
475  }
476 
477  # convert field value to user ID
478  $FieldValue = $FieldValue->Id();
479  break;
480 
483  # date field values are Date objects, so handle those
484  if ($FieldValue instanceof Date)
485  {
486  $FieldValue = strtotime($FieldValue->Formatted());
487  }
488 
489  # timestamp field values are just the date/time string
490  else
491  {
492  $FieldValue = strtotime($FieldValue);
493  }
494 
495  # use the current time for the value if it's NULL
496  if ($Value === NULL)
497  {
498  $Value = time();
499  }
500 
501  # otherwise, parse the value to get a numeric timestamp
502  else
503  {
504  $Value = strtotime($Value);
505  }
506  break;
507 
510  break;
511 
513  # for options, construct a list of the CNIDs in this field
514  $NewValue = array();
515  foreach ($FieldValue as $CName)
516  {
517  $NewValue []= $CName->Id();
518  }
519  $FieldValue = $NewValue;
520  break;
521 
522  default:
523  throw new Exception("Unsupported metadata field type ("
524  .print_r($Field->Type(), TRUE)
525  .") for condition in privilege set.");
526  break;
527  }
528 
529  # compare field value and supplied value using specified operator
530  switch ($Operator)
531  {
532  case "==":
533  if (is_array($FieldValue))
534  {
535  # equality against an option field is a 'contains' condition,
536  # true if the specified value is one of those set
537  $Result = FALSE;
538  foreach ($FieldValue as $FieldValue_i)
539  {
540  $Result |= ($FieldValue_i == $Value);
541  }
542  }
543  else
544  {
545  $Result = ($FieldValue == $Value);
546  }
547  break;
548 
549  case "!=":
550  if (is_array($FieldValue))
551  {
552  # not equal against an option field is 'does not contains',
553  # true as long as the spcified value is not one of those set
554  $Result = TRUE;
555  foreach ($FieldValue as $FieldValue_i)
556  {
557  $Result &= ($FieldValue_i != $Value);
558  }
559  }
560  else
561  {
562  $Result = ($FieldValue != $Value);
563  }
564  break;
565 
566  case "<":
567  $Result = ($FieldValue < $Value);
568  break;
569 
570  case ">":
571  $Result = ($FieldValue > $Value);
572  break;
573 
574  case "<=":
575  $Result = ($FieldValue <= $Value);
576  break;
577 
578  case ">=":
579  $Result = ($FieldValue >= $Value);
580  break;
581 
582  default:
583  throw new Exception("Unsupported condition operator ("
584  .print_r($Operator, TRUE).") in privilege set.");
585  break;
586  }
587 
588  # report to caller whether condition was met
589  return $Result ? TRUE : FALSE;
590  }
591  else
592  {
593  # error out because resource was illegal
594  throw new Exception("Invalid Resource passed in for privilege"
595  ." set comparison.");
596  }
597  }
598 
607  private function IsInPrivilegeData($Item)
608  {
609  # step through privilege data
610  foreach ($this->Privileges as $Priv)
611  {
612  # report to caller if item is found
613  if (is_object($Item))
614  {
615  if (is_object($Priv) && ($Item == $Priv)) { return TRUE; }
616  }
617  elseif (is_array($Item))
618  {
619  if (is_array($Priv) && ($Item == $Priv)) { return TRUE; }
620  }
621  elseif ($Item == $Priv) { return TRUE; }
622  }
623 
624  # report to caller that item is not in privilege data
625  return FALSE;
626  }
627 }
AssociatedUserId($NewValue=NULL)
Get/set ID of user associated with privilege set.
AddSet(PrivilegeSet $Set)
Add subgroup of privileges/conditions to set.
Set of privileges used to access resource information or other parts of the system.
IsLessThan(PrivilegeSet $Set, Resource $Resource=NULL)
Check whether a privilege set is less than another privilege set.
PHP
Definition: OAIClient.php:39
__construct($Data=NULL)
Class constructor, used to create a new set or reload an existing set from previously-constructed dat...
IncludesPrivilege($Privilege)
Check whether this privilege set includes the specified privilege.
GetPrivilegeInfo()
Get privilege information as an array, with numerical indexes except for the logic, which is contained in a element with the index "Logic".
GetPrivilegeList()
Get list of privileges.
Object representing a locally-defined type of metadata field.
Data($NewValue=NULL)
Get/set privilege set data, in the form of an opaque string.
Represents a "resource" in CWIS.
Definition: Resource.php:13
IsGreaterThan(PrivilegeSet $Set, $Resource=self::NO_RESOURCE)
Check whether a privilege set is greater than or equal to another privilege set.
AddPrivilege($Privilege)
Add specified privilege to set.
AddCondition($Field, $Value=NULL, $Operator="==")
Add condition to privilege set.
RemovePrivilege($Privilege)
Remove specified privilege from set.
const HAVE_RESOURCE
AllRequired($NewValue=NULL)
Get/set whether all privileges/conditions in set are required (i.e.
RemoveCondition($Field, $Value=NULL, $Operator="==")
Remove condition from privilege set.