Skip to content

Commit 6293dd0

Browse files
Merge pull request #61 from lepidus/stable-3_3_0
Add publication accessibility metadata (OMP 3.3.0)
2 parents 008a5b6 + 2dcde8e commit 6293dd0

18 files changed

Lines changed: 999 additions & 12 deletions

ThothPlugin.inc.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import('plugins.generic.thoth.classes.components.forms.config.CatalogEntryFormConfig');
2323
import('plugins.generic.thoth.classes.components.forms.config.PublishFormConfig');
2424
import('plugins.generic.thoth.classes.formModifiers.AuthorFormModifier');
25+
import('plugins.generic.thoth.classes.formModifiers.PublicationFormatFormModifier');
2526
import('plugins.generic.thoth.classes.listeners.PublicationEditListener');
2627
import('plugins.generic.thoth.classes.listeners.PublicationPublishListener');
2728
import('plugins.generic.thoth.classes.notification.ThothNotification');
2829
import('plugins.generic.thoth.classes.schema.ThothSchema');
30+
import('plugins.generic.thoth.classes.templateFilters.PublicationFormatTemplateFilter');
2931
import('plugins.generic.thoth.classes.templateFilters.ThothSectionTemplateFilter');
3032

3133
class ThothPlugin extends GenericPlugin
@@ -154,6 +156,16 @@ public function addFormModifiers()
154156
HookRegistry::register('authorform::Constructor', [$authorFormModifier, 'handleFormConstructor']);
155157
HookRegistry::register('authorform::display', [$authorFormModifier, 'handleFormDisplay']);
156158
HookRegistry::register('authorform::execute', [$authorFormModifier, 'handleFormExecute']);
159+
160+
$publicationFormatFormModifier = new PublicationFormatFormModifier($this);
161+
HookRegistry::register(
162+
'publicationformatdao::getAdditionalFieldNames',
163+
[$publicationFormatFormModifier, 'addAccessibilityFieldNames']
164+
);
165+
HookRegistry::register('publicationformatform::display', [$publicationFormatFormModifier, 'handleFormDisplay']);
166+
HookRegistry::register('publicationformatform::readuservars', [$publicationFormatFormModifier, 'handleFormReadUserVars']);
167+
HookRegistry::register('publicationformatform::validate', [$publicationFormatFormModifier, 'handleFormValidate']);
168+
HookRegistry::register('publicationformatform::execute', [$publicationFormatFormModifier, 'handleFormExecute']);
157169
}
158170

159171
public function addEndpoints()

classes/container/providers/ThothRepositoryProvider.inc.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ public function register($container)
8686
});
8787

8888
$container->set('accountRepository', function ($container) {
89-
return new ThothAccountRepository($container->get('client'));
89+
$config = $container->get('config');
90+
$httpConfig = [];
91+
if ($config['customThothApi'] && $config['customThothApiUrl']) {
92+
$httpConfig['base_uri'] = trim($config['customThothApiUrl']);
93+
}
94+
95+
return new ThothAccountRepository($container->get('client'), $httpConfig, $config['token']);
9096
});
9197

