23 define(
'SMARTY_DIR',
Core::getBaseDir() .
'/lib/pkp/lib/vendor/smarty/smarty/libs/');
25 require_once(
'./lib/pkp/lib/vendor/smarty/smarty/libs/plugins/modifier.escape.php');
27 define(
'CACHEABILITY_NO_CACHE',
'no-cache');
28 define(
'CACHEABILITY_NO_STORE',
'no-store');
29 define(
'CACHEABILITY_PUBLIC',
'public');
30 define(
'CACHEABILITY_MUST_REVALIDATE',
'must-revalidate');
31 define(
'CACHEABILITY_PROXY_REVALIDATE',
'proxy-revalidate');
33 define(
'STYLE_SEQUENCE_CORE', 0);
34 define(
'STYLE_SEQUENCE_NORMAL', 10);
35 define(
'STYLE_SEQUENCE_LATE', 15);
36 define(
'STYLE_SEQUENCE_LAST', 20);
38 define(
'CDN_JQUERY_VERSION',
'3.3.1');
39 define(
'CDN_JQUERY_UI_VERSION',
'1.12.0');
41 define(
'CSS_FILENAME_SUFFIX',
'css');
43 define(
'PAGE_WIDTH_NARROW',
'narrow');
44 define(
'PAGE_WIDTH_NORMAL',
'normal');
45 define(
'PAGE_WIDTH_WIDE',
'wide');
46 define(
'PAGE_WIDTH_FULL',
'full');
48 import(
'lib.pkp.classes.template.PKPTemplateResource');
52 private $_styleSheets = [];
55 private $_javaScripts = [];
58 private $_htmlHeaders = [];
61 private $_constants = [];
64 private $_localeKeys = [];
70 private $_cacheability;
83 parent::__construct();
89 $this->compile_dir = $cachePath . DIRECTORY_SEPARATOR .
't_compile';
90 $this->config_dir = $cachePath . DIRECTORY_SEPARATOR .
't_config';
91 $this->cache_dir = $cachePath . DIRECTORY_SEPARATOR .
't_cache';
93 $this->_cacheability = CACHEABILITY_NO_STORE;
96 $this->registerResource(
'core',
new PKPTemplateResource($coreTemplateDir =
'lib' . DIRECTORY_SEPARATOR .
'pkp' . DIRECTORY_SEPARATOR .
'templates'));
98 $this->default_resource_type =
'app';
100 $this->error_reporting = E_ALL & ~E_NOTICE;
108 assert(is_a($request,
'PKPRequest'));
109 $this->_request = $request;
113 $router = $request->getRouter();
114 assert(is_a($router,
'PKPRouter'));
117 $currentContext = $request->getContext();
121 'baseUrl' => $request->getBaseUrl(),
122 'dateFormatTrunc' =>
Config::getVar(
'general',
'date_format_trunc'),
123 'dateFormatShort' =>
Config::getVar(
'general',
'date_format_short'),
124 'dateFormatLong' =>
Config::getVar(
'general',
'date_format_long'),
125 'datetimeFormatShort' =>
Config::getVar(
'general',
'datetime_format_short'),
126 'datetimeFormatLong' =>
Config::getVar(
'general',
'datetime_format_long'),
128 'currentContext' => $currentContext,
129 'currentLocale' => $locale,
131 'applicationName' => __($application->getNameKey()),
135 if ($currentContext) {
136 $favicon = $currentContext->getLocalizedFavicon();
137 if (!empty($favicon)) {
139 $faviconDir = $request->getBaseUrl() .
'/' . $publicFileManager->getContextFilesPath($currentContext->getId());
140 $this->
addHeader(
'favicon',
'<link rel="icon" href="' . $faviconDir .
'/' . $favicon[
'uploadName'] .
'">');
146 $contextOrSite = $currentContext ? $currentContext : $request->getSite();
148 foreach ($allThemes as $theme) {
149 if ($contextOrSite->getData(
'themePluginPath') === $theme->getDirName()) {
150 $activeTheme = $theme;
154 $this->assign([
'activeTheme' => $activeTheme]);
157 if (is_a($router,
'PKPPageRouter')) {
159 'requestedPage' => $router->getRequestedPage($request),
160 'requestedOp' => $router->getRequestedOp($request),
164 if ($currentContext) {
165 $contextStyleSheet = $currentContext->getData(
'styleSheet');
166 if ($contextStyleSheet) {
167 import(
'classes.file.PublicFileManager');
171 $request->getBaseUrl() .
'/' . $publicFileManager->getContextFilesPath($currentContext->getId()) .
'/' . $contextStyleSheet[
'uploadName'],
172 [
'priority' => STYLE_SEQUENCE_LATE]
183 'contexts' => [
'frontend-user-register',
'frontend-user-registerUser'],
190 if (($request->getRequestedPage()==
'' || $request->getRequestedPage() ==
'index') && $currentContext && $currentContext->getLocalizedData(
'searchDescription')) {
191 $this->
addHeader(
'searchDescription',
'<meta name="description" content="' . $currentContext->getLocalizedData(
'searchDescription') .
'">');
196 '<meta name="generator" content="' . __($application->getNameKey()) .
' ' . $application->getCurrentVersion()->getVersionString(
false) .
'">',
198 'contexts' => [
'frontend',
'backend'],
202 if ($currentContext) {
203 $customHeaders = $currentContext->getLocalizedData(
'customHeaders');
204 if (!empty($customHeaders)) {
205 $this->
addHeader(
'customHeaders', $customHeaders);
210 if ($currentContext && !$currentContext->getEnabled()) {
213 '<meta name="robots" content="noindex,nofollow">',
215 'contexts' => [
'frontend',
'backend'],
221 import(
'classes.core.Services');
230 $this->registerPlugin(
'modifier',
'translate',
'AppLocale::translate');
231 $this->registerPlugin(
'modifier',
'strip_unsafe_html',
'PKPString::stripUnsafeHtml');
232 $this->registerPlugin(
'modifier',
'String_substr',
'PKPString::substr');
233 $this->registerPlugin(
'modifier',
'dateformatPHP2JQueryDatepicker',
'PKPString::dateformatPHP2JQueryDatepicker');
234 $this->registerPlugin(
'modifier',
'to_array', [$this,
'smartyToArray']);
235 $this->registerPlugin(
'modifier',
'compare', [$this,
'smartyCompare']);
236 $this->registerPlugin(
'modifier',
'concat', [$this,
'smartyConcat']);
237 $this->registerPlugin(
'modifier',
'strtotime', [$this,
'smartyStrtotime']);
238 $this->registerPlugin(
'modifier',
'explode', [$this,
'smartyExplode']);
239 $this->registerPlugin(
'modifier',
'escape', [$this,
'smartyEscape']);
240 $this->registerPlugin(
'function',
'csrf', [$this,
'smartyCSRF']);
241 $this->registerPlugin(
'function',
'translate', [$this,
'smartyTranslate']);
242 $this->registerPlugin(
'function',
'null_link_action', [$this,
'smartyNullLinkAction']);
243 $this->registerPlugin(
'function',
'help', [$this,
'smartyHelp']);
244 $this->registerPlugin(
'function',
'flush', [$this,
'smartyFlush']);
245 $this->registerPlugin(
'function',
'call_hook', [$this,
'smartyCallHook']);
246 $this->registerPlugin(
'function',
'html_options_translate', [$this,
'smartyHtmlOptionsTranslate']);
247 $this->registerPlugin(
'block',
'iterate', [$this,
'smartyIterate']);
248 $this->registerPlugin(
'function',
'page_links', [$this,
'smartyPageLinks']);
249 $this->registerPlugin(
'function',
'page_info', [$this,
'smartyPageInfo']);
250 $this->registerPlugin(
'function',
'pluck_files', [$this,
'smartyPluckFiles']);
252 $this->registerPlugin(
'function',
'title', [$this,
'smartyTitle']);
253 $this->registerPlugin(
'function',
'url', [$this,
'smartyUrl']);
256 $this->registerPlugin(
'function',
'load_stylesheet', [$this,
'smartyLoadStylesheet']);
257 $this->registerPlugin(
'function',
'load_script', [$this,
'smartyLoadScript']);
258 $this->registerPlugin(
'function',
'load_header', [$this,
'smartyLoadHeader']);
261 $this->registerPlugin(
'function',
'load_menu', [$this,
'smartyLoadNavigationMenuArea']);
265 $this->registerPlugin(
'block',
'fbvFormSection', [$fbv,
'smartyFBVFormSection']);
266 $this->registerPlugin(
'block',
'fbvFormArea', [$fbv,
'smartyFBVFormArea']);
267 $this->registerPlugin(
'function',
'fbvFormButtons', [$fbv,
'smartyFBVFormButtons']);
268 $this->registerPlugin(
'function',
'fbvElement', [$fbv,
'smartyFBVElement']);
269 $this->registerPlugin(
'function',
'fieldLabel', [$fbv,
'smartyFieldLabel']);
270 $this->assign(
'fbvStyles', $fbv->getStyles());
273 $this->registerPlugin(
'function',
'load_url_in_el', [$this,
'smartyLoadUrlInEl']);
274 $this->registerPlugin(
'function',
'load_url_in_div', [$this,
'smartyLoadUrlInDiv']);
283 import(
'lib.pkp.classes.controllers.listbuilder.ListbuilderHandler');
285 'LISTBUILDER_SOURCE_TYPE_TEXT',
286 'LISTBUILDER_SOURCE_TYPE_SELECT',
287 'LISTBUILDER_OPTGROUP_LABEL',
294 if (!defined(
'SESSION_DISABLE_INIT')) {
300 'siteTitle' => $request->getSite()->getLocalizedData(
'title'),
303 $user = $request->getUser();
306 'currentUser' => $user,
311 'loggedInUsername' => $user->getUserName(),
318 if ($currentContext) {
319 $this->assign(
'hasSidebar', !empty($currentContext->getData(
'sidebar')));
321 $this->assign(
'hasSidebar', !empty($request->getSite()->getData(
'sidebar')));
337 $this->_cacheability = $cacheability;
350 public function compileLess($name, $lessFile, $args = []) {
351 $less =
new Less_Parser([
352 'relativeUrls' =>
false,
356 $request = $this->_request;
359 HookRegistry::call(
'PageHandler::compileLess', [&$less, &$lessFile, &$args, $name, $request]);
362 $less->parseFile($lessFile);
365 if (isset($args[
'addLess']) && is_array($args[
'addLess'])) {
366 foreach ($args[
'addLess'] as $addless) {
367 $less->parseFile($addless);
372 if (isset($args[
'addLessVariables'])) {
373 foreach ((array) $args[
'addLessVariables'] as $addlessVariables) {
374 $less->parse($addlessVariables);
379 $baseUrl = !empty($args[
'baseUrl']) ? $args[
'baseUrl'] : $request->getBaseUrl(
true);
380 $less->parse(
"@baseUrl: '$baseUrl';");
382 return $less->getCSS();
392 public function cacheLess($path, $styles) {
393 if (file_put_contents($path, $styles) ===
false) {
394 error_log(
"Unable to write \"$path\".");
409 $context = $this->_request->getContext();
410 $contextId = is_a($context,
'Context') ? $context->getId() : 0;
411 return $cacheDirectory . DIRECTORY_SEPARATOR . $contextId .
'-' . $name .
'.css';
432 'priority' => STYLE_SEQUENCE_NORMAL,
433 'contexts' => [
'frontend'],
439 $args[
'contexts'] = (array) $args[
'contexts'];
440 foreach($args[
'contexts'] as $context) {
441 $this->_styleSheets[$context][$args[
'priority']][$name] = [
443 'inline' => $args[
'inline'],
466 'priority' => STYLE_SEQUENCE_NORMAL,
467 'contexts' => [
'frontend'],
473 $args[
'contexts'] = (array) $args[
'contexts'];
474 foreach($args[
'contexts'] as $context) {
475 $this->_javaScripts[$context][$args[
'priority']][$name] = [
477 'inline' => $args[
'inline'],
493 function addHeader($name, $header, $args = []) {
497 'priority' => STYLE_SEQUENCE_NORMAL,
498 'contexts' => [
'frontend'],
503 $args[
'contexts'] = (array) $args[
'contexts'];
504 foreach($args[
'contexts'] as $context) {
505 $this->_htmlHeaders[$context][$args[
'priority']][$name] = [
517 foreach ($names as $name) {
518 $this->_constants[$name] = constant($name);
528 foreach ($keys as $key) {
529 if (!array_key_exists($key, $this->_localeKeys)) {
530 $this->_localeKeys[$key] = __($key);
542 return array_key_exists($key, $this->_state)
543 ? $this->_state[$key]
553 $this->_state = array_merge($this->_state, $data);
560 $baseUrl = $this->_request->getBaseUrl();
565 'priority' => STYLE_SEQUENCE_CORE,
566 'contexts' =>
'backend',
573 $baseUrl .
'/lib/pkp/js/lib/jquery/plugins/validate/jquery.validate.min.js',
576 $jqvLocalePath =
'lib/pkp/js/lib/jquery/plugins/validate/localization/messages_';
577 foreach ($localeChecks as $localeCheck) {
578 if (file_exists($jqvLocalePath . $localeCheck .
'.js')) {
579 $this->
addJavaScript(
'jqueryValidateLocale', $baseUrl .
'/' . $jqvLocalePath . $localeCheck .
'.js', $args);
585 $baseUrl .
'/lib/pkp/lib/vendor/moxiecode/plupload/js/plupload.full.min.js',
590 $baseUrl .
'/lib/pkp/lib/vendor/moxiecode/plupload/js/jquery.ui.plupload/jquery.ui.plupload.js',
593 $plLocalePath =
'lib/pkp/lib/vendor/moxiecode/plupload/js/i18n/';
594 foreach ($localeChecks as $localeCheck) {
595 if (file_exists($plLocalePath . $localeCheck .
'.js')) {
596 $this->
addJavaScript(
'plUploadLocale', $baseUrl .
'/' . $plLocalePath . $localeCheck .
'.js', $args);
603 $baseUrl .
'/js/build.js',
605 'priority' => STYLE_SEQUENCE_LATE,
606 'contexts' => [
'backend']
614 $baseUrl .
'/js/pkp.min.js',
616 'priority' => STYLE_SEQUENCE_CORE,
617 'contexts' => [
'backend']
624 $minifiedScripts = array_filter(array_map(
'trim', file(
'registry/minifiedScripts.txt')),
function($s) {
625 return strlen($s) && $s[0] !=
'#';
627 foreach ($minifiedScripts as $key => $script) {
628 $this->
addJavaScript(
'pkpLib' . $key,
"$baseUrl/$script", $args);
644 $context = $this->_request->getContext();
647 $output =
'$.pkp = $.pkp || {};';
650 import(
'lib.pkp.classes.security.Role');
656 'baseUrl' => $this->_request->getBaseUrl(),
657 'contextPath' => isset($context) ? $context->getPath() :
'',
658 'apiBasePath' =>
'/api/v1',
659 'pathInfoEnabled' =>
Config::getVar(
'general',
'disable_path_info') ? false :
true,
660 'restfulUrlsEnabled' =>
Config::getVar(
'general',
'restful_urls') ? true :
false,
661 'tinyMceContentCSS' => $this->_request->getBaseUrl() .
'/plugins/generic/tinymce/styles/content.css',
662 'tinyMceContentFont' =>
Config::getVar(
'general',
'enable_cdn') ? $this->_request->getBaseUrl() .
'/plugins/generic/tinymce/styles/content-font.css' :
'',
665 $output .=
'$.pkp.app = ' . json_encode($app_data) .
';';
668 $output .=
'$.pkp.cons = ' . json_encode($this->_constants) .
';';
671 $output .=
'$.pkp.plugins = {};';
677 'priority' => STYLE_SEQUENCE_CORE,
678 'contexts' =>
'backend',
690 $dispatcher = $request->getDispatcher();
691 $router = $request->getRouter();
694 $this->assign(
'pageComponent',
'Page');
699 'UPLOAD_MAX_FILESIZE',
700 'WORKFLOW_STAGE_ID_PUBLISHED',
701 'WORKFLOW_STAGE_ID_SUBMISSION',
702 'WORKFLOW_STAGE_ID_INTERNAL_REVIEW',
703 'WORKFLOW_STAGE_ID_EXTERNAL_REVIEW',
704 'WORKFLOW_STAGE_ID_EDITING',
705 'WORKFLOW_STAGE_ID_PRODUCTION',
706 'INSERT_TAG_VARIABLE_TYPE_PLAIN_TEXT',
708 'ROLE_ID_SITE_ADMIN',
713 'ROLE_ID_SUB_EDITOR',
714 'ROLE_ID_SUBSCRIPTION_MANAGER',
720 'common.clearSearch',
722 'common.commaListSeparator',
729 'common.filterRemove',
732 'common.noItemsFound',
738 'common.pagination.goToPage',
739 'common.pagination.label',
740 'common.pagination.next',
741 'common.pagination.previous',
747 'common.selectWithName',
748 'common.unknownError',
752 'common.viewWithName',
754 'form.dataHasChanged',
760 'form.multilingualLabel',
761 'form.multilingualProgress',
769 $min =
Config::getVar(
'general',
'enable_minified') ?
'.min' :
'';
771 $jquery =
'//ajax.googleapis.com/ajax/libs/jquery/' . CDN_JQUERY_VERSION .
'/jquery' . $min .
'.js';
772 $jqueryUI =
'//ajax.googleapis.com/ajax/libs/jqueryui/' . CDN_JQUERY_UI_VERSION .
'/jquery-ui' . $min .
'.js';
774 $jquery = $request->getBaseUrl() .
'/lib/pkp/lib/vendor/components/jquery/jquery' . $min .
'.js';
775 $jqueryUI = $request->getBaseUrl() .
'/lib/pkp/lib/vendor/components/jqueryui/jquery-ui' . $min .
'.js';
781 'priority' => STYLE_SEQUENCE_CORE,
782 'contexts' =>
'backend',
789 'priority' => STYLE_SEQUENCE_CORE,
790 'contexts' =>
'backend',
800 '//fonts.googleapis.com/css?family=Noto+Sans:400,400italic,700,700italic',
802 'priority' => STYLE_SEQUENCE_CORE,
803 'contexts' =>
'backend',
814 $url =
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css';
816 $url = $request->getBaseUrl() .
'/lib/pkp/styles/fontawesome/fontawesome.css';
822 'priority' => STYLE_SEQUENCE_CORE,
823 'contexts' =>
'backend',
830 $request->getBaseUrl() .
'/styles/build.css',
832 'priority' => STYLE_SEQUENCE_CORE,
833 'contexts' =>
'backend',
840 $dispatcher->url($request, ROUTE_COMPONENT,
null,
'page.PageHandler',
'css'),
842 'priority' => STYLE_SEQUENCE_CORE,
843 'contexts' =>
'backend',
851 $request->getBaseUrl() .
'/' . $localeStyleSheet,
853 'contexts' => [
'backend'],
867 if (
Config::getVar(
'general',
'installed') && !defined(
'SESSION_DISABLE_INIT')) {
869 if ($request->getUser()) {
873 import(
'lib.pkp.controllers.grid.notifications.TaskNotificationsGridHandler');
874 $unreadTasksCount = (int) $notificationDao->getNotificationCount(
false, $request->getUser()->getId(),
null, NOTIFICATION_LEVEL_TASK);
877 $tasksUrl = $request->getDispatcher()->url($request, ROUTE_COMPONENT,
null,
'page.PageHandler',
'tasks');
881 $notifications = $notificationDao->getByUserId($request->getUser()->getId(), NOTIFICATION_LEVEL_TRIVIAL);
887 $args = [
'userId' => $request->getUser()->getId()];
889 $availableContexts =
Services::get(
'context')->getManySummary($args);
890 if ($request->getContext()) {
891 $availableContexts = array_filter($availableContexts,
function($context) use ($request) {
892 return $context->id !== $request->getContext()->getId();
895 $requestedPage = $router->getRequestedPage($request);
896 foreach ($availableContexts as $availableContext) {
898 if ($requestedPage !==
'admin' && in_array(ROLE_ID_SITE_ADMIN, $this->
get_template_vars(
'userRoles'))) {
899 $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath, $request->getRequestedPage(), $request->getRequestedOp(), $request->getRequestedArgs($request));
901 $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath,
'submissions');
906 $userRoles = (array) $router->getHandler()->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
910 if ($request->getContext()) {
911 if (count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR, ROLE_ID_ASSISTANT, ROLE_ID_REVIEWER, ROLE_ID_AUTHOR], $userRoles))) {
912 $menu[
'submissions'] = [
913 'name' => __(
'navigation.submissions'),
914 'url' => $router->url($request,
null,
'submissions'),
915 'isCurrent' => $router->getRequestedPage($request) ===
'submissions',
917 } elseif (count($userRoles) === 1 && in_array(ROLE_ID_READER, $userRoles)) {
920 'name' => __(
'author.submit'),
921 'url' => $router->url($request,
null,
'submission',
'wizard'),
922 'isCurrent' => $router->getRequestedPage($request) ===
'submission',
926 if (count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR], $userRoles))) {
927 $menu[
'statistics'] = [
928 'name' => __(
'navigation.tools.statistics'),
931 'name' => __(
'common.publications'),
932 'url' => $router->url($request,
null,
'stats',
'publications',
'publications'),
933 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'publications',
936 'name' => __(
'stats.editorialActivity'),
937 'url' => $router->url($request,
null,
'stats',
'editorial',
'editorial'),
938 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'editorial',
941 'name' => __(
'manager.users'),
942 'url' => $router->url($request,
null,
'stats',
'users',
'users'),
943 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'users',
949 if (in_array(ROLE_ID_MANAGER, $userRoles)) {
950 if ($request->getContext()->getData(
'enableAnnouncements')) {
951 $menu[
'announcements'] = [
952 'name' => __(
'announcement.announcements'),
953 'url' => $router->url($request,
null,
'management',
'settings',
'announcements'),
954 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'announcements', (array) $router->getRequestedArgs($request)),
957 $menu[
'statistics'][
'submenu'] += [
959 'name' => __(
'manager.statistics.reports'),
960 'url' => $router->url($request,
null,
'management',
'tools',
null,
null,
'statistics'),
961 'isCurrent' => $router->getRequestedPage($request) ===
'management' && $router->getRequestedAnchor($request) ===
'statistics',
964 $menu[
'settings'] = [
965 'name' => __(
'navigation.settings'),
968 'name' => __(
'context.context'),
969 'url' => $router->url($request,
null,
'management',
'settings',
'context'),
970 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'context', (array) $router->getRequestedArgs($request)),
973 'name' => __(
'manager.website'),
974 'url' => $router->url($request,
null,
'management',
'settings',
'website'),
975 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'website', (array) $router->getRequestedArgs($request)),
978 'name' => __(
'manager.workflow'),
979 'url' => $router->url($request,
null,
'management',
'settings',
'workflow'),
980 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'workflow', (array) $router->getRequestedArgs($request)),
983 'name' => __(
'manager.distribution'),
984 'url' => $router->url($request,
null,
'management',
'settings',
'distribution'),
985 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'distribution', (array) $router->getRequestedArgs($request)),
988 'name' => __(
'navigation.access'),
989 'url' => $router->url($request,
null,
'management',
'settings',
'access'),
990 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'access', (array) $router->getRequestedArgs($request)),
995 'name' => __(
'navigation.tools'),
996 'url' => $router->url($request,
null,
'management',
'tools'),
997 'isCurrent' => $router->getRequestedPage($request) ===
'management' && $router->getRequestedOp($request) ===
'tools',
1001 if (in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
1003 'name' => __(
'navigation.admin'),
1004 'url' => $router->url($request,
'index',
'admin'),
1005 'isCurrent' => $router->getRequestedPage($request) ===
'admin',
1012 'tasksUrl' => $tasksUrl,
1013 'unreadTasksCount' => $unreadTasksCount,
1017 'availableContexts' => $availableContexts,
1018 'hasSystemNotifications' => $notifications->getCount() > 0,
1029 function fetch($template =
null, $cache_id =
null, $compile_id =
null, $parent =
null) {
1032 if (!$compile_id) $compile_id = $this->
getCompileId($template);
1036 if (
HookRegistry::call(
'TemplateManager::fetch', [$this, $template, $cache_id, $compile_id, &$result]))
return $result;
1038 return parent::fetch($template, $cache_id, $compile_id, $parent);
1048 function fetchAjax($id, $url, $element =
'div') {
1067 $context = $this->_request->getContext();
1068 if (is_a($context,
'Context')) {
1069 $resourceName .= $context->getData(
'themePluginPath');
1073 return sha1($resourceName);
1082 function fetchJson($template, $status =
true) {
1083 import(
'lib.pkp.classes.core.JSONMessage');
1090 function display($template =
null, $cache_id =
null, $compile_id =
null, $parent =
null) {
1094 if (!empty($this->_constants)) {
1095 $output .=
'pkp.const = ' . json_encode($this->_constants) .
';';
1097 if (!empty($this->_localeKeys)) {
1098 $output .=
'pkp.localeKeys = ' . json_encode($this->_localeKeys) .
';';
1103 $user = $this->_request->getUser();
1106 $userGroupsResult = $userGroupDao->getByUserId($user->getId());
1108 while ($userGroup = $userGroupsResult->next()) {
1109 $userRoles[] = (int) $userGroup->getRoleId();
1112 'csrfToken' => $this->_request->getSession()->getCSRFToken(),
1113 'id' => (int) $user->getId(),
1114 'roles' => array_values(array_unique($userRoles)),
1116 $output .=
'pkp.currentUser = ' . json_encode($currentUser) .
';';
1124 'priority' => STYLE_SEQUENCE_LATE,
1125 'contexts' => [
'backend'],
1140 $this->assign(
'state', $this->_state);
1146 header(
'Content-Type: text/html; charset=' .
Config::getVar(
'i18n',
'client_charset'));
1147 header(
'Cache-Control: ' . $this->_cacheability);
1150 if (!$compile_id) $compile_id = $this->
getCompileId($template);
1153 parent::display($template, $cache_id, $compile_id, $parent);
1161 $this->clearCompiledTemplate();
1162 $this->clearAllCache();
1170 $files = scandir($cacheDirectory);
1186 $newContextOrSite = $args[0];
1187 $contextOrSite = $args[1];
1188 if ($newContextOrSite->getData(
'themePluginPath') !== $contextOrSite->getData(
'themePluginPath')) {
1199 static function &
getManager($request =
null) {
1200 if (!isset($request)) {
1202 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call without request object.');
1204 assert(is_a($request,
'PKPRequest'));
1208 if ($instance ===
null) {
1211 if (empty($themes)) {
1214 $instance->initialize($request);
1226 import(
'lib.pkp.classes.form.FormBuilderVocabulary');
1243 $params =& $args[0];
1244 $smarty =& $args[1];
1245 $output =& $args[2];
1247 if ($this->_request->getContext()) {
1248 $blocks = $this->_request->getContext()->getData(
'sidebar');
1250 $blocks = $this->_request->getSite()->getData(
'sidebar');
1253 if (empty($blocks)) {
1258 if (empty($plugins)) {
1262 foreach ($blocks as $pluginName) {
1263 if (!empty($plugins[$pluginName])) {
1264 $output .= $plugins[$pluginName]->getContents($smarty, $this->_request);
1288 if (isset($params) && !empty($params)) {
1289 if (!isset($params[
'key']))
return __(
'');
1291 $key = $params[
'key'];
1292 unset($params[
'key']);
1293 if (isset($params[
'params']) && is_array($params[
'params'])) {
1294 $paramsArray = $params[
'params'];
1295 unset($params[
'params']);
1296 $params = array_merge($params, $paramsArray);
1298 return __($key, $params);
1311 assert(isset($params[
'id']));
1313 $id = $params[
'id'];
1314 $key = isset($params[
'key'])?$params[
'key']:
null;
1315 $hoverTitle = isset($params[
'hoverTitle'])?
true:
false;
1316 $image = isset($params[
'image'])?$params[
'image']:
null;
1317 $translate = isset($params[
'translate'])?
false:
true;
1319 import(
'lib.pkp.classes.linkAction.request.NullAction');
1320 import(
'lib.pkp.classes.linkAction.LinkAction');
1321 $key = $translate ? __($key) : $key;
1326 $this->assign(
'hoverTitle', $hoverTitle);
1327 return $this->
fetch(
'linkAction/linkAction.tpl');
1338 assert(isset($params[
'file']));
1340 $params = array_merge(
1344 'textKey' =>
'help.help',
1352 'helpFile' => $params[
'file'],
1353 'helpSection' => $params[
'section'],
1354 'helpTextKey' => $params[
'textKey'],
1355 'helpText' => $params[
'text'],
1356 'helpClass' => $params[
'class'],
1359 return $this->
fetch(
'common/helpLink.tpl');
1371 if (isset($params[
'options'])) {
1372 if (isset($params[
'translateValues'])) {
1375 foreach ($params[
'options'] as $k => $v) {
1376 $newOptions[__($k)] = __($v);
1378 $params[
'options'] = $newOptions;
1381 $params[
'options'] = array_map(
'AppLocale::translate', $params[
'options']);
1385 if (isset($params[
'output'])) {
1386 $params[
'output'] = array_map(
'AppLocale::translate', $params[
'output']);
1389 if (isset($params[
'values']) && isset($params[
'translateValues'])) {
1390 $params[
'values'] = array_map(
'AppLocale::translate', $params[
'values']);
1393 require_once(
'lib/pkp/lib/vendor/smarty/smarty/libs/plugins/function.html_options.php');
1394 return smarty_function_html_options($params, $smarty);
1405 function smartyIterate($params, $content, $smarty, &$repeat) {
1406 $iterator = $smarty->getTemplateVars($params[
'from']);
1408 if (isset($params[
'key'])) {
1409 if (empty($content)) $smarty->assign($params[
'key'], 1);
1410 else $smarty->assign($params[
'key'], $smarty->getTemplateVars($params[
'key'])+1);
1414 if (!$iterator || $iterator->eof()) {
1415 if (!$repeat)
return $content;
1422 if (isset($params[
'key'])) {
1423 list($key, $value) = $iterator->nextWithKey();
1424 $smarty->assign($params[
'item'], $value);
1425 $smarty->assign($params[
'key'], $key);
1427 $smarty->assign($params[
'item'], $iterator->next());
1439 $iterator = $params[
'iterator'];
1441 if (isset($params[
'itemsPerPage'])) {
1442 $itemsPerPage = $params[
'itemsPerPage'];
1444 $itemsPerPage = $smarty->getTemplateVars(
'itemsPerPage');
1445 if (!is_numeric($itemsPerPage)) $itemsPerPage=25;
1448 $page = $iterator->getPage();
1449 $pageCount = $iterator->getPageCount();
1450 $itemTotal = $iterator->getCount();
1452 if ($pageCount<1)
return '';
1454 $from = (($page - 1) * $itemsPerPage) + 1;
1455 $to = min($itemTotal, $page * $itemsPerPage);
1457 return __(
'navigation.items', [
1458 'from' => ($to===0?0:$from),
1460 'total' => $itemTotal
1474 while (ob_get_level()) {
1504 function smartyUrl($parameters, $smarty) {
1505 if ( !isset($parameters[
'context']) ) {
1511 $contextList = $application->getContextList();
1512 foreach ($contextList as $contextName) {
1513 if (isset($parameters[$contextName])) {
1514 $context[$contextName] = $parameters[$contextName];
1515 unset($parameters[$contextName]);
1517 $context[$contextName] =
null;
1520 $parameters[
'context'] = $context;
1526 $paramList = [
'params',
'router',
'context',
'page',
'component',
'op',
'path',
'anchor',
'escape'];
1527 foreach ($paramList as $parameter) {
1528 if (isset($parameters[$parameter])) {
1529 $$parameter = $parameters[$parameter];
1530 unset($parameters[$parameter]);
1538 $parameters = array_merge($parameters, (array) $params);
1541 if (is_null($router)) {
1542 if (is_a($this->_request->getRouter(),
'PKPComponentRouter')) {
1543 $router = ROUTE_COMPONENT;
1545 $router = ROUTE_PAGE;
1551 $routerShortcuts = array_keys($dispatcher->getRouterNames());
1552 assert(in_array($router, $routerShortcuts));
1560 case ROUTE_COMPONENT:
1561 $handler = $component;
1570 return $dispatcher->url($this->_request, $router, $context, $handler,
$op, $path, $parameters, $anchor, !isset($escape) || $escape);
1592 $page = $parameters[
'value'] ??
'';
1593 if ($smarty->get_template_vars(
'currentContext')) {
1594 $siteTitle = $smarty->get_template_vars(
'currentContext')->getLocalizedData(
'name');
1595 } elseif ($smarty->get_template_vars(
'siteTitle')) {
1596 $siteTitle = $smarty->get_template_vars(
'siteTitle');
1598 $siteTitle = __(
'common.software');
1601 if (empty($parameters[
'value'])) {
1605 return $parameters[
'value'] . __(
'common.titleSeparator') . $siteTitle;
1619 $iterator = $params[
'iterator'];
1620 $name = $params[
'name'];
1621 if (isset($params[
'params']) && is_array($params[
'params'])) {
1622 $extraParams = $params[
'params'];
1623 unset($params[
'params']);
1624 $params = array_merge($params, $extraParams);
1626 if (isset($params[
'anchor'])) {
1627 $anchor = $params[
'anchor'];
1628 unset($params[
'anchor']);
1632 if (isset($params[
'all_extra'])) {
1633 $allExtra =
' ' . $params[
'all_extra'];
1634 unset($params[
'all_extra']);
1639 unset($params[
'iterator']);
1640 unset($params[
'name']);
1642 $numPageLinks = $smarty->getTemplateVars(
'numPageLinks');
1643 if (!is_numeric($numPageLinks)) $numPageLinks=10;
1645 $page = $iterator->getPage();
1646 $pageCount = $iterator->getPageCount();
1648 $pageBase = max($page - floor($numPageLinks / 2), 1);
1649 $paramName = $name .
'Page';
1651 if ($pageCount<=1)
return '';
1655 $router = $this->_request->getRouter();
1656 $requestedArgs =
null;
1657 if (is_a($router,
'PageRouter')) {
1658 $requestedArgs = $router->getRequestedArgs($this->_request);
1662 $params[$paramName] = 1;
1663 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'><<</a> ';
1664 $params[$paramName] = $page - 1;
1665 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'><</a> ';
1668 for ($i=$pageBase; $i<min($pageBase+$numPageLinks, $pageCount+1); $i++) {
1670 $value .=
"<strong>$i</strong> ";
1672 $params[$paramName] = $i;
1673 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>' . $i .
'</a> ';
1676 if ($page < $pageCount) {
1677 $params[$paramName] = $page + 1;
1678 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>></a> ';
1679 $params[$paramName] = $pageCount;
1680 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>>></a> ';
1690 return func_get_args();
1697 $args = func_get_args();
1698 return implode(
'', $args);
1708 function smartyCompare($a, $b, $strict =
false, $invert =
false) {
1709 $result = $strict?$a===$b:$a==$b;
1710 return $invert?!$result:$result;
1717 return strtotime($string);
1724 return explode($separator, $string);
1731 function smartyEscape($string, $esc_type =
'html', $char_set =
'ISO-8859-1') {
1732 $pattern =
"/(:|\.|\[|\]|,|=|@)/";
1733 $replacement =
"\\\\\\\\$1";
1734 switch ($esc_type) {
1741 $result = smarty_modifier_escape($string,
'html', $char_set);
1742 $result = preg_replace($pattern, $replacement, $result);
1746 $result = smarty_modifier_escape($string,
'javascript', $char_set);
1747 $result = preg_replace($pattern, $replacement, $result);
1751 return smarty_modifier_escape($string, $esc_type, $char_set);
1765 if (!isset($params[
'el'])) {
1766 throw new Exception(
"el parameter is missing from load_url_in_el");
1768 if (!isset($params[
'url'])) {
1769 throw new Exception(
"url parameter is missing from load_url_in_el");
1771 if (!isset($params[
'id'])) {
1772 throw new Exception(
"id parameter is missing from load_url_in_el");
1776 'inEl' => $params[
'el'],
1777 'inElUrl' => $params[
'url'],
1778 'inElElId' => $params[
'id'],
1779 'inElClass' => isset($params[
'class'])?$params[
'class']:
null,
1780 'refreshOn' => isset($params[
'refreshOn'])?$params[
'refreshOn']:
null,
1783 if (isset($params[
'placeholder'])) {
1784 $this->assign(
'inElPlaceholder', $params[
'placeholder']);
1785 } elseif (isset($params[
'loadMessageId'])) {
1786 $loadMessageId = $params[
'loadMessageId'];
1787 $this->assign(
'inElPlaceholder', __($loadMessageId, $params));
1789 $this->assign(
'inElPlaceholder', $this->
fetch(
'common/loadingContainer.tpl'));
1792 return $this->
fetch(
'common/urlInEl.tpl');
1805 $params[
'el'] =
'div';
1818 $csrfToken = $this->_request->getSession()->getCSRFToken();
1819 switch (isset($params[
'type'])?$params[
'type']:
null) {
1820 case 'raw':
return $csrfToken;
1821 case 'json':
return json_encode($csrfToken);
1824 return '<input type="hidden" name="csrfToken" value="' . htmlspecialchars($csrfToken) .
'">';
1838 if (empty($params[
'context'])) {
1839 $params[
'context'] =
'frontend';
1842 if (!defined(
'SESSION_DISABLE_INIT')) {
1844 $appVersion = $versionDao->getCurrentVersion()->getVersionString();
1845 }
else $appVersion =
null;
1849 ksort($stylesheets);
1852 foreach($stylesheets as $priorityList) {
1853 foreach($priorityList as $style) {
1854 if (!empty($style[
'inline'])) {
1855 $output .=
'<style type="text/css">' . $style[
'style'] .
'</style>';
1857 if ($appVersion && strpos($style[
'style'],
'?') ===
false) {
1858 $style[
'style'] .=
'?v=' . $appVersion;
1860 $output .=
'<link rel="stylesheet" href="' . $style[
'style'] .
'" type="text/css" />';
1879 if (empty($htmlContent)) {
1880 return $htmlContent;
1883 $hasEmbeddedStyle =
false;
1884 foreach ($embeddedFiles as $embeddedFile) {
1885 if ($embeddedFile->getFileType() ===
'text/css') {
1886 $hasEmbeddedStyle =
true;
1891 if ($hasEmbeddedStyle) {
1892 return $htmlContent;
1898 if (!empty($styles)) {
1900 foreach ($styles as $priorityGroup) {
1901 foreach ($priorityGroup as $htmlStyle) {
1902 $links .=
'<link rel="stylesheet" href="' . $htmlStyle[
'style'] .
'" type="text/css">' .
"\n";
1907 return str_ireplace(
'<head>',
'<head>' .
"\n" . $links, $htmlContent);
1920 if (empty($params[
'context'])) {
1921 $params[
'context'] =
'frontend';
1924 if (!defined(
'SESSION_DISABLE_INIT')) {
1926 $appVersion = defined(
'SESSION_DISABLE_INIT') ? null : $versionDao->getCurrentVersion()->getVersionString();
1927 }
else $appVersion =
null;
1934 foreach($scripts as $priorityList) {
1935 foreach($priorityList as $name => $data) {
1936 if ($data[
'inline']) {
1937 $output .=
'<script type="text/javascript">' . $data[
'script'] .
'</script>';
1939 if ($appVersion && strpos($data[
'script'],
'?') ===
false) {
1940 $data[
'script'] .=
'?v=' . $appVersion;
1942 $output .=
'<script src="' . $data[
'script'] .
'" type="text/javascript"></script>';
1960 if (empty($params[
'context'])) {
1961 $params[
'context'] =
'frontend';
1969 foreach($headers as $priorityList) {
1970 foreach($priorityList as $name => $data) {
1971 $output .=
"\n" . $data[
'header'];
1987 $areaName = $params[
'name'];
1988 $declaredMenuTemplatePath = $params[
'path'];
1989 $currentContext = $this->_request->getContext();
1990 $contextId = CONTEXT_ID_NONE;
1991 if ($currentContext) {
1992 $contextId = $currentContext->getId();
1997 if (empty($themePlugins)) {
2000 $activeThemeNavigationAreas = [];
2001 foreach ($themePlugins as $themePlugin) {
2002 if ($themePlugin->isActive()) {
2003 $areas = $themePlugin->getMenuAreas();
2004 if (!in_array($areaName, $areas)) {
2010 $menuTemplatePath =
'frontend/components/navigationMenu.tpl';
2011 if (isset($declaredMenuTemplatePath)) {
2012 $menuTemplatePath = $declaredMenuTemplatePath;
2018 $navigationMenus = $navigationMenuDao->getByArea($contextId, $areaName)->toArray();
2019 if (isset($navigationMenus[0])) {
2020 $navigationMenu = $navigationMenus[0];
2021 import(
'classes.core.Services');
2022 Services::get(
'navigationMenu')->getMenuTree($navigationMenu);
2027 'navigationMenu' => $navigationMenu,
2028 'id' => $params[
'id'],
2029 'ulClass' => $params[
'ulClass'],
2030 'liClass' => $params[
'liClass'],
2033 return $this->
fetch($menuTemplatePath);
2048 if (array_key_exists($context, $resources)) {
2049 $matches = $resources[$context];
2052 $page = $this->getTemplateVars(
'requestedPage');
2053 $page = empty( $page ) ?
'index' : $page;
2054 $op = $this->getTemplateVars(
'requestedOp');
2058 join(
'-', [$context, $page]),
2059 join(
'-', [$context, $page,
$op]),
2062 foreach($contexts as $context) {
2063 if (array_key_exists($context, $resources)) {
2064 foreach ($resources[$context] as $priority => $priorityList) {
2065 if (!array_key_exists($priority, $matches)) {
2066 $matches[$priority] = [];
2068 $matches[$priority] = array_merge($matches[$priority], $resources[$context][$priority]);
2070 $matches += $resources[$context];
2089 if (empty($params[
'assign'])) {
2090 error_log(
'Smarty: {pluck_files} function called without required `assign` param. Called in ' . __FILE__ .
':' . __LINE__);
2095 if (!is_array($params[
'files'])) {
2096 error_log(
'Smarty: {pluck_files} function called without required `files` param. Called in ' . __FILE__ .
':' . __LINE__);
2097 $smarty->assign($params[
'assign'], []);
2102 if (empty($params[
'by'])) {
2103 error_log(
'Smarty: {pluck_files} function called without required `by` param. Called in ' . __FILE__ .
':' . __LINE__);
2104 $smarty->assign($params[
'assign'], []);
2114 if (!in_array($params[
'by'], [
'chapter',
'publicationFormat',
'component',
'fileExtension',
'genre'])) {
2115 error_log(
'Smarty: {pluck_files} function called without a valid `by` param. Called in ' . __FILE__ .
':' . __LINE__);
2116 $smarty->assign($params[
'assign'], []);
2121 if (!isset($params[
'value'])) {
2122 error_log(
'Smarty: {pluck_files} function called without required `value` param. Called in ' . __FILE__ .
':' . __LINE__);
2123 $smarty->assign($params[
'assign'], []);
2127 $matching_files = [];
2130 foreach ($params[
'files'] as $file) {
2131 switch ($params[
'by']) {
2134 $genre = $genreDao->getById($file->getGenreId());
2135 if (!$genre->getDependent() && method_exists($file,
'getChapterId')) {
2136 if ($params[
'value'] ===
'any' && $file->getChapterId()) {
2137 $matching_files[] = $file;
2138 } elseif($file->getChapterId() == $params[
'value']) {
2139 $matching_files[] = $file;
2140 } elseif ($params[
'value'] == 0 && !$file->getChapterId()) {
2141 $matching_files[] = $file;
2146 case 'publicationFormat':
2147 if ($file->getAssocId() == $params[
'value']) {
2148 $matching_files[] = $file;
2153 if (get_class($file) == $params[
'value']) {
2154 $matching_files[] = $file;
2158 case 'fileExtension':
2159 if ($file->getExtension() == $params[
'value']) {
2160 $matching_files[] = $file;
2165 if ($file->getGenreId() == $params[
'value']) {
2166 $matching_files[] = $file;
2172 $smarty->assign($params[
'assign'], $matching_files);
2180 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call to Smarty2 function ' . __FUNCTION__);
2181 return $this->getTemplateVars($varname);
2191 public function register_function($name, $impl, $cacheable =
true, $cache_attrs =
null) {
2192 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call to Smarty2 function ' . __FUNCTION__);
2193 $this->registerPlugin(
'function', $name, $impl, $cacheable, $cache_attrs);