first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,100 @@
<?php
/**
* @file controllers/api/file/ManageFileApiHandler.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 ManageFileApiHandler
*
* @ingroup controllers_api_file
*
* @brief Class defining an AJAX API for file manipulation.
*/
namespace APP\controllers\api\file;
use APP\controllers\tab\pubIds\form\PublicIdentifiersForm;
use APP\core\Application;
use APP\core\Request;
use PKP\controllers\api\file\PKPManageFileApiHandler;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\security\Role;
class ManageFileApiHandler extends PKPManageFileApiHandler
{
/**
* Constructor.
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR],
['identifiers', 'updateIdentifiers', 'clearPubId',]
);
}
/**
* Edit proof submission file pub ids.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function identifiers($args, $request)
{
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$stageId = $request->getUserVar('stageId');
$form = new PublicIdentifiersForm($submissionFile, $stageId);
$form->initData();
return new JSONMessage(true, $form->fetch($request));
}
/**
* Update proof submission file pub ids.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateIdentifiers($args, $request)
{
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$stageId = $request->getUserVar('stageId');
$form = new PublicIdentifiersForm($submissionFile, $stageId);
$form->readInputData();
if ($form->validate()) {
$form->execute();
return DAO::getDataChangedEvent($submissionFile->getId());
} else {
return new JSONMessage(true, $form->fetch($request));
}
}
/**
* Clear proof submission file pub id.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function clearPubId($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$stageId = $request->getUserVar('stageId');
$form = new PublicIdentifiersForm($submissionFile, $stageId);
$form->clearPubId($request->getUserVar('pubIdPlugIn'));
return new JSONMessage(true);
}
}
@@ -0,0 +1,105 @@
<?php
/**
* @file controllers/grid/articleGalleys/ArticleGalleyGridCellProvider.php
*
* Copyright (c) 2016-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 ArticleGalleyGridCellProvider
*
* @ingroup controllers_grid_articleGalleys
*
* @brief Base class for a cell provider for article galleys.
*/
namespace APP\controllers\grid\articleGalleys;
use APP\facades\Repo;
use APP\publication\Publication;
use APP\submission\Submission;
use PKP\controllers\api\file\linkAction\DownloadFileLinkAction;
use PKP\controllers\grid\DataObjectGridCellProvider;
use PKP\controllers\grid\GridHandler;
use PKP\galley\Galley;
class ArticleGalleyGridCellProvider extends DataObjectGridCellProvider
{
/** @var Submission */
public $_submission;
/** @var Publication */
public $_publication;
public $_isEditable;
/**
* Constructor
*
* @param Submission $submission
*/
public function __construct($submission, $publication, $isEditable)
{
parent::__construct();
$this->_submission = $submission;
$this->_publication = $publication;
$this->_isEditable = $isEditable;
}
//
// Template methods from GridCellProvider
//
/**
* @copydoc GridCellProvider::getTemplateVarsFromRowColumn()
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$element = $row->getData();
$columnId = $column->getId();
assert($element instanceof \PKP\core\DataObject && !empty($columnId));
/** @var Galley $element */
switch ($columnId) {
case 'label':
return [
'label' => !$element->getRemoteUrl() && $element->getData('submissionFileId') ? '' : $element->getLabel()
];
default: assert(false);
}
return parent::getTemplateVarsFromRowColumn($row, $column);
}
/**
* Get request arguments.
*
* @param \PKP\controllers\grid\GridRow $row
*
* @return array
*/
public function getRequestArgs($row)
{
return [
'submissionId' => $this->_submission->getId(),
'publicationId' => $this->_publication->getId(),
];
}
/**
* @copydoc GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
switch ($column->getId()) {
case 'label':
$element = $row->getData();
if ($element->getRemoteUrl() || !$element->getData('submissionFileId')) {
break;
}
$submissionFile = Repo::submissionFile()
->get($element->getData('submissionFileId'));
return [new DownloadFileLinkAction($request, $submissionFile, WORKFLOW_STAGE_ID_PRODUCTION, $element->getLabel())];
}
return parent::getCellActions($request, $row, $column, $position);
}
}
@@ -0,0 +1,481 @@
<?php
/**
* @file controllers/grid/articleGalleys/ArticleGalleyGridHandler.php
*
* Copyright (c) 2016-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 ArticleGalleyGridHandler
*
* @ingroup controllers_grid_articleGalleys
*
* @brief Handle article galley grid requests.
*/
namespace APP\controllers\grid\articleGalleys;
use APP\controllers\grid\articleGalleys\form\ArticleGalleyForm;
use APP\controllers\tab\pubIds\form\PublicIdentifiersForm;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use APP\publication\Publication;
use APP\submission\Submission;
use APP\template\TemplateManager;
use PKP\controllers\grid\feature\OrderGridItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\core\JSONMessage;
use PKP\core\PKPApplication;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\galley\Galley;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\notification\NotificationDAO;
use PKP\notification\PKPNotification;
use PKP\plugins\PluginRegistry;
use PKP\security\authorization\internal\RepresentationRequiredPolicy;
use PKP\security\authorization\PublicationAccessPolicy;
use PKP\security\authorization\WorkflowStageAccessPolicy;
use PKP\security\Role;
use PKP\submission\PKPSubmission;
class ArticleGalleyGridHandler extends GridHandler
{
/** @var Request */
public $_request;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_AUTHOR, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
['fetchGrid', 'fetchRow']
);
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
['addGalley', 'editGalley', 'editGalleyTab', 'updateGalley', 'deleteGalley', 'identifiers', 'updateIdentifiers', 'clearPubId', 'saveSequence']
);
}
//
// Getters/Setters
//
/**
* Get the authorized submission.
*
* @return Submission
*/
public function getSubmission()
{
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
}
/**
* Get the authorized publication.
*
* @return Publication
*/
public function getPublication()
{
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_PUBLICATION);
}
/**
* Get the authorized galley.
*
* @return Galley
*/
public function getGalley()
{
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REPRESENTATION);
}
//
// Overridden methods from PKPHandler.
//
/**
* @see GridHandler::getJSHandler()
*/
public function getJSHandler()
{
return '$.pkp.controllers.grid.articleGalleys.ArticleGalleyGridHandler';
}
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->_request = $request;
$this->addPolicy(new WorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', WORKFLOW_STAGE_ID_PRODUCTION));
$this->addPolicy(new PublicationAccessPolicy($request, $args, $roleAssignments));
if ($request->getUserVar('representationId')) {
$this->addPolicy(new RepresentationRequiredPolicy($request, $args));
}
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
$this->setTitle('submission.layout.galleys');
$cellProvider = new ArticleGalleyGridCellProvider($this->getSubmission(), $this->getPublication(), $this->canEdit());
// Columns
$this->addColumn(new GridColumn(
'label',
'common.name',
null,
null,
$cellProvider
));
if ($this->canEdit()) {
$this->addAction(new LinkAction(
'addGalley',
new AjaxModal(
$request->getRouter()->url($request, null, null, 'addGalley', null, $this->getRequestArgs()),
__('submission.layout.newGalley'),
'modal_add_item'
),
__('grid.action.addGalley'),
'add_item'
));
}
}
//
// Overridden methods from GridHandler
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
if ($this->canEdit()) {
return [new OrderGridItemsFeature()];
}
return [];
}
/**
* @copydoc GridHandler::getDataElementSequence()
*/
public function getDataElementSequence($row)
{
return $row->getSequence();
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementSequence($request, $rowId, $gridDataElement, $newSequence)
{
$galley = Repo::galley()->get((int) $rowId);
Repo::galley()->edit($galley, ['seq' => $newSequence]);
}
//
// Overridden methods from GridHandler
//
/**
* @copydoc GridHandler::getRowInstance()
*
* @return ArticleGalleyGridRow
*/
public function getRowInstance()
{
return new ArticleGalleyGridRow(
$this->getSubmission(),
$this->getPublication(),
$this->canEdit()
);
}
/**
* Get the arguments that will identify the data in the grid.
* Overridden by child grids.
*
* @return array
*/
public function getRequestArgs()
{
return [
'submissionId' => $this->getSubmission()->getId(),
'publicationId' => $this->getPublication()->getId(),
];
}
/**
* @copydoc GridHandler::loadData()
*
* @param null|mixed $filter
*/
public function loadData($request, $filter = null)
{
return Repo::galley()->getCollector()
->filterByPublicationIds([$this->getPublication()->getId()])
->getMany();
}
//
// Public Galley Grid Actions
//
/**
* Edit article galley pub ids
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function identifiers($args, $request)
{
$representation = $this->getGalley();
$form = new PublicIdentifiersForm($representation, null, null, $this->canEdit());
$form->initData();
return new JSONMessage(true, $form->fetch($request));
}
/**
* Update article galley pub ids
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateIdentifiers($args, $request)
{
$representation = $this->getGalley();
$form = new PublicIdentifiersForm($representation, null, array_merge($this->getRequestArgs(), ['representationId' => $representation->getId()]), $this->canEdit());
$form->readInputData();
if ($form->validate()) {
$form->execute();
return DAO::getDataChangedEvent();
} else {
return new JSONMessage(true, $form->fetch($request));
}
}
/**
* Clear galley pub id
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function clearPubId($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$representation = $this->getGalley();
$form = new PublicIdentifiersForm($representation, null, null, $this->canEdit());
$form->clearPubId($request->getUserVar('pubIdPlugIn'));
return new JSONMessage(true);
}
/**
* Add a galley
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function addGalley($args, $request)
{
$galleyForm = new ArticleGalleyForm(
$request,
$this->getSubmission(),
$this->getPublication()
);
$galleyForm->initData();
return new JSONMessage(true, $galleyForm->fetch($request));
}
/**
* Delete a galley.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteGalley($args, $request)
{
$galley = $this->getGalley();
if (!$galley || !$request->checkCSRF()) {
return new JSONMessage(false);
}
Repo::galley()->delete($galley);
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_REPRESENTATION, $galley->getId());
if ($this->getSubmission()->getStageId() == WORKFLOW_STAGE_ID_EDITING ||
$this->getSubmission()->getStageId() == WORKFLOW_STAGE_ID_PRODUCTION) {
$notificationMgr = new NotificationManager();
$notificationMgr->updateNotification(
$request,
[PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER, PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS],
null,
Application::ASSOC_TYPE_SUBMISSION,
$this->getSubmission()->getId()
);
}
return DAO::getDataChangedEvent($galley->getId());
}
/**
* Edit a galley metadata modal
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editGalley($args, $request)
{
$galley = $this->getGalley();
// Check if this is a remote galley
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'submissionId' => $this->getSubmission()->getId(),
'publicationId' => $this->getPublication()->getId(),
'representationId' => $galley->getId(),
]);
$publisherIdEnabled = in_array('galley', (array) $request->getContext()->getData('enablePublisherId'));
$pubIdsEnabled = false;
$pubIdPlugins = PluginRegistry::loadCategory('pubIds', true, $request->getContext()->getId());
foreach ($pubIdPlugins as $pubIdPlugin) {
if ($pubIdPlugin->isObjectTypeEnabled('Representation', $request->getContext()->getId())) {
$pubIdsEnabled = true;
break;
}
}
if ($publisherIdEnabled || $pubIdsEnabled) {
$templateMgr->assign('enableIdentifiers', true);
}
return new JSONMessage(true, $templateMgr->fetch('controllers/grid/articleGalleys/editFormat.tpl'));
}
/**
* Edit a galley
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editGalleyTab($args, $request)
{
// Form handling
$galleyForm = new ArticleGalleyForm(
$request,
$this->getSubmission(),
$this->getPublication(),
$this->getGalley(),
$this->canEdit()
);
$galleyForm->initData();
return new JSONMessage(true, $galleyForm->fetch($request));
}
/**
* Save a galley
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateGalley($args, $request)
{
$galley = $this->getGalley();
$galleyForm = new ArticleGalleyForm($request, $this->getSubmission(), $this->getPublication(), $galley, $this->canEdit());
$galleyForm->readInputData();
if ($galleyForm->validate()) {
$galley = $galleyForm->execute();
if ($this->getSubmission()->getStageId() == WORKFLOW_STAGE_ID_EDITING ||
$this->getSubmission()->getStageId() == WORKFLOW_STAGE_ID_PRODUCTION) {
$notificationMgr = new NotificationManager();
$notificationMgr->updateNotification(
$request,
[PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER, PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS],
null,
Application::ASSOC_TYPE_SUBMISSION,
$this->getSubmission()->getId()
);
}
return DAO::getDataChangedEvent($galley->getId());
}
return new JSONMessage(true, $galleyForm->fetch($request));
}
/**
* @copydoc GridHandler::fetchRow()
*/
public function fetchRow($args, $request)
{
$json = parent::fetchRow($args, $request);
if ($row = $this->getRequestedRow($request, $args)) {
$galley = $row->getData();
if (!$galley->getRemoteUrl() && !$galley->getData('submissionFileId')) {
$json->setEvent('uploadFile', $galley->getId());
}
}
return $json;
}
/**
* Can the current user edit the galleys in this grid?
*
* The user must have an allowed role in one of the assigned stages.
* If the user is not assigned, they can edit if they are an editor
* or admin.
*
* @return bool
*/
public function canEdit()
{
return $this->getPublication()->getData('status') !== PKPSubmission::STATUS_PUBLISHED &&
Repo::user()->canUserAccessStage(
WORKFLOW_STAGE_ID_PRODUCTION,
PKPApplication::WORKFLOW_TYPE_EDITORIAL,
$this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES),
$this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES)
);
}
}
@@ -0,0 +1,152 @@
<?php
/**
* @file controllers/grid/articleGalleys/ArticleGalleyGridRow.php
*
* Copyright (c) 2016-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 ArticleGalleyGridRow
*
* @ingroup controllers_grid_articleGalleys
*
* @brief Representation of an article galley grid row.
*/
namespace APP\controllers\grid\articleGalleys;
use APP\core\Application;
use APP\publication\Publication;
use APP\submission\Submission;
use PKP\controllers\api\file\linkAction\AddFileLinkAction;
use PKP\controllers\grid\GridRow;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RemoteActionConfirmationModal;
use PKP\security\Role;
use PKP\submissionFile\SubmissionFile;
class ArticleGalleyGridRow extends GridRow
{
/** @var Submission */
public $_submission;
/** @var Publication */
public $_publication;
/** @var bool */
public $_isEditable;
/**
* Constructor
*
* @param Submission $submission
* @param bool $isEditable
*/
public function __construct($submission, $publication, $isEditable)
{
$this->_submission = $submission;
$this->_publication = $publication;
$this->_isEditable = $isEditable;
parent::__construct();
}
//
// Overridden methods from GridRow
//
/**
* @copydoc GridRow::initialize()
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
// Do the default initialization
parent::initialize($request, $template);
// Is this a new row or an existing row?
$rowId = $this->getId();
if (!empty($rowId) && is_numeric($rowId)) {
// Only add row actions if this is an existing row
$router = $request->getRouter();
$actionArgs = $this->getRequestArgs();
$actionArgs['representationId'] = $rowId;
// Add row-level actions
$this->addAction(new LinkAction(
'editGalley',
new AjaxModal(
$router->url($request, null, null, 'editGalley', null, $actionArgs),
($this->_isEditable) ? __('submission.layout.editGalley') : __('submission.layout.viewGalley'),
'modal_edit'
),
($this->_isEditable) ? __('grid.action.edit') : __('grid.action.view'),
'edit'
));
if ($this->_isEditable) {
$galley = $this->getData();
if (!$galley->getRemoteUrl()) {
$this->addAction(new AddFileLinkAction(
$request,
$this->getSubmission()->getId(),
WORKFLOW_STAGE_ID_PRODUCTION,
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
SubmissionFile::SUBMISSION_FILE_PROOF,
Application::ASSOC_TYPE_REPRESENTATION,
$rowId,
null
));
}
$this->addAction(new LinkAction(
'deleteGalley',
new RemoteActionConfirmationModal(
$request->getSession(),
__('common.confirmDelete'),
__('grid.action.delete'),
$router->url($request, null, null, 'deleteGalley', null, $actionArgs),
'modal_delete'
),
__('grid.action.delete'),
'delete'
));
}
}
}
/**
* Get the submission for this row (already authorized)
*
* @return Submission
*/
public function getSubmission()
{
return $this->_submission;
}
/**
* Get the publication for this row (already authorized)
*
* @return Publication
*/
public function getPublication()
{
return $this->_publication;
}
/**
* Get the base arguments that will identify the data in the grid.
*
* @return array
*/
public function getRequestArgs()
{
return [
'submissionId' => $this->getSubmission()->getId(),
'publicationId' => $this->getPublication()->getId(),
];
}
}
@@ -0,0 +1,193 @@
<?php
/**
* @file controllers/grid/articleGalleys/form/ArticleGalleyForm.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 ArticleGalleyForm
*
* @ingroup controllers_grid_articleGalleys_form
*
* @see Galley
*
* @brief Article galley editing form.
*/
namespace APP\controllers\grid\articleGalleys\form;
use APP\core\Request;
use APP\facades\Repo;
use APP\publication\Publication;
use APP\submission\Submission;
use APP\template\TemplateManager;
use PKP\form\Form;
use PKP\galley\Galley;
class ArticleGalleyForm extends Form
{
/** @var Submission */
public $_submission = null;
/** @var Publication */
public $_publication = null;
/** @var Galley current galley */
public $_articleGalley = null;
public bool $_isEditable = true;
/**
* Constructor.
*
* @param Request $request
* @param Submission $submission
* @param Publication $publication
* @param Galley $articleGalley (optional)
* @param bool $isEditable (optional, default = true)
*/
public function __construct($request, $submission, $publication, $articleGalley = null, bool $isEditable = true)
{
parent::__construct('controllers/grid/articleGalleys/form/articleGalleyForm.tpl');
$this->_submission = $submission;
$this->_publication = $publication;
$this->_articleGalley = $articleGalley;
$this->_isEditable = $isEditable;
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'label', 'required', 'editor.issues.galleyLabelRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'urlPath', 'optional', 'validator.alpha_dash_period', '/^[a-zA-Z0-9]+([\\.\\-_][a-zA-Z0-9]+)*$/'));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
// Ensure a locale is provided and valid
$journal = $request->getJournal();
$this->addCheck(
new \PKP\form\validation\FormValidator(
$this,
'locale',
'required',
'editor.issues.galleyLocaleRequired'
),
function ($locale) use ($journal) {
return in_array($locale, $journal->getSupportedSubmissionLocaleNames());
}
);
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
if ($this->_articleGalley) {
$articleGalleyFile = $this->_articleGalley->getFile();
$templateMgr->assign([
'representationId' => $this->_articleGalley->getId(),
'articleGalley' => $this->_articleGalley,
'articleGalleyFile' => $articleGalleyFile,
'supportsDependentFiles' => $articleGalleyFile ? Repo::submissionFile()->supportsDependentFiles($articleGalleyFile) : null,
]);
}
$context = $request->getContext();
$templateMgr->assign([
'supportedLocales' => $context->getSupportedSubmissionLocaleNames(),
'submissionId' => $this->_submission->getId(),
'publicationId' => $this->_publication->getId(),
'formDisabled' => !$this->_isEditable
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::validate
*/
public function validate($callHooks = true)
{
// Validate the urlPath
if (strlen((string) $this->getData('urlPath'))) {
if (ctype_digit((string) $this->getData('urlPath'))) {
$this->addError('urlPath', __('publication.urlPath.numberInvalid'));
$this->addErrorField('urlPath');
} else {
$existingGalley = Repo::galley()->getByUrlPath((string) $this->getData('urlPath'), $this->_publication);
if ($existingGalley && $this->_articleGalley?->getId() !== $existingGalley->getId()) {
$this->addError('urlPath', __('publication.urlPath.duplicate'));
$this->addErrorField('urlPath');
}
}
}
if (!$this->_isEditable) {
$this->addError('', __('galley.cantEditPublished'));
}
return parent::validate($callHooks);
}
/**
* Initialize form data from current galley (if applicable).
*/
public function initData()
{
if ($this->_articleGalley) {
$this->_data = [
'label' => $this->_articleGalley->getLabel(),
'locale' => $this->_articleGalley->getLocale(),
'urlPath' => $this->_articleGalley->getData('urlPath'),
'urlRemote' => $this->_articleGalley->getData('urlRemote'),
];
} else {
$this->_data = [];
}
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(
[
'label',
'locale',
'urlPath',
'urlRemote',
]
);
}
/**
* Save changes to the galley.
*
* @return Galley The resulting article galley.
*/
public function execute(...$functionArgs)
{
$data = [
'publicationId' => $this->_publication->getId(),
'label' => $this->getData('label'),
'locale' => $this->getData('locale'),
'urlPath' => strlen($urlPath = (string) $this->getData('urlPath')) ? $urlPath : null,
'urlRemote' => strlen($urlRemote = (string) $this->getData('urlRemote')) ? $urlRemote : null
];
if ($this->_articleGalley) {
// Update galley in the db
Repo::galley()->edit($this->_articleGalley, $data);
$articleGalleyId = $this->_articleGalley->getId();
} else {
// Create a new galley
$articleGalleyId = Repo::galley()->add(Repo::galley()->newDataObject($data));
}
parent::execute(...$functionArgs);
return $this->_articleGalley = Repo::galley()->get($articleGalleyId);
}
}
@@ -0,0 +1,49 @@
<?php
/**
* @file controllers/grid/issueGalleys/IssueGalleyGridCellProvider.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 IssueGalleyGridCellProvider
*
* @ingroup issue_galley
*
* @brief Grid cell provider for the issue galleys grid
*/
namespace APP\controllers\grid\issueGalleys;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
use PKP\facades\Locale;
class IssueGalleyGridCellProvider extends GridCellProvider
{
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$issueGalley = $row->getData();
$columnId = $column->getId();
assert(is_a($issueGalley, 'IssueGalley'));
assert(!empty($columnId));
switch ($columnId) {
case 'label': return ['label' => $issueGalley->getLabel()];
case 'locale': return ['label' => Locale::getMetadata($issueGalley->getLocale())->getDisplayName()];
case 'publicGalleyId': return ['label' => $issueGalley->getStoredPubId('publisher-id')];
default: assert(false);
break;
}
}
}
@@ -0,0 +1,323 @@
<?php
/**
* @file controllers/grid/issueGalleys/IssueGalleyGridHandler.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 IssueGalleyGridHandler
*
* @ingroup issue_galley
*
* @brief Handle issues grid requests.
*/
namespace APP\controllers\grid\issueGalleys;
use APP\controllers\grid\issues\form\IssueGalleyForm;
use APP\core\Application;
use APP\core\Request;
use APP\file\IssueFileManager;
use APP\issue\IssueGalleyDAO;
use APP\security\authorization\OjsIssueGalleyRequiredPolicy;
use APP\security\authorization\OjsIssueRequiredPolicy;
use PKP\controllers\grid\feature\OrderGridItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\file\TemporaryFileManager;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
class IssueGalleyGridHandler extends GridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
[
'fetchGrid', 'fetchRow', 'saveSequence',
'add', 'edit', 'upload', 'download', 'update', 'delete'
]
);
}
//
// Implement template methods from PKPHandler
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
$this->addPolicy(new OjsIssueRequiredPolicy($request, $args));
// If a signoff ID was specified, authorize it.
if ($request->getUserVar('issueGalleyId')) {
$this->addPolicy(new OjsIssueGalleyRequiredPolicy($request, $args));
}
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::getDataElementSequence()
*/
public function getDataElementSequence($issueGalley)
{
return $issueGalley->getSequence();
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementSequence($request, $rowId, $gridDataElement, $newSequence)
{
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
$gridDataElement->setSequence($newSequence);
$issueGalleyDao->updateObject($gridDataElement);
}
/**
* @copydoc GridHandler::addFeatures()
*/
public function initFeatures($request, $args)
{
return [new OrderGridItemsFeature()];
}
/**
* @copydoc GridDataProvider::getRequestArgs()
*/
public function getRequestArgs()
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$issueGalley = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE_GALLEY);
$requestArgs = (array) parent::getRequestArgs();
$requestArgs['issueId'] = $issue->getId();
if ($issueGalley) {
$requestArgs['issueGalleyId'] = $issueGalley->getId();
}
return $requestArgs;
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Add action
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'add',
new AjaxModal(
$router->url(
$request,
null,
null,
'add',
null,
array_merge($this->getRequestArgs(), ['gridId' => $this->getId()])
),
__('grid.action.addIssueGalley'),
'modal_add'
),
__('grid.action.addIssueGalley'),
'add_category'
)
);
// Grid columns.
$issueGalleyGridCellProvider = new IssueGalleyGridCellProvider();
// Issue identification
$this->addColumn(
new GridColumn(
'label',
'submission.layout.galleyLabel',
null,
null,
$issueGalleyGridCellProvider
)
);
// Language, if more than one is supported
$journal = $request->getJournal();
if (count($journal->getSupportedLocaleNames()) > 1) {
$this->addColumn(
new GridColumn(
'locale',
'common.language',
null,
null,
$issueGalleyGridCellProvider
)
);
}
// Public ID, if enabled
$this->addColumn(
new GridColumn(
'publicGalleyId',
'submission.publisherId',
null,
null,
$issueGalleyGridCellProvider
)
);
}
/**
* Get the row handler - override the default row handler
*
* @return IssueGalleyGridRow
*/
protected function getRowInstance()
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
return new IssueGalleyGridRow($issue->getId());
}
//
// Public operations
//
/**
* An action to add a new issue
*
* @param array $args
* @param Request $request
*/
public function add($args, $request)
{
// Calling editIssueData with an empty ID will add
// a new issue.
return $this->edit($args, $request);
}
/**
* An action to edit a issue galley
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function edit($args, $request)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$issueGalley = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE_GALLEY);
$issueGalleyForm = new IssueGalleyForm($request, $issue, $issueGalley);
$issueGalleyForm->initData();
return new JSONMessage(true, $issueGalleyForm->fetch($request));
}
/**
* An action to upload an issue galley file.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function upload($args, $request)
{
$user = $request->getUser();
$temporaryFileManager = new TemporaryFileManager();
$temporaryFile = $temporaryFileManager->handleUpload('uploadedFile', $user->getId());
if ($temporaryFile) {
$json = new JSONMessage(true);
$json->setAdditionalAttributes([
'temporaryFileId' => $temporaryFile->getId()
]);
return $json;
} else {
return new JSONMessage(false, __('common.uploadFailed'));
}
}
/**
* An action to download an issue galley
*
* @param array $args
* @param Request $request
*
* @return string Serialized JSON object
*/
public function download($args, $request)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$issueGalley = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE_GALLEY);
$issueFileManager = new IssueFileManager($issue->getId());
return $issueFileManager->downloadById($issueGalley->getFileId());
}
/**
* Update a issue
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function update($args, $request)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$issueGalley = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE_GALLEY);
$issueGalleyForm = new IssueGalleyForm($request, $issue, $issueGalley);
$issueGalleyForm->readInputData();
if ($issueGalleyForm->validate()) {
$issueId = $issueGalleyForm->execute();
return DAO::getDataChangedEvent($issueId);
}
return new JSONMessage(false);
}
/**
* Removes an issue galley
*
* @param array $args
* @param Request $request
*/
public function delete($args, $request)
{
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
$issueGalley = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE_GALLEY);
if ($issueGalley && $request->checkCSRF()) {
$issueGalleyDao->deleteObject($issueGalley);
return DAO::getDataChangedEvent();
}
return new JSONMessage(false);
}
/**
* @copydoc GridHandler::loadData
*/
protected function loadData($request, $filter)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
return $issueGalleyDao->getByIssueId($issue->getId());
}
}
@@ -0,0 +1,103 @@
<?php
/**
* @file controllers/grid/issueGalleys/IssueGalleyGridRow.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 IssueGalleyGridRow
*
* @ingroup issue_galley
*
* @brief Handle issue galley grid row requests.
*/
namespace APP\controllers\grid\issueGalleys;
use PKP\controllers\grid\GridRow;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class IssueGalleyGridRow extends GridRow
{
/**
* Constructor
*/
public function __construct($issueId)
{
parent::__construct();
$this->setRequestArgs(
array_merge(
((array) $this->getRequestArgs()),
['issueId' => $issueId]
)
);
}
//
// Overridden template methods
//
/**
* @copydoc GridRow::initialize
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
// Is this a new row or an existing row?
$issueGalleyId = $this->getId();
if (!empty($issueGalleyId) && is_numeric($issueGalleyId)) {
$issue = $this->getData();
assert(is_a($issue, 'IssueGalley'));
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'edit',
new AjaxModal(
$router->url(
$request,
null,
null,
'edit',
null,
array_merge($this->getRequestArgs(), ['issueGalleyId' => $issueGalleyId])
),
__('editor.issues.editIssueGalley'),
'modal_edit',
true
),
__('grid.action.edit'),
'edit'
)
);
$this->addAction(
new LinkAction(
'delete',
new RemoteActionConfirmationModal(
$request->getSession(),
__('common.confirmDelete'),
__('grid.action.delete'),
$router->url(
$request,
null,
null,
'delete',
null,
array_merge($this->getRequestArgs(), ['issueGalleyId' => $issueGalleyId])
),
'modal_delete'
),
__('grid.action.delete'),
'delete'
)
);
}
}
}
@@ -0,0 +1,131 @@
<?php
/**
* @file controllers/grid/issues/IssueGridHandler.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 BackIssueGridHandler
*
* @ingroup controllers_grid_issues
*
* @brief Handle issues grid requests.
*/
namespace APP\controllers\grid\issues;
use APP\facades\Repo;
use APP\issue\Collector;
use PKP\controllers\grid\feature\OrderGridItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\security\Role;
class BackIssueGridHandler extends IssueGridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['saveSequence']
);
}
//
// Implement template methods from PKPHandler
//
/**
* @copydoc IssueGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Basic grid configuration.
$this->setTitle('editor.issues.backIssues');
}
/**
* Private function to add central columns to the grid.
*
* @param IssueGridCellProvider $issueGridCellProvider
*/
protected function _addCenterColumns($issueGridCellProvider)
{
// Published state
$this->addColumn(
new GridColumn(
'published',
'editor.issues.published',
null,
null,
$issueGridCellProvider
)
);
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementSequence($request, $rowId, $gridDataElement, $newSequence)
{
Repo::issue()->dao->moveCustomIssueOrder($gridDataElement->getJournalId(), $gridDataElement->getId(), $newSequence);
}
/**
* @copydoc GridHandler::getDataElementSequence()
*/
public function getDataElementSequence($gridDataElement)
{
$customOrder = Repo::issue()->dao->getCustomIssueOrder($gridDataElement->getJournalId(), $gridDataElement->getId());
if ($customOrder !== null) {
return $customOrder;
}
$currentIssue = Repo::issue()->getCurrent($gridDataElement->getJournalId());
if ($currentIssue != null && $gridDataElement->getId() == $currentIssue->getId()) {
return 0;
}
return $gridDataElement->getDatePublished();
}
/**
* @copydoc GridHandler::addFeatures()
*/
public function initFeatures($request, $args)
{
return [new OrderGridItemsFeature()];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$journal = $request->getJournal();
return Repo::issue()->getCollector()
->filterByContextIds([$journal->getId()])
->filterByPublished(true)
->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES)
->getMany()
->toArray();
}
/**
* Get the js handler for this component.
*
* @return string
*/
public function getJSHandler()
{
return '$.pkp.controllers.grid.issues.BackIssueGridHandler';
}
}
@@ -0,0 +1,82 @@
<?php
/**
* @file controllers/grid/issues/IssueGridHandler.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 ExportableIssuesListGridHandler
*
* @ingroup controllers_grid_issues
*
* @brief Handle exportable issues grid requests.
*/
namespace APP\controllers\grid\issues;
use APP\facades\Repo;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\feature\selectableItems\SelectableItemsFeature;
use PKP\controllers\grid\GridRow;
class ExportableIssuesListGridHandler extends IssueGridHandler
{
//
// Implemented methods from GridHandler.
//
/**
* @copydoc GridHandler::isDataElementSelected()
*/
public function isDataElementSelected($gridDataElement)
{
return false; // Nothing is selected by default
}
/**
* @copydoc GridHandler::getSelectName()
*/
public function getSelectName()
{
return 'selectedIssues';
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$journal = $request->getJournal();
// Handle grid paging (deprecated style)
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
$collector = Repo::issue()->getCollector()
->filterByContextIds([$journal->getId()]);
$totalCount = $collector->getCount();
$collector->limit($rangeInfo->getCount());
$collector->offset($rangeInfo->getOffset() + max(0, $rangeInfo->getPage() - 1) * $rangeInfo->getCount());
return new \PKP\core\VirtualArrayIterator($collector->getMany()->toArray(), $totalCount, $rangeInfo->getPage(), $rangeInfo->getCount());
}
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new SelectableItemsFeature(), new PagingFeature()];
}
/**
* Get the row handler - override the parent row handler. We do not need grid row actions.
*
* @return GridRow
*/
protected function getRowInstance()
{
return new GridRow();
}
}
@@ -0,0 +1,79 @@
<?php
/**
* @file controllers/grid/issues/IssueGridHandler.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 FutureIssueGridHandler
*
* @ingroup controllers_grid_issues
*
* @brief Handle issues grid requests.
*/
namespace APP\controllers\grid\issues;
use APP\facades\Repo;
use APP\issue\Collector;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
class FutureIssueGridHandler extends IssueGridHandler
{
//
// Implement template methods from PKPHandler
//
/**
* @copydoc IssueGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
// Basic grid configuration.
$this->setTitle('editor.issues.futureIssues');
parent::initialize($request, $args);
// Add Create Issue action
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'addIssue',
new AjaxModal(
$router->url($request, null, null, 'addIssue', null, ['gridId' => $this->getId()]),
__('grid.action.addIssue'),
'modal_manage'
),
__('grid.action.addIssue'),
'add_category'
)
);
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$journal = $request->getJournal();
return Repo::issue()->getCollector()
->filterByContextIds([$journal->getId()])
->filterByPublished(false)
->orderBy(Collector::ORDERBY_UNPUBLISHED_ISSUES)
->getMany();
}
/**
* Get the js handler for this component.
*
* @return string
*/
public function getJSHandler()
{
return '$.pkp.controllers.grid.issues.FutureIssueGridHandler';
}
}
@@ -0,0 +1,102 @@
<?php
/**
* @file controllers/grid/issues/IssueGridCellProvider.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 IssueGridCellProvider
*
* @ingroup controllers_grid_issues
*
* @brief Grid cell provider for the issue management grid
*/
namespace APP\controllers\grid\issues;
use APP\core\Application;
use APP\issue\Issue;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\core\PKPString;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
class IssueGridCellProvider extends GridCellProvider
{
/** @var string */
public $dateFormatShort;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dateFormatShort = PKPString::convertStrftimeFormat(Application::get()->getRequest()->getContext()->getLocalizedDateFormatShort());
}
/**
* Get cell actions associated with this row/column combination
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array an array of LinkAction instances
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
if ($column->getId() == 'identification') {
$issue = $row->getData();
assert(is_a($issue, 'Issue'));
$router = $request->getRouter();
return [
new LinkAction(
'edit',
new AjaxModal(
$router->url($request, null, null, 'editIssue', null, ['issueId' => $issue->getId()]),
__('editor.issues.editIssue', ['issueIdentification' => htmlspecialchars($issue->getIssueIdentification())]),
'modal_edit',
true
),
$issue->getIssueIdentification()
)
];
}
return [];
}
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$issue = $row->getData(); /** @var Issue $issue */
$columnId = $column->getId();
assert(is_a($issue, 'Issue'));
assert(!empty($columnId));
switch ($columnId) {
case 'identification':
return ['label' => '']; // Title returned as action
case 'published':
$datePublished = $issue->getDatePublished();
if ($datePublished) {
$datePublished = strtotime($datePublished);
}
return ['label' => $datePublished ? date($this->dateFormatShort, $datePublished) : ''];
case 'numArticles':
return ['label' => $issue->getNumArticles()];
default: assert(false);
break;
}
}
}
+146
View File
@@ -0,0 +1,146 @@
<?php
/**
* @file controllers/grid/issues/IssueGridRow.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 IssueGridRow
*
* @ingroup controllers_grid_issues
*
* @brief Handle issue grid row requests.
*/
namespace APP\controllers\grid\issues;
use APP\facades\Repo;
use PKP\controllers\grid\GridRow;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\OpenWindowAction;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class IssueGridRow extends GridRow
{
//
// Overridden template methods
//
/**
* @copydoc GridRow::initialize
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
// Is this a new row or an existing row?
$issueId = $this->getId();
if (!empty($issueId) && is_numeric($issueId)) {
$issue = $this->getData();
assert(is_a($issue, 'Issue'));
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'edit',
new AjaxModal(
$router->url($request, null, null, 'editIssue', null, ['issueId' => $issueId]),
__('editor.issues.editIssue', ['issueIdentification' => htmlspecialchars($issue->getIssueIdentification())]),
'modal_edit',
true
),
__('grid.action.edit'),
'edit'
)
);
$dispatcher = $request->getDispatcher();
$this->addAction(
new LinkAction(
$issue->getDatePublished() ? 'viewIssue' : 'previewIssue',
new OpenWindowAction(
$dispatcher->url($request, PKPApplication::ROUTE_PAGE, null, 'issue', 'view', [$issueId])
),
__($issue->getDatePublished() ? 'grid.action.viewIssue' : 'grid.action.previewIssue'),
'information'
)
);
if ($issue->getDatePublished()) {
$this->addAction(
new LinkAction(
'unpublish',
new RemoteActionConfirmationModal(
$request->getSession(),
__('editor.issues.confirmUnpublish'),
__('editor.issues.unpublishIssue'),
$router->url($request, null, null, 'unpublishIssue', null, ['issueId' => $issueId]),
'modal_delete'
),
__('editor.issues.unpublishIssue'),
'delete'
)
);
} else {
$this->addAction(
new LinkAction(
'publish',
new AjaxModal(
$router->url(
$request,
null,
null,
'publishIssue',
null,
['issueId' => $issueId]
),
__('editor.issues.publishIssue'),
'modal_confirm'
),
__('editor.issues.publishIssue'),
'advance'
)
);
}
$currentIssue = Repo::issue()->getCurrent($issue->getJournalId());
$isCurrentIssue = $currentIssue != null && $issue->getId() == $currentIssue->getId();
if ($issue->getDatePublished() && !$isCurrentIssue) {
$this->addAction(
new LinkAction(
'setCurrentIssue',
new RemoteActionConfirmationModal(
$request->getSession(),
__('editor.issues.confirmSetCurrentIssue'),
__('editor.issues.currentIssue'),
$router->url($request, null, null, 'setCurrentIssue', null, ['issueId' => $issueId]),
'modal_delete'
),
__('editor.issues.currentIssue'),
'delete'
)
);
}
$this->addAction(
new LinkAction(
'delete',
new RemoteActionConfirmationModal(
$request->getSession(),
__('common.confirmDelete'),
__('grid.action.delete'),
$router->url($request, null, null, 'deleteIssue', null, ['issueId' => $issueId]),
'modal_delete'
),
__('grid.action.delete'),
'delete'
)
);
}
}
}
@@ -0,0 +1,104 @@
<?php
/**
* @file controllers/grid/issues/form/IssueAccessForm.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 IssueAccessForm
*
* @ingroup controllers_grid_issues_form
*
* @see Issue
*
* @brief Form to edit an issue's access settings
*/
namespace APP\controllers\grid\issues\form;
use APP\facades\Repo;
use APP\issue\Issue;
use APP\template\TemplateManager;
use PKP\form\Form;
use PKP\plugins\Hook;
class IssueAccessForm extends Form
{
/** @var Issue current issue */
public $_issue;
/**
* Constructor.
*
* @param Issue $issue
*/
public function __construct($issue)
{
parent::__construct('controllers/grid/issues/form/issueAccessForm.tpl');
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
$this->_issue = $issue;
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'accessOptions' => [
Issue::ISSUE_ACCESS_OPEN => 'editor.issues.openAccess',
Issue::ISSUE_ACCESS_SUBSCRIPTION => 'editor.issues.subscription',
],
'issueId' => $this->_issue->getId(),
]);
return parent::fetch($request, $template, $display);
}
/**
* Initialize form data from current issue.
*/
public function initData()
{
$this->_data = [
'accessStatus' => $this->_issue->getAccessStatus(),
'openAccessDate' => $this->_issue->getOpenAccessDate(),
];
parent::initData();
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars([
'accessStatus',
'openAccessDate',
]);
}
/**
* @copydoc Form::execute()
*
* @return int Issue ID for created/updated issue
*/
public function execute(...$functionArgs)
{
$this->_issue->setAccessStatus($this->getData('accessStatus') ? $this->getData('accessStatus') : Issue::ISSUE_ACCESS_OPEN);
if ($openAccessDate = $this->getData('openAccessDate')) {
$this->_issue->setOpenAccessDate($openAccessDate);
} else {
$this->_issue->setOpenAccessDate(null);
}
Hook::call('IssueAccessForm::execute', [$this, $this->_issue]);
Repo::issue()->edit($this->_issue, []);
parent::execute(...$functionArgs);
}
}
+281
View File
@@ -0,0 +1,281 @@
<?php
/**
* @file controllers/grid/issues/form/IssueForm.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 IssueForm
*
* @ingroup controllers_grid_issues_form
*
* @see Issue
*
* @brief Form to create or edit an issue
*/
namespace APP\controllers\grid\issues\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\file\PublicFileManager;
use APP\issue\Issue;
use APP\template\TemplateManager;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\file\TemporaryFileDAO;
use PKP\form\Form;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class IssueForm extends Form
{
/** @var Issue current issue */
public $issue;
/**
* Constructor.
*
* @param Issue $issue (optional)
*/
public function __construct($issue = null)
{
parent::__construct('controllers/grid/issues/form/issueForm.tpl');
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'volume', 'optional', 'editor.issues.volumeRequired', '/^[0-9]+$/i'));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'showVolume', 'optional', 'editor.issues.volumeRequired', function ($showVolume) use ($form) {
return !$showVolume || $form->getData('volume') ? true : false;
}));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'showNumber', 'optional', 'editor.issues.numberRequired', function ($showNumber) use ($form) {
return !$showNumber || $form->getData('number') ? true : false;
}));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'showYear', 'optional', 'editor.issues.yearRequired', function ($showYear) use ($form) {
return !$showYear || $form->getData('year') ? true : false;
}));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'showTitle', 'optional', 'editor.issues.titleRequired', function ($showTitle) use ($form) {
return !$showTitle || implode('', $form->getData('title')) != '' ? true : false;
}));
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'urlPath', 'optional', 'validator.alpha_dash_period', '/^[a-zA-Z0-9]+([\\.\\-_][a-zA-Z0-9]+)*$/'));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
$this->issue = $issue;
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
if ($this->issue) {
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'issue' => $this->issue,
'issueId' => $this->issue->getId(),
]);
// Cover image delete link action
if ($coverImage = $this->issue->getCoverImage(Locale::getLocale())) {
$templateMgr->assign(
'deleteCoverImageLinkAction',
new LinkAction(
'deleteCoverImage',
new RemoteActionConfirmationModal(
$request->getSession(),
__('common.confirmDelete'),
null,
$request->getRouter()->url(
$request,
null,
null,
'deleteCoverImage',
null,
[
'coverImage' => $coverImage,
'issueId' => $this->issue->getId(),
]
),
'modal_delete'
),
__('common.delete'),
null
)
);
}
}
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::validate()
*/
public function validate($callHooks = true)
{
if ($temporaryFileId = $this->getData('temporaryFileId')) {
$request = Application::get()->getRequest();
$user = $request->getUser();
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
$temporaryFile = $temporaryFileDao->getTemporaryFile($temporaryFileId, $user->getId());
$publicFileManager = new PublicFileManager();
if (!$publicFileManager->getImageExtension($temporaryFile->getFileType())) {
$this->addError('coverImage', __('editor.issues.invalidCoverImageFormat'));
}
}
// Check if urlPath is already being used
if (strlen((string) $this->getData('urlPath'))) {
if (ctype_digit((string) $this->getData('urlPath'))) {
$this->addError('urlPath', __('publication.urlPath.numberInvalid'));
$this->addErrorField('urlPath');
} else {
$issue = Repo::issue()->getByBestId($this->getData('urlPath'), Application::get()->getRequest()->getContext()->getId());
if ($issue && $this->issue?->getId() !== $issue->getId()) {
$this->addError('urlPath', __('publication.urlPath.duplicate'));
$this->addErrorField('urlPath');
}
}
}
return parent::validate($callHooks);
}
/**
* @copydoc Form::initData()
*/
public function initData()
{
if (isset($this->issue)) {
$locale = Locale::getLocale();
$this->_data = [
'title' => $this->issue->getTitle(null), // Localized
'volume' => $this->issue->getVolume(),
'number' => $this->issue->getNumber(),
'year' => $this->issue->getYear(),
'datePublished' => $this->issue->getDatePublished(),
'description' => $this->issue->getDescription(null), // Localized
'showVolume' => $this->issue->getShowVolume(),
'showNumber' => $this->issue->getShowNumber(),
'showYear' => $this->issue->getShowYear(),
'showTitle' => $this->issue->getShowTitle(),
'coverImage' => $this->issue->getCoverImage($locale),
'coverImageAltText' => $this->issue->getCoverImageAltText($locale),
'urlPath' => $this->issue->getData('urlPath'),
];
parent::initData();
} else {
$this->_data = [
'showVolume' => 1,
'showNumber' => 1,
'showYear' => 1,
'showTitle' => 1,
];
}
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars([
'title',
'volume',
'number',
'year',
'description',
'showVolume',
'showNumber',
'showYear',
'showTitle',
'temporaryFileId',
'coverImageAltText',
'datePublished',
'urlPath',
]);
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'issueForm', 'required', 'editor.issues.issueIdentificationRequired', function () use ($form) {
return $form->getData('showVolume') || $form->getData('showNumber') || $form->getData('showYear') || $form->getData('showTitle');
}));
}
/**
* Save issue settings.
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$journal = $request->getJournal();
if ($this->issue) {
$isNewIssue = false;
$issue = $this->issue;
} else {
$issue = Repo::issue()->newDataObject();
$this->issue = $issue;
switch ($journal->getData('publishingMode')) {
case \APP\journal\Journal::PUBLISHING_MODE_SUBSCRIPTION:
case \APP\journal\Journal::PUBLISHING_MODE_NONE:
$issue->setAccessStatus(Issue::ISSUE_ACCESS_SUBSCRIPTION);
break;
case \APP\journal\Journal::PUBLISHING_MODE_OPEN:
default:
$issue->setAccessStatus(Issue::ISSUE_ACCESS_OPEN);
break;
}
$isNewIssue = true;
}
$volume = $this->getData('volume');
$number = $this->getData('number');
$year = $this->getData('year');
$issue->setJournalId($journal->getId());
$issue->setTitle($this->getData('title'), null); // Localized
$issue->setVolume(empty($volume) ? null : $volume);
$issue->setNumber(empty($number) ? null : $number);
$issue->setYear(empty($year) ? null : $year);
if (!$isNewIssue) {
$issue->setDatePublished($this->getData('datePublished'));
}
$issue->setDescription($this->getData('description'), null); // Localized
$issue->setShowVolume((int) $this->getData('showVolume'));
$issue->setShowNumber((int) $this->getData('showNumber'));
$issue->setShowYear((int) $this->getData('showYear'));
$issue->setShowTitle((int) $this->getData('showTitle'));
$issue->setData('urlPath', strlen($urlPath = (string) $this->getData('urlPath')) ? $urlPath : null);
// If it is a new issue, first insert it, then update the cover
// because the cover name needs an issue id.
if ($isNewIssue) {
$issue->setPublished(0);
Repo::issue()->add($issue);
}
$locale = Locale::getLocale();
// Copy an uploaded cover file for the issue, if there is one.
if ($temporaryFileId = $this->getData('temporaryFileId')) {
$user = $request->getUser();
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
$temporaryFile = $temporaryFileDao->getTemporaryFile($temporaryFileId, $user->getId());
$publicFileManager = new PublicFileManager();
$newFileName = 'cover_issue_' . $issue->getId() . '_' . $locale . $publicFileManager->getImageExtension($temporaryFile->getFileType());
$journal = $request->getJournal();
$publicFileManager->copyContextFile($journal->getId(), $temporaryFile->getFilePath(), $newFileName);
$issue->setCoverImage($newFileName, $locale);
Repo::issue()->edit($issue, []);
}
$issue->setCoverImageAltText($this->getData('coverImageAltText'), $locale);
parent::execute(...$functionArgs);
Repo::issue()->edit($issue, []);
}
}
@@ -0,0 +1,237 @@
<?php
/**
* @file controllers/grid/issues/form/IssueGalleyForm.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 IssueGalleyForm
*
* @ingroup issue_galley
*
* @see IssueGalley
*
* @brief Issue galley editing form.
*/
namespace APP\controllers\grid\issues\form;
use APP\core\Application;
use APP\core\Request;
use APP\file\IssueFileManager;
use APP\issue\Issue;
use APP\issue\IssueGalley;
use APP\issue\IssueGalleyDAO;
use APP\journal\JournalDAO;
use APP\template\TemplateManager;
use PKP\db\DAORegistry;
use PKP\file\TemporaryFileDAO;
use PKP\form\Form;
class IssueGalleyForm extends Form
{
/** @var Issue the issue the galley belongs to */
public $_issue = null;
/** @var IssueGalley current galley */
public $_issueGalley = null;
/**
* Constructor.
*
* @param Request $request
* @param Issue $issue
* @param IssueGalley $issueGalley (optional)
*/
public function __construct($request, $issue, $issueGalley = null)
{
parent::__construct('controllers/grid/issueGalleys/form/issueGalleyForm.tpl');
$this->_issue = $issue;
$this->_issueGalley = $issueGalley;
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'label', 'required', 'editor.issues.galleyLabelRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'urlPath', 'optional', 'validator.alpha_dash_period', '/^[a-zA-Z0-9]+([\\.\\-_][a-zA-Z0-9]+)*$/'));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
// Ensure a locale is provided and valid
$journal = $request->getJournal();
$this->addCheck(new \PKP\form\validation\FormValidatorCustom(
$this,
'galleyLocale',
'required',
'editor.issues.galleyLocaleRequired',
function ($galleyLocale) use ($journal) {
return in_array($galleyLocale, $journal->getSupportedFormLocales());
}
));
if (!$issueGalley) {
// A file must be uploaded with a newly-created issue galley.
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'temporaryFileId', 'required', 'form.fileRequired'));
}
}
/**
* @copydoc Form::fetch()
*
* @param Request $request
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$journal = $request->getJournal();
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'issueId' => $this->_issue->getId(),
'supportedLocales' => $journal->getSupportedLocaleNames(),
'enablePublisherId' => in_array('issueGalley', (array) $request->getContext()->getData('enablePublisherId')),
]);
if ($this->_issueGalley) {
$templateMgr->assign([
'issueGalleyId' => $this->_issueGalley->getId(),
'issueGalley' => $this->_issueGalley,
]);
}
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::validate
*/
public function validate($callHooks = true)
{
// Check if public galley ID is already being used
$request = Application::get()->getRequest();
$journal = $request->getJournal();
$journalDao = DAORegistry::getDAO('JournalDAO'); /** @var JournalDAO $journalDao */
$publicGalleyId = $this->getData('publicGalleyId');
if ($publicGalleyId) {
if (ctype_digit((string) $publicGalleyId)) {
$this->addError('publicGalleyId', __('editor.publicIdentificationNumericNotAllowed', ['publicIdentifier' => $publicGalleyId]));
$this->addErrorField('publicGalleyId');
} elseif ($journalDao->anyPubIdExists($journal->getId(), 'publisher-id', $publicGalleyId, Application::ASSOC_TYPE_ISSUE_GALLEY, $this->_issueGalley ? $this->_issueGalley->getId() : null, true)) {
$this->addError('publicGalleyId', __('editor.publicIdentificationExistsForTheSameType', ['publicIdentifier' => $publicGalleyId]));
$this->addErrorField('publicGalleyId');
}
}
if (strlen((string) $this->getData('urlPath'))) {
if (ctype_digit((string) $this->getData('urlPath'))) {
$this->addError('urlPath', __('publication.urlPath.numberInvalid'));
$this->addErrorField('urlPath');
} else {
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
$issueGalley = $issueGalleyDao->getByBestId($this->getData('urlPath'), $this->_issue->getId());
if ($issueGalley && $this->_issueGalley?->getId() !== $issueGalley->getId()) {
$this->addError('urlPath', __('publication.urlPath.duplicate'));
$this->addErrorField('urlPath');
}
}
}
return parent::validate($callHooks);
}
/**
* Initialize form data from current galley (if applicable).
*/
public function initData()
{
if ($this->_issueGalley) {
$this->_data = [
'label' => $this->_issueGalley->getLabel(),
'publicGalleyId' => $this->_issueGalley->getStoredPubId('publisher-id'),
'galleyLocale' => $this->_issueGalley->getLocale(),
'urlPath' => $this->_issueGalley->getData('urlPath'),
];
} else {
$this->_data = [];
}
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(
[
'label',
'publicGalleyId',
'galleyLocale',
'temporaryFileId',
'urlPath',
]
);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$issueFileManager = new IssueFileManager($this->_issue->getId());
$request = Application::get()->getRequest();
$user = $request->getUser();
$issueGalley = $this->_issueGalley;
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
// If a temporary file ID was specified (i.e. an upload occurred), get the file for later.
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
$temporaryFile = $temporaryFileDao->getTemporaryFile($this->getData('temporaryFileId'), $user->getId());
parent::execute(...$functionArgs);
if ($issueGalley) {
// Update an existing galley
$oldFileId = null;
if ($temporaryFile) {
$oldFileId = $issueGalley->getFileId();
// Upload new file
$issueFile = $issueFileManager->fromTemporaryFile($temporaryFile);
$issueGalley->setFileId($issueFile->getId());
}
$issueGalley->setLabel($this->getData('label'));
$issueGalley->setStoredPubId('publisher-id', $this->getData('publicGalleyId'));
$issueGalley->setLocale($this->getData('galleyLocale'));
$issueGalley->setData('urlPath', strlen($urlPath = (string) $this->getData('urlPath')) ? $urlPath : null);
// Update galley in the db
$issueGalleyDao->updateObject($issueGalley);
if ($oldFileId) {
// If the galley previously had a file, delete it
$issueFileManager->deleteById($oldFileId);
}
} else {
// Create a new galley
$issueGalleyFile = $issueFileManager->fromTemporaryFile($temporaryFile);
$issueGalley = $issueGalleyDao->newDataObject();
$issueGalley->setIssueId($this->_issue->getId());
$issueGalley->setFileId($issueGalleyFile->getId());
$issueGalley->setData('urlPath', $this->getData('urlPath'));
$issueGalley->setLabel($this->getData('label'));
$issueGalley->setLocale($this->getData('galleyLocale'));
$issueGalley->setStoredPubId('publisher-id', $this->getData('publicGalleyId'));
// Insert new galley into the db
$issueGalleyDao->insertObject($issueGalley);
$this->_issueGalley = $issueGalley;
}
return $this->_issueGalley->getId();
}
}
@@ -0,0 +1,23 @@
<?php
/**
* @file controllers/grid/navigationMenus/form/NavigationMenuItemsForm.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 NavigationMenuItemsForm
*
* @ingroup controllers_grid_navigationMenus
*
* @brief Form for managers to create/edit navigationMenuItems.
*/
namespace APP\controllers\grid\navigationMenus\form;
use PKP\controllers\grid\navigationMenus\form\PKPNavigationMenuItemsForm;
class NavigationMenuItemsForm extends PKPNavigationMenuItemsForm
{
}
@@ -0,0 +1,136 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportIssuesListGridCellProvider.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 PubIdExportIssuesListGridCellProvider
*
* @ingroup controllers_grid_pubIds
*
* @brief Class for a cell provider that can retrieve labels from issues with pub ids
*/
namespace APP\controllers\grid\pubIds;
use APP\core\Application;
use PKP\controllers\grid\DataObjectGridCellProvider;
use PKP\controllers\grid\GridHandler;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RedirectAction;
use PKP\plugins\ImportExportPlugin;
class PubIdExportIssuesListGridCellProvider extends DataObjectGridCellProvider
{
/** @var ImportExportPlugin */
public $_plugin;
public $_authorizedRoles;
/**
* Constructor
*
* @param null|mixed $authorizedRoles
*/
public function __construct($plugin, $authorizedRoles = null)
{
$this->_plugin = $plugin;
if ($authorizedRoles) {
$this->_authorizedRoles = $authorizedRoles;
}
parent::__construct();
}
//
// Template methods from GridCellProvider
//
/**
* Get cell actions associated with this row/column combination
*
* @copydoc GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
$publishedIssue = $row->getData();
$columnId = $column->getId();
assert(is_a($publishedIssue, 'Issue') && !empty($columnId));
switch ($columnId) {
case 'identification':
// Link to the issue edit modal
$application = Application::get();
$dispatcher = $application->getDispatcher();
return [
new LinkAction(
'edit',
new AjaxModal(
$dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.issues.BackIssueGridHandler', 'editIssue', null, ['issueId' => $publishedIssue->getId()]),
__('plugins.importexport.common.settings.DOIPluginSettings')
),
$publishedIssue->getIssueIdentification(),
null
)
];
case 'status':
$status = $publishedIssue->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($publishedIssue);
if ($status && array_key_exists($status, $statusActions)) {
assert(array_key_exists($status, $statusNames));
return [
new LinkAction(
'edit',
new RedirectAction(
$statusActions[$status],
'_blank'
),
$statusNames[$status]
)
];
}
}
return parent::getCellActions($request, $row, $column, $position);
}
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @copydoc DataObjectGridCellProvider::getTemplateVarsFromRowColumn()
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$publishedIssue = $row->getData();
$columnId = $column->getId();
assert(is_a($publishedIssue, 'Issue') && !empty($columnId));
switch ($columnId) {
case 'identification':
return ['label' => ''];
case 'published':
return ['label' => $publishedIssue->getDatePublished()];
case 'pubId':
return ['label' => $publishedIssue->getStoredPubId($this->_plugin->getPubIdType())];
case 'status':
$status = $publishedIssue->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($publishedIssue);
if ($status) {
if (array_key_exists($status, $statusActions)) {
$label = '';
} else {
assert(array_key_exists($status, $statusNames));
$label = $statusNames[$status];
}
} else {
$label = $statusNames[EXPORT_STATUS_NOT_DEPOSITED];
}
return ['label' => $label];
}
}
}
@@ -0,0 +1,247 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportIssuesListGridHandler.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 PubIdExportIssuesListGridHandler
*
* @ingroup controllers_grid_pubIds
*
* @brief Handle exportable issues with pub ids list grid requests.
*/
namespace APP\controllers\grid\pubIds;
use APP\core\Application;
use APP\plugins\PubIdPlugin;
use APP\plugins\PubObjectsExportPlugin;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\feature\selectableItems\SelectableItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\plugins\PluginRegistry;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;
class PubIdExportIssuesListGridHandler extends GridHandler
{
/** @var PubObjectsExportPlugin */
public $_plugin;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['fetchGrid', 'fetchRow']
);
}
//
// Implement template methods from PKPHandler
//
/**
* @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);
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Basic grid configuration.
$this->setTitle('plugins.importexport.common.export.issues');
$pluginCategory = $request->getUserVar('category');
$pluginPathName = $request->getUserVar('plugin');
// Allow for plugins that have already been loaded (e.g. by injection from a generic plugin)
$this->_plugin = PluginRegistry::getPlugin($pluginCategory, $pluginPathName);
// Otherwise, load the plugin as specified
/** @var PubIdPlugin */
$this->_plugin ??= PluginRegistry::loadPlugin($pluginCategory, $pluginPathName);
assert(isset($this->_plugin));
// Fetch the authorized roles.
$authorizedRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
// Grid columns.
$cellProvider = new PubIdExportIssuesListGridCellProvider($this->_plugin, $authorizedRoles);
$this->addColumn(
new GridColumn(
'identification',
'issue.issue',
null,
null,
$cellProvider,
['html' => true,
'alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT]
)
);
$this->addColumn(
new GridColumn(
'published',
'editor.issues.published',
null,
null,
$cellProvider,
['html' => true,
'alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT]
)
);
$this->addColumn(
new GridColumn(
'pubId',
null,
$this->_plugin->getPubIdDisplayType(),
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 15]
)
);
$this->addColumn(
new GridColumn(
'status',
'common.status',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 10]
)
);
}
//
// Implemented methods from GridHandler.
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new SelectableItemsFeature(), new PagingFeature()];
}
/**
* @copydoc GridHandler::getRequestArgs()
*/
public function getRequestArgs()
{
return array_merge(parent::getRequestArgs(), ['category' => $this->_plugin->getCategory(), 'plugin' => basename($this->_plugin->getPluginPath())]);
}
/**
* @copydoc GridHandler::isDataElementSelected()
*/
public function isDataElementSelected($gridDataElement)
{
return false; // Nothing is selected by default
}
/**
* @copydoc GridHandler::getSelectName()
*/
public function getSelectName()
{
return 'selectedIssues';
}
/**
* @copydoc GridHandler::getFilterForm()
*/
protected function getFilterForm()
{
return 'controllers/grid/pubIds/pubIdExportIssuesGridFilter.tpl';
}
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$statusNames = $this->_plugin->getStatusNames();
$allFilterData = array_merge(
$filterData,
[
'status' => $statusNames,
'gridId' => $this->getId(),
]
);
return parent::renderFilter($request, $allFilterData);
}
/**
* @copydoc GridHandler::getFilterSelectionData()
*/
public function getFilterSelectionData($request)
{
$statusId = (string) $request->getUserVar('statusId');
return [
'statusId' => $statusId,
];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$context = $request->getContext();
[$statusId] = $this->getFilterValues($filter);
$pubIdStatusSettingName = null;
if ($statusId) {
$pubIdStatusSettingName = $this->_plugin->getDepositStatusSettingName();
}
return \APP\facades\Repo::issue()->dao->getExportable(
$context->getId(),
$this->_plugin->getPubIdType(),
$pubIdStatusSettingName,
$statusId,
$this->getGridRangeInfo($request, $this->getId())
);
}
/**
* Process filter values, assigning default ones if
* none was set.
*
* @return array
*/
protected function getFilterValues($filter)
{
if (isset($filter['statusId']) && $filter['statusId'] != EXPORT_STATUS_ANY) {
$statusId = $filter['statusId'];
} else {
$statusId = null;
}
return [$statusId];
}
}
@@ -0,0 +1,166 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportRepresentationsListGridCellProvider.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 PubIdExportRepresentationsListGridCellProvider
*
* @ingroup controllers_grid_pubIds
*
* @brief Class for a cell provider that can retrieve labels from representations with pub ids
*/
namespace APP\controllers\grid\pubIds;
use APP\core\Application;
use APP\facades\Repo;
use PKP\controllers\grid\DataObjectGridCellProvider;
use PKP\controllers\grid\GridHandler;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RedirectAction;
use PKP\plugins\ImportExportPlugin;
class PubIdExportRepresentationsListGridCellProvider extends DataObjectGridCellProvider
{
/** @var ImportExportPlugin */
public $_plugin;
public $_authorizedRoles;
public $_titleColumn;
/**
* Constructor
*
* @param null|mixed $authorizedRoles
*/
public function __construct($plugin, $authorizedRoles = null)
{
$this->_plugin = $plugin;
if ($authorizedRoles) {
$this->_authorizedRoles = $authorizedRoles;
}
parent::__construct();
}
//
// Template methods from GridCellProvider
//
/**
* Get cell actions associated with this row/column combination
*
* @copydoc GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
$galley = $row->getData();
$columnId = $column->getId();
assert(is_a($galley, 'Galley') && !empty($columnId));
$publication = Repo::publication()->get($galley->getData('publicationId'));
$submission = Repo::submission()->get($publication->getData('submissionId'));
switch ($columnId) {
case 'title':
$this->_titleColumn = $column;
$title = $submission->getLocalizedTitle();
if (empty($title)) {
$title = __('common.untitled');
}
$authorsInTitle = $publication->getShortAuthorString();
$title = $authorsInTitle . '; ' . $title;
return [
new LinkAction(
'itemWorkflow',
new RedirectAction(
Repo::submission()->getWorkflowUrlByUserRoles($submission)
),
htmlspecialchars($title)
)
];
case 'issue':
$contextId = $submission->getContextId();
$issueId = $submission->getCurrentPublication()->getData('issueId');
$issue = Repo::issue()->get($issueId);
$issue = $issue->getJournalId() == $contextId ? $issue : null;
// Link to the issue edit modal
$application = Application::get();
$dispatcher = $application->getDispatcher();
return [
new LinkAction(
'edit',
new AjaxModal(
$dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.issues.BackIssueGridHandler', 'editIssue', null, ['issueId' => $issue->getId()]),
__('plugins.importexport.common.settings.DOIPluginSettings')
),
$issue->getIssueIdentification(),
null
)
];
case 'status':
$status = $galley->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($submission);
if ($status && array_key_exists($status, $statusActions)) {
assert(array_key_exists($status, $statusNames));
return [
new LinkAction(
'edit',
new RedirectAction(
$statusActions[$status],
'_blank'
),
htmlspecialchars($statusNames[$status])
)
];
}
}
return parent::getCellActions($request, $row, $column, $position);
}
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @copydoc DataObjectGridCellProvider::getTemplateVarsFromRowColumn()
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$submissionGalley = $row->getData();
$columnId = $column->getId();
assert(is_a($submissionGalley, 'Galley') && !empty($columnId));
switch ($columnId) {
case 'id':
return ['label' => $submissionGalley->getId()];
case 'title':
return ['label' => ''];
case 'issue':
return ['label' => ''];
case 'galley':
return ['label' => $submissionGalley->getGalleyLabel()];
case 'pubId':
return ['label' => $submissionGalley->getStoredPubId($this->_plugin->getPubIdType())];
case 'status':
$status = $submissionGalley->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($submissionGalley);
if ($status) {
if (array_key_exists($status, $statusActions)) {
$label = '';
} else {
assert(array_key_exists($status, $statusNames));
$label = $statusNames[$status];
}
} else {
$label = $statusNames[EXPORT_STATUS_NOT_DEPOSITED];
}
return ['label' => $label];
}
}
}
@@ -0,0 +1,331 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportRepresentationsListGridHandler.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 PubIdExportRepresentationsListGridHandler
*
* @ingroup controllers_grid_pubIds
*
* @brief Handle exportable representations with pub ids list grid requests.
*/
namespace APP\controllers\grid\pubIds;
use APP\core\Application;
use APP\facades\Repo;
use APP\issue\Collector;
use APP\plugins\PubObjectsExportPlugin;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\feature\selectableItems\SelectableItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\plugins\PluginRegistry;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;
class PubIdExportRepresentationsListGridHandler extends GridHandler
{
/** @var PubObjectsExportPlugin */
public $_plugin;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['fetchGrid', 'fetchRow']
);
}
//
// Implement template methods from PKPHandler
//
/**
* @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);
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
$context = $request->getContext();
// Basic grid configuration.
$this->setTitle('plugins.importexport.common.export.articles');
$pluginCategory = $request->getUserVar('category');
$pluginPathName = $request->getUserVar('plugin');
// Allow for plugins that have already been loaded (e.g. by injection from a generic plugin)
$this->_plugin = PluginRegistry::getPlugin($pluginCategory, $pluginPathName);
// Otherwise, load the plugin as specified
$this->_plugin ??= PluginRegistry::loadPlugin($pluginCategory, $pluginPathName);
assert(isset($this->_plugin));
// Fetch the authorized roles.
$authorizedRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
// Grid columns.
$cellProvider = new PubIdExportRepresentationsListGridCellProvider($this->_plugin, $authorizedRoles);
$this->addColumn(
new GridColumn(
'id',
null,
__('common.id'),
'controllers/grid/gridCell.tpl',
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 10]
)
);
$this->addColumn(
new GridColumn(
'title',
'grid.submission.itemTitle',
null,
null,
$cellProvider,
['html' => true,
'alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT]
)
);
$this->addColumn(
new GridColumn(
'issue',
'issue.issue',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 20]
)
);
$this->addColumn(
new GridColumn(
'galley',
'submission.layout.galleyLabel',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 20]
)
);
$this->addColumn(
new GridColumn(
'pubId',
null,
$this->_plugin->getPubIdDisplayType(),
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 15]
)
);
$this->addColumn(
new GridColumn(
'status',
'common.status',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 10]
)
);
}
//
// Implemented methods from GridHandler.
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new SelectableItemsFeature(), new PagingFeature()];
}
/**
* @copydoc GridHandler::getRequestArgs()
*/
public function getRequestArgs()
{
return array_merge(parent::getRequestArgs(), ['category' => $this->_plugin->getCategory(), 'plugin' => basename($this->_plugin->getPluginPath())]);
}
/**
* @copydoc GridHandler::isDataElementSelected()
*/
public function isDataElementSelected($gridDataElement)
{
return false; // Nothing is selected by default
}
/**
* @copydoc GridHandler::getSelectName()
*/
public function getSelectName()
{
return 'selectedRepresentations';
}
/**
* @copydoc GridHandler::getFilterForm()
*/
protected function getFilterForm()
{
return 'controllers/grid/pubIds/pubIdExportRepresentationsGridFilter.tpl';
}
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$context = $request->getContext();
$issues = Repo::issue()->getCollector()
->filterByContextIds([$context->getId()])
->filterByPublished(true)
->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES)
->getMany();
foreach ($issues as $issue) {
$issueOptions[$issue->getId()] = $issue->getIssueIdentification();
}
$issueOptions[0] = __('plugins.importexport.common.filter.issue');
ksort($issueOptions);
$statusNames = $this->_plugin->getStatusNames();
$filterColumns = $this->getFilterColumns();
$allFilterData = array_merge(
$filterData,
[
'columns' => $filterColumns,
'issues' => $issueOptions,
'status' => $statusNames,
'gridId' => $this->getId(),
]
);
return parent::renderFilter($request, $allFilterData);
}
/**
* @copydoc GridHandler::getFilterSelectionData()
*/
public function getFilterSelectionData($request)
{
$search = (string) $request->getUserVar('search');
$column = (string) $request->getUserVar('column');
$issueId = (int) $request->getUserVar('issueId');
$statusId = (string) $request->getUserVar('statusId');
return [
'search' => $search,
'column' => $column,
'issueId' => $issueId,
'statusId' => $statusId,
];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$context = $request->getContext();
[$search, $column, $issueId, $statusId] = $this->getFilterValues($filter);
$title = $author = null;
if ($column == 'title') {
$title = $search;
} elseif ($column == 'author') {
$author = $search;
}
$pubIdStatusSettingName = null;
if ($statusId) {
$pubIdStatusSettingName = $this->_plugin->getDepositStatusSettingName();
}
return Repo::galley()->dao->getExportable(
$context->getId(),
$this->_plugin->getPubIdType(),
$title,
$author,
$issueId,
$pubIdStatusSettingName,
$statusId,
$this->getGridRangeInfo($request, $this->getId())
);
}
//
// Own protected methods
//
/**
* Get which columns can be used by users to filter data.
*
* @return array
*/
protected function getFilterColumns()
{
return [
'title' => __('submission.title'),
'author' => __('submission.authors')
];
}
/**
* Process filter values, assigning default ones if
* none was set.
*
* @return array
*/
protected function getFilterValues($filter)
{
if (isset($filter['search']) && $filter['search']) {
$search = $filter['search'];
} else {
$search = null;
}
if (isset($filter['column']) && $filter['column']) {
$column = $filter['column'];
} else {
$column = null;
}
if (isset($filter['issueId']) && $filter['issueId']) {
$issueId = $filter['issueId'];
} else {
$issueId = null;
}
if (isset($filter['statusId']) && $filter['statusId'] != EXPORT_STATUS_ANY) {
$statusId = $filter['statusId'];
} else {
$statusId = null;
}
return [$search, $column, $issueId, $statusId];
}
}
@@ -0,0 +1,39 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportSubmissionsListGridCellProvider.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 PubIdExportSubmissionsListGridCellProvider
*
* @ingroup controllers_grid_pubIds
*
* @brief Class for a cell provider that can retrieve labels from submissions with pub ids
*/
namespace APP\controllers\grid\pubIds;
use APP\controllers\grid\submissions\ExportPublishedSubmissionsListGridCellProvider;
use APP\submission\Submission;
class PubIdExportSubmissionsListGridCellProvider extends ExportPublishedSubmissionsListGridCellProvider
{
/**
* @copydoc ExportPublishedSubmissionsListGridCellProvider::getTemplateVarsFromRowColumn()
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$submission = $row->getData();
$columnId = $column->getId();
assert($submission instanceof Submission && !empty($columnId));
switch ($columnId) {
case 'pubId':
return ['label' => $submission->getStoredPubId($this->_plugin->getPubIdType())];
}
return parent::getTemplateVarsFromRowColumn($row, $column);
}
}
@@ -0,0 +1,85 @@
<?php
/**
* @file controllers/grid/pubIds/PubIdExportSubmissionsListGridHandler.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 PubIdExportSubmissionsListGridHandler
*
* @ingroup controllers_grid_pubIds
*
* @brief Handle exportable submissions with pub ids list grid requests.
*/
namespace APP\controllers\grid\pubIds;
use APP\controllers\grid\submissions\ExportPublishedSubmissionsListGridHandler;
use APP\core\Application;
use APP\facades\Repo;
use PKP\controllers\grid\DataObjectGridCellProvider;
use PKP\controllers\grid\GridColumn;
class PubIdExportSubmissionsListGridHandler extends ExportPublishedSubmissionsListGridHandler
{
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$context = $request->getContext();
[$search, $column, $issueId, $statusId] = $this->getFilterValues($filter);
$title = $author = null;
if ($column == 'title') {
$title = $search;
} elseif ($column == 'author') {
$author = $search;
}
$pubIdStatusSettingName = null;
if ($statusId) {
$pubIdStatusSettingName = $this->_plugin->getDepositStatusSettingName();
}
return Repo::submission()->dao->getExportable(
$context->getId(),
$this->_plugin->getPubIdType(),
$title,
$author,
$issueId,
$pubIdStatusSettingName,
$statusId,
$this->getGridRangeInfo($request, $this->getId())
);
}
/**
* @copydoc ExportPublishedSubmissionsListGridHandler::getGridCellProvider()
*/
public function getGridCellProvider()
{
// Fetch the authorized roles.
$authorizedRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
return new PubIdExportSubmissionsListGridCellProvider($this->_plugin, $authorizedRoles);
}
/**
* Get the grid cell provider instance
*
* @return DataObjectGridCellProvider
*/
public function addAdditionalColumns($cellProvider)
{
$this->addColumn(
new GridColumn(
'pubId',
null,
$this->_plugin->getPubIdDisplayType(),
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 15]
)
);
}
}
@@ -0,0 +1,69 @@
<?php
/**
* @file controllers/grid/pubIds/form/AssignPublicIdentifiersForm.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 AssignPublicIdentifiersForm
*
* @ingroup controllers_grid_pubIds_form
*
* @brief Displays the assign pub id form.
*/
namespace APP\controllers\grid\pubIds\form;
use APP\template\TemplateManager;
use PKP\controllers\grid\pubIds\form\PKPAssignPublicIdentifiersForm;
class AssignPublicIdentifiersForm extends PKPAssignPublicIdentifiersForm
{
/**
* @var array Parameters to configure the form template.
*/
public $_formParams;
/**
* Constructor.
*
* @param string $template Form template
* @param object $pubObject
* @param bool $approval
* @param string $confirmationText
* @param array $formParams
*/
public function __construct($template, $pubObject, $approval, $confirmationText, $formParams = null)
{
parent::__construct($template, $pubObject, $approval, $confirmationText);
$this->_formParams = $formParams;
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('formParams', $this->getFormParams());
return parent::fetch($request, $template, $display);
}
//
// Getters and Setters
//
/**
* Get the extra form parameters.
*
* @return array
*/
public function getFormParams()
{
return $this->_formParams;
}
}
@@ -0,0 +1,106 @@
<?php
/**
* @file controllers/grid/settings/plugins/SettingsPluginGridHandler.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 SettingsPluginGridHandler
*
* @ingroup controllers_grid_settings_plugins
*
* @brief Handle plugin grid requests.
*/
namespace APP\controllers\grid\settings\plugins;
use APP\core\Application;
use PKP\controllers\grid\plugins\PluginGridHandler;
use PKP\controllers\grid\plugins\PluginGridRow;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\authorization\PluginAccessPolicy;
use PKP\security\Role;
class SettingsPluginGridHandler extends PluginGridHandler
{
/**
* Constructor
*/
public function __construct()
{
$roles = [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER];
$this->addRoleAssignment($roles, ['manage']);
parent::__construct($roles);
}
//
// Extended methods from PluginGridHandler
//
/**
* @copydoc PluginGridHandler::loadCategoryData()
*
* @param null|mixed $filter
*/
public function loadCategoryData($request, &$categoryDataElement, $filter = null)
{
$plugins = parent::loadCategoryData($request, $categoryDataElement, $filter);
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
$showSitePlugins = false;
if (in_array(Role::ROLE_ID_SITE_ADMIN, $userRoles)) {
$showSitePlugins = true;
}
if ($showSitePlugins) {
return $plugins;
} else {
$contextLevelPlugins = [];
foreach ($plugins as $plugin) {
if (!$plugin->isSitePlugin()) {
$contextLevelPlugins[$plugin->getName()] = $plugin;
}
unset($plugin);
}
return $contextLevelPlugins;
}
}
//
// Overridden template methods.
//
/**
* @copydoc CategoryGridHandler::getCategoryRowInstance()
*/
protected function getRowInstance()
{
return new PluginGridRow($this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES));
}
/**
* @copydoc GridHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$categoryName = $request->getUserVar('category');
$pluginName = $request->getUserVar('plugin');
if ($categoryName && $pluginName) {
switch ($request->getRequestedOp()) {
case 'enable':
case 'disable':
case 'manage':
$accessMode = PluginAccessPolicy::ACCESS_MODE_MANAGE;
break;
default:
$accessMode = PluginAccessPolicy::ACCESS_MODE_ADMIN;
break;
}
$this->addPolicy(new PluginAccessPolicy($request, $args, $roleAssignments, $accessMode));
} else {
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
}
return parent::authorize($request, $args, $roleAssignments);
}
}
@@ -0,0 +1,95 @@
<?php
/**
* @file controllers/grid/settings/sections/SectionGridCellProvider.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 SectionGridCellProvider
*
* @ingroup controllers_grid_settings_sections
*
* @brief Grid cell provider for section grid
*/
namespace APP\controllers\grid\settings\sections;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class SectionGridCellProvider extends GridCellProvider
{
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$element = $row->getData();
$columnId = $column->getId();
switch ($columnId) {
case 'inactive':
return ['selected' => $element['inactive']];
}
return parent::getTemplateVarsFromRowColumn($row, $column);
}
/**
* @see GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
switch ($column->getId()) {
case 'inactive':
$element = $row->getData(); /** @var array $element */
$router = $request->getRouter();
if ($element['inactive']) {
return [new LinkAction(
'activateSection',
new RemoteActionConfirmationModal(
$request->getSession(),
__('manager.sections.confirmActivateSection'),
null,
$router->url(
$request,
null,
'grid.settings.sections.SectionGridHandler',
'activateSection',
null,
['sectionKey' => $row->getId()]
)
)
)];
} else {
return [new LinkAction(
'deactivateSection',
new RemoteActionConfirmationModal(
$request->getSession(),
__('manager.sections.confirmDeactivateSection'),
null,
$router->url(
$request,
null,
'grid.settings.sections.SectionGridHandler',
'deactivateSection',
null,
['sectionKey' => $row->getId()]
)
)
)];
}
}
return parent::getCellActions($request, $row, $column, $position);
}
}
@@ -0,0 +1,355 @@
<?php
/**
* @file controllers/grid/settings/sections/SectionGridHandler.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 SectionGridHandler
*
* @ingroup controllers_grid_settings_section
*
* @brief Handle section grid requests.
*/
namespace APP\controllers\grid\settings\sections;
use APP\controllers\grid\settings\sections\form\SectionForm;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use PKP\context\SubEditorsDAO;
use PKP\controllers\grid\feature\OrderGridItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\settings\SetupGridHandler;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\notification\PKPNotification;
use PKP\security\Role;
class SectionGridHandler extends SetupGridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['fetchGrid', 'fetchRow', 'addSection', 'editSection', 'updateSection', 'deleteSection', 'saveSequence', 'deactivateSection','activateSection']
);
}
//
// Overridden template methods
//
/**
* @copydoc SetupGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
$journal = $request->getJournal();
// Set the grid title.
$this->setTitle('section.sections');
// Elements to be displayed in the grid
$subEditorsDao = DAORegistry::getDAO('SubEditorsDAO'); /** @var SubEditorsDAO $subEditorsDao */
$sections = Repo::section()->getCollector()->filterByContextIds([$journal->getId()])->getMany();
$gridData = [];
foreach ($sections as $section) {
// Get the section editors data for the row
$users = $subEditorsDao->getBySubmissionGroupIds([$section->getId()], Application::ASSOC_TYPE_SECTION, $journal->getId());
if ($users->isEmpty()) {
$editorsString = __('common.none');
} else {
$editorsString = Repo::user()
->getCollector()
->filterByUserIds($users->map(fn ($user) => $user->userId)->toArray())
->getMany()
->map(fn ($user) => $user->getFullName())
->join(__('common.commaListSeparator'));
}
$sectionId = $section->getId();
$gridData[$sectionId] = [
'title' => $section->getLocalizedTitle(),
'editors' => $editorsString,
'inactive' => $section->getIsInactive(),
'seq' => $section->getSequence()
];
}
uasort($gridData, function ($a, $b) {
return $a['seq'] - $b['seq'];
});
$this->setGridDataElements($gridData);
// Add grid-level actions
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'addSection',
new AjaxModal(
$router->url($request, null, null, 'addSection', null, ['gridId' => $this->getId()]),
__('manager.sections.create'),
'modal_manage'
),
__('manager.sections.create'),
'add_section'
)
);
//
// Grid columns.
//
$sectionGridCellProvider = new SectionGridCellProvider();
// Section name
$this->addColumn(
new GridColumn(
'title',
'common.title'
)
);
// Section 'editors'
$this->addColumn(new GridColumn('editors', 'user.role.editors'));
//Section 'inactive'
$this->addColumn(
new GridColumn(
'inactive',
'common.inactive',
null,
'controllers/grid/common/cell/selectStatusCell.tpl',
$sectionGridCellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_CENTER,
'width' => 20]
)
);
}
//
// Overridden methods from GridHandler
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new OrderGridItemsFeature()];
}
/**
* Get the row handler - override the default row handler
*
* @return SectionGridRow
*/
protected function getRowInstance()
{
return new SectionGridRow();
}
/**
* @copydoc GridHandler::getDataElementSequence()
*/
public function getDataElementSequence($row)
{
return $row['seq'];
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementSequence($request, $rowId, $gridDataElement, $newSequence)
{
$journal = $request->getJournal();
$section = Repo::section()->get($rowId, $journal->getId());
$section->setSequence($newSequence);
Repo::section()->edit($section, []);
}
//
// Public Section Grid Actions
//
/**
* An action to add a new section
*
* @param array $args
* @param Request $request
*/
public function addSection($args, $request)
{
// Calling editSection with an empty ID will add
// a new section.
return $this->editSection($args, $request);
}
/**
* An action to edit a section
*
* @param array $args
* @param Request $request
*
* @return string Serialized JSON object
* @return JSONMessage JSON object
*/
public function editSection($args, $request)
{
$sectionId = $args['sectionId'] ?? null;
$this->setupTemplate($request);
$sectionForm = new SectionForm($request, $sectionId);
$sectionForm->initData();
return new JSONMessage(true, $sectionForm->fetch($request));
}
/**
* Update a section
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateSection($args, $request)
{
$sectionId = $request->getUserVar('sectionId');
$sectionForm = new SectionForm($request, $sectionId);
$sectionForm->readInputData();
if ($sectionForm->validate()) {
$sectionForm->execute();
$notificationManager = new NotificationManager();
$notificationManager->createTrivialNotification($request->getUser()->getId());
return DAO::getDataChangedEvent($sectionForm->getSectionId());
}
return new JSONMessage(false);
}
/**
* Delete a section
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteSection($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false, __('form.csrfInvalid'));
}
$journal = $request->getJournal();
$section = Repo::section()->get($request->getUserVar('sectionId'), $journal->getId());
if (!$section) {
return new JSONMessage(false, __('manager.setup.errorDeletingItem'));
}
// Validate if it can be deleted
$sectionEmpty = Repo::section()->isEmpty($section->getId(), $journal->getId());
if (!$sectionEmpty) {
return new JSONMessage(false, __('manager.sections.alertDelete'));
}
$activeSectionsCount = Repo::section()->getCollector()->filterByContextIds([$journal->getId()])->excludeInactive()->getCount();
$activeSectionsCount = (!$section->getIsInactive()) ? $activeSectionsCount - 1 : $activeSectionsCount;
if ($activeSectionsCount < 1) {
return new JSONMessage(false, __('manager.sections.confirmDeactivateSection.error'));
}
Repo::section()->delete($section);
return DAO::getDataChangedEvent($section->getId());
}
/**
* Deactivate a section.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deactivateSection($args, $request)
{
// Identify the current section
$sectionId = (int) $request->getUserVar('sectionKey');
// Identify the context id.
$context = $request->getContext();
// Validate if it can be inactive
$activeSectionsCount = Repo::section()->getCollector()->filterByContextIds([$context->getId()])->excludeInactive()->getCount();
if ($activeSectionsCount > 1) {
$section = Repo::section()->get($sectionId, $context->getId());
if ($request->checkCSRF() && isset($section) && !$section->getIsInactive()) {
$section->setIsInactive(1);
Repo::section()->edit($section, []);
// Create the notification.
$notificationMgr = new NotificationManager();
$user = $request->getUser();
$notificationMgr->createTrivialNotification($user->getId());
return DAO::getDataChangedEvent($sectionId);
}
} else {
// Create the notification.
$notificationMgr = new NotificationManager();
$user = $request->getUser();
$notificationMgr->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_ERROR, ['contents' => __('manager.sections.confirmDeactivateSection.error')]);
return DAO::getDataChangedEvent($sectionId);
}
return new JSONMessage(false);
}
/**
* Activate a section.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function activateSection($args, $request)
{
// Identify the current section
$sectionId = (int) $request->getUserVar('sectionKey');
// Identify the context id.
$context = $request->getContext();
// Get section object
$section = Repo::section()->get($sectionId, $context->getId());
if ($request->checkCSRF() && isset($section) && $section->getIsInactive()) {
$section->setIsInactive(0);
Repo::section()->edit($section, []);
// Create the notification.
$notificationMgr = new NotificationManager();
$user = $request->getUser();
$notificationMgr->createTrivialNotification($user->getId());
return DAO::getDataChangedEvent($sectionId);
}
return new JSONMessage(false);
}
}
@@ -0,0 +1,73 @@
<?php
/**
* @file controllers/grid/settings/sections/SectionGridRow.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 SectionGridRow
*
* @ingroup controllers_grid_settings_section
*
* @brief Handle section grid row requests.
*/
namespace APP\controllers\grid\settings\sections;
use PKP\controllers\grid\GridRow;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class SectionGridRow extends GridRow
{
//
// Overridden template methods
//
/**
* @copydoc GridRow::initialize()
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
// Is this a new row or an existing row?
$sectionId = $this->getId();
if (!empty($sectionId) && is_numeric($sectionId)) {
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'editSection',
new AjaxModal(
$router->url($request, null, null, 'editSection', null, ['sectionId' => $sectionId]),
__('grid.action.edit'),
'modal_edit',
true
),
__('grid.action.edit'),
'edit'
)
);
$this->addAction(
new LinkAction(
'deleteSection',
new RemoteActionConfirmationModal(
$request->getSession(),
__('manager.sections.confirmDelete'),
__('grid.action.delete'),
$router->url($request, null, null, 'deleteSection', null, ['sectionId' => $sectionId]),
'modal_delete'
),
__('grid.action.delete'),
'delete'
)
);
}
}
}
@@ -0,0 +1,198 @@
<?php
/**
* @file controllers/grid/settings/sections/form/SectionForm.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 SectionForm
*
* @ingroup controllers_grid_settings_section_form
*
* @brief Form for adding/editing a section
*/
namespace APP\controllers\grid\settings\sections\form;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\controllers\grid\settings\sections\form\PKPSectionForm;
use PKP\db\DAORegistry;
use PKP\reviewForm\ReviewFormDAO;
class SectionForm extends PKPSectionForm
{
/**
* Constructor.
*
* @param Request $request
* @param int $sectionId optional
*/
public function __construct($request, $sectionId = null)
{
parent::__construct(
$request,
'controllers/grid/settings/sections/form/sectionForm.tpl',
$sectionId
);
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'title', 'required', 'manager.setup.form.section.nameRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'abbrev', 'required', 'manager.sections.form.abbrevRequired'));
$journal = $request->getJournal();
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'reviewFormId', 'optional', 'manager.sections.form.reviewFormId', [DAORegistry::getDAO('ReviewFormDAO'), 'reviewFormExists'], [Application::ASSOC_TYPE_JOURNAL, $journal->getId()]));
}
/**
* Initialize form data from current settings.
*/
public function initData()
{
$request = Application::get()->getRequest();
$journal = $request->getJournal();
$sectionId = $this->getSectionId();
if ($sectionId) {
$this->section = Repo::section()->get($sectionId, $journal->getId());
}
if (isset($this->section)) {
$this->setData([
'title' => $this->section->getTitle(null), // Localized
'abbrev' => $this->section->getAbbrev(null), // Localized
'reviewFormId' => $this->section->getReviewFormId(),
'isInactive' => $this->section->getIsInactive(),
'metaIndexed' => !$this->section->getMetaIndexed(), // #2066: Inverted
'metaReviewed' => !$this->section->getMetaReviewed(), // #2066: Inverted
'abstractsNotRequired' => $this->section->getAbstractsNotRequired(),
'identifyType' => $this->section->getIdentifyType(null), // Localized
'editorRestricted' => $this->section->getEditorRestricted(),
'hideTitle' => $this->section->getHideTitle(),
'hideAuthor' => $this->section->getHideAuthor(),
'policy' => $this->section->getPolicy(null), // Localized
'wordCount' => $this->section->getAbstractWordCount(),
]);
}
parent::initData();
}
/**
* @see Form::validate()
*/
public function validate($callHooks = true)
{
// Validate if it can be inactive
if ($this->getData('isInactive')) {
$request = Application::get()->getRequest();
$context = $request->getContext();
$sectionId = $this->getSectionId();
$activeSections = Repo::section()->getCollector()->filterByContextIds([$context->getId()])->excludeInactive()->getMany();
$otherActiveSections = $activeSections->filter(function ($activeSection) use ($sectionId) {
return $activeSection->getId() != $sectionId;
});
if ($otherActiveSections->count() < 1) {
$this->addError('isInactive', __('manager.sections.confirmDeactivateSection.error'));
}
}
return parent::validate($callHooks);
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('sectionId', $this->getSectionId());
$journal = $request->getContext();
$reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */
$reviewForms = $reviewFormDao->getActiveByAssocId(Application::ASSOC_TYPE_JOURNAL, $journal->getId());
$reviewFormOptions = [];
while ($reviewForm = $reviewForms->next()) {
$reviewFormOptions[$reviewForm->getId()] = $reviewForm->getLocalizedTitle();
}
$templateMgr->assign('reviewFormOptions', $reviewFormOptions);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::readInputData()
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars(['abbrev', 'policy', 'reviewFormId', 'identifyType', 'isInactive', 'metaIndexed', 'metaReviewed', 'abstractsNotRequired', 'editorRestricted', 'hideTitle', 'hideAuthor', 'wordCount']);
}
/**
* Get the names of fields for which localized data is allowed.
*
* @return array
*/
public function getLocaleFieldNames()
{
return ['title', 'policy', 'abbrev', 'identifyType'];
}
/**
* Save section.
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$journal = $request->getJournal();
// Get or create the section object
if ($this->getSectionId()) {
$section = Repo::section()->get($this->getSectionId(), $journal->getId());
} else {
$section = Repo::section()->newDataObject();
$section->setContextId($journal->getId());
}
// Populate/update the section object from the form
$section->setTitle($this->getData('title'), null); // Localized
$section->setAbbrev($this->getData('abbrev'), null); // Localized
$reviewFormId = $this->getData('reviewFormId');
if (!$reviewFormId) {
$reviewFormId = null;
}
$section->setReviewFormId($reviewFormId);
$section->setIsInactive($this->getData('isInactive') ? 1 : 0);
$section->setMetaIndexed($this->getData('metaIndexed') ? 0 : 1); // #2066: Inverted
$section->setMetaReviewed($this->getData('metaReviewed') ? 0 : 1); // #2066: Inverted
$section->setAbstractsNotRequired($this->getData('abstractsNotRequired') ? 1 : 0);
$section->setIdentifyType($this->getData('identifyType'), null); // Localized
$section->setEditorRestricted($this->getData('editorRestricted') ? 1 : 0);
$section->setHideTitle($this->getData('hideTitle') ? 1 : 0);
$section->setHideAuthor($this->getData('hideAuthor') ? 1 : 0);
$section->setPolicy($this->getData('policy'), null); // Localized
$section->setAbstractWordCount((int) $this->getData('wordCount'));
// Insert or update the section in the DB
if ($this->getSectionId()) {
Repo::section()->edit($section, []);
} else {
$section->setSequence(REALLY_BIG_NUMBER);
$sectionId = Repo::section()->add($section);
$this->setSectionId($sectionId);
Repo::section()->resequence($journal->getId());
}
return parent::execute(...$functionArgs);
}
}
@@ -0,0 +1,156 @@
<?php
/**
* @file controllers/grid/submissions/ExportPublishedSubmissionsListGridCellProvider.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 ExportPublishedSubmissionsListGridCellProvider
*
* @ingroup controllers_grid_submissions
*
* @brief Class for a cell provider that can retrieve labels from submissions
*/
namespace APP\controllers\grid\submissions;
use APP\core\Application;
use APP\facades\Repo;
use APP\submission\Submission;
use PKP\controllers\grid\DataObjectGridCellProvider;
use PKP\controllers\grid\GridHandler;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RedirectAction;
use PKP\plugins\ImportExportPlugin;
class ExportPublishedSubmissionsListGridCellProvider extends DataObjectGridCellProvider
{
/** @var ImportExportPlugin */
public $_plugin;
public $_authorizedRoles;
public $_titleColumn;
/**
* Constructor
*
* @param null|mixed $authorizedRoles
*/
public function __construct($plugin, $authorizedRoles = null)
{
$this->_plugin = $plugin;
if ($authorizedRoles) {
$this->_authorizedRoles = $authorizedRoles;
}
parent::__construct();
}
//
// Template methods from GridCellProvider
//
/**
* Get cell actions associated with this row/column combination
*
* @copydoc GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
$submission = $row->getData();
$columnId = $column->getId();
assert($submission instanceof Submission && !empty($columnId));
switch ($columnId) {
case 'title':
$this->_titleColumn = $column;
$title = $submission->getCurrentPublication()->getLocalizedTitle(null, 'html');
if (empty($title)) {
$title = __('common.untitled');
}
$authorsInTitle = $submission->getCurrentPublication()->getShortAuthorString();
$title = $authorsInTitle . '; ' . $title;
return [
new LinkAction(
'itemWorkflow',
new RedirectAction(
Repo::submission()->getWorkflowUrlByUserRoles($submission)
),
htmlspecialchars($title)
)
];
case 'issue':
$contextId = $submission->getContextId();
$issueId = $submission->getCurrentPublication()->getData('issueId');
$issue = Repo::issue()->get($issueId);
$issue = $issue->getJournalId() == $contextId ? $issue : null;
if ($issue) {
// Link to the issue edit modal
$application = Application::get();
$dispatcher = $application->getDispatcher();
return [
new LinkAction(
'edit',
new AjaxModal(
$dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.issues.BackIssueGridHandler', 'editIssue', null, ['issueId' => $issue->getId()]),
__('plugins.importexport.common.settings.DOIPluginSettings')
),
$issue->getIssueIdentification(),
null
)
];
}
break;
case 'status':
$status = $submission->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($submission);
if ($status && array_key_exists($status, $statusActions)) {
assert(array_key_exists($status, $statusNames));
return [$statusActions[$status]];
}
break;
}
return parent::getCellActions($request, $row, $column, $position);
}
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @copydoc DataObjectGridCellProvider::getTemplateVarsFromRowColumn()
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$submission = $row->getData();
$columnId = $column->getId();
assert($submission instanceof Submission && !empty($columnId));
switch ($columnId) {
case 'id':
return ['label' => $submission->getId()];
case 'title':
return ['label' => ''];
case 'issue':
return ['label' => ''];
case 'status':
$status = $submission->getData($this->_plugin->getDepositStatusSettingName());
$statusNames = $this->_plugin->getStatusNames();
$statusActions = $this->_plugin->getStatusActions($submission);
if ($status) {
if (array_key_exists($status, $statusActions)) {
$label = '';
} else {
assert(array_key_exists($status, $statusNames));
$label = $statusNames[$status];
}
} else {
$label = $statusNames[EXPORT_STATUS_NOT_DEPOSITED];
}
return ['label' => $label];
}
}
}
@@ -0,0 +1,321 @@
<?php
/**
* @file controllers/grid/submissions/ExportPublishedSubmissionsListGridHandler.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 ExportPublishedSubmissionsListGridHandler
*
* @ingroup controllers_grid_submissions
*
* @brief Handle exportable published submissions list grid requests.
*/
namespace APP\controllers\grid\submissions;
use APP\core\Application;
use APP\facades\Repo;
use APP\issue\Collector;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\feature\selectableItems\SelectableItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\plugins\ImportExportPlugin;
use PKP\plugins\PluginRegistry;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\RoleBasedHandlerOperationPolicy;
use PKP\security\Role;
class ExportPublishedSubmissionsListGridHandler extends GridHandler
{
/** @var ImportExportPlugin */
public $_plugin;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['fetchGrid', 'fetchRow']
);
}
//
// Implement template methods from PKPHandler
//
/**
* @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);
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
$context = $request->getContext();
// Basic grid configuration.
$this->setTitle('plugins.importexport.common.export.articles');
$pluginCategory = $request->getUserVar('category');
$pluginPathName = $request->getUserVar('plugin');
// Allow for plugins that have already been loaded (e.g. by injection from a generic plugin)
$this->_plugin = PluginRegistry::getPlugin($pluginCategory, $pluginPathName);
// Otherwise, load the plugin as specified
$this->_plugin ??= PluginRegistry::loadPlugin($pluginCategory, $pluginPathName);
assert(isset($this->_plugin));
// Grid columns.
$cellProvider = $this->getGridCellProvider();
$this->addColumn(
new GridColumn(
'id',
null,
__('common.id'),
'controllers/grid/gridCell.tpl',
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 10]
)
);
$this->addColumn(
new GridColumn(
'title',
'grid.submission.itemTitle',
null,
null,
$cellProvider,
['html' => true,
'alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT]
)
);
$this->addColumn(
new GridColumn(
'issue',
'issue.issue',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 20]
)
);
if (method_exists($this, 'addAdditionalColumns')) {
$this->addAdditionalColumns($cellProvider);
}
$this->addColumn(
new GridColumn(
'status',
'common.status',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 10]
)
);
}
//
// Implemented methods from GridHandler.
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new SelectableItemsFeature(), new PagingFeature()];
}
/**
* @copydoc GridHandler::getRequestArgs()
*/
public function getRequestArgs()
{
return array_merge(parent::getRequestArgs(), ['category' => $this->_plugin->getCategory(), 'plugin' => basename($this->_plugin->getPluginPath())]);
}
/**
* @copydoc GridHandler::isDataElementSelected()
*/
public function isDataElementSelected($gridDataElement)
{
return false; // Nothing is selected by default
}
/**
* @copydoc GridHandler::getSelectName()
*/
public function getSelectName()
{
return 'selectedSubmissions';
}
/**
* @copydoc GridHandler::getFilterForm()
*/
protected function getFilterForm()
{
return 'controllers/grid/submissions/exportPublishedSubmissionsGridFilter.tpl';
}
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$context = $request->getContext();
$issues = Repo::issue()->getCollector()
->filterByContextIds([$context->getId()])
->filterByPublished(true)
->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES)
->getMany();
foreach ($issues as $issue) {
$issueOptions[$issue->getId()] = $issue->getIssueIdentification();
}
$issueOptions[0] = __('plugins.importexport.common.filter.issue');
ksort($issueOptions);
$statusNames = $this->_plugin->getStatusNames();
$filterColumns = $this->getFilterColumns();
$allFilterData = array_merge(
$filterData,
[
'columns' => $filterColumns,
'issues' => $issueOptions,
'status' => $statusNames,
'gridId' => $this->getId(),
]
);
return parent::renderFilter($request, $allFilterData);
}
/**
* @copydoc GridHandler::getFilterSelectionData()
*/
public function getFilterSelectionData($request)
{
$search = (string) $request->getUserVar('search');
$column = (string) $request->getUserVar('column');
$issueId = (int) $request->getUserVar('issueId');
$statusId = (string) $request->getUserVar('statusId');
return [
'search' => $search,
'column' => $column,
'issueId' => $issueId,
'statusId' => $statusId,
];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$context = $request->getContext();
[$search, $column, $issueId, $statusId] = $this->getFilterValues($filter);
$title = $author = null;
if ($column == 'title') {
$title = $search;
} elseif ($column == 'author') {
$author = $search;
}
$pubIdStatusSettingName = null;
if ($statusId) {
$pubIdStatusSettingName = $this->_plugin->getDepositStatusSettingName();
}
return Repo::submission()->dao->getExportable(
$context->getId(),
null,
$title,
$author,
$issueId,
$pubIdStatusSettingName,
$statusId,
$this->getGridRangeInfo($request, $this->getId())
);
}
//
// Own protected methods
//
/**
* Get which columns can be used by users to filter data.
*
* @return array
*/
protected function getFilterColumns()
{
return [
'title' => __('submission.title'),
'author' => __('submission.authors')
];
}
/**
* Process filter values, assigning default ones if
* none was set.
*
* @return array
*/
protected function getFilterValues($filter)
{
if (isset($filter['search']) && $filter['search']) {
$search = $filter['search'];
} else {
$search = null;
}
if (isset($filter['column']) && $filter['column']) {
$column = $filter['column'];
} else {
$column = null;
}
if (isset($filter['issueId']) && $filter['issueId']) {
$issueId = $filter['issueId'];
} else {
$issueId = null;
}
if (isset($filter['statusId']) && $filter['statusId'] != EXPORT_STATUS_ANY) {
$statusId = $filter['statusId'];
} else {
$statusId = null;
}
return [$search, $column, $issueId, $statusId];
}
/**
* Get the grid cell provider instance
*
* @return ExportPublishedSubmissionsListGridCellProvider
*/
public function getGridCellProvider()
{
// Fetch the authorized roles.
$authorizedRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
return new ExportPublishedSubmissionsListGridCellProvider($this->_plugin, $authorizedRoles);
}
}
@@ -0,0 +1,117 @@
<?php
/**
* @file controllers/grid/subscriptions/IndividualSubscriptionForm.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 IndividualSubscriptionForm
*
* @ingroup subscription
*
* @brief Form class for individual subscription create/edits.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Application;
use APP\core\Request;
use APP\notification\NotificationManager;
use APP\subscription\form\SubscriptionForm;
use APP\subscription\IndividualSubscription;
use APP\subscription\IndividualSubscriptionDAO;
use APP\subscription\SubscriptionTypeDAO;
use Exception;
use Illuminate\Support\Facades\Mail;
use PKP\db\DAORegistry;
use PKP\notification\PKPNotification;
class IndividualSubscriptionForm extends SubscriptionForm
{
/**
* Constructor
*
* @param Request $request
* @param int $subscriptionId leave as default for new subscription
*/
public function __construct($request, $subscriptionId = null)
{
parent::__construct('payments/individualSubscriptionForm.tpl', $subscriptionId);
$subscriptionId = isset($subscriptionId) ? (int) $subscriptionId : null;
$journal = $request->getJournal();
$journalId = $journal->getId();
if (isset($subscriptionId)) {
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
if ($subscriptionDao->subscriptionExists($subscriptionId)) {
$this->subscription = $subscriptionDao->getById($subscriptionId);
}
}
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$subscriptionTypeIterator = $subscriptionTypeDao->getByInstitutional($journalId, false);
$this->subscriptionTypes = [];
while ($subscriptionType = $subscriptionTypeIterator->next()) {
$this->subscriptionTypes[$subscriptionType->getId()] = $subscriptionType->getSummaryString();
}
if (count($this->subscriptionTypes) == 0) {
$this->addError('typeId', __('manager.subscriptions.form.typeRequired'));
$this->addErrorField('typeId');
}
// Ensure subscription type is valid
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'typeId', 'required', 'manager.subscriptions.form.typeIdValid', function ($typeId) use ($journalId) {
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
return $subscriptionTypeDao->subscriptionTypeExistsByTypeId($typeId, $journalId) && !$subscriptionTypeDao->getSubscriptionTypeInstitutional($typeId);
}));
// Ensure that user does not already have a subscription for this journal
if (!isset($subscriptionId)) {
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'userId', 'required', 'manager.subscriptions.form.subscriptionExists', [DAORegistry::getDAO('IndividualSubscriptionDAO'), 'subscriptionExistsByUserForJournal'], [$journalId], true));
} else {
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'userId', 'required', 'manager.subscriptions.form.subscriptionExists', function ($userId) use ($journalId, $subscriptionId) {
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
$checkSubscription = $subscriptionDao->getByUserIdForJournal($userId, $journalId);
return (!$checkSubscription || $checkSubscription->getId() == $subscriptionId) ? true : false;
}));
}
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$insert = false;
if (!isset($this->subscription)) {
$this->subscription = new IndividualSubscription();
$insert = true;
}
parent::execute(...$functionArgs);
$individualSubscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $individualSubscriptionDao */
if ($insert) {
$individualSubscriptionDao->insertObject($this->subscription);
} else {
$individualSubscriptionDao->updateObject($this->subscription);
}
// Send notification email
if ($this->getData('notifyEmail')) {
$mailable = $this->_prepareNotificationEmail();
try {
Mail::send($mailable);
} catch (Exception $e) {
$notificationMgr = new NotificationManager();
$request = Application::get()->getRequest();
$notificationMgr->createTrivialNotification($request->getUser()->getId(), PKPNotification::NOTIFICATION_TYPE_ERROR, ['contents' => __('email.compose.error')]);
error_log($e->getMessage());
}
}
}
}
@@ -0,0 +1,228 @@
<?php
/**
* @file controllers/grid/subscriptions/IndividualSubscriptionsGridHandler.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 IndividualSubscriptionsGridHandler
*
* @ingroup controllers_grid_subscriptions
*
* @brief Handle subscription grid requests.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Request;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use APP\subscription\IndividualSubscriptionDAO;
use APP\subscription\SubscriptionDAO;
use PKP\controllers\grid\GridColumn;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\identity\Identity;
use PKP\notification\PKPNotification;
class IndividualSubscriptionsGridHandler extends SubscriptionsGridHandler
{
/**
* @copydoc SubscriptionsGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Basic grid configuration.
$this->setTitle('subscriptionManager.individualSubscriptions');
//
// Grid columns.
//
$cellProvider = new SubscriptionsGridCellProvider();
$this->addColumn(
new GridColumn(
'name',
'common.name',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'email',
'user.email',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'subscriptionType',
'manager.subscriptions.subscriptionType',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'status',
'manager.subscriptions.form.status',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'dateStart',
'manager.subscriptions.dateStart',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'dateEnd',
'manager.subscriptions.dateEnd',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'referenceNumber',
'manager.subscriptions.referenceNumber',
null,
null,
$cellProvider
)
);
}
//
// Implement methods from GridHandler.
//
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$userDao = Repo::user()->dao;
return parent::renderFilter($request, array_merge_recursive(
$filterData,
[
'fieldOptions' => [
Identity::IDENTITY_SETTING_GIVENNAME => 'user.givenName',
Identity::IDENTITY_SETTING_FAMILYNAME => 'user.familyName',
$userDao::USER_FIELD_USERNAME => 'user.username',
$userDao::USER_FIELD_EMAIL => 'user.email',
SubscriptionDAO::SUBSCRIPTION_MEMBERSHIP => 'user.subscriptions.form.membership',
SubscriptionDAO::SUBSCRIPTION_REFERENCE_NUMBER => 'manager.subscriptions.form.referenceNumber',
SubscriptionDAO::SUBSCRIPTION_NOTES => 'manager.subscriptions.form.notes',
],
'matchOptions' => [
'contains' => 'form.contains',
'is' => 'form.is'
]
]
));
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
// Get the context.
$journal = $request->getContext();
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
return $subscriptionDao->getByJournalId($journal->getId(), null, $filter['searchField'], $filter['searchMatch'], $filter['search'] ? $filter['search'] : null, null, null, null, $rangeInfo);
}
//
// Public grid actions.
//
/**
* Edit an existing subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editSubscription($args, $request)
{
// Form handling.
$subscriptionForm = new IndividualSubscriptionForm($request, $request->getUserVar('rowId'));
$subscriptionForm->initData();
return new JSONMessage(true, $subscriptionForm->fetch($request));
}
/**
* Update an existing subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateSubscription($args, $request)
{
$subscriptionId = $request->getUserVar('subscriptionId');
// Form handling.
$subscriptionForm = new IndividualSubscriptionForm($request, $subscriptionId);
$subscriptionForm->readInputData();
if ($subscriptionForm->validate()) {
$subscriptionForm->execute();
$notificationManager = new NotificationManager();
$notificationManager->createTrivialNotification($request->getUser()->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS);
// Prepare the grid row data.
return DAO::getDataChangedEvent($subscriptionId);
} else {
return new JSONMessage(true, $subscriptionForm->fetch($request));
}
}
/**
* Delete a subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteSubscription($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$context = $request->getContext();
$user = $request->getUser();
// Identify the subscription ID.
$subscriptionId = $request->getUserVar('rowId');
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
$subscriptionDao->deleteById($subscriptionId, $context->getId());
return DAO::getDataChangedEvent();
}
}
@@ -0,0 +1,225 @@
<?php
/**
* @file controllers/grid/subscriptions/InstitutionalSubscriptionForm.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 InstitutionalSubscriptionForm
*
* @ingroup subscription
*
* @brief Form class for institutional subscription create/edits.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use APP\subscription\form\SubscriptionForm;
use APP\subscription\InstitutionalSubscription;
use APP\subscription\InstitutionalSubscriptionDAO;
use APP\subscription\SubscriptionType;
use APP\subscription\SubscriptionTypeDAO;
use APP\template\TemplateManager;
use Exception;
use Illuminate\Support\Facades\Mail;
use PKP\db\DAORegistry;
use PKP\notification\PKPNotification;
class InstitutionalSubscriptionForm extends SubscriptionForm
{
/** @var array of the journal institutions [institutionId => name] */
public array $institutions;
/**
* Constructor
*
* @param Request $request
* @param int $subscriptionId leave as default for new subscription
*/
public function __construct($request, $subscriptionId = null)
{
parent::__construct('payments/institutionalSubscriptionForm.tpl', $subscriptionId);
$subscriptionId = isset($subscriptionId) ? (int) $subscriptionId : null;
$journal = $request->getJournal();
$journalId = $journal->getId();
$subscriptionInstitutionId = null;
if (isset($subscriptionId)) {
/** @var InstitutionalSubscriptionDAO */
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO');
if ($subscriptionDao->subscriptionExists($subscriptionId)) {
$this->subscription = $subscriptionDao->getById($subscriptionId);
$subscriptionInstitutionId = $this->subscription->getInstitutionId();
}
}
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$subscriptionTypeIterator = $subscriptionTypeDao->getByInstitutional($journalId, true);
$this->subscriptionTypes = [];
while ($subscriptionType = $subscriptionTypeIterator->next()) {
$this->subscriptionTypes[$subscriptionType->getId()] = $subscriptionType->getSummaryString();
}
if (count($this->subscriptionTypes) == 0) {
$this->addError('typeId', __('manager.subscriptions.form.typeRequired'));
$this->addErrorField('typeId');
}
$institutions = Repo::institution()->getCollector()
->filterByContextIds([$journalId])
->getMany();
$this->institutions = [];
foreach ($institutions as $institution) {
$this->institutions[$institution->getId()] = $institution->getLocalizedName();
}
if (isset($subscriptionInstitutionId) && !array_key_exists($subscriptionInstitutionId, $this->institutions)) {
// The institution is soft deleted, add it to the institutions list
$subscriptionInstitution = Repo::institution()->get($subscriptionInstitutionId);
$this->institutions[$subscriptionInstitutionId] = $subscriptionInstitution->getLocalizedName();
}
if (!count($this->institutions)) {
$this->addError('institutionId', __('manager.subscriptions.form.institutionRequired'));
$this->addErrorField('institutionId');
}
// Ensure subscription type is valid
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'typeId', 'required', 'manager.subscriptions.form.typeIdValid', function ($typeId) use ($journalId) {
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
return $subscriptionTypeDao->subscriptionTypeExistsByTypeId($typeId, $journalId) && $subscriptionTypeDao->getSubscriptionTypeInstitutional($typeId);
}));
// Ensure institution ID exists
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'institutionId', 'required', 'manager.subscriptions.form.institutionIdValid', function ($institutionId) use ($journalId, $subscriptionInstitutionId) {
return ($institutionId == $subscriptionInstitutionId) || Repo::institution()->exists($institutionId, $journalId);
}));
// If provided, domain is valid
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'domain', 'optional', 'manager.subscriptions.form.domainValid', '/^' .
'[A-Z0-9]+([\-_\.][A-Z0-9]+)*' .
'\.' .
'[A-Z]{2,4}' .
'$/i'));
}
/**
* @copydoc Form::fetch
*
* @param null|string $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'institutions' => $this->institutions,
]);
return parent::fetch($request, $template, $display);
}
/**
* Initialize form data from current subscription.
*/
public function initData()
{
parent::initData();
if (isset($this->subscription)) {
/** @var InstitutionalSubscription */
$subscription = $this->subscription;
$this->_data = array_merge(
$this->_data,
[
'institutionMailingAddress' => $subscription->getInstitutionMailingAddress(),
'domain' => $subscription->getDomain(),
'institutionId' => $subscription->getInstitutionId(),
]
);
}
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars(['institutionMailingAddress', 'domain', 'institutionId']);
}
/**
* @copydoc Form::validate()
*/
public function validate($callHooks = true)
{
if (!parent::validate()) {
return false;
}
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$subscriptionType = $subscriptionTypeDao->getById($this->getData('typeId'));
$institution = Repo::institution()->get($this->getData('institutionId'));
$ipRanges = $institution->getIPRanges();
$domain = $this->getData('domain');
// If online or print + online, domain or at least one IP range has to be provided
if ($subscriptionType->getFormat() != SubscriptionType::SUBSCRIPTION_TYPE_FORMAT_PRINT) {
if (empty($domain) && empty($ipRanges)) {
$this->addError('domain', __('manager.subscriptions.form.domainIPRangeRequired'));
$this->addErrorField('domain');
return false;
}
}
return true;
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$insert = false;
if (!isset($this->subscription)) {
$this->subscription = new InstitutionalSubscription();
$insert = true;
}
/** @var InstitutionalSubscription */
$subscription = $this->subscription;
parent::execute(...$functionArgs);
$subscription->setInstitutionId($this->getData('institutionId'));
$subscription->setInstitutionMailingAddress($this->getData('institutionMailingAddress'));
$subscription->setDomain($this->getData('domain'));
/** @var InstitutionalSubscriptionDAO $institutionalSubscriptionDao */
$institutionalSubscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO');
if ($insert) {
$institutionalSubscriptionDao->insertObject($this->subscription);
} else {
$institutionalSubscriptionDao->updateObject($this->subscription);
}
// Send notification email
if ($this->getData('notifyEmail')) {
$mailable = $this->_prepareNotificationEmail();
try {
Mail::send($mailable);
} catch (Exception $e) {
$notificationMgr = new NotificationManager();
$request = Application::get()->getRequest();
$notificationMgr->createTrivialNotification($request->getUser()->getId(), PKPNotification::NOTIFICATION_TYPE_ERROR, ['contents' => __('email.compose.error')]);
error_log($e->getMessage());
}
}
}
}
@@ -0,0 +1,221 @@
<?php
/**
* @file controllers/grid/subscriptions/InstitutionalSubscriptionsGridHandler.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 InstitutionalSubscriptionsGridHandler
*
* @ingroup controllers_grid_subscriptions
*
* @brief Handle subscription grid requests.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Request;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use APP\subscription\InstitutionalSubscriptionDAO;
use APP\subscription\SubscriptionDAO;
use PKP\controllers\grid\GridColumn;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\identity\Identity;
use PKP\notification\PKPNotification;
class InstitutionalSubscriptionsGridHandler extends SubscriptionsGridHandler
{
/**
* @copydoc SubscriptionsGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Basic grid configuration.
$this->setTitle('subscriptionManager.institutionalSubscriptions');
//
// Grid columns.
//
$cellProvider = new SubscriptionsGridCellProvider();
$this->addColumn(
new GridColumn(
'name',
'common.name',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'subscriptionType',
'manager.subscriptions.subscriptionType',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'status',
'manager.subscriptions.form.status',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'dateStart',
'manager.subscriptions.dateStart',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'dateEnd',
'manager.subscriptions.dateEnd',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'referenceNumber',
'manager.subscriptions.referenceNumber',
null,
null,
$cellProvider
)
);
}
//
// Implement methods from GridHandler.
//
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$userDao = Repo::user()->dao;
$filterData = array_merge($filterData, [
'fieldOptions' => [
Identity::IDENTITY_SETTING_GIVENNAME => 'user.givenName',
Identity::IDENTITY_SETTING_FAMILYNAME => 'user.familyName',
$userDao::USER_FIELD_USERNAME => 'user.username',
$userDao::USER_FIELD_EMAIL => 'user.email',
SubscriptionDAO::SUBSCRIPTION_MEMBERSHIP => 'user.subscriptions.form.membership',
SubscriptionDAO::SUBSCRIPTION_REFERENCE_NUMBER => 'manager.subscriptions.form.referenceNumber',
SubscriptionDAO::SUBSCRIPTION_NOTES => 'manager.subscriptions.form.notes',
InstitutionalSubscriptionDAO::SUBSCRIPTION_INSTITUTION_NAME => 'manager.subscriptions.form.institutionName',
InstitutionalSubscriptionDAO::SUBSCRIPTION_DOMAIN => 'manager.subscriptions.form.domain',
InstitutionalSubscriptionDAO::SUBSCRIPTION_IP_RANGE => 'manager.subscriptions.form.ipRange',
],
'matchOptions' => [
'contains' => 'form.contains',
'is' => 'form.is'
],
]);
return parent::renderFilter($request, $filterData);
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
// Get the context.
$journal = $request->getContext();
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
return $subscriptionDao->getByJournalId($journal->getId(), null, $filter['searchField'], $filter['searchMatch'], $filter['search'] ? $filter['search'] : null, null, null, null, $rangeInfo);
}
//
// Public grid actions.
//
/**
* Edit an existing subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editSubscription($args, $request)
{
// Form handling.
$subscriptionForm = new InstitutionalSubscriptionForm($request, $request->getUserVar('rowId'));
$subscriptionForm->initData();
return new JSONMessage(true, $subscriptionForm->fetch($request));
}
/**
* Update an existing subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateSubscription($args, $request)
{
$subscriptionId = (int) $request->getUserVar('subscriptionId');
// Form handling.
$subscriptionForm = new InstitutionalSubscriptionForm($request, $subscriptionId);
$subscriptionForm->readInputData();
if ($subscriptionForm->validate()) {
$subscriptionForm->execute();
$notificationManager = new NotificationManager();
$notificationManager->createTrivialNotification($request->getUser()->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS);
// Prepare the grid row data.
return DAO::getDataChangedEvent($subscriptionId);
} else {
return new JSONMessage(true, $subscriptionForm->fetch($request));
}
}
/**
* Delete a subscription.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteSubscription($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$context = $request->getContext();
$user = $request->getUser();
// Identify the subscription ID.
$subscriptionId = $request->getUserVar('rowId');
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
$subscriptionDao->deleteById($subscriptionId, $context->getId());
return DAO::getDataChangedEvent();
}
}
@@ -0,0 +1,72 @@
<?php
/**
* @file controllers/grid/subscriptions/PaymentsGridCellProvider.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 PaymentsGridCellProvider
*
* @ingroup controllers_grid_subscriptions
*
* @brief Class for a cell provider to display information about payments
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
class PaymentsGridCellProvider extends GridCellProvider
{
/** @var Request */
public $_request;
/**
* Constructor.
*
* @param Request $request
*/
public function __construct($request)
{
$this->_request = $request;
parent::__construct();
}
//
// Template methods from GridCellProvider
//
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$payment = $row->getData();
switch ($column->getId()) {
case 'name':
$user = Repo::user()->get($payment->getUserId(), true);
return ['label' => $user ? $user->getFullName() : __('common.user.nonexistent')]; // If no $user, returns "[Nonexistent user]" to avoid null user
case 'type':
$paymentManager = Application::getPaymentManager($this->_request->getJournal());
return ['label' => $paymentManager->getPaymentName($payment)];
case 'amount':
return ['label' => $payment->getAmount() . ' ' . $payment->getCurrencyCode()];
case 'timestamp':
return ['label' => $payment->getTimestamp()];
}
assert(false);
}
}
@@ -0,0 +1,143 @@
<?php
/**
* @file controllers/grid/subscriptions/PaymentsGridHandler.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 PaymentsGridHandler
*
* @ingroup controllers_grid_subscriptions
*
* @brief Handle payment grid requests.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Request;
use APP\payment\ojs\OJSCompletedPaymentDAO;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\db\DAORegistry;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
class PaymentsGridHandler extends GridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUBSCRIPTION_MANAGER],
['fetchGrid', 'fetchRow', 'viewPayment']
);
}
//
// Implement template methods from PKPHandler.
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Grid actions.
$router = $request->getRouter();
//
// Grid columns.
//
$cellProvider = new PaymentsGridCellProvider($request);
$this->addColumn(
new GridColumn(
'name',
'common.user',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'type',
'manager.payment.paymentType',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'amount',
'manager.payment.amount',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'timestamp',
'manager.payment.timestamp',
null,
null,
$cellProvider
)
);
}
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new PagingFeature()];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$paymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $paymentDao */
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
return $paymentDao->getByContextId($request->getContext()->getId(), $rangeInfo);
}
//
// Public grid actions.
//
/**
* View a payment.
*
* @param array $args
* @param Request $request
*/
public function viewPayment($args, $request)
{
// FIXME
}
}
@@ -0,0 +1,195 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionTypeForm.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 SubscriptionTypeForm
*
* @ingroup manager_form
*
* @brief Form for journal managers to create/edit subscription types.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Application;
use APP\subscription\SubscriptionType;
use APP\subscription\SubscriptionTypeDAO;
use APP\template\TemplateManager;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\form\Form;
class SubscriptionTypeForm extends Form
{
/** @var int $typeId the ID of the subscription type being edited */
public $typeId;
/** @var array $validFormats keys are valid subscription type formats */
public $validFormats;
/** @var array $validCurrencies keys are valid subscription type currencies */
public $validCurrencies;
/** @var int $journalId Journal ID */
public $journalId;
/**
* Constructor
*
* @param int $journalId Journal ID
* @param int $typeId leave as default for new subscription type
* @param null|mixed $typeId
*/
public function __construct($journalId, $typeId = null)
{
$this->journalId = $journalId;
$this->validFormats = [
SubscriptionType::SUBSCRIPTION_TYPE_FORMAT_ONLINE => __('subscriptionTypes.format.online'),
SubscriptionType::SUBSCRIPTION_TYPE_FORMAT_PRINT => __('subscriptionTypes.format.print'),
SubscriptionType::SUBSCRIPTION_TYPE_FORMAT_PRINT_ONLINE => __('subscriptionTypes.format.printOnline')
];
$this->validCurrencies = [];
foreach (Locale::getCurrencies() as $currency) {
$this->validCurrencies[$currency->getLetterCode()] = $currency->getLocalName() . ' (' . $currency->getLetterCode() . ')';
}
asort($this->validCurrencies);
$this->typeId = isset($typeId) ? (int) $typeId : null;
parent::__construct('payments/subscriptionTypeForm.tpl');
// Type name is provided
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'name', 'required', 'manager.subscriptionTypes.form.typeNameRequired'));
// Cost is provided and is numeric and positive
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'cost', 'required', 'manager.subscriptionTypes.form.costRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'cost', 'required', 'manager.subscriptionTypes.form.costNumeric', fn ($cost) => is_numeric($cost) && $cost >= 0));
// Currency is provided and is valid value
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'currency', 'required', 'manager.subscriptionTypes.form.currencyRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorInSet($this, 'currency', 'required', 'manager.subscriptionTypes.form.currencyValid', array_keys($this->validCurrencies)));
// Format is provided and is valid value
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'format', 'required', 'manager.subscriptionTypes.form.formatRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorInSet($this, 'format', 'required', 'manager.subscriptionTypes.form.formatValid', array_keys($this->validFormats)));
// Institutional flag is valid value
$this->addCheck(new \PKP\form\validation\FormValidatorInSet($this, 'institutional', 'optional', 'manager.subscriptionTypes.form.institutionalValid', ['0', '1']));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* Get a list of localized field names for this form
*
* @return array
*/
public function getLocaleFieldNames()
{
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
return $subscriptionTypeDao->getLocaleFieldNames();
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'typeId' => $this->typeId,
'validCurrencies' => $this->validCurrencies,
'validFormats' => $this->validFormats,
]);
return parent::fetch($request, $template, $display);
}
/**
* Initialize form data from current subscription type.
*/
public function initData()
{
if (isset($this->typeId)) {
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$subscriptionType = $subscriptionTypeDao->getById($this->typeId, $this->journalId);
if ($subscriptionType != null) {
$this->_data = [
'name' => $subscriptionType->getName(null), // Localized
'description' => $subscriptionType->getDescription(null), // Localized
'cost' => $subscriptionType->getCost(),
'currency' => $subscriptionType->getCurrencyCodeAlpha(),
'duration' => $subscriptionType->getDuration(),
'format' => $subscriptionType->getFormat(),
'institutional' => $subscriptionType->getInstitutional(),
'membership' => $subscriptionType->getMembership(),
'disable_public_display' => $subscriptionType->getDisablePublicDisplay()
];
} else {
$this->typeId = null;
}
}
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(['name', 'description', 'cost', 'currency', 'duration', 'format', 'institutional', 'membership', 'disable_public_display']);
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'duration', 'optional', 'manager.subscriptionTypes.form.durationNumeric', fn ($duration) => is_numeric($duration) && $duration >= 0));
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
if (isset($this->typeId)) {
$subscriptionType = $subscriptionTypeDao->getById($this->typeId, $this->journalId);
}
if (!isset($subscriptionType)) {
$subscriptionType = $subscriptionTypeDao->newDataObject();
$subscriptionType->setInstitutional($this->getData('institutional') == null ? 0 : $this->getData('institutional'));
}
$request = Application::get()->getRequest();
$journal = $request->getJournal();
$subscriptionType->setJournalId($journal->getId());
$subscriptionType->setName($this->getData('name'), null); // Localized
$subscriptionType->setDescription($this->getData('description'), null); // Localized
$subscriptionType->setCost(round($this->getData('cost'), 2));
$subscriptionType->setCurrencyCodeAlpha($this->getData('currency'));
$subscriptionType->setDuration(($duration = $this->getData('duration')) ? (int) $duration : null);
$subscriptionType->setFormat($this->getData('format'));
$subscriptionType->setMembership((int) $this->getData('membership'));
$subscriptionType->setDisablePublicDisplay((int) $this->getData('disable_public_display'));
parent::execute(...$functionArgs);
// Update or insert subscription type
if ($subscriptionType->getId() != null) {
$subscriptionTypeDao->updateObject($subscriptionType);
} else {
$subscriptionType->setSequence(REALLY_BIG_NUMBER);
$subscriptionTypeDao->insertObject($subscriptionType);
// Re-order the subscription types so the new one is at the end of the list.
$subscriptionTypeDao->resequenceSubscriptionTypes($subscriptionType->getJournalId());
}
}
}
@@ -0,0 +1,53 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionTypesGridCellProvider.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 SubscriptionTypesGridCellProvider
*
* @ingroup controllers_grid_subscriptions
*
* @brief Class for a cell provider to display information about individual subscriptions
*/
namespace APP\controllers\grid\subscriptions;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
class SubscriptionTypesGridCellProvider extends GridCellProvider
{
//
// Template methods from GridCellProvider
//
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$subscriptionType = $row->getData();
switch ($column->getId()) {
case 'name':
return ['label' => $subscriptionType->getLocalizedName()];
case 'type':
return ['label' => __($subscriptionType->getInstitutional() ? 'manager.subscriptionTypes.institutional' : 'manager.subscriptionTypes.individual')];
case 'duration':
return ['label' => $subscriptionType->getDurationYearsMonths()];
case 'cost':
return ['label' => sprintf('%.2f', $subscriptionType->getCost()) . ' (' . $subscriptionType->getCurrencyStringShort() . ')'];
}
assert(false);
}
}
@@ -0,0 +1,250 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionTypesGridHandler.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 SubscriptionTypesGridHandler
*
* @ingroup controllers_grid_subscriptions
*
* @brief Handle subscription type grid requests.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Request;
use APP\notification\NotificationManager;
use APP\subscription\SubscriptionTypeDAO;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\notification\PKPNotification;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
class SubscriptionTypesGridHandler extends GridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUBSCRIPTION_MANAGER],
['fetchGrid', 'fetchRow', 'editSubscriptionType', 'updateSubscriptionType',
'deleteSubscriptionType', 'addSubscriptionType']
);
}
//
// Implement template methods from PKPHandler.
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Basic grid configuration.
$this->setTitle('subscriptionManager.subscriptionTypes');
// Grid actions.
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'addSubscriptionType',
new AjaxModal(
$router->url($request, null, null, 'addSubscriptionType', null, null),
__('manager.subscriptionTypes.create'),
'modal_add_subscription_type',
true
),
__('manager.subscriptionTypes.create'),
'add_subscription_type'
)
);
//
// Grid columns.
//
$cellProvider = new SubscriptionTypesGridCellProvider();
$this->addColumn(
new GridColumn(
'name',
'common.name',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'type',
'manager.subscriptionTypes.subscriptions',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'duration',
'manager.subscriptionTypes.duration',
null,
null,
$cellProvider
)
);
$this->addColumn(
new GridColumn(
'cost',
'manager.subscriptionTypes.cost',
null,
null,
$cellProvider
)
);
}
//
// Implement methods from GridHandler.
//
/**
* @copydoc GridHandler::getRowInstance()
*
* @return SubscriptionTypesGridRow
*/
protected function getRowInstance()
{
return new SubscriptionTypesGridRow();
}
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new PagingFeature()];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
// Get the context.
$journal = $request->getContext();
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
return $subscriptionTypeDao->getByJournalId($journal->getId(), $rangeInfo);
}
//
// Public grid actions.
//
/**
* Add a new subscription type.
*
* @param array $args
* @param Request $request
*/
public function addSubscriptionType($args, $request)
{
// Calling editSubscription with an empty row id will add a new subscription type.
return $this->editSubscriptionType($args, $request);
}
/**
* Edit an existing subscription type.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editSubscriptionType($args, $request)
{
// Form handling.
$subscriptionTypeForm = new SubscriptionTypeForm($request->getJournal()->getId(), $request->getUserVar('rowId'));
$subscriptionTypeForm->initData();
return new JSONMessage(true, $subscriptionTypeForm->fetch($request));
}
/**
* Update an existing subscription type.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function updateSubscriptionType($args, $request)
{
$subscriptionTypeId = (int) $request->getUserVar('typeId');
// Form handling.
$subscriptionTypeForm = new SubscriptionTypeForm($request->getJournal()->getId(), $subscriptionTypeId);
$subscriptionTypeForm->readInputData();
if ($subscriptionTypeForm->validate()) {
$subscriptionTypeForm->execute();
$notificationManager = new NotificationManager();
$notificationManager->createTrivialNotification($request->getUser()->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS);
// Prepare the grid row data.
return DAO::getDataChangedEvent($subscriptionTypeId);
} else {
return new JSONMessage(false);
}
}
/**
* Delete a subscription type.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteSubscriptionType($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$context = $request->getContext();
$user = $request->getUser();
// Identify the subscription type ID.
$subscriptionTypeId = $request->getUserVar('rowId');
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
$subscriptionTypeDao->deleteById($subscriptionTypeId, $context->getId());
return DAO::getDataChangedEvent($subscriptionTypeId);
}
}
@@ -0,0 +1,82 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionTypesGridRow.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 SubscriptionTypesGridRow
*
* @ingroup controllers_grid_subscriptions
*
* @brief User grid row definition
*/
namespace APP\controllers\grid\subscriptions;
use PKP\controllers\grid\GridRow;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class SubscriptionTypesGridRow extends GridRow
{
//
// Overridden methods from GridRow
//
/**
* @copydoc GridRow::initialize()
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
// Is this a new row or an existing row?
$element = & $this->getData();
assert(is_a($element, 'SubscriptionType'));
$rowId = $this->getId();
if (!empty($rowId) && is_numeric($rowId)) {
// Only add row actions if this is an existing row
$router = $request->getRouter();
$actionArgs = [
'gridId' => $this->getGridId(),
'rowId' => $rowId
];
$actionArgs = array_merge($actionArgs, $this->getRequestArgs());
$this->addAction(
new LinkAction(
'edit',
new AjaxModal(
$router->url($request, null, null, 'editSubscriptionType', null, $actionArgs),
__('manager.subscriptionTypes.edit'),
'modal_edit',
true
),
__('common.edit'),
'edit'
)
);
$this->addAction(
new LinkAction(
'delete',
new RemoteActionConfirmationModal(
$request->getSession(),
__('manager.subscriptionTypes.confirmDelete'),
__('common.delete'),
$router->url($request, null, null, 'deleteSubscriptionType', null, $actionArgs),
'modal_delete'
),
__('grid.action.delete'),
'delete'
)
);
}
}
}
@@ -0,0 +1,69 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionsGridCellProvider.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 SubscriptionsGridCellProvider
*
* @ingroup controllers_grid_subscriptions
*
* @brief Class for a cell provider to display information about subscriptions
*/
namespace APP\controllers\grid\subscriptions;
use APP\facades\Repo;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
class SubscriptionsGridCellProvider extends GridCellProvider
{
//
// Template methods from GridCellProvider
//
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$subscription = $row->getData();
switch ($column->getId()) {
case 'name':
switch (1) {
case is_a($subscription, 'IndividualSubscription'):
return ['label' => $subscription->getUserFullName()];
case is_a($subscription, 'InstitutionalSubscription'):
$institution = Repo::institution()->get($subscription->getInstitutionId());
return ['label' => $institution->getLocalizedName()];
}
assert(false);
break;
case 'email':
assert(is_a($subscription, 'IndividualSubscription'));
return ['label' => $subscription->getUserEmail()];
case 'subscriptionType':
return ['label' => $subscription->getSubscriptionTypeName()];
case 'status':
return ['label' => $subscription->getStatusString()];
case 'dateStart':
return ['label' => $subscription->getDateStart()];
case 'dateEnd':
return ['label' => $subscription->getDateEnd()];
case 'referenceNumber':
return ['label' => $subscription->getReferenceNumber()];
}
assert(false);
}
}
@@ -0,0 +1,166 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionsGridHandler.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 SubscriptionsGridHandler
*
* @ingroup controllers_grid_subscriptions
*
* @brief Handle subscription grid requests.
*/
namespace APP\controllers\grid\subscriptions;
use APP\core\Request;
use APP\subscription\IndividualSubscriptionDAO;
use APP\subscription\InstitutionalSubscriptionDAO;
use PKP\controllers\grid\feature\PagingFeature;
use PKP\controllers\grid\GridHandler;
use PKP\db\DAO;
use PKP\db\DAORegistry;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
abstract class SubscriptionsGridHandler extends GridHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUBSCRIPTION_MANAGER],
['fetchGrid', 'fetchRow', 'editSubscription', 'updateSubscription',
'deleteSubscription', 'addSubscription', 'renewSubscription']
);
}
//
// Implement template methods from PKPHandler.
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
// Grid actions.
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'addSubscription',
new AjaxModal(
$router->url($request, null, null, 'addSubscription', null, null),
__('manager.subscriptions.create'),
'modal_add_subscription',
true
),
__('manager.subscriptions.create'),
'add_subscription'
)
);
}
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new PagingFeature()];
}
/**
* @copydoc GridHandler::getRowInstance()
*
* @return SubscriptionsGridRow
*/
protected function getRowInstance()
{
return new SubscriptionsGridRow();
}
/**
* @copydoc GridHandler::getFilterSelectionData()
*
* @return array Filter selection data.
*/
public function getFilterSelectionData($request)
{
// Get the search terms.
$searchField = $request->getUserVar('searchField');
$searchMatch = $request->getUserVar('searchMatch');
$search = $request->getUserVar('search');
return $filterSelectionData = [
'searchField' => $searchField,
'searchMatch' => $searchMatch,
'search' => $search ? $search : ''
];
}
/**
* @copydoc GridHandler::getFilterForm()
*
* @return string Filter template.
*/
protected function getFilterForm()
{
return 'controllers/grid/subscriptions/subscriptionsGridFilter.tpl';
}
//
// Public grid actions.
//
/**
* Add a new subscription.
*
* @param array $args
* @param Request $request
*/
public function addSubscription($args, $request)
{
// Calling editSubscription with an empty row id will add a new subscription.
return $this->editSubscription($args, $request);
}
/**
* Renew a subscription.
*
* @param array $args first parameter is the ID of the subscription to renew
* @param Request $request
*/
public function renewSubscription($args, $request)
{
/** @var InstitutionalSubscriptionDAO|IndividualSubscriptionDAO */
$subscriptionDao = DAORegistry::getDAO($request->getUserVar('institutional') ? 'InstitutionalSubscriptionDAO' : 'IndividualSubscriptionDAO');
$subscriptionId = $request->getUserVar('rowId');
if ($subscription = $subscriptionDao->getById($subscriptionId, $request->getJournal()->getId())) {
$subscriptionDao->renewSubscription($subscription);
}
return DAO::getDataChangedEvent($subscriptionId);
}
}
@@ -0,0 +1,102 @@
<?php
/**
* @file controllers/grid/subscriptions/SubscriptionsGridRow.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 SubscriptionsGridRow
*
* @ingroup controllers_grid_subscriptions
*
* @brief Subscriptions grid row definition
*/
namespace APP\controllers\grid\subscriptions;
use PKP\controllers\grid\GridRow;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class SubscriptionsGridRow extends GridRow
{
//
// Overridden methods from GridRow
//
/**
* @copydoc GridRow::initialize()
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
// Is this a new row or an existing row?
$element = & $this->getData();
assert(is_a($element, 'IndividualSubscription') || is_a($element, 'InstitutionalSubscription'));
$rowId = $this->getId();
if (!empty($rowId) && is_numeric($rowId)) {
// Only add row actions if this is an existing row
$router = $request->getRouter();
$actionArgs = [
'gridId' => $this->getGridId(),
'rowId' => $rowId
];
$actionArgs = array_merge($actionArgs, $this->getRequestArgs());
$this->addAction(new LinkAction(
'edit',
new AjaxModal(
$router->url($request, null, null, 'editSubscription', null, $actionArgs),
__('manager.subscriptions.edit'),
'modal_edit',
true
),
__('common.edit'),
'edit'
));
if (!$element->isNonExpiring()) {
$this->addAction(new LinkAction(
'renew',
new RemoteActionConfirmationModal(
$request->getSession(),
__('manager.subscriptions.confirmRenew'),
__('manager.subscriptions.renew'),
$router->url(
$request,
null,
null,
'renewSubscription',
null,
array_merge($actionArgs, [
'institutional' => is_a($element, 'InstitutionalSubscription') ? 1 : 0
])
),
'modal_delete'
),
__('manager.subscriptions.renew'),
'renew'
));
}
$this->addAction(new LinkAction(
'delete',
new RemoteActionConfirmationModal(
$request->getSession(),
__('subscriptionManager.subscription.confirmRemove'),
__('common.delete'),
$router->url($request, null, null, 'deleteSubscription', null, $actionArgs),
'modal_delete'
),
__('grid.action.delete'),
'delete'
));
}
}
}
@@ -0,0 +1,35 @@
<?php
/**
* @file controllers/grid/toc/TocGridCategoryRow.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 TocGridCategoryRow
*
* @ingroup controllers_grid_admin_systemInfo
*
* @brief System Info grid category row definition
*/
namespace APP\controllers\grid\toc;
use PKP\controllers\grid\GridCategoryRow;
class TocGridCategoryRow extends GridCategoryRow
{
//
// Overridden methods from GridCategoryRow
//
/**
* Use a label if the actions in the grid are disabled.
* return string
*/
public function getCategoryLabel()
{
$section = $this->getData();
return $section->getLocalizedTitle();
}
}
@@ -0,0 +1,83 @@
<?php
/**
* @file controllers/grid/toc/TocGridCellProvider.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 TocGridCellProvider
*
* @ingroup controllers_grid_toc
*
* @brief Grid cell provider for the TOC (Table of Contents) category grid
*/
namespace APP\controllers\grid\toc;
use APP\submission\Submission;
use PKP\controllers\grid\GridCellProvider;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxAction;
class TocGridCellProvider extends GridCellProvider
{
/**
* Extracts variables for a given column from a data element
* so that they may be assigned to template before rendering.
*
* @param \PKP\controllers\grid\GridRow $row
* @param GridColumn $column
*
* @return array
*/
public function getTemplateVarsFromRowColumn($row, $column)
{
$element = $row->getData();
$columnId = $column->getId();
assert(!empty($columnId));
switch ($columnId) {
case 'title':
return ['label' => $element->getLocalizedTitle()];
case 'access':
return ['selected' => $element->getCurrentPublication()->getData('accessStatus') == Submission::ARTICLE_ACCESS_OPEN];
default: assert(false);
}
}
/**
* @copydoc GridCellProvider::getCellActions()
*/
public function getCellActions($request, $row, $column, $position = GridHandler::GRID_ACTION_POSITION_DEFAULT)
{
switch ($column->getId()) {
case 'access':
$article = $row->getData(); /** @var Submission $article */
return [new LinkAction(
'disable',
new AjaxAction(
$request->url(
null,
null,
'setAccessStatus',
null,
array_merge(
[
'articleId' => $article->getId(),
'status' => ($article->getCurrentPublication()->getData('accessStatus') == Submission::ARTICLE_ACCESS_OPEN) ? Submission::ARTICLE_ACCESS_ISSUE_DEFAULT : Submission::ARTICLE_ACCESS_OPEN,
'csrfToken' => $request->getSession()->getCSRFToken(),
],
$row->getRequestArgs()
)
)
),
__('manager.plugins.disable'),
null
)];
}
return parent::getCellActions($request, $row, $column, $position);
}
}
+300
View File
@@ -0,0 +1,300 @@
<?php
/**
* @file controllers/grid/toc/TocGridHandler.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 TocGridHandler
*
* @ingroup controllers_grid_toc
*
* @brief Handle TOC (table of contents) grid requests.
*/
namespace APP\controllers\grid\toc;
use APP\core\Application;
use APP\core\Request;
use APP\facades\Repo;
use APP\section\Section;
use APP\security\authorization\OjsIssueRequiredPolicy;
use APP\submission\Submission;
use PKP\controllers\grid\CategoryGridHandler;
use PKP\controllers\grid\feature\OrderCategoryGridItemsFeature;
use PKP\controllers\grid\GridColumn;
use PKP\core\JSONMessage;
use PKP\db\DAO;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
use PKP\submission\PKPSubmission;
class TocGridHandler extends CategoryGridHandler
{
public $submissionsBySectionId = [];
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
['fetchGrid', 'fetchCategory', 'fetchRow', 'saveSequence', 'removeArticle', 'setAccessStatus']
);
$this->submissionsBySectionId = [];
}
//
// Implement template methods from PKPHandler.
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
$this->addPolicy(new OjsIssueRequiredPolicy($request, $args));
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc CategoryGridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
//
// Grid columns.
//
$tocGridCellProvider = new TocGridCellProvider();
// Article title
$this->addColumn(
new GridColumn(
'title',
'article.title',
null,
null,
$tocGridCellProvider
)
);
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
if ($request->getJournal()->getData('publishingMode') == \APP\journal\Journal::PUBLISHING_MODE_SUBSCRIPTION && $issue->getAccessStatus() == \APP\issue\Issue::ISSUE_ACCESS_SUBSCRIPTION) {
// Article access status
$this->addColumn(
new GridColumn(
'access',
'reader.openAccess',
null,
'controllers/grid/common/cell/selectStatusCell.tpl',
$tocGridCellProvider,
['width' => 20, 'alignment' => GridColumn::COLUMN_ALIGNMENT_CENTER]
)
);
}
}
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new OrderCategoryGridItemsFeature(OrderCategoryGridItemsFeature::ORDER_CATEGORY_GRID_CATEGORIES_AND_ROWS, true, $this)];
}
/**
* @copydoc CategoryGridHandler::getCategoryRowIdParameterName()
*/
public function getCategoryRowIdParameterName()
{
return 'sectionId';
}
/**
* @copydoc GridDataProvider::getRequestArgs()
*/
public function getRequestArgs()
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
return array_merge(
parent::getRequestArgs(),
['issueId' => $issue->getId()]
);
}
/**
* Get the row handler - override the default row handler
*
* @return TocGridRow
*/
protected function getRowInstance()
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
return new TocGridRow($issue->getId());
}
/**
* @copydoc CategoryGridHandler::getCategoryRowInstance()
*/
protected function getCategoryRowInstance()
{
return new TocGridCategoryRow();
}
/**
* @copydoc CategoryGridHandler::loadCategoryData()
*
* @param null|mixed $filter
*/
public function loadCategoryData($request, &$section, $filter = null)
{
return $this->submissionsBySectionId[$section->getId()];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$submissionsInSections = Repo::submission()->getInSections($issue->getId(), $request->getContext()->getId());
foreach ($submissionsInSections as $sectionId => $articles) {
foreach ($articles['articles'] as $article) {
$this->submissionsBySectionId[$sectionId][$article->getId()] = $article;
}
}
$sections = Repo::section()->getByIssueId($issue->getId());
$arrayKeySections = [];
foreach ($sections as $section) {
$arrayKeySections[$section->getId()] = $section;
}
return $arrayKeySections;
}
/**
* @copydoc GridHandler::getDataElementSequence()
*
* @param Section|Submission $object
*/
public function getDataElementSequence($object)
{
if ($object instanceof Submission) {
return $object->getCurrentPublication()->getData('seq');
} else { // section
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$customOrdering = Repo::section()->getCustomSectionOrder($issue->getId(), $object->getId());
if ($customOrdering === null) { // No custom ordering specified; use default section ordering
return $object->getSequence();
} else { // Custom ordering specified.
return $customOrdering;
}
}
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementSequence($request, $sectionId, $gridDataElement, $newSequence)
{
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
Repo::section()->upsertCustomSectionOrder($issue->getId(), $sectionId, $newSequence);
}
/**
* @copydoc CategoryGridHandler::getDataElementInCategorySequence()
*/
public function getDataElementInCategorySequence($categoryId, &$submission)
{
return $submission->getCurrentPublication()->getData('seq');
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
public function setDataElementInCategorySequence($sectionId, &$submission, $newSequence)
{
$publication = $submission->getCurrentPublication();
$params = ['seq' => $newSequence];
if ($sectionId != $publication->getData('sectionId')) {
$params['sectionId'] = $sectionId;
}
Repo::publication()->edit($publication, $params);
}
//
// Public handler functions
//
/**
* Remove an article from the issue.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function removeArticle($args, $request)
{
$journal = $request->getJournal();
$submission = Repo::submission()->get((int) $request->getUserVar('articleId'));
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
if ($submission && $request->checkCSRF()) {
foreach ($submission->getData('publications') as $publication) {
if ($publication->getData('issueId') === (int) $issue->getId()
&& in_array($publication->getData('status'), [PKPSubmission::STATUS_SCHEDULED, PKPSubmission::STATUS_PUBLISHED])) {
Repo::publication()->unpublish($publication);
$publication = Repo::publication()->get($publication->getId());
Repo::publication()->edit(
$publication,
['seq' => '']
);
}
}
// If the article is the only one in the section, delete the section from custom issue ordering
$sectionId = $submission->getCurrentPublication()->getData('sectionId');
$submissionsInSections = Repo::submission()->getInSections($issue->getId(), $issue->getJournalId());
if (!empty($submissionsInSections[$sectionId]) && count($submissionsInSections[$sectionId]) === 1) {
Repo::section()->deleteCustomSectionOrder($issue->getId(), $sectionId);
}
return DAO::getDataChangedEvent();
}
// If we've fallen through, it must be a badly-specified article
return new JSONMessage(false);
}
/**
* Set access status on an article.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function setAccessStatus($args, $request)
{
$articleId = (int) $request->getUserVar('articleId');
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
$submission = Repo::submission()->get($articleId);
$publication = $submission ? $submission->getCurrentPublication() : null;
if ($publication && $publication->getData('issueId') == $issue->getId() && $request->checkCSRF()) {
Repo::publication()->edit($publication, ['accessStatus' => $request->getUserVar('status')]);
return DAO::getDataChangedEvent();
}
// If we've fallen through, it must be a badly-specified article
return new JSONMessage(false);
}
}
+81
View File
@@ -0,0 +1,81 @@
<?php
/**
* @file controllers/grid/toc/TocGridRow.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 TocGridRow
*
* @ingroup controllers_grid_settings_issue
*
* @brief Handle issue grid row requests.
*/
namespace APP\controllers\grid\toc;
use PKP\controllers\grid\GridRow;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\RedirectAction;
use PKP\linkAction\request\RemoteActionConfirmationModal;
class TocGridRow extends GridRow
{
/** @var int */
public $issueId;
/**
* Constructor
*
* @param int $issueId
*/
public function __construct($issueId)
{
parent::__construct();
$this->issueId = $issueId;
}
//
// Overridden template methods
//
/**
* @copydoc GridRow::initialize
*
* @param null|mixed $template
*/
public function initialize($request, $template = null)
{
parent::initialize($request, $template);
$dispatcher = $request->getDispatcher();
$this->addAction(
new LinkAction(
'workflow',
new RedirectAction(
$dispatcher->url($request, PKPApplication::ROUTE_PAGE, null, 'workflow', 'access', [$this->getId()])
),
__('submission.submission'),
'information'
)
);
$router = $request->getRouter();
$this->addAction(
new LinkAction(
'removeArticle',
new RemoteActionConfirmationModal(
$request->getSession(),
__('editor.article.remove.confirm'),
__('grid.action.removeArticle'),
$router->url($request, null, null, 'removeArticle', null, ['articleId' => $this->getId(), 'issueId' => $this->issueId]),
'modal_delete'
),
__('editor.article.remove'),
'delete'
)
);
}
}
@@ -0,0 +1,66 @@
<?php
/**
* @file controllers/grid/users/reviewer/ReviewerGridHandler.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 ReviewerGridHandler
*
* @ingroup controllers_grid_users_reviewer
*
* @brief Handle reviewer grid requests.
*/
namespace APP\controllers\grid\users\reviewer;
use APP\core\Application;
use APP\facades\Repo;
use PKP\controllers\grid\users\reviewer\PKPReviewerGridHandler;
use PKP\core\Core;
use PKP\core\PKPApplication;
use PKP\security\Validation;
class ReviewerGridHandler extends PKPReviewerGridHandler
{
/**
* @copydoc PKPReviewerGridHandler::reviewRead()
*/
public function reviewRead($args, $request)
{
// Retrieve review assignment.
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT); /** @var \PKP\submission\reviewAssignment\ReviewAssignment $reviewAssignment */
// Recommendation
$newRecommendation = $request->getUserVar('recommendation');
// If editor set or changed the recommendation
if ($newRecommendation && $reviewAssignment->getRecommendation() != $newRecommendation) {
$reviewAssignment->setRecommendation($newRecommendation);
// Add log entry
$submission = $this->getSubmission();
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId(), true);
$user = $request->getUser();
class_exists(\APP\log\event\SubmissionEventLogEntry::class); // Force definition of SUBMISSION_LOG_REVIEW_RECOMMENDATION_BY_PROXY
$eventLog = Repo::eventLog()->newDataObject([
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
'assocId' => $submission->getId(),
'eventType' => \SUBMISSION_LOG_REVIEW_RECOMMENDATION_BY_PROXY,
'userId' => Validation::loggedInAs() ?? $user->getId(),
'message' => 'log.review.reviewRecommendationSetByProxy',
'isTranslated' => false,
'dateLogged' => Core::getCurrentDate(),
'round' => $reviewAssignment->getRound(),
'submissionId' => $submission->getId(),
'editorName' => $user->getFullName(),
'reviewAssignmentId' => $reviewAssignment->getId(),
'reviewerName' => $reviewer->getFullName(),
]);
Repo::eventLog()->add($eventLog);
}
return parent::reviewRead($args, $request);
}
}
@@ -0,0 +1,233 @@
<?php
/**
* @file controllers/grid/users/subscriberSelect/SubscriberSelectGridHandler.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 SubscriberSelectGridHandler
*
* @ingroup controllers_grid_users_subscriberSelect
*
* @brief Handle subscriber selector grid requests.
*/
namespace APP\controllers\grid\users\subscriberSelect;
use APP\core\Application;
use APP\facades\Repo;
use PKP\controllers\grid\feature\CollapsibleGridFeature;
use PKP\controllers\grid\feature\InfiniteScrollingFeature;
use PKP\controllers\grid\GridColumn;
use PKP\controllers\grid\GridHandler;
use PKP\controllers\grid\users\userSelect\UserSelectGridCellProvider;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\Role;
class SubscriberSelectGridHandler extends GridHandler
{
/** @var array (user group ID => user group name) */
public $_userGroupOptions;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUBSCRIPTION_MANAGER],
['fetchGrid', 'fetchRows']
);
}
//
// Implement template methods from PKPHandler
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*
* @param null|mixed $args
*/
public function initialize($request, $args = null)
{
parent::initialize($request, $args);
$stageId = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
$userGroups = Repo::userGroup()->getUserGroupsByStage(
$request->getContext()->getId(),
$stageId
);
$this->_userGroupOptions = [];
foreach ($userGroups as $userGroup) {
$this->_userGroupOptions[$userGroup->getId()] = $userGroup->getLocalizedName();
}
$this->setTitle('editor.submission.findAndSelectUser');
// Columns
$cellProvider = new UserSelectGridCellProvider($request->getUserVar('userId'));
$this->addColumn(
new GridColumn(
'select',
'',
null,
'controllers/grid/users/userSelect/userSelectRadioButton.tpl',
$cellProvider,
['width' => 5]
)
);
$this->addColumn(
new GridColumn(
'name',
'common.name',
null,
null,
$cellProvider,
['alignment' => GridColumn::COLUMN_ALIGNMENT_LEFT,
'width' => 30
]
)
);
}
//
// Overridden methods from GridHandler
//
/**
* @copydoc GridHandler::initFeatures()
*/
public function initFeatures($request, $args)
{
return [new InfiniteScrollingFeature('infiniteScrolling', $this->getItemsNumber()), new CollapsibleGridFeature()];
}
/**
* @copydoc GridHandler::loadData()
*/
protected function loadData($request, $filter)
{
// Get the context.
$context = $request->getContext();
// Get all users for this context that match search criteria.
$rangeInfo = $this->getGridRangeInfo($request, $this->getId());
// The user interface uses filter['userGroup'] and $filter['search']
$userGroupSearchTerm = $filter['userGroup'] ? [$filter['userGroup']] : null;
$userCollector = Repo::user()->getCollector()
->filterByContextIds([$context->getId()])
->searchPhrase($filter['search'])
->filterByUserGroupIds($userGroupSearchTerm)
->limit($rangeInfo->getCount())
->offset($rangeInfo->getOffset() + max(0, $rangeInfo->getPage() - 1) * $rangeInfo->getCount());
$users = $userCollector->getMany();
$totalCount = $userCollector->limit(null)->offset(null)->getCount();
return new \PKP\core\VirtualArrayIterator(iterator_to_array($users, true), $totalCount, $rangeInfo->getPage(), $rangeInfo->getCount());
}
/**
* @copydoc GridHandler::renderFilter()
*/
public function renderFilter($request, $filterData = [])
{
$context = $request->getContext();
$userGroups = Repo::userGroup()->getCollector()
->filterByContextIds([$context->getId()])
->getMany();
$userGroupOptions = ['' => __('grid.user.allRoles')];
foreach ($userGroups as $userGroup) {
$userGroupOptions[$userGroup->getId()] = $userGroup->getLocalizedName();
}
return parent::renderFilter(
$request,
[
'userGroupOptions' => $userGroupOptions,
]
);
}
/**
* @copydoc GridHandler::getFilterSelectionData()
*
* @return array Filter selection data.
*/
public function getFilterSelectionData($request)
{
// If we're editing an existing subscription, use the filter form to ensure that
// the already-selected user is chosen.
if (($userId = (int) $request->getUserVar('userId')) && !$request->getUserVar('clientSubmit')) {
return [
'userGroup' => null,
'searchField' => Repo::user()->dao::USER_FIELD_USERNAME,
'searchMatch' => 'is',
'search' => Repo::user()->get($userId)->getUsername(),
];
}
return [
'userGroup' => $request->getUserVar('userGroup') ? (int) $request->getUserVar('userGroup') : null,
'searchField' => $request->getUserVar('searchField'),
'searchMatch' => $request->getUserVar('searchMatch'),
'search' => (string) $request->getUserVar('search'),
];
}
/**
* @copydoc GridHandler::getFilterForm()
*
* @return string Filter template.
*/
protected function getFilterForm()
{
return 'controllers/grid/users/exportableUsers/userGridFilter.tpl';
}
/**
* Determine whether a filter form should be collapsible.
*
* @return bool
*/
protected function isFilterFormCollapsible()
{
return false;
}
/**
* Define how many items this grid will start loading.
*
* @return int
*/
protected function getItemsNumber()
{
return 5;
}
/**
* @copydoc GridHandler::getRequestArgs()
*/
public function getRequestArgs()
{
$request = Application::get()->getRequest();
return array_merge(parent::getRequestArgs(), [
'userId' => $request->getUserVar('userId'),
]);
}
}
@@ -0,0 +1,112 @@
<?php
/**
* @file controllers/modals/publish/AssignToIssueHandler.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 AssignToIssueHandler
*
* @ingroup controllers_modals_publish
*
* @brief A handler to assign a publication to an issue before scheduling for
* publication
*/
namespace APP\controllers\modals\publish;
use APP\components\forms\publication\AssignToIssueForm;
use APP\core\Application;
use APP\core\Request;
use APP\core\Services;
use APP\handler\Handler;
use APP\publication\Publication;
use APP\submission\Submission;
use APP\template\TemplateManager;
use PKP\core\JSONMessage;
use PKP\core\PKPApplication;
use PKP\security\authorization\PublicationAccessPolicy;
use PKP\security\authorization\SubmissionAccessPolicy;
use PKP\security\Role;
class AssignToIssueHandler extends Handler
{
/** @var Submission */
public $submission;
/** @var Publication */
public $publication;
/**
* Constructor.
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_ASSISTANT],
['assign']
);
}
//
// Overridden methods from Handler
//
/**
* @copydoc PKPHandler::initialize()
*/
public function initialize($request)
{
parent::initialize($request);
$this->submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
$this->publication = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_PUBLICATION);
$this->setupTemplate($request);
}
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new SubmissionAccessPolicy($request, $args, $roleAssignments));
$this->addPolicy(new PublicationAccessPolicy($request, $args, $roleAssignments));
return parent::authorize($request, $args, $roleAssignments);
}
//
// Public handler methods
//
/**
* Display a form to assign an issue to a publication
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function assign($args, $request)
{
$templateMgr = TemplateManager::getManager($request);
$submissionContext = $request->getContext();
if (!$submissionContext || $submissionContext->getId() !== $this->submission->getData('contextId')) {
$submissionContext = Services::get('context')->get($this->submission->getData('contextId'));
}
$publicationApiUrl = $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $submissionContext->getPath(), 'submissions/' . $this->submission->getId() . '/publications/' . $this->publication->getId());
$assignToIssueForm = new AssignToIssueForm($publicationApiUrl, $this->publication, $submissionContext);
$settingsData = [
'components' => [
FORM_ASSIGN_TO_ISSUE => $assignToIssueForm->getConfig(),
],
];
$templateMgr->assign('assignData', $settingsData);
return $templateMgr->fetchJson('controllers/modals/publish/assignToIssue.tpl');
}
}
@@ -0,0 +1,86 @@
<?php
/**
* @file controllers/tab/pubIds/form/PublicIdentifiersForm.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 PublicIdentifiersForm
*
* @ingroup controllers_tab_pubIds_form
*
* @brief Displays a pub ids form.
*/
namespace APP\controllers\tab\pubIds\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\issue\Issue;
use APP\issue\IssueGalley;
use APP\template\TemplateManager;
use PKP\controllers\tab\pubIds\form\PKPPublicIdentifiersForm;
use PKP\galley\Galley;
use PKP\plugins\PluginRegistry;
class PublicIdentifiersForm extends PKPPublicIdentifiersForm
{
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$enablePublisherId = (array) $request->getContext()->getData('enablePublisherId');
$templateMgr->assign([
'enablePublisherId' => ($this->getPubObject() instanceof Galley && in_array('galley', $enablePublisherId)) ||
($this->getPubObject() instanceof Issue && in_array('issue', $enablePublisherId)) ||
($this->getPubObject() instanceof IssueGalley && in_array('issueGalley', $enablePublisherId)),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
parent::execute(...$functionArgs);
$pubObject = $this->getPubObject();
if ($pubObject instanceof Issue) {
Repo::issue()->edit($pubObject, []);
}
}
/**
* Clear issue objects pub ids.
*
* @param string $pubIdPlugInClassName
*/
public function clearIssueObjectsPubIds($pubIdPlugInClassName)
{
$pubIdPlugins = PluginRegistry::loadCategory('pubIds', true);
foreach ($pubIdPlugins as $pubIdPlugin) {
$classNameParts = explode('\\', get_class($pubIdPlugin)); // Separate namespace info from class name
if (end($classNameParts) == $pubIdPlugInClassName) {
$pubIdPlugin->clearIssueObjectsPubIds($this->getPubObject());
}
}
}
/**
* @copydoc PKPPublicIdentifiersForm::getAssocType()
*/
public function getAssocType($pubObject)
{
if ($pubObject instanceof Issue) {
return Application::ASSOC_TYPE_ISSUE;
}
return parent::getAssocType($pubObject);
}
}
@@ -0,0 +1,52 @@
<?php
/**
* @file controllers/tab/workflow/ReviewRoundTabHandler.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 ReviewRoundTabHandler
*
* @ingroup controllers_tab_workflow
*
* @brief Handle AJAX operations for review round tabs on review stages workflow pages.
*/
namespace APP\controllers\tab\workflow;
use PKP\controllers\tab\workflow\PKPReviewRoundTabHandler;
use PKP\security\authorization\WorkflowStageAccessPolicy;
use PKP\security\Role;
class ReviewRoundTabHandler extends PKPReviewRoundTabHandler
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->addRoleAssignment(
[Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_ASSISTANT],
['externalReviewRound']
);
}
//
// Extended methods from Handler
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$stageId = (int) $request->getUserVar('stageId'); // This is validated in WorkflowStageAccessPolicy.
$this->addPolicy(new WorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $stageId));
return parent::authorize($request, $args, $roleAssignments);
}
}
@@ -0,0 +1,90 @@
<?php
/**
* @file controllers/tab/workflow/WorkflowTabHandler.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 WorkflowTabHandler
*
* @ingroup controllers_tab_workflow
*
* @brief Handle AJAX operations for workflow tabs.
*/
namespace APP\controllers\tab\workflow;
use APP\core\Application;
use APP\notification\Notification;
use APP\template\TemplateManager;
use PKP\controllers\tab\workflow\PKPWorkflowTabHandler;
use PKP\core\PKPApplication;
use PKP\decision\DecisionType;
use PKP\decision\types\NewExternalReviewRound;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
use PKP\notification\PKPNotification;
class WorkflowTabHandler extends PKPWorkflowTabHandler
{
/**
* @copydoc PKPWorkflowTabHandler::fetchTab
*/
public function fetchTab($args, $request)
{
$this->setupTemplate($request);
$templateMgr = TemplateManager::getManager($request);
$stageId = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
switch ($stageId) {
case WORKFLOW_STAGE_ID_PRODUCTION:
$dispatcher = $request->getDispatcher();
$schedulePublicationLinkAction = new LinkAction(
'schedulePublication',
new AjaxModal(
$dispatcher->url(
$request,
PKPApplication::ROUTE_COMPONENT,
null,
'tab.issueEntry.IssueEntryTabHandler',
'publicationMetadata',
null,
['submissionId' => $submission->getId(), 'stageId' => $stageId]
),
__('submission.publication')
),
__('editor.submission.schedulePublication')
);
$templateMgr->assign('schedulePublicationLinkAction', $schedulePublicationLinkAction);
break;
}
return parent::fetchTab($args, $request);
}
/**
* Get all production notification options to be used in the production stage tab.
*
* @param int $submissionId
*
* @return array
*/
protected function getProductionNotificationOptions($submissionId)
{
return [
Notification::NOTIFICATION_LEVEL_NORMAL => [
PKPNotification::NOTIFICATION_TYPE_VISIT_CATALOG => [Application::ASSOC_TYPE_SUBMISSION, $submissionId],
PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER => [Application::ASSOC_TYPE_SUBMISSION, $submissionId],
PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS => [Application::ASSOC_TYPE_SUBMISSION, $submissionId],
],
Notification::NOTIFICATION_LEVEL_TRIVIAL => []
];
}
protected function getNewReviewRoundDecisionType(int $stageId): DecisionType
{
// OJS only supports the external review stage
return new NewExternalReviewRound();
}
}