diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 9fce2ce..04293c7 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -56,6 +56,7 @@ class DashboardController extends Controller ->orderBy($order, param($request, 'order', 'DESC')) ->withUserId($this->session->get('user_id')) ->search(param($request, 'search', null)) + ->filterByTag(param($request, 'tag')) ->run($page); return view()->render( diff --git a/app/Controllers/TagController.php b/app/Controllers/TagController.php index a223f0b..6f958b1 100644 --- a/app/Controllers/TagController.php +++ b/app/Controllers/TagController.php @@ -35,7 +35,7 @@ class TagController extends Controller ])->fetchAll(PDO::FETCH_COLUMN, 0); if (!$tag && count($connectedIds) < self::PER_MEDIA_LIMIT) { - $this->database->query('INSERT INTO `tags`(`name`) VALUES (?)', param($request, 'tag')); + $this->database->query('INSERT INTO `tags`(`name`) VALUES (?)', strtolower(param($request, 'tag'))); $tagId = $this->database->getPdo()->lastInsertId(); @@ -47,6 +47,7 @@ class TagController extends Controller return json($response, [ 'limitReached' => false, 'tagId' => $tagId, + 'href' => queryParams(['tag' => $tagId]), ]); } @@ -54,6 +55,7 @@ class TagController extends Controller return json($response, [ 'limitReached' => true, 'tagId' => null, + 'href' => null, ]); } @@ -65,6 +67,7 @@ class TagController extends Controller return json($response, [ 'limitReached' => false, 'tagId' => $tag->id, + 'href' => queryParams(['tag' => $tag->id]), ]); } @@ -78,7 +81,7 @@ class TagController extends Controller public function removeTag(Request $request, Response $response): Response { $validator = $this->validateTag($request) - ->removeRule('tag.notEmpty'); + ->removeRule('tag.notEmpty'); if ($validator->fails()) { throw new HttpBadRequestException($request); diff --git a/app/Database/Queries/MediaQuery.php b/app/Database/Queries/MediaQuery.php index 4a9155f..b91760a 100644 --- a/app/Database/Queries/MediaQuery.php +++ b/app/Database/Queries/MediaQuery.php @@ -41,6 +41,11 @@ class MediaQuery private $pages; private $media; + /** + * @var int + */ + private $tagId; + /** * MediaQuery constructor. * @@ -104,6 +109,15 @@ class MediaQuery return $this; } + public function filterByTag($tagId) + { + if ($tagId !== null) { + $this->tagId = (int) $tagId; + } + + return $this; + } + public function run(int $page) { @@ -242,9 +256,25 @@ class MediaQuery $queryPages = 'SELECT COUNT(*) AS `count` FROM `uploads`'; $queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id`'; + if ($this->text !== null || $this->tagId !== null) { + $queryMedia .= ' WHERE'; + $queryPages .= ' WHERE'; + } + if ($this->text !== null) { - $queryMedia .= ' WHERE `uploads`.`filename` LIKE ? '; - $queryPages .= ' WHERE `filename` LIKE ?'; + $queryMedia .= ' `uploads`.`filename` LIKE ?'; + $queryPages .= ' `filename` LIKE ?'; + } + + if ($this->tagId !== null) { + if ($this->text !== null) { + $queryMedia .= ' AND'; + $queryPages .= ' AND'; + } + + $ids = $this->getMediaIdsByTagId($this->tagId); + $queryMedia .= ' `uploads`.`id` IN ('.implode(',', $ids).')'; + $queryPages .= ' `uploads`.`id` IN ('.implode(',', $ids).')'; } return [$queryMedia, $queryPages]; @@ -260,6 +290,12 @@ class MediaQuery $queryPages .= ' AND `filename` LIKE ?'; } + if ($this->tagId !== null) { + $ids = $this->getMediaIdsByTagId($this->tagId); + $queryMedia .= ' AND `uploads`.`id` IN ('.implode(',', $ids).')'; + $queryPages .= ' AND `uploads`.`id` IN ('.implode(',', $ids).')'; + } + return [$queryMedia, $queryPages]; } @@ -277,6 +313,10 @@ class MediaQuery } } + /** + * @param array $mediaIds + * @return array + */ protected function getTags(array $mediaIds) { $allTags = $this->db->query('SELECT `uploads_tags`.`upload_id`,`tags`.`id`, `tags`.`name` FROM `uploads_tags` INNER JOIN `tags` ON `uploads_tags`.`tag_id` = `tags`.`id` WHERE `uploads_tags`.`upload_id` IN ("'.implode('","', $mediaIds).'") ORDER BY `tags`.`timestamp`')->fetchAll(); @@ -287,6 +327,20 @@ class MediaQuery return $tags; } + /** + * @param $tagId + * @return array + */ + protected function getMediaIdsByTagId($tagId) + { + $mediaIds = $this->db->query('SELECT `upload_id` FROM `uploads_tags` WHERE `tag_id` = ?', $tagId)->fetchAll(); + $ids = []; + foreach ($mediaIds as $pivot) { + $ids[] = $pivot->upload_id; + } + return $ids; + } + /** * @return mixed */ diff --git a/src/js/app.js b/src/js/app.js index 4ae7f45..6c6f025 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -154,6 +154,7 @@ var app = { .attr('data-id', $caller.data('id')) .attr('maxlength', 32) .css('width', '90px') + .attr('onchange', 'this.value = this.value.toLowerCase();') .keydown(function (e) { if (e.keyCode === 13) { // enter -> save tag app.saveTag.call($(this)); // change context @@ -192,6 +193,7 @@ var app = { .addClass('badge badge-pill badge-light shadow-sm tag-item mr-1') .attr('data-id', data.tagId) .attr('data-media', mediaId) + .attr('href', data.href) .contextmenu(app.removeTag) .text(tag) );