Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions api/v1/editTaskTemplates/PKPEditTaskTemplateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Arr;
use PKP\API\v1\editTaskTemplates\formRequests\AddTaskTemplate;
use PKP\API\v1\editTaskTemplates\resources\TaskTemplateResource;
use PKP\core\PKPBaseController;
Expand All @@ -29,6 +30,8 @@
use PKP\security\authorization\CanAccessSettingsPolicy;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
use PKP\editorialTask\enums\EditorialTaskType;
use PKP\API\v1\editTaskTemplates\formRequests\UpdateTaskTemplate;

class PKPEditTaskTemplateController extends PKPBaseController
{
Expand Down Expand Up @@ -59,6 +62,8 @@ public function getGroupRoutes(): void
])->group(function () {
Route::post('', $this->add(...));
Route::get('', $this->getMany(...));
Route::put('{templateId}', $this->update(...))->whereNumber('templateId');
Route::delete('{templateId}', $this->delete(...))->whereNumber('templateId');
});
}

Expand Down Expand Up @@ -120,6 +125,9 @@ public function getMany(Request $request): JsonResponse
->with('userGroups');

$queryParams = $this->_processAllowedParams($request->query(), [
'search',
'title',
'type',
'stageId',
'include',
'count',
Expand All @@ -128,6 +136,18 @@ public function getMany(Request $request): JsonResponse

foreach ($queryParams as $param => $val) {
switch ($param) {
case 'search':
$collector->filterBySearch((string) $val);
break;
case 'title':
$collector->filterByTitleLike((string) $val);
break;
case 'type':
$type = (int) $val;
if (in_array($type, array_column(EditorialTaskType::cases(), 'value'), true)) {
$collector->filterByType($type);
}
break;
case 'stageId':
$collector->filterByStageId((int) $val);
break;
Expand Down Expand Up @@ -156,4 +176,71 @@ public function getMany(Request $request): JsonResponse
->setStatusCode(Response::HTTP_OK);
}

/**
* UPDATE /api/v1/editTaskTemplates/{templateId}
*/
public function update(UpdateTaskTemplate $request): JsonResponse
{
$contextId = (int) $this->getRequest()->getContext()->getId();
$id = (int) $request->route('templateId');

$template = Template::query()
->byContextId($contextId)
->find($id);

if (!$template) {
return response()->json([
'error' => __('api.404.resourceNotFound'),
], Response::HTTP_NOT_FOUND);
}

$data = $request->validated();

DB::transaction(function () use ($template, $data) {
$userGroupIds = \Illuminate\Support\Arr::pull($data, 'userGroupIds');

$template->update($data);

if ($userGroupIds !== null) {
$template->userGroups()->sync($userGroupIds);
}
});

return response()->json(
(new TaskTemplateResource($template->refresh()->load('userGroups')))->toArray($request),
Response::HTTP_OK
);
}

/**
* DELETE /api/v1/editTaskTemplates/{templateId}
*/
public function delete(Request $illuminateRequest): JsonResponse
{
$contextId = (int) $this->getRequest()->getContext()->getId();
$id = (int) $illuminateRequest->route('templateId');

$template = Template::query()
->byContextId($contextId)
->find($id);

if (!$template) {
return response()->json([
'error' => __('api.404.resourceNotFound'),
], Response::HTTP_NOT_FOUND);
}

$resource = new TaskTemplateResource($template->load('userGroups'));

DB::transaction(function () use ($template) {
// Pivot/settings rows cascade via FKs defined in migration
$template->delete();
});

return response()->json(
$resource->toArray($illuminateRequest),
Response::HTTP_OK
);
}

}
22 changes: 8 additions & 14 deletions api/v1/editTaskTemplates/formRequests/AddTaskTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,20 @@

namespace PKP\API\v1\editTaskTemplates\formRequests;

use APP\core\Application;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use PKP\editorialTask\enums\EditorialTaskDueInterval;
use PKP\editorialTask\enums\EditorialTaskType;

class AddTaskTemplate extends FormRequest
{
public function authorize(): bool
{
return true;
}
use TaskTemplateRequestTrait;

public function rules(): array
{
$contextId = Application::get()->getRequest()->getContext()->getId();
$stageIds = array_keys(Application::getApplicationStages());
$contextId = $this->getContextId();
$stageIds = $this->getStageIds();

return [
'type' => ['required', Rule::in(array_column(EditorialTaskType::cases(), 'value'))],
'stageId' => ['required', 'integer', Rule::in($stageIds)],
Expand All @@ -40,22 +37,19 @@ public function rules(): array
'dueInterval' => ['sometimes', 'nullable', 'string', Rule::in(array_column(EditorialTaskDueInterval::cases(), 'value'))],
'description' => ['sometimes', 'nullable', 'string'],
'userGroupIds' => ['required', 'array', 'min:1'],
'userGroupIds.*' => [
'integer',
'distinct',
Rule::exists('user_groups', 'user_group_id')
->where(fn ($q) => $q->where('context_id', $contextId)),
],
'userGroupIds.*' => $this->userGroupIdsItemRules($contextId),
];
}

protected function prepareForValidation(): void
{
$stageId = $this->input('stageId', null);
$type = $this->input('type', null);
$this->merge([
'include' => filter_var($this->input('include', false), FILTER_VALIDATE_BOOLEAN),
'userGroupIds' => array_values(array_map('intval', (array) $this->input('userGroupIds', []))),
'stageId' => is_null($stageId) ? $stageId : (int) $stageId,
'stageId' => is_null($stageId) ? null : (int) $stageId,
'type' => is_null($type) ? null : (int) $type,
]);
}
}
42 changes: 42 additions & 0 deletions api/v1/editTaskTemplates/formRequests/TaskTemplateRequestTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/**
* @file api/v1/editTaskTemplates/formRequests/TaskTemplateRequestTrait.php
*
* Copyright (c) 2025 Simon Fraser University
* Copyright (c) 2025 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class TaskTemplateRequestTrait
*
* @brief Common helpers for resolving context, stage IDs and user group rules in task template form requests.
*
*/

namespace PKP\API\v1\editTaskTemplates\formRequests;

use APP\core\Application;
use Illuminate\Validation\Rule;

trait TaskTemplateRequestTrait
{
protected function getContextId(): int
{
return Application::get()->getRequest()->getContext()->getId();
}

protected function getStageIds(): array
{
return Application::getApplicationStages();
}

protected function userGroupIdsItemRules(int $contextId): array
{
return [
'integer',
'distinct',
Rule::exists('user_groups', 'user_group_id')
->where(fn ($q) => $q->where('context_id', $contextId)),
];
}
}
63 changes: 63 additions & 0 deletions api/v1/editTaskTemplates/formRequests/UpdateTaskTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace PKP\API\v1\editTaskTemplates\formRequests;

use APP\core\Application;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use PKP\editorialTask\enums\EditorialTaskDueInterval;
use PKP\editorialTask\enums\EditorialTaskType;

class UpdateTaskTemplate extends FormRequest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this class and AddTaskTemplate could have a common parent to avoid code duplication. Or AddTaskTemplate could extend this class. Or have a common trait...

{
use TaskTemplateRequestTrait;

public function rules(): array
{
$contextId = $this->getContextId();
$stageIds = $this->getStageIds();

return [
'stageId' => ['sometimes', 'integer', Rule::in($stageIds)],
'title' => ['sometimes', 'string', 'max:255'],
'include' => ['sometimes', 'boolean'],
'description' => ['sometimes', 'nullable', 'string'],
'dueInterval' => ['sometimes', 'nullable', 'string', Rule::in(array_column(EditorialTaskDueInterval::cases(), 'value'))],
'type' => ['sometimes', Rule::in(array_column(EditorialTaskType::cases(), 'value'))],

'userGroupIds' => ['sometimes', 'array', 'min:1'],
'userGroupIds.*' => $this->userGroupIdsItemRules($contextId),
];
}

protected function prepareForValidation(): void
{
$stageId = $this->input('stageId');
$type = $this->input('type');

$data = [];

if ($this->has('include')) {
$data['include'] = filter_var($this->input('include'), FILTER_VALIDATE_BOOLEAN);
}

if ($this->has('userGroupIds')) {
$data['userGroupIds'] = array_values(
array_map('intval', (array) $this->input('userGroupIds', []))
);
}

if ($this->has('stageId')) {
$data['stageId'] = is_null($stageId) ? null : (int) $stageId;
}

if ($this->has('type')) {
$data['type'] = is_null($type) ? null : (int) $type;
}

if ($data) {
$this->merge($data);
}
}

}
Loading