1 | <?php |
||
2 | /** |
||
3 | * @package midcom |
||
4 | * @author The Midgard Project, http://www.midgard-project.org |
||
5 | * @copyright The Midgard Project, http://www.midgard-project.org |
||
6 | * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License |
||
7 | */ |
||
8 | |||
9 | use Doctrine\ORM\Query\Expr\Join; |
||
10 | |||
11 | /** |
||
12 | * MidCOM group implementation supporting Midgard Groups. |
||
13 | * |
||
14 | * @package midcom |
||
15 | */ |
||
16 | class midcom_core_group |
||
17 | { |
||
18 | /** |
||
19 | * The storage object on which we are based. This is usually a midgard_group |
||
20 | * directly, as this class has to work outside of the ACLs. It must not be used |
||
21 | * from the outside. |
||
22 | * |
||
23 | * Access to this member is restricted to the ACL user/group core. In case you |
||
24 | * need a real Storage object for this group, call get_storage() instead. |
||
25 | * |
||
26 | * @var midgard_group |
||
27 | */ |
||
28 | protected $_storage = null; |
||
29 | |||
30 | /** |
||
31 | * Name of the group |
||
32 | * |
||
33 | * The variable is considered to be read-only. |
||
34 | * |
||
35 | * @var string |
||
36 | */ |
||
37 | public $name = ''; |
||
38 | |||
39 | /** |
||
40 | * The identification string used to internally identify the group uniquely |
||
41 | * in the system. This is usually some kind of group:$guid string combination. |
||
42 | * |
||
43 | * The variable is considered to be read-only. |
||
44 | * |
||
45 | * @var string |
||
46 | */ |
||
47 | public $id = ''; |
||
48 | |||
49 | /** |
||
50 | * The scope value, which must be set during the _load callback, indicates the "depth" of the |
||
51 | * group in the inheritance tree. This is used during privilege merging in the content |
||
52 | * privilege code, which needs a way to determine the proper ordering. Top level groups |
||
53 | * start with a scope of 1. |
||
54 | * |
||
55 | * The variable is considered to be read-only. |
||
56 | * |
||
57 | * @var integer |
||
58 | */ |
||
59 | public $scope = MIDCOM_PRIVILEGE_SCOPE_ROOTGROUP; |
||
60 | |||
61 | /** |
||
62 | * Contains the parent of the current group, cached for repeated accesses. |
||
63 | * |
||
64 | * @var midcom_core_group |
||
65 | */ |
||
66 | private $_cached_parent_group = null; |
||
67 | |||
68 | /** |
||
69 | * The constructor retrieves the group identified by its name from the database and |
||
70 | * prepares the object for operation. |
||
71 | * |
||
72 | * It will use the Query Builder to retrieve a group by its name and populate the |
||
73 | * $storage, $name and $id members accordingly. |
||
74 | * |
||
75 | * Any error will trigger midcom_error. |
||
76 | * |
||
77 | * @param mixed $id This is a valid identifier for the group to be loaded. Usually this is either |
||
78 | * a database ID or GUID for Midgard Groups or a valid complete MidCOM group identifier, which |
||
79 | * will work for all subclasses. |
||
80 | */ |
||
81 | 3 | public function __construct($id = null) |
|
82 | { |
||
83 | 3 | if (is_null($id)) { |
|
84 | throw new midcom_error('The class midcom_core_group is not default constructible.'); |
||
85 | } |
||
86 | |||
87 | 3 | if (is_a($id, midcom_db_group::class) || is_a($id, 'midgard_group')) { |
|
88 | 1 | $this->_storage = $id; |
|
89 | } else { |
||
90 | 3 | if (is_string($id)) { |
|
91 | 3 | $id_parts = explode(':', $id); |
|
92 | 3 | if (count($id_parts) == 2) { |
|
93 | 3 | if ($id_parts[0] != 'group') { |
|
94 | throw new midcom_error("The group type identifier {$id_parts[0]} is unknown"); |
||
95 | } |
||
96 | 3 | $id = $id_parts[1]; |
|
97 | } |
||
98 | } elseif (is_numeric($id) && $id == 0) { |
||
99 | throw new midcom_error('0 is not a valid DB identifier'); |
||
100 | } |
||
101 | try { |
||
102 | 3 | $this->_storage = new midgard_group($id); |
|
103 | } catch (Exception $e) { |
||
104 | debug_add('Tried to load a midcom_core_group, but got error ' . $e->getMessage(), MIDCOM_LOG_ERROR); |
||
105 | debug_print_r('Passed argument was:', $id); |
||
106 | throw new midcom_error($e->getMessage()); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | 3 | if ($this->_storage->official != '') { |
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
111 | $this->name = $this->_storage->official; |
||
112 | 3 | } elseif ($this->_storage->name != '') { |
|
0 ignored issues
–
show
|
|||
113 | $this->name = $this->_storage->name; |
||
114 | } else { |
||
115 | 3 | $this->name = "Group #{$this->_storage->id}"; |
|
0 ignored issues
–
show
|
|||
116 | } |
||
117 | 3 | $this->id = "group:{$this->_storage->guid}"; |
|
0 ignored issues
–
show
|
|||
118 | |||
119 | // Determine scope |
||
120 | 3 | $parent = $this->get_parent_group(); |
|
121 | 3 | if (is_null($parent)) { |
|
122 | 3 | $this->scope = MIDCOM_PRIVILEGE_SCOPE_ROOTGROUP; |
|
123 | } else { |
||
124 | $this->scope = $parent->scope + 1; |
||
125 | } |
||
126 | 3 | } |
|
127 | |||
128 | /** |
||
129 | * Retrieves a list of users for which are a member in this group. |
||
130 | * |
||
131 | * @return midcom_core_user[] A list of user objects in which are members of the current group, indexed by their ID. |
||
132 | */ |
||
133 | public function list_members() |
||
134 | { |
||
135 | $return = []; |
||
136 | |||
137 | if (empty($this->_storage->id)) { |
||
0 ignored issues
–
show
|
|||
138 | debug_add('$this->storage is not object or id is empty', MIDCOM_LOG_ERROR); |
||
139 | return $return; |
||
140 | } |
||
141 | |||
142 | $qb = new midgard_query_builder(midcom::get()->config->get('person_class')); |
||
143 | $qb->get_doctrine() |
||
144 | ->leftJoin('midgard_member', 'm', Join::WITH, 'm.uid = c.id') |
||
145 | ->where('m.gid = :id') |
||
146 | ->setParameter('id', $this->_storage->id); |
||
147 | |||
148 | foreach ($qb->execute() as $person) { |
||
149 | $user = new midcom_core_user($person); |
||
150 | $return[$user->id] = $user; |
||
151 | } |
||
152 | |||
153 | return $return; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Return a list of all groups in which the MidCOM user passed is a member. |
||
158 | * |
||
159 | * @param midcom_core_user $user The user that should be looked up. |
||
160 | * @return midcom_core_group[] Member groups, indexed by their ID. |
||
161 | */ |
||
162 | 95 | public static function list_memberships(midcom_core_user $user) |
|
163 | { |
||
164 | 95 | $qb = new midgard_query_builder('midgard_group'); |
|
165 | 95 | $qb->get_doctrine() |
|
166 | 95 | ->leftJoin('midgard_member', 'm', Join::WITH, 'm.gid = c.id') |
|
167 | 95 | ->leftJoin('midgard_person', 'p', Join::WITH, 'm.uid = p.id') |
|
168 | 95 | ->where('p.guid = :guid') |
|
169 | 95 | ->setParameter('guid', $user->guid); |
|
170 | |||
171 | 95 | $return = []; |
|
172 | 95 | foreach ($qb->execute() as $group) { |
|
173 | 1 | $return['group:' . $group->guid] = new static($group); |
|
174 | } |
||
175 | |||
176 | 95 | return $return; |
|
177 | } |
||
178 | |||
179 | /** |
||
180 | * Returns the parent group. |
||
181 | * |
||
182 | * @return midcom_core_group The parent group of the current group or null if there is none. |
||
183 | */ |
||
184 | 3 | function get_parent_group() |
|
185 | { |
||
186 | 3 | if (is_null($this->_cached_parent_group)) { |
|
187 | 3 | if ($this->_storage->owner == 0) { |
|
0 ignored issues
–
show
|
|||
188 | 3 | return null; |
|
189 | } |
||
190 | |||
191 | if ($this->_storage->id == $this->_storage->owner) { |
||
0 ignored issues
–
show
|
|||
192 | debug_print_r('Broken Group', $this, MIDCOM_LOG_CRIT); |
||
193 | throw new midcom_error('A group was its own parent, which will result in an infinite loop. See debug log for more info.'); |
||
194 | } |
||
195 | |||
196 | $parent = new midgard_group(); |
||
197 | $parent->get_by_id($this->_storage->owner); |
||
198 | |||
199 | if (!$parent->id) { |
||
200 | debug_add("Could not load Group ID {$this->_storage->owner} from the database, aborting, this should not happen. See the debug level log for details. (" |
||
201 | . midcom_connection::get_error_string() . ')', |
||
202 | MIDCOM_LOG_ERROR); |
||
203 | debug_print_r('Group that we started from is:', $this->_storage); |
||
204 | return null; |
||
205 | } |
||
206 | |||
207 | $this->_cached_parent_group = midcom::get()->auth->get_group($parent); |
||
208 | } |
||
209 | return $this->_cached_parent_group; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Return a list of privileges assigned directly to the group. The default implementation |
||
214 | * queries the GUID directly using the get_self_privileges method of the |
||
215 | * midcom_core_privilege class, which should work fine on all MgdSchema |
||
216 | * objects. If the storage object is null, an empty array is returned. |
||
217 | * |
||
218 | * @return midcom_core_privilege[] |
||
219 | */ |
||
220 | public function get_privileges() |
||
221 | { |
||
222 | if (is_null($this->_storage)) { |
||
223 | return []; |
||
224 | } |
||
225 | return midcom_core_privilege::get_self_privileges($this->_storage->guid); |
||
0 ignored issues
–
show
|
|||
226 | } |
||
227 | |||
228 | /** |
||
229 | * Return a MidCOM DBA level storage object for the current group. Be aware, |
||
230 | * that depending on ACL information, the retrieval of the user may fail. |
||
231 | * |
||
232 | * Also, as outlined in the member $_storage, not all groups may have a DBA object associated |
||
233 | * with them, therefore this call may return null. |
||
234 | * |
||
235 | * The default implementation will return an instance of midcom_db_group based |
||
236 | * on the member $this->_storage->id if that object is defined, or null otherwise. |
||
237 | * |
||
238 | * @return midcom_db_group A MidCOM DBA object that holds the information associated with |
||
239 | * this group, or null if there is no storage object. |
||
240 | */ |
||
241 | public function get_storage() |
||
242 | { |
||
243 | if ($this->_storage === null) { |
||
244 | return null; |
||
245 | } |
||
246 | return new midcom_db_group($this->_storage); |
||
247 | } |
||
248 | } |
||
249 |