Notifications: Started back-end for watch system
Added DB and started controller method.
This commit is contained in:
		
							parent
							
								
									6100b99828
								
							
						
					
					
						commit
						8cdf3203ef
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
    <input type="hidden" name="id" value="{{ $entity->id }}">
 | 
					    <input type="hidden" name="id" value="{{ $entity->id }}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <ul refs="dropdown@menu" class="dropdown-menu xl-limited anchor-left pb-none">
 | 
					    <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>
 | 
					        <li>
 | 
				
			||||||
            <button name="level" value="{{ $option }}" class="icon-item">
 | 
					            <button name="level" value="{{ $option }}" class="icon-item">
 | 
				
			||||||
                @if(request()->query('level') === $option)
 | 
					                @if(request()->query('level') === $option)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue