vd/app/Models/Permission/Traits/HasRoles.php
2018-11-05 09:26:30 +08:00

221 lines
5.2 KiB
PHP

<?php
namespace App\Models\Permission\Traits;
use App\Models\Permission\Role;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Contracts\Auth\Access\Gate;
use App\Domains\Permission\Services\PermissionService;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
trait HasRoles
{
use HasPermissions;
public static function bootHasRoles()
{
static::deleting(function ($model) {
if (method_exists($model, 'isForceDeleting') && ! $model->isForceDeleting()) {
return;
}
$model->roles()->detach();
});
}
/**
* A model may have roles.
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class, 'account_has_roles', 'account_id', 'role_id');
}
/**
* Assign the given role to the model.
*
* @param array|string|Role ...$roles
*
* @return $this
*/
public function assignRole(...$roles)
{
$roles = collect($roles)->flatten()->map(function ($role) {
if (empty($role)) {
return false;
}
return $this->getStoredRole($role);
})->filter(function ($role) {
return $role instanceof Role;
})->all();
$this->roles()->saveMany($roles);
$this->forgetCachedPermissions();
return $this;
}
/**
* Revoke the given role from the model.
*
* @param string|Role $role
*/
public function removeRole($role)
{
$this->roles()->detach($this->getStoredRole($role));
}
/**
* Remove all current roles and set the given ones.
*
* @param array|Role|string ...$roles
*
* @return $this
*/
public function syncRoles(...$roles)
{
return DB::transaction(function () use ($roles) {
$this->roles()->detach();
return $this->assignRole($roles);
});
}
/**
* Determine if the model has (one of) the given role(s).
*
* @param string|array|Role|Collection $roles
*
* @return bool
*/
public function hasRole($roles): bool
{
if (is_string($roles) && false !== strpos($roles, '|')) {
$roles = $this->convertPipeToArray($roles);
}
if (is_string($roles)) {
return $this->roles->contains('name', $roles);
}
if ($roles instanceof Role) {
return $this->roles->contains('id', $roles->id);
}
if (is_array($roles)) {
foreach ($roles as $role) {
if ($this->hasRole($role)) {
return true;
}
}
return false;
}
return $roles->intersect($this->roles)->isNotEmpty();
}
/**
* Determine if the model has any of the given role(s).
*
* @param string|array|Role|Collection $roles
*
* @return bool
*/
public function hasAnyRole($roles): bool
{
return $this->hasRole($roles);
}
/**
* Determine if the model has all of the given role(s).
*
* @param string|Role|Collection $roles
*
* @return bool
*/
public function hasAllRoles($roles): bool
{
if (is_string($roles) && false !== strpos($roles, '|')) {
$roles = $this->convertPipeToArray($roles);
}
if (is_string($roles)) {
return $this->roles->contains('name', $roles);
}
if ($roles instanceof Role) {
return $this->roles->contains('id', $roles->id);
}
$roles = collect()->make($roles)->map(function ($role) {
return $role instanceof Role ? $role->name : $role;
});
return $roles->intersect($this->roles->pluck('name')) == $roles;
}
/**
* Return all permissions directly coupled to the model.
*/
public function getDirectPermissions(): Collection
{
return $this->permissions;
}
public function getRoleNames(): Collection
{
return $this->roles->pluck('name');
}
protected function getStoredRole($role): Role
{
if (is_numeric($role)) {
return app(Role::class)->findById($role);
}
return $role;
}
protected function convertPipeToArray(string $pipeString)
{
$pipeString = trim($pipeString);
if (strlen($pipeString) <= 2) {
return $pipeString;
}
$quoteCharacter = substr($pipeString, 0, 1);
$endCharacter = substr($quoteCharacter, -1, 1);
if ($quoteCharacter !== $endCharacter) {
return explode('|', $pipeString);
}
if (! in_array($quoteCharacter, ["'", '"'])) {
return explode('|', $pipeString);
}
return explode('|', trim($pipeString, $quoteCharacter));
}
/**
* Determine if the entity has a given ability.
*
* @param string $ability
* @param array|mixed $arguments
* @return bool
*/
public function can($ability, $arguments = [])
{
return app(Gate::class)->forUser($this)->check($ability, $arguments);
}
}