]> BookStack Code Mirror - bookstack/commitdiff
Notifications: Started back-end for watch system
authorDan Brown <redacted>
Mon, 31 Jul 2023 15:08:29 +0000 (16:08 +0100)
committerDan Brown <redacted>
Mon, 31 Jul 2023 15:08:29 +0000 (16:08 +0100)
Added DB and started controller method.

app/Activity/Controllers/WatchController.php [new file with mode: 0644]
app/Activity/Models/Watch.php [new file with mode: 0644]
app/Users/UserWatchOptions.php [deleted file]
database/migrations/2023_07_31_104430_create_watches_table.php [new file with mode: 0644]
resources/views/entities/watch-controls.blade.php

diff --git a/app/Activity/Controllers/WatchController.php b/app/Activity/Controllers/WatchController.php
new file mode 100644 (file)
index 0000000..f9e8a4e
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+namespace BookStack\Activity\Controllers;
+
+use BookStack\Activity\Models\Watch;
+use BookStack\App\Model;
+use BookStack\Entities\Models\Entity;
+use BookStack\Http\Controller;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Validation\ValidationException;
+
+class WatchController extends Controller
+{
+    public function update(Request $request)
+    {
+        $requestData = $this->validate($request, [
+            'level' => ['required', 'string'],
+        ]);
+
+        $watchable = $this->getValidatedModelFromRequest($request);
+        $newLevel = Watch::optionNameToLevel($requestData['level']);
+
+        if ($newLevel < 0) {
+            // TODO - Delete
+        } else {
+            // TODO - Upsert
+        }
+    }
+
+    /**
+     * @throws ValidationException
+     * @throws Exception
+     */
+    protected function getValidatedModelFromRequest(Request $request): Entity
+    {
+        $modelInfo = $this->validate($request, [
+            'type' => ['required', 'string'],
+            'id'   => ['required', 'integer'],
+        ]);
+
+        if (!class_exists($modelInfo['type'])) {
+            throw new Exception('Model not found');
+        }
+
+        /** @var Model $model */
+        $model = new $modelInfo['type']();
+        if (!$model instanceof Entity) {
+            throw new Exception('Model not an entity');
+        }
+
+        $modelInstance = $model->newQuery()
+            ->where('id', '=', $modelInfo['id'])
+            ->first(['id', 'name', 'owned_by']);
+
+        $inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
+        if (is_null($modelInstance) || $inaccessibleEntity) {
+            throw new Exception('Model instance not found');
+        }
+
+        return $modelInstance;
+    }
+}
diff --git a/app/Activity/Models/Watch.php b/app/Activity/Models/Watch.php
new file mode 100644 (file)
index 0000000..6e0e1f7
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+namespace BookStack\Activity\Models;
+
+use BookStack\Permissions\Models\JointPermission;
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+
+/**
+ * @property int $id
+ * @property int $user_id
+ * @property int $watchable_id
+ * @property string $watchable_type
+ * @property int $level
+ * @property Carbon $created_at
+ * @property Carbon $updated_at
+ */
+class Watch extends Model
+{
+    protected static array $levelByOption = [
+        'default' => -1,
+        'ignore' => 0,
+        'new' => 1,
+        'updates' => 2,
+        'comments' => 3,
+    ];
+
+    public function watchable()
+    {
+        $this->morphTo();
+    }
+
+    public function jointPermissions(): HasMany
+    {
+        return $this->hasMany(JointPermission::class, 'entity_id', 'watchable_id')
+            ->whereColumn('favourites.watchable_type', '=', 'joint_permissions.entity_type');
+    }
+
+    /**
+     * @return string[]
+     */
+    public static function getAvailableOptionNames(): array
+    {
+        return array_keys(static::$levelByOption);
+    }
+
+    public static function optionNameToLevel(string $option): int
+    {
+        return static::$levelByOption[$option] ?? -1;
+    }
+}
diff --git a/app/Users/UserWatchOptions.php b/app/Users/UserWatchOptions.php
deleted file mode 100644 (file)
index a835bcf..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace BookStack\Users;
-
-class UserWatchOptions
-{
-    protected static array $levelByOption = [
-        'default' => -1,
-        'ignore' => 0,
-        'new' => 1,
-        'updates' => 2,
-        'comments' => 3,
-    ];
-
-    /**
-     * @return string[]
-     */
-    public static function getAvailableOptionNames(): array
-    {
-        return array_keys(static::$levelByOption);
-    }
-}
diff --git a/database/migrations/2023_07_31_104430_create_watches_table.php b/database/migrations/2023_07_31_104430_create_watches_table.php
new file mode 100644 (file)
index 0000000..e2a5c20
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('watches', function (Blueprint $table) {
+            $table->increments('id');
+            $table->integer('user_id')->index();
+            $table->integer('watchable_id');
+            $table->string('watchable_type', 100);
+            $table->tinyInteger('level', false, true)->index();
+            $table->timestamps();
+
+            $table->index(['watchable_id', 'watchable_type'], 'watchable_index');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('watches');
+    }
+};
index b6b16a607b25bffaee67adcbe979bf9389f87a18..8d6bfed006ebc23fd27f4c589aa59329ad97c10f 100644 (file)
@@ -5,7 +5,7 @@
     <input type="hidden" name="id" value="{{ $entity->id }}">
 
     <ul refs="dropdown@menu" class="dropdown-menu xl-limited anchor-left pb-none">
-        @foreach(\BookStack\Users\UserWatchOptions::getAvailableOptionNames() as $option)
+        @foreach(\BookStack\Activity\Models\Watch::getAvailableOptionNames() as $option)
         <li>
             <button name="level" value="{{ $option }}" class="icon-item">
                 @if(request()->query('level') === $option)