Open Journal Systems  3.3.0
DOIPubIdPlugin.inc.php
1 <?php
2 
16 import('classes.plugins.PubIdPlugin');
17 
18 class DOIPubIdPlugin extends PubIdPlugin {
19 
23  public function register($category, $path, $mainContextId = null) {
24  $success = parent::register($category, $path, $mainContextId);
25  if (!Config::getVar('general', 'installed') || defined('RUNNING_UPGRADE')) return $success;
26  if ($success && $this->getEnabled($mainContextId)) {
27  HookRegistry::register('CitationStyleLanguage::citation', array($this, 'getCitationData'));
28  HookRegistry::register('Publication::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
29  HookRegistry::register('Publication::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
30  HookRegistry::register('Publication::validate', array($this, 'validatePublicationDoi'));
31  HookRegistry::register('Issue::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
32  HookRegistry::register('Issue::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
33  HookRegistry::register('Galley::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
34  HookRegistry::register('Galley::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
35  HookRegistry::register('Publication::getProperties::values', array($this, 'modifyObjectPropertyValues'));
36  HookRegistry::register('Issue::getProperties::values', array($this, 'modifyObjectPropertyValues'));
37  HookRegistry::register('Galley::getProperties::values', array($this, 'modifyObjectPropertyValues'));
38  HookRegistry::register('Form::config::before', array($this, 'addPublicationFormFields'));
39  HookRegistry::register('Form::config::before', array($this, 'addPublishFormNotice'));
40  }
41  return $success;
42  }
43 
44  //
45  // Implement template methods from Plugin.
46  //
50  function getDisplayName() {
51  return __('plugins.pubIds.doi.displayName');
52  }
53 
57  function getDescription() {
58  return __('plugins.pubIds.doi.description');
59  }
60 
61 
62  //
63  // Implement template methods from PubIdPlugin.
64  //
68  function constructPubId($pubIdPrefix, $pubIdSuffix, $contextId) {
69  return $pubIdPrefix . '/' . $pubIdSuffix;
70  }
71 
75  function getPubIdType() {
76  return 'doi';
77  }
78 
82  function getPubIdDisplayType() {
83  return 'DOI';
84  }
85 
89  function getPubIdFullName() {
90  return 'Digital Object Identifier';
91  }
92 
96  function getResolvingURL($contextId, $pubId) {
97  return 'https://doi.org/'.$this->_doiURLEncode($pubId);
98  }
99 
103  function getPubIdMetadataFile() {
104  return $this->getTemplateResource('doiSuffixEdit.tpl');
105  }
106 
110  function getPubIdAssignFile() {
111  return $this->getTemplateResource('doiAssign.tpl');
112  }
113 
117  function instantiateSettingsForm($contextId) {
118  $this->import('classes.form.DOISettingsForm');
119  return new DOISettingsForm($this, $contextId);
120  }
121 
125  function getFormFieldNames() {
126  return array('doiSuffix');
127  }
128 
133  return 'assignDoi';
134  }
135 
139  function getPrefixFieldName() {
140  return 'doiPrefix';
141  }
142 
146  function getSuffixFieldName() {
147  return 'doiSuffix';
148  }
149 
153  function getLinkActions($pubObject) {
154  $linkActions = array();
155  import('lib.pkp.classes.linkAction.request.RemoteActionConfirmationModal');
156  $request = Application::get()->getRequest();
157  $userVars = $request->getUserVars();
158  $userVars['pubIdPlugIn'] = get_class($this);
159  // Clear object pub id
160  $linkActions['clearPubIdLinkActionDoi'] = new LinkAction(
161  'clearPubId',
163  $request->getSession(),
164  __('plugins.pubIds.doi.editor.clearObjectsDoi.confirm'),
165  __('common.delete'),
166  $request->url(null, null, 'clearPubId', null, $userVars),
167  'modal_delete'
168  ),
169  __('plugins.pubIds.doi.editor.clearObjectsDoi'),
170  'delete',
171  __('plugins.pubIds.doi.editor.clearObjectsDoi')
172  );
173 
174  if (is_a($pubObject, 'Issue')) {
175  // Clear issue objects pub ids
176  $linkActions['clearIssueObjectsPubIdsLinkActionDoi'] = new LinkAction(
177  'clearObjectsPubIds',
179  $request->getSession(),
180  __('plugins.pubIds.doi.editor.clearIssueObjectsDoi.confirm'),
181  __('common.delete'),
182  $request->url(null, null, 'clearIssueObjectsPubIds', null, $userVars),
183  'modal_delete'
184  ),
185  __('plugins.pubIds.doi.editor.clearIssueObjectsDoi'),
186  'delete',
187  __('plugins.pubIds.doi.editor.clearIssueObjectsDoi')
188  );
189  }
190 
191  return $linkActions;
192  }
193 
198  return array(
199  'Issue' => 'doiIssueSuffixPattern',
200  'Publication' => 'doiPublicationSuffixPattern',
201  'Representation' => 'doiRepresentationSuffixPattern'
202  );
203  }
204 
208  function getDAOFieldNames() {
209  return array('pub-id::doi');
210  }
211 
215  function isObjectTypeEnabled($pubObjectType, $contextId) {
216  return (boolean) $this->getSetting($contextId, "enable${pubObjectType}Doi");
217  }
218 
222  function getNotUniqueErrorMsg() {
223  return __('plugins.pubIds.doi.editor.doiSuffixCustomIdentifierNotUnique');
224  }
225 
229  function validatePubId($pubId) {
230  return preg_match('/^\d+(.\d+)+\//', $pubId);
231  }
232 
233  /*
234  * Public methods
235  */
244  public function getCitationData($hookname, $args) {
245  $citationData = $args[0];
246  $article = $args[2];
247  $issue = $args[3];
248  $journal = $args[4];
249 
250  if ($issue && $issue->getPublished()) {
251  $pubId = $article->getStoredPubId($this->getPubIdType());
252  } else {
253  $pubId = $this->getPubId($article);
254  }
255 
256  if (!$pubId) {
257  return;
258  }
259 
260  $citationData->DOI = $pubId;
261  }
262 
263 
264  /*
265  * Private methods
266  */
272  function _doiURLEncode($pubId) {
273  $search = array ('%', '"', '#', ' ', '<', '>', '{');
274  $replace = array ('%25', '%22', '%23', '%20', '%3c', '%3e', '%7b');
275  $pubId = str_replace($search, $replace, $pubId);
276  return $pubId;
277  }
278 
285  public function validatePublicationDoi($hookName, $args) {
286  $errors =& $args[0];
287  $action = $args[1];
288  $props =& $args[2];
289 
290  if (empty($props['pub-id::doi'])) {
291  return;
292  }
293 
294  if ($action === VALIDATE_ACTION_ADD) {
295  $submission = Services::get('submission')->get($props['submissionId']);
296  } else {
297  $publication = Services::get('publication')->get($props['id']);
298  $submission = Services::get('submission')->get($publication->getData('submissionId'));
299  }
300 
301  $contextId = $submission->getData('contextId');
302  $doiPrefix = $this->getSetting($contextId, 'doiPrefix');
303 
304  $doiErrors = [];
305  if (strpos($props['pub-id::doi'], $doiPrefix) !== 0) {
306  $doiErrors[] = __('plugins.pubIds.doi.editor.missingPrefix', ['doiPrefix' => $doiPrefix]);
307  }
308  if (!$this->checkDuplicate($props['pub-id::doi'], 'Publication', $submission->getId(), $contextId)) {
309  $doiErrors[] = $this->getNotUniqueErrorMsg();
310  }
311  if (!empty($doiErrors)) {
312  $errors['pub-id::doi'] = $doiErrors;
313  }
314  }
315 
329  public function modifyObjectProperties($hookName, $args) {
330  $props =& $args[0];
331 
332  $props[] = 'pub-id::doi';
333  }
334 
348  public function modifyObjectPropertyValues($hookName, $args) {
349  $values =& $args[0];
350  $object = $args[1];
351  $props = $args[2];
352 
353  // DOIs are not supported for IssueGalleys
354  if (get_class($object) === 'IssueGalley') {
355  return;
356  }
357 
358  // DOIs are already added to property values for Publications and Galleys
359  if (get_class($object) === 'Publication' || get_class($object) === 'ArticleGalley') {
360  return;
361  }
362 
363  if (in_array('pub-id::doi', $props)) {
364  $pubId = $this->getPubId($object);
365  $values['pub-id::doi'] = $pubId ? $pubId : null;
366  }
367  }
368 
375  public function addPublicationFormFields($hookName, $form) {
376 
377  if ($form->id !== 'publicationIdentifiers') {
378  return;
379  }
380 
381  if (!$this->getSetting($form->submissionContext->getId(), 'enablePublicationDoi')) {
382  return;
383  }
384 
385  $prefix = $this->getSetting($form->submissionContext->getId(), 'doiPrefix');
386 
387  $suffixType = $this->getSetting($form->submissionContext->getId(), 'doiSuffix');
388  $pattern = '';
389  if ($suffixType === 'default') {
390  $pattern = '%j.v%vi%i.%a';
391  } elseif ($suffixType === 'pattern') {
392  $pattern = $this->getSetting($form->submissionContext->getId(), 'doiPublicationSuffixPattern');
393  }
394 
395  // Add a text field to enter the DOI if no pattern exists
396  if (!$pattern) {
397  $form->addField(new \PKP\components\forms\FieldText('pub-id::doi', [
398  'label' => __('metadata.property.displayName.doi'),
399  'description' => __('plugins.pubIds.doi.editor.doi.description', ['prefix' => $prefix]),
400  'value' => $form->publication->getData('pub-id::doi'),
401  ]));
402  } else {
403  $fieldData = [
404  'label' => __('metadata.property.displayName.doi'),
405  'value' => $form->publication->getData('pub-id::doi'),
406  'prefix' => $prefix,
407  'pattern' => $pattern,
408  'contextInitials' => PKPString::regexp_replace('/[^A-Za-z0-9]/', '', PKPString::strtolower($form->submissionContext->getData('acronym', $form->submissionContext->getData('primaryLocale')))) ?? '',
409  'separator' => '/',
410  'submissionId' => $form->publication->getData('submissionId'),
411  'assignIdLabel' => __('plugins.pubIds.doi.editor.doi.assignDoi'),
412  'clearIdLabel' => __('plugins.pubIds.doi.editor.clearObjectsDoi'),
413  ];
414  if ($form->publication->getData('pub-id::publisher-id')) {
415  $fieldData['publisherId'] = $form->publication->getData('pub-id::publisher-id');
416  }
417  if ($form->publication->getData('pages')) {
418  $fieldData['pages'] = $form->publication->getData('pages');
419  }
420  if ($form->publication->getData('issueId')) {
421  $issue = Services::get('issue')->get($form->publication->getData('issueId'));
422  if ($issue) {
423  $fieldData['issueNumber'] = $issue->getNumber() ?? '';
424  $fieldData['issueVolume'] = $issue->getVolume() ?? '';
425  $fieldData['year'] = $issue->getYear() ?? '';
426  }
427  }
428  if ($suffixType === 'default') {
429  $fieldData['missingPartsLabel'] = __('plugins.pubIds.doi.editor.missingIssue');
430  } else {
431  $fieldData['missingPartsLabel'] = __('plugins.pubIds.doi.editor.missingParts');
432  }
433  $form->addField(new \PKP\components\forms\FieldPubId('pub-id::doi', $fieldData));
434  }
435  }
436 
443  public function addPublishFormNotice($hookName, $form) {
444 
445  if ($form->id !== 'publish' || !empty($form->errors)) {
446  return;
447  }
448 
449  $submission = Services::get('submission')->get($form->publication->getData('submissionId'));
450  $publicationDoiEnabled = $this->getSetting($submission->getData('contextId'), 'enablePublicationDoi');
451  $galleyDoiEnabled = $this->getSetting($submission->getData('contextId'), 'enableRepresentationDoi');
452  $warningIconHtml = '<span class="fa fa-exclamation-triangle pkpIcon--inline"></span>';
453 
454  if (!$publicationDoiEnabled && !$galleyDoiEnabled) {
455  return;
456 
457  // Use a simplified view when only assigning to the publication
458  } else if (!$galleyDoiEnabled) {
459  if ($form->publication->getData('pub-id::doi')) {
460  $msg = __('plugins.pubIds.doi.editor.preview.publication', ['doi' => $form->publication->getData('pub-id::doi')]);
461  } else {
462  $msg = '<div class="pkpNotification pkpNotification--warning">' . $warningIconHtml . __('plugins.pubIds.doi.editor.preview.publication.none') . '</div>';
463  }
464  $form->addField(new \PKP\components\forms\FieldHTML('doi', [
465  'description' => $msg,
466  'groupId' => 'default',
467  ]));
468  return;
469 
470  // Show a table if more than one DOI is going to be created
471  } else {
472  $doiTableRows = [];
473  if ($publicationDoiEnabled) {
474  if ($form->publication->getData('pub-id::doi')) {
475  $doiTableRows[] = [$form->publication->getData('pub-id::doi'), 'Publication'];
476  } else {
477  $doiTableRows[] = [$warningIconHtml . __('submission.status.unassigned'), 'Publication'];
478  }
479  }
480  if ($galleyDoiEnabled) {
481  foreach ((array) $form->publication->getData('galleys') as $galley) {
482  if ($galley->getStoredPubId('doi')) {
483  $doiTableRows[] = [$galley->getStoredPubId('doi'), __('plugins.pubIds.doi.editor.preview.galleys', ['galleyLabel' => $galley->getGalleyLabel()])];
484  } else {
485  $doiTableRows[] = [$warningIconHtml . __('submission.status.unassigned'),__('plugins.pubIds.doi.editor.preview.galleys', ['galleyLabel' => $galley->getGalleyLabel()])];
486  }
487  }
488  }
489  if (!empty($doiTableRows)) {
490  $table = '<table class="pkpTable"><thead><tr>' .
491  '<th>' . __('plugins.pubIds.doi.editor.doi') . '</th>' .
492  '<th>' . __('plugins.pubIds.doi.editor.preview.objects') . '</th>' .
493  '</tr></thead><tbody>';
494  foreach ($doiTableRows as $doiTableRow) {
495  $table .= '<tr><td>' . $doiTableRow[0] . '</td><td>' . $doiTableRow[1] . '</td></tr>';
496  }
497  $table .= '</tbody></table>';
498  }
499  $form->addField(new \PKP\components\forms\FieldHTML('doi', [
500  'description' => $table,
501  'groupId' => 'default',
502  ]));
503  }
504  }
505 }
DOIPubIdPlugin\getResolvingURL
getResolvingURL($contextId, $pubId)
Definition: DOIPubIdPlugin.inc.php:96
DOIPubIdPlugin\getCitationData
getCitationData($hookname, $args)
Definition: DOIPubIdPlugin.inc.php:244
DOIPubIdPlugin\getPubIdType
getPubIdType()
Definition: DOIPubIdPlugin.inc.php:75
DOIPubIdPlugin\getDAOFieldNames
getDAOFieldNames()
Definition: DOIPubIdPlugin.inc.php:208
PKPString\regexp_replace
static regexp_replace($pattern, $replacement, $subject, $limit=-1)
Definition: PKPString.inc.php:279
RemoteActionConfirmationModal
Class defining a simple confirmation modal with a remote action and ok/cancel buttons.
Definition: RemoteActionConfirmationModal.inc.php:18
PKP
FieldPubId
A field for generating a pub id, like a DOI.
DOISettingsForm
Form for journal managers to setup DOI plugin.
Definition: DOISettingsForm.inc.php:19
PubIdPlugin
Public identifiers plugins common functions.
Definition: PubIdPlugin.inc.php:18
DOIPubIdPlugin\_doiURLEncode
_doiURLEncode($pubId)
Definition: DOIPubIdPlugin.inc.php:272
DOIPubIdPlugin\getNotUniqueErrorMsg
getNotUniqueErrorMsg()
Definition: DOIPubIdPlugin.inc.php:222
PubIdPlugin\checkDuplicate
checkDuplicate($pubId, $pubObjectType, $excludeId, $contextId)
Definition: PubIdPlugin.inc.php:104
DOIPubIdPlugin\getPubIdDisplayType
getPubIdDisplayType()
Definition: DOIPubIdPlugin.inc.php:82
DOIPubIdPlugin\addPublicationFormFields
addPublicationFormFields($hookName, $form)
Definition: DOIPubIdPlugin.inc.php:375
DOIPubIdPlugin\getSuffixFieldName
getSuffixFieldName()
Definition: DOIPubIdPlugin.inc.php:146
DOIPubIdPlugin\modifyObjectPropertyValues
modifyObjectPropertyValues($hookName, $args)
Definition: DOIPubIdPlugin.inc.php:348
DOIPubIdPlugin\addPublishFormNotice
addPublishFormNotice($hookName, $form)
Definition: DOIPubIdPlugin.inc.php:443
DOIPubIdPlugin\instantiateSettingsForm
instantiateSettingsForm($contextId)
Definition: DOIPubIdPlugin.inc.php:117
Plugin\getEnabled
getEnabled()
Definition: Plugin.inc.php:868
DOIPubIdPlugin\getFormFieldNames
getFormFieldNames()
Definition: DOIPubIdPlugin.inc.php:125
Plugin\getSetting
getSetting($contextId, $name)
Definition: Plugin.inc.php:473
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
LinkAction
Base class defining an action that can be performed by the user in the user interface.
Definition: LinkAction.inc.php:22
DOIPubIdPlugin\validatePubId
validatePubId($pubId)
Definition: DOIPubIdPlugin.inc.php:229
DOIPubIdPlugin\getPubIdAssignFile
getPubIdAssignFile()
Definition: DOIPubIdPlugin.inc.php:110
DOIPubIdPlugin\getSuffixPatternsFieldNames
getSuffixPatternsFieldNames()
Definition: DOIPubIdPlugin.inc.php:197
PubIdPlugin\getPubId
getPubId($pubObject)
Definition: PubIdPlugin.inc.php:121
DOIPubIdPlugin\validatePublicationDoi
validatePublicationDoi($hookName, $args)
Definition: DOIPubIdPlugin.inc.php:285
DOIPubIdPlugin\getPubIdMetadataFile
getPubIdMetadataFile()
Definition: DOIPubIdPlugin.inc.php:103
DOIPubIdPlugin
DOI plugin class.
Definition: DOIPubIdPlugin.inc.php:18
DOIPubIdPlugin\getPrefixFieldName
getPrefixFieldName()
Definition: DOIPubIdPlugin.inc.php:139
Plugin\getTemplateResource
getTemplateResource($template=null, $inCore=false)
Definition: Plugin.inc.php:349
PKPString\strtolower
static strtolower($string)
Definition: PKPString.inc.php:169
Plugin\$request
$request
Definition: Plugin.inc.php:68
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
DOIPubIdPlugin\modifyObjectProperties
modifyObjectProperties($hookName, $args)
Definition: DOIPubIdPlugin.inc.php:329
DOIPubIdPlugin\isObjectTypeEnabled
isObjectTypeEnabled($pubObjectType, $contextId)
Definition: DOIPubIdPlugin.inc.php:215
FieldText
A basic text field in a form.
DOIPubIdPlugin\getPubIdFullName
getPubIdFullName()
Definition: DOIPubIdPlugin.inc.php:89
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
DOIPubIdPlugin\getDescription
getDescription()
Definition: DOIPubIdPlugin.inc.php:57
DOIPubIdPlugin\constructPubId
constructPubId($pubIdPrefix, $pubIdSuffix, $contextId)
Definition: DOIPubIdPlugin.inc.php:68
FieldHTML
A component for inserting HTML into a form, when you don't need any input fields or values stored.
DOIPubIdPlugin\getDisplayName
getDisplayName()
Definition: DOIPubIdPlugin.inc.php:50
DOIPubIdPlugin\getAssignFormFieldName
getAssignFormFieldName()
Definition: DOIPubIdPlugin.inc.php:132
DOIPubIdPlugin\getLinkActions
getLinkActions($pubObject)
Definition: DOIPubIdPlugin.inc.php:153
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49