1 <?php
  2 /**
  3  * @package     Joomla.Platform
  4  * @subpackage  Access
  5  *
  6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
  7  * @license     GNU General Public License version 2 or later; see LICENSE
  8  */
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 /**
 13  * JAccessRules class.
 14  *
 15  * @since  11.4
 16  */
 17 class JAccessRules
 18 {
 19     /**
 20      * A named array.
 21      *
 22      * @var    array
 23      * @since  11.1
 24      */
 25     protected $data = array();
 26 
 27     /**
 28      * Constructor.
 29      *
 30      * The input array must be in the form: array('action' => array(-42 => true, 3 => true, 4 => false))
 31      * or an equivalent JSON encoded string, or an object where properties are arrays.
 32      *
 33      * @param   mixed  $input  A JSON format string (probably from the database) or a nested array.
 34      *
 35      * @since   11.1
 36      */
 37     public function __construct($input = '')
 38     {
 39         // Convert in input to an array.
 40         if (is_string($input))
 41         {
 42             $input = json_decode($input, true);
 43         }
 44         elseif (is_object($input))
 45         {
 46             $input = (array) $input;
 47         }
 48 
 49         if (is_array($input))
 50         {
 51             // Top level keys represent the actions.
 52             foreach ($input as $action => $identities)
 53             {
 54                 $this->mergeAction($action, $identities);
 55             }
 56         }
 57     }
 58 
 59     /**
 60      * Get the data for the action.
 61      *
 62      * @return  array  A named array of JAccessRule objects.
 63      *
 64      * @since   11.1
 65      */
 66     public function getData()
 67     {
 68         return $this->data;
 69     }
 70 
 71     /**
 72      * Method to merge a collection of JAccessRules.
 73      *
 74      * @param   mixed  $input  JAccessRule or array of JAccessRules
 75      *
 76      * @return  void
 77      *
 78      * @since   11.1
 79      */
 80     public function mergeCollection($input)
 81     {
 82         // Check if the input is an array.
 83         if (is_array($input))
 84         {
 85             foreach ($input as $actions)
 86             {
 87                 $this->merge($actions);
 88             }
 89         }
 90     }
 91 
 92     /**
 93      * Method to merge actions with this object.
 94      *
 95      * @param   mixed  $actions  JAccessRule object, an array of actions or a JSON string array of actions.
 96      *
 97      * @return  void
 98      *
 99      * @since   11.1
100      */
101     public function merge($actions)
102     {
103         if (is_string($actions))
104         {
105             $actions = json_decode($actions, true);
106         }
107 
108         if (is_array($actions))
109         {
110             foreach ($actions as $action => $identities)
111             {
112                 $this->mergeAction($action, $identities);
113             }
114         }
115         elseif ($actions instanceof JAccessRules)
116         {
117             $data = $actions->getData();
118 
119             foreach ($data as $name => $identities)
120             {
121                 $this->mergeAction($name, $identities);
122             }
123         }
124     }
125 
126     /**
127      * Merges an array of identities for an action.
128      *
129      * @param   string  $action      The name of the action.
130      * @param   array   $identities  An array of identities
131      *
132      * @return  void
133      *
134      * @since   11.1
135      */
136     public function mergeAction($action, $identities)
137     {
138         if (isset($this->data[$action]))
139         {
140             // If exists, merge the action.
141             $this->data[$action]->mergeIdentities($identities);
142         }
143         else
144         {
145             // If new, add the action.
146             $this->data[$action] = new JAccessRule($identities);
147         }
148     }
149 
150     /**
151      * Checks that an action can be performed by an identity.
152      *
153      * The identity is an integer where +ve represents a user group,
154      * and -ve represents a user.
155      *
156      * @param   string  $action    The name of the action.
157      * @param   mixed   $identity  An integer representing the identity, or an array of identities
158      *
159      * @return  mixed   Object or null if there is no information about the action.
160      *
161      * @since   11.1
162      */
163     public function allow($action, $identity)
164     {
165         // Check we have information about this action.
166         if (isset($this->data[$action]))
167         {
168             return $this->data[$action]->allow($identity);
169         }
170 
171         return;
172     }
173 
174     /**
175      * Get the allowed actions for an identity.
176      *
177      * @param   mixed  $identity  An integer representing the identity or an array of identities
178      *
179      * @return  JObject  Allowed actions for the identity or identities
180      *
181      * @since   11.1
182      */
183     public function getAllowed($identity)
184     {
185         // Sweep for the allowed actions.
186         $allowed = new JObject;
187 
188         foreach ($this->data as $name => &$action)
189         {
190             if ($action->allow($identity))
191             {
192                 $allowed->set($name, true);
193             }
194         }
195 
196         return $allowed;
197     }
198 
199     /**
200      * Magic method to convert the object to JSON string representation.
201      *
202      * @return  string  JSON representation of the actions array
203      *
204      * @since   11.1
205      */
206     public function __toString()
207     {
208         $temp = array();
209 
210         foreach ($this->data as $name => $rule)
211         {
212             if ($data = $rule->getData())
213             {
214                 $temp[$name] = $data;
215             }
216         }
217 
218         return json_encode($temp, JSON_FORCE_OBJECT);
219     }
220 }
221