Open Monograph Press  3.3.0
URNPubIdPlugin.inc.php
1 <?php
2 
17 import('classes.plugins.PubIdPlugin');
18 
19 class URNPubIdPlugin extends PubIdPlugin {
20 
24  public function register($category, $path, $mainContextId = null) {
25  $success = parent::register($category, $path, $mainContextId);
26  if (!Config::getVar('general', 'installed') || defined('RUNNING_UPGRADE')) return $success;
27  if ($success && $this->getEnabled($mainContextId)) {
28  HookRegistry::register('Publication::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
29  HookRegistry::register('Publication::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
30  HookRegistry::register('Publication::getProperties::values', array($this, 'modifyObjectPropertyValues'));
31  HookRegistry::register('Publication::validate', array($this, 'validatePublicationUrn'));
32  HookRegistry::register('Galley::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
33  HookRegistry::register('Galley::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
34  HookRegistry::register('Galley::getProperties::values', array($this, 'modifyObjectPropertyValues'));
35  HookRegistry::register('Issue::getProperties::summaryProperties', array($this, 'modifyObjectProperties'));
36  HookRegistry::register('Issue::getProperties::fullProperties', array($this, 'modifyObjectProperties'));
37  HookRegistry::register('Issue::getProperties::values', array($this, 'modifyObjectPropertyValues'));
38  HookRegistry::register('Form::config::before', array($this, 'addPublicationFormFields'));
39  HookRegistry::register('Form::config::before', array($this, 'addPublishFormNotice'));
40  HookRegistry::register('TemplateManager::display', array($this, 'loadUrnFieldComponent'));
41  }
42  return $success;
43  }
44 
45  //
46  // Implement template methods from Plugin.
47  //
51  function getDisplayName() {
52  return __('plugins.pubIds.urn.displayName');
53  }
54 
58  function getDescription() {
59  return __('plugins.pubIds.urn.description');
60  }
61 
62 
63  //
64  // Implement template methods from PubIdPlugin.
65  //
69  function constructPubId($pubIdPrefix, $pubIdSuffix, $contextId) {
70  $urn = $pubIdPrefix . $pubIdSuffix;
71  $suffixFieldName = $this->getSuffixFieldName();
72  $suffixGenerationStrategy = $this->getSetting($contextId, $suffixFieldName);
73  // checkNo is already calculated for custom suffixes
74  if ($suffixGenerationStrategy != 'customId' && $this->getSetting($contextId, 'urnCheckNo')) {
75  $urn .= $this->_calculateCheckNo($urn);
76  }
77  return $urn;
78  }
79 
83  function getPubIdType() {
84  return 'other::urn';
85  }
86 
90  function getPubIdDisplayType() {
91  return 'URN';
92  }
93 
97  function getPubIdFullName() {
98  return 'Uniform Resource Name';
99  }
100 
104  function getResolvingURL($contextId, $pubId) {
105  $resolverURL = $this->getSetting($contextId, 'urnResolver');
106  return $resolverURL . $pubId;
107  }
108 
112  function getPubIdMetadataFile() {
113  return $this->getTemplateResource('urnSuffixEdit.tpl');
114  }
115 
119  function addJavaScript($request, $templateMgr) {
120  $templateMgr->addJavaScript(
121  'urnCheckNo',
122  $request->getBaseUrl() . DIRECTORY_SEPARATOR . $this->getPluginPath() . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR . 'checkNumber.js',
123  array(
124  'inline' => false,
125  'contexts' => ['publicIdentifiersForm', 'backend'],
126  )
127  );
128  }
129 
133  function getPubIdAssignFile() {
134  return $this->getTemplateResource('urnAssign.tpl');
135  }
136 
140  function instantiateSettingsForm($contextId) {
141  $this->import('classes.form.URNSettingsForm');
142  return new URNSettingsForm($this, $contextId);
143  }
144 
148  function getFormFieldNames() {
149  return array('urnSuffix');
150  }
151 
156  return 'assignURN';
157  }
158 
162  function getPrefixFieldName() {
163  return 'urnPrefix';
164  }
165 
169  function getSuffixFieldName() {
170  return 'urnSuffix';
171  }
172 
176  function getLinkActions($pubObject) {
177  $linkActions = array();
178  import('lib.pkp.classes.linkAction.request.RemoteActionConfirmationModal');
179  $request = Application::get()->getRequest();
180  $userVars = $request->getUserVars();
181  $userVars['pubIdPlugIn'] = get_class($this);
182  // Clear object pub id
183  $linkActions['clearPubIdLinkActionURN'] = new LinkAction(
184  'clearPubId',
186  $request->getSession(),
187  __('plugins.pubIds.urn.editor.clearObjectsURN.confirm'),
188  __('common.delete'),
189  $request->url(null, null, 'clearPubId', null, $userVars),
190  'modal_delete'
191  ),
192  __('plugins.pubIds.urn.editor.clearObjectsURN'),
193  'delete',
194  __('plugins.pubIds.urn.editor.clearObjectsURN')
195  );
196  return $linkActions;
197  }
198 
203  return array(
204  'Submission' => 'urnPublicationSuffixPattern',
205  'Representation' => 'urnRepresentationSuffixPattern',
206  'SubmissionFile' => 'urnSubmissionFileSuffixPattern',
207  'Chapter' => 'urnChapterSuffixPattern',
208  );
209  }
210 
214  function getDAOFieldNames() {
215  return array('pub-id::other::urn');
216  }
217 
221  function isObjectTypeEnabled($pubObjectType, $contextId) {
222  return (boolean) $this->getSetting($contextId, "enable${pubObjectType}URN");
223  }
224 
228  function getNotUniqueErrorMsg() {
229  return __('plugins.pubIds.urn.editor.urnSuffixCustomIdentifierNotUnique');
230  }
231 
245  public function modifyObjectProperties($hookName, $args) {
246  $props =& $args[0];
247 
248  $props[] = 'pub-id::other::urn';
249  }
250 
264  public function modifyObjectPropertyValues($hookName, $args) {
265  $values =& $args[0];
266  $object = $args[1];
267  $props = $args[2];
268 
269  // URNs are not supported for IssueGalleys
270  if (get_class($object) === 'IssueGalley') {
271  return;
272  }
273 
274  // URNs are already added to property values for Publications and Galleys
275  if (get_class($object) === 'Publication' || get_class($object) === 'ArticleGalley') {
276  return;
277  }
278 
279  if (in_array('pub-id::other::urn', $props)) {
280  $pubId = $this->getPubId($object);
281  $values['pub-id::other::urn'] = $pubId ? $pubId : null;
282  }
283  }
284 
291  public function validatePublicationUrn($hookName, $args) {
292  $errors =& $args[0];
293  $action = $args[1];
294  $props =& $args[2];
295 
296  if (empty($props['pub-id::other::urn'])) {
297  return;
298  }
299 
300  if ($action === VALIDATE_ACTION_ADD) {
301  $submission = Services::get('submission')->get($props['submissionId']);
302  } else {
303  $publication = Services::get('publication')->get($props['id']);
304  $submission = Services::get('submission')->get($publication->getData('submissionId'));
305  }
306 
307  $contextId = $submission->getData('contextId');
308  $urnPrefix = $this->getSetting($contextId, 'urnPrefix');
309 
310  $urnErrors = [];
311  if (strpos($props['pub-id::other::urn'], $urnPrefix) !== 0) {
312  $urnErrors[] = __('plugins.pubIds.urn.editor.missingPrefix', ['urnPrefix' => $urnPrefix]);
313  }
314  if (!$this->checkDuplicate($props['pub-id::other::urn'], 'Publication', $submission->getId(), $contextId)) {
315  $urnErrors[] = $this->getNotUniqueErrorMsg();
316  }
317  if (!empty($urnErrors)) {
318  $errors['pub-id::other::urn'] = $urnErrors;
319  }
320  }
321 
328  public function addPublicationFormFields($hookName, $form) {
329 
330  if ($form->id !== 'publicationIdentifiers') {
331  return;
332  }
333 
334  if (!$this->getSetting($form->submissionContext->getId(), 'enablePublicationURN')) {
335  return;
336  }
337 
338  $prefix = $this->getSetting($form->submissionContext->getId(), 'urnPrefix');
339 
340  $suffixType = $this->getSetting($form->submissionContext->getId(), 'urnSuffix');
341  $pattern = '';
342  if ($suffixType === 'default') {
343  $pattern = '%p.%m';
344  } elseif ($suffixType === 'pattern') {
345  $pattern = $this->getSetting($form->submissionContext->getId(), 'urnPublicationSuffixPattern');
346  }
347 
348  // If a pattern exists, use a DOI-like field to generate the URN
349  if ($pattern) {
350  $fieldData = [
351  'label' => __('plugins.pubIds.urn.displayName'),
352  'value' => $form->publication->getData('pub-id::other::urn'),
353  'prefix' => $prefix,
354  'pattern' => $pattern,
355  'contextInitials' => $form->submissionContext->getData('acronym', $form->submissionContext->getData('primaryLocale')) ?? '',
356  'isPForPress' => true,
357  'submissionId' => $form->publication->getData('submissionId'),
358  'assignIdLabel' => __('plugins.pubIds.urn.editor.urn.assignUrn'),
359  'clearIdLabel' => __('plugins.pubIds.urn.editor.clearObjectsURN'),
360  'missingPartsLabel' => __('plugins.pubIds.doi.editor.missingParts'),
361  ];
362  if ($form->publication->getData('pub-id::publisher-id')) {
363  $fieldData['publisherId'] = $form->publication->getData('pub-id::publisher-id');
364  }
365  if ($form->publication->getData('pages')) {
366  $fieldData['pages'] = $form->publication->getData('pages');
367  }
368  if ($form->publication->getData('issueId')) {
369  $issue = Services::get('issue')->get($form->publication->getData('issueId'));
370  if ($issue) {
371  $fieldData['issueNumber'] = $issue->getNumber() ?? '';
372  $fieldData['issueVolume'] = $issue->getVolume() ?? '';
373  $fieldData['year'] = $issue->getYear() ?? '';
374  }
375  }
376  $form->addField(new \PKP\components\forms\FieldPubId('pub-id::other::urn', $fieldData));
377 
378  // Otherwise add a field for manual entry that includes a button to generate
379  // the check number
380  } else {
381  // Load the checkNumber.js file that is required for this field
383 
384  $this->import('classes.form.FieldUrn');
385  $form->addField(new \Plugins\Generic\URN\FieldUrn('pub-id::other::urn', [
386  'label' => __('plugins.pubIds.urn.displayName'),
387  'description' => __('plugins.pubIds.urn.editor.urn.description', ['prefix' => $prefix]),
388  'value' => $form->publication->getData('pub-id::other::urn'),
389  'addCheckNumberLabel' => __('plugins.pubIds.urn.editor.addCheckNo'),
390  ]));
391  }
392  }
393 
400  public function addPublishFormNotice($hookName, $form) {
401 
402  if ($form->id !== 'publish' || !empty($form->errors)) {
403  return;
404  }
405 
406  $submission = Services::get('submission')->get($form->publication->getData('submissionId'));
407  $publicationUrnEnabled = $this->getSetting($submission->getData('contextId'), 'enablePublicationURN');
408  $galleyUrnEnabled = $this->getSetting($submission->getData('contextId'), 'enableRepresentationURN');
409  $warningIconHtml = '<span class="fa fa-exclamation-triangle pkpIcon--inline"></span>';
410 
411  if (!$publicationUrnEnabled && !$galleyUrnEnabled) {
412  return;
413 
414  // Use a simplified view when only assigning to the publication
415  } else if (!$galleyUrnEnabled) {
416  if ($form->publication->getData('pub-id::other::urn')) {
417  $msg = __('plugins.pubIds.urn.editor.preview.publication', ['urn' => $form->publication->getData('pub-id::other::urn')]);
418  } else {
419  $msg = '<div class="pkpNotification pkpNotification--warning">' . $warningIconHtml . __('plugins.pubIds.urn.editor.preview.publication.none') . '</div>';
420  }
421  $form->addField(new \PKP\components\forms\FieldHTML('urn', [
422  'description' => $msg,
423  'groupId' => 'default',
424  ]));
425  return;
426 
427  // Show a table if more than one URN is going to be created
428  } else {
429  $urnTableRows = [];
430  if ($publicationUrnEnabled) {
431  if ($form->publication->getData('pub-id::other::urn')) {
432  $urnTableRows[] = [$form->publication->getData('pub-id::other::urn'), 'Publication'];
433  } else {
434  $urnTableRows[] = [$warningIconHtml . __('submission.status.unassigned'), 'Publication'];
435  }
436  }
437  if ($galleyUrnEnabled) {
438  foreach ((array) $form->publication->getData('galleys') as $galley) {
439  if ($galley->getStoredPubId('other::urn')) {
440  $urnTableRows[] = [$galley->getStoredPubId('other::urn'), __('plugins.pubIds.urn.editor.preview.galleys', ['galleyLabel' => $galley->getGalleyLabel()])];
441  } else {
442  $urnTableRows[] = [$warningIconHtml . __('submission.status.unassigned'),__('plugins.pubIds.urn.editor.preview.galleys', ['galleyLabel' => $galley->getGalleyLabel()])];
443  }
444  }
445  }
446  if (!empty($urnTableRows)) {
447  $table = '<table class="pkpTable"><thead><tr>' .
448  '<th>' . __('plugins.pubIds.urn.displayName') . '</th>' .
449  '<th>' . __('plugins.pubIds.urn.editor.preview.objects') . '</th>' .
450  '</tr></thead><tbody>';
451  foreach ($urnTableRows as $urnTableRow) {
452  $table .= '<tr><td>' . $urnTableRow[0] . '</td><td>' . $urnTableRow[1] . '</td></tr>';
453  }
454  $table .= '</tbody></table>';
455  }
456  $form->addField(new \PKP\components\forms\FieldHTML('urn', [
457  'description' => $table,
458  'groupId' => 'default',
459  ]));
460  }
461  }
462 
469  public function loadUrnFieldComponent($hookName, $args) {
470  $templateMgr = $args[0];
471  $template = $args[1];
472 
473  if ($template !== 'workflow/workflow.tpl') {
474  return;
475  }
476 
477  $templateMgr->addJavaScript(
478  'urn-field-component',
479  Application::get()->getRequest()->getBaseUrl() . '/' . $this->getPluginPath() . '/js/FieldUrn.js',
480  [
481  'contexts' => 'backend',
482  'priority' => STYLE_SEQUENCE_LAST,
483  ]
484  );
485 
486  $templateMgr->addStyleSheet(
487  'urn-field-component',
488  '
489  .pkpFormField--urn__input {
490  display: inline-block;
491  }
492 
493  .pkpFormField--urn__button {
494  margin-left: 0.25rem;
495  height: 2.5rem; // Match input height
496  }
497  ',
498  [
499  'contexts' => 'backend',
500  'inline' => true,
501  'priority' => STYLE_SEQUENCE_LAST,
502  ]
503  );
504  }
505 
506 
507  //
508  // Private helper methods
509  //
519  function _calculateCheckNo($urn) {
520  $urnLower = strtolower_codesafe($urn);
521  $conversionTable = array('9' => '41', '8' => '9', '7' => '8', '6' => '7', '5' => '6', '4' => '5', '3' => '4', '2' => '3', '1' => '2', '0' => '1', 'a' => '18', 'b' => '14', 'c' => '19', 'd' => '15', 'e' => '16', 'f' => '21', 'g' => '22', 'h' => '23', 'i' => '24', 'j' => '25', 'k' => '42', 'l' => '26', 'm' => '27', 'n' => '13', 'o' => '28', 'p' => '29', 'q' => '31', 'r' => '12', 's' => '32', 't' => '33', 'u' => '11', 'v' => '34', 'w' => '35', 'x' => '36', 'y' => '37', 'z' => '38', '-' => '39', ':' => '17', '_' => '43', '/' => '45', '.' => '47', '+' => '49');
522  $newURN = '';
523  for ($i = 0; $i < strlen($urnLower); $i++) {
524  $char = $urnLower[$i];
525  $newURN .= $conversionTable[$char];
526  }
527  $sum = 0;
528  for ($j = 1; $j <= strlen($newURN); $j++) {
529  $sum = $sum + ($newURN[$j-1] * $j);
530  }
531  $lastNumber = $newURN[strlen($newURN)-1];
532  $quot = $sum / $lastNumber;
533  $quotRound = floor($quot);
534  $quotString = (string)$quotRound;
535  return $quotString[strlen($quotString)-1];
536  }
537 
538 
539 }
URNSettingsForm
Form for journal managers to setup URN plugin.
Definition: URNSettingsForm.inc.php:19
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.
URNPubIdPlugin\addJavaScript
addJavaScript($request, $templateMgr)
Definition: URNPubIdPlugin.inc.php:119
Plugin\getRequest
& getRequest()
Definition: Plugin.inc.php:828
URNPubIdPlugin\getPubIdMetadataFile
getPubIdMetadataFile()
Definition: URNPubIdPlugin.inc.php:112
FieldUrn
A field for entering a URN and then having the check number generated.
URNPubIdPlugin\getNotUniqueErrorMsg
getNotUniqueErrorMsg()
Definition: URNPubIdPlugin.inc.php:228
PubIdPlugin
Public identifiers plugins common functions.
Definition: PubIdPlugin.inc.php:18
URNPubIdPlugin\modifyObjectPropertyValues
modifyObjectPropertyValues($hookName, $args)
Definition: URNPubIdPlugin.inc.php:264
URNPubIdPlugin\getPrefixFieldName
getPrefixFieldName()
Definition: URNPubIdPlugin.inc.php:162
URNPubIdPlugin
URN plugin class.
Definition: URNPubIdPlugin.inc.php:19
PubIdPlugin\checkDuplicate
checkDuplicate($pubId, $pubObjectType, $excludeId, $contextId)
Definition: PubIdPlugin.inc.php:168
URNPubIdPlugin\loadUrnFieldComponent
loadUrnFieldComponent($hookName, $args)
Definition: URNPubIdPlugin.inc.php:469
URNPubIdPlugin\getPubIdDisplayType
getPubIdDisplayType()
Definition: URNPubIdPlugin.inc.php:90
URNPubIdPlugin\getSuffixFieldName
getSuffixFieldName()
Definition: URNPubIdPlugin.inc.php:169
Plugins
URNPubIdPlugin\getDAOFieldNames
getDAOFieldNames()
Definition: URNPubIdPlugin.inc.php:214
URNPubIdPlugin\getPubIdAssignFile
getPubIdAssignFile()
Definition: URNPubIdPlugin.inc.php:133
Plugin\getEnabled
getEnabled()
Definition: Plugin.inc.php:868
Plugin\getSetting
getSetting($contextId, $name)
Definition: Plugin.inc.php:473
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
URNPubIdPlugin\getFormFieldNames
getFormFieldNames()
Definition: URNPubIdPlugin.inc.php:148
LinkAction
Base class defining an action that can be performed by the user in the user interface.
Definition: LinkAction.inc.php:22
URNPubIdPlugin\instantiateSettingsForm
instantiateSettingsForm($contextId)
Definition: URNPubIdPlugin.inc.php:140
PubIdPlugin\getPubId
getPubId($pubObject)
Definition: PubIdPlugin.inc.php:43
PKPTemplateManager\getManager
static & getManager($request=null)
Definition: PKPTemplateManager.inc.php:1239
URNPubIdPlugin\getResolvingURL
getResolvingURL($contextId, $pubId)
Definition: URNPubIdPlugin.inc.php:104
URNPubIdPlugin\_calculateCheckNo
_calculateCheckNo($urn)
Definition: URNPubIdPlugin.inc.php:519
URNPubIdPlugin\addPublicationFormFields
addPublicationFormFields($hookName, $form)
Definition: URNPubIdPlugin.inc.php:328
URNPubIdPlugin\getDisplayName
getDisplayName()
Definition: URNPubIdPlugin.inc.php:51
Plugin\getTemplateResource
getTemplateResource($template=null, $inCore=false)
Definition: Plugin.inc.php:349
strtolower_codesafe
strtolower_codesafe($str)
Definition: functions.inc.php:280
Plugin\getPluginPath
getPluginPath()
Definition: Plugin.inc.php:330
URNPubIdPlugin\isObjectTypeEnabled
isObjectTypeEnabled($pubObjectType, $contextId)
Definition: URNPubIdPlugin.inc.php:221
URNPubIdPlugin\getPubIdType
getPubIdType()
Definition: URNPubIdPlugin.inc.php:83
Plugin\$request
$request
Definition: Plugin.inc.php:68
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
URNPubIdPlugin\getSuffixPatternsFieldNames
getSuffixPatternsFieldNames()
Definition: URNPubIdPlugin.inc.php:202
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
URNPubIdPlugin\getPubIdFullName
getPubIdFullName()
Definition: URNPubIdPlugin.inc.php:97
FieldHTML
A component for inserting HTML into a form, when you don't need any input fields or values stored.
URNPubIdPlugin\getDescription
getDescription()
Definition: URNPubIdPlugin.inc.php:58
URNPubIdPlugin\validatePublicationUrn
validatePublicationUrn($hookName, $args)
Definition: URNPubIdPlugin.inc.php:291
URNPubIdPlugin\constructPubId
constructPubId($pubIdPrefix, $pubIdSuffix, $contextId)
Definition: URNPubIdPlugin.inc.php:69
URNPubIdPlugin\getLinkActions
getLinkActions($pubObject)
Definition: URNPubIdPlugin.inc.php:176
URNPubIdPlugin\addPublishFormNotice
addPublishFormNotice($hookName, $form)
Definition: URNPubIdPlugin.inc.php:400
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49
URNPubIdPlugin\getAssignFormFieldName
getAssignFormFieldName()
Definition: URNPubIdPlugin.inc.php:155
URNPubIdPlugin\modifyObjectProperties
modifyObjectProperties($hookName, $args)
Definition: URNPubIdPlugin.inc.php:245