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

midcom_core_group::get_privileges()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $id can also be of type midcom_db_group. However, the property $_storage is declared as type midgard_group. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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);
0 ignored issues
show
Documentation Bug introduced by
It seems like midcom::get()->auth->get_group($parent) can also be of type false. However, the property $_cached_parent_group is declared as type midcom_core_group. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
Bug introduced by
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