Skip to content

Commit 4314e65

Browse files
Merge pull request #23 from lepidus/stable-3_3_0
Feature/added work exists validation (OMP 3.3.0)
2 parents 820ff65 + 0839b29 commit 4314e65

96 files changed

Lines changed: 1746 additions & 4671 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitlab-ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ include:
1313
- rm -rf lib/APIKeyEncryption
1414
- git submodule update --init --depth 1
1515
- composer install
16+
17+
unit_test_php_7_3:
18+
rules:
19+
- when: never

ThothPlugin.inc.php

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
* @brief Plugin for integration with Thoth for communication and synchronization of book data between the two platforms
1616
*/
1717

18+
require_once(__DIR__ . '/vendor/autoload.php');
19+
1820
import('lib.pkp.classes.plugins.GenericPlugin');
1921
import('plugins.generic.thoth.classes.ThothBadgeRender');
2022
import('plugins.generic.thoth.classes.ThothNotification');
2123
import('plugins.generic.thoth.classes.ThothRegister');
2224
import('plugins.generic.thoth.classes.ThothUpdater');
23-
import('plugins.generic.thoth.lib.thothAPI.exceptions.ThothException');
2425

2526
class ThothPlugin extends GenericPlugin
2627
{
@@ -120,26 +121,4 @@ public function manage($args, $request)
120121
}
121122
return parent::manage($args, $request);
122123
}
123-
124-
public function getThothClient($contextId = null)
125-
{
126-
$contextId = $contextId ?? Application::get()->getRequest()->getContext()->getId();
127-
128-
$email = $this->getSetting($contextId, 'email');
129-
$password = $this->getSetting($contextId, 'password');
130-
131-
if (!$email || !$password) {
132-
throw new ThothException("Credentials not configured", 0);
133-
}
134-
135-
import('plugins.generic.thoth.lib.APIKeyEncryption.APIKeyEncryption');
136-
$password = APIKeyEncryption::decryptString($password);
137-
$testEnvironment = $this->getSetting($contextId, 'testEnvironment');
138-
139-
import('plugins.generic.thoth.lib.thothAPI.ThothClient');
140-
$thothClient = new ThothClient($testEnvironment);
141-
$thothClient->login($email, $password);
142-
143-
return $thothClient;
144-
}
145124
}

ThothSettingsForm.inc.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
* @brief Form for managers to modify Thoth plugin settings
1616
*/
1717

18+
use ThothApi\Exception\QueryException;
19+
use ThothApi\GraphQL\Client;
20+
1821
import('lib.pkp.classes.form.Form');
1922
import('plugins.generic.thoth.lib.APIKeyEncryption.APIKeyEncryption');
20-
import('plugins.generic.thoth.lib.thothAPI.ThothClient');
2123

2224
class ThothSettingsForm extends Form
2325
{
@@ -48,13 +50,17 @@ public function __construct($plugin, $contextId)
4850
function ($password) use ($form) {
4951
$email = trim($this->getData('email'));
5052
$testEnvironment = $this->getData('testEnvironment');
51-
$thothClient = new ThothClient($testEnvironment);
53+
54+
$httpConfig = [];
55+
if ($testEnvironment) {
56+
$httpConfig['base_uri'] = 'http://localhost:8000/';
57+
}
58+
59+
$client = new Client($httpConfig);
60+
5261
try {
53-
$thothClient->login(
54-
$email,
55-
$password
56-
);
57-
} catch (ThothException $e) {
62+
$client->login($email, $password);
63+
} catch (QueryException $e) {
5864
return false;
5965
}
6066
return true;

classes/ThothRegister.inc.php

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* @brief Manage callback functions to register works in Thoth
1414
*/
1515

16+
use ThothApi\Exception\QueryException;
17+
1618
import('plugins.generic.thoth.classes.facades.ThothService');
1719
import('plugins.generic.thoth.classes.ThothValidator');
1820

@@ -51,12 +53,14 @@ public function addThothField($hookName, $form)
5153
$errors = [];
5254

5355
try {
54-
$thothClient = $this->plugin->getThothClient($submission->getData('contextId'));
55-
$publishers = $thothClient->linkedPublishers();
56+
$thothClient = ThothContainer::getInstance()->get('client');
57+
$thothAccountDetails = $thothClient->accountDetails();
58+
$publishers = $thothAccountDetails['resourceAccess']['linkedPublishers'];
59+
5660
$imprints = $thothClient->imprints(['publishers' => array_column($publishers, 'publisherId')]);
57-
} catch (ThothException $e) {
61+
} catch (QueryException $e) {
5862
$errors[] = __('plugins.generic.thoth.connectionError');
59-
error_log($e->getMessage());
63+
error_log('Failed to send the request to Thoth: ' . $e->getMessage());
6064
}
6165

6266
if (empty($errors)) {
@@ -83,8 +87,8 @@ public function addThothField($hookName, $form)
8387
$imprintOptions = [];
8488
foreach ($imprints as $imprint) {
8589
$imprintOptions[] = [
86-
'value' => $imprint['imprintId'],
87-
'label' => $imprint['imprintName']
90+
'value' => $imprint->getImprintId(),
91+
'label' => $imprint->getImprintName()
8892
];
8993
}
9094

@@ -102,7 +106,7 @@ public function addThothField($hookName, $form)
102106
'required' => true,
103107
'showWhen' => 'registerConfirmation',
104108
'groupId' => 'default',
105-
'value' => $imprints[0]['imprintId'] ?? null
109+
'value' => $imprintOptions[0]['value'] ?? null
106110
]));
107111

