Showing
2 changed files
with
31 additions
and
45 deletions
| ... | @@ -318,15 +318,15 @@ class EntityRepo | ... | @@ -318,15 +318,15 @@ class EntityRepo |
| 318 | */ | 318 | */ |
| 319 | public function getBookChildren(Book $book, $filterDrafts = false) | 319 | public function getBookChildren(Book $book, $filterDrafts = false) |
| 320 | { | 320 | { |
| 321 | - $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts); | 321 | + $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts)->get(); |
| 322 | $entities = []; | 322 | $entities = []; |
| 323 | $parents = []; | 323 | $parents = []; |
| 324 | $tree = []; | 324 | $tree = []; |
| 325 | 325 | ||
| 326 | foreach ($q as $index => $rawEntity) { | 326 | foreach ($q as $index => $rawEntity) { |
| 327 | - if ($rawEntity->entity_type === 'Bookstack\\Page') { | 327 | + if ($rawEntity->entity_type === 'BookStack\\Page') { |
| 328 | $entities[$index] = $this->page->newFromBuilder($rawEntity); | 328 | $entities[$index] = $this->page->newFromBuilder($rawEntity); |
| 329 | - } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') { | 329 | + } else if ($rawEntity->entity_type === 'BookStack\\Chapter') { |
| 330 | $entities[$index] = $this->chapter->newFromBuilder($rawEntity); | 330 | $entities[$index] = $this->chapter->newFromBuilder($rawEntity); |
| 331 | $key = $entities[$index]->entity_type . ':' . $entities[$index]->id; | 331 | $key = $entities[$index]->entity_type . ':' . $entities[$index]->id; |
| 332 | $parents[$key] = $entities[$index]; | 332 | $parents[$key] = $entities[$index]; |
| ... | @@ -338,7 +338,7 @@ class EntityRepo | ... | @@ -338,7 +338,7 @@ class EntityRepo |
| 338 | 338 | ||
| 339 | foreach ($entities as $entity) { | 339 | foreach ($entities as $entity) { |
| 340 | if ($entity->chapter_id === 0) continue; | 340 | if ($entity->chapter_id === 0) continue; |
| 341 | - $parentKey = 'Bookstack\\Chapter:' . $entity->chapter_id; | 341 | + $parentKey = 'BookStack\\Chapter:' . $entity->chapter_id; |
| 342 | $chapter = $parents[$parentKey]; | 342 | $chapter = $parents[$parentKey]; |
| 343 | $chapter->pages->push($entity); | 343 | $chapter->pages->push($entity); |
| 344 | } | 344 | } | ... | ... |
| ... | @@ -470,49 +470,35 @@ class PermissionService | ... | @@ -470,49 +470,35 @@ class PermissionService |
| 470 | return $q; | 470 | return $q; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | + /** | ||
| 474 | + * Get the children of a book in an efficient single query, Filtered by the permission system. | ||
| 475 | + * @param integer $book_id | ||
| 476 | + * @param bool $filterDrafts | ||
| 477 | + * @return \Illuminate\Database\Query\Builder | ||
| 478 | + */ | ||
| 473 | public function bookChildrenQuery($book_id, $filterDrafts = false) { | 479 | public function bookChildrenQuery($book_id, $filterDrafts = false) { |
| 474 | - | 480 | + $pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) { |
| 475 | - // Draft setup | 481 | + $query->where('draft', '=', 0); |
| 476 | - $params = [ | 482 | + if (!$filterDrafts) { |
| 477 | - 'userId' => $this->currentUser()->id, | 483 | + $query->orWhere(function($query) { |
| 478 | - 'bookIdPage' => $book_id, | 484 | + $query->where('draft', '=', 1)->where('created_by', '=', $this->currentUser()->id); |
| 479 | - 'bookIdChapter' => $book_id | 485 | + }); |
| 480 | - ]; | 486 | + } |
| 481 | - if (!$filterDrafts) { | 487 | + }); |
| 482 | - $params['userIdDrafts'] = $this->currentUser()->id; | 488 | + $chapterSelect = $this->db->table('chapters')->selectRaw("'BookStack\\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft")->where('book_id', '=', $book_id); |
| 483 | - } | 489 | + $whereQuery = $this->db->table('joint_permissions as jp')->selectRaw('COUNT(*)') |
| 484 | - // Role setup | 490 | + ->whereRaw('jp.entity_id=U.id')->whereRaw('jp.entity_type=U.entity_type') |
| 485 | - $userRoles = $this->getRoles(); | 491 | + ->where('jp.action', '=', 'view')->whereIn('jp.role_id', $this->getRoles()) |
| 486 | - $roleBindings = []; | 492 | + ->where(function($query) { |
| 487 | - $roleValues = []; | 493 | + $query->where('jp.has_permission', '=', 1)->orWhere(function($query) { |
| 488 | - foreach ($userRoles as $index => $roleId) { | 494 | + $query->where('jp.has_permission_own', '=', 1)->where('jp.created_by', '=', $this->currentUser()->id); |
| 489 | - $roleBindings[':role'.$index] = $roleId; | 495 | + }); |
| 490 | - $roleValues['role'.$index] = $roleId; | 496 | + }); |
| 491 | - } | 497 | + $query = $this->db->query()->select('*')->from($this->db->raw("({$pageSelect->toSql()} UNION {$chapterSelect->toSql()}) AS U")) |
| 492 | - // TODO - Clean this up, Maybe extract into a nice class for doing these kind of manual things | 498 | + ->mergeBindings($pageSelect)->mergeBindings($chapterSelect) |
| 493 | - // Something which will handle the above role crap in a nice clean way | 499 | + ->whereRaw("({$whereQuery->toSql()}) > 0")->mergeBindings($whereQuery)->orderBy('draft', 'desc')->orderBy('priority', 'asc'); |
| 494 | - $roleBindingString = implode(',', array_keys($roleBindings)); | ||
| 495 | - $query = "SELECT * from ( | ||
| 496 | -(SELECT 'Bookstack\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft FROM {$this->page->getTable()} | ||
| 497 | - where book_id = :bookIdPage AND ". ($filterDrafts ? '(draft = 0)' : '(draft = 0 OR (draft = 1 AND created_by = :userIdDrafts))') .") | ||
| 498 | -UNION | ||
| 499 | -(SELECT 'Bookstack\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft FROM {$this->chapter->getTable()} WHERE book_id = :bookIdChapter) | ||
| 500 | -) as U WHERE ( | ||
| 501 | - SELECT COUNT(*) FROM {$this->jointPermission->getTable()} jp | ||
| 502 | - WHERE | ||
| 503 | - jp.entity_id=U.id AND | ||
| 504 | - jp.entity_type=U.entity_type AND | ||
| 505 | - jp.action = 'view' AND | ||
| 506 | - jp.role_id IN ({$roleBindingString}) AND | ||
| 507 | - ( | ||
| 508 | - jp.has_permission = 1 OR | ||
| 509 | - (jp.has_permission_own = 1 AND jp.created_by = :userId) | ||
| 510 | - ) | ||
| 511 | -) > 0 | ||
| 512 | -ORDER BY draft desc, priority asc"; | ||
| 513 | - | ||
| 514 | $this->clean(); | 500 | $this->clean(); |
| 515 | - return $this->db->select($query, array_replace($roleValues, $params)); | 501 | + return $query; |
| 516 | } | 502 | } |
| 517 | 503 | ||
| 518 | /** | 504 | /** | ... | ... |
-
Please register or sign in to post a comment