mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Started extraction of image controller to separate controllers
This commit is contained in:
parent
aeb1fc4d49
commit
a87ae16010
@ -732,18 +732,21 @@ class PermissionService
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters pages that are a direct relation to another item.
|
||||
* Add conditions to a query to filter the selection to related entities
|
||||
* where permissions are granted.
|
||||
* @param $entityType
|
||||
* @param $query
|
||||
* @param $tableName
|
||||
* @param $entityIdColumn
|
||||
* @return mixed
|
||||
*/
|
||||
public function filterRelatedPages($query, $tableName, $entityIdColumn)
|
||||
public function filterRelatedEntity($entityType, $query, $tableName, $entityIdColumn)
|
||||
{
|
||||
$this->currentAction = 'view';
|
||||
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn];
|
||||
|
||||
$pageMorphClass = $this->entityProvider->page->getMorphClass();
|
||||
$pageMorphClass = $this->entityProvider->get($entityType)->getMorphClass();
|
||||
|
||||
$q = $query->where(function ($query) use ($tableDetails, $pageMorphClass) {
|
||||
$query->where(function ($query) use (&$tableDetails, $pageMorphClass) {
|
||||
$query->whereExists(function ($permissionQuery) use (&$tableDetails, $pageMorphClass) {
|
||||
@ -761,7 +764,9 @@ class PermissionService
|
||||
});
|
||||
})->orWhere($tableDetails['entityIdColumn'], '=', 0);
|
||||
});
|
||||
|
||||
$this->clean();
|
||||
|
||||
return $q;
|
||||
}
|
||||
|
||||
|
@ -81,35 +81,6 @@ class ImageController extends Controller
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gallery images with a specific filter such as book or page
|
||||
* @param $filter
|
||||
* @param int $page
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function getGalleryFiltered(Request $request, $filter, $page = 0)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'uploaded_to' => 'required|integer'
|
||||
]);
|
||||
|
||||
$validFilters = collect(['page', 'book']);
|
||||
if (!$validFilters->contains($filter)) {
|
||||
return response('Invalid filter', 500);
|
||||
}
|
||||
|
||||
$pageId = $request->get('uploaded_to');
|
||||
$imgData = $this->imageRepo->getGalleryFiltered(strtolower($filter), $pageId, $page, 24);
|
||||
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
public function uploadGalleryImage(Request $request)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public function uploadUserImage(Request $request)
|
||||
{
|
||||
// TODO
|
||||
|
95
app/Http/Controllers/Images/CoverImageController.php
Normal file
95
app/Http/Controllers/Images/CoverImageController.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers\Images;
|
||||
|
||||
use BookStack\Entities\EntityProvider;
|
||||
use BookStack\Entities\Repos\EntityRepo;
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use BookStack\Http\Controllers\Controller;
|
||||
|
||||
class CoverImageController extends Controller
|
||||
{
|
||||
protected $imageRepo;
|
||||
protected $entityRepo;
|
||||
|
||||
/**
|
||||
* CoverImageController constructor.
|
||||
* @param ImageRepo $imageRepo
|
||||
* @param EntityRepo $entityRepo
|
||||
*/
|
||||
public function __construct(ImageRepo $imageRepo, EntityRepo $entityRepo)
|
||||
{
|
||||
$this->imageRepo = $imageRepo;
|
||||
$this->entityRepo = $entityRepo;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of cover images, in a list.
|
||||
* Can be paged and filtered by entity.
|
||||
* @param Request $request
|
||||
* @param string $entity
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function list(Request $request, $entity)
|
||||
{
|
||||
if (!$this->isValidEntityTypeForCover($entity)) {
|
||||
return $this->jsonError(trans('errors.image_upload_type_error'));
|
||||
}
|
||||
|
||||
$page = $request->get('page', 1);
|
||||
$searchTerm = $request->get('search', null);
|
||||
|
||||
$type = 'cover_' . $entity;
|
||||
$imgData = $this->imageRepo->getPaginatedByType($type, $page, 24, null, $searchTerm);
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new cover image in the system.
|
||||
* @param Request $request
|
||||
* @param string $entity
|
||||
* @return Illuminate\Http\JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(Request $request, $entity)
|
||||
{
|
||||
$this->checkPermission('image-create-all');
|
||||
$this->validate($request, [
|
||||
'file' => $this->imageRepo->getImageValidationRules(),
|
||||
'uploaded_to' => 'required|integer'
|
||||
]);
|
||||
|
||||
if (!$this->isValidEntityTypeForCover($entity)) {
|
||||
return $this->jsonError(trans('errors.image_upload_type_error'));
|
||||
}
|
||||
|
||||
$uploadedTo = $request->get('uploaded_to', 0);
|
||||
$entityInstance = $this->entityRepo->getById($entity, $uploadedTo);
|
||||
$this->checkOwnablePermission($entity . '-update', $entityInstance);
|
||||
|
||||
try {
|
||||
$type = 'cover_' . $entity;
|
||||
$imageUpload = $request->file('file');
|
||||
$image = $this->imageRepo->saveNew($imageUpload, $type, $uploadedTo);
|
||||
} catch (ImageUploadException $e) {
|
||||
return response($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response()->json($image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given entity type is valid entity to have cover images.
|
||||
* @param string $entityType
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidEntityTypeForCover(string $entityType)
|
||||
{
|
||||
return ($entityType === 'book' || $entityType === 'bookshelf');
|
||||
}
|
||||
|
||||
}
|
67
app/Http/Controllers/Images/DrawioImageController.php
Normal file
67
app/Http/Controllers/Images/DrawioImageController.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers\Images;
|
||||
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use BookStack\Http\Controllers\Controller;
|
||||
|
||||
class DrawioImageController extends Controller
|
||||
{
|
||||
protected $imageRepo;
|
||||
|
||||
/**
|
||||
* DrawioImageController constructor.
|
||||
* @param ImageRepo $imageRepo
|
||||
*/
|
||||
public function __construct(ImageRepo $imageRepo)
|
||||
{
|
||||
$this->imageRepo = $imageRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of gallery images, in a list.
|
||||
* Can be paged and filtered by entity.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = $request->get('page', 1);
|
||||
$searchTerm = $request->get('search', null);
|
||||
$uploadedToFilter = $request->get('uploaded_to', null);
|
||||
$parentTypeFilter = $request->get('filter_type', null);
|
||||
|
||||
$imgData = $this->imageRepo->getEntityFiltered('drawio', $parentTypeFilter, $page, 24, $uploadedToFilter, $searchTerm);
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new gallery image in the system.
|
||||
* @param Request $request
|
||||
* @return Illuminate\Http\JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'image' => 'required|string',
|
||||
'uploaded_to' => 'required|integer'
|
||||
]);
|
||||
|
||||
$this->checkPermission('image-create-all');
|
||||
$imageBase64Data = $request->get('image');
|
||||
|
||||
try {
|
||||
$uploadedTo = $request->get('uploaded_to', 0);
|
||||
$image = $this->imageRepo->saveDrawing($imageBase64Data, $uploadedTo);
|
||||
} catch (ImageUploadException $e) {
|
||||
return response($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response()->json($image);
|
||||
}
|
||||
|
||||
}
|
65
app/Http/Controllers/Images/GalleryImageController.php
Normal file
65
app/Http/Controllers/Images/GalleryImageController.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers\Images;
|
||||
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use BookStack\Http\Controllers\Controller;
|
||||
|
||||
class GalleryImageController extends Controller
|
||||
{
|
||||
protected $imageRepo;
|
||||
|
||||
/**
|
||||
* GalleryImageController constructor.
|
||||
* @param ImageRepo $imageRepo
|
||||
*/
|
||||
public function __construct(ImageRepo $imageRepo)
|
||||
{
|
||||
$this->imageRepo = $imageRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of gallery images, in a list.
|
||||
* Can be paged and filtered by entity.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = $request->get('page', 1);
|
||||
$searchTerm = $request->get('search', null);
|
||||
$uploadedToFilter = $request->get('uploaded_to', null);
|
||||
$parentTypeFilter = $request->get('filter_type', null);
|
||||
|
||||
$imgData = $this->imageRepo->getEntityFiltered('gallery', $parentTypeFilter, $page, 24, $uploadedToFilter, $searchTerm);
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new gallery image in the system.
|
||||
* @param Request $request
|
||||
* @return Illuminate\Http\JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->checkPermission('image-create-all');
|
||||
$this->validate($request, [
|
||||
'file' => $this->imageRepo->getImageValidationRules()
|
||||
]);
|
||||
|
||||
try {
|
||||
$imageUpload = $request->file('file');
|
||||
$uploadedTo = $request->get('uploaded_to', 0);
|
||||
$image = $this->imageRepo->saveNew($imageUpload, 'gallery', $uploadedTo);
|
||||
} catch (ImageUploadException $e) {
|
||||
return response($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response()->json($image);
|
||||
}
|
||||
|
||||
}
|
64
app/Http/Controllers/Images/SystemImageController.php
Normal file
64
app/Http/Controllers/Images/SystemImageController.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers\Images;
|
||||
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use BookStack\Http\Controllers\Controller;
|
||||
|
||||
class SystemImageController extends Controller
|
||||
{
|
||||
protected $imageRepo;
|
||||
|
||||
/**
|
||||
* SystemImageController constructor.
|
||||
* @param ImageRepo $imageRepo
|
||||
*/
|
||||
public function __construct(ImageRepo $imageRepo)
|
||||
{
|
||||
$this->imageRepo = $imageRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of system images, in a list.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$this->checkPermission('settings-manage');
|
||||
$page = $request->get('page', 1);
|
||||
$searchTerm = $request->get('search', null);
|
||||
|
||||
$imgData = $this->imageRepo->getPaginatedByType('system', $page, 24, null, $searchTerm);
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new system image.
|
||||
* @param Request $request
|
||||
* @return Illuminate\Http\JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->checkPermission('image-create-all');
|
||||
$this->checkPermission('settings-manage');
|
||||
|
||||
$this->validate($request, [
|
||||
'file' => $this->imageRepo->getImageValidationRules()
|
||||
]);
|
||||
|
||||
try {
|
||||
$imageUpload = $request->file('file');
|
||||
$image = $this->imageRepo->saveNew($imageUpload, 'system', 0);
|
||||
} catch (ImageUploadException $e) {
|
||||
return response($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response()->json($image);
|
||||
}
|
||||
|
||||
}
|
70
app/Http/Controllers/Images/UserImageController.php
Normal file
70
app/Http/Controllers/Images/UserImageController.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers\Images;
|
||||
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Uploads\ImageRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use BookStack\Http\Controllers\Controller;
|
||||
|
||||
class UserImageController extends Controller
|
||||
{
|
||||
protected $imageRepo;
|
||||
|
||||
/**
|
||||
* UserImageController constructor.
|
||||
* @param ImageRepo $imageRepo
|
||||
*/
|
||||
public function __construct(ImageRepo $imageRepo)
|
||||
{
|
||||
$this->imageRepo = $imageRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of user profile images, in a list.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function list(Request $request)
|
||||
{
|
||||
$page = $request->get('page', 1);
|
||||
$searchTerm = $request->get('search', null);
|
||||
$userId = $request->get('uploaded_to', null);
|
||||
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $userId);
|
||||
|
||||
$imgData = $this->imageRepo->getPaginatedByType('user', $page, 24, $userId, $searchTerm);
|
||||
return response()->json($imgData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new user profile image in the system.
|
||||
* @param Request $request
|
||||
* @return Illuminate\Http\JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->checkPermission('image-create-all');
|
||||
|
||||
$this->validate($request, [
|
||||
'uploaded_to' => 'required|integer',
|
||||
'file' => $this->imageRepo->getImageValidationRules()
|
||||
]);
|
||||
|
||||
$userId = $request->get('uploaded_to', null);
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $userId);
|
||||
|
||||
try {
|
||||
$imageUpload = $request->file('file');
|
||||
$uploadedTo = $request->get('uploaded_to', 0);
|
||||
$image = $this->imageRepo->saveNew($imageUpload, 'user', $uploadedTo);
|
||||
} catch (ImageUploadException $e) {
|
||||
return response($e->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response()->json($image);
|
||||
}
|
||||
|
||||
}
|
@ -107,9 +107,7 @@ class UserController extends Controller
|
||||
*/
|
||||
public function edit($id, SocialAuthService $socialAuthService)
|
||||
{
|
||||
$this->checkPermissionOr('users-manage', function () use ($id) {
|
||||
return $this->currentUser->id == $id;
|
||||
});
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $id);
|
||||
|
||||
$user = $this->user->findOrFail($id);
|
||||
|
||||
@ -131,9 +129,7 @@ class UserController extends Controller
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$this->preventAccessForDemoUsers();
|
||||
$this->checkPermissionOr('users-manage', function () use ($id) {
|
||||
return $this->currentUser->id == $id;
|
||||
});
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $id);
|
||||
|
||||
$this->validate($request, [
|
||||
'name' => 'min:2',
|
||||
@ -184,9 +180,7 @@ class UserController extends Controller
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->checkPermissionOr('users-manage', function () use ($id) {
|
||||
return $this->currentUser->id == $id;
|
||||
});
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $id);
|
||||
|
||||
$user = $this->userRepo->getById($id);
|
||||
$this->setPageTitle(trans('settings.users_delete_named', ['userName' => $user->name]));
|
||||
@ -202,9 +196,7 @@ class UserController extends Controller
|
||||
public function destroy($id)
|
||||
{
|
||||
$this->preventAccessForDemoUsers();
|
||||
$this->checkPermissionOr('users-manage', function () use ($id) {
|
||||
return $this->currentUser->id == $id;
|
||||
});
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $id);
|
||||
|
||||
$user = $this->userRepo->getById($id);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
use BookStack\Auth\Permissions\PermissionService;
|
||||
use BookStack\Entities\Page;
|
||||
use BookStack\Http\Requests\Request;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
class ImageRepo
|
||||
@ -20,7 +21,12 @@ class ImageRepo
|
||||
* @param \BookStack\Auth\Permissions\PermissionService $permissionService
|
||||
* @param \BookStack\Entities\Page $page
|
||||
*/
|
||||
public function __construct(Image $image, ImageService $imageService, PermissionService $permissionService, Page $page)
|
||||
public function __construct(
|
||||
Image $image,
|
||||
ImageService $imageService,
|
||||
PermissionService $permissionService,
|
||||
Page $page
|
||||
)
|
||||
{
|
||||
$this->image = $image;
|
||||
$this->imageService = $imageService;
|
||||
@ -48,92 +54,104 @@ class ImageRepo
|
||||
* @param bool $filterOnPage
|
||||
* @return array
|
||||
*/
|
||||
private function returnPaginated($query, $page = 0, $pageSize = 24)
|
||||
private function returnPaginated($query, $page = 1, $pageSize = 24)
|
||||
{
|
||||
$images = $query->orderBy('created_at', 'desc')->skip($pageSize * $page)->take($pageSize + 1)->get();
|
||||
$images = $query->orderBy('created_at', 'desc')->skip($pageSize * ($page - 1))->take($pageSize + 1)->get();
|
||||
$hasMore = count($images) > $pageSize;
|
||||
|
||||
$returnImages = $images->take(24);
|
||||
$returnImages = $images->take($pageSize);
|
||||
$returnImages->each(function ($image) {
|
||||
$this->loadThumbs($image);
|
||||
});
|
||||
|
||||
return [
|
||||
'images' => $returnImages,
|
||||
'hasMore' => $hasMore
|
||||
'has_more' => $hasMore
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a load images paginated, filtered by image type.
|
||||
* Fetch a list of images in a paginated format, filtered by image type.
|
||||
* Can be filtered by uploaded to and also by name.
|
||||
* @param string $type
|
||||
* @param int $page
|
||||
* @param int $pageSize
|
||||
* @param int $uploadedTo
|
||||
* @param string|null $search
|
||||
* @param callable|null $whereClause
|
||||
* @return array
|
||||
*/
|
||||
public function getPaginatedByType(string $type, int $page = 0, int $pageSize = 24, int $uploadedTo = null)
|
||||
public function getPaginatedByType(
|
||||
string $type,
|
||||
int $page = 0,
|
||||
int $pageSize = 24,
|
||||
int $uploadedTo = null,
|
||||
string $search = null,
|
||||
callable $whereClause = null
|
||||
)
|
||||
{
|
||||
$images = $this->image->newQuery()->where('type', '=', strtolower($type));
|
||||
$imageQuery = $this->image->newQuery()->where('type', '=', strtolower($type));
|
||||
|
||||
if ($uploadedTo !== null) {
|
||||
$images = $images->where('uploaded_to', '=', $uploadedTo);
|
||||
$imageQuery = $imageQuery->where('uploaded_to', '=', $uploadedTo);
|
||||
}
|
||||
|
||||
if ($search !== null) {
|
||||
$imageQuery = $imageQuery->where('name', 'LIKE', '%' . $search . '%');
|
||||
}
|
||||
|
||||
// Filter by page access if gallery
|
||||
if ($type === 'gallery') {
|
||||
$images = $this->restrictionService->filterRelatedPages($images, 'images', 'uploaded_to');
|
||||
$imageQuery = $this->restrictionService->filterRelatedEntity('page', $imageQuery, 'images', 'uploaded_to');
|
||||
}
|
||||
|
||||
return $this->returnPaginated($images, $page, $pageSize);
|
||||
// Filter by entity if cover
|
||||
if (strpos($type, 'cover_') === 0) {
|
||||
$entityType = explode('_', $type)[1];
|
||||
$imageQuery = $this->restrictionService->filterRelatedEntity($entityType, $imageQuery, 'images', 'uploaded_to');
|
||||
}
|
||||
|
||||
if ($whereClause !== null) {
|
||||
$imageQuery = $imageQuery->where($whereClause);
|
||||
}
|
||||
|
||||
return $this->returnPaginated($imageQuery, $page, $pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for images by query, of a particular type.
|
||||
* Get paginated gallery images within a specific page or book.
|
||||
* @param string $type
|
||||
* @param string $filterType
|
||||
* @param int $page
|
||||
* @param int $pageSize
|
||||
* @param string $searchTerm
|
||||
* @param int|null $uploadedTo
|
||||
* @param string|null $search
|
||||
* @return array
|
||||
*/
|
||||
public function searchPaginatedByType(Request $request, $type, $searchTerm, $page = 0, $pageSize = 24)
|
||||
public function getEntityFiltered(
|
||||
string $type,
|
||||
string $filterType = null,
|
||||
int $page = 0,
|
||||
int $pageSize = 24,
|
||||
int $uploadedTo = null,
|
||||
string $search = null
|
||||
)
|
||||
{
|
||||
// TODO - Filter by uploaded_to
|
||||
$images = $this->image->newQuery()
|
||||
->where('type', '=', strtolower($type))
|
||||
->where('name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$contextPage = $this->page->findOrFail($uploadedTo);
|
||||
$parentFilter = null;
|
||||
|
||||
if ($type === 'gallery') {
|
||||
$images = $this->restrictionService->filterRelatedPages($images, 'images', 'uploaded_to');
|
||||
if ($filterType === 'book' || $filterType === 'page') {
|
||||
$parentFilter = function(Builder $query) use ($filterType, $contextPage) {
|
||||
if ($filterType === 'page') {
|
||||
$query->where('uploaded_to', '=', $contextPage->id);
|
||||
} elseif ($filterType === 'book') {
|
||||
$validPageIds = $contextPage->book->pages()->get(['id'])->pluck('id')->toArray();
|
||||
$query->whereIn('uploaded_to', $validPageIds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return $this->returnPaginated($images, $page, $pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gallery images with a particular filter criteria such as
|
||||
* being within the current book or page.
|
||||
* @param $filter
|
||||
* @param $pageId
|
||||
* @param int $pageNum
|
||||
* @param int $pageSize
|
||||
* @return array
|
||||
*/
|
||||
public function getGalleryFiltered($filter, $pageId, $pageNum = 0, $pageSize = 24)
|
||||
{
|
||||
$images = $this->image->where('type', '=', 'gallery');
|
||||
|
||||
$page = $this->page->findOrFail($pageId);
|
||||
|
||||
if ($filter === 'page') {
|
||||
$images = $images->where('uploaded_to', '=', $page->id);
|
||||
} elseif ($filter === 'book') {
|
||||
$validPageIds = $page->book->pages->pluck('id')->toArray();
|
||||
$images = $images->whereIn('uploaded_to', $validPageIds);
|
||||
}
|
||||
|
||||
$images = $this->restrictionService->filterRelatedPages($images, 'images', 'uploaded_to');
|
||||
return $this->returnPaginated($images, $pageNum, $pageSize);
|
||||
return $this->getPaginatedByType($type, $page, $pageSize, null, $search, $parentFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,7 +271,17 @@ class ImageRepo
|
||||
*/
|
||||
public function isValidType($type)
|
||||
{
|
||||
// TODO - To delete?
|
||||
$validTypes = ['gallery', 'cover', 'system', 'user'];
|
||||
return in_array($type, $validTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for image files.
|
||||
* @return string
|
||||
*/
|
||||
public function getImageValidationRules()
|
||||
{
|
||||
return 'image_extension|no_double_extension|mimes:jpeg,png,gif,bmp,webp,tiff';
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,17 @@ class SetUserProfileImagesUploadedTo extends Migration
|
||||
->update([
|
||||
'uploaded_to' => DB::raw('`created_by`')
|
||||
]);
|
||||
|
||||
DB::table('images')
|
||||
->where('type', '=', 'cover')
|
||||
->update(['type' => 'cover_book']);
|
||||
|
||||
$firstBook = DB::table('books')->first(['id']);
|
||||
if ($firstBook) {
|
||||
DB::table('images')
|
||||
->where('type', '=', 'cover_book')
|
||||
->update(['uploaded_to' => $firstBook->id]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,5 +43,9 @@ class SetUserProfileImagesUploadedTo extends Migration
|
||||
->update([
|
||||
'uploaded_to' => 0
|
||||
]);
|
||||
|
||||
DB::table('images')
|
||||
->where('type', '=', 'cover_book')
|
||||
->update(['type' => 'cover', 'uploaded_to' => 0]);
|
||||
}
|
||||
}
|
||||
|
@ -257,39 +257,38 @@ function drawIoPlugin() {
|
||||
DrawIO.show(drawingInit, updateContent);
|
||||
}
|
||||
|
||||
function updateContent(pngData) {
|
||||
let id = "image-" + Math.random().toString(16).slice(2);
|
||||
let loadingImage = window.baseUrl('/loading.gif');
|
||||
let data = {
|
||||
image: pngData,
|
||||
uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
|
||||
};
|
||||
async function updateContent(pngData) {
|
||||
const id = "image-" + Math.random().toString(16).slice(2);
|
||||
const loadingImage = window.baseUrl('/loading.gif');
|
||||
const pageId = Number(document.getElementById('page-editor').getAttribute('page-id'));
|
||||
|
||||
// Handle updating an existing image
|
||||
if (currentNode) {
|
||||
DrawIO.close();
|
||||
let imgElem = currentNode.querySelector('img');
|
||||
window.$http.post(window.baseUrl(`/images/drawing/upload`), data).then(resp => {
|
||||
pageEditor.dom.setAttrib(imgElem, 'src', resp.data.url);
|
||||
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', resp.data.id);
|
||||
}).catch(err => {
|
||||
try {
|
||||
const img = await DrawIO.upload(pngData, pageId);
|
||||
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
|
||||
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
|
||||
} catch (err) {
|
||||
window.$events.emit('error', trans('errors.image_upload_error'));
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" id="${id}"></div>`);
|
||||
DrawIO.close();
|
||||
window.$http.post(window.baseUrl('/images/drawing/upload'), data).then(resp => {
|
||||
pageEditor.dom.setAttrib(id, 'src', resp.data.url);
|
||||
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', resp.data.id);
|
||||
}).catch(err => {
|
||||
try {
|
||||
const img = await DrawIO.upload(pngData, pageId);
|
||||
pageEditor.dom.setAttrib(id, 'src', img.url);
|
||||
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
|
||||
} catch (err) {
|
||||
pageEditor.dom.remove(id);
|
||||
window.$events.emit('error', trans('errors.image_upload_error'));
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
}, 5);
|
||||
}
|
||||
|
||||
|
@ -66,4 +66,13 @@ function drawPostMessage(data) {
|
||||
iFrame.contentWindow.postMessage(JSON.stringify(data), '*');
|
||||
}
|
||||
|
||||
export default {show, close};
|
||||
async function upload(imageData, pageUploadedToId) {
|
||||
let data = {
|
||||
image: imageData,
|
||||
uploaded_to: pageUploadedToId,
|
||||
};
|
||||
const resp = await window.$http.post(window.baseUrl(`/images/drawio`), data);
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
export default {show, close, upload};
|
@ -1,7 +1,7 @@
|
||||
import * as Dates from "../services/dates";
|
||||
import dropzone from "./components/dropzone";
|
||||
|
||||
let page = 0;
|
||||
let page = 1;
|
||||
let previousClickTime = 0;
|
||||
let previousClickImage = 0;
|
||||
let dataLoaded = false;
|
||||
@ -20,7 +20,7 @@ const data = {
|
||||
selectedImage: false,
|
||||
dependantPages: false,
|
||||
showing: false,
|
||||
view: 'all',
|
||||
filter: null,
|
||||
hasMore: false,
|
||||
searching: false,
|
||||
searchTerm: '',
|
||||
@ -56,32 +56,37 @@ const methods = {
|
||||
this.$el.children[0].components.overlay.hide();
|
||||
},
|
||||
|
||||
fetchData() {
|
||||
let url = baseUrl + page;
|
||||
let query = {};
|
||||
if (this.uploadedTo !== false) query.uploaded_to = this.uploadedTo;
|
||||
if (this.searching) query.term = this.searchTerm;
|
||||
async fetchData() {
|
||||
let query = {
|
||||
page,
|
||||
search: this.searching ? this.searchTerm : null,
|
||||
uploaded_to: this.uploadedTo || null,
|
||||
filter_type: this.filter,
|
||||
};
|
||||
|
||||
this.$http.get(url, {params: query}).then(response => {
|
||||
this.images = this.images.concat(response.data.images);
|
||||
this.hasMore = response.data.hasMore;
|
||||
const {data} = await this.$http.get(baseUrl, {params: query});
|
||||
this.images = this.images.concat(data.images);
|
||||
this.hasMore = data.has_more;
|
||||
page++;
|
||||
});
|
||||
},
|
||||
|
||||
setView(viewName) {
|
||||
this.view = viewName;
|
||||
setFilterType(filterType) {
|
||||
this.filter = filterType;
|
||||
this.resetState();
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
resetState() {
|
||||
this.cancelSearch();
|
||||
this.resetListView();
|
||||
this.deleteConfirm = false;
|
||||
baseUrl = window.baseUrl(`/images/${this.imageType}`);
|
||||
},
|
||||
|
||||
resetListView() {
|
||||
this.images = [];
|
||||
this.hasMore = false;
|
||||
this.deleteConfirm = false;
|
||||
page = 0;
|
||||
baseUrl = window.baseUrl(`/images/${this.imageType}/${this.view}/`);
|
||||
page = 1;
|
||||
},
|
||||
|
||||
searchImages() {
|
||||
@ -94,10 +99,7 @@ const methods = {
|
||||
}
|
||||
|
||||
this.searching = true;
|
||||
this.images = [];
|
||||
this.hasMore = false;
|
||||
page = 0;
|
||||
baseUrl = window.baseUrl(`/images/${this.imageType}/search/`);
|
||||
this.resetListView();
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
@ -110,10 +112,10 @@ const methods = {
|
||||
},
|
||||
|
||||
imageSelect(image) {
|
||||
let dblClickTime = 300;
|
||||
let currentTime = Date.now();
|
||||
let timeDiff = currentTime - previousClickTime;
|
||||
let isDblClick = timeDiff < dblClickTime && image.id === previousClickImage;
|
||||
const dblClickTime = 300;
|
||||
const currentTime = Date.now();
|
||||
const timeDiff = currentTime - previousClickTime;
|
||||
const isDblClick = timeDiff < dblClickTime && image.id === previousClickImage;
|
||||
|
||||
if (isDblClick) {
|
||||
this.callbackAndHide(image);
|
||||
@ -132,11 +134,11 @@ const methods = {
|
||||
this.hide();
|
||||
},
|
||||
|
||||
saveImageDetails() {
|
||||
async saveImageDetails() {
|
||||
let url = window.baseUrl(`/images/${this.selectedImage.id}`);
|
||||
this.$http.put(url, this.selectedImage).then(response => {
|
||||
this.$events.emit('success', trans('components.image_update_success'));
|
||||
}).catch(error => {
|
||||
try {
|
||||
await this.$http.put(url, this.selectedImage)
|
||||
} catch (error) {
|
||||
if (error.response.status === 422) {
|
||||
let errors = error.response.data;
|
||||
let message = '';
|
||||
@ -145,27 +147,29 @@ const methods = {
|
||||
});
|
||||
this.$events.emit('error', message);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
deleteImage() {
|
||||
async deleteImage() {
|
||||
|
||||
if (!this.deleteConfirm) {
|
||||
let url = window.baseUrl(`/images/usage/${this.selectedImage.id}`);
|
||||
this.$http.get(url).then(resp => {
|
||||
this.dependantPages = resp.data;
|
||||
}).catch(console.error).then(() => {
|
||||
const url = window.baseUrl(`/images/usage/${this.selectedImage.id}`);
|
||||
try {
|
||||
const {data} = await this.$http.get(url);
|
||||
this.dependantPages = data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
this.deleteConfirm = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
let url = window.baseUrl(`/images/${this.selectedImage.id}`);
|
||||
this.$http.delete(url).then(resp => {
|
||||
|
||||
const url = window.baseUrl(`/images/${this.selectedImage.id}`);
|
||||
await this.$http.delete(url);
|
||||
this.images.splice(this.images.indexOf(this.selectedImage), 1);
|
||||
this.selectedImage = false;
|
||||
this.$events.emit('success', trans('components.image_delete_success'));
|
||||
this.deleteConfirm = false;
|
||||
});
|
||||
},
|
||||
|
||||
getDate(stringDate) {
|
||||
@ -180,7 +184,7 @@ const methods = {
|
||||
|
||||
const computed = {
|
||||
uploadUrl() {
|
||||
return window.baseUrl(`/images/${this.imageType}/upload`);
|
||||
return window.baseUrl(`/images/${this.imageType}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -188,7 +192,7 @@ function mounted() {
|
||||
window.ImageManager = this;
|
||||
this.imageType = this.$el.getAttribute('image-type');
|
||||
this.uploadedTo = this.$el.getAttribute('uploaded-to');
|
||||
baseUrl = window.baseUrl('/images/' + this.imageType + '/all/')
|
||||
baseUrl = window.baseUrl('/images/' + this.imageType)
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -23,5 +23,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('components.image-manager', ['imageType' => 'cover'])
|
||||
@include('components.image-manager', ['imageType' => 'cover', 'uploaded_to'])
|
||||
@stop
|
@ -10,12 +10,12 @@
|
||||
<div class="flex-fill image-manager-body">
|
||||
|
||||
<div class="image-manager-content">
|
||||
<div v-if="imageType === 'gallery'" class="image-manager-header primary-background-light nav-tabs grid third">
|
||||
<div class="tab-item" title="{{ trans('components.image_all_title') }}" :class="{selected: (view=='all')}" @click="setView('all')">@icon('images') {{ trans('components.image_all') }}</div>
|
||||
<div class="tab-item" title="{{ trans('components.image_book_title') }}" :class="{selected: (view=='book')}" @click="setView('book')">@icon('book', ['class' => 'text-book svg-icon']) {{ trans('entities.book') }}</div>
|
||||
<div class="tab-item" title="{{ trans('components.image_page_title') }}" :class="{selected: (view=='page')}" @click="setView('page')">@icon('page', ['class' => 'text-page svg-icon']) {{ trans('entities.page') }}</div>
|
||||
<div v-if="imageType === 'gallery' || imageType === 'drawio'" class="image-manager-header primary-background-light nav-tabs grid third">
|
||||
<div class="tab-item" title="{{ trans('components.image_all_title') }}" :class="{selected: !filter}" @click="setFilterType(null)">@icon('images') {{ trans('components.image_all') }}</div>
|
||||
<div class="tab-item" title="{{ trans('components.image_book_title') }}" :class="{selected: (filter=='book')}" @click="setFilterType('book')">@icon('book', ['class' => 'text-book svg-icon']) {{ trans('entities.book') }}</div>
|
||||
<div class="tab-item" title="{{ trans('components.image_page_title') }}" :class="{selected: (filter=='page')}" @click="setFilterType('page')">@icon('page', ['class' => 'text-page svg-icon']) {{ trans('entities.page') }}</div>
|
||||
</div>
|
||||
<div v-show="view === 'all'" >
|
||||
<div>
|
||||
<form @submit.prevent="searchImages" class="contained-search-box">
|
||||
<input placeholder="{{ trans('components.image_search_hint') }}" v-model="searchTerm">
|
||||
<button :class="{active: searching}" title="{{ trans('common.search_clear') }}" type="button" @click="cancelSearch()" class="text-button cancel">@icon('close')</button>
|
||||
@ -63,7 +63,7 @@
|
||||
<button type="button" class="button icon outline" @click="deleteImage">@icon('delete')</button>
|
||||
|
||||
</div>
|
||||
<button class="button anim fadeIn float right" v-show="selectedImage" @click="callbackAndHide(selectedImage)">
|
||||
<button class="button primary anim fadeIn float right" v-show="selectedImage" @click="callbackAndHide(selectedImage)">
|
||||
{{ trans('components.image_select_image') }}
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -23,5 +23,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('components.image-manager', ['imageType' => 'cover'])
|
||||
@include('components.image-manager', ['imageType' => 'cover_bookshelf', 'uploaded_to' => $shelf->id])
|
||||
@stop
|
@ -104,26 +104,40 @@ Route::group(['middleware' => 'auth'], function () {
|
||||
|
||||
// Image routes
|
||||
Route::group(['prefix' => 'images'], function () {
|
||||
|
||||
// Get for user images
|
||||
// Route::get('/user/all', 'ImageController@getAllForUserType');
|
||||
// Route::get('/user/all/{page}', 'ImageController@getAllForUserType');
|
||||
|
||||
// Standard get, update and deletion for all types
|
||||
Route::get('/thumb/{id}/{width}/{height}/{crop}', 'ImageController@getThumbnail');
|
||||
Route::get('/base64/{id}', 'ImageController@getBase64Image');
|
||||
Route::get('/usage/{id}', 'ImageController@usage');
|
||||
Route::get('/{type}/all', 'ImageController@getAllByType');
|
||||
Route::get('/{type}/all/{page}', 'ImageController@getAllByType');
|
||||
Route::get('/{type}/search/{page}', 'ImageController@searchByType');
|
||||
Route::get('/gallery/{filter}/{page}', 'ImageController@getGalleryFiltered');
|
||||
// Route::get('/{type}/all', 'ImageController@getAllByType');
|
||||
// Route::get('/{type}/all/{page}', 'ImageController@getAllByType');
|
||||
// Route::get('/{type}/search/{page}', 'ImageController@searchByType');
|
||||
// Route::get('/gallery/{filter}/{page}', 'ImageController@getGalleryFiltered');
|
||||
|
||||
// Gallery
|
||||
Route::get('/gallery', 'Images\GalleryImageController@list');
|
||||
Route::post('/gallery', 'Images\GalleryImageController@create');
|
||||
// Drawio
|
||||
Route::get('/drawio', 'Images\DrawioImageController@list');
|
||||
Route::post('/drawio', 'Images\DrawioImageController@create');
|
||||
// User
|
||||
Route::get('/user', 'Images\UserImageController@list');
|
||||
Route::post('/user', 'Images\UserImageController@create');
|
||||
// System
|
||||
Route::get('/system', 'Images\SystemImageController@list');
|
||||
Route::post('/system', 'Images\SystemImageController@create');
|
||||
// Cover
|
||||
Route::get('/cover_{entity}', 'Images\CoverImageController@list');
|
||||
Route::post('/cover_{entity}', 'Images\CoverImageController@create');
|
||||
|
||||
// TODO - Remove use of abstract "Type" variable (Above)
|
||||
// TODO - Clearly define each endpoint so logic for each is clear
|
||||
// TODO - Move into per-type controllers
|
||||
// TODO - Test and fully think about permissions and each stage
|
||||
Route::post('/drawio', 'ImageController@uploadDrawioImage');
|
||||
Route::post('/gallery', 'ImageController@uploadGalleryImage');
|
||||
Route::post('/user', 'ImageController@uploadUserImage');
|
||||
Route::post('/system', 'ImageController@uploadSystemImage');
|
||||
Route::post('/cover', 'ImageController@uploadCoverImage');
|
||||
|
||||
Route::put('/{id}', 'ImageController@update');
|
||||
|
Loading…
Reference in New Issue
Block a user