108112
return false;
@@ -187,11 +191,10 @@ public function registerWork($submission, $imprint)
187191
}
188192

189193
try {
190-
$thothClient = $this->plugin->getThothClient($submissionContext->getId());
191-
$thothBook = ThothService::work()->registerBook($thothClient, $submission, $imprint);
194+
$thothBook = ThothService::work()->registerBook($submission, $imprint);
192195
$submission = Services::get('submission')->edit(
193196
$submission,
194-
['thothWorkId' => $thothBook->getId()],
197+
['thothWorkId' => $thothBook->getWorkId()],
195198
$request
196199
);
197200

@@ -201,14 +204,14 @@ public function registerWork($submission, $imprint)
201204
NOTIFICATION_TYPE_SUCCESS,
202205
'plugins.generic.thoth.register.success'
203206
);
204-
} catch (ThothException $e) {
205-
error_log($e->getMessage());
207+
} catch (QueryException $e) {
208+
error_log('Failed to send the request to Thoth: ' . $e->getMessage());
206209
ThothNotification::notify(
207210
$request,
208211
$submission,
209212
NOTIFICATION_TYPE_ERROR,
210213
'plugins.generic.thoth.register.error',
211-
$e->getError()
214+
$e->getMessage()
212215
);
213216
}
214217
}

classes/ThothUpdater.inc.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* @brief Manage callback functions to update works in Thoth
1414
*/
1515

16+
use ThothApi\Exception\QueryException;
17+
1618
import('plugins.generic.thoth.classes.facades.ThothService');
1719

1820
class ThothUpdater
@@ -37,23 +39,22 @@ public function updateWork($hookName, $args)
3739
}
3840

3941
try {
40-
$thothClient = $this->plugin->getThothClient($submission->getData('contextId'));
41-
ThothService::work()->updateBook($thothClient, $thothWorkId, $submission, $publication);
42+
ThothService::work()->updateBook($thothWorkId, $submission, $publication);
4243

4344
ThothNotification::notify(
4445
$request,
4546
$submission,
4647
NOTIFICATION_TYPE_SUCCESS,
4748
'plugins.generic.thoth.update.success'
4849
);
49-
} catch (ThothException $e) {
50-
error_log($e->getMessage());
50+
} catch (QueryException $e) {
51+
error_log('Failed to send the request to Thoth: ' . $e->getMessage());
5152
ThothNotification::notify(
5253
$request,
5354
$submission,
5455
NOTIFICATION_TYPE_ERROR,
5556
'plugins.generic.thoth.update.error',
56-
$e->getError()
57+
$e->getMessage()
5758
);
5859
}
5960

classes/ThothValidator.inc.php

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
* @brief Validate submission metadata to Thoth submit
1414
*/
1515

16-
require_once(__DIR__ . '/../vendor/autoload.php');
17-
1816
use Biblys\Isbn\Isbn;
17+
use ThothApi\GraphQL\Models\Work as ThothWork;
1918

2019
import('plugins.generic.thoth.classes.facades.ThothService');
2120

