[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
classes
/
controllers
/
grid
/
issues
/
[
Home
]
File: IssueGridHandler.php
<?php /** * @defgroup controllers_grid_issues Issues Grid * The Issues Grid implements the management interface allowing editors to * manage future and archived issues. */ /** * @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 IssueGridHandler * * @ingroup controllers_grid_issues * * @brief Handle issues grid requests. */ namespace APP\controllers\grid\issues; use APP\controllers\grid\issues\form\IssueAccessForm; use APP\controllers\grid\issues\form\IssueForm; use APP\controllers\grid\pubIds\form\AssignPublicIdentifiersForm; use APP\controllers\tab\pubIds\form\PublicIdentifiersForm; use APP\core\Application; use APP\core\Request; use APP\facades\Repo; use APP\file\PublicFileManager; use APP\issue\Collector; use APP\jobs\notifications\IssuePublishedNotifyUsers; use APP\notification\Notification; use APP\notification\NotificationManager; use APP\publication\Publication; use APP\security\authorization\OjsIssueRequiredPolicy; use APP\submission\Submission; use APP\template\TemplateManager; use Illuminate\Support\Facades\Bus; use PKP\controllers\grid\GridColumn; use PKP\controllers\grid\GridHandler; use PKP\core\Core; use PKP\core\JSONMessage; use PKP\core\PKPApplication; use PKP\db\DAO; use PKP\db\DAORegistry; use PKP\facades\Locale; use PKP\file\TemporaryFileManager; use PKP\mail\Mailer; use PKP\notification\NotificationSubscriptionSettingsDAO; use PKP\notification\PKPNotification; use PKP\plugins\Hook; use PKP\plugins\PluginRegistry; use PKP\security\authorization\ContextAccessPolicy; use PKP\security\Role; class IssueGridHandler extends GridHandler { /** * Constructor */ public function __construct() { parent::__construct(); $this->addRoleAssignment( [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN], [ 'fetchGrid', 'fetchRow', 'addIssue', 'editIssue', 'editIssueData', 'updateIssue', 'uploadFile', 'deleteCoverImage', 'issueToc', 'issueGalleys', 'deleteIssue', 'publishIssue', 'unpublishIssue', 'setCurrentIssue', 'identifiers', 'updateIdentifiers', 'clearPubId', 'clearIssueObjectsPubIds', 'access', 'updateAccess', ] ); } // // Implement template methods from PKPHandler // /** * @copydoc PKPHandler::authorize() */ public function authorize($request, &$args, $roleAssignments) { $this->addPolicy(new ContextAccessPolicy($request, $roleAssignments)); // If a signoff ID was specified, authorize it. if ($request->getUserVar('issueId')) { $this->addPolicy(new OjsIssueRequiredPolicy($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); // Grid columns. $issueGridCellProvider = new IssueGridCellProvider(); // Issue identification $this->addColumn( new GridColumn( 'identification', 'issue.issue', null, null, $issueGridCellProvider ) ); $this->_addCenterColumns($issueGridCellProvider); // Number of articles $this->addColumn( new GridColumn( 'numArticles', 'editor.issues.numArticles', null, null, $issueGridCellProvider ) ); } /** * Private function to add central columns to the grid. * May be overridden by subclasses. * * @param IssueGridCellProvider $issueGridCellProvider */ protected function _addCenterColumns($issueGridCellProvider) { // Default implementation does nothing. } /** * Get the row handler - override the default row handler * * @return IssueGridRow */ protected function getRowInstance() { return new IssueGridRow(); } // // Public operations // /** * An action to add a new issue * * @param array $args * @param Request $request */ public function addIssue($args, $request) { // Calling editIssueData with an empty ID will add // a new issue. return $this->editIssueData($args, $request); } /** * An action to edit an issue * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function editIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $templateMgr = TemplateManager::getManager($request); if ($issue) { $templateMgr->assign('issueId', $issue->getId()); } $publisherIdEnabled = in_array('issue', (array) $request->getContext()->getData('enablePublisherId')); $pubIdPlugins = PluginRegistry::getPlugins('pubIds'); if ($publisherIdEnabled || count($pubIdPlugins)) { $templateMgr->assign('enableIdentifiers', true); } return new JSONMessage(true, $templateMgr->fetch('controllers/grid/issues/issue.tpl')); } /** * An action to edit an issue's identifying data * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function editIssueData($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $issueForm = new IssueForm($issue); $issueForm->initData(); return new JSONMessage(true, $issueForm->fetch($request)); } /** * An action to upload an issue file. Used for issue cover images. * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function uploadFile($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')); } } /** * Delete an uploaded cover image. * * @param array $args * `coverImage` string Filename of the cover image to be deleted. * `issueId` int Id of the issue this cover image is attached to * @param Request $request * * @return JSONMessage JSON object */ public function deleteCoverImage($args, $request) { assert(!empty($args['coverImage']) && !empty($args['issueId'])); // Check if the passed filename matches the filename for this issue's // cover page. $issue = Repo::issue()->get((int) $args['issueId']); $context = $request->getContext(); if ($issue->getJournalId() != $context->getId()) { return new JSONMessage(false, __('editor.issues.removeCoverImageOnDifferentContextNowAllowed')); } $locale = Locale::getLocale(); if ($args['coverImage'] != $issue->getCoverImage($locale)) { return new JSONMessage(false, __('editor.issues.removeCoverImageFileNameMismatch')); } $file = $args['coverImage']; // Remove cover image and alt text from issue settings $issue->setCoverImage('', $locale); $issue->setCoverImageAltText('', $locale); Repo::issue()->edit($issue, []); // Remove the file $publicFileManager = new PublicFileManager(); if ($publicFileManager->removeContextFile($issue->getJournalId(), $file)) { $json = new JSONMessage(true); $json->setEvent('fileDeleted'); return $json; } else { return new JSONMessage(false, __('editor.issues.removeCoverImageFileNotFound')); } } /** * Update an issue * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function updateIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $issueForm = new IssueForm($issue); $issueForm->readInputData(); if ($issueForm->validate()) { $issueForm->execute(); $notificationManager = new NotificationManager(); $notificationManager->createTrivialNotification($request->getUser()->getId()); return DAO::getDataChangedEvent(); } else { return new JSONMessage(true, $issueForm->fetch($request)); } } /** * An action to edit an issue's access settings * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function access($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $issueAccessForm = new IssueAccessForm($issue); $issueAccessForm->initData(); return new JSONMessage(true, $issueAccessForm->fetch($request)); } /** * Update an issue's access settings * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function updateAccess($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $issueAccessForm = new IssueAccessForm($issue); $issueAccessForm->readInputData(); if ($issueAccessForm->validate()) { $issueAccessForm->execute(); $notificationManager = new NotificationManager(); $notificationManager->createTrivialNotification($request->getUser()->getId()); return DAO::getDataChangedEvent(); } else { return new JSONMessage(true, $issueAccessForm->fetch($request)); } } /** * Removes an issue * * @param array $args * @param Request $request */ public function deleteIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); if (!$issue || !$request->checkCSRF()) { return new JSONMessage(false); } $journal = $request->getJournal(); if ($issue->getJournalId() != $journal->getId()) { return new JSONMessage(false); } // remove all published submissions and return original articles to editing queue $submissions = Repo::submission() ->getCollector() ->filterByContextIds([$issue->getData('journalId')]) ->filterByIssueIds([$issue->getId()]) ->getMany(); foreach ($submissions as $submission) { $publications = $submission->getData('publications'); foreach ($publications as $publication) { if ($publication->getData('issueId') === (int) $issue->getId()) { Repo::publication()->edit($publication, ['issueId' => '', 'status' => Submission::STATUS_QUEUED]); } } $newSubmission = Repo::submission()->get($submission->getId()); Repo::submission()->updateStatus($newSubmission); } Repo::issue()->delete($issue); $currentIssue = Repo::issue()->getCurrent($issue->getJournalId()); if ($currentIssue != null && $issue->getId() == $currentIssue->getId()) { $issues = Repo::issue()->getCollector() ->filterByContextIds([$journal->getId()]) ->filterByPublished(true) ->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES) ->getMany(); if ($issue = $issues->first()) { Repo::issue()->updateCurrent($journal->getId(), $issue); } } return DAO::getDataChangedEvent($issue->getId()); } /** * An action to edit issue pub ids * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function identifiers($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $form = new PublicIdentifiersForm($issue); $form->initData(); return new JSONMessage(true, $form->fetch($request)); } /** * Update issue pub ids * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function updateIdentifiers($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $form = new PublicIdentifiersForm($issue); $form->readInputData(); if ($form->validate()) { $form->execute(); return DAO::getDataChangedEvent($issue->getId()); } else { return new JSONMessage(true, $form->fetch($request)); } } /** * Clear issue pub id * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function clearPubId($args, $request) { if (!$request->checkCSRF()) { return new JSONMessage(false); } $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $form = new PublicIdentifiersForm($issue); $form->clearPubId($request->getUserVar('pubIdPlugIn')); $json = new JSONMessage(true); $json->setEvent('reloadTab', [['tabsSelector' => '#editIssueTabs', 'tabSelector' => '#identifiersTab']]); return $json; } /** * Clear issue objects pub ids * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function clearIssueObjectsPubIds($args, $request) { if (!$request->checkCSRF()) { return new JSONMessage(false); } $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $form = new PublicIdentifiersForm($issue); $form->clearIssueObjectsPubIds($request->getUserVar('pubIdPlugIn')); return new JSONMessage(true); } /** * Display the table of contents * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function issueToc($args, $request) { $templateMgr = TemplateManager::getManager($request); $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $templateMgr->assign('issue', $issue); return new JSONMessage(true, $templateMgr->fetch('controllers/grid/issues/issueToc.tpl')); } /** * Displays the issue galleys page. * * @param array $args * @param Request $request * * @return JSONMessage JSON object */ public function issueGalleys($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $templateMgr = TemplateManager::getManager($request); $dispatcher = $request->getDispatcher(); return $templateMgr->fetchAjax( 'issueGalleysGridContainer', $dispatcher->url( $request, PKPApplication::ROUTE_COMPONENT, null, 'grid.issueGalleys.IssueGalleyGridHandler', 'fetchGrid', null, ['issueId' => $issue->getId()] ) ); } /** * Publish issue * * @param array $args * @param Request $request */ public function publishIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $context = $request->getContext(); $contextId = $context->getId(); $wasPublished = $issue->getPublished(); if (!$wasPublished) { $confirmationText = __('editor.issues.confirmPublish'); $formTemplate = $this->getAssignPublicIdentifiersFormTemplate(); $assignPublicIdentifiersForm = new AssignPublicIdentifiersForm($formTemplate, $issue, true, $confirmationText); if (!$request->getUserVar('confirmed')) { // Display assign pub ids modal $assignPublicIdentifiersForm->initData(); return new JSONMessage(true, $assignPublicIdentifiersForm->fetch($request)); } // Assign pub ids $assignPublicIdentifiersForm->readInputData(); if (!$assignPublicIdentifiersForm->validate()) { return new JSONMessage(true, $assignPublicIdentifiersForm->fetch($request)); } $assignPublicIdentifiersForm->execute(); Repo::issue()->createDoi($issue); } if (!$request->checkCSRF()) { return new JSONMessage(false); } $issue->setPublished(1); $issue->setDatePublished(Core::getCurrentDate()); // If subscriptions with delayed open access are enabled then // update open access date according to open access delay policy if ($context->getData('publishingMode') == \APP\journal\Journal::PUBLISHING_MODE_SUBSCRIPTION && ($delayDuration = $context->getData('delayedOpenAccessDuration'))) { $delayYears = (int)floor($delayDuration / 12); $delayMonths = (int)fmod($delayDuration, 12); $curYear = date('Y'); $curMonth = date('n'); $curDay = date('j'); $delayOpenAccessYear = $curYear + $delayYears + (int)floor(($curMonth + $delayMonths) / 12); $delayOpenAccessMonth = (int)fmod($curMonth + $delayMonths, 12); $issue->setAccessStatus(\APP\issue\Issue::ISSUE_ACCESS_SUBSCRIPTION); $issue->setOpenAccessDate(date('Y-m-d H:i:s', mktime(0, 0, 0, $delayOpenAccessMonth, $curDay, $delayOpenAccessYear))); } Hook::call('IssueGridHandler::publishIssue', [&$issue]); Repo::issue()->updateCurrent($contextId, $issue); if (!$wasPublished) { Repo::doi()->issueUpdated($issue); // Publish all related publications // Include published submissions in order to support cases where two // versions of the same submission are published in distinct issues. In // such cases, the submission will be STATUS_PUBLISHED but the // publication will be STATUS_SCHEDULED. $submissions = Repo::submission()->getCollector() ->filterByContextIds([$issue->getJournalId()]) ->filterByIssueIds([$issue->getId()]) ->filterByStatus([Submission::STATUS_SCHEDULED, Submission::STATUS_PUBLISHED]) ->getMany(); foreach ($submissions as $submission) { /** @var Submission $submission */ $publications = $submission->getData('publications'); foreach ($publications as $publication) { /** @var Publication $publication */ if ($publication->getData('status') === Submission::STATUS_SCHEDULED && $publication->getData('issueId') === (int) $issue->getId()) { Repo::publication()->publish($publication); } } } } // Send a notification to associated users if selected and context is publishing content online with OJS if ($request->getUserVar('sendIssueNotification') && $context->getData('publishingMode') != \APP\journal\Journal::PUBLISHING_MODE_NONE) { // Notify users /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */ $notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); $userIdsToNotify = $notificationSubscriptionSettingsDao->getSubscribedUserIds( [NotificationSubscriptionSettingsDAO::BLOCKED_NOTIFICATION_KEY], [Notification::NOTIFICATION_TYPE_PUBLISHED_ISSUE], [$contextId] ); $userIdsToMail = $notificationSubscriptionSettingsDao->getSubscribedUserIds( [ NotificationSubscriptionSettingsDAO::BLOCKED_NOTIFICATION_KEY, NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY ], [Notification::NOTIFICATION_TYPE_PUBLISHED_ISSUE], [$contextId] ); $userIdsToNotifyAndMail = $userIdsToNotify->intersect($userIdsToMail); $userIdsToNotify = $userIdsToNotify->diff($userIdsToMail); $jobs = []; foreach ($userIdsToNotify->chunk(PKPNotification::NOTIFICATION_CHUNK_SIZE_LIMIT) as $notifyUserIds) { $jobs[] = new IssuePublishedNotifyUsers( $notifyUserIds, $contextId, $issue, Locale::getLocale(), ); } foreach ($userIdsToNotifyAndMail->chunk(Mailer::BULK_EMAIL_SIZE_LIMIT) as $mailUserIds) { $jobs[] = new IssuePublishedNotifyUsers( $mailUserIds, $contextId, $issue, Locale::getLocale(), $request->getUser() ); } Bus::batch($jobs)->dispatch(); } $json = DAO::getDataChangedEvent(); $json->setGlobalEvent('issuePublished', ['id' => $issue->getId()]); return $json; } /** * Unpublish a previously-published issue * * @param array $args * @param Request $request */ public function unpublishIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $journal = $request->getJournal(); if (!$request->checkCSRF()) { return new JSONMessage(false); } // NB: Data set via params because setData('datePublished', null) // removes the entry into _data rather than updating 'datePublished' to null. $updateParams = [ 'published' => 0, 'datePublished' => null ]; Hook::call('IssueGridHandler::unpublishIssue', [&$issue]); Repo::issue()->edit($issue, $updateParams); Repo::issue()->updateCurrent($request->getContext()->getId()); Repo::doi()->issueUpdated($issue); // insert article tombstones for all articles $submissions = Repo::submission()->getCollector() ->filterByContextIds([$issue->getJournalId()]) ->filterByIssueIds([$issue->getId()]) ->getMany(); foreach ($submissions as $submission) { /** @var Submission $submission */ $publications = $submission->getData('publications'); foreach ($publications as $publication) { /** @var Publication $publication */ if ($publication->getData('status') === Submission::STATUS_PUBLISHED && $publication->getData('issueId') === (int) $issue->getId()) { // Republish the publication in the issue, now that it's status has changed, // to ensure the publication's status is restored to Submission::STATUS_SCHEDULED // rather than Submission::STATUS_QUEUED Repo::publication()->unpublish($publication); Repo::publication()->publish($publication); } } } $json = DAO::getDataChangedEvent($issue->getId()); $json->setGlobalEvent('issueUnpublished', ['id' => $issue->getId()]); return $json; } /** * Set Issue as current * * @param array $args * @param Request $request */ public function setCurrentIssue($args, $request) { $issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE); $journal = $request->getJournal(); if (!$request->checkCSRF()) { return new JSONMessage(false); } Repo::issue()->updateCurrent($journal->getId(), $issue); $dispatcher = $request->getDispatcher(); return DAO::getDataChangedEvent(); } /** * Get the template for the assign public identifiers form. * * @return string */ public function getAssignPublicIdentifiersFormTemplate() { return 'controllers/grid/pubIds/form/assignPublicIdentifiersForm.tpl'; } }