From 6326f52bd1c7f5f2455e65a0140280a2a087013b Mon Sep 17 00:00:00 2001 From: Sergio Brighenti Date: Mon, 30 Mar 2020 18:26:47 +0200 Subject: [PATCH] Added autotagging (closes #75) --- CHANGELOG.md | 1 + app/Controllers/TagController.php | 59 +++---------------- app/Controllers/UploadController.php | 27 ++++++++- app/Database/Queries/TagQuery.php | 86 ++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 52 deletions(-) create mode 100644 app/Database/Queries/TagQuery.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d95a33..6f2ae32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## v.3.1 (WIP) + Added tagging system (add, delete, search of tagged files). ++ Added basic media auto-tagging on upload. + Added registration system. + Added password recovery system. + Added ability to export all media of an account. diff --git a/app/Controllers/TagController.php b/app/Controllers/TagController.php index 6f958b1..fff5f20 100644 --- a/app/Controllers/TagController.php +++ b/app/Controllers/TagController.php @@ -3,6 +3,7 @@ namespace App\Controllers; +use App\Database\Queries\TagQuery; use App\Web\ValidationChecker; use PDO; use Psr\Http\Message\ResponseInterface as Response; @@ -28,46 +29,12 @@ class TagController extends Controller throw new HttpBadRequestException($request); } - $tag = $this->database->query('SELECT * FROM `tags` WHERE `name` = ? LIMIT 1', param($request, 'tag'))->fetch(); - - $connectedIds = $this->database->query('SELECT `tag_id` FROM `uploads_tags` WHERE `upload_id` = ?', [ - param($request, 'mediaId'), - ])->fetchAll(PDO::FETCH_COLUMN, 0); - - if (!$tag && count($connectedIds) < self::PER_MEDIA_LIMIT) { - $this->database->query('INSERT INTO `tags`(`name`) VALUES (?)', strtolower(param($request, 'tag'))); - - $tagId = $this->database->getPdo()->lastInsertId(); - - $this->database->query('INSERT INTO `uploads_tags`(`upload_id`, `tag_id`) VALUES (?, ?)', [ - param($request, 'mediaId'), - $tagId, - ]); - - return json($response, [ - 'limitReached' => false, - 'tagId' => $tagId, - 'href' => queryParams(['tag' => $tagId]), - ]); - } - - if (count($connectedIds) >= self::PER_MEDIA_LIMIT || in_array($tag->id, $connectedIds)) { - return json($response, [ - 'limitReached' => true, - 'tagId' => null, - 'href' => null, - ]); - } - - $this->database->query('INSERT INTO `uploads_tags`(`upload_id`, `tag_id`) VALUES (?, ?)', [ - param($request, 'mediaId'), - $tag->id, - ]); + [$id, $limit] = make(TagQuery::class)->addTag(param($request, 'tag'), param($request, 'mediaId')); return json($response, [ - 'limitReached' => false, - 'tagId' => $tag->id, - 'href' => queryParams(['tag' => $tag->id]), + 'limitReached' => $limit, + 'tagId' => $id, + 'href' => queryParams(['tag' => $id]), ]); } @@ -80,28 +47,18 @@ class TagController extends Controller */ public function removeTag(Request $request, Response $response): Response { - $validator = $this->validateTag($request) - ->removeRule('tag.notEmpty'); + $validator = $this->validateTag($request)->removeRule('tag.notEmpty'); if ($validator->fails()) { throw new HttpBadRequestException($request); } - $tag = $this->database->query('SELECT * FROM `tags` WHERE `id` = ? LIMIT 1', param($request, 'tagId'))->fetch(); + $result = make(TagQuery::class)->removeTag(param($request, 'tagId'), param($request, 'mediaId')); - if (!$tag) { + if (!$result) { throw new HttpNotFoundException($request); } - $this->database->query('DELETE FROM `uploads_tags` WHERE `upload_id` = ? AND `tag_id` = ?', [ - param($request, 'mediaId'), - $tag->id, - ]); - - if ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads_tags` WHERE `tag_id` = ?', $tag->id)->fetch()->count == 0) { - $this->database->query('DELETE FROM `tags` WHERE `id` = ? ', $tag->id); - } - return $response; } diff --git a/app/Controllers/UploadController.php b/app/Controllers/UploadController.php index 550a671..7f9331a 100644 --- a/app/Controllers/UploadController.php +++ b/app/Controllers/UploadController.php @@ -2,6 +2,7 @@ namespace App\Controllers; +use App\Database\Queries\TagQuery; use App\Database\Queries\UserQuery; use App\Exceptions\ValidationException; use Exception; @@ -183,6 +184,7 @@ class UploadController extends Controller * @param $user * @return Response * @throws \League\Flysystem\FileExistsException + * @throws \League\Flysystem\FileNotFoundException */ protected function saveMedia(Response $response, UploadedFileInterface $file, $user) { @@ -207,12 +209,35 @@ class UploadController extends Controller $storagePath, $published, ]); + $mediaId = $this->database->getPdo()->lastInsertId(); + + $this->autoTag($mediaId, $storagePath); $this->json['message'] = 'OK'; $this->json['url'] = urlFor("/{$user->user_code}/{$code}.{$fileInfo['extension']}"); - $this->logger->info("User $user->username uploaded new media.", [$this->database->getPdo()->lastInsertId()]); + $this->logger->info("User $user->username uploaded new media.", [$mediaId]); return json($response, $this->json, 201); } + + /** + * @param $mediaId + * @param $storagePath + * @throws \League\Flysystem\FileNotFoundException + */ + protected function autoTag($mediaId, $storagePath) + { + $mime = $this->storage->getMimetype($storagePath); + + [$type, $subtype] = explode('/', $mime); + + /** @var TagQuery $query */ + $query = make(TagQuery::class); + $query->addTag($type, $mediaId); + + if ($type === 'application') { + $query->addTag($subtype, $mediaId); + } + } } diff --git a/app/Database/Queries/TagQuery.php b/app/Database/Queries/TagQuery.php new file mode 100644 index 0000000..31c2f76 --- /dev/null +++ b/app/Database/Queries/TagQuery.php @@ -0,0 +1,86 @@ +db = $db; + } + + /** + * @param string $tagName + * @param $mediaId + * @return array [id, limit] + */ + public function addTag(string $tagName, $mediaId) + { + $tag = $this->db->query('SELECT * FROM `tags` WHERE `name` = ? LIMIT 1', $tagName)->fetch(); + + $connectedIds = $this->db->query('SELECT `tag_id` FROM `uploads_tags` WHERE `upload_id` = ?', $mediaId)->fetchAll(PDO::FETCH_COLUMN, 0); + + if (!$tag && count($connectedIds) < self::PER_MEDIA_LIMIT) { + $this->db->query('INSERT INTO `tags`(`name`) VALUES (?)', strtolower($tagName)); + + $tagId = $this->db->getPdo()->lastInsertId(); + + $this->db->query('INSERT INTO `uploads_tags`(`upload_id`, `tag_id`) VALUES (?, ?)', [ + $mediaId, + $tagId, + ]); + + return [$tagId, false]; + } + + if (count($connectedIds) >= self::PER_MEDIA_LIMIT || in_array($tag->id, $connectedIds)) { + return [null, true]; + } + + $this->db->query('INSERT INTO `uploads_tags`(`upload_id`, `tag_id`) VALUES (?, ?)', [ + $mediaId, + $tag->id, + ]); + + return [$tag->id, false]; + } + + /** + * @param $tagId + * @param $mediaId + * @return bool + */ + public function removeTag($tagId, $mediaId) + { + $tag = $this->db->query('SELECT * FROM `tags` WHERE `id` = ? LIMIT 1', $tagId)->fetch(); + + if ($tag) { + $this->db->query('DELETE FROM `uploads_tags` WHERE `upload_id` = ? AND `tag_id` = ?', [ + $mediaId, + $tag->id, + ]); + + if ($this->db->query('SELECT COUNT(*) AS `count` FROM `uploads_tags` WHERE `tag_id` = ?', $tag->id)->fetch()->count == 0) { + $this->db->query('DELETE FROM `tags` WHERE `id` = ? ', $tag->id); + } + + return true; + } + + return false; + } + +} \ No newline at end of file