Skip to content

Commit

Permalink
[V5] Cache loader improvements (#1912)
Browse files Browse the repository at this point in the history
* Cache loader improvements

* Cache even smaller

Co-authored-by: Erik Niebla <ep_niebla@hotmail.com>
  • Loading branch information
erikn69 and Erik Niebla committed May 5, 2022
1 parent 67c4df7 commit 4e3ad0a
Showing 1 changed file with 83 additions and 32 deletions.
115 changes: 83 additions & 32 deletions src/PermissionRegistrar.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,32 +170,22 @@ private function loadPermissions()
}

$this->permissions = $this->cache->remember(self::$cacheKey, self::$cacheExpirationTime, function () {
// make the cache smaller using an array with only required fields
return $this->getPermissionClass()->select('id', 'id as i', 'name as n', 'guard_name as g')
->with('roles:id,id as i,name as n,guard_name as g')->get()
->map(function ($permission) {
return $permission->only('i', 'n', 'g') +
['r' => $permission->roles->map->only('i', 'n', 'g')->all()];
})->all();
return $this->getSerializedPermissionsForCache();
});

if (is_array($this->permissions)) {
$this->permissions = $this->getPermissionClass()::hydrate(
collect($this->permissions)->map(function ($item) {
return ['id' => $item['i'] ?? $item['id'], 'name' => $item['n'] ?? $item['name'], 'guard_name' => $item['g'] ?? $item['guard_name']];
})->all()
)
->each(function ($permission, $i) {
$roles = Collection::make($this->permissions[$i]['r'] ?? $this->permissions[$i]['roles'] ?? [])
->map(function ($item) {
return $this->getHydratedRole($item);
});

$permission->setRelation('roles', $roles);
});

$this->cachedRoles = [];
// fallback for old cache method, must be removed on next mayor version
if (! isset($this->permissions['permissions'])) {

This comment has been minimized.

Copy link
@drbyte

drbyte Dec 20, 2023

Collaborator

@erikn69 Do you think we should wait until v7 to remove this?

This comment has been minimized.

Copy link
@erikn69

erikn69 Dec 20, 2023

Author Contributor

In v6 it could have already been removed, but it shouldn't affect anyone anymore

$this->forgetCachedPermissions();
$this->loadPermissions();

return;
}

$this->hydrateRolesCache();

$this->permissions = $this->getHydratedPermissionCollection();

$this->cachedRoles = [];
}

/**
Expand Down Expand Up @@ -277,21 +267,82 @@ public function getCacheStore(): Store
return $this->cache->getStore();
}

private function getHydratedRole(array $item)
/*
* Make the cache smaller using an array with only required fields
*/
private function getSerializedPermissionsForCache()
{
$roleId = $item['i'] ?? $item['id'];
$roleClass = $this->getRoleClass();
$roleKey = (new $roleClass())->getKeyName();

$permissionClass = $this->getPermissionClass();
$permissionKey = (new $permissionClass())->getKeyName();

$permissions = $permissionClass
->select($permissionKey, "$permissionKey as i", 'name as n', 'guard_name as g')
->with("roles:$roleKey,$roleKey as i,name as n,guard_name as g")->get()
->map(function ($permission) {
return $permission->only('i', 'n', 'g') + $this->getSerializedRoleRelation($permission);
})->all();
$roles = array_values($this->cachedRoles);
$this->cachedRoles = [];

if (isset($this->cachedRoles[$roleId])) {
return $this->cachedRoles[$roleId];
return compact('permissions', 'roles');
}

private function getSerializedRoleRelation($permission)
{
if (! $permission->roles->count()) {
return [];
}

return [
'r' => $permission->roles->map(function ($role) {
if (! isset($this->cachedRoles[$role->i])) {
$this->cachedRoles[$role->i] = $role->only('i', 'n', 'g');
}

return $role->i;
})->all(),
];
}

private function getHydratedPermissionCollection()
{
$permissionClass = $this->getPermissionClass();
$permissionInstance = new $permissionClass();

return Collection::make(
array_map(function ($item) use ($permissionInstance) {
return $permissionInstance
->newFromBuilder([
$permissionInstance->getKeyName() => $item['i'],
'name' => $item['n'],
'guard_name' => $item['g'],
])
->setRelation('roles', $this->getHydratedRoleCollection($item['r'] ?? []));
}, $this->permissions['permissions'])
);
}

private function getHydratedRoleCollection(array $roles)
{
return Collection::make(array_values(
array_intersect_key($this->cachedRoles, array_flip($roles))
));
}

private function hydrateRolesCache()
{
$roleClass = $this->getRoleClass();
$roleInstance = new $roleClass();

return $this->cachedRoles[$roleId] = $roleInstance->newFromBuilder([
'id' => $roleId,
'name' => $item['n'] ?? $item['name'],
'guard_name' => $item['g'] ?? $item['guard_name'],
]);
array_map(function ($item) use ($roleInstance) {
$this->cachedRoles[$item['i']] = $roleInstance->newFromBuilder([
$roleInstance->getKeyName() => $item['i'],
'name' => $item['n'],
'guard_name' => $item['g'],
]);
}, $this->permissions['roles']);
}
}

0 comments on commit 4e3ad0a

Please sign in to comment.