Sergio Brighenti преди 5 години
родител
ревизия
576131b67b

+ 1 - 1
app/Controllers/SettingController.php

@@ -57,7 +57,7 @@ class SettingController extends Controller
     public function applyLang(Request $request)
     {
         if (param($request, 'lang') !== 'auto') {
-            $this->updateSetting('copy_url_behavior', param($request, 'lang'));
+            $this->updateSetting('lang', param($request, 'lang'));
         } else {
             $this->database->query('DELETE FROM `settings` WHERE `key` = \'lang\'');
         }

+ 117 - 0
app/Controllers/TagController.php

@@ -0,0 +1,117 @@
+<?php
+
+
+namespace App\Controllers;
+
+
+use App\Web\ValidationChecker;
+use PDO;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\HttpBadRequestException;
+use Slim\Exception\HttpNotFoundException;
+
+class TagController extends Controller
+{
+    const PER_MEDIA_LIMIT = 10;
+
+    /**
+     * @param  Request  $request
+     * @param  Response  $response
+     * @return Response
+     * @throws HttpBadRequestException
+     */
+    public function addTag(Request $request, Response $response): Response
+    {
+        $validator = $this->validateTag($request);
+
+        if ($validator->fails()) {
+            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 (?)', 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,
+            ]);
+        }
+
+        if (count($connectedIds) >= self::PER_MEDIA_LIMIT || in_array($tag->id, $connectedIds)) {
+            return json($response, [
+                'limitReached' => true,
+                'tagId' => null,
+            ]);
+        }
+
+        $this->database->query('INSERT INTO `uploads_tags`(`upload_id`, `tag_id`) VALUES (?, ?)', [
+            param($request, 'mediaId'),
+            $tag->id,
+        ]);
+
+        return json($response, [
+            'limitReached' => false,
+            'tagId' => $tag->id,
+        ]);
+    }
+
+    /**
+     * @param  Request  $request
+     * @param  Response  $response
+     * @return Response
+     * @throws HttpBadRequestException
+     * @throws HttpNotFoundException
+     */
+    public function removeTag(Request $request, Response $response): Response
+    {
+        $validator = $this->validateTag($request)
+            ->addRule('tag.exists', false);
+
+        if ($validator->fails()) {
+            throw new HttpBadRequestException($request);
+        }
+
+        $tag = $this->database->query('SELECT * FROM `tags` WHERE `name` = ? LIMIT 1', param($request, 'tag'))->fetch();
+
+        if (!$tag) {
+            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;
+    }
+
+    protected function validateTag(Request $request)
+    {
+        return ValidationChecker::make()
+            ->rules([
+                'tag.notEmpty' => !empty(param($request, 'tag')),
+                'mediaId.notEmpty' => !empty(param($request, 'mediaId')),
+                'media.exists' => $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `id` = ?', param($request, 'mediaId'))->fetch()->count > 0,
+                'same.userOrAdmin' => $this->session->get('admin', false) || $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', param($request, 'mediaId'))->fetch()->user_id === $this->session->get('user_id'),
+            ]);
+    }
+
+}

+ 1 - 1
app/Web/Lang.php

@@ -92,7 +92,7 @@ class Lang
         foreach (glob(self::$langPath.'*.lang.php') as $file) {
             $dict = include $file;
 
-            if (!is_array($dict)) {
+            if (!is_array($dict) || !isset($dict['lang'])) {
                 continue;
             }
 

+ 11 - 0
app/Web/ValidationChecker.php

@@ -64,4 +64,15 @@ class ValidationChecker
 
         return $condition;
     }
+
+    /**
+     * @param  string  $key
+     * @param $condition
+     * @return ValidationChecker
+     */
+    public function addRule(string $key, $condition)
+    {
+        $this->rules[$key] = $condition;
+        return $this;
+    }
 }

+ 3 - 0
app/helpers.php

