Added autotagging

(closes #75)
This commit is contained in:
Sergio Brighenti 2020-03-30 18:26:47 +02:00
parent 5990d5fba1
commit 6326f52bd1
4 changed files with 121 additions and 52 deletions

View file

@ -1,5 +1,6 @@
## v.3.1 (WIP) ## v.3.1 (WIP)
+ Added tagging system (add, delete, search of tagged files). + Added tagging system (add, delete, search of tagged files).
+ Added basic media auto-tagging on upload.
+ Added registration system. + Added registration system.
+ Added password recovery system. + Added password recovery system.
+ Added ability to export all media of an account. + Added ability to export all media of an account.

View file

@ -3,6 +3,7 @@
namespace App\Controllers; namespace App\Controllers;
use App\Database\Queries\TagQuery;
use App\Web\ValidationChecker; use App\Web\ValidationChecker;
use PDO; use PDO;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
@ -28,46 +29,12 @@ class TagController extends Controller
throw new HttpBadRequestException($request); throw new HttpBadRequestException($request);
} }
$tag = $this->database->query('SELECT * FROM `tags` WHERE `name` = ? LIMIT 1', param($request, 'tag'))->fetch(); [$id, $limit] = make(TagQuery::class)->addTag(param($request, 'tag'), param($request, 'mediaId'));
$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,
]);
return json($response, [ return json($response, [
'limitReached' => false, 'limitReached' => $limit,
'tagId' => $tag->id, 'tagId' => $id,
'href' => queryParams(['tag' => $tag->id]), 'href' => queryParams(['tag' => $id]),
]); ]);
} }
@ -80,28 +47,18 @@ class TagController extends Controller
*/ */
public function removeTag(Request $request, Response $response): Response public function removeTag(Request $request, Response $response): Response
{ {
$validator = $this->validateTag($request) $validator = $this->validateTag($request)->removeRule('tag.notEmpty');
->removeRule('tag.notEmpty');
if ($validator->fails()) { if ($validator->fails()) {
throw new HttpBadRequestException($request); 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); 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; return $response;
} }

View file

@ -2,6 +2,7 @@
namespace App\Controllers; namespace App\Controllers;
use App\Database\Queries\TagQuery;
use App\Database\Queries\UserQuery; use App\Database\Queries\UserQuery;
use App\Exceptions\ValidationException; use App\Exceptions\ValidationException;
use Exception; use Exception;
@ -183,6 +184,7 @@ class UploadController extends Controller
* @param $user * @param $user
* @return Response * @return Response
* @throws \League\Flysystem\FileExistsException * @throws \League\Flysystem\FileExistsException
* @throws \League\Flysystem\FileNotFoundException
*/ */
protected function saveMedia(Response $response, UploadedFileInterface $file, $user) protected function saveMedia(Response $response, UploadedFileInterface $file, $user)
{ {
@ -207,12 +209,35 @@ class UploadController extends Controller
$storagePath, $storagePath,
$published, $published,
]); ]);
$mediaId = $this->database->getPdo()->lastInsertId();
$this->autoTag($mediaId, $storagePath);
$this->json['message'] = 'OK'; $this->json['message'] = 'OK';
$this->json['url'] = urlFor("/{$user->user_code}/{$code}.{$fileInfo['extension']}"); $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); 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);
}
}
} }

View file

@ -0,0 +1,86 @@
<?php
namespace App\Database\Queries;
use App\Database\DB;
use PDO;
class TagQuery
{
const PER_MEDIA_LIMIT = 10;
/**
* @var DB
*/
private $db;
public function __construct(DB $db)
{
$this->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;
}
}