|
22 | 22 | use APP\facades\Repo;
|
23 | 23 | use APP\handler\Handler;
|
24 | 24 | use APP\observers\events\UsageEvent;
|
| 25 | +use APP\publication\Publication; |
25 | 26 | use APP\security\authorization\OpsServerMustPublishPolicy;
|
26 | 27 | use APP\template\TemplateManager;
|
27 | 28 | use Firebase\JWT\JWT;
|
| 29 | +use Illuminate\Support\Arr; |
| 30 | +use PKP\author\Author; |
28 | 31 | use PKP\citation\CitationDAO;
|
29 | 32 | use PKP\config\Config;
|
30 | 33 | use PKP\core\Core;
|
31 | 34 | use PKP\core\PKPApplication;
|
32 | 35 | use PKP\db\DAORegistry;
|
| 36 | +use PKP\facades\Locale; |
33 | 37 | use PKP\orcid\OrcidManager;
|
34 | 38 | use PKP\plugins\Hook;
|
35 | 39 | use PKP\plugins\PluginRegistry;
|
36 | 40 | use PKP\security\authorization\ContextRequiredPolicy;
|
| 41 | +use PKP\services\PKPSchemaService; |
37 | 42 | use PKP\submission\Genre;
|
38 | 43 | use PKP\submission\GenreDAO;
|
39 | 44 | use PKP\submission\PKPSubmission;
|
@@ -302,6 +307,16 @@ public function view($args, $request)
|
302 | 307 | $templateMgr->addHeader('canonical', '<link rel="canonical" href="' . $url . '">');
|
303 | 308 | }
|
304 | 309 |
|
| 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 | + |
305 | 320 | if (!Hook::call('PreprintHandler::view', [&$request, &$preprint, $publication])) {
|
306 | 321 | $templateMgr->display('frontend/pages/preprint.tpl');
|
307 | 322 | event(new UsageEvent(Application::ASSOC_TYPE_SUBMISSION, $context, $preprint));
|
@@ -424,4 +439,128 @@ public function userCanViewGalley($request)
|
424 | 439 | }
|
425 | 440 | return false;
|
426 | 441 | }
|
| 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 | + } |
427 | 566 | }
|
0 commit comments