283 lines
9.0 KiB
PHP
283 lines
9.0 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file api/v1/issues/IssueHandler.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 IssueHandler
|
|
*
|
|
* @ingroup api_v1_issues
|
|
*
|
|
* @brief Handle API requests for issues operations.
|
|
*
|
|
*/
|
|
|
|
namespace APP\API\v1\issues;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use APP\issue\Collector;
|
|
use APP\security\authorization\OjsIssueRequiredPolicy;
|
|
use APP\security\authorization\OjsJournalMustPublishPolicy;
|
|
use Illuminate\Support\LazyCollection;
|
|
use PKP\core\APIResponse;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\handler\APIHandler;
|
|
use PKP\plugins\Hook;
|
|
use PKP\security\authorization\ContextAccessPolicy;
|
|
use PKP\security\authorization\ContextRequiredPolicy;
|
|
use PKP\security\authorization\UserRolesRequiredPolicy;
|
|
use PKP\security\Role;
|
|
use PKP\submission\GenreDAO;
|
|
use Slim\Http\Request;
|
|
|
|
class IssueHandler extends APIHandler
|
|
{
|
|
/** @var int The default number of issues to return in one request */
|
|
public const DEFAULT_COUNT = 20;
|
|
|
|
/** @var int The maximum number of issues to return in one request */
|
|
public const MAX_COUNT = 100;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->_handlerPath = 'issues';
|
|
$roles = [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR];
|
|
$this->_endpoints = [
|
|
'GET' => [
|
|
[
|
|
'pattern' => $this->getEndpointPattern(),
|
|
'handler' => [$this, 'getMany'],
|
|
'roles' => $roles
|
|
],
|
|
[
|
|
'pattern' => $this->getEndpointPattern() . '/current',
|
|
'handler' => [$this, 'getCurrent'],
|
|
'roles' => $roles
|
|
],
|
|
[
|
|
'pattern' => $this->getEndpointPattern() . '/{issueId:\d+}',
|
|
'handler' => [$this, 'get'],
|
|
'roles' => $roles
|
|
],
|
|
]
|
|
];
|
|
parent::__construct();
|
|
}
|
|
|
|
//
|
|
// Implement methods from PKPHandler
|
|
//
|
|
public function authorize($request, &$args, $roleAssignments)
|
|
{
|
|
$routeName = null;
|
|
$slimRequest = $this->getSlimRequest();
|
|
|
|
if (!is_null($slimRequest) && ($route = $slimRequest->getAttribute('route'))) {
|
|
$routeName = $route->getName();
|
|
}
|
|
|
|
$this->addPolicy(new UserRolesRequiredPolicy($request), true);
|
|
$this->addPolicy(new ContextRequiredPolicy($request));
|
|
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
|
|
$this->addPolicy(new OjsJournalMustPublishPolicy($request));
|
|
|
|
if ($routeName === 'get') {
|
|
$this->addPolicy(new OjsIssueRequiredPolicy($request, $args));
|
|
}
|
|
|
|
return parent::authorize($request, $args, $roleAssignments);
|
|
}
|
|
|
|
//
|
|
// Public handler methods
|
|
//
|
|
/**
|
|
* Get a collection of issues
|
|
*
|
|
* @param Request $slimRequest Slim request object
|
|
* @param APIResponse $response object
|
|
* @param array $args arguments
|
|
*
|
|
* @return APIResponse
|
|
*/
|
|
public function getMany($slimRequest, $response, $args)
|
|
{
|
|
$collector = Repo::issue()->getCollector()
|
|
->limit(self::DEFAULT_COUNT)
|
|
->offset(0);
|
|
|
|
$request = $this->getRequest();
|
|
$currentUser = $request->getUser();
|
|
$context = $request->getContext();
|
|
|
|
if (!$context) {
|
|
return $response->withStatus(404)->withJsonError('api.404.resourceNotFound');
|
|
}
|
|
|
|
// Process query params to format incoming data as needed
|
|
foreach ($slimRequest->getQueryParams() as $param => $val) {
|
|
switch ($param) {
|
|
case 'orderBy':
|
|
if (in_array($val, [Collector::ORDERBY_DATE_PUBLISHED, Collector::ORDERBY_LAST_MODIFIED, Collector::ORDERBY_SEQUENCE])) {
|
|
$collector->orderBy($val);
|
|
}
|
|
break;
|
|
|
|
// Enforce a maximum count to prevent the API from crippling the
|
|
// server
|
|
case 'count':
|
|
$collector->limit(min((int) $val, self::MAX_COUNT));
|
|
break;
|
|
|
|
case 'offset':
|
|
$collector->offset((int) $val);
|
|
break;
|
|
|
|
// Always convert volume, number and year values to array
|
|
case 'volumes':
|
|
case 'volume':
|
|
case 'numbers':
|
|
case 'number':
|
|
case 'years':
|
|
case 'year':
|
|
|
|
// Support deprecated `year`, `number` and `volume` params
|
|
if (substr($param, -1) !== 's') {
|
|
$param .= 's';
|
|
}
|
|
|
|
if (is_string($val)) {
|
|
$val = explode(',', $val);
|
|
} elseif (!is_array($val)) {
|
|
$val = [$val];
|
|
}
|
|
$values = array_map('intval', $val);
|
|
switch ($param) {
|
|
case 'volumes':
|
|
$collector->filterByVolumes($values);
|
|
break;
|
|
case 'numbers':
|
|
$collector->filterByNumbers($values);
|
|
break;
|
|
case 'years':
|
|
$collector->filterByYears($values);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'isPublished':
|
|
$collector->filterByPublished((bool) $val);
|
|
break;
|
|
|
|
case 'searchPhrase':
|
|
$collector->searchPhrase($val);
|
|
break;
|
|
case 'doiStatus':
|
|
$collector->filterByDoiStatuses(array_map('intval', $this->paramToArray($val)));
|
|
break;
|
|
case 'hasDois':
|
|
$collector->filterByHasDois((bool) $val, $context->getEnabledDoiTypes());
|
|
}
|
|
}
|
|
|
|
$collector->filterByContextIds([$context->getId()]);
|
|
|
|
Hook::call('API::issues::params', [&$collector, $slimRequest]);
|
|
|
|
// You must be a manager or site admin to access unpublished Issues
|
|
$isAdmin = $currentUser->hasRole([Role::ROLE_ID_MANAGER], $context->getId()) || $currentUser->hasRole([Role::ROLE_ID_SITE_ADMIN], \PKP\core\PKPApplication::CONTEXT_SITE);
|
|
if (isset($collector->isPublished) && !$collector->isPublished && !$isAdmin) {
|
|
return $response->withStatus(403)->withJsonError('api.submissions.403.unpublishedIssues');
|
|
} elseif (!$isAdmin) {
|
|
$collector->filterByPublished(true);
|
|
}
|
|
|
|
$issues = $collector->getMany();
|
|
|
|
return $response->withJson([
|
|
'items' => Repo::issue()->getSchemaMap()->summarizeMany($issues, $context)->values(),
|
|
'itemsMax' => $collector->limit(null)->offset(null)->getCount(),
|
|
], 200);
|
|
}
|
|
|
|
/**
|
|
* Get the current issue
|
|
*
|
|
* @param Request $slimRequest Slim request object
|
|
* @param APIResponse $response object
|
|
* @param array $args arguments
|
|
*
|
|
* @return APIResponse
|
|
*/
|
|
public function getCurrent($slimRequest, $response, $args)
|
|
{
|
|
$context = $this->getRequest()->getContext();
|
|
|
|
$issue = Repo::issue()->getCurrent($context->getId());
|
|
|
|
if (!$issue) {
|
|
return $response->withStatus(404)->withJsonError('api.404.resourceNotFound');
|
|
}
|
|
|
|
$data = Repo::issue()->getSchemaMap()->map(
|
|
$issue,
|
|
$context,
|
|
$this->getUserGroups($context->getId()),
|
|
$this->getGenres($context->getId())
|
|
);
|
|
|
|
return $response->withJson($data, 200);
|
|
}
|
|
|
|
/**
|
|
* Get a single issue
|
|
*
|
|
* @param Request $slimRequest Slim request object
|
|
* @param APIResponse $response object
|
|
* @param array $args arguments
|
|
*
|
|
* @return APIResponse
|
|
*/
|
|
public function get($slimRequest, $response, $args)
|
|
{
|
|
$context = $this->getRequest()->getContext();
|
|
|
|
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
|
|
|
|
if (!$issue) {
|
|
return $response->withStatus(404)->withJsonError('api.404.resourceNotFound');
|
|
}
|
|
|
|
$data = Repo::issue()->getSchemaMap()->map(
|
|
$issue,
|
|
$context,
|
|
$this->getUserGroups($context->getId()),
|
|
$this->getGenres($context->getId())
|
|
);
|
|
|
|
return $response->withJson($data, 200);
|
|
}
|
|
|
|
protected function getUserGroups(int $contextId): LazyCollection
|
|
{
|
|
return Repo::userGroup()->getCollector()
|
|
->filterByContextIds([$contextId])
|
|
->getMany();
|
|
}
|
|
|
|
protected function getGenres(int $contextId): array
|
|
{
|
|
/** @var GenreDAO $genreDao */
|
|
$genreDao = DAORegistry::getDAO('GenreDAO');
|
|
return $genreDao->getByContextId($contextId)->toArray();
|
|
}
|
|
}
|