Completed
Push — master ( a97a29...ec6402 )
by Jonathan
09:06
created

User::getInitialsAttribute()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 0
dl 0
loc 17
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace Uccello\Core\Models;
4
5
use Illuminate\Notifications\Notifiable;
0 ignored issues
show
Bug introduced by
The type Illuminate\Notifications\Notifiable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Illuminate\Foundation\Auth\User as Authenticatable;
0 ignored issues
show
Bug introduced by
The type Illuminate\Foundation\Auth\User was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Illuminate\Database\Eloquent\SoftDeletes;
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Eloquent\SoftDeletes was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Illuminate\Support\Collection;
0 ignored issues
show
Bug introduced by
The type Illuminate\Support\Collection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Illuminate\Support\Facades\Cache;
0 ignored issues
show
Bug introduced by
The type Illuminate\Support\Facades\Cache was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Spatie\Searchable\Searchable;
0 ignored issues
show
Bug introduced by
The type Spatie\Searchable\Searchable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Spatie\Searchable\SearchResult;
0 ignored issues
show
Bug introduced by
The type Spatie\Searchable\SearchResult was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Uccello\Core\Support\Traits\RelatedlistTrait;
13
14
class User extends Authenticatable implements Searchable
15
{
16
    use SoftDeletes;
17
    use Notifiable;
18
    use RelatedlistTrait;
19
20
    /**
21
     * The table associated with the model.
22
     *
23
     * @var string
24
     */
25
    protected $table = 'users';
26
27
    /**
28
     * The attributes that should be mutated to dates.
29
     *
30
     * @var array
31
     */
32
    protected $dates = [ 'deleted_at' ];
33
34
    /**
35
     * The attributes that should be casted to native types.
36
     *
37
     * @var array
38
     */
39
    protected $casts = [
40
        'avatar' => 'object',
41
    ];
42
43
    /**
44
     * The attributes that are mass assignable.
45
     *
46
     * @var array
47
     */
48
    protected $fillable = [
49
        'username',
50
        'name',
51
        'email',
52
        'password',
53
        'is_admin',
54
        'domain_id'
55
    ];
56
57
    /**
58
     * The attributes that should be hidden for arrays.
59
     *
60
     * @var array
61
     */
62
    protected $hidden = [
63
        'password', 'remember_token',
64
    ];
65
66
    /**
67
     * The accessors to append to the model's array form.
68
     *
69
     * @var array
70
     */
71
    protected $appends = [
72
        'recordLabel'
73
    ];
74
75
    public $searchableType = 'user';
76
77
    public $searchableColumns = [
78
        'name'
79
    ];
80
81
    public function getSearchResult(): SearchResult
82
    {
83
        return new SearchResult(
84
            $this,
85
            $this->recordLabel
86
        );
87
    }
88
89
    public function domain()
90
    {
91
        return $this->belongsTo(Domain::class);
92
    }
93
94
    public function lastDomain()
95
    {
96
        return $this->belongsTo(Domain::class);
97
    }
98
99
    public function privileges()
100
    {
101
        return $this->hasMany(Privilege::class);
102
    }
103
104
    public function menus()
105
    {
106
        return $this->hasMany(Menu::class);
107
    }
108
109
    /**
110
     * Returns record label
111
     *
112
     * @return string
113
     */
114
    public function getRecordLabelAttribute() : string
115
    {
116
        return trim($this->name) ?? $this->username;
117
    }
118
119
    /**
120
     * Get avatar type
121
     *
122
     * @return string
123
     */
124
    public function getAvatarTypeAttribute() : string
125
    {
126
        return $this->avatar->type ?? 'initials';
127
    }
128
129
    /**
130
     * Returns initals generated from the user name
131
     *
132
     * @return string
133
     */
134
    public function getInitialsAttribute() : string
135
    {
136
        $initials = "";
137
138
        $words = explode(" ", strtoupper($this->name));
139
140
        $i = 0;
141
        foreach ($words as $w) {
142
            $initials .= $w[0];
143
            $i++;
144
145
            if ($i === 3) { // Maximum: 3 letters
146
                break;
147
            }
148
        }
149
150
        return $initials;
151
    }
152
153
    /**
154
     * Returns the image to use as the user avatar
155
     *
156
     * @return string
157
     */
158
    public function getImageAttribute() : string
159
    {
160
        $image = 'vendor/uccello/uccello/images/user-no-image.png';
161
162
        if ($this->avatarType === 'gravatar') {
163
            $image = 'https://www.gravatar.com/avatar/' . md5($this->email) . '?d=mm';
164
165
        } elseif ($this->avatarType === 'image' && !empty($this->avatar->path)) {
166
            $image = $this->avatar->path;
167
        }
168
169
        return $image;
170
    }
171
172
    /**
173
     * Returns user's roles on a domain
174
     *
175
     * @param \Uccello\Core\Models\Domain $domain
176
     * @return \Illuminate\Support\Collection
177
     */
178
    public function rolesOnDomain($domain) : Collection
179
    {
180
        return Cache::remember('domain_'.$domain->slug.'_roles', 600, function () use($domain) {
181
            $roles = collect();
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
            $roles = /** @scrutinizer ignore-call */ collect();
Loading history...
182
183
            foreach ($this->privileges->where('domain_id', $domain->id) as $privilege) {
184
                $roles[ ] = $privilege->role;
185
            }
186
187
            return $roles;
188
        });
189
190
    }
191
192
    /**
193
     * Check if the user has at least a role on a domain
194
     *
195
     * @param \Uccello\Core\Models\Domain $domain
196
     * @return boolean
197
     */
198
    public function hasRoleOnDomain($domain) : bool {
199
        if ($this->is_admin) {
200
            return true;
201
        }
202
203
        return $this->rolesOnDomain($domain)->count() > 0;
204
    }
205
206
    /**
207
     * Check if the user has at least a role on a domain or its descendants
208
     *
209
     * @param \Uccello\Core\Models\Domain $domain
210
     * @return boolean
211
     */
212
    public function hasRoleOnDescendantDomain(Domain $domain) : bool {
213
        if ($this->is_admin) {
214
            return true;
215
        }
216
217
        $hasRole = false;
218
219
        $descendants = Cache::remember('domain_'.$domain->slug.'_descendants', 600, function () use($domain) {
220
            return $domain->findDescendants()->get();
221
        });
222
223
        foreach ($descendants as $descendant) {
224
            if ($this->hasRoleOnDomain($descendant)) {
225
                $hasRole = true;
226
                break;
227
            }
228
        }
229
230
        return $hasRole;
231
    }
232
233
    /**
234
     * Returns all user capabilities on a module in a domain.
235
     * If the user has a capability in one of the parents of a domain, he also has it in that domain.
236
     *
237
     * @param \Uccello\Core\Models\Domain $domain
238
     * @param \Uccello\Core\Models\Module $module
239
     * @return \Illuminate\Support\Collection
240
     */
241
    public function capabilitiesOnModule(Domain $domain, Module $module) : Collection
242
    {
243
        $keyName = 'user_'.$this->id.'_'.$domain->slug.'_'.$module->name.'_capabilities';
244
245
        return Cache::remember($keyName, 600, function () use($domain, $module) {
246
            $capabilities = collect();
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
            $capabilities = /** @scrutinizer ignore-call */ collect();
Loading history...
247
248
            // Get the domain and all its parents
249
            $domainParents = $domain->findAncestors()->get();
250
251
            // Get user privileges on each domain
252
            foreach ($domainParents as $_domain) {
253
                $privileges = $this->privileges->where('domain_id', $_domain->id);
254
255
                foreach ($privileges as $privilege) {
256
257
                    foreach ($privilege->role->profiles as $profile) {
258
                        $capabilities = $capabilities->merge($profile->capabilitiesOnModule($module));
259
                    }
260
                }
261
            }
262
263
            return $capabilities;
264
        });
265
    }
266
267
    /**
268
     * Checks if the user has a capability on a module in a domain.
269
     *
270
     * @param string $capabilityName
271
     * @param \Uccello\Core\Models\Domain $domain
272
     * @param \Uccello\Core\Models\Module $module
273
     * @return boolean
274
     */
275
    public function hasCapabilityOnModule(string $capabilityName, Domain $domain, Module $module) : bool
276
    {
277
        $capability = capability($capabilityName);
278
279
        $userCapabilities = $this->capabilitiesOnModule($domain, $module);
280
281
        return $this->is_admin || $userCapabilities->contains($capability);
282
    }
283
284
    /**
285
     * Checks if the user can access to settings panel.
286
     * Checks if the user has at least one admin capability on admin modules in a domain.
287
     *
288
     * @param \Uccello\Core\Models\Domain|null $domain
289
     * @return boolean
290
     */
291
    public function canAccessToSettingsPanel(?Domain $domain) : bool
292
    {
293
        if (empty($domain)) {
294
            $domain = Domain::first();
295
        }
296
297
        $keyName = 'user_'.$this->id.'_'.$domain->slug.'_can_access_to_settings_panel';
298
299
        return Cache::remember($keyName, 600, function () use($domain) {
300
301
            $hasCapability = false;
302
303
            foreach (Module::all() as $module) {
304
                if ($module->isAdminModule() === true && $this->canAdmin($domain, $module)) {
305
                    $hasCapability = true;
306
                    break;
307
                }
308
            }
309
310
            return $hasCapability;
311
        });
312
    }
313
314
    /**
315
     * Checks if the user can admin a module in a domain.
316
     *
317
     * @param \Uccello\Core\Models\Domain $domain
318
     * @param \Uccello\Core\Models\Module $module
319
     * @return boolean
320
     */
321
    public function canAdmin(Domain $domain, Module $module) : bool
322
    {
323
        return $this->hasCapabilityOnModule('admin', $domain, $module);
324
    }
325
326
    /**
327
     * Checks if the user can create a module in a domain.
328
     *
329
     * @param \Uccello\Core\Models\Domain $domain
330
     * @param \Uccello\Core\Models\Module $module
331
     * @return boolean
332
     */
333
    public function canCreate(Domain $domain, Module $module) : bool
334
    {
335
        return $this->hasCapabilityOnModule('create', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
336
    }
337
338
    /**
339
     * Checks if the user can retrieve a module in a domain.
340
     *
341
     * @param \Uccello\Core\Models\Domain $domain
342
     * @param \Uccello\Core\Models\Module $module
343
     * @return boolean
344
     */
345
    public function canRetrieve(Domain $domain, Module $module) : bool
346
    {
347
        return $this->hasCapabilityOnModule('retrieve', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
348
    }
349
350
    /**
351
     * Checks if the user can update a module in a domain.
352
     *
353
     * @param \Uccello\Core\Models\Domain $domain
354
     * @param \Uccello\Core\Models\Module $module
355
     * @return boolean
356
     */
357
    public function canUpdate(Domain $domain, Module $module) : bool
358
    {
359
        return $this->hasCapabilityOnModule('update', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
360
    }
361
362
    /**
363
     * Checks if the user can delete a module in a domain.
364
     *
365
     * @param \Uccello\Core\Models\Domain $domain
366
     * @param \Uccello\Core\Models\Module $module
367
     * @return boolean
368
     */
369
    public function canDelete(Domain $domain, Module $module) : bool
370
    {
371
        return $this->hasCapabilityOnModule('delete', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
372
    }
373
374
    /**
375
     * Checks if the user can create by API a module in a domain.
376
     *
377
     * @param \Uccello\Core\Models\Domain $domain
378
     * @param \Uccello\Core\Models\Module $module
379
     * @return boolean
380
     */
381
    public function canCreateByApi(Domain $domain, Module $module) : bool
382
    {
383
        return $this->hasCapabilityOnModule('api-create', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
384
    }
385
386
    /**
387
     * Checks if the user can retrieve by API a module in a domain.
388
     *
389
     * @param \Uccello\Core\Models\Domain $domain
390
     * @param \Uccello\Core\Models\Module $module
391
     * @return boolean
392
     */
393
    public function canRetrieveByApi(Domain $domain, Module $module) : bool
394
    {
395
        return $this->hasCapabilityOnModule('api-retrieve', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
396
    }
397
398
    /**
399
     * Checks if the user can update by API a module in a domain.
400
     *
401
     * @param \Uccello\Core\Models\Domain $domain
402
     * @param \Uccello\Core\Models\Module $module
403
     * @return boolean
404
     */
405
    public function canUpdateByApi(Domain $domain, Module $module) : bool
406
    {
407
        return $this->hasCapabilityOnModule('api-update', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
408
    }
409
410
    /**
411
     * Checks if the user can delete by API a module in a domain.
412
     *
413
     * @param \Uccello\Core\Models\Domain $domain
414
     * @param \Uccello\Core\Models\Module $module
415
     * @return boolean
416
     */
417
    public function canDeleteByApi(Domain $domain, Module $module) : bool
418
    {
419
        return $this->hasCapabilityOnModule('api-delete', $domain, $module) || ($module->isAdminModule() && $this->canAdmin($domain, $module));
420
    }
421
}
422