Skip to content

Commit

Permalink
pkp#5717 Refactor editorial decisions and introduce email composer UI…
Browse files Browse the repository at this point in the history
… component

- Refactor editorial decisions to use EntityDAO and Repo
- Add class for each editorial decision type
- Add new decision types for back to review, back to copyediting, etc
- Add new decision types for reverting declined decisions
- Add new decision type for skip review
- Add event when decision added
- Add API endpoint to record a decision
- Add step-by-step workflow page to record decisions
- Add steps to send emails, promote files and complete forms
- Add composer UI component with template search, file attachments and multiple locales
- Add support for file attachments by upload, review files, submission files and library files
- Add private API endpoint to get library files
- Add email notification to all authors when editorial decision is made
- Add file genre of submission files to API responses
- Add new email templates for all new email notifications
- Update editorial statistics to include skip review as accept decision
- Remove EditDecisionDAO, EditorDecisionActionsManager, and related code
  • Loading branch information
NateWr committed Jan 13, 2022
1 parent e7fdf1a commit 85be8de
Show file tree
Hide file tree
Showing 199 changed files with 10,509 additions and 4,849 deletions.
145 changes: 145 additions & 0 deletions api/v1/_library/PKPLibraryHandler.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

/**
* @file api/v1/_library/PKPLibraryHandler.inc.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPLibraryHandler
* @ingroup api_v1_announcement
*
* @brief Handle API requests for announcement operations.
*
*/

use APP\core\Application;
use APP\core\Services;
use APP\file\LibraryFileManager;
use PKP\context\LibraryFile;
use PKP\context\LibraryFileDAO;
use PKP\core\APIResponse;
use PKP\db\DAORegistry;
use PKP\db\DAOResultFactory;
use PKP\handler\APIHandler;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\authorization\SubmissionAccessPolicy;
use PKP\security\Role;

use Psr\Http\Message\ServerRequestInterface;

class PKPLibraryHandler extends APIHandler
{
public function __construct()
{
$this->_handlerPath = '_library';
$this->_endpoints = [
'GET' => [
[
'pattern' => $this->getEndpointPattern(),
'handler' => [$this, 'getLibrary'],
'roles' => [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR],
],
],
];
parent::__construct();

}

/**
* @copydoc PKPHandler::authorize
*/
public function authorize($request, &$args, $roleAssignments)
{
$rolePolicy = new PolicySet(PolicySet::COMBINING_PERMIT_OVERRIDES);

foreach ($roleAssignments as $role => $operations) {
$rolePolicy->addPolicy(new RoleBasedHandlerOperationPolicy($request, $role, $operations));
}
$this->addPolicy($rolePolicy);

if ($request->getUserVar('includeSubmissionId')) {
$this->addPolicy(new SubmissionAccessPolicy($request, $args, $roleAssignments, 'includeSubmissionId'));
}

return parent::authorize($request, $args, $roleAssignments);
}

/**
* Get a list of all files in the library
*
* @param array $args arguments
*
* @return APIResponse
*/
public function getLibrary(ServerRequestInterface $slimRequest, APIResponse $response, array $args)
{
/** @var LibraryFileDAO $libraryFileDao */
$libraryFileDao = DAORegistry::getDAO('LibraryFileDAO');
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
$context = $this->getRequest()->getContext();
$contextId = $context->getId();
$libraryFileManager = new LibraryFileManager($contextId);

$files = [];

$params = $slimRequest->getQueryParams();
if (isset($params['includeSubmissionId'])) {
/** @var DAOResultFactory $result */
$result = $libraryFileDao->getBySubmissionId($submission->getId());
/** @var LibraryFile $file */
while ($file = $result->next()) {
$files[] = $this->fileToResponse($file, $libraryFileManager);
}
}

/** @var DAOResultFactory $result */
$result = $libraryFileDao->getByContextId($contextId);
/** @var LibraryFile $file */
while ($file = $result->next()) {
$files[] = $this->fileToResponse($file, $libraryFileManager);
}

return $response->withJson([
'items' => $files,
'itemsMax' => count($files),
], 200);
}

/**
* Convert a file object to the JSON response object
*/
protected function fileToResponse(LibraryFile $file, LibraryFileManager $libraryFileManager): array
{
$request = Application::get()->getRequest();

$urlArgs = [
'libraryFileId' => $file->getId(),
];
if ($file->getSubmissionId()) {
$urlArgs['submissionId'] = $file->getSubmissionId();
}

return [
'id' => $file->getId(),
'filename' => $file->getServerFileName(),
'name' => $file->getName(null),
'mimetype' => $file->getFileType(),
'documentType' => Services::get('file')->getDocumentType($file->getFileType()),
'submissionId' => $file->getSubmissionId() ?? 0,
'type' => $file->getType(),
'typeName' => __($libraryFileManager->getTitleKeyFromType($file->getType())),
'url' => $request->getDispatcher()->url(
$request,
Application::ROUTE_COMPONENT,
null,
'api.file.FileApiHandler',
'downloadLibraryFile',
null,
$urlArgs
),
];
}
}
61 changes: 59 additions & 2 deletions api/v1/_submissions/PKPBackendSubmissionsHandler.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
use PKP\plugins\HookRegistry;

