Optimized pre-joint-permission logic efficiency
This commit is contained in:
parent
a721405202
commit
c5e9dfa168
|
@ -37,7 +37,7 @@ class PermissionService
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array<string, array<int, Entity>>
|
||||||
*/
|
*/
|
||||||
protected $entityCache;
|
protected $entityCache;
|
||||||
|
|
||||||
|
@ -68,10 +68,12 @@ class PermissionService
|
||||||
|
|
||||||
foreach ($entities as $entity) {
|
foreach ($entities as $entity) {
|
||||||
$class = get_class($entity);
|
$class = get_class($entity);
|
||||||
|
|
||||||
if (!isset($this->entityCache[$class])) {
|
if (!isset($this->entityCache[$class])) {
|
||||||
$this->entityCache[$class] = collect();
|
$this->entityCache[$class] = [];
|
||||||
}
|
}
|
||||||
$this->entityCache[$class]->put($entity->id, $entity);
|
|
||||||
|
$this->entityCache[$class][$entity->getRawAttribute('id')] = $entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +82,8 @@ class PermissionService
|
||||||
*/
|
*/
|
||||||
protected function getBook(int $bookId): ?Book
|
protected function getBook(int $bookId): ?Book
|
||||||
{
|
{
|
||||||
if (isset($this->entityCache[Book::class]) && $this->entityCache[Book::class]->has($bookId)) {
|
if ($this->entityCache[Book::class][$bookId] ?? false) {
|
||||||
return $this->entityCache[Book::class]->get($bookId);
|
return $this->entityCache[Book::class][$bookId];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Book::query()->withTrashed()->find($bookId);
|
return Book::query()->withTrashed()->find($bookId);
|
||||||
|
@ -92,8 +94,8 @@ class PermissionService
|
||||||
*/
|
*/
|
||||||
protected function getChapter(int $chapterId): ?Chapter
|
protected function getChapter(int $chapterId): ?Chapter
|
||||||
{
|
{
|
||||||
if (isset($this->entityCache[Chapter::class]) && $this->entityCache[Chapter::class]->has($chapterId)) {
|
if ($this->entityCache[Chapter::class][$chapterId] ?? false) {
|
||||||
return $this->entityCache[Chapter::class]->get($chapterId);
|
return $this->entityCache[Chapter::class][$chapterId];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Chapter::query()
|
return Chapter::query()
|
||||||
|
@ -206,7 +208,7 @@ class PermissionService
|
||||||
$entities = [$entity];
|
$entities = [$entity];
|
||||||
if ($entity instanceof Book) {
|
if ($entity instanceof Book) {
|
||||||
$books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get();
|
$books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get();
|
||||||
$this->buildJointPermissionsForBooks($books, Role::query()->get()->all(), true);
|
$this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +272,7 @@ class PermissionService
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all of the entity jointPermissions for a list of entities.
|
* Delete all the entity jointPermissions for a list of entities.
|
||||||
*
|
*
|
||||||
* @param Role[] $roles
|
* @param Role[] $roles
|
||||||
*/
|
*/
|
||||||
|
@ -283,19 +285,7 @@ class PermissionService
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the entity jointPermissions for a particular entity.
|
* Delete all the entity jointPermissions for a list of entities.
|
||||||
*
|
|
||||||
* @param Entity $entity
|
|
||||||
*
|
|
||||||
* @throws Throwable
|
|
||||||
*/
|
|
||||||
public function deleteJointPermissionsForEntity(Entity $entity)
|
|
||||||
{
|
|
||||||
$this->deleteManyJointPermissionsForEntities([$entity]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all of the entity jointPermissions for a list of entities.
|
|
||||||
*
|
*
|
||||||
* @param Entity[] $entities
|
* @param Entity[] $entities
|
||||||
*
|
*
|
||||||
|
@ -303,20 +293,16 @@ class PermissionService
|
||||||
*/
|
*/
|
||||||
protected function deleteManyJointPermissionsForEntities(array $entities)
|
protected function deleteManyJointPermissionsForEntities(array $entities)
|
||||||
{
|
{
|
||||||
if (count($entities) === 0) {
|
$idsByType = $this->entitiesToTypeIdMap($entities);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->db->transaction(function () use ($entities) {
|
$this->db->transaction(function () use ($idsByType) {
|
||||||
foreach (array_chunk($entities, 1000) as $entityChunk) {
|
foreach ($idsByType as $type => $ids) {
|
||||||
$query = $this->db->table('joint_permissions');
|
foreach (array_chunk($ids, 1000) as $idChunk) {
|
||||||
foreach ($entityChunk as $entity) {
|
$this->db->table('joint_permissions')
|
||||||
$query->orWhere(function (QueryBuilder $query) use ($entity) {
|
->where('entity_type', '=', $type)
|
||||||
$query->where('entity_id', '=', $entity->id)
|
->whereIn('entity_id', $idChunk)
|
||||||
->where('entity_type', '=', $entity->getMorphClass());
|
->delete();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
$query->delete();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -334,16 +320,14 @@ class PermissionService
|
||||||
$this->readyEntityCache($entities);
|
$this->readyEntityCache($entities);
|
||||||
$jointPermissions = [];
|
$jointPermissions = [];
|
||||||
|
|
||||||
// Fetch Entity Permissions and create a mapping of entity restricted statuses
|
// Create a mapping of entity restricted statuses
|
||||||
$entityRestrictedMap = [];
|
$entityRestrictedMap = [];
|
||||||
$permissionFetch = EntityPermission::query();
|
|
||||||
foreach ($entities as $entity) {
|
foreach ($entities as $entity) {
|
||||||
$entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->id] = boolval($entity->getRawAttribute('restricted'));
|
$entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->getRawAttribute('id')] = boolval($entity->getRawAttribute('restricted'));
|
||||||
$permissionFetch->orWhere(function ($query) use ($entity) {
|
|
||||||
$query->where('restrictable_id', '=', $entity->id)->where('restrictable_type', '=', $entity->getMorphClass());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
$permissions = $permissionFetch->get();
|
|
||||||
|
// Fetch related entity permissions
|
||||||
|
$permissions = $this->getEntityPermissionsForEntities($entities);
|
||||||
|
|
||||||
// Create a mapping of explicit entity permissions
|
// Create a mapping of explicit entity permissions
|
||||||
$permissionMap = [];
|
$permissionMap = [];
|
||||||
|
@ -377,6 +361,48 @@ class PermissionService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From the given entity list, provide back a mapping of entity types to
|
||||||
|
* the ids of that given type. The type used is the DB morph class.
|
||||||
|
* @param Entity[] $entities
|
||||||
|
* @return array<string, int[]>
|
||||||
|
*/
|
||||||
|
protected function entitiesToTypeIdMap(array $entities): array
|
||||||
|
{
|
||||||
|
$idsByType = [];
|
||||||
|
|
||||||
|
foreach ($entities as $entity) {
|
||||||
|
$type = $entity->getMorphClass();
|
||||||
|
|
||||||
|
if (!isset($idsByType[$type])) {
|
||||||
|
$idsByType[$type] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$idsByType[$type][] = $entity->getRawAttribute('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $idsByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity permissions for all the given entities
|
||||||
|
* @param Entity[] $entities
|
||||||
|
* @return EloquentCollection
|
||||||
|
*/
|
||||||
|
protected function getEntityPermissionsForEntities(array $entities)
|
||||||
|
{
|
||||||
|
$idsByType = $this->entitiesToTypeIdMap($entities);
|
||||||
|
$permissionFetch = EntityPermission::query();
|
||||||
|
|
||||||
|
foreach ($idsByType as $type => $ids) {
|
||||||
|
$permissionFetch->orWhere(function (Builder $query) use ($type, $ids) {
|
||||||
|
$query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $permissionFetch->get();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actions related to an entity.
|
* Get the actions related to an entity.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue