From 0eb23c5a19fc43502e260cc7ee70395957d9ae9b Mon Sep 17 00:00:00 2001 From: Alec Smecher <alec@smecher.bc.ca> Date: Tue, 8 Dec 2020 12:20:17 -0800 Subject: [PATCH] Expose production ready files via JATS --- JatsTemplateDownloadHandler.inc.php | 93 +++++++++++++++++++++++++++++ JatsTemplatePlugin.inc.php | 58 +++++++++++++++--- 2 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 JatsTemplateDownloadHandler.inc.php diff --git a/JatsTemplateDownloadHandler.inc.php b/JatsTemplateDownloadHandler.inc.php new file mode 100644 index 0000000..c0af7c4 --- /dev/null +++ b/JatsTemplateDownloadHandler.inc.php @@ -0,0 +1,93 @@ +<?php + +/** + * @file JatsTemplateDownloadHandler.inc.php + * + * Copyright (c) 2014-2020 Simon Fraser University + * Copyright (c) 2003-2020 John Willinsky + * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. + * + * @package plugins.generic.jatsTemplate + * @class JatsTemplateDownloadHandler + */ + +import('classes.handler.Handler'); + +use \Firebase\JWT\JWT; + +class JatsTemplateDownloadHandler extends Handler { + /** @var JatsTemplatePlugin The JATS Template plugin */ + static $plugin; + + /** + * Provide the JATS template plugin to the handler. + * @param $plugin JATSTemplatePlugin + */ + static function setPlugin($plugin) { + self::$plugin = $plugin; + } + + /** + * @copydoc PKPHandler::authorize() + */ + function authorize($request, &$args, $roleAssignments) { + // Permit the use of the Authorization header and an API key for access to unpublished/subscription content + if ($header = array_search('Authorization', array_flip(getallheaders()))) { + list($bearer, $jwt) = explode(' ', $header); + if (strcasecmp($bearer, 'Bearer') == 0) { + $apiToken = JWT::decode($jwt, Config::getVar('security', 'api_key_secret', ''), array('HS256')); + $this->setApiToken($apiToken); + } + } + + import('lib.pkp.classes.security.authorization.ContextRequiredPolicy'); + $this->addPolicy(new ContextRequiredPolicy($request)); + + import('classes.security.authorization.OjsJournalMustPublishPolicy'); + $this->addPolicy(new OjsJournalMustPublishPolicy($request)); + + return parent::authorize($request, $args, $roleAssignments); + } + + protected function _isUserAllowedAccess($request) { + $user = $request->getUser(); + $context = $request->getContext(); + if (!$user || !$context) return false; + $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var $roleDao RoleDAO */ + $roles = $roleDao->getByUserId($user->getId(), $context->getId()); + $allowedAccess = false; + foreach ($roles as $role) { + if (in_array($role->getRoleId(), [ROLE_ID_MANAGER, ROLE_ID_SUBSCRIPTION_MANAGER])) return true; + } + return false; + } + + /** + * Handle a download request + * @param $args array Arguments array. + * @param $request PKPRequest Request object. + */ + function download($args, $request) { + if (!$this->_isUserAllowedAccess($request)) $request->getDispatcher()->handle404(); + + // Check the stage (this is only for consistency with other download URLs in the system + // in case the built-in download handler can be used in place of this in the future) + $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); + if ($request->getUserVar('stageId') != WORKFLOW_STAGE_ID_PRODUCTION) $request->getDispatcher()->handle404(); + + $submissionId = $request->getUserVar('submissionId'); + $layoutFiles = Services::get('submissionFile')->getMany([ + 'submissionIds' => [$submissionId], + 'fileStages' => [SUBMISSION_FILE_PRODUCTION_READY], + ]); + foreach ($layoutFiles as $layoutFile) { + if ($layoutFile->getId() != $request->getUserVar('submissionFileId') || $layoutFile->getData('fileId') != $request->getUserVar('fileId')) continue; + + $filename = Services::get('file')->formatFilename($layoutFile->getData('path'), $layoutFile->getLocalizedData('name')); + Services::get('file')->download($layoutFile->getData('fileId'), $filename); + return; + } + $request->getDispatcher()->handle404(); + } +} + diff --git a/JatsTemplatePlugin.inc.php b/JatsTemplatePlugin.inc.php index 48321ee..45c5e80 100644 --- a/JatsTemplatePlugin.inc.php +++ b/JatsTemplatePlugin.inc.php @@ -21,7 +21,8 @@ public function register($category, $path, $mainContextId = null) { $this->addLocaleData(); if ($success && $this->getEnabled()) { - HookRegistry::register('OAIMetadataFormat_JATS::findJats', array($this, 'callback')); + HookRegistry::register('OAIMetadataFormat_JATS::findJats', [$this, 'callbackFindJats']); + HookRegistry::register('LoadHandler', [$this, 'callbackHandleContent']); } return $success; } @@ -41,11 +42,11 @@ public function getDescription() { } /** - * Send submission files to iThenticate. + * Prepare JATS template document * @param $hookName string * @param $args array */ - public function callback($hookName, $args) { + public function callbackFindJats($hookName, $args) { $plugin =& $args[0]; $record =& $args[1]; $candidateFiles =& $args[2]; @@ -212,10 +213,31 @@ function toXml(&$record, $format = null) { $response .= "\t\t\t</kwd-group>\n"; } - $response .= - (isset($pageCount)?"\t\t\t<counts><page-count count=\"" . (int) $pageCount. "\" /></counts>\n":'') . - "\t\t</article-meta>\n" . - "\t</front>\n"; + $response .= (isset($pageCount)?"\t\t\t<counts><page-count count=\"" . (int) $pageCount. "\" /></counts>\n":''); + + $candidateFound = false; + $layoutResponse = "\t\t\t\t<custom-meta-group>"; + $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); + $layoutFiles = Services::get('submissionFile')->getMany([ + 'submissionIds' => [$article->getId()], + 'fileStages' => [SUBMISSION_FILE_PRODUCTION_READY], + ]); + foreach ($layoutFiles as $layoutFile) { + $candidateFound = true; + $sourceFileUrl = $request->url(null, 'jatsTemplate', 'download', null, + [ + 'submissionFileId' => $layoutFile->getId(), + 'fileId' => $layoutFile->getData('fileId'), + 'submissionId' => $article->getId(), + 'stageId' => WORKFLOW_STAGE_ID_PRODUCTION, + ] + ); + $layoutResponse .= "\t\t\t\t\t<custom-meta>\t\t\t\t\t\t<meta-name>production-ready-file-url</meta-name>\n\t\t\t\t\t\t<meta-value><ext-link ext-link-type=\"uri\" xlink:href=\"" . htmlspecialchars($sourceFileUrl) . "\"/></meta-value>\n\t\t\t\t\t</custom-meta>\n"; + } + $layoutResponse .= "\t\t\t\t</custom-meta-group>"; + if ($candidateFound) $response .= $layoutResponse; + + $response .= "\t\t</article-meta>\n\t</front>\n"; // Include body text (for search indexing only) import('classes.search.ArticleSearchIndex'); @@ -278,4 +300,26 @@ function toXml(&$record, $format = null) { $response .= "</article>"; return $response; } + + /** + * Declare the handler function to process the actual page PATH + * @param $hookName string The name of the invoked hook + * @param $args array Hook parameters + * @return boolean Hook handling status + */ + function callbackHandleContent($hookName, $args) { + $request = Application::get()->getRequest(); + $templateMgr = TemplateManager::getManager($request); + + $page =& $args[0]; + $op =& $args[1]; + + if ($page == 'jatsTemplate' && $op == 'download') { + define('HANDLER_CLASS', 'JatsTemplateDownloadHandler'); + $this->import('JatsTemplateDownloadHandler'); + JatsTemplateDownloadHandler::setPlugin($this); + return true; + } + return false; + } }