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 decision to use EntityDAO and Repo
- Introduce decision types for each decision
- Add new decision types for back to review, back to copyediting, etc
- Add event when decision added
- Add API endpoint to record a decision
- Add step-by-step workflow page to record decisions
- Modify submission workflow page to link to record decision page
- 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
  • Loading branch information
NateWr committed Dec 8, 2021
1 parent 46d1226 commit c9e7be4
Show file tree
Hide file tree
Showing 155 changed files with 9,719 additions and 755 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
),
];
}
}
55 changes: 54 additions & 1 deletion 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 @@ -232,4 +248,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
77 changes: 77 additions & 0 deletions api/v1/mailables/PKPMailableHandler.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
/**
* @file api/v1/mailables/PKPMailableHandler.inc.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPMailableHandler
* @ingroup api_v1_mmailables
*
* @brief Base class to handle API requests for email events
*/

use Illuminate\Support\Facades\App;
use PKP\handler\APIHandler;
use PKP\security\authorization\ContextRequiredPolicy;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;

class PKPMailableHandler extends APIHandler
{
/**
* @copydoc APIHandler::__construct()
*/
public function __construct()
{
$this->_handlerPath = 'mailables';
$roles = [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT];
$this->_endpoints = [
'GET' => [
[
'pattern' => $this->getEndpointPattern() . '/{class}',
'handler' => [$this, 'get'],
'roles' => $roles,
],
],
];
parent::__construct();
}

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

// This endpoint is not available at the site-wide level
$this->addPolicy(new ContextRequiredPolicy($request));

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

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

/**
* Get a single mailable
*
* @param $slimRequest Request Slim request object
* @param $response Response object
* @param array $args arguments
*
* @return Response
*/
public function get($slimRequest, $response, $args)
{
// TODO: Obviously this is not safe and shouldn't be used!!!!
$mailable = App::make(str_replace('-', '\\', $args['class']));

return $response->withJson($mailable->getEmailTemplates(), 200);
}
}
Loading

0 comments on commit c9e7be4

Please sign in to comment.