Refactored common list handling operations to new class
This commit is contained in:
		
							parent
							
								
									f75091a1c5
								
							
						
					
					
						commit
						ec4cbbd004
					
				| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
namespace BookStack\Actions\Queries;
 | 
			
		||||
 | 
			
		||||
use BookStack\Actions\Webhook;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -10,19 +11,14 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		|||
 */
 | 
			
		||||
class WebhooksAllPaginatedAndSorted
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @param array{sort: string, order: string, search: string} $sortData
 | 
			
		||||
     */
 | 
			
		||||
    public function run(int $count, array $sortData): LengthAwarePaginator
 | 
			
		||||
    public function run(int $count, SimpleListOptions $listOptions): LengthAwarePaginator
 | 
			
		||||
    {
 | 
			
		||||
        $sort = $sortData['sort'];
 | 
			
		||||
 | 
			
		||||
        $query = Webhook::query()->select(['*'])
 | 
			
		||||
            ->withCount(['trackedEvents'])
 | 
			
		||||
            ->orderBy($sort, $sortData['order']);
 | 
			
		||||
            ->orderBy($listOptions->getSort(), $listOptions->getOrder());
 | 
			
		||||
 | 
			
		||||
        if ($sortData['search']) {
 | 
			
		||||
            $term = '%' . $sortData['search'] . '%';
 | 
			
		||||
        if ($listOptions->getSearch()) {
 | 
			
		||||
            $term = '%' . $listOptions->getSearch() . '%';
 | 
			
		||||
            $query->where(function ($query) use ($term) {
 | 
			
		||||
                $query->where('name', 'like', $term)
 | 
			
		||||
                    ->orWhere('endpoint', 'like', $term);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
namespace BookStack\Auth\Queries;
 | 
			
		||||
 | 
			
		||||
use BookStack\Auth\Role;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -10,22 +11,19 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		|||
 */
 | 
			
		||||
class RolesAllPaginatedAndSorted
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @param array{sort: string, order: string, search: string} $sortData
 | 
			
		||||
     */
 | 
			
		||||
    public function run(int $count, array $sortData): LengthAwarePaginator
 | 
			
		||||
    public function run(int $count, SimpleListOptions $listOptions): LengthAwarePaginator
 | 
			
		||||
    {
 | 
			
		||||
        $sort = $sortData['sort'];
 | 
			
		||||
        $sort = $listOptions->getSort();
 | 
			
		||||
        if ($sort === 'created_at') {
 | 
			
		||||
            $sort = 'users.created_at';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $query = Role::query()->select(['*'])
 | 
			
		||||
            ->withCount(['users', 'permissions'])
 | 
			
		||||
            ->orderBy($sort, $sortData['order']);
 | 
			
		||||
            ->orderBy($sort, $listOptions->getOrder());
 | 
			
		||||
 | 
			
		||||
        if ($sortData['search']) {
 | 
			
		||||
            $term = '%' . $sortData['search'] . '%';
 | 
			
		||||
        if ($listOptions->getSearch()) {
 | 
			
		||||
            $term = '%' . $listOptions->getSearch() . '%';
 | 
			
		||||
            $query->where(function ($query) use ($term) {
 | 
			
		||||
                $query->where('display_name', 'like', $term)
 | 
			
		||||
                    ->orWhere('description', 'like', $term);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
namespace BookStack\Auth\Queries;
 | 
			
		||||
 | 
			
		||||
use BookStack\Auth\User;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -13,12 +14,9 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		|||
 */
 | 
			
		||||
class UsersAllPaginatedAndSorted
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @param array{sort: string, order: string, search: string} $sortData
 | 
			
		||||
     */
 | 
			
		||||
    public function run(int $count, array $sortData): LengthAwarePaginator
 | 
			
		||||
    public function run(int $count, SimpleListOptions $listOptions): LengthAwarePaginator
 | 
			
		||||
    {
 | 
			
		||||
        $sort = $sortData['sort'];
 | 
			
		||||
        $sort = $listOptions->getSort();
 | 
			
		||||
        if ($sort === 'created_at') {
 | 
			
		||||
            $sort = 'users.created_at';
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -27,10 +25,10 @@ class UsersAllPaginatedAndSorted
 | 
			
		|||
            ->scopes(['withLastActivityAt'])
 | 
			
		||||
            ->with(['roles', 'avatar'])
 | 
			
		||||
            ->withCount('mfaValues')
 | 
			
		||||
            ->orderBy($sort, $sortData['order']);
 | 
			
		||||
            ->orderBy($sort, $listOptions->getOrder());
 | 
			
		||||
 | 
			
		||||
        if ($sortData['search']) {
 | 
			
		||||
            $term = '%' . $sortData['search'] . '%';
 | 
			
		||||
        if ($listOptions->getSearch()) {
 | 
			
		||||
            $term = '%' . $listOptions->getSearch() . '%';
 | 
			
		||||
            $query->where(function ($query) use ($term) {
 | 
			
		||||
                $query->where('name', 'like', $term)
 | 
			
		||||
                    ->orWhere('email', 'like', $term);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ use BookStack\Exceptions\ImageUploadException;
 | 
			
		|||
use BookStack\Exceptions\NotFoundException;
 | 
			
		||||
use BookStack\Facades\Activity;
 | 
			
		||||
use BookStack\References\ReferenceFetcher;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Validation\ValidationException;
 | 
			
		||||
use Throwable;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,13 +36,16 @@ class BookController extends Controller
 | 
			
		|||
    /**
 | 
			
		||||
     * Display a listing of the book.
 | 
			
		||||
     */
 | 
			
		||||
    public function index()
 | 
			
		||||
    public function index(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $view = setting()->getForCurrentUser('books_view_type');
 | 
			
		||||
        $sort = setting()->getForCurrentUser('books_sort', 'name');
 | 
			
		||||
        $order = setting()->getForCurrentUser('books_sort_order', 'asc');
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'books')->withSortOptions([
 | 
			
		||||
            'name' => trans('common.sort_name'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $books = $this->bookRepo->getAllPaginated(18, $sort, $order);
 | 
			
		||||
        $books = $this->bookRepo->getAllPaginated(18, $listOptions->getSort(), $listOptions->getOrder());
 | 
			
		||||
        $recents = $this->isSignedIn() ? $this->bookRepo->getRecentlyViewed(4) : false;
 | 
			
		||||
        $popular = $this->bookRepo->getPopular(4);
 | 
			
		||||
        $new = $this->bookRepo->getRecentlyCreated(4);
 | 
			
		||||
| 
						 | 
				
			
			@ -56,8 +60,7 @@ class BookController extends Controller
 | 
			
		|||
            'popular' => $popular,
 | 
			
		||||
            'new'     => $new,
 | 
			
		||||
            'view'    => $view,
 | 
			
		||||
            'sort'    => $sort,
 | 
			
		||||
            'order'   => $order,
 | 
			
		||||
            'listOptions' => $listOptions,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ use BookStack\Entities\Tools\ShelfContext;
 | 
			
		|||
use BookStack\Exceptions\ImageUploadException;
 | 
			
		||||
use BookStack\Exceptions\NotFoundException;
 | 
			
		||||
use BookStack\References\ReferenceFetcher;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Exception;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Validation\ValidationException;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,18 +31,16 @@ class BookshelfController extends Controller
 | 
			
		|||
    /**
 | 
			
		||||
     * Display a listing of the book.
 | 
			
		||||
     */
 | 
			
		||||
    public function index()
 | 
			
		||||
    public function index(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $view = setting()->getForCurrentUser('bookshelves_view_type');
 | 
			
		||||
        $sort = setting()->getForCurrentUser('bookshelves_sort', 'name');
 | 
			
		||||
        $order = setting()->getForCurrentUser('bookshelves_sort_order', 'asc');
 | 
			
		||||
        $sortOptions = [
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'bookshelves')->withSortOptions([
 | 
			
		||||
            'name'       => trans('common.sort_name'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
        ];
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $shelves = $this->shelfRepo->getAllPaginated(18, $sort, $order);
 | 
			
		||||
        $shelves = $this->shelfRepo->getAllPaginated(18, $listOptions->getSort(), $listOptions->getOrder());
 | 
			
		||||
        $recents = $this->isSignedIn() ? $this->shelfRepo->getRecentlyViewed(4) : false;
 | 
			
		||||
        $popular = $this->shelfRepo->getPopular(4);
 | 
			
		||||
        $new = $this->shelfRepo->getRecentlyCreated(4);
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +54,7 @@ class BookshelfController extends Controller
 | 
			
		|||
            'popular'     => $popular,
 | 
			
		||||
            'new'         => $new,
 | 
			
		||||
            'view'        => $view,
 | 
			
		||||
            'sort'        => $sort,
 | 
			
		||||
            'order'       => $order,
 | 
			
		||||
            'sortOptions' => $sortOptions,
 | 
			
		||||
            'listOptions' => $listOptions,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,16 +97,21 @@ class BookshelfController extends Controller
 | 
			
		|||
     *
 | 
			
		||||
     * @throws NotFoundException
 | 
			
		||||
     */
 | 
			
		||||
    public function show(ActivityQueries $activities, string $slug)
 | 
			
		||||
    public function show(Request $request, ActivityQueries $activities, string $slug)
 | 
			
		||||
    {
 | 
			
		||||
        $shelf = $this->shelfRepo->getBySlug($slug);
 | 
			
		||||
        $this->checkOwnablePermission('bookshelf-view', $shelf);
 | 
			
		||||
 | 
			
		||||
        $sort = setting()->getForCurrentUser('shelf_books_sort', 'default');
 | 
			
		||||
        $order = setting()->getForCurrentUser('shelf_books_sort_order', 'asc');
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([
 | 
			
		||||
            'default' => trans('common.sort_default'),
 | 
			
		||||
            'name' => trans('common.sort_name'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $sort = $listOptions->getSort();
 | 
			
		||||
        $sortedVisibleShelfBooks = $shelf->visibleBooks()->get()
 | 
			
		||||
            ->sortBy($sort === 'default' ? 'pivot.order' : $sort, SORT_REGULAR, $order === 'desc')
 | 
			
		||||
            ->sortBy($sort === 'default' ? 'pivot.order' : $sort, SORT_REGULAR, $listOptions->getOrder() === 'desc')
 | 
			
		||||
            ->values()
 | 
			
		||||
            ->all();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,8 +126,7 @@ class BookshelfController extends Controller
 | 
			
		|||
            'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
 | 
			
		||||
            'view'                    => $view,
 | 
			
		||||
            'activity'                => $activities->entityActivity($shelf, 20, 1),
 | 
			
		||||
            'order'                   => $order,
 | 
			
		||||
            'sort'                    => $sort,
 | 
			
		||||
            'listOptions'             => $listOptions,
 | 
			
		||||
            'referenceCount'          => $this->referenceFetcher->getPageReferenceCountToEntity($shelf),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ use BookStack\Auth\Permissions\PermissionsRepo;
 | 
			
		|||
use BookStack\Auth\Queries\RolesAllPaginatedAndSorted;
 | 
			
		||||
use BookStack\Auth\Role;
 | 
			
		||||
use BookStack\Exceptions\PermissionsException;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Exception;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Validation\ValidationException;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,20 +27,22 @@ class RoleController extends Controller
 | 
			
		|||
    {
 | 
			
		||||
        $this->checkPermission('user-roles-manage');
 | 
			
		||||
 | 
			
		||||
        $listDetails = [
 | 
			
		||||
            'search' => $request->get('search', ''),
 | 
			
		||||
            'sort'   => setting()->getForCurrentUser('roles_sort', 'display_name'),
 | 
			
		||||
            'order'  => setting()->getForCurrentUser('roles_sort_order', 'asc'),
 | 
			
		||||
        ];
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'roles')->withSortOptions([
 | 
			
		||||
            'display_name' => trans('common.sort_name'),
 | 
			
		||||
            'users_count' => trans('settings.roles_assigned_users'),
 | 
			
		||||
            'permissions_count' => trans('settings.roles_permissions_provided'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $roles = (new RolesAllPaginatedAndSorted())->run(20, $listDetails);
 | 
			
		||||
        $roles->appends(['search' => $listDetails['search']]);
 | 
			
		||||
        $roles = (new RolesAllPaginatedAndSorted())->run(20, $listOptions);
 | 
			
		||||
        $roles->appends($listOptions->getPaginationAppends());
 | 
			
		||||
 | 
			
		||||
        $this->setPageTitle(trans('settings.roles'));
 | 
			
		||||
 | 
			
		||||
        return view('settings.roles.index', [
 | 
			
		||||
            'roles'       => $roles,
 | 
			
		||||
            'listDetails' => $listDetails,
 | 
			
		||||
            'listOptions' => $listOptions,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ use BookStack\Auth\UserRepo;
 | 
			
		|||
use BookStack\Exceptions\ImageUploadException;
 | 
			
		||||
use BookStack\Exceptions\UserUpdateException;
 | 
			
		||||
use BookStack\Uploads\ImageRepo;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Exception;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,20 +37,23 @@ class UserController extends Controller
 | 
			
		|||
    public function index(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $this->checkPermission('users-manage');
 | 
			
		||||
        $listDetails = [
 | 
			
		||||
            'search' => $request->get('search', ''),
 | 
			
		||||
            'sort'   => setting()->getForCurrentUser('users_sort', 'name'),
 | 
			
		||||
            'order'  => setting()->getForCurrentUser('users_sort_order', 'asc'),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $users = (new UsersAllPaginatedAndSorted())->run(20, $listDetails);
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'users')->withSortOptions([
 | 
			
		||||
            'name' => trans('common.sort_name'),
 | 
			
		||||
            'email' => trans('auth.email'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
            'last_activity_at' => trans('settings.users_latest_activity'),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $users = (new UsersAllPaginatedAndSorted())->run(20, $listOptions);
 | 
			
		||||
 | 
			
		||||
        $this->setPageTitle(trans('settings.users'));
 | 
			
		||||
        $users->appends(['search' => $listDetails['search']]);
 | 
			
		||||
        $users->appends($listOptions->getPaginationAppends());
 | 
			
		||||
 | 
			
		||||
        return view('users.index', [
 | 
			
		||||
            'users'       => $users,
 | 
			
		||||
            'listDetails' => $listDetails,
 | 
			
		||||
            'listOptions' => $listOptions,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +260,18 @@ class UserController extends Controller
 | 
			
		|||
            return redirect()->back(500);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->changeListSort($id, $request, $type);
 | 
			
		||||
        $this->checkPermissionOrCurrentUser('users-manage', $id);
 | 
			
		||||
 | 
			
		||||
        $sort = substr($request->get('sort') ?: 'name', 0, 50);
 | 
			
		||||
        $order = $request->get('order') === 'desc' ? 'desc' : 'asc';
 | 
			
		||||
 | 
			
		||||
        $user = $this->userRepo->getById($id);
 | 
			
		||||
        $sortKey = $type . '_sort';
 | 
			
		||||
        $orderKey = $type . '_sort_order';
 | 
			
		||||
        setting()->putUser($user, $sortKey, $sort);
 | 
			
		||||
        setting()->putUser($user, $orderKey, $order);
 | 
			
		||||
 | 
			
		||||
        return redirect()->back(302, [], "/settings/users/{$id}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -309,36 +324,4 @@ class UserController extends Controller
 | 
			
		|||
 | 
			
		||||
        setting()->putUser(user(), 'code-language-favourites', implode(',', $currentFavorites));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Changed the stored preference for a list sort order.
 | 
			
		||||
     */
 | 
			
		||||
    protected function changeListSort(int $userId, Request $request, string $listName)
 | 
			
		||||
    {
 | 
			
		||||
        $this->checkPermissionOrCurrentUser('users-manage', $userId);
 | 
			
		||||
 | 
			
		||||
        $sort = $request->get('sort');
 | 
			
		||||
        // TODO - Need to find a better way to validate sort options
 | 
			
		||||
        //   Probably better to do a simple validation here then validate at usage.
 | 
			
		||||
        $validSorts = [
 | 
			
		||||
            'name', 'created_at', 'updated_at', 'default', 'email', 'last_activity_at', 'display_name',
 | 
			
		||||
            'users_count', 'permissions_count', 'endpoint', 'active',
 | 
			
		||||
        ];
 | 
			
		||||
        if (!in_array($sort, $validSorts)) {
 | 
			
		||||
            $sort = 'name';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $order = $request->get('order');
 | 
			
		||||
        if (!in_array($order, ['asc', 'desc'])) {
 | 
			
		||||
            $order = 'asc';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $user = $this->userRepo->getById($userId);
 | 
			
		||||
        $sortKey = $listName . '_sort';
 | 
			
		||||
        $orderKey = $listName . '_sort_order';
 | 
			
		||||
        setting()->putUser($user, $sortKey, $sort);
 | 
			
		||||
        setting()->putUser($user, $orderKey, $order);
 | 
			
		||||
 | 
			
		||||
        return redirect()->back(302, [], "/settings/users/$userId");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ namespace BookStack\Http\Controllers;
 | 
			
		|||
use BookStack\Actions\ActivityType;
 | 
			
		||||
use BookStack\Actions\Queries\WebhooksAllPaginatedAndSorted;
 | 
			
		||||
use BookStack\Actions\Webhook;
 | 
			
		||||
use BookStack\Util\SimpleListOptions;
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
 | 
			
		||||
class WebhookController extends Controller
 | 
			
		||||
| 
						 | 
				
			
			@ -21,20 +22,22 @@ class WebhookController extends Controller
 | 
			
		|||
     */
 | 
			
		||||
    public function index(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $listDetails = [
 | 
			
		||||
            'search' => $request->get('search', ''),
 | 
			
		||||
            'sort'   => setting()->getForCurrentUser('webhooks_sort', 'name'),
 | 
			
		||||
            'order'  => setting()->getForCurrentUser('webhooks_sort_order', 'asc'),
 | 
			
		||||
        ];
 | 
			
		||||
        $listOptions = SimpleListOptions::fromRequest($request, 'webhooks')->withSortOptions([
 | 
			
		||||
            'name' => trans('common.sort_name'),
 | 
			
		||||
            'endpoint'  => trans('settings.webhooks_endpoint'),
 | 
			
		||||
            'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
            'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
            'active'     => trans('common.status'),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $webhooks = (new WebhooksAllPaginatedAndSorted())->run(20, $listDetails);
 | 
			
		||||
        $webhooks->appends(['search' => $listDetails['search']]);
 | 
			
		||||
        $webhooks = (new WebhooksAllPaginatedAndSorted())->run(20, $listOptions);
 | 
			
		||||
        $webhooks->appends($listOptions->getPaginationAppends());
 | 
			
		||||
 | 
			
		||||
        $this->setPageTitle(trans('settings.webhooks'));
 | 
			
		||||
 | 
			
		||||
        return view('settings.webhooks.index', [
 | 
			
		||||
            'webhooks'    => $webhooks,
 | 
			
		||||
            'listDetails' => $listDetails,
 | 
			
		||||
            'listOptions' => $listOptions,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
namespace BookStack\Util;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Http\Request;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handled options commonly used for item lists within the system, providing a standard
 | 
			
		||||
 * model for handling and validating sort, order and search options.
 | 
			
		||||
 */
 | 
			
		||||
class SimpleListOptions
 | 
			
		||||
{
 | 
			
		||||
    protected string $typeKey;
 | 
			
		||||
    protected string $sort;
 | 
			
		||||
    protected string $order;
 | 
			
		||||
    protected string $search;
 | 
			
		||||
    protected array $sortOptions = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct(string $typeKey, string $sort, string $order, string $search = '')
 | 
			
		||||
    {
 | 
			
		||||
        $this->typeKey = $typeKey;
 | 
			
		||||
        $this->sort = $sort;
 | 
			
		||||
        $this->order = $order;
 | 
			
		||||
        $this->search = $search;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new instance from the given request.
 | 
			
		||||
     * Takes the item type (plural) that's used as a key for storing sort preferences.
 | 
			
		||||
     */
 | 
			
		||||
    public static function fromRequest(Request $request, string $typeKey): self
 | 
			
		||||
    {
 | 
			
		||||
        $search = $request->get('search', '');
 | 
			
		||||
        $sort = setting()->getForCurrentUser($typeKey . '_sort', '');
 | 
			
		||||
        $order = setting()->getForCurrentUser($typeKey . '_sort_order', 'asc');
 | 
			
		||||
 | 
			
		||||
        return new static($typeKey, $sort, $order, $search);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Configure the valid sort options for this set of list options.
 | 
			
		||||
     * Provided sort options must be an array, keyed by search properties
 | 
			
		||||
     * with values being user-visible option labels.
 | 
			
		||||
     * Returns current options for easy fluent usage during creation.
 | 
			
		||||
     */
 | 
			
		||||
    public function withSortOptions(array $sortOptions): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->sortOptions = array_merge($this->sortOptions, $sortOptions);
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the current order option.
 | 
			
		||||
     */
 | 
			
		||||
    public function getOrder(): string
 | 
			
		||||
    {
 | 
			
		||||
        return strtolower($this->order) === 'desc' ? 'desc' : 'asc';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the current sort option.
 | 
			
		||||
     */
 | 
			
		||||
    public function getSort(): string
 | 
			
		||||
    {
 | 
			
		||||
        $default = array_key_first($this->sortOptions) ?? 'name';
 | 
			
		||||
        $sort = $this->sort ?: $default;
 | 
			
		||||
 | 
			
		||||
        if (empty($this->sortOptions) || array_key_exists($sort, $this->sortOptions)) {
 | 
			
		||||
            return $sort;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $default;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the set search term.
 | 
			
		||||
     */
 | 
			
		||||
    public function getSearch(): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->search;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the data to append for pagination.
 | 
			
		||||
     */
 | 
			
		||||
    public function getPaginationAppends(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['search' => $this->search];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the data required by the sort control view.
 | 
			
		||||
     */
 | 
			
		||||
    public function getSortControlData(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'options' => $this->sortOptions,
 | 
			
		||||
            'order' => $this->getOrder(),
 | 
			
		||||
            'sort' => $this->getSort(),
 | 
			
		||||
            'type' => $this->typeKey,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
@extends('layouts.tri')
 | 
			
		||||
 | 
			
		||||
@section('body')
 | 
			
		||||
    @include('books.parts.list', ['books' => $books, 'view' => $view])
 | 
			
		||||
    @include('books.parts.list', ['books' => $books, 'view' => $view, 'listOptions' => $listOptions])
 | 
			
		||||
@stop
 | 
			
		||||
 | 
			
		||||
@section('left')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,13 +2,7 @@
 | 
			
		|||
    <div class="grid half v-center no-row-gap">
 | 
			
		||||
        <h1 class="list-heading">{{ trans('entities.books') }}</h1>
 | 
			
		||||
        <div class="text-m-right my-m">
 | 
			
		||||
 | 
			
		||||
            @include('common.sort', ['options' => [
 | 
			
		||||
                'name' => trans('common.sort_name'),
 | 
			
		||||
                'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
                'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
            ], 'order' => $order, 'sort' => $sort, 'type' => 'books'])
 | 
			
		||||
 | 
			
		||||
            @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    @if(count($books) > 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,18 +22,15 @@
 | 
			
		|||
                <div>
 | 
			
		||||
                    <div class="block inline mr-xs">
 | 
			
		||||
                        <form method="get" action="{{ url("/settings/roles") }}">
 | 
			
		||||
                            <input type="text" name="search" placeholder="{{ trans('common.search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
 | 
			
		||||
                            <input type="text"
 | 
			
		||||
                                   name="search"
 | 
			
		||||
                                   placeholder="{{ trans('common.search') }}"
 | 
			
		||||
                                   value="{{ $listOptions->getSearch() }}">
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="justify-flex-end">
 | 
			
		||||
                    @include('common.sort', ['options' => [
 | 
			
		||||
                        'display_name' => trans('common.sort_name'),
 | 
			
		||||
                        'users_count' => trans('settings.roles_assigned_users'),
 | 
			
		||||
                        'permissions_count' => trans('settings.roles_permissions_provided'),
 | 
			
		||||
                        'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
                        'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'roles'])
 | 
			
		||||
                    @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,18 +23,15 @@
 | 
			
		|||
                <div>
 | 
			
		||||
                    <div class="block inline mr-xs">
 | 
			
		||||
                        <form method="get" action="{{ url("/settings/webhooks") }}">
 | 
			
		||||
                            <input type="text" name="search" placeholder="{{ trans('common.search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
 | 
			
		||||
                            <input type="text"
 | 
			
		||||
                                   name="search"
 | 
			
		||||
                                   placeholder="{{ trans('common.search') }}"
 | 
			
		||||
                                   value="{{ $listOptions->getSearch() }}">
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="justify-flex-end">
 | 
			
		||||
                    @include('common.sort', ['options' => [
 | 
			
		||||
                        'name' => trans('common.sort_name'),
 | 
			
		||||
                        'endpoint'  => trans('settings.webhooks_endpoint'),
 | 
			
		||||
                        'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
                        'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
                        'active'     => trans('common.status'),
 | 
			
		||||
                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'webhooks'])
 | 
			
		||||
                    @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
@extends('layouts.tri')
 | 
			
		||||
 | 
			
		||||
@section('body')
 | 
			
		||||
    @include('shelves.parts.list', ['shelves' => $shelves, 'view' => $view])
 | 
			
		||||
    @include('shelves.parts.list', ['shelves' => $shelves, 'view' => $view, 'listOptions' => $listOptions])
 | 
			
		||||
@stop
 | 
			
		||||
 | 
			
		||||
@section('right')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
    <div class="grid half v-center">
 | 
			
		||||
        <h1 class="list-heading">{{ trans('entities.shelves') }}</h1>
 | 
			
		||||
        <div class="text-right">
 | 
			
		||||
            @include('common.sort', ['options' => $sortOptions, 'order' => $order, 'sort' => $sort, 'type' => 'bookshelves'])
 | 
			
		||||
            @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,12 +23,7 @@
 | 
			
		|||
            <h1 class="flex fit-content break-text">{{ $shelf->name }}</h1>
 | 
			
		||||
            <div class="flex"></div>
 | 
			
		||||
            <div class="flex fit-content text-m-right my-m ml-m">
 | 
			
		||||
                @include('common.sort', ['options' => [
 | 
			
		||||
                    'default' => trans('common.sort_default'),
 | 
			
		||||
                    'name' => trans('common.sort_name'),
 | 
			
		||||
                    'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
                    'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
                ], 'order' => $order, 'sort' => $sort, 'type' => 'shelf_books'])
 | 
			
		||||
                @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,18 +20,15 @@
 | 
			
		|||
                <div>
 | 
			
		||||
                    <div class="block inline mr-xs">
 | 
			
		||||
                        <form method="get" action="{{ url("/settings/users") }}">
 | 
			
		||||
                            <input type="text" name="search" placeholder="{{ trans('settings.users_search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
 | 
			
		||||
                            <input type="text"
 | 
			
		||||
                                   name="search"
 | 
			
		||||
                                   placeholder="{{ trans('settings.users_search') }}"
 | 
			
		||||
                                   value="{{ $listOptions->getSearch() }}">
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="justify-flex-end">
 | 
			
		||||
                    @include('common.sort', ['options' => [
 | 
			
		||||
                        'name' => trans('common.sort_name'),
 | 
			
		||||
                        'email' => trans('auth.email'),
 | 
			
		||||
                        'created_at' => trans('common.sort_created_at'),
 | 
			
		||||
                        'updated_at' => trans('common.sort_updated_at'),
 | 
			
		||||
                        'last_activity_at' => trans('settings.users_latest_activity'),
 | 
			
		||||
                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'users'])
 | 
			
		||||
                    @include('common.sort', $listOptions->getSortControlData())
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue