Skip to content

Commit 820ff65

Browse files
Merge pull request #21 from lepidus/stable-3_3_0
Feature/added publication format ISBN validation (OMP 3.3.0)
2 parents 6704fa4 + fc4fe65 commit 820ff65

16 files changed

Lines changed: 301 additions & 64 deletions

File tree

.github/workflows/generate-package.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ jobs:
3434
mkdir $PLUGIN_NAME
3535
shopt -s extglob
3636
cp -r !($PLUGIN_NAME|.git*|.|..|tests) $PLUGIN_NAME
37+
wget -O composer.phar https://getcomposer.org/composer-stable.phar
38+
php composer.phar install -d ${PLUGIN_NAME}
3739
tar -zcvf $PLUGIN_NAME.tar.gz $PLUGIN_NAME
3840
shell: bash
3941
- name: Create the release
@@ -47,7 +49,7 @@ jobs:
4749
draft: false
4850
prerelease: false
4951
- name: Upload the package as release asset
50-
id: upload-release-asset
52+
id: upload-release-asset
5153
uses: actions/upload-release-asset@v1
5254
env:
5355
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor

.gitlab-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ include:
1212
before_script:
1313
- rm -rf lib/APIKeyEncryption
1414
- git submodule update --init --depth 1
15+
- composer install

ThothPlugin.inc.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function register($category, $path, $mainContextId = null)
3131
if ($success && $this->getEnabled()) {
3232
$thothRegister = new ThothRegister($this);
3333
HookRegistry::register('Schema::get::submission', [$thothRegister, 'addWorkIdToSchema']);
34-
HookRegistry::register('Form::config::before', [$thothRegister, 'addImprintField']);
34+
HookRegistry::register('Form::config::before', [$thothRegister, 'addThothField']);
3535
HookRegistry::register('Publication::validatePublish', [$thothRegister, 'validateRegister']);
3636
HookRegistry::register('TemplateManager::display', [$thothRegister, 'addResources']);
3737
HookRegistry::register('Publication::publish', [$thothRegister, 'registerOnPublish']);

classes/ThothRegister.inc.php

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
import('plugins.generic.thoth.classes.facades.ThothService');
17+
import('plugins.generic.thoth.classes.ThothValidator');
1718

1819
class ThothRegister
1920
{
@@ -35,9 +36,8 @@ public function addWorkIdToSchema($hookName, $args)
3536
return false;
3637
}
3738

38-
public function addImprintField($hookName, $form)
39+
public function addThothField($hookName, $form)
3940
{
40-
4141
if ($form->id !== 'publish' || !empty($form->errors)) {
4242
return;
4343
}
@@ -48,48 +48,63 @@ public function addImprintField($hookName, $form)
4848
return;
4949
}
5050

51+
$errors = [];
52+
5153
try {
5254
$thothClient = $this->plugin->getThothClient($submission->getData('contextId'));
5355
$publishers = $thothClient->linkedPublishers();
5456
$imprints = $thothClient->imprints(['publishers' => array_column($publishers, 'publisherId')]);
57+
} catch (ThothException $e) {
58+
$errors[] = __('plugins.generic.thoth.connectionError');
59+
error_log($e->getMessage());
60+
}
5561

56-
$imprintOptions = [];
57-
foreach ($imprints as $imprint) {
58-
$imprintOptions[] = [
59-
'value' => $imprint['imprintId'],
60-
'label' => $imprint['imprintName']
61-
];
62-
}
62+
if (empty($errors)) {
63+
$errors = ThothValidator::validate($submission);
64+
}
6365

64-
$form->addField(new \PKP\components\forms\FieldOptions('registerConfirmation', [
65-
'label' => __('plugins.generic.thoth.register.label'),
66-
'options' => [
67-
['value' => true, 'label' => __('plugins.generic.thoth.register.confirmation')]
68-
],
69-
'value' => false,
70-
'groupId' => 'default',
71-
]))
72-
->addField(new \PKP\components\forms\FieldSelect('imprint', [
73-
'label' => __('plugins.generic.thoth.imprint'),
74-
'options' => $imprintOptions,
75-
'required' => true,
76-
'showWhen' => 'registerConfirmation',
77-
'groupId' => 'default',
78-
'value' => $imprints[0]['imprintId'] ?? null
79-
]));
80-
} catch (ThothException $e) {
81-
$warningIconHtml = '<span class="fa fa-exclamation-triangle pkpIcon--inline"></span>';
82-
$noticeMsg = __('plugins.generic.thoth.connectionError');
83-
$msg = '<div class="pkpNotification pkpNotification--warning">' . $warningIconHtml . $noticeMsg . '</div>';
66+
if (!empty($errors)) {
67+
$msg = '<div class="pkpNotification pkpNotification--warning">';
68+
$msg .= __('plugins.generic.thoth.register.warning');
69+
$msg .= '<ul>';
70+
foreach ($errors as $error) {
71+
$msg .= '<li>' . $error . '</li>';
72+
}
73+
$msg .= '</ul></div>';
8474

8575
$form->addField(new \PKP\components\forms\FieldHTML('registerNotice', [
8676
'description' => $msg,
8777
'groupId' => 'default',
8878
]));
8979

90-
error_log($e->getMessage());
80+
return false;
9181
}
9282

83+
$imprintOptions = [];
84+
foreach ($imprints as $imprint) {
85+
$imprintOptions[] = [
86+
'value' => $imprint['imprintId'],
87+
'label' => $imprint['imprintName']
88+
];
89+
}
90+
91+
$form->addField(new \PKP\components\forms\FieldOptions('registerConfirmation', [
92+
'label' => __('plugins.generic.thoth.register.label'),
93+
'options' => [
94+
['value' => true, 'label' => __('plugins.generic.thoth.register.confirmation')]
95+
],
96+
'value' => false,
97+
'groupId' => 'default',
98+
]))
99+
->addField(new \PKP\components\forms\FieldSelect('imprint', [
100+
'label' => __('plugins.generic.thoth.imprint'),
101+
'options' => $imprintOptions,
102+
'required' => true,
103+
'showWhen' => 'registerConfirmation',
104+
'groupId' => 'default',
105+
'value' => $imprints[0]['imprintId'] ?? null
106+
]));
107+
93108
return false;
94109
}
95110

