Skip to content

Commit

Permalink
pkp#6528 implement endpoint to perform bulk delete of incomplete subm…
Browse files Browse the repository at this point in the history
…issions
  • Loading branch information
taslangraham committed Aug 5, 2024
1 parent 9a78401 commit 04b0410
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 2 deletions.
73 changes: 73 additions & 0 deletions api/v1/_submissions/PKPBackendSubmissionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use APP\core\Application;
use APP\facades\Repo;
use APP\submission\Collector;
use APP\submission\Submission;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
Expand Down Expand Up @@ -87,6 +88,14 @@ public function getGroupRoutes(): void
),
]);

Route::delete('', $this->bulkDeleteIncompleteSubmissions(...))
->name('_submission.incomplete.delete')
->middleware([
self::roleAuthorizer([
Role::ROLE_ID_SITE_ADMIN,
]),
]);

Route::delete('{submissionId}', $this->delete(...))
->name('_submission.delete')
->middleware([
Expand Down Expand Up @@ -430,6 +439,70 @@ public function delete(Request $illuminateRequest): JsonResponse
return response()->json([], Response::HTTP_OK);
}

/**
* Delete a list of incomplete submissions
*/
public function bulkDeleteIncompleteSubmissions(Request $illuminateRequest): JsonResponse
{
$submissionIdsRaw = paramToArray($illuminateRequest->query('ids') ?? []);

if (empty($submissionIdsRaw)) {
return response()->json([
'error' => __('api.submission.400.missingQueryParam'),
], Response::HTTP_BAD_REQUEST);
}

$submissionIds = [];

foreach ($submissionIdsRaw as $id) {
$integerId = intval($id);

if (!$integerId) {
return response()->json([
'error' => __('api.submission.400.invalidId', ['id' => $id])
], Response::HTTP_BAD_REQUEST);
}

$submissionIds[] = $id;
}

$submissions = $this->getSubmissionCollector($illuminateRequest->query())
->filterBySubmissionIds($submissionIds)
->filterByIncomplete(true)
->getMany()
->all();

$submissionIdsFound = array_map(fn (Submission $submission) => $submission->getData('id'), $submissions);

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

$context = $this->getRequest()->getContext();

foreach ($submissions as $submission) {
if ($context->getId() != $submission->getData('contextId')) {
return response()->json([
'error' => __('api.submissions.403.deleteSubmissionOutOfContext'),
], Response::HTTP_FORBIDDEN);
}

if (!Repo::submission()->canCurrentUserDelete($submission)) {
return response()->json([
'error' => __('api.submissions.403.unauthorizedDeleteSubmission'),
], Response::HTTP_FORBIDDEN);
}
}

foreach ($submissions as $submission) {
Repo::submission()->delete($submission);
}

return response()->json([], Response::HTTP_OK);
}

/**
* Configure a submission Collector based on the query params
*/
Expand Down
16 changes: 16 additions & 0 deletions classes/submission/Collector.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ abstract class Collector implements CollectorInterface, ViewsCount
public DAO $dao;
public ?array $categoryIds = null;
public ?array $contextIds = null;
public ?array $submissionIds = null;
public ?int $count = null;
public ?int $daysInactive = null;
public bool $isIncomplete = false;
Expand Down Expand Up @@ -250,6 +251,17 @@ public function filterByRevisionsSubmitted(?bool $revisionsSubmitted): AppCollec
return $this;
}

/**
* Limit results to only submissions with the specified IDs
*
* @param ?int[] $submissionIds Submission IDs
*/
public function filterBySubmissionIds(?array $submissionIds): static
{
$this->submissionIds = $submissionIds;
return $this;
}

/**
* Limit results to submissions assigned to these users
*
Expand Down Expand Up @@ -370,6 +382,10 @@ public function getQueryBuilder(): Builder
$q->whereIn('s.context_id', $this->contextIds);
}

if (isset($this->submissionIds)) {
$q->whereIn('s.submission_id', array_map(intval(...), $this->submissionIds));
}

// Prepare keywords (allows short and numeric words)
$keywords = collect(Application::getSubmissionSearchIndex()->filterKeywords($this->searchPhrase, false, true, true))
->unique()
Expand Down
1 change: 1 addition & 0 deletions classes/submission/DAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use PKP\db\DAORegistry;
use PKP\log\event\EventLogEntry;
use PKP\note\NoteDAO;
use PKP\notification\Notification;
use PKP\query\QueryDAO;
use PKP\services\PKPSchemaService;
use PKP\stageAssignment\StageAssignment;
Expand Down
5 changes: 4 additions & 1 deletion locale/en/admin.po
Original file line number Diff line number Diff line change
Expand Up @@ -1022,4 +1022,7 @@ msgid "admin.submissions.incomplete.bulkDelete.body"
msgstr "Are you sure you want to delete the selected items? This action cannot be undone. Please confirm to proceed."

msgid "admin.submissions.incomplete.bulkDelete.selectionStatus"
msgstr "{$selected} of {$total} Incomplete Submissions Selected"
msgstr "Incomplete Submissions Selected."

msgid "admin.submissions.incomplete.bulkDelete.success"
msgstr "Submissions deleted successfully!"
6 changes: 6 additions & 0 deletions locale/en/api.po
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,9 @@ msgstr "The reviewer for the assignment could not be found"

msgid "api.submission.400.sectionDoesNotExist"
msgstr "The provided section does not exist."

msgid "api.submission.400.missingQueryParam"
msgstr "The request is missing the required query parameter `ids`. Please provide the `ids` of the submissions you wish to delete."

msgid "api.submission.400.invalidId"
msgstr "Invalid ID: \"{$id}\" provided."
2 changes: 1 addition & 1 deletion locale/en/common.po
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ msgid "common.replaceFile"
msgstr "Replace file"

msgid "common.requiredField"
msgstr 'Required fields are marked with an asterisk: <abbr class="required" title="required">*</abbr>'
msgstr "Required fields are marked with an asterisk: <abbr class=\"required\" title=\"required\">*</abbr>"

msgid "common.required"
msgstr "Required"
Expand Down

0 comments on commit 04b0410

Please sign in to comment.