Skip to content

Commit e79b66e

Browse files
committed
Simultaneously Displaying Multilingual Metadata on the Article Landing Page
1 parent 97f8c26 commit e79b66e

File tree

6 files changed

+643
-47
lines changed

6 files changed

+643
-47
lines changed

pages/preprint/PreprintHandler.php

+139
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,23 @@
2222
use APP\facades\Repo;
2323
use APP\handler\Handler;
2424
use APP\observers\events\UsageEvent;
25+
use APP\publication\Publication;
2526
use APP\security\authorization\OpsServerMustPublishPolicy;
2627
use APP\template\TemplateManager;
2728
use Firebase\JWT\JWT;
29+
use Illuminate\Support\Arr;
30+
use PKP\author\Author;
2831
use PKP\citation\CitationDAO;
2932
use PKP\config\Config;
3033
use PKP\core\Core;
3134
use PKP\core\PKPApplication;
3235
use PKP\db\DAORegistry;
36+
use PKP\facades\Locale;
3337
use PKP\orcid\OrcidManager;
3438
use PKP\plugins\Hook;
3539
use PKP\plugins\PluginRegistry;
3640
use PKP\security\authorization\ContextRequiredPolicy;
41+
use PKP\services\PKPSchemaService;
3742
use PKP\submission\Genre;
3843
use PKP\submission\GenreDAO;
3944
use PKP\submission\PKPSubmission;
@@ -302,6 +307,16 @@ public function view($args, $request)
302307
$templateMgr->addHeader('canonical', '<link rel="canonical" href="' . $url . '">');
303308
}
304309