classes/ThothValidator.inc.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/**
4+
* @file plugins/generic/thoth/classes/ThothValidator.php
5+
*
6+
* Copyright (c) 2025 Lepidus Tecnologia
7+
* Copyright (c) 2025 Thoth
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class ThothValidator
11+
* @ingroup plugins_generic_thoth
12+
*
13+
* @brief Validate submission metadata to Thoth submit
14+
*/
15+
16+
require_once(__DIR__ . '/../vendor/autoload.php');
17+
18+
use Biblys\Isbn\Isbn;
19+
20+
import('plugins.generic.thoth.classes.facades.ThothService');
21+
22+
class ThothValidator
23+
{
24+
public static function validate($submission)
25+
{
26+
$errors = [];
27+
28+
$publicationFormats = Application::getRepresentationDao()
29+
->getApprovedByPublicationId($submission->getData('currentPublicationId'))
30+
->toArray();
31+
32+
$publicationFormats = array_filter($publicationFormats, function ($publicationFormat) {
33+
return $publicationFormat->getIsAvailable();
34+
});
35+
36+
$errors = array_merge($errors, self::validateIsbn($publicationFormats));
37+
38+
return $errors;
39+
}
40+
41+
public static function validateIsbn($publicationFormats)
42+
{
43+
$errors = [];
44+
foreach ($publicationFormats as $publicationFormat) {
45+
try {
46+
$isbn = ThothService::publication()->getIsbnByPublicationFormat($publicationFormat);
47+
Isbn::validateAsIsbn13($isbn);
48+
} catch (Exception $e) {
49+
$errors[] = __('plugins.generic.thoth.validation.isbn', [
50+
'isbn' => $isbn,
51+
'formatName' => $publicationFormat->getLocalizedName()
52+
]);
53+
}
54+
}
55+
56+
return $errors;
57+
}
58+
}

classes/components/forms/RegisterForm.inc.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,18 @@ public function __construct($action, $imprints, $errors)
3939
'pageId' => 'default',
4040
]);
4141

42+
$msg = '<div class="pkpNotification pkpNotification--warning">';
43+
$msg .= __('plugins.generic.thoth.register.warning');
44+
$msg .= '<ul>';
4245
foreach ($errors as $error) {
43-
$warningIconHtml = '<span class="fa fa-exclamation-triangle pkpIcon--inline"></span>';
44-
$msg = '<div class="pkpNotification pkpNotification--warning">' . $warningIconHtml . $error . '</div>';
45-
$this->addField(new \PKP\components\forms\FieldHTML('registerNotice', [
46-
'description' => $msg,
47-
'groupId' => 'default',
48-
]));
46+
$msg .= '<li>' . $error . '</li>';
4947
}
48+
$msg .= '</ul></div>';
49+
50+
$this->addField(new \PKP\components\forms\FieldHTML('registerNotice', [
51+
'description' => $msg,
52+
'groupId' => 'default',
53+
]));
5054

5155
return;
5256
}

classes/services/ThothPublicationService.inc.php

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -169,33 +169,10 @@ public function getIsbnByPublicationFormat($publicationFormat)
169169
$identificationCodes = $publicationFormat->getIdentificationCodes()->toArray();
170170
foreach ($identificationCodes as $identificationCode) {
171171
if ($identificationCode->getCode() == "15" || $identificationCode->getCode() == "24") {
172-
$isbn = $identificationCode->getValue();
173-
return $this->convertToIsbn13($isbn);
172+
return $identificationCode->getValue();
174173
}
175174
}
176175

177176
return null;
178177
}
179-
180-
private function convertToIsbn13($isbnString)
181-
{
182-
if (preg_match('/(?=.{17}$)97(?:8|9)([ -])\d{1,5}\1\d{1,7}\1\d{1,6}\1\d$/', $isbnString)) {
183-
return $isbnString;
184-
}
185-
186-
$isbnNumber = preg_replace('/\D/', '', $isbnString);
187-
188-
if (strlen($isbnNumber) != 13) {
189-
return $isbnString;
190-
}
191-
192-
return sprintf(
193-
'%s-%s-%s-%s-%s',
194-
substr($isbnNumber, 0, 3),
195-
substr($isbnNumber, 3, 1),
196-
substr($isbnNumber, 4, 2),
197-
substr($isbnNumber, 6, 6),
198-
substr($isbnNumber, 12, 1)
199-
);
200-
}
201178
}

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"require": {
3+
"biblys/isbn": "~3.0"
4+
}
5+
}

composer.lock

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)