@@ -329,6 +329,9 @@ if (!function_exists('isBot')) {
             'Facebot',
             'curl/',
             'wget/',
+            'WhatsApp/',
+            'Slackbot',
+            'Slack-ImgProxy',
         ];
 
         foreach ($bots as $bot) {

+ 4 - 0
app/routes.php

@@ -10,6 +10,7 @@ use App\Controllers\ExportController;
 use App\Controllers\MediaController;
 use App\Controllers\ProfileController;
 use App\Controllers\SettingController;
+use App\Controllers\TagController;
 use App\Controllers\UpgradeController;
 use App\Controllers\UploadController;
 use App\Controllers\UserController;
@@ -63,6 +64,9 @@ $app->group('', function (RouteCollectorProxy $group) {
     $group->post('/upload/{id}/unpublish', [MediaController::class, 'togglePublish'])->setName('upload.unpublish');
     $group->get('/upload/{id}/raw', [MediaController::class, 'getRawById'])->add(AdminMiddleware::class)->setName('upload.raw');
     $group->map(['GET', 'POST'], '/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');
+
+    $group->post('/tag/add', [TagController::class, 'addTag'])->setName('tag.add');
+    $group->post('/tag/remove', [TagController::class, 'removeTag'])->setName('tag.remove');
 })->add(App\Middleware\CheckForMaintenanceMiddleware::class)->add(AuthMiddleware::class);
 
 $app->get('/', [DashboardController::class, 'redirects'])->setName('root');

+ 1 - 0
resources/lang/ar.lang.php

@@ -1,5 +1,6 @@
 <?php
 return [
+    'lang' => 'Arabian',
     'yes' => 'نعم',
     'no' => 'لا',
     'send' => 'إرسال',

+ 1 - 1
resources/templates/dashboard/grid.twig

@@ -40,7 +40,7 @@
                                             </div>
                                         </a>
                                         <div class="overlay-rows-bottom pl-3 pr-3 pb-1">
-                                            <a href="javascript:void(0)" class="badge badge-pill badge-success shadow-sm tag-add"><i class="fas fa-plus fa-sm fa-fw"></i></a>
+                                            <a href="javascript:void(0)" class="badge badge-pill badge-success shadow-sm tag-add" data-id="{{ media.id }}"><i class="fas fa-plus fa-sm fa-fw"></i></a>
                                         </div>
                                     </div>
                                 </div>

+ 1 - 1
resources/templates/dashboard/list.twig

@@ -43,7 +43,7 @@
                                             <td>
                                                 <span class="text-maxlen">{{ media.filename }}</span>
                                                 <p>
-                                                    <a href="javascript:void(0)" class="badge badge-pill badge-success shadow-sm tag-add"><i class="fas fa-plus fa-sm fa-fw"></i></a>
+                                                    <a href="javascript:void(0)" class="badge badge-pill badge-success shadow-sm tag-add" data-id="{{ media.id }}"><i class="fas fa-plus fa-sm fa-fw"></i></a>
                                                 </p>
                                             </td>
                                             <td>{{ media.size }}</td>

+ 29 - 11
src/js/app.js

@@ -150,12 +150,15 @@ var app = {
 
         var tagInput = $(document.createElement('input'))
             .addClass('form-control form-control-verysm tag-input')
+            .attr('data-id', $caller.data('id'))
+            .attr('maxlength', 32)
             .keydown(function (e) {
-                if (e.keyCode === 13 || e.keyCode === 32) { // enter -> save tag
+                if (e.keyCode === 13) { // enter -> save tag
                     app.saveTag.call($(this)); // change context
-                    if (e.keyCode === 32) { // space -> save and add new tag
-                        $newAddTag.click();
-                    }
+                    return false;
+                }
+                if (e.keyCode === 32) { // space -> save and add new tag
+                    $newAddTag.click();
                     return false;
                 }
             })
@@ -169,15 +172,30 @@ var app = {
     },
     saveTag: function () {
         var tag = $(this).val();
+        var $parent = $(this).parent();
         if (tag === '') {
-            $(this).parent().remove();
+            $parent.remove();
+            return false;
         }
-        console.log(tag);
-        var $newTag = $(document.createElement('span'))
-            .addClass('badge badge-pill badge-light shadow-sm tag-item')
-            .dblclick(app.removeTag)
-            .text(tag);
-        $(this).parent().replaceWith($newTag);
+        $.ajax({
+            type: 'POST',
+            url: window.AppConfig.base_url + '/tag/add',
+            data: {'tag': tag, 'mediaId': $(this).data('id')},
+            dataType: 'json',
+            success: function (data) {
+                if (!data.limitReached) {
+                    $parent.replaceWith(
+                        $(document.createElement('span'))
+                            .addClass('badge badge-pill badge-light shadow-sm tag-item mr-1')
+                            .attr('data-id', data.tagId)
+                            .dblclick(app.removeTag)
+                            .text(tag)
+                    );
+                } else {
+                    $parent.remove();
+                }
+            }
+        });
     },
     removeTag: function (e) {
         e.preventDefault();