@@ -25,6 +24,29 @@ public static function validate($submission)
2524
{
2625
$errors = [];
2726

27+
$publication = $submission->getCurrentPublication();
28+
$doi = $publication->getStoredPubId('doi');
29+
$doiUrl = ThothService::work()->getDoiResolvingUrl($doi);
30+
31+
if ($doiUrl !== null) {
32+
$errors = array_merge($errors, self::validateDoiExists($doiUrl));
33+
}
34+
35+
$request = Application::get()->getRequest();
36+
$context = $request->getContext();
37+
$dispatcher = $request->getDispatcher();
38+
39+
$landingPage = $dispatcher->url(
40+
$request,
41+
ROUTE_PAGE,
42+
$context->getPath(),
43+
'catalog',
44+
'book',
45+
$submission->getBestId()
46+
);
47+
48+
$errors = array_merge($errors, self::validateLandingPageExists($landingPage));
49+
2850
$publicationFormats = Application::getRepresentationDao()
2951
->getApprovedByPublicationId($submission->getData('currentPublicationId'))
3052
->toArray();
@@ -44,7 +66,10 @@ public static function validateIsbn($publicationFormats)
4466
foreach ($publicationFormats as $publicationFormat) {
4567
try {
4668
$isbn = ThothService::publication()->getIsbnByPublicationFormat($publicationFormat);
47-
Isbn::validateAsIsbn13($isbn);
69+
if ($isbn !== null) {
70+
Isbn::validateAsIsbn13($isbn);
71+
}
72+
$errors = array_merge($errors, self::validateIsbnExists($isbn));
4873
} catch (Exception $e) {
4974
$errors[] = __('plugins.generic.thoth.validation.isbn', [
5075
'isbn' => $isbn,
@@ -55,4 +80,46 @@ public static function validateIsbn($publicationFormats)
5580

5681
return $errors;
5782
}
83+
84+
public static function validateDoiExists($doi)
85+
{
86+
$errors = [];
87+
88+
try {
89+
$work = ThothService::work()->getByDoi($doi);
90+
if ($work instanceof ThothWork) {
91+
$errors[] = __('plugins.generic.thoth.validation.doiExists', ['doi' => $doi]);
92+
}
93+
} catch (Exception $e) {
94+
return $errors;
95+
}
96+
97+
return $errors;
98+
}
99+
100+
public static function validateLandingPageExists($landingPage)
101+
{
102+
$errors = [];
103+
104+
$works = ThothService::work()->search($landingPage);
105+
106+
if (!empty($works)) {
107+
$errors[] = __('plugins.generic.thoth.validation.landingPageExists', ['landingPage' => $landingPage]);
108+
}
109+
110+
return $errors;
111+
}
112+
113+
public static function validateIsbnExists($isbn)
114+
{
115+
$errors = [];
116+
117+
$publications = ThothService::publication()->search($isbn);
118+
119+
if (!empty($publications)) {
120+
$errors[] = __('plugins.generic.thoth.validation.isbnExists', ['isbn' => $isbn]);
121+
}
122+
123+
return $errors;
124+
}
58125
}

classes/components/forms/RegisterForm.inc.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public function __construct($action, $imprints, $errors)
5858
$imprintOptions = [];
5959
foreach ($imprints as $imprint) {
6060
$imprintOptions[] = [
61-
'value' => $imprint['imprintId'],
62-
'label' => $imprint['imprintName']
61+
'value' => $imprint->getImprintId(),
62+
'label' => $imprint->getImprintName()
6363
];
6464
}
6565

@@ -85,7 +85,7 @@ public function __construct($action, $imprints, $errors)
8585
'options' => $imprintOptions,
8686
'required' => true,
8787
'groupId' => 'default',
88-
'value' => $imprints[0]['imprintId'] ?? null
88+
'value' => $imprintOptions[0]['value'] ?? null
8989
]));
9090
}
9191

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/**
4+
* @file plugins/generic/thoth/tests/classes/container/Container.inc.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 Container
11+
* @ingroup plugins_generic_thoth
12+
*
13+
* @brief Simple dependency injection container implementation
14+
*/
15+
16+
class Container
17+
{
18+
private $bindings = [];
19+
20+
public function set($id, $factory)
21+
{
22+
$this->bindings[$id] = $factory;
23+
}
24+
25+
public function get($id)
26+
{
27+
if (!isset($this->bindings[$id])) {
28+
throw new Exception("Target binding \"$id\" does not exist.");
29+
}
30+
31+
$factory = $this->bindings[$id];
32+
33+
return $factory($this);
34+
}
35+
36+
public function backup($id)
37+
{
38+
return $this->bindings[$id];
39+
}
40+
41+
public function register($containerProvider)
42+
{
43+
$containerProvider->register($this);
44+
}
45+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/**
4+
* @file plugins/generic/thoth/tests/classes/container/ContainerProvider.inc.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 ContainerProvider
11+
* @ingroup plugins_generic_thoth
12+
*
13+
* @brief Interface to package container bindings
14+
*/
15+
16+
interface ContainerProvider
17+
{
18+
public function register($container);
19+
}

0 commit comments

Comments
 (0)