310+
$templateMgr->assign('pubLocaleData', $this->getMultilingualMetadataOpts(
311+
$publication,
312+
$templateMgr->getTemplateVars('currentLocale'),
313+
$templateMgr->getTemplateVars('activeTheme')->getOption('showMultilingualMetadata') ?: [],
314+
));
315+
$templateMgr->registerPlugin('modifier', 'wrapData', fn (...$args) => $this->smartyWrapData($templateMgr, ...$args));
316+
$templateMgr->registerPlugin('modifier', 'useFilters', fn (...$args) => $this->smartyUseFilters($templateMgr, ...$args));
317+
$templateMgr->registerPlugin('modifier', 'getAuthorFullNames', $this->smartyGetAuthorFullNames(...));
318+
$templateMgr->registerPlugin('modifier', 'getAffiliationNamesWithRors', $this->smartyGetAffiliationNamesWithRors(...));
319+
305320
if (!Hook::call('PreprintHandler::view', [&$request, &$preprint, $publication])) {
306321
$templateMgr->display('frontend/pages/preprint.tpl');
307322
event(new UsageEvent(Application::ASSOC_TYPE_SUBMISSION, $context, $preprint));
@@ -424,4 +439,128 @@ public function userCanViewGalley($request)
424439
}
425440
return false;
426441
}
442+
443+
/**
444+
* Multilingual publication metadata for template:
445+
* showMultilingualMetadataOpts - Show metadata in other languages: title (+ subtitle), keywords, abstract, etc.
446+
*/
447+
protected function getMultilingualMetadataOpts(Publication $publication, string $currentUILocale, array $showMultilingualMetadataOpts): array
448+
{
449+
// Affiliation languages are not in multiligual props
450+
$authorsLocales = collect($publication->getData('authors'))
451+
->map(fn ($author): array => $this->getAuthorLocales($author))
452+
->flatten()
453+
->unique()
454+
->values()
455+
->toArray();
456+
$langNames = collect($publication->getLanguageNames() + Locale::getSubmissionLocaleDisplayNames($authorsLocales))
457+
->sortKeys();
458+
$langs = $langNames->keys();
459+
460+
return [
461+
'opts' => array_flip($showMultilingualMetadataOpts),
462+
'uiLocale' => $currentUILocale,
463+
'localeNames' => $langNames,
464+
'localeOrder' => collect($publication->getLocalePrecedence())
465+
->intersect($langs) /* remove locales not in publication's languages */
466+
->concat($langs)
467+
->unique()
468+
->values()
469+
->toArray(),
470+
'accessibility' => [
471+
'localeNames' => $langNames,
472+
'langAttrs' => $langNames->map(fn ($_, $l) => preg_replace(['/@.+$/', '/_/'], ['', '-'], $l))->toArray() /* remove @ and text after */,
473+
],
474+
];
475+
}
476+
477+
/**
478+
* Publication's multilingual data to array for js and page
479+
*/
480+
protected function smartyWrapData(TemplateManager $templateMgr, array $data, string $switcher, ?array $filters = null, ?string $separator = null): array
481+
{
482+
return [
483+
'switcher' => $switcher,
484+
'data' => collect($data)
485+
->map(
486+
fn ($value): string => collect(Arr::wrap($value))
487+
->when($filters, fn ($value) => $value->map(fn ($v) => $this->smartyUseFilters($templateMgr, $v, $filters)))
488+
->when($separator, fn ($value): string => $value->join($separator), fn ($value): string => $value->first())
489+
)
490+
->toArray(),
491+
'defaultLocale' => collect($templateMgr->getTemplateVars('pubLocaleData')['localeOrder'])
492+
->first(fn (string $locale) => isset($data[$locale])),
493+
];
494+
}
495+
496+
/**
497+
* Smarty template: Apply filters to given value
498+
*/
499+
protected function smartyUseFilters(TemplateManager $templateMgr, string $value, ?array $filters): string
500+
{
501+
if (!$filters) {
502+
return $value;
503+
}
504+
foreach ($filters as $filter) {
505+
$params = Arr::wrap($filter);
506+
$funcName = array_shift($params);
507+
if ($func = $templateMgr->registered_plugins['modifier'][$funcName][0] ?? null) {
508+
$value = $func($value, ...$params);
509+
} else {
510+
error_log("{$funcName} : No such modifier in template registered plugins.");
511+
}
512+
}
513+
return $value;
514+
}
515+
516+
/**
517+
* Smarty template: Get author's full names to multilingual array including all multilingual and affiliation languages as default localized name
518+
*/
519+
protected function smartyGetAuthorFullNames(Author $author): array
520+
{
521+
return collect($this->getAuthorLocales($author))
522+
->mapWithKeys(fn (string $locale) => [$locale => $author->getFullName(preferredLocale: $locale)])
523+
->toArray();
524+
}
525+
526+
/**
527+
* Smarty template: Get authors' affiliations with rors
528+
*/
529+
protected function smartyGetAffiliationNamesWithRors(Author $author): array
530+
{
531+
$affiliations = collect($author->getAffiliations());
532+
533+
return collect($this->getAuthorLocales($author))
534+
->flip()
535+
->map(
536+
fn ($_, string $locale) => $affiliations
537+
->map(fn ($affiliation): array => [
538+
'name' => $affiliation->getAffiliationName($locale),
539+
'ror' => $affiliation->getRor(),
540+
])
541+
->filter(fn (array $nameRor) => $nameRor['name'])
542+
->toArray()
543+
)
544+
->filter()
545+
->toArray();
546+
}
547+
548+
/**
549+
* Aux for smarty template functions: Get author's locales from multilingual props and affiliations
550+
*/
551+
protected function getAuthorLocales(Author $author): array
552+
{
553+
$multilingualLocales = collect(app()->get('schema')->getMultilingualProps(PKPSchemaService::SCHEMA_AUTHOR))
554+
->map(fn (string $prop): array => array_keys($author->getData($prop) ?? []));
555+
$affiliationLocales = collect($author->getAffiliations())
556+
->flatten()
557+
->map(fn ($affiliation): array => array_keys($affiliation->getData('name') ?? []));
558+
559+
return $multilingualLocales
560+
->concat($affiliationLocales)
561+
->flatten()
562+
->unique()
563+
->values()
564+
->toArray();
565+
}
427566
}

plugins/themes/default/DefaultThemePlugin.php

+24
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ public function init()
125125
'default' => 'none',
126126
]);
127127

128+
$this->addOption('showMultilingualMetadata', 'FieldOptions', [
129+
'label' => __('plugins.themes.default.option.metadata.label'),
130+
'description' => __('plugins.themes.default.option.metadata.description'),
131+
'options' => [
132+
[
133+
'value' => 'title',
134+
'label' => __('submission.title'),
135+
],
136+
[
137+
'value' => 'keywords',
138+
'label' => __('common.keywords'),
139+
],
140+
[
141+
'value' => 'abstract',
142+
'label' => __('common.abstract'),
143+
],
144+
[
145+
'value' => 'author',
146+
'label' => __('default.groups.name.author'),
147+
],
148+
],
149+
'default' => [],
150+
]);
151+
128152
// Load primary stylesheet
129153
$this->addStyle('stylesheet', 'styles/index.less');
130154

0 commit comments

Comments
 (0)