use PKP\security\authorization\ContextAccessPolicy;

use PKP\security\authorization\SubmissionAccessPolicy;
use PKP\security\Role;
use Slim\Http\Response;

abstract class PKPBackendSubmissionsHandler extends APIHandler
{
Expand All @@ -50,6 +51,15 @@ public function __construct()
Role::ROLE_ID_ASSISTANT,
],
],
[
'pattern' => "{$rootPattern}/{submissionId:\d+}/reviewRound",
'handler' => [$this, 'getReviewRound'],
'roles' => [
Role::ROLE_ID_SITE_ADMIN,
Role::ROLE_ID_MANAGER,
Role::ROLE_ID_SUB_EDITOR,
],
],
],
'DELETE' => [
[
Expand All @@ -72,6 +82,12 @@ public function __construct()
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));

$routeName = $this->getSlimRequest()->getAttribute('route')->getName();
if (in_array($routeName, ['delete', 'getReviewRound'])) {
$this->addPolicy(new SubmissionAccessPolicy($request, $args, $roleAssignments));
}

return parent::authorize($request, $args, $roleAssignments);
}

Expand Down Expand Up @@ -114,9 +130,13 @@ public function getMany($slimRequest, $response, $args)
$userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /** @var UserGroupDAO $userGroupDao */
$userGroups = $userGroupDao->getByContextId($context->getId())->toArray();

/** @var GenreDAO $genreDao */
$genreDao = DAORegistry::getDAO('GenreDAO');
$genres = $genreDao->getByContextId($context->getId())->toArray();

return $response->withJson([
'itemsMax' => Repo::submission()->getCount($collector->limit(null)->offset(null)),
'items' => Repo::submission()->getSchemaMap()->mapManyToSubmissionsList($submissions, $userGroups),
'items' => Repo::submission()->getSchemaMap()->mapManyToSubmissionsList($submissions, $userGroups, $genres),
], 200);
}

Expand Down Expand Up @@ -232,4 +252,41 @@ public function delete($slimRequest, $response, $args)

return $response->withJson(true);
}

/**
* Get the current review round for this submission
*
* @param $slimRequest Request Slim request object
* @param $response Response object
* @param array $args arguments
*/
public function getReviewRound($slimRequest, $response, $args): Response
{
$request = $this->getRequest();
$context = $request->getContext();
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);

if (!$submission) {
return $response->withStatus(404)->withJsonError('api.404.resourceNotFound');
}

if ($context->getId() != $submission->getContextId()) {
return $response->withStatus(403)->withJsonError('api.submissions.400.wrongContext');
}

/** @var ReviewRoundDAO */
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
$reviewRound = $reviewRoundDao->getLastReviewRoundBySubmissionId($submission->getId());
if (!$reviewRound) {
return $response->withStatus(404)->withJsonError('api.404.resourceNotFound');
}

return $response->withJson([
'id' => $reviewRound->getId(),
'submissionId' => $reviewRound->getSubmissionId(),
'stageId' => $reviewRound->getStageId(),
'round' => $reviewRound->getRound(),
'status' => $reviewRound->getStatus(),
], 200);
}
}
8 changes: 4 additions & 4 deletions api/v1/emailTemplates/PKPEmailTemplateHandler.inc.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* @file api/v1/contexts/PKPEmailTemplateHandler.inc.php
* @file api/v1/emailTemplates/PKPEmailTemplateHandler.inc.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
Expand All @@ -14,12 +14,12 @@

use PKP\facades\Repo;
use PKP\handler\APIHandler;
use PKP\plugins\HookRegistry;
use PKP\security\authorization\ContextRequiredPolicy;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;
use PKP\services\PKPSchemaService;
use PKP\plugins\HookRegistry;
use Slim\Http\Request as SlimRequest;
use Slim\Http\Response;

Expand All @@ -37,12 +37,12 @@ public function __construct()
[
'pattern' => $this->getEndpointPattern(),
'handler' => [$this, 'getMany'],
'roles' => $roles,
'roles' => array_merge($roles, [Role::ROLE_ID_SUB_EDITOR, ROLE::ROLE_ID_ASSISTANT]),
],
[
'pattern' => $this->getEndpointPattern() . '/{key}',
'handler' => [$this, 'get'],
'roles' => $roles,
'roles' => array_merge($roles, [Role::ROLE_ID_SUB_EDITOR, ROLE::ROLE_ID_ASSISTANT]),
],
],
'POST' => [
Expand Down
Loading

0 comments on commit 85be8de

Please sign in to comment.