Completed
Push — master ( a4a1ca...4311a9 )
by Nekrasov
01:52
created

UserModel::getGroups()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace Arrilot\BitrixModels\Models;
4
5
use Arrilot\BitrixModels\Queries\UserQuery;
6
7
class UserModel extends BitrixModel
8
{
9
    /**
10
     * Corresponding object class name.
11
     *
12
     * @var string
13
     */
14
    protected static $objectClass = 'CUser';
15
16
    /**
17
     * Current user cache.
18
     *
19
     * @var static
20
     */
21
    protected static $currentUser = null;
22
23
    /**
24
     * Have groups been already fetched from DB?
25
     *
26
     * @var bool
27
     */
28
    protected $groupsAreFetched = false;
29
30
    /**
31
     * Instantiate a query object for the model.
32
     *
33
     * @return UserQuery
34
     */
35
    public static function query()
36
    {
37
        return new UserQuery(static::instantiateObject(), get_called_class());
38
    }
39
40
    /**
41
     * Get a new instance for the current user
42
     *
43
     * @return static
44
     */
45
    public static function current()
46
    {
47
        return is_null(static::$currentUser)
48
            ? static::freshCurrent()
49
            : static::$currentUser;
50
    }
51
52
    /**
53
     * Get a fresh instance for the current user and save it to local cache.
54
     *
55
     * @return static
56
     */
57
    public static function freshCurrent()
58
    {
59
        global $USER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
60
61
        return static::$currentUser = (new static($USER->getId()))->load();
62
    }
63
64
    /**
65
     * Fill extra fields when $this->field is called.
66
     *
67
     * @return null
68
     */
69
    protected function afterFill()
70
    {
71
        if (isset($this->fields['GROUP_ID']) && is_array(['GROUP_ID'])) {
72
            $this->groupsAreFetched = true;
73
        }
74
    }
75
76
    /**
77
     * Fill model groups if they are already known.
78
     * Saves DB queries.
79
     *
80
     * @param array $groups
81
     *
82
     * @return null
83
     */
84
    public function fillGroups($groups)
85
    {
86
        $this->fields['GROUP_ID'] = $groups;
87
88
        $this->groupsAreFetched = true;
89
    }
90
91
    /**
92
     * Load model fields from database if they are not loaded yet.
93
     *
94
     * @return $this
95
     */
96
    public function load()
97
    {
98
        $this->getFields();
99
        $this->getGroups();
100
101
        return $this;
102
    }
103
104
    /**
105
     * Get user groups from cache or database.
106
     *
107
     * @return array
108
     */
109
    public function getGroups()
110
    {
111
        if ($this->groupsAreFetched) {
112
            return $this->fields['GROUP_ID'];
113
        }
114
115
        return $this->refreshGroups();
116
    }
117
118
    /**
119
     * Refresh model from database and place data to $this->fields.
120
     *
121
     * @return array
122
     */
123
    public function refresh()
124
    {
125
        $this->refreshFields();
126
127
        $this->refreshGroups();
128
129
        return $this->fields;
130
    }
131
132
    /**
133
     * Refresh user fields and save them to a class field.
134
     *
135
     * @return array
136
     */
137
    public function refreshFields()
138
    {
139
        if ($this->id === null) {
140
            return  $this->fields = [];
141
        }
142
143
        $groupBackup = isset($this->fields['GROUP_ID']) ? $this->fields['GROUP_ID'] : null;
144
145
        $this->fields = static::query()->getById($this->id)->fields;
146
147
        if ($groupBackup) {
148
            $this->fields['GROUP_ID'] = $groupBackup;
149
        }
150
151
        $this->fieldsAreFetched = true;
152
153
        return $this->fields;
154
    }
155
156
    /**
157
     * Refresh user groups and save them to a class field.
158
     *
159
     * @return array
160
     */
161
    public function refreshGroups()
162
    {
163
        if ($this->id === null) {
164
            return [];
165
        }
166
167
        global $USER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
168
169
        $this->fields['GROUP_ID'] = $this->isCurrent()
170
            ? $USER->getUserGroupArray()
171
            : static::$bxObject->getUserGroup($this->id);
172
173
        $this->groupsAreFetched = true;
174
175
        return $this->fields['GROUP_ID'];
176
    }
177
178
    /**
179
     * Check if user is an admin.
180
     */
181
    public function isAdmin()
182
    {
183
        return $this->hasGroupWithId(1);
184
    }
185
186
    /**
187
     * Check if this user is the operating user.
188
     */
189
    public function isCurrent()
190
    {
191
        global $USER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
192
193
        return $USER->getId() && $this->id == $USER->getId();
194
    }
195
196
    /**
197
     * Check if user has role with a given ID.
198
     *
199
     * @param $role_id
200
     *
201
     * @return bool
202
     */
203
    public function hasGroupWithId($role_id)
204
    {
205
        return in_array($role_id, $this->getGroups());
206
    }
207
208
    /**
209
     * Check if user is authorized.
210
     *
211
     * @return bool
212
     */
213
    public function isAuthorized()
214
    {
215
        global $USER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
216
217
        return ($USER->getId() == $this->id) && $USER->isAuthorized();
218
    }
219
220
    /**
221
     * Check if user is guest.
222
     *
223
     * @return bool
224
     */
225
    public function isGuest()
226
    {
227
        return ! $this->isAuthorized();
228
    }
229
230
    /**
231
     * Logout user.
232
     *
233
     * @return void
234
     */
235
    public function logout()
236
    {
237
        global $USER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
238
239
        $USER->logout();
240
    }
241
242
    /**
243
     * Scope to get only users from a given group / groups.
244
     *
245
     * @param UserQuery $query
246
     * @param int|array $id
247
     *
248
     * @return UserQuery
249
     */
250
    public function scopeFromGroup($query, $id)
251
    {
252
        $query->filter['GROUPS_ID'] = $id;
253
254
        return $query;
255
    }
256
257
    /**
258
     * Substitute old group with the new one.
259
     *
260
     * @param int $old
261
     * @param int $new
262
     *
263
     * @return void
264
     */
265
    public function substituteGroup($old, $new)
266
    {
267
        $groups = $this->getGroups();
268
269
        if(($key = array_search($old, $groups)) !== false) {
270
            unset($groups[$key]);
271
        }
272
273
        if (!in_array($new, $groups)) {
274
            $groups[] = $new;
275
        }
276
277
        $this->fields['GROUP_ID'] = $groups;
278
    }
279
}
280