Skip to content

Commit

Permalink
feat: WIP initial commit for reports (#769)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyrch authored Dec 30, 2024
1 parent 912a9c7 commit 33f62da
Show file tree
Hide file tree
Showing 160 changed files with 3,067 additions and 1,176 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ QUEUE_CONNECTION=sync
REDIS_QUEUE=default
QUEUE_FAILED_DRIVER=database-uuids

# report
USER_MAX_REPORTS=50

# sanctum
SANCTUM_STATEFUL_DOMAINS=

Expand Down
3 changes: 3 additions & 0 deletions .env.example-sail
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ QUEUE_CONNECTION=sync
REDIS_QUEUE=default
QUEUE_FAILED_DRIVER=database-uuids

# report
USER_MAX_REPORTS=50

# sanctum
SANCTUM_STATEFUL_DOMAINS=*

Expand Down
158 changes: 158 additions & 0 deletions app/Actions/Models/Admin/Report/ManageStepAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?php

declare(strict_types=1);

namespace App\Actions\Models\Admin\Report;

use App\Enums\Models\Admin\ApprovableStatus;
use App\Enums\Models\Admin\ReportActionType;
use App\Models\Admin\Report\ReportStep;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Facades\Date;

/**
* Class ManageStepAction.
*/
class ManageStepAction
{
/**
* Execute the action and approve the step.
*
* @param ReportStep $step
* @return void
*/
public static function approveStep(ReportStep $step): void
{
match ($step->action) {
ReportActionType::CREATE => static::approveCreate($step),
ReportActionType::DELETE => static::approveDelete($step),
ReportActionType::UPDATE => static::approveUpdate($step),
ReportActionType::ATTACH => static::approveAttach($step),
ReportActionType::DETACH => static::approveDetach($step),
default => null,
};
}

/**
* Create the model according the step.
*
* @param ReportStep $step
* @return void
*/
protected static function approveCreate(ReportStep $step): void
{
/** @var Model $model */
$model = new $step->actionable_type;

$model::query()->create($step->fields);

static::markAsApproved($step);
}

/**
* Delete the model according the step.
*
* @param ReportStep $step
* @return void
*/
protected static function approveDelete(ReportStep $step): void
{
$step->actionable->delete();

static::markAsApproved($step);
}

/**
* Update the model according the step.
*
* @param ReportStep $step
* @return void
*/
protected static function approveUpdate(ReportStep $step): void
{
$step->actionable->update($step->fields);

static::markAsApproved($step);
}

/**
* Attach a model to another according the step.
*
* @param ReportStep $step
* @return void
*/
protected static function approveAttach(ReportStep $step): void
{
/** @var Pivot $pivot */
$pivot = new $step->pivot_class;

$pivot::query()->create($step->fields);

static::markAsApproved($step);
}

/**
* Detach a model from another according the step.
*
* @param ReportStep $step
* @return void
*/
protected static function approveDetach(ReportStep $step): void
{
/** @var Pivot $pivot */
$pivot = new $step->pivot_class;

$pivot::query()->where($step->fields)->delete();

static::markAsApproved($step);
}

/**
* Approve the step.
*
* @param ReportStep $step
* @return void
*/
protected static function markAsApproved(ReportStep $step): void
{
static::updateStatus($step, ApprovableStatus::APPROVED);
}

/**
* Reject the step.
*
* @param ReportStep $step
* @return void
*/
protected static function markAsRejected(ReportStep $step): void
{
static::updateStatus($step, ApprovableStatus::REJECTED);
}

/**
* Approve partially the step.
*
* @param ReportStep $step
* @return void
*/
protected static function markAsPartiallyApproved(ReportStep $step): void
{
static::updateStatus($step, ApprovableStatus::PARTIALLY_APPROVED);
}

/**
* Update the status of the step.
*
* @param ReportStep $step
* @param ApprovableStatus $status
* @return void
*/
protected static function updateStatus(ReportStep $step, ApprovableStatus $status): void
{
$step->query()->update([
ReportStep::ATTRIBUTE_STATUS => $status->value,
ReportStep::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ protected function setUp(): void
*
* @param BaseModel $model
* @return void
*
* @noinspection PhpUnusedParameterInspection
*/
public function handle(BaseModel $model): void
{
Expand Down
6 changes: 1 addition & 5 deletions app/Concerns/Models/CanCreateAnimeSynonym.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ trait CanCreateAnimeSynonym
*/
public function createAnimeSynonym(?string $text, int $type, Anime $anime): void
{
if (
$text === null
|| empty($text)
|| ($type === AnimeSynonymType::OTHER->value && $text === $anime->getName())
) {
if (blank($text) || ($type === AnimeSynonymType::OTHER->value && $text === $anime->getName())) {
return;
}

Expand Down
71 changes: 71 additions & 0 deletions app/Concerns/Models/Reportable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace App\Concerns\Models;

use App\Models\Admin\Report;
use App\Models\Admin\Report\ReportStep;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;

/**
* Trait Reportable.
*/
trait Reportable
{
/**
* Get the reports made to the model.
*
* @return MorphMany
*/
public function reportsteps(): MorphMany
{
return $this->morphMany(ReportStep::class, ReportStep::ATTRIBUTE_ACTIONABLE);
}

/**
* Bootstrap the model.
*
* @return void
*/
protected static function boot(): void
{
parent::boot();

static::creating(function (BaseModel $model) {

if (Gate::forUser(Auth::user())->check('create', $model)) {
return;
}

Report::makeReport(ReportStep::makeForCreate($model::class, $model->attributesToArray()));

return false;
});

static::deleting(function (BaseModel $model) {

if (Gate::forUser(Auth::user())->check('delete', $model)) {
return;
}

Report::makeReport(ReportStep::makeForDelete($model));

return false;
});

static::updating(function (BaseModel $model) {

if (Gate::forUser(Auth::user())->check('update', $model)) {
return;
}

Report::makeReport(ReportStep::makeForUpdate($model, $model->attributesToArray()));

return false;
});
}
}
13 changes: 13 additions & 0 deletions app/Constants/Config/ReportConstants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace App\Constants\Config;

/**
* Class ReportConstants.
*/
class ReportConstants
{
final public const MAX_REPORTS_QUALIFIED = 'report.user_max_reports';
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace App\Enums\Actions;
namespace App\Enums\Models\Admin;

use App\Concerns\Enums\LocalizesName;

Expand Down
35 changes: 35 additions & 0 deletions app/Enums/Models/Admin/ApprovableStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace App\Enums\Models\Admin;

use App\Concerns\Enums\LocalizesName;

/**
* Enum ApprovableStatus.
*/
enum ApprovableStatus: int
{
use LocalizesName;

case PENDING = 0;
case REJECTED = 1;
case PARTIALLY_APPROVED = 2;
case APPROVED = 3;

/**
* Get the filament color for the enum.
*
* @return string
*/
public function color(): string
{
return match ($this) {
ApprovableStatus::PENDING => 'warning',
ApprovableStatus::REJECTED => 'danger',
ApprovableStatus::PARTIALLY_APPROVED => 'info',
ApprovableStatus::APPROVED => 'success',
};
}
}
21 changes: 21 additions & 0 deletions app/Enums/Models/Admin/ReportActionType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Enums\Models\Admin;

use App\Concerns\Enums\LocalizesName;

/**
* Enum ReportActionType.
*/
enum ReportActionType: int
{
use LocalizesName;

case CREATE = 0;
case UPDATE = 1;
case DELETE = 2;
case ATTACH = 3;
case DETACH = 4;
}
30 changes: 30 additions & 0 deletions app/Features/AllowReport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace App\Features;

use App\Enums\Auth\SpecialPermission;
use App\Models\Auth\User;
use Laravel\Pennant\Feature;

/**
* Class AllowReport.
*/
class AllowReport
{
/**
* Resolve feature for scope.
*
* @param User|null $user
* @return bool
*/
public function resolve(?User $user): bool
{
if (! empty($user?->can(SpecialPermission::BYPASS_FEATURE_FLAGS->value))) {
return true;
}

return Feature::for(null)->value(static::class);
}
}
2 changes: 1 addition & 1 deletion app/Filament/Actions/Base/AttachAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected function setUp(): void
$title = $livewire->getTable()->getRecordTitle(new $model);
return Select::make('recordId')
->label($title)
->useScout($model)
->useScout($livewire, $model)
->required();
});

Expand Down
Loading

0 comments on commit 33f62da

Please sign in to comment.