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 * JAccessRule class.
14 *
15 * @since 11.4
16 */
17 class JAccessRule
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(-42 => true, 3 => true, 4 => false)
31 * or an equivalent JSON encoded string.
32 *
33 * @param mixed $identities A JSON format string (probably from the database) or a named array.
34 *
35 * @since 11.1
36 */
37 public function __construct($identities)
38 {
39 // Convert string input to an array.
40 if (is_string($identities))
41 {
42 $identities = json_decode($identities, true);
43 }
44
45 $this->mergeIdentities($identities);
46 }
47
48 /**
49 * Get the data for the action.
50 *
51 * @return array A named array
52 *
53 * @since 11.1
54 */
55 public function getData()
56 {
57 return $this->data;
58 }
59
60 /**
61 * Merges the identities
62 *
63 * @param mixed $identities An integer or array of integers representing the identities to check.
64 *
65 * @return void
66 *
67 * @since 11.1
68 */
69 public function mergeIdentities($identities)
70 {
71 if ($identities instanceof JAccessRule)
72 {
73 $identities = $identities->getData();
74 }
75
76 if (is_array($identities))
77 {
78 foreach ($identities as $identity => $allow)
79 {
80 $this->mergeIdentity($identity, $allow);
81 }
82 }
83 }
84
85 /**
86 * Merges the values for an identity.
87 *
88 * @param integer $identity The identity.
89 * @param boolean $allow The value for the identity (true == allow, false == deny).
90 *
91 * @return void
92 *
93 * @since 11.1
94 */
95 public function mergeIdentity($identity, $allow)
96 {
97 $identity = (int) $identity;
98 $allow = (int) ((boolean) $allow);
99
100 // Check that the identity exists.
101 if (isset($this->data[$identity]))
102 {
103 // Explicit deny always wins a merge.
104 if ($this->data[$identity] !== 0)
105 {
106 $this->data[$identity] = $allow;
107 }
108 }
109 else
110 {
111 $this->data[$identity] = $allow;
112 }
113 }
114
115 /**
116 * Checks that this action can be performed by an identity.
117 *
118 * The identity is an integer where +ve represents a user group,
119 * and -ve represents a user.
120 *
121 * @param mixed $identities An integer or array of integers representing the identities to check.
122 *
123 * @return mixed True if allowed, false for an explicit deny, null for an implicit deny.
124 *
125 * @since 11.1
126 */
127 public function allow($identities)
128 {
129 // Implicit deny by default.
130 $result = null;
131
132 // Check that the inputs are valid.
133 if (!empty($identities))
134 {
135 if (!is_array($identities))
136 {
137 $identities = array($identities);
138 }
139
140 foreach ($identities as $identity)
141 {
142 // Technically the identity just needs to be unique.
143 $identity = (int) $identity;
144
145 // Check if the identity is known.
146 if (isset($this->data[$identity]))
147 {
148 $result = (boolean) $this->data[$identity];
149
150 // An explicit deny wins.
151 if ($result === false)
152 {
153 break;
154 }
155 }
156 }
157 }
158
159 return $result;
160 }
161
162 /**
163 * Convert this object into a JSON encoded string.
164 *
165 * @return string JSON encoded string
166 *
167 * @since 11.1
168 */
169 public function __toString()
170 {
171 return json_encode($this->data);
172 }
173 }
174