Skip to content

Commit 78373f3

Browse files
Merge pull request #62 from lepidus/stable-3_4_0
Add publication accessibility metadata (OMP 3.4.0)
2 parents 510a949 + 9324ba6 commit 78373f3

18 files changed

Lines changed: 883 additions & 26 deletions

ThothPlugin.inc.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import('plugins.generic.thoth.classes.components.forms.config.CatalogEntryFormConfig');
2626
import('plugins.generic.thoth.classes.components.forms.config.PublishFormConfig');
2727
import('plugins.generic.thoth.classes.components.forms.config.ContributorFormConfig');
28+
import('plugins.generic.thoth.classes.formModifiers.PublicationFormatFormModifier');
29+
import('plugins.generic.thoth.classes.templateFilters.PublicationFormatTemplateFilter');
2830
import('plugins.generic.thoth.classes.templateFilters.ThothSectionTemplateFilter');
2931
import('plugins.generic.thoth.classes.listeners.PublicationEditListener');
3032
import('plugins.generic.thoth.classes.listeners.PublicationPublishListener');
@@ -40,6 +42,7 @@ public function register($category, $path, $mainContextId = null)
4042
if ($success && $this->getEnabled()) {
4143
$this->addToSchema();
4244
$this->addFormConfig();
45+
$this->addFormModifiers();
4346
$this->addListeners();
4447
$this->addEndpoints();
4548
HookRegistry::register('TemplateManager::display', [$this, 'addTemplateFilters']);
@@ -168,6 +171,19 @@ public function addFormConfig()
168171
HookRegistry::register('Form::config::before', [$contributorFormConfig, 'addConfig']);
169172
}
170173

174+
public function addFormModifiers()
175+
{
176+
$publicationFormatFormModifier = new PublicationFormatFormModifier($this);
177+
HookRegistry::register(
178+
'publicationformatdao::getAdditionalFieldNames',
179+
[$publicationFormatFormModifier, 'addAccessibilityFieldNames']
180+
);
181+
HookRegistry::register('publicationformatform::display', [$publicationFormatFormModifier, 'handleFormDisplay']);
182+
HookRegistry::register('publicationformatform::readuservars', [$publicationFormatFormModifier, 'handleFormReadUserVars']);
183+
HookRegistry::register('publicationformatform::validate', [$publicationFormatFormModifier, 'handleFormValidate']);
184+
HookRegistry::register('publicationformatform::execute', [$publicationFormatFormModifier, 'handleFormExecute']);
185+
}
186+
171187
public function addListeners()
172188
{
173189
$publicationPublishListener = new PublicationPublishListener();

classes/container/providers/ThothRepositoryProvider.inc.php

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

9191
$container->set('accountRepository', function ($container) {
92-
return new ThothAccountRepository($container->get('client'));
92+
$config = $container->get('config');
93+
$httpConfig = [];
94+
if ($config['customThothApi'] && $config['customThothApiUrl']) {
95+
$httpConfig['base_uri'] = trim($config['customThothApiUrl']);
96+
}
97+
98+
return new ThothAccountRepository($container->get('client'), $httpConfig, $config['token']);
9399
});
94100

95101
$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: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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, $dao, &$fieldNames)
57+
{
58+
$fieldNames = array_values(array_unique(array_merge($fieldNames, self::ACCESSIBILITY_FIELDS)));
59+
60+
return false;
61+
}
62+
63+
public function handleFormReadUserVars($hookName, $args)
64+
{
65+
$vars = & $args[1];
66+
$vars = array_unique(array_merge($vars, self::ACCESSIBILITY_FIELDS));
67+
68+
return false;
69+
}
70+
71+
public function handleFormValidate($hookName, $args)
72+
{
73+
$form = $args[0];
74+
$reportUrl = trim((string) $form->getData('accessibilityReportUrl'));
75+
76+
if ($reportUrl !== '' && filter_var($reportUrl, FILTER_VALIDATE_URL) === false) {
77+
$form->addError(
78+
'accessibilityReportUrl',
79+
__('plugins.generic.thoth.publicationFormat.accessibilityReportUrl.invalid')
80+
);
81+
}
82+
83+
return false;
84+
}
85+
86+
public function handleFormExecute($hookName, $args)
87+
{
88+
$form = $args[0];
89+
$publicationFormat = $form->getPublicationFormat();
90+
91+
if (!$publicationFormat) {
92+
return false;
93+
}
94+
95+
foreach (self::ACCESSIBILITY_FIELDS as $fieldName) {
96+
$publicationFormat->setData($fieldName, $this->normalizeOptionalValue($form->getData($fieldName)));
97+
}
98+
99+
return false;
100+
}
101+
102+
private function normalizeOptionalValue($value)
103+
{
104+
$value = trim((string) $value);
105+
return $value === '' ? null : $value;
106+
}
107+
108+
private function getAccessibilityStandardOptions()
109+
{
110+
return [
111+
'' => 'common.none',
112+
'WCAG21AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag21aa',
113+
'WCAG21AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag21aaa',
114+
'WCAG22AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag22aa',
115+
'WCAG22AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.wcag22aaa',
116+
'EPUB_A11Y10AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y10aa',
117+
'EPUB_A11Y10AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y10aaa',
118+
'EPUB_A11Y11AA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y11aa',
119+
'EPUB_A11Y11AAA' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.epubA11y11aaa',
120+
'PDF_UA1' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.pdfUa1',
121+
'PDF_UA2' => 'plugins.generic.thoth.publicationFormat.accessibilityStandard.pdfUa2',
122+
];
123+
}
124+
125+
private function getAccessibilityExceptionOptions()
126+
{
127+
return [
128+
'' => 'common.none',
129+
'MICRO_ENTERPRISES' => 'plugins.generic.thoth.publicationFormat.accessibilityException.microEnterprises',
130+
'DISPROPORTIONATE_BURDEN' => 'plugins.generic.thoth.publicationFormat.accessibilityException.disproportionateBurden',
131+
'FUNDAMENTAL_ALTERATION' => 'plugins.generic.thoth.publicationFormat.accessibilityException.fundamentalAlteration',
132+
];
133+
}
134+
}

classes/repositories/ThothAccountRepository.inc.php

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

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

21-
public function __construct($thothClient)
44+
public function __construct($thothClient, $httpConfig = [], $token = '')
2245
{
2346
$this->thothClient = $thothClient;
47+
$this->httpConfig = $httpConfig;
48+
$this->token = $token;
2449
}
2550

2651
public function getLinkedPublishers()
2752
{
28-
$publisherContexts = $this->thothClient->me()->getPublisherContexts() ?? [];
53+
$publisherContexts = $this->token
54+
? $this->getPublisherContextsWithPublishers()
55+
: $this->thothClient->me()->getPublisherContexts() ?? [];
2956

3057
return array_values(array_map(
3158
fn ($publisherContext) => $publisherContext['publisher'],
3259
array_filter($publisherContexts, fn ($publisherContext) => !empty($publisherContext['publisher']))
3360
));
3461
}
62+
63+
protected function getPublisherContextsWithPublishers()
64+
{
65+
$httpConfig = $this->httpConfig ?: ['base_uri' => Client::THOTH_BASE_URI];
66+
$response = (new Request($httpConfig))->runQuery(self::ME_WITH_PUBLISHERS_QUERY, null, $this->token);
67+
68+
return $response->getData()['me']['publisherContexts'] ?? [];
69+
}
3570
}
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)