diff --git a/CHANGELOG.md b/CHANGELOG.md index 20109a2..72d7a42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## v2.4 + Added function to remove orphaned files. ++ Switch between tab and gallery mode using an admin account. ++ Multiple uploads sorting methods. + Internal refactoring and improvements ## v2.3.1 diff --git a/app/Controllers/AdminController.php b/app/Controllers/AdminController.php index ce5a9f2..bba7329 100644 --- a/app/Controllers/AdminController.php +++ b/app/Controllers/AdminController.php @@ -22,7 +22,7 @@ class AdminController extends Controller $mediasCount = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads`')->fetch()->count; $orphanFilesCount = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `user_id` IS NULL')->fetch()->count; - $medias = $this->database->query('SELECT `users`.`user_code`, `uploads`.`code`, `uploads`.`storage_path` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id`')->fetchAll(); + $medias = $this->database->query('SELECT `uploads`.`storage_path` FROM `uploads`')->fetchAll(); $totalSize = 0; diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 1df55ca..57ae979 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -2,7 +2,7 @@ namespace App\Controllers; -use League\Flysystem\FileNotFoundException; +use App\Database\Queries\MediaQuery; use Slim\Http\Request; use Slim\Http\Response; @@ -39,36 +39,33 @@ class DashboardController extends Controller $page = isset($args['page']) ? (int)$args['page'] : 0; $page = max(0, --$page); - if ($this->session->get('admin', false)) { - $medias = $this->database->query('SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` ORDER BY `timestamp` DESC LIMIT ? OFFSET ?', [self::PER_PAGE_ADMIN, $page * self::PER_PAGE_ADMIN])->fetchAll(); - $pages = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads`')->fetch()->count / self::PER_PAGE_ADMIN; - } else { - $medias = $this->database->query('SELECT `uploads`.*,`users`.`user_code`, `users`.`username` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_id` = ? ORDER BY `timestamp` DESC LIMIT ? OFFSET ?', [$this->session->get('user_id'), self::PER_PAGE, $page * self::PER_PAGE])->fetchAll(); - $pages = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `user_id` = ?', $this->session->get('user_id'))->fetch()->count / self::PER_PAGE; - } + $query = new MediaQuery($this->database, $this->session->get('admin', false)); - $filesystem = storage(); - - foreach ($medias as $media) { - try { - $media->size = humanFileSize($filesystem->getSize($media->storage_path)); - $media->mimetype = $filesystem->getMimetype($media->storage_path); - } catch (FileNotFoundException $e) { - $media->size = null; - $media->mimetype = null; - } - $media->extension = pathinfo($media->filename, PATHINFO_EXTENSION); - } + $query->orderBy(MediaQuery::ORDER_NAME) + ->withUserId($this->session->get('user_id')) + ->run($page); return $this->view->render( $response, - $this->session->get('admin', false) ? 'dashboard/admin.twig' : 'dashboard/home.twig', + ($this->session->get('admin', false) && $this->session->get('gallery_view', true)) ? 'dashboard/admin.twig' : 'dashboard/home.twig', [ - 'medias' => $medias, - 'next' => $page < floor($pages), + 'medias' => $query->getMedia(), + 'next' => $page < floor($query->getPages()), 'previous' => $page >= 1, 'current_page' => ++$page, ] ); } + + /** + * @param Request $request + * @param Response $response + * @param $args + * @return Response + */ + public function switchView(Request $request, Response $response, $args): Response + { + $this->session->set('gallery_view', !$this->session->get('gallery_view', true)); + return redirect($response, 'home'); + } } \ No newline at end of file diff --git a/app/Database/Queries/MediaQuery.php b/app/Database/Queries/MediaQuery.php new file mode 100644 index 0000000..17f521d --- /dev/null +++ b/app/Database/Queries/MediaQuery.php @@ -0,0 +1,201 @@ +db = $db; + $this->isAdmin = $isAdmin; + } + + /** + * @param $id + * @return $this + */ + public function withUserId($id) + { + $this->userId = $id; + return $this; + } + + /** + * @param string|null $type + * @param string $mode + * @return $this + */ + public function orderBy(string $type = null, $mode = 'ASC') + { + $this->orderBy = ($type === null) ? self::ORDER_TIME : $type; + $this->orderMode = (strtoupper($mode) === 'ASC') ? 'ASC' : 'DESC'; + return $this; + } + + /** + * @param string $text + * @return $this + */ + public function search(string $text) + { + $this->text = $text; + return $this; + } + + /** + * @param int $page + */ + public function run(int $page) + { + if ($this->orderBy == self::ORDER_SIZE) { + $this->runWithOrderBySize($page); + return; + } + + $queryPages = 'SELECT COUNT(*) AS `count` FROM `uploads`'; + + if ($this->isAdmin) { + $queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` %s LIMIT ? OFFSET ?'; + } else { + $queryMedia = 'SELECT `uploads`.*,`users`.`user_code`, `users`.`username` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_id` = ? %s LIMIT ? OFFSET ?'; + $queryPages .= ' WHERE `user_id` = ?'; + } + + switch ($this->orderBy) { + case self::ORDER_NAME: + $queryMedia = sprintf($queryMedia, 'ORDER BY `filename` ' . $this->orderMode); + break; + default: + case self::ORDER_TIME: + $queryMedia = sprintf($queryMedia, 'ORDER BY `timestamp` ' . $this->orderMode); + break; + } + + if ($this->isAdmin) { + $this->media = $this->db->query($queryMedia, [self::PER_PAGE_ADMIN, $page * self::PER_PAGE_ADMIN])->fetchAll(); + $this->pages = $this->db->query($queryPages)->fetch()->count / self::PER_PAGE_ADMIN; + } else { + $this->media = $this->db->query($queryMedia, [$this->userId, self::PER_PAGE, $page * self::PER_PAGE])->fetchAll(); + $this->pages = $this->db->query($queryPages, $this->userId)->fetch()->count / self::PER_PAGE; + } + + $filesystem = storage(); + + foreach ($this->media as $media) { + try { + $media->size = humanFileSize($filesystem->getSize($media->storage_path)); + $media->mimetype = $filesystem->getMimetype($media->storage_path); + } catch (FileNotFoundException $e) { + $media->size = null; + $media->mimetype = null; + } + $media->extension = pathinfo($media->filename, PATHINFO_EXTENSION); + } + + } + + /** + * @param int $page + */ + private function runWithOrderBySize(int $page) + { + $filesystem = storage(); + $filesystem->addPlugin(new ListFiles()); + + if ($this->isAdmin) { + $files = $filesystem->listFiles('/', true); + $this->pages = count($files) / self::PER_PAGE_ADMIN; + + $offset = $page * self::PER_PAGE_ADMIN; + $limit = self::PER_PAGE_ADMIN; + } else { + $userCode = $this->db->query('SELECT `user_code` FROM `users` WHERE `id` = ?', [$this->userId])->fetch()->user_code; + $files = $filesystem->listFiles($userCode); + $this->pages = count($files) / self::PER_PAGE; + + $offset = $page * self::PER_PAGE; + $limit = self::PER_PAGE; + } + + array_multisort(array_column($files, 'size'), ($this->orderMode === 'ASC') ? SORT_ASC : SORT_DESC, SORT_NUMERIC, $files); + + $files = array_slice($files, $offset, $limit); + $paths = array_column($files, 'path'); + + $medias = $this->db->query('SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("' . implode('","', $paths) . '")')->fetchAll(); + + $paths = array_flip($paths); + foreach ($medias as $media) { + $paths[$media->storage_path] = $media; + } + + $this->media = []; + + foreach ($files as $file) { + $media = $paths[$file['path']]; + $media->size = humanFileSize($file['size']); + try { + $media->mimetype = $filesystem->getMimetype($file['path']); + } catch (FileNotFoundException $e) { + $media->mimetype = null; + } + $media->extension = $file['extension']; + $this->media[] = $media; + } + } + + /** + * @return mixed + */ + public function getMedia() + { + return $this->media; + + } + + /** + * @return mixed + */ + public function getPages() + { + return $this->pages; + } +} \ No newline at end of file diff --git a/app/helpers.php b/app/helpers.php index cabcc17..8b69e50 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -158,6 +158,11 @@ if (!function_exists('isBot')) { } if (!function_exists('mime2font')) { + /** + * Convert get the icon from the file mimetype + * @param $mime + * @return mixed|string + */ function mime2font($mime) { $classes = [ @@ -177,6 +182,7 @@ if (!function_exists('mime2font')) { 'application/vnd.oasis.opendocument.presentation' => 'fa-file-powerpoint', 'text/plain' => 'fa-file-alt', 'text/html' => 'fa-file-code', + 'text/x-php' => 'fa-file-code', 'application/json' => 'fa-file-code', 'application/gzip' => 'fa-file-archive', 'application/zip' => 'fa-file-archive', @@ -189,4 +195,19 @@ if (!function_exists('mime2font')) { } return 'fa-file'; } +} + +if (!function_exists('dd')) { + /** + * Dumps all the giver vars and halt the execution. + */ + function dd() + { + echo '
';
+		array_map(function ($x) {
+			print_r($x);
+		}, func_get_args());
+		echo '
'; + die(); + } } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index 7d817fc..aa9c004 100644 --- a/app/routes.php +++ b/app/routes.php @@ -2,18 +2,24 @@ // Auth routes $app->group('', function () { $this->get('/home[/page/{page}]', \App\Controllers\DashboardController::class . ':home')->setName('home'); - $this->get('/system/deleteOrphanFiles', \App\Controllers\AdminController::class . ':deleteOrphanFiles')->add(\App\Middleware\AdminMiddleware::class)->setName('system.deleteOrphanFiles'); - $this->get('/system/themes', \App\Controllers\ThemeController::class . ':getThemes')->add(\App\Middleware\AdminMiddleware::class)->setName('theme'); - $this->post('/system/theme/apply', \App\Controllers\ThemeController::class . ':applyTheme')->add(\App\Middleware\AdminMiddleware::class)->setName('theme.apply'); - $this->get('/system', \App\Controllers\AdminController::class . ':system')->add(\App\Middleware\AdminMiddleware::class)->setName('system'); $this->group('', function () { + $this->get('/home/switchView', \App\Controllers\DashboardController::class . ':switchView')->setName('switchView'); + $this->get('/system/deleteOrphanFiles', \App\Controllers\AdminController::class . ':deleteOrphanFiles')->setName('system.deleteOrphanFiles'); + $this->get('/system/themes', \App\Controllers\ThemeController::class . ':getThemes')->setName('theme'); + $this->post('/system/theme/apply', \App\Controllers\ThemeController::class . ':applyTheme')->setName('theme.apply'); + $this->get('/system', \App\Controllers\AdminController::class . ':system')->setName('system'); + $this->get('/users[/page/{page}]', \App\Controllers\UserController::class . ':index')->setName('user.index'); - $this->get('/user/create', \App\Controllers\UserController::class . ':create')->setName('user.create'); - $this->post('/user/create', \App\Controllers\UserController::class . ':store')->setName('user.store'); - $this->get('/user/{id}/edit', \App\Controllers\UserController::class . ':edit')->setName('user.edit'); - $this->post('/user/{id}', \App\Controllers\UserController::class . ':update')->setName('user.update'); - $this->get('/user/{id}/delete', \App\Controllers\UserController::class . ':delete')->setName('user.delete'); + })->add(\App\Middleware\AdminMiddleware::class); + + $this->group('/user', function () { + + $this->get('/create', \App\Controllers\UserController::class . ':create')->setName('user.create'); + $this->post('/create', \App\Controllers\UserController::class . ':store')->setName('user.store'); + $this->get('/{id}/edit', \App\Controllers\UserController::class . ':edit')->setName('user.edit'); + $this->post('/{id}', \App\Controllers\UserController::class . ':update')->setName('user.update'); + $this->get('/{id}/delete', \App\Controllers\UserController::class . ':delete')->setName('user.delete'); })->add(\App\Middleware\AdminMiddleware::class); $this->get('/profile', \App\Controllers\UserController::class . ':profile')->setName('profile'); diff --git a/composer.lock b/composer.lock index 47e1e66..08a9dd9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "265c1ca72d526b36b50fcec633b5807f", + "content-hash": "3ffe3637bbcca9dc78923aca4ffdbbe6", "packages": [ { "name": "container-interop/container-interop", @@ -859,32 +859,32 @@ }, { "name": "twig/twig", - "version": "v2.5.0", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323" + "reference": "a11dd39f5b6589e14f0ff3b36675d06047c589b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/6a5f676b77a90823c2d4eaf76137b771adf31323", - "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a11dd39f5b6589e14f0ff3b36675d06047c589b1", + "reference": "a11dd39f5b6589e14f0ff3b36675d06047c589b1", "shasum": "" }, "require": { "php": "^7.0", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { "psr/container": "^1.0", "symfony/debug": "^2.7", - "symfony/phpunit-bridge": "^3.3" + "symfony/phpunit-bridge": "^3.4.19|^4.1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -922,7 +922,7 @@ "keywords": [ "templating" ], - "time": "2018-07-13T07:18:09+00:00" + "time": "2018-12-16T10:36:48+00:00" } ], "packages-dev": [], diff --git a/resources/lang/en.lang.php b/resources/lang/en.lang.php index c5ec894..2be05ea 100644 --- a/resources/lang/en.lang.php +++ b/resources/lang/en.lang.php @@ -86,4 +86,7 @@ return [ 'cannot_demote' => 'You cannot demote yourself.', 'cannot_write_file' => 'The destination path is not writable.', 'deleted_orphans' => 'Successfully deleted %d orphaned files.', + 'switch_to' => 'Switch to', + 'gallery' => 'Gallery', + 'table' => 'Table', ]; \ No newline at end of file diff --git a/resources/lang/it.lang.php b/resources/lang/it.lang.php index 1f3f492..c46b2e9 100644 --- a/resources/lang/it.lang.php +++ b/resources/lang/it.lang.php @@ -86,4 +86,7 @@ return [ 'cannot_demote' => 'Non puoi degradare te stesso. ', 'cannot_write_file' => 'Il percorso di destinazione non รจ scrivibile.', 'deleted_orphans' => 'Eliminati %d file orfani.', + 'switch_to' => 'Vedi come', + 'gallery' => 'Galleria', + 'table' => 'Tabella', ]; \ No newline at end of file diff --git a/resources/templates/comp/navbar.twig b/resources/templates/comp/navbar.twig index 18d155f..2611fc3 100644 --- a/resources/templates/comp/navbar.twig +++ b/resources/templates/comp/navbar.twig @@ -31,6 +31,7 @@