Completed
Push — master ( 2a7334...2bafa1 )
by Andreas
19:53
created

lib/midcom/core/group.php (8 issues)

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
The property official does not exist on org_openpsa_organization. Did you mean official?
Loading history...
111
            $this->name = $this->_storage->official;
112 3
        } elseif ($this->_storage->name != '') {
0 ignored issues
show
The property name does not exist on org_openpsa_organization. Did you mean name?
Loading history...
113
            $this->name = $this->_storage->name;
114
        } else {
115 3
            $this->name = "Group #{$this->_storage->id}";
0 ignored issues
show
The property id does not exist on org_openpsa_organization. Did you mean id?
Loading history...
116
        }
117 3
        $this->id = "group:{$this->_storage->guid}";
0 ignored issues
show
The property guid does not exist on org_openpsa_organization. Did you mean guid?
Loading history...
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
The property id does not exist on org_openpsa_organization. Did you mean id?
Loading history...
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
The property owner does not exist on org_openpsa_organization. Did you mean owner?
Loading history...
188 3
                return null;
189
            }
190
191
            if ($this->_storage->id == $this->_storage->owner) {
0 ignored issues
show
The property id does not exist on org_openpsa_organization. Did you mean id?
Loading history...
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
The property guid does not exist on org_openpsa_organization. Did you mean guid?
Loading history...
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