Completed
Push — master ( af05a7...eda6ec )
by Nekrasov
02:11
created

UserModel::fillGroups()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Arrilot\BitrixModels\Models;
4
5
use Arrilot\BitrixModels\Queries\UserQuery;
6
7
class UserModel extends BaseModel
8
{
9
    /**
10
     * Bitrix entity object.
11
     *
12
     * @var object
13
     */
14
    public static $bxObject;
15
16
    /**
17
     * Corresponding object class name.
18
     *
19
     * @var string
20
     */
21
    protected static $objectClass = 'CUser';
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
     * @param null $fields
44
     *
45
     * @return static
46
     */
47
    public static function current($fields = null)
48
    {
49
        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...
50
51
        $user = new static($USER->getId());
52
53
        if (!is_null($fields)) {
54
            $user->fill($fields);
55
        }
56
57
        return $user;
58
    }
59
60
    /**
61
     * Fill extra fields when $this->field is called.
62
     *
63
     * @return null
64
     */
65
    protected function afterFill()
66
    {
67
        if (isset($this->fields['GROUP_ID']) && is_array(['GROUP_ID'])) {
68
            $this->groupsAreFetched = true;
69
        }
70
    }
71
72
    /**
73
     * Fill model groups if they are already known.
74
     * Saves DB queries.
75
     *
76
     * @param array $groups
77
     *
78
     * @return null
79
     */
80
    public function fillGroups($groups)
81
    {
82
        $this->fields['GROUP_ID'] = $groups;
83
84
        $this->groupsAreFetched = true;
85
    }
86
87
    /**
88
     * Get all model attributes from cache or database.
89
     *
90
     * @return array
91
     */
92
    public function get()
93
    {
94
        $this->getFields();
95
96
        $this->getGroups();
97
98
        return $this->fields;
99
    }
100
101
    /**
102
     * Get user groups from cache or database.
103
     *
104
     * @return array
105
     */
106
    public function getGroups()
107
    {
108
        if ($this->groupsAreFetched) {
109
            return $this->fields['GROUP_ID'];
110
        }
111
112
        return $this->refreshGroups();
113
    }
114
115
    /**
116
     * Refresh model from database and place data to $this->fields.
117
     *
118
     * @return array
119
     */
120
    public function refresh()
121
    {
122
        $this->refreshFields();
123
124
        $this->refreshGroups();
125
126
        return $this->fields;
127
    }
128
129
    /**
130
     * Refresh user fields and save them to a class field.
131
     *
132
     * @return array
133
     */
134
    public function refreshFields()
135
    {
136
        if ($this->id === null) {
137
            return  $this->fields = [];
138
        }
139
140
        $groupBackup = isset($this->fields['GROUP_ID']) ? $this->fields['GROUP_ID'] : null;
141
142
        $this->fields = static::query()->getById($this->id)->fields;
143
144
        if ($groupBackup) {
145
            $this->fields['GROUP_ID'] = $groupBackup;
146
        }
147
148
        $this->fieldsAreFetched = true;
149
150
        return $this->fields;
151
    }
152
153
    /**
154
     * Refresh user groups and save them to a class field.
155
     *
156
     * @return array
157
     */
158
    public function refreshGroups()
159
    {
160
        if ($this->id === null) {
161
            return [];
162
        }
163
164
        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...
165
166
        $this->fields['GROUP_ID'] = $this->isCurrent()
167
            ? $USER->getUserGroupArray()
168
            : static::$bxObject->getUserGroup($this->id);
169
170
        $this->groupsAreFetched = true;
171
172
        return $this->fields['GROUP_ID'];
173
    }
174
175
    /**
176
     * Check if user is an admin.
177
     */
178
    public function isAdmin()
179
    {
180
        return $this->hasGroupWithId(1);
181
    }
182
183
    /**
184
     * Check if this user is the operating user.
185
     */
186
    public function isCurrent()
187
    {
188
        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...
189
190
        return $USER->getId() && $this->id == $USER->getId();
191
    }
192
193
    /**
194
     * Check if user has role with a given ID.
195
     *
196
     * @param $role_id
197
     *
198
     * @return bool
199
     */
200
    public function hasGroupWithId($role_id)
201
    {
202
        return in_array($role_id, $this->getGroups());
203
    }
204
205
    /**
206
     * Check if user is authorized.
207
     *
208
     * @return bool
209
     */
210
    public function isAuthorized()
211
    {
212
        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...
213
214
        return ($USER->getId() == $this->id) && $USER->isAuthorized();
215
    }
216
217
    /**
218
     * Check if user is guest.
219
     *
220
     * @return bool
221
     */
222
    public function isGuest()
223
    {
224
        return ! $this->isAuthorized();
225
    }
226
227
    /**
228
     * Logout user.
229
     *
230
     * @return void
231
     */
232
    public function logout()
233
    {
234
        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...
235
236
        $USER->logout();
237
    }
238
239
    /**
240
     * Scope to get only users from a given group / groups.
241
     *
242
     * @param UserQuery $query
243
     * @param int|array $id
244
     *
245
     * @return UserQuery
246
     */
247
    public function scopeFromGroup($query, $id)
248
    {
249
        $query->filter['GROUPS_ID'] = $id;
250
251
        return $query;
252
    }
253
254
    /**
255
     * Substitute old group with the new one.
256
     *
257
     * @param int $old
258
     * @param int $new
259
     *
260
     * @return void
261
     */
262
    public function substituteGroup($old, $new)
263
    {
264
        $groups = $this->getGroups();
265
266
        if(($key = array_search($old, $groups)) !== false) {
267
            unset($groups[$key]);
268
        }
269
270
        if (!in_array($new, $groups)) {
271
            $groups[] = $new;
272
        }
273
274
        $this->fields['GROUP_ID'] = $groups;
275
    }
276
}
277