diff --git a/app/Http/Requests/V1/Goal/GoalFilterRules.php b/app/Http/Requests/V1/Goal/GoalFilterRules.php index 44fc6dd0..1856b812 100644 --- a/app/Http/Requests/V1/Goal/GoalFilterRules.php +++ b/app/Http/Requests/V1/Goal/GoalFilterRules.php @@ -19,6 +19,7 @@ use Illuminate\Contracts\Validation\Rule as LegacyValidationRule; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Database\Eloquent\Builder; use Illuminate\Validation\Rule; +use Illuminate\Validation\Rules\ProhibitedIf; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; /** @@ -29,10 +30,10 @@ use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; trait GoalFilterRules { /** - * @param bool $forEveryMember Whether the goal counts every member instead of one member - * @return array> + * @param \Closure(): bool $forEveryMember Whether the goal counts every member instead of one member, evaluated during validation + * @return array> */ - protected function filterRules(bool $forEveryMember): array + protected function filterRules(\Closure $forEveryMember): array { return [ 'filters' => [ @@ -44,7 +45,7 @@ trait GoalFilterRules 'nullable', 'array', // "prohibited" still lets null and an empty array through, both mean "no restriction" - ...($forEveryMember ? [] : ['prohibited']), + Rule::prohibitedIf(fn (): bool => ! $forEveryMember()), ], 'filters.member_ids.*' => [ 'string', diff --git a/app/Http/Requests/V1/Goal/GoalStoreRequest.php b/app/Http/Requests/V1/Goal/GoalStoreRequest.php index a6e9ba71..d67ac1e7 100644 --- a/app/Http/Requests/V1/Goal/GoalStoreRequest.php +++ b/app/Http/Requests/V1/Goal/GoalStoreRequest.php @@ -17,6 +17,7 @@ use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Database\Eloquent\Builder; use Illuminate\Validation\Rule; use Illuminate\Validation\Rules\In; +use Illuminate\Validation\Rules\ProhibitedIf; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; /** @@ -29,7 +30,7 @@ class GoalStoreRequest extends BaseFormRequest /** * Get the validation rules that apply to the request. * - * @return array> + * @return array> */ public function rules(): array { @@ -97,7 +98,7 @@ class GoalStoreRequest extends BaseFormRequest ], ], $this->filterRules( // Without a member_id the goal is for the current member - $this->has('member_id') && $this->input('member_id') === null, + fn (): bool => $this->has('member_id') && $this->input('member_id') === null, )); } diff --git a/app/Http/Requests/V1/Goal/GoalUpdateRequest.php b/app/Http/Requests/V1/Goal/GoalUpdateRequest.php index 66de1775..72f12a64 100644 --- a/app/Http/Requests/V1/Goal/GoalUpdateRequest.php +++ b/app/Http/Requests/V1/Goal/GoalUpdateRequest.php @@ -13,6 +13,7 @@ use App\Models\Organization; use Illuminate\Contracts\Validation\Rule as LegacyValidationRule; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Validation\Rule; +use Illuminate\Validation\Rules\ProhibitedIf; /** * @property Organization $organization Organization from model binding @@ -25,7 +26,7 @@ class GoalUpdateRequest extends BaseFormRequest * Get the validation rules that apply to the request. * The type of a goal and the member it is for can not be changed after creation. * - * @return array> + * @return array> */ public function rules(): array { @@ -89,7 +90,7 @@ class GoalUpdateRequest extends BaseFormRequest } }, ], - ], $this->filterRules($goal->member_id === null)); + ], $this->filterRules(fn (): bool => $goal->member_id === null)); } public function getName(): string diff --git a/app/Http/Resources/V1/Goal/GoalResource.php b/app/Http/Resources/V1/Goal/GoalResource.php index 0ff16a9d..5ced4e92 100644 --- a/app/Http/Resources/V1/Goal/GoalResource.php +++ b/app/Http/Resources/V1/Goal/GoalResource.php @@ -31,27 +31,27 @@ class GoalResource extends BaseResource public function toArray(Request $request): array { return [ - /** @var string $id ID of the goal */ + /** ID of the goal */ 'id' => $this->resource->id, - /** @var string $name Name */ + /** Name */ 'name' => $this->resource->name, - /** @var string $type personal: a goal a member set for themselves, organization: a goal of the organization (team goals extension) */ + /** personal: a goal a member set for themselves, organization: a goal of the organization (team goals extension) */ 'type' => $this->resource->type->value, - /** @var string $comparison Whether the goal is reached with "at least" or "less than" the target time (at_least, less_than) */ + /** Whether the goal is reached with "at least" or "less than" the target time (at_least, less_than) */ 'comparison' => $this->resource->comparison->value, - /** @var int $target_seconds Target time in seconds */ + /** Target time in seconds */ 'target_seconds' => $this->resource->target_seconds, - /** @var string $period Recurring time frame (day, week, month) */ + /** Recurring time frame (day, week, month) */ 'period' => $this->resource->period->value, - /** @var string|null $member_id ID of the member whose time entries count towards the goal, null if every member counts */ + /** ID of the member whose time entries count towards the goal, null if every member counts */ 'member_id' => $this->resource->member_id, - /** @var string|null $member_name Name of the member whose time entries count towards the goal, null if every member counts */ + /** Name of the member whose time entries count towards the goal, null if every member counts */ 'member_name' => $this->resource->member?->user->name, - /** @var string $timezone Timezone that defines the periods of the goal */ + /** Timezone that defines the periods of the goal */ 'timezone' => $this->resource->timezone, - /** @var string $week_start Week start that defines weekly periods */ + /** Week start that defines weekly periods */ 'week_start' => $this->resource->week_start->value, - /** @var bool $is_archived Whether the goal is archived */ + /** Whether the goal is archived */ 'is_archived' => $this->resource->is_archived, 'filters' => [ /** @var array|null $member_ids Filter by member IDs, member IDs are OR combined, only for goals that count every member */ @@ -62,28 +62,28 @@ class GoalResource extends BaseResource 'task_ids' => $this->resource->filters->taskIds?->toArray(), /** @var array|null $tag_ids Filter by tag IDs, tag IDs are OR combined */ 'tag_ids' => $this->resource->filters->tagIds?->toArray(), - /** @var string|null $tag_match_type Tag match type (contains, not_contains) */ + /** Tag match type (contains, not_contains) */ 'tag_match_type' => $this->resource->filters->tagMatchType?->value, /** @var array|null $client_ids Filter by client IDs, client IDs are OR combined */ 'client_ids' => $this->resource->filters->clientIds?->toArray(), - /** @var bool|null $billable Filter by billable status */ + /** Filter by billable status */ 'billable' => $this->resource->filters->billable, - /** @var string|null $time_entry_type Filter by time entry type (work, break) */ + /** Filter by time entry type (work, break) */ 'time_entry_type' => $this->resource->filters->timeEntryType?->value, ], 'progress' => [ - /** @var string $period_start Start of the current period (inclusive) */ + /** Start of the current period (inclusive) */ 'period_start' => $this->formatDateTime($this->progress->periodStart), - /** @var string $period_end End of the current period (exclusive) */ + /** End of the current period (exclusive) */ 'period_end' => $this->formatDateTime($this->progress->periodEnd), - /** @var int $tracked_seconds Seconds tracked in the current period that match the filters, incl. the running time entry */ + /** Seconds tracked in the current period that match the filters, incl. the running time entry */ 'tracked_seconds' => $this->progress->trackedSeconds, - /** @var string $status Status in the current period (in_progress, achieved, on_track, exceeded) */ + /** Status in the current period (in_progress, achieved, on_track, exceeded) */ 'status' => $this->progress->status->value, ], - /** @var string $created_at Date when the goal was created */ + /** Date when the goal was created */ 'created_at' => $this->formatDateTime($this->resource->created_at), - /** @var string $updated_at Date when the goal was last updated */ + /** Date when the goal was last updated */ 'updated_at' => $this->formatDateTime($this->resource->updated_at), ]; }