refactor: from reports to submissions (#1010)

This commit is contained in:
Kyrch
2025-11-28 17:24:40 -03:00
committed by GitHub
parent 3698939f88
commit f95cac61a2
94 changed files with 966 additions and 963 deletions
+3 -3
View File
@@ -234,9 +234,6 @@ QUEUE_CONNECTION=sync
REDIS_QUEUE=default
QUEUE_FAILED_DRIVER=database-uuids
# report
USER_MAX_REPORTS=50
# sanctum
SANCTUM_STATEFUL_DOMAINS=
@@ -281,6 +278,9 @@ SESSION_STORE=null
SESSION_DOMAIN=null
SESSION_SECURE_COOKIE=
# submission
USER_MAX_SUBMISSIONS=50
# validation
MODERATION_SERVICE=none
+3 -3
View File
@@ -232,9 +232,6 @@ QUEUE_CONNECTION=sync
REDIS_QUEUE=default
QUEUE_FAILED_DRIVER=database-uuids
# report
USER_MAX_REPORTS=50
# sanctum
SANCTUM_STATEFUL_DOMAINS=*
@@ -279,6 +276,9 @@ SESSION_STORE=null
SESSION_DOMAIN=null
SESSION_SECURE_COOKIE=
# submission
USER_MAX_SUBMISSIONS=50
# validation
MODERATION_SERVICE=none
@@ -1,99 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Actions\Models\User\Report;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
class ReportAction
{
/**
* Create a report with the given steps.
*
* @param ReportStep|ReportStep[] $steps
*/
public static function makeReport(ReportStep|array $steps, ?string $notes = null): Report
{
$report = Report::query()->create([
Report::ATTRIBUTE_USER => Auth::id(),
Report::ATTRIBUTE_STATUS => ApprovableStatus::PENDING->value,
Report::ATTRIBUTE_NOTES => $notes,
]);
$report->steps()->saveMany(Arr::wrap($steps));
return $report;
}
/**
* Create a report step to create a model.
*
* @param class-string<Model> $model
*/
public static function makeForCreate(string $model, array $fields): ReportStep
{
return static::makeFor(ReportActionType::CREATE, $model, $fields);
}
/**
* Create a report step to edit a model.
*/
public static function makeForUpdate(Model $model, array $fields): ReportStep
{
return static::makeFor(ReportActionType::UPDATE, $model, $fields);
}
/**
* Create a report step to delete a model.
*/
public static function makeForDelete(Model $model): ReportStep
{
return static::makeFor(ReportActionType::DELETE, $model);
}
/**
* Create a report step to attach a model to another in a many-to-many relationship.
*
* @param class-string<Pivot> $pivot
*/
public static function makeForAttach(Model $foreign, Model $related, string $pivot, array $fields): ReportStep
{
return static::makeFor(ReportActionType::ATTACH, $foreign, $fields, $related, $pivot);
}
/**
* Create a report step to detach a model from another in a many-to-many relationship.
*/
public static function makeForDetach(Model $foreign, Model $related, Pivot $pivot, array $fields): ReportStep
{
return static::makeFor(ReportActionType::DETACH, $foreign, $fields, $related, $pivot);
}
/**
* Create a report step for given action.
*
* @param class-string<Model>|Model $model
*/
protected static function makeFor(ReportActionType $action, Model|string $model, ?array $fields = null, ?Model $related = null, Pivot|string|null $pivot = null): ReportStep
{
return new ReportStep([
ReportStep::ATTRIBUTE_ACTION => $action->value,
ReportStep::ATTRIBUTE_ACTIONABLE_TYPE => $model instanceof Model ? Relation::getMorphAlias($model->getMorphClass()) : $model,
ReportStep::ATTRIBUTE_ACTIONABLE_ID => $model instanceof Model ? $model->getKey() : null,
ReportStep::ATTRIBUTE_FIELDS => Arr::where($fields, fn ($value, $key) => $model->isFillable($key)),
ReportStep::ATTRIBUTE_STATUS => ApprovableStatus::PENDING->value,
ReportStep::ATTRIBUTE_TARGET_TYPE => $related instanceof Model ? Relation::getMorphAlias($related->getMorphClass()) : null,
ReportStep::ATTRIBUTE_TARGET_ID => $related instanceof Model ? $related->getKey() : null,
ReportStep::ATTRIBUTE_PIVOT => $pivot instanceof Model ? Relation::getMorphAlias($pivot->getMorphClass()) : $pivot,
]);
}
}
@@ -2,11 +2,11 @@
declare(strict_types=1);
namespace App\Actions\Models\User\Report;
namespace App\Actions\Models\User\Submission;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Models\User\Report\ReportStep;
use App\Enums\Models\User\SubmissionActionType;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Facades\Date;
@@ -16,19 +16,19 @@ class ManageStepAction
/**
* Execute the action and approve the step.
*/
public static function approveStep(ReportStep $step): void
public static function approveStep(SubmissionStep $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),
SubmissionActionType::CREATE => static::approveCreate($step),
SubmissionActionType::DELETE => static::approveDelete($step),
SubmissionActionType::UPDATE => static::approveUpdate($step),
SubmissionActionType::ATTACH => static::approveAttach($step),
SubmissionActionType::DETACH => static::approveDetach($step),
default => null,
};
}
protected static function approveCreate(ReportStep $step): void
protected static function approveCreate(SubmissionStep $step): void
{
/** @var Model $model */
$model = new $step->actionable_type;
@@ -38,21 +38,21 @@ class ManageStepAction
static::markAsApproved($step);
}
protected static function approveDelete(ReportStep $step): void
protected static function approveDelete(SubmissionStep $step): void
{
$step->actionable->delete();
static::markAsApproved($step);
}
protected static function approveUpdate(ReportStep $step): void
protected static function approveUpdate(SubmissionStep $step): void
{
$step->actionable->update($step->fields);
static::markAsApproved($step);
}
protected static function approveAttach(ReportStep $step): void
protected static function approveAttach(SubmissionStep $step): void
{
/** @var Pivot $pivot */
$pivot = new $step->pivot;
@@ -62,7 +62,7 @@ class ManageStepAction
static::markAsApproved($step);
}
protected static function approveDetach(ReportStep $step): void
protected static function approveDetach(SubmissionStep $step): void
{
/** @var Pivot $pivot */
$pivot = new $step->pivot;
@@ -72,26 +72,26 @@ class ManageStepAction
static::markAsApproved($step);
}
protected static function markAsApproved(ReportStep $step): void
protected static function markAsApproved(SubmissionStep $step): void
{
static::updateStatus($step, ApprovableStatus::APPROVED);
}
protected static function markAsRejected(ReportStep $step): void
protected static function markAsRejected(SubmissionStep $step): void
{
static::updateStatus($step, ApprovableStatus::REJECTED);
}
protected static function markAsPartiallyApproved(ReportStep $step): void
protected static function markAsPartiallyApproved(SubmissionStep $step): void
{
static::updateStatus($step, ApprovableStatus::PARTIALLY_APPROVED);
}
protected static function updateStatus(ReportStep $step, ApprovableStatus $status): void
protected static function updateStatus(SubmissionStep $step, ApprovableStatus $status): void
{
$step->update([
ReportStep::ATTRIBUTE_STATUS => $status->value,
ReportStep::ATTRIBUTE_FINISHED_AT => Date::now(),
SubmissionStep::ATTRIBUTE_STATUS => $status->value,
SubmissionStep::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
}
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace App\Actions\Models\User\Submission;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\SubmissionActionType;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
class SubmissionAction
{
/**
* Create a submission with the given steps.
*
* @param SubmissionStep|SubmissionStep[] $steps
*/
public static function makeSubmission(SubmissionStep|array $steps, ?string $notes = null): Submission
{
$submission = Submission::query()->create([
Submission::ATTRIBUTE_USER => Auth::id(),
Submission::ATTRIBUTE_STATUS => ApprovableStatus::PENDING->value,
Submission::ATTRIBUTE_NOTES => $notes,
]);
$submission->steps()->saveMany(Arr::wrap($steps));
return $submission;
}
/**
* Create a submission step to create a model.
*
* @param class-string<Model> $model
*/
public static function makeForCreate(string $model, array $fields): SubmissionStep
{
return static::makeFor(SubmissionActionType::CREATE, $model, $fields);
}
/**
* Create a submission step to edit a model.
*/
public static function makeForUpdate(Model $model, array $fields): SubmissionStep
{
return static::makeFor(SubmissionActionType::UPDATE, $model, $fields);
}
/**
* Create a submission step to delete a model.
*/
public static function makeForDelete(Model $model): SubmissionStep
{
return static::makeFor(SubmissionActionType::DELETE, $model);
}
/**
* Create a submission step to attach a model to another in a many-to-many relationship.
*
* @param class-string<Pivot> $pivot
*/
public static function makeForAttach(Model $foreign, Model $related, string $pivot, array $fields): SubmissionStep
{
return static::makeFor(SubmissionActionType::ATTACH, $foreign, $fields, $related, $pivot);
}
/**
* Create a submission step to detach a model from another in a many-to-many relationship.
*/
public static function makeForDetach(Model $foreign, Model $related, Pivot $pivot, array $fields): SubmissionStep
{
return static::makeFor(SubmissionActionType::DETACH, $foreign, $fields, $related, $pivot);
}
/**
* Create a submission step for given action.
*
* @param class-string<Model>|Model $model
*/
protected static function makeFor(SubmissionActionType $action, Model|string $model, ?array $fields = null, ?Model $related = null, Pivot|string|null $pivot = null): SubmissionStep
{
return new SubmissionStep([
SubmissionStep::ATTRIBUTE_ACTION => $action->value,
SubmissionStep::ATTRIBUTE_ACTIONABLE_TYPE => $model instanceof Model ? Relation::getMorphAlias($model->getMorphClass()) : $model,
SubmissionStep::ATTRIBUTE_ACTIONABLE_ID => $model instanceof Model ? $model->getKey() : null,
SubmissionStep::ATTRIBUTE_FIELDS => Arr::where($fields, fn ($value, $key) => $model->isFillable($key)),
SubmissionStep::ATTRIBUTE_STATUS => ApprovableStatus::PENDING->value,
SubmissionStep::ATTRIBUTE_TARGET_TYPE => $related instanceof Model ? Relation::getMorphAlias($related->getMorphClass()) : null,
SubmissionStep::ATTRIBUTE_TARGET_ID => $related instanceof Model ? $related->getKey() : null,
SubmissionStep::ATTRIBUTE_PIVOT => $pivot instanceof Model ? Relation::getMorphAlias($pivot->getMorphClass()) : $pivot,
]);
}
}
@@ -8,8 +8,8 @@ use App\Concerns\Repositories\Admin\ReconcilesDumpRepositories;
use App\Models\Aggregate\LikeAggregate;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
@@ -29,8 +29,8 @@ class DumpUserAction extends DumpAction
Like::TABLE,
LikeAggregate::TABLE,
Notification::TABLE,
Report::TABLE,
ReportStep::TABLE,
Submission::TABLE,
SubmissionStep::TABLE,
];
}
-16
View File
@@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Models;
use App\Models\User\Report\ReportStep;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait Reportable
{
public function reportsteps(): MorphMany
{
return $this->morphMany(ReportStep::class, ReportStep::RELATION_ACTIONABLE);
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Models;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait Submitable
{
public function submissionsteps(): MorphMany
{
return $this->morphMany(SubmissionStep::class, SubmissionStep::RELATION_ACTIONABLE);
}
}
-10
View File
@@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Constants\Config;
class ReportConstants
{
final public const string MAX_REPORTS_QUALIFIED = 'report.user_max_reports';
}
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace App\Constants\Config;
class SubmissionConstants
{
final public const string MAX_SUBMISSIONS_QUALIFIED = 'submission.user_max_submissions';
}
@@ -4,4 +4,4 @@ declare(strict_types=1);
namespace App\Contracts\GraphQL\Types;
interface ReportableType {}
interface SubmitableType {}
@@ -7,7 +7,7 @@ namespace App\Enums\Models\User;
use App\Concerns\Enums\LocalizesName;
use Filament\Support\Contracts\HasLabel;
enum ReportActionType: int implements HasLabel
enum SubmissionActionType: int implements HasLabel
{
use LocalizesName;
@@ -8,7 +8,7 @@ use App\Enums\Auth\SpecialPermission;
use App\Models\Auth\User;
use Laravel\Pennant\Feature;
class AllowReport
class AllowSubmission
{
public function resolve(?User $user): bool
{
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Filament\Actions\Models\Wiki;
use App\Actions\ActionResult;
use App\Actions\Models\Wiki\AttachResourceAction as AttachResource;
use App\Contracts\Models\HasResources;
use App\Enums\Models\Wiki\ResourceSite;
@@ -34,7 +35,7 @@ abstract class AttachResourceAction extends BaseAction
$this->visible(Gate::allows('create', ExternalResource::class));
$this->action(fn (BaseModel&HasResources $record, array $data, AttachResource $attachResource) => $attachResource->handle($record, $data, $this->sites));
$this->action(fn (BaseModel&HasResources $record, array $data, AttachResource $attachResource): ActionResult => $attachResource->handle($record, $data, $this->sites));
}
/**
@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\RelationManagers\User;
use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\BaseResource;
use App\Filament\Resources\User\Report\ReportStep as ReportStepResource;
use App\Models\User\Report\ReportStep;
use Filament\Tables\Table;
abstract class ReportStepRelationManager extends BaseRelationManager
{
/**
* The resource of the relation manager.
*
* @var class-string<BaseResource>|null
*/
protected static ?string $relatedResource = ReportStepResource::class;
public function table(Table $table): Table
{
return parent::table(
$table
->recordTitleAttribute(ReportStepResource::getRecordTitleAttribute())
->defaultSort(ReportStep::TABLE.'.'.ReportStep::ATTRIBUTE_ID, 'desc')
);
}
}
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Filament\RelationManagers\User;
use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\BaseResource;
use App\Filament\Resources\User\Submission\SubmissionStep as SubmissionStepResource;
use App\Models\User\Submission\SubmissionStep;
use Filament\Tables\Table;
abstract class SubmissionStepRelationManager extends BaseRelationManager
{
/**
* The resource of the relation manager.
*
* @var class-string<BaseResource>|null
*/
protected static ?string $relatedResource = SubmissionStepResource::class;
public function table(Table $table): Table
{
return parent::table(
$table
->recordTitleAttribute(SubmissionStepResource::getRecordTitleAttribute())
->defaultSort(SubmissionStep::TABLE.'.'.SubmissionStep::ATTRIBUTE_ID, 'desc')
);
}
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report\Pages;
use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\User\Report;
class ListReports extends BaseListResources
{
protected static string $resource = Report::class;
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report\Pages;
use App\Filament\Resources\Base\BaseViewResource;
use App\Filament\Resources\User\Report;
class ViewReport extends BaseViewResource
{
protected static string $resource = Report::class;
}
@@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report\RelationManagers;
use App\Filament\RelationManagers\User\ReportStepRelationManager;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use Filament\Tables\Table;
class StepReportRelationManager extends ReportStepRelationManager
{
/**
* The relationship the relation manager corresponds to.
*/
protected static string $relationship = Report::RELATION_STEPS;
public function table(Table $table): Table
{
return parent::table(
$table
->inverseRelationship(ReportStep::RELATION_REPORT)
);
}
}
@@ -1,196 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report;
use App\Contracts\Models\Nameable;
use App\Enums\Filament\NavigationGroup;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Filament\Components\Columns\BelongsToColumn;
use App\Filament\Components\Columns\TextColumn;
use App\Filament\Components\Infolist\BelongsToEntry;
use App\Filament\Components\Infolist\KeyValueThreeEntry;
use App\Filament\Components\Infolist\TextEntry;
use App\Filament\Components\Infolist\TimestampSection;
use App\Filament\Resources\BaseResource;
use App\Filament\Resources\User\Report as ReportResource;
use App\Filament\Resources\User\Report\ReportStep\Pages\ListReportSteps;
use App\Filament\Resources\User\Report\ReportStep\Pages\ViewReportStep;
use App\Models\User\Report\ReportStep as ReportStepModel;
use Filament\Facades\Filament;
use Filament\Infolists\Components\KeyValueEntry;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class ReportStep extends BaseResource
{
/**
* The model the resource corresponds to.
*
* @var class-string<Model>|null
*/
protected static ?string $model = ReportStepModel::class;
public static function getModelLabel(): string
{
return __('filament.resources.singularLabel.report_step');
}
public static function getPluralModelLabel(): string
{
return __('filament.resources.label.report_steps');
}
public static function getNavigationGroup(): NavigationGroup
{
return NavigationGroup::USER;
}
public static function getNavigationIcon(): Heroicon
{
return Heroicon::OutlinedLightBulb;
}
public static function getRecordSlug(): string
{
return 'report-steps';
}
public static function getRecordTitleAttribute(): string
{
return ReportStepModel::ATTRIBUTE_ID;
}
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery();
// Necessary to prevent lazy loading when loading related resources
return $query->with([
ReportStepModel::RELATION_REPORT,
]);
}
public static function form(Schema $schema): Schema
{
return $schema;
}
public static function table(Table $table): Table
{
return parent::table($table)
->columns([
TextColumn::make(ReportStepModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextColumn::make(ReportStepModel::ATTRIBUTE_ACTION)
->label(__('filament.fields.report_step.actionable'))
->html()
->formatStateUsing(fn (ReportStepModel $record): string => class_basename($record->actionable_type)),
TextColumn::make(ReportStepModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.report.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
TextColumn::make(ReportStepModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.report.finished_at'))
->dateTime(),
BelongsToColumn::make(ReportStepModel::RELATION_REPORT, ReportResource::class),
]);
}
public static function infolist(Schema $schema): Schema
{
return $schema
->components([
Section::make(static::getRecordTitle($schema->getRecord()))
->schema([
TextEntry::make(ReportStepModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextEntry::make(ReportStepModel::ATTRIBUTE_ACTION)
->label(__('filament.fields.report_step.action'))
->html()
->formatStateUsing(fn (ReportStepModel $record, ReportActionType $state): string => static::getActionName($record, $state)),
TextEntry::make(ReportStepModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.report.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
TextEntry::make(ReportStepModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.report.finished_at'))
->dateTime(),
BelongsToEntry::make(ReportStepModel::RELATION_REPORT, ReportResource::class)
->label(__('filament.resources.singularLabel.report')),
KeyValueThreeEntry::make(ReportStepModel::ATTRIBUTE_FIELDS)
->label(__('filament.fields.report_step.fields.name'))
->leftLabel(__('filament.fields.report_step.fields.columns'))
->middleLabel(__('filament.fields.report_step.fields.old_values'))
->rightLabel(__('filament.fields.report_step.fields.values'))
->middleValueThroughState(fn (ReportStepModel $record): array => $record->formatFields($record->actionable->attributesToArray()))
->visible(fn (ReportStepModel $record): bool => $record->action === ReportActionType::UPDATE)
->state(fn (ReportStepModel $record): array => $record->formatFields())
->columnSpanFull(),
KeyValueEntry::make(ReportStepModel::ATTRIBUTE_FIELDS)
->label(__('filament.fields.report_step.fields.name'))
->keyLabel(__('filament.fields.report_step.fields.columns'))
->valueLabel(__('filament.fields.report_step.fields.values'))
->hidden(fn (?array $state, ReportStepModel $record): bool => is_null($state) || $record->action === ReportActionType::UPDATE)
->columnSpanFull(),
])
->columns(3),
TimestampSection::make(),
]);
}
/**
* The title of the report step.
*/
protected static function getActionName(ReportStepModel $record, ReportActionType $state): string
{
$name = $record->actionable instanceof Nameable ? $record->actionable->getName() : $record->actionable_type;
if ($state === ReportActionType::CREATE) {
return $record->action->localize().' '.$name;
}
$actionableUrl = Filament::getUrl($record->actionable);
$actionableLink = "<a style='color: rgb(64, 184, 166);' href='{$actionableUrl}'>{$name}</a>";
if ($state === ReportActionType::ATTACH || $state === ReportActionType::DETACH) {
$targetUrl = Filament::getUrl($record->target);
$targetName = $record->target instanceof Nameable ? $record->target->getName() : $record->target_type;
$targetLink = "<a style='color: rgb(64, 184, 166);' href='{$targetUrl}'>{$targetName}</a>";
return $state->localize().' '.$actionableLink.' to '.$targetLink.' via '.class_basename($record->pivot);
}
return $record->action->localize().' '.$actionableLink;
}
/**
* @return array<string, \Filament\Resources\Pages\PageRegistration>
*/
public static function getPages(): array
{
return [
'index' => ListReportSteps::route('/'),
'view' => ViewReportStep::route('/{record:step_id}'),
];
}
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report\ReportStep\Pages;
use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\User\Report\ReportStep;
class ListReportSteps extends BaseListResources
{
protected static string $resource = ReportStep::class;
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Report\ReportStep\Pages;
use App\Filament\Resources\Base\BaseViewResource;
use App\Filament\Resources\User\Report\ReportStep;
class ViewReportStep extends BaseViewResource
{
protected static string $resource = ReportStep::class;
}
@@ -13,10 +13,10 @@ use App\Filament\Components\Infolist\TextEntry;
use App\Filament\Components\Infolist\TimestampSection;
use App\Filament\Resources\Auth\User as UserResource;
use App\Filament\Resources\BaseResource;
use App\Filament\Resources\User\Report\Pages\ListReports;
use App\Filament\Resources\User\Report\Pages\ViewReport;
use App\Filament\Resources\User\Report\RelationManagers\StepReportRelationManager;
use App\Models\User\Report as ReportModel;
use App\Filament\Resources\User\Submission\Pages\ListSubmissions;
use App\Filament\Resources\User\Submission\Pages\ViewSubmission;
use App\Filament\Resources\User\Submission\RelationManagers\StepSubmissionRelationManager;
use App\Models\User\Submission as SubmissionModel;
use Filament\Resources\RelationManagers\RelationGroup;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
@@ -25,23 +25,23 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Report extends BaseResource
class Submission extends BaseResource
{
/**
* The model the resource corresponds to.
*
* @var class-string<Model>|null
*/
protected static ?string $model = ReportModel::class;
protected static ?string $model = SubmissionModel::class;
public static function getModelLabel(): string
{
return __('filament.resources.singularLabel.report');
return __('filament.resources.singularLabel.submission');
}
public static function getPluralModelLabel(): string
{
return __('filament.resources.label.reports');
return __('filament.resources.label.submissions');
}
public static function getNavigationGroup(): NavigationGroup
@@ -56,12 +56,12 @@ class Report extends BaseResource
public static function getRecordSlug(): string
{
return 'reports';
return 'submissions';
}
public static function getRecordTitleAttribute(): string
{
return ReportModel::ATTRIBUTE_ID;
return SubmissionModel::ATTRIBUTE_ID;
}
public static function getEloquentQuery(): Builder
@@ -70,8 +70,8 @@ class Report extends BaseResource
// Necessary to prevent lazy loading when loading related resources
return $query->with([
ReportModel::RELATION_USER,
ReportModel::RELATION_MODERATOR,
SubmissionModel::RELATION_USER,
SubmissionModel::RELATION_MODERATOR,
]);
}
@@ -84,21 +84,21 @@ class Report extends BaseResource
{
return parent::table($table)
->columns([
TextColumn::make(ReportModel::ATTRIBUTE_ID)
TextColumn::make(SubmissionModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextColumn::make(ReportModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.report.status'))
TextColumn::make(SubmissionModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.submission.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
BelongsToColumn::make(ReportModel::RELATION_USER, UserResource::class),
BelongsToColumn::make(SubmissionModel::RELATION_USER, UserResource::class),
BelongsToColumn::make(ReportModel::RELATION_MODERATOR, UserResource::class)
->label(__('filament.fields.report.moderator')),
BelongsToColumn::make(SubmissionModel::RELATION_MODERATOR, UserResource::class)
->label(__('filament.fields.submission.moderator')),
TextColumn::make(ReportModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.report.finished_at'))
TextColumn::make(SubmissionModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.submission.finished_at'))
->dateTime(),
]);
}
@@ -109,25 +109,25 @@ class Report extends BaseResource
->components([
Section::make(static::getRecordTitle($schema->getRecord()))
->schema([
TextEntry::make(ReportModel::ATTRIBUTE_ID)
TextEntry::make(SubmissionModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextEntry::make(ReportModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.report.status'))
TextEntry::make(SubmissionModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.submission.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
BelongsToEntry::make(ReportModel::RELATION_USER, UserResource::class),
BelongsToEntry::make(SubmissionModel::RELATION_USER, UserResource::class),
BelongsToEntry::make(ReportModel::RELATION_MODERATOR, UserResource::class)
->label(__('filament.fields.report.moderator')),
BelongsToEntry::make(SubmissionModel::RELATION_MODERATOR, UserResource::class)
->label(__('filament.fields.submission.moderator')),
TextEntry::make(ReportModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.report.finished_at'))
TextEntry::make(SubmissionModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.submission.finished_at'))
->dateTime(),
TextEntry::make(ReportModel::ATTRIBUTE_NOTES)
->label(__('filament.fields.report.notes'))
TextEntry::make(SubmissionModel::ATTRIBUTE_NOTES)
->label(__('filament.fields.submission.notes'))
->columnSpanFull(),
])
->columns(3),
@@ -143,7 +143,7 @@ class Report extends BaseResource
{
return [
RelationGroup::make(static::getModelLabel(), [
StepReportRelationManager::class,
StepSubmissionRelationManager::class,
]),
];
}
@@ -154,8 +154,8 @@ class Report extends BaseResource
public static function getPages(): array
{
return [
'index' => ListReports::route('/'),
'view' => ViewReport::route('/{record:report_id}'),
'index' => ListSubmissions::route('/'),
'view' => ViewSubmission::route('/{record:submission_id}'),
];
}
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission\Pages;
use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\User\Submission;
class ListSubmissions extends BaseListResources
{
protected static string $resource = Submission::class;
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission\Pages;
use App\Filament\Resources\Base\BaseViewResource;
use App\Filament\Resources\User\Submission;
class ViewSubmission extends BaseViewResource
{
protected static string $resource = Submission::class;
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission\RelationManagers;
use App\Filament\RelationManagers\User\SubmissionStepRelationManager;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Filament\Tables\Table;
class StepSubmissionRelationManager extends SubmissionStepRelationManager
{
/**
* The relationship the relation manager corresponds to.
*/
protected static string $relationship = Submission::RELATION_STEPS;
public function table(Table $table): Table
{
return parent::table(
$table
->inverseRelationship(SubmissionStep::RELATION_SUBMISSION)
);
}
}
@@ -0,0 +1,196 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission;
use App\Contracts\Models\Nameable;
use App\Enums\Filament\NavigationGroup;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\SubmissionActionType;
use App\Filament\Components\Columns\BelongsToColumn;
use App\Filament\Components\Columns\TextColumn;
use App\Filament\Components\Infolist\BelongsToEntry;
use App\Filament\Components\Infolist\KeyValueThreeEntry;
use App\Filament\Components\Infolist\TextEntry;
use App\Filament\Components\Infolist\TimestampSection;
use App\Filament\Resources\BaseResource;
use App\Filament\Resources\User\Submission as SubmissionResource;
use App\Filament\Resources\User\Submission\SubmissionStep\Pages\ListSubmissionSteps;
use App\Filament\Resources\User\Submission\SubmissionStep\Pages\ViewSubmissionStep;
use App\Models\User\Submission\SubmissionStep as SubmissionStepModel;
use Filament\Facades\Filament;
use Filament\Infolists\Components\KeyValueEntry;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class SubmissionStep extends BaseResource
{
/**
* The model the resource corresponds to.
*
* @var class-string<Model>|null
*/
protected static ?string $model = SubmissionStepModel::class;
public static function getModelLabel(): string
{
return __('filament.resources.singularLabel.submission_step');
}
public static function getPluralModelLabel(): string
{
return __('filament.resources.label.submission_steps');
}
public static function getNavigationGroup(): NavigationGroup
{
return NavigationGroup::USER;
}
public static function getNavigationIcon(): Heroicon
{
return Heroicon::OutlinedLightBulb;
}
public static function getRecordSlug(): string
{
return 'submission-steps';
}
public static function getRecordTitleAttribute(): string
{
return SubmissionStepModel::ATTRIBUTE_ID;
}
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery();
// Necessary to prevent lazy loading when loading related resources
return $query->with([
SubmissionStepModel::RELATION_SUBMISSION,
]);
}
public static function form(Schema $schema): Schema
{
return $schema;
}
public static function table(Table $table): Table
{
return parent::table($table)
->columns([
TextColumn::make(SubmissionStepModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextColumn::make(SubmissionStepModel::ATTRIBUTE_ACTION)
->label(__('filament.fields.submission_step.actionable'))
->html()
->formatStateUsing(fn (SubmissionStepModel $record): string => class_basename($record->actionable_type)),
TextColumn::make(SubmissionStepModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.submission.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
TextColumn::make(SubmissionStepModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.submission.finished_at'))
->dateTime(),
BelongsToColumn::make(SubmissionStepModel::RELATION_SUBMISSION, SubmissionResource::class),
]);
}
public static function infolist(Schema $schema): Schema
{
return $schema
->components([
Section::make(static::getRecordTitle($schema->getRecord()))
->schema([
TextEntry::make(SubmissionStepModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
TextEntry::make(SubmissionStepModel::ATTRIBUTE_ACTION)
->label(__('filament.fields.submission_step.action'))
->html()
->formatStateUsing(fn (SubmissionStepModel $record, SubmissionActionType $state): string => static::getActionName($record, $state)),
TextEntry::make(SubmissionStepModel::ATTRIBUTE_STATUS)
->label(__('filament.fields.submission.status'))
->formatStateUsing(fn (ApprovableStatus $state): ?string => $state->localize())
->badge(),
TextEntry::make(SubmissionStepModel::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.submission.finished_at'))
->dateTime(),
BelongsToEntry::make(SubmissionStepModel::RELATION_SUBMISSION, SubmissionResource::class)
->label(__('filament.resources.singularLabel.submission')),
KeyValueThreeEntry::make(SubmissionStepModel::ATTRIBUTE_FIELDS)
->label(__('filament.fields.submission_step.fields.name'))
->leftLabel(__('filament.fields.submission_step.fields.columns'))
->middleLabel(__('filament.fields.submission_step.fields.old_values'))
->rightLabel(__('filament.fields.submission_step.fields.values'))
->middleValueThroughState(fn (SubmissionStepModel $record): array => $record->formatFields($record->actionable->attributesToArray()))
->visible(fn (SubmissionStepModel $record): bool => $record->action === SubmissionActionType::UPDATE)
->state(fn (SubmissionStepModel $record): array => $record->formatFields())
->columnSpanFull(),
KeyValueEntry::make(SubmissionStepModel::ATTRIBUTE_FIELDS)
->label(__('filament.fields.submission_step.fields.name'))
->keyLabel(__('filament.fields.submission_step.fields.columns'))
->valueLabel(__('filament.fields.submission_step.fields.values'))
->hidden(fn (?array $state, SubmissionStepModel $record): bool => is_null($state) || $record->action === SubmissionActionType::UPDATE)
->columnSpanFull(),
])
->columns(3),
TimestampSection::make(),
]);
}
/**
* The title of the submission step.
*/
protected static function getActionName(SubmissionStepModel $record, SubmissionActionType $state): string
{
$name = $record->actionable instanceof Nameable ? $record->actionable->getName() : $record->actionable_type;
if ($state === SubmissionActionType::CREATE) {
return $record->action->localize().' '.$name;
}
$actionableUrl = Filament::getUrl($record->actionable);
$actionableLink = "<a style='color: rgb(64, 184, 166);' href='{$actionableUrl}'>{$name}</a>";
if ($state === SubmissionActionType::ATTACH || $state === SubmissionActionType::DETACH) {
$targetUrl = Filament::getUrl($record->target);
$targetName = $record->target instanceof Nameable ? $record->target->getName() : $record->target_type;
$targetLink = "<a style='color: rgb(64, 184, 166);' href='{$targetUrl}'>{$targetName}</a>";
return $state->localize().' '.$actionableLink.' to '.$targetLink.' via '.class_basename($record->pivot);
}
return $record->action->localize().' '.$actionableLink;
}
/**
* @return array<string, \Filament\Resources\Pages\PageRegistration>
*/
public static function getPages(): array
{
return [
'index' => ListSubmissionSteps::route('/'),
'view' => ViewSubmissionStep::route('/{record:step_id}'),
];
}
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission\SubmissionStep\Pages;
use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\User\Submission\SubmissionStep;
class ListSubmissionSteps extends BaseListResources
{
protected static string $resource = SubmissionStep::class;
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\User\Submission\SubmissionStep\Pages;
use App\Filament\Resources\Base\BaseViewResource;
use App\Filament\Resources\User\Submission\SubmissionStep;
class ViewSubmissionStep extends BaseViewResource
{
protected static string $resource = SubmissionStep::class;
}
@@ -40,7 +40,7 @@ class CreateInput extends Input
$baseType = $this->type;
$fields[] = collect($baseType->fieldClasses())
->filter(fn (Field $field): bool => $field instanceof CreatableField) // and reportable field?
->filter(fn (Field $field): bool => $field instanceof CreatableField) // and submitable field?
->map(
fn (Field&CreatableField $field): InputField => new InputField($field->getName(), $field->type().($field instanceof RequiredOnCreation ? '!' : ''))
)
@@ -46,7 +46,7 @@ class UpdateInput extends Input
->toArray();
$fields[] = collect($baseType->fieldClasses())
->filter(fn (Field $field): bool => $field instanceof UpdatableField) // and reportable field?
->filter(fn (Field $field): bool => $field instanceof UpdatableField) // and submitable field?
->map(
fn (Field&UpdatableField $field): InputField => new InputField($field->getName(), $field->type().($field instanceof RequiredOnUpdate ? '!' : ''))
)
@@ -2,12 +2,12 @@
declare(strict_types=1);
namespace App\GraphQL\Schema\Mutations\Reports\Base;
namespace App\GraphQL\Schema\Mutations\Submissions\Base;
use App\GraphQL\Schema\Mutations\Reports\BaseReportMutation;
use App\GraphQL\Schema\Mutations\Submissions\BaseSubmissionMutation;
use Illuminate\Support\Str;
abstract class UpdateReportMutation extends BaseReportMutation
abstract class UpdateSubmissionMutation extends BaseSubmissionMutation
{
/**
* The input type of the 'input' argument on the top mutation.
@@ -2,13 +2,13 @@
declare(strict_types=1);
namespace App\GraphQL\Schema\Mutations\Reports;
namespace App\GraphQL\Schema\Mutations\Submissions;
use App\GraphQL\Schema\Mutations\BaseMutation;
use App\GraphQL\Support\Argument\Argument;
use GraphQL\Type\Definition\Type;
abstract class BaseReportMutation extends BaseMutation
abstract class BaseSubmissionMutation extends BaseMutation
{
/**
* The arguments of the mutation.
@@ -2,22 +2,22 @@
declare(strict_types=1);
namespace App\GraphQL\Schema\Mutations\Reports\Wiki;
namespace App\GraphQL\Schema\Mutations\Submissions\Wiki;
use App\GraphQL\Schema\Mutations\Reports\Base\UpdateReportMutation;
use App\GraphQL\Schema\Mutations\Submissions\Base\UpdateSubmissionMutation;
use App\GraphQL\Schema\Types\Wiki\AnimeType;
use GraphQL\Type\Definition\ResolveInfo;
class AnimeReportMutation extends UpdateReportMutation
class AnimeSubmissionMutation extends UpdateSubmissionMutation
{
public function __construct()
{
parent::__construct('reportUpdateAnime');
parent::__construct('submitUpdateAnime');
}
public function description(): string
{
return 'Report information about an anime page.';
return 'Submission information about an anime page.';
}
/**
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Document;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdUnbindableField;
@@ -16,7 +16,7 @@ use App\GraphQL\Schema\Fields\Field;
use App\GraphQL\Schema\Types\EloquentType;
use App\Models\Document\Page;
class PageType extends EloquentType implements ReportableType
class PageType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Morph;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -17,7 +17,7 @@ use App\GraphQL\Schema\Types\Wiki\ImageType;
use App\GraphQL\Schema\Unions\ImageableUnion;
use App\Pivots\Morph\Imageable;
class ImageableType extends PivotType implements ReportableType
class ImageableType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Morph;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -17,7 +17,7 @@ use App\GraphQL\Schema\Types\Wiki\ExternalResourceType;
use App\GraphQL\Schema\Unions\ResourceableUnion;
use App\Pivots\Morph\Resourceable;
class ResourceableType extends PivotType implements ReportableType
class ResourceableType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -15,7 +15,7 @@ use App\GraphQL\Schema\Types\Wiki\AnimeType;
use App\GraphQL\Schema\Types\Wiki\SeriesType;
use App\Pivots\Wiki\AnimeSeries;
class AnimeSeriesType extends PivotType implements ReportableType
class AnimeSeriesType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -15,7 +15,7 @@ use App\GraphQL\Schema\Types\Wiki\AnimeType;
use App\GraphQL\Schema\Types\Wiki\StudioType;
use App\Pivots\Wiki\AnimeStudio;
class AnimeStudioType extends PivotType implements ReportableType
class AnimeStudioType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -15,7 +15,7 @@ use App\GraphQL\Schema\Types\Wiki\Anime\Theme\AnimeThemeEntryType;
use App\GraphQL\Schema\Types\Wiki\VideoType;
use App\Pivots\Wiki\AnimeThemeEntryVideo;
class AnimeThemeEntryVideoType extends PivotType implements ReportableType
class AnimeThemeEntryVideoType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Pivot\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\UpdatedAtField;
use App\GraphQL\Schema\Fields\Field;
@@ -18,7 +18,7 @@ use App\GraphQL\Schema\Types\Pivot\PivotType;
use App\GraphQL\Schema\Types\Wiki\ArtistType;
use App\Pivots\Wiki\ArtistMember;
class ArtistMemberType extends PivotType implements ReportableType
class ArtistMemberType extends PivotType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki\Anime;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -19,7 +19,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Wiki\AnimeType;
use App\Models\Wiki\Anime\AnimeSynonym;
class AnimeSynonymType extends EloquentType implements ReportableType
class AnimeSynonymType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki\Anime;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -24,7 +24,7 @@ use App\GraphQL\Schema\Types\Wiki\SongType;
use App\GraphQL\Schema\Types\Wiki\ThemeGroupType;
use App\Models\Wiki\Anime\AnimeTheme;
class AnimeThemeType extends EloquentType implements ReportableType
class AnimeThemeType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki\Anime\Theme;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -29,7 +29,7 @@ use App\GraphQL\Schema\Types\Wiki\ExternalResourceType;
use App\GraphQL\Schema\Types\Wiki\VideoType;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
class AnimeThemeEntryType extends EloquentType implements ReportableType
class AnimeThemeEntryType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdUnbindableField;
@@ -30,7 +30,7 @@ use App\GraphQL\Schema\Types\Wiki\Anime\AnimeSynonymType;
use App\GraphQL\Schema\Types\Wiki\Anime\AnimeThemeType;
use App\Models\Wiki\Anime;
class AnimeType extends EloquentType implements ReportableType
class AnimeType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdUnbindableField;
@@ -26,7 +26,7 @@ use App\GraphQL\Schema\Types\Wiki\Song\MembershipType;
use App\GraphQL\Schema\Types\Wiki\Song\PerformanceType;
use App\Models\Wiki\Artist;
class ArtistType extends EloquentType implements ReportableType
class ArtistType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -20,7 +20,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Pivot\Morph\ResourceableType;
use App\Models\Wiki\ExternalResource;
class ExternalResourceType extends EloquentType implements ReportableType
class ExternalResourceType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -20,7 +20,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Pivot\Morph\ImageableType;
use App\Models\Wiki\Image;
class ImageType extends EloquentType implements ReportableType
class ImageType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdUnbindableField;
@@ -18,7 +18,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Pivot\Wiki\AnimeSeriesType;
use App\Models\Wiki\Series;
class SeriesType extends EloquentType implements ReportableType
class SeriesType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki\Song;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -19,7 +19,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Wiki\ArtistType;
use App\Models\Wiki\Song\Membership;
class MembershipType extends EloquentType implements ReportableType
class MembershipType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki\Song;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -21,7 +21,7 @@ use App\GraphQL\Schema\Types\Wiki\SongType;
use App\GraphQL\Schema\Unions\PerformanceArtistUnion;
use App\Models\Wiki\Song\Performance;
class PerformanceType extends EloquentType implements ReportableType
class PerformanceType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -21,7 +21,7 @@ use App\GraphQL\Schema\Types\Wiki\Anime\AnimeThemeType;
use App\GraphQL\Schema\Types\Wiki\Song\PerformanceType;
use App\Models\Wiki\Song;
class SongType extends EloquentType implements ReportableType
class SongType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdUnbindableField;
@@ -21,7 +21,7 @@ use App\GraphQL\Schema\Types\Pivot\Morph\ResourceableType;
use App\GraphQL\Schema\Types\Pivot\Wiki\AnimeStudioType;
use App\Models\Wiki\Studio;
class StudioType extends EloquentType implements ReportableType
class StudioType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -18,7 +18,7 @@ use App\GraphQL\Schema\Types\EloquentType;
use App\GraphQL\Schema\Types\Wiki\Anime\AnimeThemeType;
use App\Models\Wiki\Group;
class ThemeGroupType extends EloquentType implements ReportableType
class ThemeGroupType extends EloquentType implements SubmitableType
{
public function description(): string
{
+2 -2
View File
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Types\Wiki;
use App\Contracts\GraphQL\Types\ReportableType;
use App\Contracts\GraphQL\Types\SubmitableType;
use App\GraphQL\Schema\Fields\Base\CreatedAtField;
use App\GraphQL\Schema\Fields\Base\DeletedAtField;
use App\GraphQL\Schema\Fields\Base\IdField;
@@ -36,7 +36,7 @@ use App\GraphQL\Schema\Types\Wiki\Anime\Theme\AnimeThemeEntryType;
use App\GraphQL\Schema\Types\Wiki\Video\VideoScriptType;
use App\Models\Wiki\Video;
class VideoType extends EloquentType implements ReportableType
class VideoType extends EloquentType implements SubmitableType
{
public function description(): string
{
@@ -4,29 +4,29 @@ declare(strict_types=1);
namespace App\Http\Middleware\Models\Admin;
use App\Constants\Config\ReportConstants;
use App\Constants\Config\SubmissionConstants;
use App\Enums\Auth\SpecialPermission;
use App\Enums\Models\User\ApprovableStatus;
use App\Models\Auth\User;
use App\Models\User\Report;
use App\Models\User\Submission;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
class UserExceedsReportLimit
class UserExceedsSubmissionLimit
{
/**
* @param Closure(Request): mixed $next
*/
public function handle(Request $request, Closure $next): mixed
{
$reportLimit = intval(Config::get(ReportConstants::MAX_REPORTS_QUALIFIED));
$submissionLimit = intval(Config::get(SubmissionConstants::MAX_SUBMISSIONS_QUALIFIED));
/** @var User|null $user */
$user = $request->user('sanctum');
abort_if(intval($user?->reports->where(Report::ATTRIBUTE_STATUS, ApprovableStatus::PENDING->value)->count()) >= $reportLimit
&& blank($user?->can(SpecialPermission::BYPASS_FEATURE_FLAGS->value)), 403, "User cannot have more than '$reportLimit' outstanding reports.");
abort_if(intval($user?->submissions->where(Submission::ATTRIBUTE_STATUS, ApprovableStatus::PENDING->value)->count()) >= $submissionLimit
&& blank($user?->can(SpecialPermission::BYPASS_FEATURE_FLAGS->value)), 403, "User cannot have more than '$submissionLimit' outstanding submissions.");
return $next($request);
}
+10 -10
View File
@@ -19,7 +19,7 @@ use App\Models\List\ExternalProfile;
use App\Models\List\Playlist;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use Database\Factories\Auth\UserFactory;
use Filament\Facades\Filament;
@@ -50,12 +50,12 @@ use Spatie\Permission\Traits\HasRoles;
* @property Carbon|null $email_verified_at
* @property Collection<int, ExternalProfile> $externalprofiles
* @property int $id
* @property Collection<int, Report> $managedreports
* @property Collection<int, Submission> $managedsubmissions
* @property string $name
* @property string $password
* @property Collection<int, Playlist> $playlists
* @property string $remember_token
* @property Collection<int, Report> $reports
* @property Collection<int, Submission> $submissions
* @property Collection<int, PersonalAccessToken> $tokens
* @property Carbon|null $two_factor_confirmed_at
* @property string|null $two_factor_recovery_codes
@@ -86,11 +86,11 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasSubtit
final public const string ATTRIBUTE_TWO_FACTOR_SECRET = 'two_factor_secret';
final public const string RELATION_EXTERNAL_PROFILES = 'externalprofiles';
final public const string RELATION_MANAGED_REPORTS = 'managedreports';
final public const string RELATION_MANAGED_SUBMISSIONS = 'managedsubmissions';
final public const string RELATION_NOTIFICATIONS = 'notifications';
final public const string RELATION_PERMISSIONS = 'permissions';
final public const string RELATION_PLAYLISTS = 'playlists';
final public const string RELATION_REPORTS = 'reports';
final public const string RELATION_SUBMISSIONS = 'submissions';
final public const string RELATION_ROLES = 'roles';
final public const string RELATION_ROLES_PERMISSIONS = 'roles.permissions';
@@ -245,17 +245,17 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasSubtit
/**
* Get the submissions that the user made.
*/
public function reports(): HasMany
public function submissions(): HasMany
{
return $this->hasMany(Report::class, Report::ATTRIBUTE_USER);
return $this->hasMany(Submission::class, Submission::ATTRIBUTE_USER);
}
/**
* Get the reports that the admin managed.
* Get the submissions that the admin managed.
*/
public function managedreports(): HasMany
public function managedsubmissions(): HasMany
{
return $this->hasMany(Report::class, Report::ATTRIBUTE_MODERATOR);
return $this->hasMany(Submission::class, Submission::ATTRIBUTE_MODERATOR);
}
/**
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Document;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Events\Document\Page\PageCreated;
use App\Events\Document\Page\PageDeleted;
@@ -26,8 +26,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
class Page extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'pages';
@@ -7,8 +7,8 @@ namespace App\Models\User;
use App\Enums\Models\User\ApprovableStatus;
use App\Models\Auth\User;
use App\Models\BaseModel;
use App\Models\User\Report\ReportStep;
use Database\Factories\User\ReportFactory;
use App\Models\User\Submission\SubmissionStep;
use Database\Factories\User\SubmissionFactory;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -21,26 +21,26 @@ use Illuminate\Support\Collection;
* @property Carbon|null $finished_at
* @property User|null $moderator
* @property int|null $moderator_id
* @property string|null $mod_notes
* @property string|null $moderator_notes
* @property string|null $notes
* @property ApprovableStatus $status
* @property Collection<int, ReportStep> $steps
* @property Collection<int, SubmissionStep> $steps
* @property User|null $user
* @property int|null $user_id
*
* @method static Builder pending()
* @method static ReportFactory factory(...$parameters)
* @method static SubmissionFactory factory(...$parameters)
*/
class Report extends BaseModel
class Submission extends BaseModel
{
use HasFactory;
final public const string TABLE = 'reports';
final public const string TABLE = 'submissions';
final public const string ATTRIBUTE_ID = 'report_id';
final public const string ATTRIBUTE_ID = 'submission_id';
final public const string ATTRIBUTE_FINISHED_AT = 'finished_at';
final public const string ATTRIBUTE_MODERATOR = 'moderator_id';
final public const string ATTRIBUTE_MOD_NOTES = 'mod_notes';
final public const string ATTRIBUTE_MODERATOR_NOTES = 'moderator_notes';
final public const string ATTRIBUTE_NOTES = 'notes';
final public const string ATTRIBUTE_STATUS = 'status';
final public const string ATTRIBUTE_USER = 'user_id';
@@ -62,12 +62,12 @@ class Report extends BaseModel
* @var list<string>
*/
protected $fillable = [
Report::ATTRIBUTE_FINISHED_AT,
Report::ATTRIBUTE_MODERATOR,
Report::ATTRIBUTE_MOD_NOTES,
Report::ATTRIBUTE_NOTES,
Report::ATTRIBUTE_STATUS,
Report::ATTRIBUTE_USER,
Submission::ATTRIBUTE_FINISHED_AT,
Submission::ATTRIBUTE_MODERATOR,
Submission::ATTRIBUTE_MODERATOR_NOTES,
Submission::ATTRIBUTE_NOTES,
Submission::ATTRIBUTE_STATUS,
Submission::ATTRIBUTE_USER,
];
/**
@@ -75,14 +75,14 @@ class Report extends BaseModel
*
* @var string
*/
protected $table = Report::TABLE;
protected $table = Submission::TABLE;
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = Report::ATTRIBUTE_ID;
protected $primaryKey = Submission::ATTRIBUTE_ID;
public function getName(): string
{
@@ -106,45 +106,45 @@ class Report extends BaseModel
protected function casts(): array
{
return [
Report::ATTRIBUTE_FINISHED_AT => 'datetime',
Report::ATTRIBUTE_STATUS => ApprovableStatus::class,
Submission::ATTRIBUTE_FINISHED_AT => 'datetime',
Submission::ATTRIBUTE_STATUS => ApprovableStatus::class,
];
}
/**
* Scope a query to only include pending reports.
* Scope a query to only include pending submissions.
*/
#[Scope]
protected function pending(Builder $query): void
{
$query->where(Report::ATTRIBUTE_STATUS, ApprovableStatus::PENDING->value);
$query->where(Submission::ATTRIBUTE_STATUS, ApprovableStatus::PENDING->value);
}
/**
* @return HasMany<ReportStep, $this>
* @return HasMany<SubmissionStep, $this>
*/
public function steps(): HasMany
{
return $this->hasMany(ReportStep::class, ReportStep::ATTRIBUTE_REPORT);
return $this->hasMany(SubmissionStep::class, SubmissionStep::ATTRIBUTE_SUBMISSION);
}
/**
* Get the moderator that is working on the report.
* Get the moderator that is working on the submission.
*
* @return BelongsTo<User, $this>
*/
public function moderator(): BelongsTo
{
return $this->belongsTo(User::class, Report::ATTRIBUTE_MODERATOR);
return $this->belongsTo(User::class, Submission::ATTRIBUTE_MODERATOR);
}
/**
* Get the user that made the report.
* Get the user that made the submission.
*
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, Report::ATTRIBUTE_USER);
return $this->belongsTo(User::class, Submission::ATTRIBUTE_USER);
}
}
@@ -2,13 +2,13 @@
declare(strict_types=1);
namespace App\Models\User\Report;
namespace App\Models\User\Submission;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Enums\Models\User\SubmissionActionType;
use App\Models\BaseModel;
use App\Models\User\Report;
use Database\Factories\User\Report\ReportStepFactory;
use App\Models\User\Submission;
use Database\Factories\User\Submission\SubmissionStepFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -16,26 +16,26 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Carbon;
/**
* @property ReportActionType|null $action
* @property SubmissionActionType|null $action
* @property Model|null $actionable
* @property string $actionable_type
* @property int|null $actionable_id
* @property array|null $fields
* @property Carbon|null $finished_at
* @property class-string<Model>|null $pivot
* @property Report $report
* @property Submission $submission
* @property ApprovableStatus $status
* @property Model|null $target
* @property string|null $target_type
* @property int|null $target_id
*
* @method static ReportStepFactory factory(...$parameters)
* @method static SubmissionStepFactory factory(...$parameters)
*/
class ReportStep extends BaseModel
class SubmissionStep extends BaseModel
{
use HasFactory;
final public const string TABLE = 'report_step';
final public const string TABLE = 'submission_step';
final public const string ATTRIBUTE_ID = 'step_id';
@@ -48,14 +48,14 @@ class ReportStep extends BaseModel
final public const string ATTRIBUTE_PIVOT = 'pivot';
final public const string ATTRIBUTE_REPORT = 'report_id';
final public const string ATTRIBUTE_SUBMISSION = 'submission_id';
final public const string ATTRIBUTE_FIELDS = 'fields';
final public const string ATTRIBUTE_FINISHED_AT = 'finished_at';
final public const string ATTRIBUTE_STATUS = 'status';
final public const string RELATION_ACTIONABLE = 'actionable';
final public const string RELATION_TARGET = 'target';
final public const string RELATION_REPORT = 'report';
final public const string RELATION_SUBMISSION = 'submission';
/**
* Is auditing disabled?
@@ -70,15 +70,15 @@ class ReportStep extends BaseModel
* @var list<string>
*/
protected $fillable = [
ReportStep::ATTRIBUTE_ACTION,
ReportStep::ATTRIBUTE_ACTIONABLE_TYPE,
ReportStep::ATTRIBUTE_ACTIONABLE_ID,
ReportStep::ATTRIBUTE_FIELDS,
ReportStep::ATTRIBUTE_PIVOT,
ReportStep::ATTRIBUTE_REPORT,
ReportStep::ATTRIBUTE_STATUS,
ReportStep::ATTRIBUTE_TARGET_TYPE,
ReportStep::ATTRIBUTE_TARGET_ID,
SubmissionStep::ATTRIBUTE_ACTION,
SubmissionStep::ATTRIBUTE_ACTIONABLE_TYPE,
SubmissionStep::ATTRIBUTE_ACTIONABLE_ID,
SubmissionStep::ATTRIBUTE_FIELDS,
SubmissionStep::ATTRIBUTE_PIVOT,
SubmissionStep::ATTRIBUTE_SUBMISSION,
SubmissionStep::ATTRIBUTE_STATUS,
SubmissionStep::ATTRIBUTE_TARGET_TYPE,
SubmissionStep::ATTRIBUTE_TARGET_ID,
];
/**
@@ -86,14 +86,14 @@ class ReportStep extends BaseModel
*
* @var string
*/
protected $table = ReportStep::TABLE;
protected $table = SubmissionStep::TABLE;
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = ReportStep::ATTRIBUTE_ID;
protected $primaryKey = SubmissionStep::ATTRIBUTE_ID;
public function getName(): string
{
@@ -113,10 +113,10 @@ class ReportStep extends BaseModel
protected function casts(): array
{
return [
ReportStep::ATTRIBUTE_ACTION => ReportActionType::class,
ReportStep::ATTRIBUTE_FIELDS => 'array',
ReportStep::ATTRIBUTE_FINISHED_AT => 'datetime',
ReportStep::ATTRIBUTE_STATUS => ApprovableStatus::class,
SubmissionStep::ATTRIBUTE_ACTION => SubmissionActionType::class,
SubmissionStep::ATTRIBUTE_FIELDS => 'array',
SubmissionStep::ATTRIBUTE_FINISHED_AT => 'datetime',
SubmissionStep::ATTRIBUTE_STATUS => ApprovableStatus::class,
];
}
@@ -160,10 +160,10 @@ class ReportStep extends BaseModel
}
/**
* @return BelongsTo<Report, $this>
* @return BelongsTo<Submission, $this>
*/
public function report(): BelongsTo
public function submission(): BelongsTo
{
return $this->belongsTo(Report::class, ReportStep::ATTRIBUTE_REPORT);
return $this->belongsTo(Submission::class, SubmissionStep::ATTRIBUTE_SUBMISSION);
}
}
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasImages;
use App\Contracts\Models\HasResources;
use App\Contracts\Models\SoftDeletable;
@@ -59,9 +59,9 @@ use Illuminate\Support\Collection;
class Anime extends BaseModel implements HasImages, HasResources, SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'anime';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki\Anime;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Enums\Models\Wiki\AnimeSynonymType;
use App\Events\Wiki\Anime\Synonym\SynonymCreated;
@@ -31,9 +31,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AnimeSynonym extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'anime_synonyms';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki\Anime;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Http\Api\InteractsWithSchema;
use App\Contracts\Models\SoftDeletable;
use App\Enums\Models\Wiki\ThemeType;
@@ -50,9 +50,9 @@ use Illuminate\Support\Stringable;
class AnimeTheme extends BaseModel implements InteractsWithSchema, SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'anime_themes';
@@ -6,8 +6,8 @@ namespace App\Models\Wiki\Anime\Theme;
use App\Concerns\Models\Aggregate\AggregatesLike;
use App\Concerns\Models\InteractsWithLikes;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Http\Api\InteractsWithSchema;
use App\Contracts\Models\HasAggregateLikes;
use App\Contracts\Models\HasResources;
@@ -65,9 +65,9 @@ class AnimeThemeEntry extends BaseModel implements HasAggregateLikes, HasResourc
use AggregatesLike;
use HasFactory;
use InteractsWithLikes;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
use ZnckBelongsToThrough;
final public const string TABLE = 'anime_theme_entries';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasImages;
use App\Contracts\Models\HasResources;
use App\Contracts\Models\SoftDeletable;
@@ -55,9 +55,9 @@ class Artist extends BaseModel implements HasImages, HasResources, SoftDeletable
{
use HasFactory;
use HasRelationships;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'artists';
+2 -2
View File
@@ -5,8 +5,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Aggregate\AggregatesView;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasAggregateViews;
use App\Contracts\Models\SoftDeletable;
use App\Contracts\Models\Streamable;
@@ -37,8 +37,8 @@ class Audio extends BaseModel implements HasAggregateViews, SoftDeletable, Strea
{
use AggregatesView;
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'audios';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Enums\Models\Wiki\ResourceSite;
use App\Events\Wiki\ExternalResource\ExternalResourceCreated;
@@ -37,8 +37,8 @@ use Illuminate\Support\Uri;
class ExternalResource extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'resources';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Events\Wiki\Group\GroupCreated;
use App\Events\Wiki\Group\GroupDeleted;
@@ -30,8 +30,8 @@ use Illuminate\Support\Collection;
class Group extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'groups';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Enums\Models\Wiki\ImageFacet;
use App\Events\Wiki\Image\ImageCreated;
@@ -40,8 +40,8 @@ use Illuminate\Support\Facades\Storage;
class Image extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'images';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Events\Wiki\Series\SeriesCreated;
use App\Events\Wiki\Series\SeriesDeleted;
@@ -32,9 +32,9 @@ use Illuminate\Support\Collection;
class Series extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'series';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasResources;
use App\Contracts\Models\SoftDeletable;
use App\Events\Wiki\Song\SongCreated;
@@ -41,9 +41,9 @@ use Illuminate\Support\Collection;
class Song extends BaseModel implements HasResources, SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'songs';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki\Song;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Events\Wiki\Song\Membership\MembershipCreated;
use App\Events\Wiki\Song\Membership\MembershipDeleted;
@@ -35,8 +35,8 @@ use Illuminate\Support\Collection;
class Membership extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'memberships';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki\Song;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\SoftDeletable;
use App\Events\Wiki\Song\Performance\PerformanceCreated;
use App\Events\Wiki\Song\Performance\PerformanceDeleted;
@@ -36,8 +36,8 @@ use Illuminate\Database\Eloquent\Relations\Relation;
class Performance extends BaseModel implements SoftDeletable
{
use HasFactory;
use Reportable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'performances';
+2 -2
View File
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasImages;
use App\Contracts\Models\HasResources;
use App\Contracts\Models\SoftDeletable;
@@ -37,9 +37,9 @@ use Illuminate\Support\Collection;
class Studio extends BaseModel implements HasImages, HasResources, SoftDeletable
{
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'studios';
+2 -2
View File
@@ -5,8 +5,8 @@ declare(strict_types=1);
namespace App\Models\Wiki;
use App\Concerns\Models\Aggregate\AggregatesView;
use App\Concerns\Models\Reportable;
use App\Concerns\Models\SoftDeletes;
use App\Concerns\Models\Submitable;
use App\Contracts\Models\HasAggregateViews;
use App\Contracts\Models\SoftDeletable;
use App\Contracts\Models\Streamable;
@@ -63,9 +63,9 @@ class Video extends BaseModel implements HasAggregateViews, SoftDeletable, Strea
{
use AggregatesView;
use HasFactory;
use Reportable;
use Searchable;
use SoftDeletes;
use Submitable;
final public const string TABLE = 'videos';
@@ -2,18 +2,18 @@
declare(strict_types=1);
namespace App\Policies\User\Report;
namespace App\Policies\User\Submission;
use App\Enums\Auth\CrudPermission;
use App\Enums\Auth\Role;
use App\Models\Auth\User;
use App\Models\User\Report\ReportStep;
use App\Models\User\Submission\SubmissionStep;
use App\Policies\BasePolicy;
use Filament\Facades\Filament;
use Illuminate\Auth\Access\Response;
use Illuminate\Database\Eloquent\Model;
class ReportStepPolicy extends BasePolicy
class SubmissionStepPolicy extends BasePolicy
{
public function viewAny(?User $user, mixed $value = null): Response
{
@@ -27,7 +27,7 @@ class ReportStepPolicy extends BasePolicy
}
/**
* @param ReportStep $step
* @param SubmissionStep $step
*/
public function view(?User $user, Model $step): Response
{
@@ -37,13 +37,13 @@ class ReportStepPolicy extends BasePolicy
: Response::deny();
}
return $step->report->user()->is($user) && $user?->can(CrudPermission::VIEW->format(static::getModel()))
return $step->submission->user()->is($user) && $user?->can(CrudPermission::VIEW->format(static::getModel()))
? Response::allow()
: Response::deny();
}
/**
* @param ReportStep $step
* @param SubmissionStep $step
*/
public function update(User $user, Model $step): Response
{
@@ -51,13 +51,13 @@ class ReportStepPolicy extends BasePolicy
return Response::allow();
}
return $step->report->user()->is($user) && $user->can(CrudPermission::UPDATE->format(static::getModel()))
return $step->submission->user()->is($user) && $user->can(CrudPermission::UPDATE->format(static::getModel()))
? Response::allow()
: Response::deny();
}
/**
* @param ReportStep $step
* @param SubmissionStep $step
*/
public function delete(User $user, Model $step): Response
{
@@ -7,13 +7,13 @@ namespace App\Policies\User;
use App\Enums\Auth\CrudPermission;
use App\Enums\Auth\Role;
use App\Models\Auth\User;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Policies\BasePolicy;
use Filament\Facades\Filament;
use Illuminate\Auth\Access\Response;
use Illuminate\Database\Eloquent\Model;
class ReportPolicy extends BasePolicy
class SubmissionPolicy extends BasePolicy
{
public function viewAny(?User $user, mixed $value = null): Response
{
@@ -27,9 +27,9 @@ class ReportPolicy extends BasePolicy
}
/**
* @param Report $report
* @param Submission $submission
*/
public function view(?User $user, Model $report): Response
public function view(?User $user, Model $submission): Response
{
if (Filament::isServing()) {
return $user instanceof User && $user->hasRole(Role::ADMIN->value)
@@ -37,29 +37,29 @@ class ReportPolicy extends BasePolicy
: Response::deny();
}
return $report->user()->is($user) && $user?->can(CrudPermission::VIEW->format(static::getModel()))
return $submission->user()->is($user) && $user?->can(CrudPermission::VIEW->format(static::getModel()))
? Response::allow()
: Response::deny();
}
/**
* @param Report $report
* @param Submission $submission
*/
public function update(User $user, Model $report): Response
public function update(User $user, Model $submission): Response
{
if ($user->hasRole(Role::ADMIN->value)) {
return Response::allow();
}
return $report->user()->is($user) && $user->can(CrudPermission::UPDATE->format(static::getModel()))
return $submission->user()->is($user) && $user->can(CrudPermission::UPDATE->format(static::getModel()))
? Response::allow()
: Response::deny();
}
/**
* @param Report $report
* @param Submission $submission
*/
public function delete(User $user, Model $report): Response
public function delete(User $user, Model $submission): Response
{
return $user->hasRole(Role::ADMIN->value)
? Response::allow()
+3 -3
View File
@@ -9,9 +9,9 @@ return [
| Limits
|--------------------------------------------------------------------------
|
| These values represent caps on reports to prevent spam. By default,
| a user is permitted 50 reports.
| These values represent caps on submissions to prevent spam. By default,
| a user is permitted 50 submissions.
*/
'user_max_reports' => (int) env('USER_MAX_REPORTS', 50),
'user_max_submissions' => (int) env('USER_MAX_SUBMISSIONS', 50),
];
@@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\User\Report;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Models\User\Report\ReportStep;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Arr;
/**
* @method ReportStep createOne($attributes = [])
* @method ReportStep makeOne($attributes = [])
*
* @extends Factory<ReportStep>
*/
class ReportStepFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var class-string<ReportStep>
*/
protected $model = ReportStep::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$action = Arr::random(ReportActionType::cases());
$status = Arr::random(ApprovableStatus::cases());
return [
ReportStep::ATTRIBUTE_ACTION => $action->value,
ReportStep::ATTRIBUTE_STATUS => $status->value,
];
}
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Database\Factories\User\Submission;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\SubmissionActionType;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Arr;
/**
* @method SubmissionStep createOne($attributes = [])
* @method SubmissionStep makeOne($attributes = [])
*
* @extends Factory<SubmissionStep>
*/
class SubmissionStepFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var class-string<SubmissionStep>
*/
protected $model = SubmissionStep::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$action = Arr::random(SubmissionActionType::cases());
$status = Arr::random(ApprovableStatus::cases());
return [
SubmissionStep::ATTRIBUTE_ACTION => $action->value,
SubmissionStep::ATTRIBUTE_STATUS => $status->value,
SubmissionStep::ATTRIBUTE_SUBMISSION => Submission::factory(),
];
}
}
@@ -5,24 +5,24 @@ declare(strict_types=1);
namespace Database\Factories\User;
use App\Enums\Models\User\ApprovableStatus;
use App\Models\User\Report;
use App\Models\User\Submission;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Arr;
/**
* @method Report createOne($attributes = [])
* @method Report makeOne($attributes = [])
* @method Submission createOne($attributes = [])
* @method Submission makeOne($attributes = [])
*
* @extends Factory<Report>
* @extends Factory<Submission>
*/
class ReportFactory extends Factory
class SubmissionFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var class-string<Report>
* @var class-string<Submission>
*/
protected $model = Report::class;
protected $model = Submission::class;
/**
* Define the model's default state.
@@ -34,8 +34,8 @@ class ReportFactory extends Factory
$status = Arr::random(ApprovableStatus::cases());
return [
Report::ATTRIBUTE_MOD_NOTES => fake()->text(),
Report::ATTRIBUTE_STATUS => $status->value,
Submission::ATTRIBUTE_MODERATOR_NOTES => fake()->text(),
Submission::ATTRIBUTE_STATUS => $status->value,
];
}
}
@@ -1,70 +0,0 @@
<?php
declare(strict_types=1);
use App\Models\Auth\User;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
if (! Schema::hasTable(Report::TABLE)) {
Schema::create(Report::TABLE, function (Blueprint $table) {
$table->id(Report::ATTRIBUTE_ID);
$table->longText(Report::ATTRIBUTE_NOTES)->nullable();
$table->longText(Report::ATTRIBUTE_MOD_NOTES)->nullable();
$table->integer(Report::ATTRIBUTE_STATUS)->nullable();
$table->unsignedBigInteger(Report::ATTRIBUTE_USER)->nullable();
$table->foreign(Report::ATTRIBUTE_USER)->references(User::ATTRIBUTE_ID)->on(User::TABLE)->nullOnDelete();
$table->unsignedBigInteger(Report::ATTRIBUTE_MODERATOR)->nullable();
$table->foreign(Report::ATTRIBUTE_MODERATOR)->references(User::ATTRIBUTE_ID)->on(User::TABLE)->nullOnDelete();
$table->timestamp(Report::ATTRIBUTE_FINISHED_AT, 6)->nullable();
$table->timestamps(6);
$table->index(Report::ATTRIBUTE_STATUS);
});
}
if (! Schema::hasTable(ReportStep::TABLE)) {
Schema::create(ReportStep::TABLE, function (Blueprint $table) {
$table->id(ReportStep::ATTRIBUTE_ID);
$table->integer(ReportStep::ATTRIBUTE_ACTION)->nullable();
$table->nullableMorphs(ReportStep::RELATION_ACTIONABLE);
$table->nullableMorphs(ReportStep::RELATION_TARGET);
$table->string(ReportStep::ATTRIBUTE_PIVOT)->nullable();
$table->json(ReportStep::ATTRIBUTE_FIELDS)->nullable();
$table->integer(ReportStep::ATTRIBUTE_STATUS)->nullable();
$table->unsignedBigInteger(ReportStep::ATTRIBUTE_REPORT)->nullable();
$table->foreign(ReportStep::ATTRIBUTE_REPORT)->references(Report::ATTRIBUTE_ID)->on(Report::TABLE)->cascadeOnDelete();
$table->timestamp(ReportStep::ATTRIBUTE_FINISHED_AT, 6)->nullable();
$table->timestamps(6);
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists(ReportStep::TABLE);
Schema::dropIfExists(Report::TABLE);
}
};
@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
use App\Models\Auth\User;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
if (! Schema::hasTable(Submission::TABLE)) {
Schema::create(Submission::TABLE, function (Blueprint $table) {
$table->id(Submission::ATTRIBUTE_ID);
$table->longText(Submission::ATTRIBUTE_NOTES)->nullable();
$table->longText(Submission::ATTRIBUTE_MODERATOR_NOTES)->nullable();
$table->integer(Submission::ATTRIBUTE_STATUS)->nullable();
$table->unsignedBigInteger(Submission::ATTRIBUTE_USER)->nullable();
$table->foreign(Submission::ATTRIBUTE_USER)->references(User::ATTRIBUTE_ID)->on(User::TABLE)->nullOnDelete();
$table->unsignedBigInteger(Submission::ATTRIBUTE_MODERATOR)->nullable();
$table->foreign(Submission::ATTRIBUTE_MODERATOR)->references(User::ATTRIBUTE_ID)->on(User::TABLE)->nullOnDelete();
$table->timestamp(Submission::ATTRIBUTE_FINISHED_AT, 6)->nullable();
$table->timestamps(6);
$table->index(Submission::ATTRIBUTE_STATUS);
});
}
if (! Schema::hasTable(SubmissionStep::TABLE)) {
Schema::create(SubmissionStep::TABLE, function (Blueprint $table) {
$table->id(SubmissionStep::ATTRIBUTE_ID);
$table->integer(SubmissionStep::ATTRIBUTE_ACTION)->nullable();
$table->nullableMorphs(SubmissionStep::RELATION_ACTIONABLE);
$table->nullableMorphs(SubmissionStep::RELATION_TARGET);
$table->string(SubmissionStep::ATTRIBUTE_PIVOT)->nullable();
$table->json(SubmissionStep::ATTRIBUTE_FIELDS)->nullable();
$table->integer(SubmissionStep::ATTRIBUTE_STATUS)->nullable();
$table->unsignedBigInteger(SubmissionStep::ATTRIBUTE_SUBMISSION);
$table->foreign(SubmissionStep::ATTRIBUTE_SUBMISSION)->references(Submission::ATTRIBUTE_ID)->on(Submission::TABLE)->cascadeOnDelete();
$table->timestamp(SubmissionStep::ATTRIBUTE_FINISHED_AT, 6)->nullable();
$table->timestamps(6);
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists(SubmissionStep::TABLE);
Schema::dropIfExists(Submission::TABLE);
}
};
@@ -9,8 +9,8 @@ use App\Features\AllowAudioStreams;
use App\Features\AllowDumpDownloading;
use App\Features\AllowExternalProfileManagement;
use App\Features\AllowPlaylistManagement;
use App\Features\AllowReport;
use App\Features\AllowScriptDownloading;
use App\Features\AllowSubmission;
use App\Features\AllowVideoStreams;
use Illuminate\Database\Seeder;
use Laravel\Pennant\Feature;
@@ -26,7 +26,7 @@ class FeatureSeeder extends Seeder
Feature::deactivate(AllowDumpDownloading::class);
Feature::deactivate(AllowExternalProfileManagement::class);
Feature::deactivate(AllowPlaylistManagement::class);
Feature::deactivate(AllowReport::class);
Feature::deactivate(AllowSubmission::class);
Feature::deactivate(AllowScriptDownloading::class);
Feature::deactivate(AllowVideoStreams::class);
@@ -22,7 +22,7 @@ use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use App\Models\Wiki\Anime\AnimeTheme;
@@ -76,7 +76,7 @@ class PermissionSeeder extends Seeder
// User Resources
$this->registerResource(Like::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::DELETE]);
$this->registerResource(Notification::class, [CrudPermission::VIEW, CrudPermission::UPDATE]);
$this->registerResource(Report::class, CrudPermission::cases());
$this->registerResource(Submission::class, CrudPermission::cases());
// Wiki Resources
$this->registerResource(Anime::class, $extendedCrudPermissions);
+2 -2
View File
@@ -23,7 +23,7 @@ use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use App\Models\Wiki\Anime\AnimeTheme;
@@ -84,7 +84,7 @@ class AdminSeeder extends RoleSeeder
// User Resources
$this->configureResource($role, Like::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::DELETE]);
$this->configureResource($role, Notification::class, [CrudPermission::VIEW, CrudPermission::UPDATE]);
$this->configureResource($role, Report::class, CrudPermission::cases());
$this->configureResource($role, Submission::class, CrudPermission::cases());
// Wiki Resources
$this->configureResource($role, Anime::class, $extendedCrudPermissions);
@@ -16,7 +16,7 @@ use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use App\Models\Wiki\Anime\AnimeTheme;
@@ -60,7 +60,7 @@ class ContributorRoleSeeder extends RoleSeeder
// User Resources
$this->configureResource($role, Like::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::DELETE]);
$this->configureResource($role, Notification::class, [CrudPermission::VIEW, CrudPermission::UPDATE]);
$this->configureResource($role, Report::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::UPDATE]);
$this->configureResource($role, Submission::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::UPDATE]);
// Wiki Resources
$this->configureResource($role, Anime::class, [CrudPermission::VIEW]);
@@ -16,7 +16,7 @@ use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\User\Like;
use App\Models\User\Notification;
use App\Models\User\Report;
use App\Models\User\Submission;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use App\Models\Wiki\Anime\AnimeTheme;
@@ -60,7 +60,7 @@ class PanelViewerRoleSeeder extends RoleSeeder
// User Resources
$this->configureResource($role, Like::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::DELETE]);
$this->configureResource($role, Notification::class, [CrudPermission::VIEW, CrudPermission::UPDATE]);
$this->configureResource($role, Report::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::UPDATE]);
$this->configureResource($role, Submission::class, [CrudPermission::VIEW, CrudPermission::CREATE, CrudPermission::UPDATE]);
// Wiki Resources
$this->configureResource($role, Anime::class, [CrudPermission::VIEW]);
+7 -7
View File
@@ -8,7 +8,7 @@ use App\Enums\Models\List\ExternalProfileSite;
use App\Enums\Models\List\ExternalProfileVisibility;
use App\Enums\Models\List\PlaylistVisibility;
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Enums\Models\User\SubmissionActionType;
use App\Enums\Models\Wiki\AnimeMediaFormat;
use App\Enums\Models\Wiki\AnimeSeason;
use App\Enums\Models\Wiki\AnimeSynonymType;
@@ -81,12 +81,12 @@ return [
PlaylistVisibility::PRIVATE->name => 'Private',
PlaylistVisibility::UNLISTED->name => 'Unlisted',
],
ReportActionType::class => [
ReportActionType::CREATE->name => 'Create',
ReportActionType::UPDATE->name => 'Update',
ReportActionType::DELETE->name => 'Delete',
ReportActionType::ATTACH->name => 'Attach',
ReportActionType::DETACH->name => 'Detach',
SubmissionActionType::class => [
SubmissionActionType::CREATE->name => 'Create',
SubmissionActionType::UPDATE->name => 'Update',
SubmissionActionType::DELETE->name => 'Delete',
SubmissionActionType::ATTACH->name => 'Attach',
SubmissionActionType::DETACH->name => 'Detach',
],
ResourceSite::class => [
ResourceSite::OFFICIAL_SITE->name => 'Official Website',
+7 -7
View File
@@ -834,15 +834,15 @@ return [
'name' => 'Visibility',
],
],
'report' => [
'submission' => [
'finished_at' => 'Finished At',
'moderator' => 'Moderator',
'mod_notes' => 'Moderator Notes',
'moderator_notes' => 'Moderator Notes',
'notes' => 'Notes',
'status' => 'Status',
'target' => 'Target',
],
'report_step' => [
'submission_step' => [
'action' => 'Action',
'actionable' => 'Actionable',
'fields' => [
@@ -1000,8 +1000,8 @@ return [
'permissions' => 'Permissions',
'playlist_tracks' => 'Playlist Tracks',
'playlists' => 'Playlists',
'reports' => 'Reports',
'report_steps' => 'Report Steps',
'submissions' => 'Submissions',
'submission_steps' => 'Submission Steps',
'roles' => 'Roles',
'series' => 'Series',
'songs' => 'Songs',
@@ -1036,8 +1036,8 @@ return [
'permission' => 'Permission',
'playlist_track' => 'Playlist Track',
'playlist' => 'Playlist',
'report' => 'Report',
'report_step' => 'Report Step',
'submission' => 'Submission',
'submission_step' => 'Submission Step',
'role' => 'Role',
'series' => 'Series',
'song' => 'Song',
@@ -1,72 +0,0 @@
<?php
declare(strict_types=1);
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\ReportActionType;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use App\Models\Wiki\Anime;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
uses(Illuminate\Foundation\Testing\WithFaker::class);
test('nameable', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne();
$this->assertIsString($step->getName());
});
test('has subtitle', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne();
$this->assertIsString($step->getSubtitle());
});
test('casts action to enum', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne();
$this->assertInstanceOf(ReportActionType::class, $step->action);
});
test('casts fields to array', function () {
$anime = Anime::factory()->makeOne();
$step = ReportStep::factory()
->for(Report::factory())
->createOne([ReportStep::ATTRIBUTE_FIELDS => $anime->attributesToArray()]);
$this->assertIsArray($step->fields);
});
test('casts finished at', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne([ReportStep::ATTRIBUTE_FINISHED_AT => now()]);
$this->assertInstanceOf(Carbon::class, $step->finished_at);
});
test('casts status to enum', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne();
$this->assertInstanceOf(ApprovableStatus::class, $step->status);
});
test('report', function () {
$step = ReportStep::factory()
->for(Report::factory())
->createOne();
$this->assertInstanceOf(BelongsTo::class, $step->report());
$this->assertInstanceOf(Report::class, $step->report()->first());
});
-70
View File
@@ -1,70 +0,0 @@
<?php
declare(strict_types=1);
use App\Enums\Models\User\ApprovableStatus;
use App\Models\Auth\User;
use App\Models\User\Report;
use App\Models\User\Report\ReportStep;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
uses(Illuminate\Foundation\Testing\WithFaker::class);
test('nameable', function () {
$report = Report::factory()->createOne();
$this->assertIsString($report->getName());
});
test('has subtitle', function () {
$report = Report::factory()->createOne();
$this->assertIsString($report->getSubtitle());
});
test('casts finished at', function () {
$report = Report::factory()->createOne([Report::ATTRIBUTE_FINISHED_AT => now()]);
$this->assertInstanceOf(Carbon::class, $report->finished_at);
});
test('casts status to enum', function () {
$report = Report::factory()->createOne();
$this->assertInstanceOf(ApprovableStatus::class, $report->status);
});
test('steps', function () {
$stepsCount = fake()->randomDigitNotNull();
$report = Report::factory()->createOne();
ReportStep::factory()
->for($report)
->count($stepsCount)
->create();
$this->assertInstanceOf(HasMany::class, $report->steps());
$this->assertEquals($stepsCount, $report->steps()->count());
$this->assertInstanceOf(ReportStep::class, $report->steps()->first());
});
test('user', function () {
$report = Report::factory()
->for(User::factory(), Report::RELATION_USER)
->createOne();
$this->assertInstanceOf(BelongsTo::class, $report->user());
$this->assertInstanceOf(User::class, $report->user()->first());
});
test('moderator', function () {
$report = Report::factory()
->for(User::factory(), Report::RELATION_MODERATOR)
->createOne();
$this->assertInstanceOf(BelongsTo::class, $report->moderator());
$this->assertInstanceOf(User::class, $report->moderator()->first());
});
@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
use App\Enums\Models\User\ApprovableStatus;
use App\Enums\Models\User\SubmissionActionType;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use App\Models\Wiki\Anime;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
uses(Illuminate\Foundation\Testing\WithFaker::class);
test('nameable', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne();
$this->assertIsString($step->getName());
});
test('has subtitle', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne();
$this->assertIsString($step->getSubtitle());
});
test('casts action to enum', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne();
$this->assertInstanceOf(SubmissionActionType::class, $step->action);
});
test('casts fields to array', function () {
$anime = Anime::factory()->makeOne();
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne([SubmissionStep::ATTRIBUTE_FIELDS => $anime->attributesToArray()]);
$this->assertIsArray($step->fields);
});
test('casts finished at', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne([SubmissionStep::ATTRIBUTE_FINISHED_AT => now()]);
$this->assertInstanceOf(Carbon::class, $step->finished_at);
});
test('casts status to enum', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne();
$this->assertInstanceOf(ApprovableStatus::class, $step->status);
});
test('submission', function () {
$step = SubmissionStep::factory()
->for(Submission::factory())
->createOne();
$this->assertInstanceOf(BelongsTo::class, $step->submission());
$this->assertInstanceOf(Submission::class, $step->submission()->first());
});
+70
View File
@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
use App\Enums\Models\User\ApprovableStatus;
use App\Models\Auth\User;
use App\Models\User\Submission;
use App\Models\User\Submission\SubmissionStep;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
uses(Illuminate\Foundation\Testing\WithFaker::class);
test('nameable', function () {
$submission = Submission::factory()->createOne();
$this->assertIsString($submission->getName());
});
test('has subtitle', function () {
$submission = Submission::factory()->createOne();
$this->assertIsString($submission->getSubtitle());
});
test('casts finished at', function () {
$submission = Submission::factory()->createOne([Submission::ATTRIBUTE_FINISHED_AT => now()]);
$this->assertInstanceOf(Carbon::class, $submission->finished_at);
});
test('casts status to enum', function () {
$submission = Submission::factory()->createOne();
$this->assertInstanceOf(ApprovableStatus::class, $submission->status);
});
test('steps', function () {
$stepsCount = fake()->randomDigitNotNull();
$submission = Submission::factory()->createOne();
SubmissionStep::factory()
->for($submission)
->count($stepsCount)
->create();
$this->assertInstanceOf(HasMany::class, $submission->steps());
$this->assertEquals($stepsCount, $submission->steps()->count());
$this->assertInstanceOf(SubmissionStep::class, $submission->steps()->first());
});
test('user', function () {
$submission = Submission::factory()
->for(User::factory(), Submission::RELATION_USER)
->createOne();
$this->assertInstanceOf(BelongsTo::class, $submission->user());
$this->assertInstanceOf(User::class, $submission->user()->first());
});
test('moderator', function () {
$submission = Submission::factory()
->for(User::factory(), Submission::RELATION_MODERATOR)
->createOne();
$this->assertInstanceOf(BelongsTo::class, $submission->moderator());
$this->assertInstanceOf(User::class, $submission->moderator()->first());
});