diff --git a/pages/OrcidHandler.inc.php b/OrcidProfileHandler.php similarity index 72% rename from pages/OrcidHandler.inc.php rename to OrcidProfileHandler.php index 90383c73..6495e1fb 100644 --- a/pages/OrcidHandler.inc.php +++ b/OrcidProfileHandler.php @@ -1,23 +1,28 @@ getUserVar('targetOp'); if ($op === 'orcidAuthorize' && in_array($targetOp, ['profile', 'submit'])) { // ... but user must be logged in for orcidAuthorize with profile or submit - import('lib.pkp.classes.security.authorization.UserRequiredPolicy'); $this->addPolicy(new UserRequiredPolicy($request)); } @@ -68,7 +78,7 @@ public function orcidAuthorize($args, $request) { $context = $request->getContext(); $op = $request->getRequestedOp(); - $plugin = PluginRegistry::getPlugin('generic', 'orcidprofileplugin'); + $plugin = PluginRegistry::getPlugin('generic', self::ORCIDPROFILEPLUGIN); $contextId = ($context == null) ? \PKP\core\PKPApplication::CONTEXT_ID_NONE : $context->getId(); $httpClient = Application::get()->getHttpClient(); @@ -128,7 +138,7 @@ public function orcidAuthorize($args, $request) ] ); if ($response->getStatusCode() != 200) { - error_log('ORCID employments URL error: ' . $response->getStatusCode() . ' (' . __FILE__ . ' line ' . __LINE__ . ', URL ' . $url . ')'); + error_log('ORCID deployments URL error: ' . $response->getStatusCode() . ' (' . __FILE__ . ' line ' . __LINE__ . ', URL ' . $url . ')'); $employmentJson = null; } else { $employmentJson = json_decode($response->getBody(), true); @@ -162,7 +172,8 @@ public function orcidAuthorize($args, $request) '; break; - default: assert(false); + default: + assert(false); } } @@ -177,17 +188,19 @@ public function orcidVerify($args, $request) $templateMgr = TemplateManager::getManager($request); $context = $request->getContext(); $contextId = $context == null ? \PKP\core\PKPApplication::CONTEXT_ID_NONE : $context->getId(); + $plugin = PluginRegistry::getPlugin('generic', self::ORCIDPROFILEPLUGIN); - $plugin = PluginRegistry::getPlugin('generic', 'orcidprofileplugin'); $templatePath = $plugin->getTemplateResource(self::TEMPLATE); - $publicationId = $request->getUserVar('publicationId'); + $publicationId = $request->getUserVar('state'); $authors = Repo::author() ->getCollector() ->filterByPublicationIds([$publicationId]) ->getMany(); + $isSandBox = $plugin->getSetting($contextId, 'orcidProfileAPIPath') == ORCID_API_URL_MEMBER_SANDBOX || + $plugin->getSetting($contextId, 'orcidProfileAPIPath') == ORCID_API_URL_PUBLIC_SANDBOX; $publication = Repo::publication()->get($publicationId); $authorToVerify = null; @@ -213,7 +226,7 @@ public function orcidVerify($args, $request) if ($authorToVerify == null) { // no Author exists in the database with the supplied orcidEmailToken - $plugin->logError('OrcidHandler::orcidverify - No author found with supplied token'); + $plugin->logError('OrcidProfileHandler::orcidverify - No author found with supplied token'); $templateMgr->assign('verifySuccess', false); $templateMgr->display($templatePath); return; @@ -230,7 +243,7 @@ public function orcidVerify($args, $request) $authorToVerify->setData('orcidAccessExpiresOn', null); $authorToVerify->setData('orcidEmailToken', null); Repo::author()->dao->update($authorToVerify); - $plugin->logError('OrcidHandler::orcidverify - ORCID access denied. Error description: ' . $request->getUserVar('error_description')); + $plugin->logError('OrcidProfileHandler::orcidverify - ORCID access denied. Error description: ' . $request->getUserVar('error_description')); $templateMgr->assign('denied', true); $templateMgr->display($templatePath); return; @@ -251,80 +264,82 @@ public function orcidVerify($args, $request) $plugin->logInfo('POST ' . $url); $plugin->logInfo('Request header: ' . var_export($header, true)); $plugin->logInfo('Request body: ' . http_build_query($postData)); + try { + $response = $httpClient->request( + 'POST', + $url, + [ + 'headers' => $header, + 'form_params' => $postData, + ] + ); + if ($response->getStatusCode() != 200) { + $plugin->logError('OrcidProfileHandler::orcidverify - unexpected response: ' . $response->getStatusCode()); + $templateMgr->assign('authFailure', true); - $response = $httpClient->request( - 'POST', - $url, - [ - 'headers' => $header, - 'form_params' => $postData, - ] - ); - if ($response->getStatusCode() != 200) { - $plugin->logError('OrcidHandler::orcidverify - unexpected response: ' . $response->getStatusCode()); - $templateMgr->assign('authFailure', true); - $templateMgr->display($templatePath); - return; - } - $response = json_decode($response->getBody(), true); + } + $response = json_decode($response->getBody(), true); - $plugin->logInfo('Response body: ' . print_r($response, true)); - if (($response['error'] ?? null) === 'invalid_grant') { - $plugin->logError('Authorization code invalid, maybe already used'); - $templateMgr->assign('authFailure', true); - $templateMgr->display($templatePath); - return; - } - if (isset($response['error'])) { - $plugin->logError("Invalid ORCID response: " . $response['error']); - $templateMgr->assign('authFailure', true); - $templateMgr->display($templatePath); - } - // Set the orcid id using the full https uri - $orcidUri = ($plugin->getSetting($contextId, 'isSandBox') == true ? ORCID_URL_SANDBOX : ORCID_URL) . $response['orcid']; - if (!empty($authorToVerify->getOrcid()) && $orcidUri != $authorToVerify->getOrcid()) { - // another ORCID id is stored for the author - $templateMgr->assign('duplicateOrcid', true); - $templateMgr->display($templatePath); - return; - } - $authorToVerify->setOrcid($orcidUri); - if (in_array($plugin->getSetting($contextId, 'orcidProfileAPIPath'), [ORCID_API_URL_MEMBER_SANDBOX, ORCID_API_URL_PUBLIC_SANDBOX])) { - // Set a flag to mark that the stored orcid id and access token came form the sandbox api - $authorToVerify->setData('orcidSandbox', true); - $templateMgr->assign('orcid', ORCID_URL_SANDBOX . $response['orcid']); - } else { - $templateMgr->assign('orcid', $orcidUri); - } + $plugin->logInfo('Response body: ' . print_r($response, true)); + if (($response['error'] ?? null) === 'invalid_grant') { + $plugin->logError('Authorization code invalid, maybe already used'); + $templateMgr->assign('authFailure', true); - // remove the email token - $authorToVerify->setData('orcidEmailToken', null); - $this->_setOrcidData($authorToVerify, $orcidUri, $response); - Repo::author()->dao->update($authorToVerify); - if ($plugin->isMemberApiEnabled($contextId)) { - if ($publication->getData('status') == PKPSubmission::STATUS_PUBLISHED) { - $templateMgr->assign('sendSubmission', true); - $sendResult = $plugin->sendSubmissionToOrcid($publication, $request); - if ($sendResult === true || (is_array($sendResult) && $sendResult[$response['orcid']])) { - $templateMgr->assign('sendSubmissionSuccess', true); + } + if (isset($response['error'])) { + $plugin->logError("Invalid ORCID response: " . $response['error']); + $templateMgr->assign('authFailure', true); } + // Set the orcid id using the full https uri + $orcidUri = ($plugin->getSetting($contextId, 'isSandBox') == true ? ORCID_URL_SANDBOX : ORCID_URL) . $response['orcid']; + if (!empty($authorToVerify->getOrcid()) && $orcidUri != $authorToVerify->getOrcid()) { + // another ORCID id is stored for the author + $templateMgr->assign('duplicateOrcid', true); + } + $authorToVerify->setOrcid($orcidUri); + if (in_array($plugin->getSetting($contextId, 'orcidProfileAPIPath'), [ORCID_API_URL_MEMBER_SANDBOX, ORCID_API_URL_PUBLIC_SANDBOX])) { + // Set a flag to mark that the stored orcid id and access token came form the sandbox api + $authorToVerify->setData('orcidSandbox', true); + $templateMgr->assign('orcid', ORCID_URL_SANDBOX . $response['orcid']); } else { - $templateMgr->assign('submissionNotPublished', true); + $templateMgr->assign('orcid', $orcidUri); } - } - $templateMgr->assign([ - 'verifySuccess' => true, - 'orcidIcon' => $plugin->getIcon() - ]); + // remove the email token + $authorToVerify->setData('orcidEmailToken', null); + $this->_setOrcidData($authorToVerify, $orcidUri, $response); + Repo::author()->dao->update($authorToVerify); + if ($plugin->isMemberApiEnabled($contextId)) { + if ($publication->getData('status') == PKPSubmission::STATUS_PUBLISHED) { + $templateMgr->assign('sendSubmission', true); + $sendResult = $plugin->sendSubmissionToOrcid($publication, $request); + if ($sendResult === true || (is_array($sendResult) && $sendResult[$response['orcid']])) { + $templateMgr->assign('sendSubmissionSuccess', true); + } + } else { + $templateMgr->assign('submissionNotPublished', true); + } + } + + $templateMgr->assign([ + 'verifySuccess' => true, + 'orcidIcon' => $plugin->getIcon() + ]); + + } catch (\GuzzleHttp\Exception\ClientException $exception) { + $reason = $exception->getResponse()->getBody(false); + $plugin->logInfo("Publication fail: ${reason}"); + + } + $templateMgr->assign('authFailure', true); $templateMgr->display($templatePath); } public function _setOrcidData($userOrAuthor, $orcidUri, $orcidResponse) { // Save the access token - $orcidAccessExpiresOn = Carbon\Carbon::now(); + $orcidAccessExpiresOn = Carbon::now(); // expires_in field from the response contains the lifetime in seconds of the token // See https://members.orcid.org/api/get-oauthtoken $orcidAccessExpiresOn->addSeconds($orcidResponse['expires_in']); @@ -348,9 +363,11 @@ public function about($args, $request) $context = $request->getContext(); $contextId = $context == null ? \PKP\core\PKPApplication::CONTEXT_ID_NONE : $context->getId(); $templateMgr = TemplateManager::getManager($request); - $plugin = PluginRegistry::getPlugin('generic', 'orcidprofileplugin'); + $plugin = PluginRegistry::getPlugin('generic', self::ORCIDPROFILEPLUGIN); $templateMgr->assign('orcidIcon', $plugin->getIcon()); $templateMgr->assign('isMemberApi', $plugin->isMemberApiEnabled($contextId)); $templateMgr->display($plugin->getTemplateResource('orcidAbout.tpl')); } + + } diff --git a/OrcidProfilePlugin.inc.php b/OrcidProfilePlugin.php similarity index 87% rename from OrcidProfilePlugin.inc.php rename to OrcidProfilePlugin.php index 1f78d960..8367dc1c 100755 --- a/OrcidProfilePlugin.inc.php +++ b/OrcidProfilePlugin.php @@ -1,7 +1,7 @@ 'doi', 'other::urn' => 'urn']; - public const USER_GROUP_TO_ORCID_ROLE = ['Author' => 'AUTHOR', 'Translator' => 'CHAIR_OR_TRANSLATOR','Journal manager' => 'AUTHOR']; + public const USER_GROUP_TO_ORCID_ROLE = ['Author' => 'AUTHOR', 'Translator' => 'CHAIR_OR_TRANSLATOR', 'Journal manager' => 'AUTHOR']; private $submissionIdToBePublished; private $currentContextId; @@ -71,7 +85,7 @@ public function register($category, $path, $mainContextId = null) Hook::add('ArticleHandler::view', [&$this, 'submissionView']); Hook::add('PreprintHandler::view', [&$this, 'submissionView']); - // Insert the OrcidHandler to handle ORCID redirects + // Insert the OrcidProfileHandler to handle ORCID redirects Hook::add('LoadHandler', [$this, 'setupCallbackHandler']); // Register callback for Smarty filters; add CSS @@ -130,6 +144,8 @@ public function register($category, $path, $mainContextId = null) Hook::add('Publication::publish', [$this, 'handlePublicationStatusChange']); + Hook::add('ThankReviewerForm::thankReviewer', [$this, 'handleThankReviewer']); + // Add more ORCiD fields to author Schema Hook::add('Schema::get::author', function ($hookName, $args) { $schema = $args[0]; @@ -177,38 +193,64 @@ public function register($category, $path, $mainContextId = null) }); Hook::add('Mailer::Mailables', [$this, 'addMailable']); + + #Hook::add('Form::config::before', [$this, 'addOrcidFormFields']); + Hook::add('Author::edit', [$this, 'handleAuthorFormExecute']); + + Hook::add('Form::config::before', [$this, 'addOrcidFormFields']); + } return $success; } /** - * Get page handler path for this plugin. - * - * @return string Path to plugin's page handler + * adds orcid form fields. + * @param $hookName + * @param $form + * @return bool */ - public function getHandlerPath() + function addOrcidFormFields($hookName, $form): bool + { - return "{$this->getPluginPath()}/pages"; + + if (!$form instanceof ContributorForm) return Hook::CONTINUE; + $form->addField(new FieldOptions('requestOrcidAuthorization', [ + 'label' => __('plugins.generic.orcidProfile.verify.title'), + 'options' => [ + [ + 'value' => true, + 'label' => __('plugins.generic.orcidProfile.author.requestAuthorization') + ] + ] + ])); + $form->addField(new FieldOptions('deleteORCID', [ + 'label' => __('plugins.generic.orcidProfile.displayName'), + 'options' => [ + [ + 'value' => true, + 'label' => __('plugins.generic.orcidProfile.author.deleteORCID') + ] + ] + ])); + return Hook::CONTINUE; } /** - * Hook callback: register pages for each sushi-lite method - * This URL is of the form: orcidapi/{$orcidrequest} - * - * @see PKPPageRouter::route() + * @param $hookName + * @param $args */ - public function setupCallbackHandler($hookName, $params) + function handleThankReviewer($hookName, $args) { - $page = $params[0]; - if ($this->getEnabled() && $page == 'orcidapi') { - $this->import('pages/OrcidHandler'); - define('HANDLER_CLASS', 'OrcidHandler'); - return true; + $request = PKPApplication::get()->getRequest(); + $context = $request->getContext(); + $newPublication =& $args[0]; + if ($this->getSetting($context->getId(), 'country') && $this->getSetting($context->getId(), 'city')) { + $this->publishReviewerWorkToOrcid($newPublication, $request); } - return false; } + /** * Load a setting for a specific journal or load it from the config.inc.php if it is specified there. * @@ -230,6 +272,12 @@ public function getSetting($contextId, $name) case 'orcidClientSecret': $config_value = Config::getVar('orcid', 'client_secret'); break; + case 'country': + $config_value = Config::getVar('orcid', 'country'); + break; + case 'city': + $config_value = Config::getVar('orcid', 'city'); + break; default: return parent::getSetting($contextId, $name); } @@ -238,11 +286,26 @@ public function getSetting($contextId, $name) } /** - * Check if there exist a valid orcid configuration section in the global config.inc.php of OJS. + * Hook callback: register pages for each sushi-lite method + * This URL is of the form: orcidapi/{$orcidrequest} * - * @return bool True, if the config file has api_url, client_id and client_secret set in an [orcid] section + * @see PKPPageRouter::route() */ - public function isGloballyConfigured() + public function setupCallbackHandler($hookName, $params) + { + $page = $params[0]; + if ($this->getEnabled() && $page == 'orcidapi') { + define('HANDLER_CLASS', 'APP\plugins\generic\orcidProfile\OrcidProfileHandler'); + return true; + } + return false; + } + + /** + * Check if there exist a valid orcid configuration section in the global config.inc.php of OJS. + * @return boolean True, if the config file has api_url, client_id and client_secret set in an [orcid] section + */ + function isGloballyConfigured() { $apiUrl = Config::getVar('orcid', 'api_url'); $clientId = Config::getVar('orcid', 'client_id'); @@ -251,6 +314,7 @@ public function isGloballyConfigured() isset($clientSecret) && trim($clientSecret); } + /** * Hook callback to handle form display. * Registers output filter for public user profile and author form. @@ -265,11 +329,12 @@ public function isGloballyConfigured() */ public function handleFormDisplay($hookName, $args) { + //TODO orcid $request = Application::get()->getRequest(); $templateMgr = TemplateManager::getManager($request); switch ($hookName) { case 'authorform::display': - $authorForm = & $args[0]; + $authorForm = &$args[0]; $author = $authorForm->getAuthor(); if ($author) { $authenticated = !empty($author->getData('orcidAccessToken')); @@ -303,8 +368,9 @@ public function handleFormDisplay($hookName, $args) */ public function handleTemplateDisplay($hookName, $args) { - $templateMgr = & $args[0]; - $template = & $args[1]; + //TODO orcid + $templateMgr = &$args[0]; + $template = &$args[1]; $request = Application::get()->getRequest(); // Assign our private stylesheet, for front and back ends. @@ -325,15 +391,16 @@ public function handleTemplateDisplay($hookName, $args) } /** - * Return the OAUTH path (prod or sandbox) based on the current API configuration + * Return the location of the plugin's CSS file * * @return string */ - public function getOauthPath() + function getStyleSheet() { - return $this->getOrcidUrl() . 'oauth/'; + return $this->getPluginPath() . '/css/orcidProfile.css'; } + /** * Return the ORCID website url (prod or sandbox) based on the current API configuration * @@ -352,7 +419,7 @@ public function getOrcidUrl() /** * Return an ORCID OAuth authorization link with * - * @param string $handlerMethod containting a valid method of the OrcidHandler + * @param string $handlerMethod containting a valid method of the OrcidProfileHandler * @param array $redirectParams associative array with additional request parameters for the redirect URL */ public function buildOAuthUrl($handlerMethod, $redirectParams) @@ -381,12 +448,54 @@ public function buildOAuthUrl($handlerMethod, $redirectParams) ); return $this->getOauthPath() . 'authorize?' . http_build_query( - [ - 'client_id' => $this->getSetting($contextId, 'orcidClientId'), - 'response_type' => 'code', - 'scope' => $scope, - 'redirect_uri' => $redirectUrl] - ); + [ + 'client_id' => $this->getSetting($contextId, 'orcidClientId'), + 'response_type' => 'code', + 'scope' => $scope, + 'redirect_uri' => $redirectUrl] + ); + } + + /** + * Return a string of the ORCiD SVG icon + * + * @return string + */ + function getIcon() + { + $path = Core::getBaseDir() . '/' . $this->getPluginPath() . '/templates/images/orcid.svg'; + return file_exists($path) ? file_get_contents($path) : ''; + } + + /** + * @return bool True if the ORCID Member API has been selected in this context. + */ + public function isMemberApiEnabled($contextId) + { + $apiUrl = $this->getSetting($contextId, 'orcidProfileAPIPath'); + if ($apiUrl === ORCID_API_URL_MEMBER || $apiUrl === ORCID_API_URL_MEMBER_SANDBOX) { + return true; + } else { + return false; + } + } + + /** + * Return the OAUTH path (prod or sandbox) based on the current API configuration + * + * @return string + */ + public function getOauthPath() + { + return $this->getOrcidUrl() . 'oauth/'; + } + + public function isSandbox() + { + + $apiUrl = $this->getSetting($this->getCurrentContextId(), 'orcidProfileAPIPath'); + return ($apiUrl == ORCID_API_URL_MEMBER_SANDBOX); + } /** @@ -435,8 +544,8 @@ public function registrationFilter($output, $templateMgr) */ public function handleUserPublicProfileDisplay($hookName, $params) { - $templateMgr = & $params[1]; - $output = & $params[2]; + $templateMgr = &$params[1]; + $output = &$params[2]; $request = Application::get()->getRequest(); $context = $request->getContext(); $user = $request->getUser(); @@ -457,28 +566,6 @@ public function handleUserPublicProfileDisplay($hookName, $params) return true; } - /** - * Output filter adds ORCiD interaction to contributors metadata add/edit form. - * - * @param string $output - * @param TemplateManager $templateMgr - * - * @return string - */ - public function authorFormFilter($output, $templateMgr) - { - if (preg_match('/]+name="submissionId"[^>]*>/', $output, $matches, PREG_OFFSET_CAPTURE)) { - $match = $matches[0][0]; - $offset = $matches[0][1]; - $templateMgr->assign('orcidIcon', $this->getIcon()); - $newOutput = substr($output, 0, $offset + strlen($match)); - $newOutput .= $templateMgr->fetch($this->getTemplateResource('authorFormOrcid.tpl')); - $newOutput .= substr($output, $offset + strlen($match)); - $output = $newOutput; - $templateMgr->unregisterFilter('output', [$this, 'authorFormFilter']); - } - return $output; - } /** * handleAuthorFormexecute sends an e-mail to the author if a specific checkbox was ticked in the author form. @@ -491,23 +578,88 @@ public function authorFormFilter($output, $templateMgr) */ public function handleAuthorFormExecute($hookname, $args) { - $form = & $args[0]; - $form->readUserVars(['requestOrcidAuthorization', 'deleteOrcid']); + if (count($args) == 3) { + $author = &$args[0]; + $values = $args[2]; - $requestAuthorization = $form->getData('requestOrcidAuthorization'); - $deleteOrcid = $form->getData('deleteOrcid'); - $author = $form->getAuthor(); + if ($author && $values['requestOrcidAuthorization']) { + $this->sendAuthorMail($author); + } - if ($author && $requestAuthorization) { - $this->sendAuthorMail($author); + if ($author && $values['deleteORCID']) { + $author->setOrcid(null); + $this->removeOrcidAccessToken($author, false); + } } + } + - if ($author && $deleteOrcid) { - $author->setOrcid(null); - $this->removeOrcidAccessToken($author, false); + /** + * Send mail with ORCID authorization link to the e-mail address of the supplied Author object. + * + * @param Author $author + * @param bool $updateAuthor If true update the author fields in the database. + * Use this only if not called from a function, which does this anyway. + */ + public function sendAuthorMail($author, $updateAuthor = false) + { + $request = Application::get()->getRequest(); + $context = $request->getContext(); + + // This should only ever happen within a context, never site-wide. + if ($context != null) { + $contextId = $context->getId(); + $publicationId = $author->getData('publicationId'); + $publication = Repo::publication()->get($publicationId); + $submission = Repo::submission()->get($publication->getData('submissionId')); + + $emailToken = md5(microtime() . $author->getEmail()); + $author->setData('orcidEmailToken', $emailToken); + $oauthUrl = $this->buildOAuthUrl('orcidVerify', ['token' => $emailToken, 'state' => $publicationId]); + + if ($this->isMemberApiEnabled($contextId)) { + $mailable = new OrcidRequestAuthorAuthorization($context, $submission, $oauthUrl); + } else { + $mailable = new OrcidCollectAuthorId($context, $submission, $oauthUrl); + } + + // Set From to primary journal contact + $mailable->from($context->getData('contactEmail'), $context->getData('contactName')); + + // Send to author + $mailable->recipients([$author]); + $emailTemplateKey = $mailable::getEmailTemplateKey(); + $emailTemplate = Repo::emailTemplate()->getByKey($contextId, $emailTemplateKey); + $mailable->body($emailTemplate->getLocalizedData('body')) + ->subject($emailTemplate->getLocalizedData('subject')); + Mail::send($mailable); + + if ($updateAuthor) { + Repo::author()->dao->update($author); + } } } + /** + * Remove all data fields, which belong to an ORCID access token from the + * given Author object. Also updates fields in the db. + * + * @param Author $author object with ORCID access token + */ + public function removeOrcidAccessToken($author, $saveAuthor = true) + { + $author->setData('orcidAccessToken', null); + $author->setData('orcidAccessScope', null); + $author->setData('orcidRefreshToken', null); + $author->setData('orcidAccessExpiresOn', null); + $author->setData('orcidSandbox', null); + + if ($saveAuthor) { + Repo::author()->dao->update($author); + } + } + + /** * Collect the ORCID when registering a user. * @@ -570,7 +722,7 @@ public function handleSubmissionSubmitStep3FormExecute($hookName, $params) */ public function handleAdditionalFieldNames($hookName, $params) { - $fields = & $params[1]; + $fields = &$params[1]; $fields[] = 'orcidSandbox'; $fields[] = 'orcidAccessToken'; $fields[] = 'orcidAccessScope'; @@ -581,14 +733,6 @@ public function handleAdditionalFieldNames($hookName, $params) return false; } - /** - * @copydoc Plugin::getDisplayName() - */ - public function getDisplayName() - { - return __('plugins.generic.orcidProfile.displayName'); - } - /** * @copydoc Plugin::getDescription() */ @@ -661,6 +805,12 @@ public function getActions($request, $actionArgs) __('manager.plugins.settings'), null ), + new LinkAction( + 'status', + new AjaxModal($router->url($request, null, null, 'manage', null, array('verb' => 'status', 'plugin' => $this->getName(), 'category' => 'generic')), $this->getDisplayName()), + __('common.status'), + null + ) ] : [], parent::getActions($request, $actionArgs) ); @@ -669,27 +819,68 @@ public function getActions($request, $actionArgs) /** * @see Plugin::manage() */ + function getDisplayName() + { + return __('plugins.generic.orcidProfile.displayName'); + } + + + function setEnabled($enabled) + { + $contextId = $this->getCurrentContextId(); + $request = Application::get()->getRequest(); + $validator = new OrcidValidator($this); + + if ($this->isSitePlugin()) { + $contextId = 0; + } + if ($request->getUserVar('save') == 1) { + $clientId = $request->getUserVar('orcidClientId'); + $clientSecret = $request->getUserVar('orcidClientSecret'); + } else { + $clientId = $this->getSetting($contextId, 'orcidClientId'); + $clientSecret = $this->getSetting($contextId, 'orcidClientSecret'); + + } + + if (!$validator->validateClientSecret($clientSecret) or !$validator->validateClientId($clientId)) { + $enabled = false; + + } + $this->updateSetting($contextId, 'enabled', $enabled, 'bool'); + } + + public function manage($args, $request) { + $context = $request->getContext(); + $contextId = ($context == null) ? 0 : $context->getId(); + switch ($request->getUserVar('verb')) { case 'settings': - $context = $request->getContext(); - $contextId = ($context == null) ? 0 : $context->getId(); $templateMgr = TemplateManager::getManager(); $templateMgr->registerPlugin('function', 'plugin_url', [$this, 'smartyPluginUrl']); - $apiOptions = [ + + $templateMgr->assign('orcidApiUrls', [ ORCID_API_URL_PUBLIC => 'plugins.generic.orcidProfile.manager.settings.orcidProfileAPIPath.public', ORCID_API_URL_PUBLIC_SANDBOX => 'plugins.generic.orcidProfile.manager.settings.orcidProfileAPIPath.publicSandbox', ORCID_API_URL_MEMBER => 'plugins.generic.orcidProfile.manager.settings.orcidProfileAPIPath.member', ORCID_API_URL_MEMBER_SANDBOX => 'plugins.generic.orcidProfile.manager.settings.orcidProfileAPIPath.memberSandbox' - ]; - $templateMgr->assign('orcidApiUrls', $apiOptions); + ]); + + $isoCodes = new \Sokil\IsoCodes\IsoCodesFactory(); + $countries = array(); + foreach ($isoCodes->getCountries() as $country) { + $countries[$country->getAlpha2()] = $country->getLocalName(); + } + asort($countries); + $templateMgr->assign('countries', $countries); $templateMgr->assign('logLevelOptions', [ 'ERROR' => 'plugins.generic.orcidProfile.manager.settings.logLevel.error', 'ALL' => 'plugins.generic.orcidProfile.manager.settings.logLevel.all' ]); - $this->import('OrcidProfileSettingsForm'); + $form = new OrcidProfileSettingsForm($this, $contextId); if ($request->getUserVar('save')) { $form->readInputData(); @@ -701,72 +892,14 @@ public function manage($args, $request) $form->initData(); } return new JSONMessage(true, $form->fetch($request)); + case 'status': + $form = new OrcidProfileStatusForm($this, $contextId); + $form->initData(); + return new JSONMessage(true, $form->fetch($request)); } return parent::manage($args, $request); } - /** - * Return the location of the plugin's CSS file - * - * @return string - */ - public function getStyleSheet() - { - return $this->getPluginPath() . '/css/orcidProfile.css'; - } - - /** - * Return a string of the ORCiD SVG icon - * - * @return string - */ - public function getIcon() - { - $path = Core::getBaseDir() . '/' . $this->getPluginPath() . '/templates/images/orcid.svg'; - return file_exists($path) ? file_get_contents($path) : ''; - } - - /** - * Send mail with ORCID authorization link to the e-mail address of the supplied Author object. - * - * @param Author $author - * @param bool $updateAuthor If true update the author fields in the database. - * Use this only if not called from a function, which does this anyway. - */ - public function sendAuthorMail($author, $updateAuthor = false) - { - $request = Application::get()->getRequest(); - $context = $request->getContext(); - - // This should only ever happen within a context, never site-wide. - if ($context != null) { - $contextId = $context->getId(); - $publicationId = $author->getData('publicationId'); - $publication = Repo::publication()->get($publicationId); - $submission = Repo::submission()->get($publication->getData('submissionId')); - - $emailToken = md5(microtime() . $author->getEmail()); - $author->setData('orcidEmailToken', $emailToken); - $oauthUrl = $this->buildOAuthUrl('orcidVerify', ['token' => $emailToken, 'publicationId' => $publicationId]); - - if ($this->isMemberApiEnabled($contextId)) { - $mailable = new OrcidRequestAuthorAuthorization($context, $submission, $oauthUrl); - } else { - $mailable = new OrcidCollectAuthorId($context, $submission, $oauthUrl); - } - - // Set From to primary journal contact - $mailable->from($context->getData('contactEmail'), $context->getData('contactName')); - - // Send to author - $mailable->recipients([$author]); - Mail::send($mailable); - - if ($updateAuthor) { - Repo::author()->dao->update($author); - } - } - } /** * handlePublishIssue sends all submissions for which the authors hava an ORCID and access token @@ -780,11 +913,11 @@ public function sendAuthorMail($author, $updateAuthor = false) */ public function handlePublicationStatusChange($hookName, $args) { - $newPublication = & $args[0]; + $newPublication = &$args[0]; /** @var Publication $newPublication */ - $publication = & $args[1]; + $publication = &$args[1]; /** @var Publication $publication */ - $submission = & $args[2]; + $submission = &$args[2]; /** @var Submission $submission */ $request = Application::get()->getRequest(); @@ -1024,7 +1157,7 @@ public function buildOrcidWork($publication, $context, $authors, $request, $issu 'value' => $context->getName($publicationLocale) ?? '' ], 'short-description' => trim(strip_tags($publication->getLocalizedData('abstract', $publicationLocale))) ?? '', - 'type' => 'annotation', + 'external-ids' => [ 'external-id' => $this->buildOrcidExternalIds($submission, $publication, $context, $issue, $publicationUrl) ], @@ -1043,11 +1176,13 @@ public function buildOrcidWork($publication, $context, $authors, $request, $issu $bibtexCitation = trim(strip_tags($citationPlugin->getCitation($request, $submission, 'bibtex', $issue, $publication))); $orcidWork['citation'] = [ 'citation-type' => 'bibtex', - 'citation-value' => $bibtexCitation + 'citation-value' => $bibtexCitation, ]; + $orcidWork['type'] = 'journal-article'; + } elseif ($applicationName == 'ops') { + $orcidWork['type'] = 'preprint'; } - $translatedTitleAvailable = false; foreach ($supportedSubmissionLocales as $defaultLanguage) { if ($defaultLanguage !== $publicationLocale) { @@ -1265,24 +1400,6 @@ private function buildOrcidContributors($authors, $context, $publication) return $contributors; } - /** - * Remove all data fields, which belong to an ORCID access token from the - * given Author object. Also updates fields in the db. - * - * @param Author $author object with ORCID access token - */ - public function removeOrcidAccessToken($author, $saveAuthor = true) - { - $author->setData('orcidAccessToken', null); - $author->setData('orcidAccessScope', null); - $author->setData('orcidRefreshToken', null); - $author->setData('orcidAccessExpiresOn', null); - $author->setData('orcidSandbox', null); - - if ($saveAuthor) { - Repo::author()->dao->update($author); - } - } /** * @return string Path to a custom ORCID log file. @@ -1337,20 +1454,13 @@ public function setCurrentContextId($contextId) $this->currentContextId = $contextId; } - /** - * @return bool True if the ORCID Member API has been selected in this context. - */ - public function isMemberApiEnabled($contextId) - { - $apiUrl = $this->getSetting($contextId, 'orcidProfileAPIPath'); - return in_array($apiUrl, [ORCID_API_URL_MEMBER, ORCID_API_URL_MEMBER_SANDBOX]); - } - /** * Add mailable to the list of mailables in the application */ public function addMailable(string $hookName, array $args): void { - $args[0] = array_merge($args[0], [OrcidCollectAuthorId::class, OrcidRequestAuthorAuthorization::class]); + foreach ([OrcidCollectAuthorId::class, OrcidRequestAuthorAuthorization::class] as $mailable) { + $args[0]->push($mailable); + } } } diff --git a/OrcidProfileSettingsForm.inc.php b/OrcidProfileSettingsForm.inc.php deleted file mode 100644 index b3a8a920..00000000 --- a/OrcidProfileSettingsForm.inc.php +++ /dev/null @@ -1,130 +0,0 @@ - 'string', - 'orcidClientId' => 'string', - 'orcidClientSecret' => 'string', - 'sendMailToAuthorsOnPublication' => 'bool', - 'logLevel' => 'string', - 'isSandBox' => 'bool' - ]; - /** @var int $contextId */ - public $contextId; - - /** @var object $plugin */ - public $plugin; - - /** - * Constructor - * - * @param object $plugin - * @param int $contextId - */ - public function __construct(&$plugin, $contextId) - { - $this->contextId = $contextId; - $this->plugin = & $plugin; - - parent::__construct($plugin->getTemplateResource('settingsForm.tpl')); - - if (!$this->plugin->isGloballyConfigured()) { - $this->addCheck(new \PKP\form\validation\FormValidator( - $this, - 'orcidProfileAPIPath', - 'required', - 'plugins.generic.orcidProfile.manager.settings.orcidAPIPathRequired' - )); - } - $this->addCheck(new \PKP\form\validation\FormValidatorPost($this)); - $this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this)); - $this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'orcidClientId', 'required', 'plugins.generic.orcidProfile.manager.settings.orcidClientId.error', function ($clientId) { - if (preg_match('/^APP-[\da-zA-Z]{16}|(\d{4}-){3,}\d{3}[\dX]/', $clientId) == 1) { - $this->plugin->setEnabled(true); - return true; - } - $this->plugin->setEnabled(false); - })); - $this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'orcidClientSecret', 'required', 'plugins.generic.orcidProfile.manager.settings.orcidClientSecret.error', function ($clientSecret) { - if (preg_match('/^(\d|-|[a-f]){36,64}/', $clientSecret) == 1) { - $this->plugin->setEnabled(true); - return true; - } - $this->plugin->setEnabled(false); - })); - } - - /** - * Initialize form data. - */ - public function initData() - { - $contextId = $this->contextId; - $plugin = & $this->plugin; - $this->_data = []; - foreach (self::CONFIG_VARS as $configVar => $type) { - $this->_data[$configVar] = $plugin->getSetting($contextId, $configVar); - } - } - - /** - * Assign form data to user-submitted data. - */ - public function readInputData() - { - $this->readUserVars(array_keys(self::CONFIG_VARS)); - } - - /** - * Fetch the form. - * - * @copydoc Form::fetch() - * - * @param null|mixed $template - */ - public function fetch($request, $template = null, $display = false) - { - $templateMgr = TemplateManager::getManager($request); - $templateMgr->assign('globallyConfigured', $this->plugin->isGloballyConfigured()); - $templateMgr->assign('pluginName', $this->plugin->getName()); - return parent::fetch($request, $template, $display); - } - - /** - * @copydoc Form::execute() - */ - public function execute(...$functionArgs) - { - $plugin = & $this->plugin; - $contextId = $this->contextId; - foreach (self::CONFIG_VARS as $configVar => $type) { - if ($configVar === 'orcidProfileAPIPath') { - $plugin->updateSetting($contextId, $configVar, trim($this->getData($configVar), "\"\';"), $type); - } else { - $plugin->updateSetting($contextId, $configVar, $this->getData($configVar), $type); - } - } - if (strpos($this->getData('orcidProfileAPIPath'), 'sandbox.orcid.org') == true) { - $plugin->updateSetting($contextId, 'isSandBox', true, 'bool'); - } - - parent::execute(...$functionArgs); - } -} diff --git a/classes/OrcidValidator.php b/classes/OrcidValidator.php new file mode 100644 index 00000000..b4c28f45 --- /dev/null +++ b/classes/OrcidValidator.php @@ -0,0 +1,39 @@ +plugin =& $plugin; + } + + /** + * @param $str + * @return bool + */ + public function validateClientId($str) { + $valid = false; + if (preg_match('/^APP-[\da-zA-Z]{16}|(\d{4}-){3,}\d{3}[\dX]/', $str) == 1) { + $valid = true; + } + return $valid; + } + + /** + * @param $str + * @return bool + */ + public function validateClientSecret($str) { + $valid = false; + if (preg_match('/^(\d|-|[a-f]){36,64}/', $str) == 1) { + $valid = true; + } + return $valid; + } + +} diff --git a/classes/form/OrcidProfileSettingsForm.php b/classes/form/OrcidProfileSettingsForm.php new file mode 100644 index 00000000..94a22d7d --- /dev/null +++ b/classes/form/OrcidProfileSettingsForm.php @@ -0,0 +1,142 @@ + 'string', + 'orcidClientId' => 'string', + 'orcidClientSecret' => 'string', + 'sendMailToAuthorsOnPublication' => 'bool', + 'logLevel' => 'string', + 'isSandBox' => 'bool', + 'country' => 'string', + 'city' => 'string' + + ); + /** @var $contextId int */ + var $contextId; + + /** @var $plugin object */ + var $plugin; + + var $validator; + + /** + * Constructor + * @param $plugin object + * @param $contextId int + */ + function __construct($plugin, $contextId) { + $this->contextId = $contextId; + $this->plugin = $plugin; + $orcidValidator = new OrcidValidator($plugin); + $this->validator = $orcidValidator; + parent::__construct($plugin->getTemplateResource('settingsForm.tpl')); + $this->addCheck(new \PKP\form\validation\FormValidatorPost($this)); + $this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this)); + + if (!$this->plugin->isGloballyConfigured()) { + $this->addCheck(new \PKP\form\validation\FormValidator($this, 'orcidProfileAPIPath', 'required', 'plugins.generic.orcidProfile.manager.settings.orcidAPIPathRequired')); + $this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'orcidClientId', 'required', 'plugins.generic.orcidProfile.manager.settings.orcidClientId.error', function ($clientId) { + return $this->validator->validateClientId($clientId); + })); + $this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'orcidClientSecret', 'required', 'plugins.generic.orcidProfile.manager.settings.orcidClientSecret.error', function ($clientSecret) { + return $this->validator->validateClientSecret($clientSecret); + })); + } + + } + + /** + * Initialize form data. + */ + function initData() { + $contextId = $this->contextId; + $plugin =& $this->plugin; + $this->_data = array(); + foreach (self::CONFIG_VARS as $configVar => $type) { + $this->_data[$configVar] = $plugin->getSetting($contextId, $configVar); + } + } + + /** + * Assign form data to user-submitted data. + */ + function readInputData() { + $this->readUserVars(array_keys(self::CONFIG_VARS)); + } + + /** + * Fetch the form. + * @copydoc Form::fetch() + */ + function fetch($request, $template = null, $display = false) { + $templateMgr = TemplateManager::getManager($request); + $templateMgr->assign('globallyConfigured', $this->plugin->isGloballyConfigured()); + $templateMgr->assign('pluginName', $this->plugin->getName()); + $templateMgr->assign('applicationName', Application::get()->getName()); + return parent::fetch($request, $template, $display); + } + + /** + * @copydoc Form::execute() + */ + function execute(...$functionArgs) { + $plugin =& $this->plugin; + $contextId = $this->contextId; + foreach (self::CONFIG_VARS as $configVar => $type) { + if ($configVar === 'orcidProfileAPIPath') { + $plugin->updateSetting($contextId, $configVar, trim($this->getData($configVar), "\"\';"), $type); + } else { + $plugin->updateSetting($contextId, $configVar, $this->getData($configVar), $type); + } + } + if (strpos($this->getData("orcidProfileAPIPath"), "sandbox.orcid.org") == true) { + $plugin->updateSetting($contextId, "isSandBox", true, "bool"); + } + + parent::execute(...$functionArgs); + } + + public function _checkPrerequisites() { + $messages = array(); + + $clientId = $this->getData('orcidClientId'); + if (!$this->validator->validateClientId($clientId)) { + $messages[] = __('plugins.generic.orcidProfile.manager.settings.orcidClientId.error'); + } + $clientSecret = $this->getData('orcidClientSecret'); + if (!$this->validator->validateClientSecret($clientSecret)) { + $messages[] = __('plugins.generic.orcidProfile.manager.settings.orcidClientSecret.error'); + } + if (strlen($clientId) == 0 or strlen($clientSecret) == 0) { + $this->plugin->setEnabled(false); + } + return $messages; + } + + +} + diff --git a/classes/form/OrcidProfileStatusForm.php b/classes/form/OrcidProfileStatusForm.php new file mode 100644 index 00000000..e356ae4b --- /dev/null +++ b/classes/form/OrcidProfileStatusForm.php @@ -0,0 +1,101 @@ + 'string', + 'orcidClientId' => 'string', + 'orcidClientSecret' => 'string', + 'sendMailToAuthorsOnPublication' => 'bool', + 'logLevel' => 'string', + 'isSandBox' => 'bool' + ); + + /** @var $contextId int */ + var $contextId; + + /** @var $plugin object */ + var $plugin; + + /** @var OrcidValidator */ + var $validator; + + /** + * Constructor + * @param $plugin object + * @param $contextId int + */ + function __construct($plugin, $contextId) { + $this->contextId = $contextId; + $this->plugin = $plugin; + $orcidValidator = new OrcidValidator($plugin); + $this->validator = $orcidValidator; + parent::__construct($plugin->getTemplateResource('statusForm.tpl')); + + if (!$this->plugin->isGloballyConfigured()) { + + } + + } + + /** + * Initialize form data. + */ + function initData() { + $contextId = $this->contextId; + $plugin =& $this->plugin; + $this->_data = array(); + foreach (self::CONFIG_VARS as $configVar => $type) { + $this->_data[$configVar] = $plugin->getSetting($contextId, $configVar); + } + } + + + /** + * Fetch the form. + * @copydoc Form::fetch() + */ + function fetch($request, $template = null, $display = false) { + $contextId = $request->getContext()->getId(); + $clientId = $this->plugin->getSetting($contextId, 'orcidClientId'); + $clientSecret = $this->plugin->getSetting($contextId, 'orcidClientSecret'); + + $templateMgr = TemplateManager::getManager($request); + $aboutUrl = $request->getDispatcher()->url($request, ROUTE_PAGE, null, 'orcidapi', 'about', null); + $templateMgr->assign(array( + 'globallyConfigured' => $this->plugin->isGloballyConfigured(), + 'orcidAboutUrl' => $aboutUrl, + 'pluginEnabled' => $this->plugin->getEnabled($contextId), + 'clientIdValid' => $this->validator->validateClientId($clientId), + 'clientSecretValid' => $this->validator->validateClientSecret($clientSecret), + + + )); + return parent::fetch($request, $template, $display); + } + + +} + diff --git a/emailTemplates.xml b/emailTemplates.xml index d0a5c0e3..980bf98e 100644 --- a/emailTemplates.xml +++ b/emailTemplates.xml @@ -3,14 +3,14 @@ - - + + diff --git a/index.php b/index.php index 454047ec..f31ac0de 100644 --- a/index.php +++ b/index.php @@ -8,8 +8,8 @@ * @file index.php * * Copyright (c) 2015-2019 University of Pittsburgh - * Copyright (c) 2014-2020 Simon Fraser University - * Copyright (c) 2003-2020 John Willinsky + * 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. * * @ingroup plugins_generic_orcidProfile @@ -17,6 +17,4 @@ * */ -require_once('OrcidProfilePlugin.inc.php'); - -return new OrcidProfilePlugin(); +return new \APP\plugins\generic\orcidProfile\OrcidProfilePlugin(); diff --git a/locale/en_US/emails.po b/locale/en_US/emails.po index 7fb3d2ad..69788658 100644 --- a/locale/en_US/emails.po +++ b/locale/en_US/emails.po @@ -81,3 +81,9 @@ msgstr "ORCID OAuth authorization link" msgid "emailTemplate.variable.orcidAboutUrl" msgstr "URL to the page about ORCID" + +msgid "plugins.generic.orcidProfile.orcidRequestAuthorAuthorization.name" +msgstr "orcidRequestAuthorAuthorization" + +msgid "plugins.generic.orcidProfile.orcidCollectAuthorId.name" +msgstr "orcidCollectAuthorId" diff --git a/locale/en_US/locale.po b/locale/en_US/locale.po index eaf3ea15..ba3f7f3f 100644 --- a/locale/en_US/locale.po +++ b/locale/en_US/locale.po @@ -41,6 +41,9 @@ msgstr "Please configure the ORCID API access for use in pulling ORCID profile i msgid "plugins.generic.orcidProfile.manager.settings.description.globallyconfigured" msgstr "The ORCID API was configured globally by the host. The following credentials have been saved." +msgid "plugins.generic.orcidProfile.manager.settings.pluginDisabled" +msgstr "Due to validation errors, plugin was disabled." + msgid "plugins.generic.orcidProfile.manager.settings.orcidProfileAPIPath" msgstr "ORCID API" @@ -68,6 +71,9 @@ msgstr "Profile Access Scope" msgid "plugins.generic.orcidProfile.manager.settings.mailSectionTitle" msgstr "E-Mail Settings" +msgid "plugins.generic.orcidProfile.manager.settings.saved" +msgstr "Settings saved" + msgid "plugins.generic.orcidProfile.manager.settings.sendMailToAuthorsOnPublication" msgstr "Send e-mail to request ORCID authorization from authors when an article is accepted ie. sent to copy editing" @@ -83,6 +89,18 @@ msgstr "Errors" msgid "plugins.generic.orcidProfile.manager.settings.logLevel.all" msgstr "All" +msgid "plugins.generic.orcidProfile.manager.settings.city" +msgstr "City" + +msgid "plugins.generic.orcidProfile.manager.settings.country" +msgstr "Country" + +msgid "plugins.generic.orcidProfile.manager.settings.review" +msgstr "Review Location settings" + +msgid "plugins.generic.orcidProfile.manager.settings.review.help" +msgstr "Select City, Country for enabling sending reviewer information to ORCID" + msgid "plugins.generic.orcidProfile.author.accessDenied" msgstr "ORCID access was denied at" @@ -128,6 +146,9 @@ msgstr "You denied access to your ORCID record." msgid "plugins.generic.orcidProfile.authFailure" msgstr "The ORCID authorization link has already been used or is invalid." +msgid "plugins.generic.orcidProfile.invalidClient" +msgstr "Invalid client credentials" + msgid "plugins.generic.orcidProfile.failure.contact" msgstr "Please contact the journal manager with your name, ORCID iD, and details of your submission." @@ -209,3 +230,31 @@ msgstr "Invalid client ID" msgid "plugins.generic.orcidProfile.manager.settings.orcidClientSecret.error" msgstr "Invalid client secret" + +msgid "plugins.generic.orcidProfile.manager.status.description" +msgstr "OrcidProfile Plugin Status" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.enabled" +msgstr "OrcidProfile Plugin enabled" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.disabled" +msgstr "OrcidProfile Plugin disabled" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.global" +msgstr "Globally configured in config.inc.php" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.journal" +msgstr "Journal-wise configured" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.clientIdValid" +msgstr "Client Id is valid" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.clientIdInvalid" +msgstr "Client Id is invalid valid, please check your input" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.clientSecretValid" +msgstr "Client Secret is valid" + +msgid "plugins.generic.orcidProfile.manager.status.configuration.clientSecretInvalid" +msgstr "Client Secret is invalid valid, please check your credentials" + diff --git a/templates/orcidAbout.tpl b/templates/orcidAbout.tpl index 4876f39e..30b4ca40 100644 --- a/templates/orcidAbout.tpl +++ b/templates/orcidAbout.tpl @@ -6,7 +6,7 @@ * Copyright (c) 2018-2019 University Library Heidelberg * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * - * Page template to display from the OrcidHandler to show ORCID verification success or failure. + * Page template to display from the OrcidProfileHandler to show ORCID verification success or failure. *} {include file="frontend/components/header.tpl"} diff --git a/templates/orcidVerify.tpl b/templates/orcidVerify.tpl index e7f1d751..b4db2123 100644 --- a/templates/orcidVerify.tpl +++ b/templates/orcidVerify.tpl @@ -6,7 +6,7 @@ * Copyright (c) 2018-2019 University Library Heidelberg * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * - * Page template to display from the OrcidHandler to show ORCID verification success or failure. + * Page template to display from the OrcidProfileHandler to show ORCID verification success or failure. *} {include file="frontend/components/header.tpl"} @@ -38,12 +38,17 @@ {/if} {else}
- {if $denied} + {if $orcidAPIError} + {$orcidAPIError} + {/if} + {if $invalidClient} + {translate key="plugins.generic.orcidProfile.invalidClient"} + {elseif $duplicateOrcid} + {translate key="plugins.generic.orcidProfile.verify.duplicateOrcid"} + {elseif $denied} {translate key="plugins.generic.orcidProfile.authDenied"} {elseif $authFailure} {translate key="plugins.generic.orcidProfile.authFailure"} - {elseif $duplicateOrcid} - {translate key="plugins.generic.orcidProfile.verify.duplicateOrcid"} {else} {translate key="plugins.generic.orcidProfile.verify.failure"} {/if} diff --git a/templates/settingsForm.tpl b/templates/settingsForm.tpl index 73aceccb..7260be74 100644 --- a/templates/settingsForm.tpl +++ b/templates/settingsForm.tpl @@ -45,6 +45,14 @@ {/if} {/fbvFormSection} {/fbvFormArea} + {if $applicationName == 'ojs2'} + {fbvFormSection for="coutries" title="plugins.generic.orcidProfile.manager.settings.review"} +

{translate key="plugins.generic.orcidProfile.manager.settings.review.help"}

+ {fbvElement id="country" label="plugins.generic.orcidProfile.manager.settings.country" name="country" type="select" from=$countries translate=false selected=$country} + {/fbvFormSection} + {fbvElement type="text" id="city" value=$city label="plugins.generic.orcidProfile.manager.settings.city" maxlength="40" size=$fbvStyles.size.MEDIUM } + {/if} + {fbvFormSection for="sendMailToAuthorsOnPublication" title="plugins.generic.orcidProfile.manager.settings.mailSectionTitle" list="true"} {fbvElement type="checkbox" name="sendMailToAuthorsOnPublication" label="plugins.generic.orcidProfile.manager.settings.sendMailToAuthorsOnPublication" id="sendMailToAuthorsOnPublication" checked=$sendMailToAuthorsOnPublication} {/fbvFormSection} diff --git a/templates/statusForm.tpl b/templates/statusForm.tpl new file mode 100644 index 00000000..6b5f6056 --- /dev/null +++ b/templates/statusForm.tpl @@ -0,0 +1,62 @@ +{** + * templates/settingsForm.tpl + * + * Copyright (c) 2015-2019 University of Pittsburgh + * 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. + * + * ORCID Profile plugin settings + * + *} + + + + +
+

{translate key="plugins.generic.orcidProfile.manager.status.description"}

+ +
+ {if $globallyConfigured} + {translate key="plugins.generic.orcidProfile.manager.status.configuration.global"} + {else} + {translate key="plugins.generic.orcidProfile.manager.status.configuration.journal"} + {/if} +
+
+ {if $pluginEnabled} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.enabled"}

+ {else} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.disabled"}

+
+ + {/if} +
+ + +
+ {if $clientIdValid} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.clientIdValid"}

+ {else} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.clientIdInvalid"}

+ {/if} +
+ +
+ {if $clientSecretValid} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.clientSecretValid"}

+ {else} +

{translate key="plugins.generic.orcidProfile.manager.status.configuration.clientSecretInvalid"}

+ {/if} +
+ + + +
+ + diff --git a/version.xml b/version.xml index e0a5b6be..90359842 100755 --- a/version.xml +++ b/version.xml @@ -15,8 +15,8 @@ orcidProfile plugins.generic - 1.2.0.0 - 2021-03-07 + 1.3.4.0 + 2023-01-27 1 OrcidProfilePlugin