9298
$container->set('abstractRepository', function ($container) {

classes/factories/ThothPublicationFactory.inc.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717

1818
class ThothPublicationFactory
1919
{
20+
private const ACCESSIBILITY_FIELDS = [
21+
'accessibilityStandard',
22+
'accessibilityAdditionalStandard',
23+
'accessibilityException',
24+
'accessibilityReportUrl',
25+
];
26+
2027
private const PHYSICAL_PUBLICATION_TYPE_MAPPING = [
2128
'BC' => ThothPublication::PUBLICATION_TYPE_PAPERBACK,
2229
'BB' => ThothPublication::PUBLICATION_TYPE_HARDBACK,
@@ -73,10 +80,19 @@ class ThothPublicationFactory
7380

7481
public function createFromPublicationFormat($publicationFormat, $submissionFile = null)
7582
{
76-
return new ThothPublication([
83+
$publicationData = [
7784
'publicationType' => $this->getPublicationTypeByPublicationFormat($publicationFormat, $submissionFile),
78-
'isbn' => $this->getIsbnByPublicationFormat($publicationFormat)
79-
]);
85+
'isbn' => $this->getIsbnByPublicationFormat($publicationFormat),
86+
];
87+
88+
foreach (self::ACCESSIBILITY_FIELDS as $fieldName) {
89+
$fieldValue = $publicationFormat->getData($fieldName);
90+
if ($fieldValue !== null && $fieldValue !== '') {
91+
$publicationData[$fieldName] = $fieldValue;
92+
}
93+
}
94+
95+
return new ThothPublication($publicationData);
8096
}
8197

8298
private function getPublicationTypeByPublicationFormat($publicationFormat, $submissionFile = null)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
/**
4+
* @file plugins/generic/thoth/classes/formModifiers/PublicationFormatFormModifier.inc.php
5+
*
6+
* Copyright (c) 2024-2026 Lepidus Tecnologia
7+
* Copyright (c) 2024-2026 Thoth
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class PublicationFormatFormModifier
11+
*
12+
* @ingroup plugins_generic_thoth
13+
*
14+
* @brief Handles Thoth accessibility metadata in OMP publication format forms
15+
*/
16+
17+
class PublicationFormatFormModifier
18+
{
19+
public const ACCESSIBILITY_FIELDS = [
20+
'accessibilityStandard',
21+
'accessibilityAdditionalStandard',
22+
'accessibilityException',
23+
'accessibilityReportUrl',
24+
];
25+
26+
private $plugin;
27+
28+
public function __construct($plugin)
29+
{
30+
$this->plugin = $plugin;
31+
}
32+
33+
public function handleFormDisplay($hookName, $args)
34+
{
35+
$form = $args[0];
36+
$templateMgr = TemplateManager::getManager();
37+
$publicationFormat = $form->getPublicationFormat();
38+
39+
foreach (self::ACCESSIBILITY_FIELDS as $fieldName) {
40+
if ($publicationFormat && $form->getData($fieldName) === null) {
41+
$form->setData($fieldName, $publicationFormat->getData($fieldName));
42+
}
43+
}
44+
45+
$templateMgr->assign([
46+
'thothAccessibilityStandardOptions' => $this->getAccessibilityStandardOptions(),
47+
'thothAccessibilityExceptionOptions' => $this->getAccessibilityExceptionOptions(),
48+
]);
49+
50+
$filter = new PublicationFormatTemplateFilter($this->plugin);
51+
$filter->register($templateMgr);
52+
53+
return false;
54+
}
55+
56+
public function addAccessibilityFieldNames($hookName, $args)
57+
{
58+
$fieldNames = & $args[1];
59+
$fieldNames = array_values(array_unique(array_merge($fieldNames, self::ACCESSIBILITY_FIELDS)));
60+
61+
return false;
62+
}
63+
64+
public function handleFormReadUserVars($hookName, $args)
65+
{
66+
$vars = & $args[1];
67+
$vars = array_unique(array_merge($vars, self::ACCESSIBILITY_FIELDS));
68+
69+
return false;
70+
}
71+
72+
public function handleFormValidate($hookName, $args)
73+
{
74+
$form = $args[0];
75+
$reportUrl = trim((string) $form->getData('accessibilityReportUrl'));
76+
77+
if ($reportUrl !== '' && filter_var($reportUrl, FILTER_VALIDATE_URL) === false) {
78+
$form->addError(
79+
'accessibilityReportUrl',
80+
__('plugins.generic.thoth.publicationFormat.accessibilityReportUrl.invalid')
81+
);
82+
}
83+
84+
return false;
85+
}
86+
87+
public function handleFormExecute($hookName, $args)
88+
{
89+
$form = $args[0];
90+
$publicationFormat = $form->getPublicationFormat();
91+
92+
if (!$publicationFormat) {
93+
return false;
94+
}
95+
96+
foreach (self::ACCESSIBILITY_FIELDS as $fieldName) {
97+
$publicationFormat->setData($fieldName, $this->normalizeOptionalValue($form->getData($fieldName)));
98+
}
99+
100+
return false;
101+
}
102+
103+
private function normalizeOptionalValue($value)
104+
{
105+
$value = trim((string) $value);
106+
return $value === '' ? null : $value;
107+
}
108+
109+
private function getAccessibilityStandardOptions()
110+
{
111+
return [
112+
'' => 'common.none',
113+
'WCAG21AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag21aa',
114+
'WCAG21AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag21aaa',
115+
'WCAG22AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag22aa',
116+
'WCAG22AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag22aaa',
117+
'EPUB_A11Y10AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y10aa',
118+
'EPUB_A11Y10AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y10aaa',
119+
'EPUB_A11Y11AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y11aa',
120+
'EPUB_A11Y11AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y11aaa',
121+
'PDF_UA1' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.pdfUa1',
122+
'PDF_UA2' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.pdfUa2',
123+
];
124+
}
125+
126+
private function getAccessibilityExceptionOptions()
127+
{
128+
return [
129+
'' => 'common.none',
130+
'MICRO_ENTERPRISES' => 'plugins.generic.thoth.publicationFormat.accessibilityException.microEnterprises',
131+
'DISPROPORTIONATE_BURDEN' => 'plugins.generic.thoth.publicationFormat.accessibilityException.disproportionateBurden',
132+
'FUNDAMENTAL_ALTERATION' => 'plugins.generic.thoth.publicationFormat.accessibilityException.fundamentalAlteration',
133+
];
134+
}
135+
}

classes/repositories/ThothAccountRepository.inc.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,57 @@
1313
* @brief A repository to manage Thoth accounts
1414
*/
1515

16+
use ThothApi\GraphQL\Client;
17+
use ThothApi\GraphQL\Request;
18+
1619
class ThothAccountRepository
1720
{
21+
private const ME_WITH_PUBLISHERS_QUERY = <<<GQL
22+
query {
23+
me {
24+
publisherContexts {
25+
publisher {
26+
publisherId
27+
publisherName
28+
}
29+
permissions {
30+
publisherAdmin
31+
workLifecycle
32+
cdnWrite
33+
}
34+
}
35+
}
36+
}
37+
GQL;
38+
1839
protected $thothClient;
40+
protected $httpConfig;
41+
protected $token;
1942

20-
public function __construct($thothClient)
43+
public function __construct($thothClient, $httpConfig = [], $token = '')
2144
{
2245
$this->thothClient = $thothClient;
46+
$this->httpConfig = $httpConfig;
47+
$this->token = $token;
2348
}
2449

2550
public function getLinkedPublishers()
2651
{
27-
$publisherContexts = $this->thothClient->me()->getPublisherContexts() ?? [];
52+
$publisherContexts = $this->token
53+
? $this->getPublisherContextsWithPublishers()
54+
: $this->thothClient->me()->getPublisherContexts() ?? [];
2855

2956
return array_values(array_map(
3057
fn ($publisherContext) => $publisherContext['publisher'],
3158
array_filter($publisherContexts, fn ($publisherContext) => !empty($publisherContext['publisher']))
3259
));
3360
}
61+
62+
protected function getPublisherContextsWithPublishers()
63+
{
64+
$httpConfig = $this->httpConfig ?: ['base_uri' => Client::THOTH_BASE_URI];
65+
$response = (new Request($httpConfig))->runQuery(self::ME_WITH_PUBLISHERS_QUERY, null, $this->token);
66+
67+
return $response->getData()['me']['publisherContexts'] ?? [];
68+
}
3469
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/**
4+
* @file plugins/generic/thoth/classes/templateFilters/PublicationFormatTemplateFilter.inc.php
5+
*
6+
* Copyright (c) 2024-2026 Lepidus Tecnologia
7+
* Copyright (c) 2024-2026 Thoth
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class PublicationFormatTemplateFilter
11+
*
12+
* @ingroup plugins_generic_thoth
13+
*
14+
* @brief Injects Thoth accessibility fields into OMP publication format forms
15+
*/
16+
17+
class PublicationFormatTemplateFilter
18+
{
19+
private const FORMAT_FORM_ID = 'addPublicationFormatForm';
20+
21+
private $plugin;
22+
23+
public function __construct($plugin)
24+
{
25+
$this->plugin = $plugin;
26+
}
27+
28+
public function register($templateMgr)
29+
{
30+
$templateMgr->registerFilter('output', [$this, 'injectAccessibilityFields']);
31+
}
32+
33+
public function injectAccessibilityFields($output, $template)
34+
{
35+
if (
36+
strpos($output, self::FORMAT_FORM_ID) === false
37+
|| strpos($output, 'id="accessibilityStandard"') !== false
38+
) {
39+
return $output;
40+
}
41+
42+
$partial = $template->smarty->fetch(
43+
$this->plugin->getTemplateResource('publicationFormatAccessibilityFields.tpl')
44+
);
45+
46+
$insertionPosition = $this->getInsertionPosition($output);
47+
if ($insertionPosition === false) {
48+
return $output;
49+
}
50+
51+
return substr_replace($output, $partial, $insertionPosition, 0);
52+
}
53+
54+
private function getInsertionPosition($output)
55+
{
56+
$isbnTitle = __('grid.catalogEntry.isbn');
57+
$isbnTitlePosition = strpos($output, $isbnTitle);
58+
if ($isbnTitlePosition !== false) {
59+
$fieldsetEndPosition = strpos($output, '</fieldset>', $isbnTitlePosition);
60+
if ($fieldsetEndPosition !== false) {
61+
return $fieldsetEndPosition + strlen('</fieldset>');
62+
}
63+
}
64+
65+
return strpos($output, '<p><span class="formRequired">');
66+
}
67+
}

docs/images/plugin_settings.png

6.17 KB
Loading

0 commit comments

Comments
 (0)