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 'currentContext' => $currentContext,
123 'currentLocale' => $locale,
129 if ($currentContext) {
131 'dateFormatShort' => $currentContext->getLocalizedDateFormatShort(),
132 'dateFormatLong' => $currentContext->getLocalizedDateFormatLong(),
133 'datetimeFormatShort' => $currentContext->getLocalizedDateTimeFormatShort(),
134 'datetimeFormatLong' => $currentContext->getLocalizedDateTimeFormatLong(),
135 'timeFormat' => $currentContext->getLocalizedTimeFormat(),
139 'dateFormatShort' =>
Config::getVar(
'general',
'date_format_short'),
140 'dateFormatLong' =>
Config::getVar(
'general',
'date_format_long'),
141 'datetimeFormatShort' =>
Config::getVar(
'general',
'datetime_format_short'),
142 'datetimeFormatLong' =>
Config::getVar(
'general',
'datetime_format_long'),
148 if ($currentContext) {
149 $favicon = $currentContext->getLocalizedFavicon();
150 if (!empty($favicon)) {
152 $faviconDir = $request->getBaseUrl() .
'/' . $publicFileManager->getContextFilesPath($currentContext->getId());
153 $this->
addHeader(
'favicon',
'<link rel="icon" href="' . $faviconDir .
'/' . $favicon[
'uploadName'] .
'">');
159 $contextOrSite = $currentContext ? $currentContext : $request->getSite();
161 foreach ($allThemes as $theme) {
162 if ($contextOrSite->getData(
'themePluginPath') === $theme->getDirName()) {
163 $activeTheme = $theme;
167 $this->assign([
'activeTheme' => $activeTheme]);
170 if (is_a($router,
'PKPPageRouter')) {
172 'requestedPage' => $router->getRequestedPage($request),
173 'requestedOp' => $router->getRequestedOp($request),
177 if ($currentContext) {
178 $contextStyleSheet = $currentContext->getData(
'styleSheet');
179 if ($contextStyleSheet) {
180 import(
'classes.file.PublicFileManager');
184 $request->getBaseUrl() .
'/' . $publicFileManager->getContextFilesPath($currentContext->getId()) .
'/' . $contextStyleSheet[
'uploadName'],
185 [
'priority' => STYLE_SEQUENCE_LATE]
196 'contexts' => [
'frontend-user-register',
'frontend-user-registerUser'],
203 if (($request->getRequestedPage()==
'' || $request->getRequestedPage() ==
'index') && $currentContext && $currentContext->getLocalizedData(
'searchDescription')) {
204 $this->
addHeader(
'searchDescription',
'<meta name="description" content="' . $currentContext->getLocalizedData(
'searchDescription') .
'">');
209 '<meta name="generator" content="' . __(
$application->getNameKey()) .
' ' .
$application->getCurrentVersion()->getVersionString(
false) .
'">',
211 'contexts' => [
'frontend',
'backend'],
215 if ($currentContext) {
216 $customHeaders = $currentContext->getLocalizedData(
'customHeaders');
217 if (!empty($customHeaders)) {
218 $this->
addHeader(
'customHeaders', $customHeaders);
223 if ($currentContext && !$currentContext->getEnabled()) {
226 '<meta name="robots" content="noindex,nofollow">',
228 'contexts' => [
'frontend',
'backend'],
234 import(
'classes.core.Services');
243 $this->registerPlugin(
'modifier',
'translate',
'AppLocale::translate');
244 $this->registerPlugin(
'modifier',
'strip_unsafe_html',
'PKPString::stripUnsafeHtml');
245 $this->registerPlugin(
'modifier',
'String_substr',
'PKPString::substr');
246 $this->registerPlugin(
'modifier',
'dateformatPHP2JQueryDatepicker',
'PKPString::dateformatPHP2JQueryDatepicker');
247 $this->registerPlugin(
'modifier',
'to_array', [$this,
'smartyToArray']);
248 $this->registerPlugin(
'modifier',
'compare', [$this,
'smartyCompare']);
249 $this->registerPlugin(
'modifier',
'concat', [$this,
'smartyConcat']);
250 $this->registerPlugin(
'modifier',
'strtotime', [$this,
'smartyStrtotime']);
251 $this->registerPlugin(
'modifier',
'explode', [$this,
'smartyExplode']);
252 $this->registerPlugin(
'modifier',
'escape', [$this,
'smartyEscape']);
253 $this->registerPlugin(
'function',
'csrf', [$this,
'smartyCSRF']);
254 $this->registerPlugin(
'function',
'translate', [$this,
'smartyTranslate']);
255 $this->registerPlugin(
'function',
'null_link_action', [$this,
'smartyNullLinkAction']);
256 $this->registerPlugin(
'function',
'help', [$this,
'smartyHelp']);
257 $this->registerPlugin(
'function',
'flush', [$this,
'smartyFlush']);
258 $this->registerPlugin(
'function',
'call_hook', [$this,
'smartyCallHook']);
259 $this->registerPlugin(
'function',
'html_options_translate', [$this,
'smartyHtmlOptionsTranslate']);
260 $this->registerPlugin(
'block',
'iterate', [$this,
'smartyIterate']);
261 $this->registerPlugin(
'function',
'page_links', [$this,
'smartyPageLinks']);
262 $this->registerPlugin(
'function',
'page_info', [$this,
'smartyPageInfo']);
263 $this->registerPlugin(
'function',
'pluck_files', [$this,
'smartyPluckFiles']);
265 $this->registerPlugin(
'function',
'title', [$this,
'smartyTitle']);
266 $this->registerPlugin(
'function',
'url', [$this,
'smartyUrl']);
269 $this->registerPlugin(
'function',
'load_stylesheet', [$this,
'smartyLoadStylesheet']);
270 $this->registerPlugin(
'function',
'load_script', [$this,
'smartyLoadScript']);
271 $this->registerPlugin(
'function',
'load_header', [$this,
'smartyLoadHeader']);
274 $this->registerPlugin(
'function',
'load_menu', [$this,
'smartyLoadNavigationMenuArea']);
278 $this->registerPlugin(
'block',
'fbvFormSection', [$fbv,
'smartyFBVFormSection']);
279 $this->registerPlugin(
'block',
'fbvFormArea', [$fbv,
'smartyFBVFormArea']);
280 $this->registerPlugin(
'function',
'fbvFormButtons', [$fbv,
'smartyFBVFormButtons']);
281 $this->registerPlugin(
'function',
'fbvElement', [$fbv,
'smartyFBVElement']);
282 $this->registerPlugin(
'function',
'fieldLabel', [$fbv,
'smartyFieldLabel']);
283 $this->assign(
'fbvStyles', $fbv->getStyles());
286 $this->registerPlugin(
'function',
'load_url_in_el', [$this,
'smartyLoadUrlInEl']);
287 $this->registerPlugin(
'function',
'load_url_in_div', [$this,
'smartyLoadUrlInDiv']);
296 import(
'lib.pkp.classes.controllers.listbuilder.ListbuilderHandler');
298 'LISTBUILDER_SOURCE_TYPE_TEXT',
299 'LISTBUILDER_SOURCE_TYPE_SELECT',
300 'LISTBUILDER_OPTGROUP_LABEL',
307 if (!defined(
'SESSION_DISABLE_INIT')) {
313 'siteTitle' => $request->getSite()->getLocalizedData(
'title'),
316 $user = $request->getUser();
319 'currentUser' => $user,
324 'loggedInUsername' => $user->getUserName(),
331 if ($currentContext) {
332 $this->assign(
'hasSidebar', !empty($currentContext->getData(
'sidebar')));
334 $this->assign(
'hasSidebar', !empty($request->getSite()->getData(
'sidebar')));
350 $this->_cacheability = $cacheability;
363 public function compileLess($name, $lessFile, $args = []) {
364 $less =
new Less_Parser([
365 'relativeUrls' =>
false,
369 $request = $this->_request;
372 HookRegistry::call(
'PageHandler::compileLess', [&$less, &$lessFile, &$args, $name, $request]);
375 $less->parseFile($lessFile);
378 if (isset($args[
'addLess']) && is_array($args[
'addLess'])) {
379 foreach ($args[
'addLess'] as $addless) {
380 $less->parseFile($addless);
385 if (isset($args[
'addLessVariables'])) {
386 foreach ((array) $args[
'addLessVariables'] as $addlessVariables) {
387 $less->parse($addlessVariables);
392 $baseUrl = !empty($args[
'baseUrl']) ? $args[
'baseUrl'] : $request->getBaseUrl(
true);
393 $less->parse(
"@baseUrl: '$baseUrl';");
395 return $less->getCSS();
405 public function cacheLess($path, $styles) {
406 if (file_put_contents($path, $styles) ===
false) {
407 error_log(
"Unable to write \"$path\".");
422 $context = $this->_request->getContext();
423 $contextId = is_a($context,
'Context') ? $context->getId() : 0;
424 return $cacheDirectory . DIRECTORY_SEPARATOR . $contextId .
'-' . $name .
'.css';
445 'priority' => STYLE_SEQUENCE_NORMAL,
446 'contexts' => [
'frontend'],
452 $args[
'contexts'] = (array) $args[
'contexts'];
453 foreach($args[
'contexts'] as $context) {
454 $this->_styleSheets[$context][$args[
'priority']][$name] = [
456 'inline' => $args[
'inline'],
479 'priority' => STYLE_SEQUENCE_NORMAL,
480 'contexts' => [
'frontend'],
486 $args[
'contexts'] = (array) $args[
'contexts'];
487 foreach($args[
'contexts'] as $context) {
488 $this->_javaScripts[$context][$args[
'priority']][$name] = [
490 'inline' => $args[
'inline'],
506 function addHeader($name, $header, $args = []) {
510 'priority' => STYLE_SEQUENCE_NORMAL,
511 'contexts' => [
'frontend'],
516 $args[
'contexts'] = (array) $args[
'contexts'];
517 foreach($args[
'contexts'] as $context) {
518 $this->_htmlHeaders[$context][$args[
'priority']][$name] = [
530 foreach ($names as $name) {
531 $this->_constants[$name] = constant($name);
541 foreach ($keys as $key) {
542 if (!array_key_exists($key, $this->_localeKeys)) {
543 $this->_localeKeys[$key] = __($key);
555 return array_key_exists($key, $this->_state)
556 ? $this->_state[$key]
566 $this->_state = array_merge($this->_state, $data);
573 $baseUrl = $this->_request->getBaseUrl();
578 'priority' => STYLE_SEQUENCE_CORE,
579 'contexts' =>
'backend',
586 $baseUrl .
'/lib/pkp/js/lib/jquery/plugins/validate/jquery.validate.min.js',
589 $jqvLocalePath =
'lib/pkp/js/lib/jquery/plugins/validate/localization/messages_';
590 foreach ($localeChecks as $localeCheck) {
591 if (file_exists($jqvLocalePath . $localeCheck .
'.js')) {
592 $this->
addJavaScript(
'jqueryValidateLocale', $baseUrl .
'/' . $jqvLocalePath . $localeCheck .
'.js', $args);
598 $baseUrl .
'/lib/pkp/lib/vendor/moxiecode/plupload/js/plupload.full.min.js',
603 $baseUrl .
'/lib/pkp/lib/vendor/moxiecode/plupload/js/jquery.ui.plupload/jquery.ui.plupload.js',
606 $plLocalePath =
'lib/pkp/lib/vendor/moxiecode/plupload/js/i18n/';
607 foreach ($localeChecks as $localeCheck) {
608 if (file_exists($plLocalePath . $localeCheck .
'.js')) {
609 $this->
addJavaScript(
'plUploadLocale', $baseUrl .
'/' . $plLocalePath . $localeCheck .
'.js', $args);
616 $baseUrl .
'/js/build.js',
618 'priority' => STYLE_SEQUENCE_LATE,
619 'contexts' => [
'backend']
627 $baseUrl .
'/js/pkp.min.js',
629 'priority' => STYLE_SEQUENCE_CORE,
630 'contexts' => [
'backend']
637 $minifiedScripts = array_filter(array_map(
'trim', file(
'registry/minifiedScripts.txt')),
function($s) {
638 return strlen($s) && $s[0] !=
'#';
640 foreach ($minifiedScripts as $key => $script) {
641 $this->
addJavaScript(
'pkpLib' . $key,
"$baseUrl/$script", $args);
657 $context = $this->_request->getContext();
660 $output =
'$.pkp = $.pkp || {};';
663 import(
'lib.pkp.classes.security.Role');
669 'baseUrl' => $this->_request->getBaseUrl(),
670 'contextPath' => isset($context) ? $context->getPath() :
'',
671 'apiBasePath' =>
'/api/v1',
672 'pathInfoEnabled' =>
Config::getVar(
'general',
'disable_path_info') ? false :
true,
673 'restfulUrlsEnabled' =>
Config::getVar(
'general',
'restful_urls') ? true :
false,
674 'tinyMceContentCSS' => $this->_request->getBaseUrl() .
'/plugins/generic/tinymce/styles/content.css',
675 'tinyMceContentFont' =>
Config::getVar(
'general',
'enable_cdn') ? $this->_request->getBaseUrl() .
'/plugins/generic/tinymce/styles/content-font.css' :
'',
678 $output .=
'$.pkp.app = ' .
json_encode($app_data) .
';';
681 $output .=
'$.pkp.cons = ' .
json_encode($this->_constants) .
';';
684 $output .=
'$.pkp.plugins = {};';
690 'priority' => STYLE_SEQUENCE_CORE,
691 'contexts' =>
'backend',
703 $dispatcher = $request->getDispatcher();
704 $router = $request->getRouter();
707 $this->assign(
'pageComponent',
'Page');
712 'UPLOAD_MAX_FILESIZE',
713 'WORKFLOW_STAGE_ID_PUBLISHED',
714 'WORKFLOW_STAGE_ID_SUBMISSION',
715 'WORKFLOW_STAGE_ID_INTERNAL_REVIEW',
716 'WORKFLOW_STAGE_ID_EXTERNAL_REVIEW',
717 'WORKFLOW_STAGE_ID_EDITING',
718 'WORKFLOW_STAGE_ID_PRODUCTION',
719 'INSERT_TAG_VARIABLE_TYPE_PLAIN_TEXT',
721 'ROLE_ID_SITE_ADMIN',
726 'ROLE_ID_SUB_EDITOR',
727 'ROLE_ID_SUBSCRIPTION_MANAGER',
733 'common.clearSearch',
735 'common.commaListSeparator',
742 'common.filterRemove',
745 'common.noItemsFound',
751 'common.pagination.goToPage',
752 'common.pagination.label',
753 'common.pagination.next',
754 'common.pagination.previous',
760 'common.selectWithName',
761 'common.unknownError',
765 'common.viewWithName',
767 'form.dataHasChanged',
773 'form.multilingualLabel',
774 'form.multilingualProgress',
782 $min =
Config::getVar(
'general',
'enable_minified') ?
'.min' :
'';
784 $jquery =
'//ajax.googleapis.com/ajax/libs/jquery/' . CDN_JQUERY_VERSION .
'/jquery' . $min .
'.js';
785 $jqueryUI =
'//ajax.googleapis.com/ajax/libs/jqueryui/' . CDN_JQUERY_UI_VERSION .
'/jquery-ui' . $min .
'.js';
787 $jquery = $request->getBaseUrl() .
'/lib/pkp/lib/vendor/components/jquery/jquery' . $min .
'.js';
788 $jqueryUI = $request->getBaseUrl() .
'/lib/pkp/lib/vendor/components/jqueryui/jquery-ui' . $min .
'.js';
794 'priority' => STYLE_SEQUENCE_CORE,
795 'contexts' =>
'backend',
802 'priority' => STYLE_SEQUENCE_CORE,
803 'contexts' =>
'backend',
813 '//fonts.googleapis.com/css?family=Noto+Sans:400,400italic,700,700italic',
815 'priority' => STYLE_SEQUENCE_CORE,
816 'contexts' =>
'backend',
827 $url =
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css';
829 $url = $request->getBaseUrl() .
'/lib/pkp/styles/fontawesome/fontawesome.css';
835 'priority' => STYLE_SEQUENCE_CORE,
836 'contexts' =>
'backend',
843 $request->getBaseUrl() .
'/styles/build.css',
845 'priority' => STYLE_SEQUENCE_CORE,
846 'contexts' =>
'backend',
853 $dispatcher->url($request, ROUTE_COMPONENT,
null,
'page.PageHandler',
'css'),
855 'priority' => STYLE_SEQUENCE_CORE,
856 'contexts' =>
'backend',
864 $request->getBaseUrl() .
'/' . $localeStyleSheet,
866 'contexts' => [
'backend'],
880 if (
Config::getVar(
'general',
'installed') && !defined(
'SESSION_DISABLE_INIT')) {
882 if ($request->getUser()) {
886 import(
'lib.pkp.controllers.grid.notifications.TaskNotificationsGridHandler');
887 $unreadTasksCount = (int) $notificationDao->getNotificationCount(
false, $request->getUser()->getId(),
null, NOTIFICATION_LEVEL_TASK);
890 $tasksUrl = $request->getDispatcher()->url($request, ROUTE_COMPONENT,
null,
'page.PageHandler',
'tasks');
894 $notifications = $notificationDao->getByUserId($request->getUser()->getId(), NOTIFICATION_LEVEL_TRIVIAL);
900 $args = [
'userId' => $request->getUser()->getId()];
902 $availableContexts =
Services::get(
'context')->getManySummary($args);
903 if ($request->getContext()) {
904 $availableContexts = array_filter($availableContexts,
function($context) use ($request) {
905 return $context->id !== $request->getContext()->getId();
908 $requestedPage = $router->getRequestedPage($request);
909 foreach ($availableContexts as $availableContext) {
911 if ($requestedPage !==
'admin' && in_array(ROLE_ID_SITE_ADMIN, $this->
get_template_vars(
'userRoles'))) {
912 $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath, $request->getRequestedPage(), $request->getRequestedOp(), $request->getRequestedArgs($request));
914 $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath,
'submissions');
919 $userRoles = (array) $router->getHandler()->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
923 if ($request->getContext()) {
924 if (
count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR, ROLE_ID_ASSISTANT, ROLE_ID_REVIEWER, ROLE_ID_AUTHOR], $userRoles))) {
925 $menu[
'submissions'] = [
926 'name' => __(
'navigation.submissions'),
927 'url' => $router->url($request,
null,
'submissions'),
928 'isCurrent' => $router->getRequestedPage($request) ===
'submissions',
930 } elseif (
count($userRoles) === 1 && in_array(ROLE_ID_READER, $userRoles)) {
933 'name' => __(
'author.submit'),
934 'url' => $router->url($request,
null,
'submission',
'wizard'),
935 'isCurrent' => $router->getRequestedPage($request) ===
'submission',
939 if (
count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR], $userRoles))) {
940 $menu[
'statistics'] = [
941 'name' => __(
'navigation.tools.statistics'),
944 'name' => __(
'common.publications'),
945 'url' => $router->url($request,
null,
'stats',
'publications',
'publications'),
946 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'publications',
949 'name' => __(
'stats.editorialActivity'),
950 'url' => $router->url($request,
null,
'stats',
'editorial',
'editorial'),
951 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'editorial',
954 'name' => __(
'manager.users'),
955 'url' => $router->url($request,
null,
'stats',
'users',
'users'),
956 'isCurrent' => $router->getRequestedPage($request) ===
'stats' && $router->getRequestedOp($request) ===
'users',
962 if (in_array(ROLE_ID_MANAGER, $userRoles)) {
963 if ($request->getContext()->getData(
'enableAnnouncements')) {
964 $menu[
'announcements'] = [
965 'name' => __(
'announcement.announcements'),
966 'url' => $router->url($request,
null,
'management',
'settings',
'announcements'),
967 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'announcements', (array) $router->getRequestedArgs($request)),
970 $menu[
'statistics'][
'submenu'] += [
972 'name' => __(
'manager.statistics.reports'),
973 'url' => $router->url($request,
null,
'management',
'tools',
null,
null,
'statistics'),
974 'isCurrent' => $router->getRequestedPage($request) ===
'management' && $router->getRequestedAnchor($request) ===
'statistics',
977 $menu[
'settings'] = [
978 'name' => __(
'navigation.settings'),
981 'name' => __(
'context.context'),
982 'url' => $router->url($request,
null,
'management',
'settings',
'context'),
983 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'context', (array) $router->getRequestedArgs($request)),
986 'name' => __(
'manager.website'),
987 'url' => $router->url($request,
null,
'management',
'settings',
'website'),
988 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'website', (array) $router->getRequestedArgs($request)),
991 'name' => __(
'manager.workflow'),
992 'url' => $router->url($request,
null,
'management',
'settings',
'workflow'),
993 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'workflow', (array) $router->getRequestedArgs($request)),
996 'name' => __(
'manager.distribution'),
997 'url' => $router->url($request,
null,
'management',
'settings',
'distribution'),
998 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'distribution', (array) $router->getRequestedArgs($request)),
1001 'name' => __(
'navigation.access'),
1002 'url' => $router->url($request,
null,
'management',
'settings',
'access'),
1003 'isCurrent' => $router->getRequestedPage($request) ===
'management' && in_array(
'access', (array) $router->getRequestedArgs($request)),
1008 'name' => __(
'navigation.tools'),
1009 'url' => $router->url($request,
null,
'management',
'tools'),
1010 'isCurrent' => $router->getRequestedPage($request) ===
'management' && $router->getRequestedOp($request) ===
'tools',
1014 if (in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
1016 'name' => __(
'navigation.admin'),
1017 'url' => $router->url($request,
'index',
'admin'),
1018 'isCurrent' => $router->getRequestedPage($request) ===
'admin',
1025 'tasksUrl' => $tasksUrl,
1026 'unreadTasksCount' => $unreadTasksCount,
1030 'availableContexts' => $availableContexts,
1031 'hasSystemNotifications' => $notifications->getCount() > 0,
1042 function fetch($template =
null, $cache_id =
null, $compile_id =
null, $parent =
null) {
1045 if (!$compile_id) $compile_id = $this->
getCompileId($template);
1049 if (
HookRegistry::call(
'TemplateManager::fetch', [$this, $template, $cache_id, $compile_id, &$result]))
return $result;
1051 return parent::fetch($template, $cache_id, $compile_id, $parent);
1061 function fetchAjax($id, $url, $element =
'div') {
1080 $context = $this->_request->getContext();
1081 if (is_a($context,
'Context')) {
1082 $resourceName .= $context->getData(
'themePluginPath');
1086 return sha1($resourceName);
1095 function fetchJson($template, $status =
true) {
1096 import(
'lib.pkp.classes.core.JSONMessage');
1103 function display($template =
null, $cache_id =
null, $compile_id =
null, $parent =
null) {
1107 if (!empty($this->_constants)) {
1108 $output .=
'pkp.const = ' . json_encode($this->_constants) .
';';
1110 if (!empty($this->_localeKeys)) {
1111 $output .=
'pkp.localeKeys = ' . json_encode($this->_localeKeys) .
';';
1116 $user = $this->_request->getUser();
1119 $userGroupsResult = $userGroupDao->getByUserId($user->getId());
1121 while ($userGroup = $userGroupsResult->next()) {
1122 $userRoles[] = (int) $userGroup->getRoleId();
1125 'csrfToken' => $this->_request->getSession()->getCSRFToken(),
1126 'id' => (int) $user->getId(),
1127 'roles' => array_values(array_unique($userRoles)),
1129 $output .=
'pkp.currentUser = ' . json_encode($currentUser) .
';';
1137 'priority' => STYLE_SEQUENCE_LATE,
1138 'contexts' => [
'backend'],
1153 $this->assign(
'state', $this->_state);
1159 header(
'Content-Type: text/html; charset=' .
Config::getVar(
'i18n',
'client_charset'));
1160 header(
'Cache-Control: ' . $this->_cacheability);
1163 if (!$compile_id) $compile_id = $this->
getCompileId($template);
1166 parent::display($template, $cache_id, $compile_id, $parent);
1174 $this->clearCompiledTemplate();
1175 $this->clearAllCache();
1183 $files = scandir($cacheDirectory);
1199 $newContextOrSite = $args[0];
1200 $contextOrSite = $args[1];
1201 if ($newContextOrSite->getData(
'themePluginPath') !== $contextOrSite->getData(
'themePluginPath')) {
1212 static function &
getManager($request =
null) {
1213 if (!isset($request)) {
1215 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call without request object.');
1217 assert(is_a($request,
'PKPRequest'));
1221 if ($instance ===
null) {
1224 if (empty($themes)) {
1227 $instance->initialize($request);
1239 import(
'lib.pkp.classes.form.FormBuilderVocabulary');
1256 $params =& $args[0];
1257 $smarty =& $args[1];
1258 $output =& $args[2];
1260 if ($this->_request->getContext()) {
1261 $blocks = $this->_request->getContext()->getData(
'sidebar');
1263 $blocks = $this->_request->getSite()->getData(
'sidebar');
1266 if (empty($blocks)) {
1271 if (empty($plugins)) {
1275 foreach ($blocks as $pluginName) {
1276 if (!empty($plugins[$pluginName])) {
1277 $output .= $plugins[$pluginName]->getContents($smarty, $this->_request);
1301 if (isset($params) && !empty($params)) {
1302 if (!isset($params[
'key']))
return __(
'');
1304 $key = $params[
'key'];
1305 unset($params[
'key']);
1306 if (isset($params[
'params']) && is_array($params[
'params'])) {
1307 $paramsArray = $params[
'params'];
1308 unset($params[
'params']);
1309 $params = array_merge($params, $paramsArray);
1311 return __($key, $params);
1324 assert(isset($params[
'id']));
1326 $id = $params[
'id'];
1327 $key = isset($params[
'key'])?$params[
'key']:
null;
1328 $hoverTitle = isset($params[
'hoverTitle'])?
true:
false;
1329 $image = isset($params[
'image'])?$params[
'image']:
null;
1330 $translate = isset($params[
'translate'])?
false:
true;
1332 import(
'lib.pkp.classes.linkAction.request.NullAction');
1333 import(
'lib.pkp.classes.linkAction.LinkAction');
1334 $key = $translate ? __($key) : $key;
1339 $this->assign(
'hoverTitle', $hoverTitle);
1340 return $this->
fetch(
'linkAction/linkAction.tpl');
1351 assert(isset($params[
'file']));
1353 $params = array_merge(
1357 'textKey' =>
'help.help',
1365 'helpFile' => $params[
'file'],
1366 'helpSection' => $params[
'section'],
1367 'helpTextKey' => $params[
'textKey'],
1368 'helpText' => $params[
'text'],
1369 'helpClass' => $params[
'class'],
1372 return $this->
fetch(
'common/helpLink.tpl');
1384 if (isset($params[
'options'])) {
1385 if (isset($params[
'translateValues'])) {
1388 foreach ($params[
'options'] as $k => $v) {
1389 $newOptions[__($k)] = __($v);
1391 $params[
'options'] = $newOptions;
1394 $params[
'options'] = array_map(
'AppLocale::translate', $params[
'options']);
1398 if (isset($params[
'output'])) {
1399 $params[
'output'] = array_map(
'AppLocale::translate', $params[
'output']);
1402 if (isset($params[
'values']) && isset($params[
'translateValues'])) {
1403 $params[
'values'] = array_map(
'AppLocale::translate', $params[
'values']);
1406 require_once(
'lib/pkp/lib/vendor/smarty/smarty/libs/plugins/function.html_options.php');
1407 return smarty_function_html_options($params, $smarty);
1418 function smartyIterate($params, $content, $smarty, &$repeat) {
1419 $iterator = $smarty->getTemplateVars($params[
'from']);
1421 if (isset($params[
'key'])) {
1422 if (empty($content)) $smarty->assign($params[
'key'], 1);
1423 else $smarty->assign($params[
'key'], $smarty->getTemplateVars($params[
'key'])+1);
1427 if (!$iterator || $iterator->eof()) {
1428 if (!$repeat)
return $content;
1435 if (isset($params[
'key'])) {
1436 list($key, $value) = $iterator->nextWithKey();
1437 $smarty->assign($params[
'item'], $value);
1438 $smarty->assign($params[
'key'], $key);
1440 $smarty->assign($params[
'item'], $iterator->next());
1452 $iterator = $params[
'iterator'];
1454 if (isset($params[
'itemsPerPage'])) {
1455 $itemsPerPage = $params[
'itemsPerPage'];
1457 $itemsPerPage = $smarty->getTemplateVars(
'itemsPerPage');
1458 if (!is_numeric($itemsPerPage)) $itemsPerPage=25;
1461 $page = $iterator->getPage();
1462 $pageCount = $iterator->getPageCount();
1463 $itemTotal = $iterator->getCount();
1465 if ($pageCount<1)
return '';
1467 $from = (($page - 1) * $itemsPerPage) + 1;
1468 $to = min($itemTotal, $page * $itemsPerPage);
1470 return __(
'navigation.items', [
1471 'from' => ($to===0?0:$from),
1473 'total' => $itemTotal
1487 while (ob_get_level()) {
1517 function smartyUrl($parameters, $smarty) {
1518 if ( !isset($parameters[
'context']) ) {
1525 foreach ($contextList as $contextName) {
1526 if (isset($parameters[$contextName])) {
1527 $context[$contextName] = $parameters[$contextName];
1528 unset($parameters[$contextName]);
1530 $context[$contextName] =
null;
1533 $parameters[
'context'] = $context;
1539 $paramList = [
'params',
'router',
'context',
'page',
'component',
'op',
'path',
'anchor',
'escape'];
1540 foreach ($paramList as $parameter) {
1541 if (isset($parameters[$parameter])) {
1542 $$parameter = $parameters[$parameter];
1543 unset($parameters[$parameter]);
1551 $parameters = array_merge($parameters, (array) $params);
1554 if (is_null($router)) {
1555 if (is_a($this->_request->getRouter(),
'PKPComponentRouter')) {
1556 $router = ROUTE_COMPONENT;
1558 $router = ROUTE_PAGE;
1564 $routerShortcuts = array_keys($dispatcher->getRouterNames());
1565 assert(in_array($router, $routerShortcuts));
1573 case ROUTE_COMPONENT:
1574 $handler = $component;
1583 return $dispatcher->url($this->_request, $router, $context, $handler,
$op, $path, $parameters, $anchor, !isset($escape) || $escape);
1605 $page = $parameters[
'value'] ??
'';
1606 if ($smarty->get_template_vars(
'currentContext')) {
1607 $siteTitle = $smarty->get_template_vars(
'currentContext')->getLocalizedData(
'name');
1608 } elseif ($smarty->get_template_vars(
'siteTitle')) {
1609 $siteTitle = $smarty->get_template_vars(
'siteTitle');
1611 $siteTitle = __(
'common.software');
1614 if (empty($parameters[
'value'])) {
1618 return $parameters[
'value'] . __(
'common.titleSeparator') . $siteTitle;
1632 $iterator = $params[
'iterator'];
1633 $name = $params[
'name'];
1634 if (isset($params[
'params']) && is_array($params[
'params'])) {
1635 $extraParams = $params[
'params'];
1636 unset($params[
'params']);
1637 $params = array_merge($params, $extraParams);
1639 if (isset($params[
'anchor'])) {
1640 $anchor = $params[
'anchor'];
1641 unset($params[
'anchor']);
1645 if (isset($params[
'all_extra'])) {
1646 $allExtra =
' ' . $params[
'all_extra'];
1647 unset($params[
'all_extra']);
1652 unset($params[
'iterator']);
1653 unset($params[
'name']);
1655 $numPageLinks = $smarty->getTemplateVars(
'numPageLinks');
1656 if (!is_numeric($numPageLinks)) $numPageLinks=10;
1658 $page = $iterator->getPage();
1659 $pageCount = $iterator->getPageCount();
1661 $pageBase = max($page - floor($numPageLinks / 2), 1);
1662 $paramName = $name .
'Page';
1664 if ($pageCount<=1)
return '';
1668 $router = $this->_request->getRouter();
1669 $requestedArgs =
null;
1670 if (is_a($router,
'PageRouter')) {
1671 $requestedArgs = $router->getRequestedArgs($this->_request);
1675 $params[$paramName] = 1;
1676 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'><<</a> ';
1677 $params[$paramName] = $page - 1;
1678 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'><</a> ';
1681 for ($i=$pageBase; $i<min($pageBase+$numPageLinks, $pageCount+1); $i++) {
1683 $value .=
"<strong>$i</strong> ";
1685 $params[$paramName] = $i;
1686 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>' . $i .
'</a> ';
1689 if ($page < $pageCount) {
1690 $params[$paramName] = $page + 1;
1691 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>></a> ';
1692 $params[$paramName] = $pageCount;
1693 $value .=
'<a href="' . $this->_request->url(
null,
null,
null, $requestedArgs, $params, $anchor) .
'"' . $allExtra .
'>>></a> ';
1703 return func_get_args();
1710 $args = func_get_args();
1711 return implode(
'', $args);
1721 function smartyCompare($a, $b, $strict =
false, $invert =
false) {
1722 $result = $strict?$a===$b:$a==$b;
1723 return $invert?!$result:$result;
1730 return strtotime($string);
1737 return explode($separator, $string);
1744 function smartyEscape($string, $esc_type =
'html', $char_set =
'ISO-8859-1') {
1745 $pattern =
"/(:|\.|\[|\]|,|=|@)/";
1746 $replacement =
"\\\\\\\\$1";
1747 switch ($esc_type) {
1754 $result = smarty_modifier_escape($string,
'html', $char_set);
1755 $result = preg_replace($pattern, $replacement, $result);
1759 $result = smarty_modifier_escape($string,
'javascript', $char_set);
1760 $result = preg_replace($pattern, $replacement, $result);
1764 return smarty_modifier_escape($string, $esc_type, $char_set);
1778 if (!isset($params[
'el'])) {
1779 throw new Exception(
"el parameter is missing from load_url_in_el");
1781 if (!isset($params[
'url'])) {
1782 throw new Exception(
"url parameter is missing from load_url_in_el");
1784 if (!isset($params[
'id'])) {
1785 throw new Exception(
"id parameter is missing from load_url_in_el");
1789 'inEl' => $params[
'el'],
1790 'inElUrl' => $params[
'url'],
1791 'inElElId' => $params[
'id'],
1792 'inElClass' => isset($params[
'class'])?$params[
'class']:
null,
1793 'refreshOn' => isset($params[
'refreshOn'])?$params[
'refreshOn']:
null,
1796 if (isset($params[
'placeholder'])) {
1797 $this->assign(
'inElPlaceholder', $params[
'placeholder']);
1798 } elseif (isset($params[
'loadMessageId'])) {
1799 $loadMessageId = $params[
'loadMessageId'];
1800 $this->assign(
'inElPlaceholder', __($loadMessageId, $params));
1802 $this->assign(
'inElPlaceholder', $this->
fetch(
'common/loadingContainer.tpl'));
1805 return $this->
fetch(
'common/urlInEl.tpl');
1818 $params[
'el'] =
'div';
1831 $csrfToken = $this->_request->getSession()->getCSRFToken();
1832 switch (isset($params[
'type'])?$params[
'type']:
null) {
1833 case 'raw':
return $csrfToken;
1837 return '<input type="hidden" name="csrfToken" value="' . htmlspecialchars($csrfToken) .
'">';
1851 if (empty($params[
'context'])) {
1852 $params[
'context'] =
'frontend';
1855 if (!defined(
'SESSION_DISABLE_INIT')) {
1857 $appVersion = $versionDao->getCurrentVersion()->getVersionString();
1858 }
else $appVersion =
null;
1862 ksort($stylesheets);
1865 foreach($stylesheets as $priorityList) {
1866 foreach($priorityList as $style) {
1867 if (!empty($style[
'inline'])) {
1868 $output .=
'<style type="text/css">' . $style[
'style'] .
'</style>';
1870 if ($appVersion && strpos($style[
'style'],
'?') ===
false) {
1871 $style[
'style'] .=
'?v=' . $appVersion;
1873 $output .=
'<link rel="stylesheet" href="' . $style[
'style'] .
'" type="text/css" />';
1892 if (empty($htmlContent)) {
1893 return $htmlContent;
1896 $hasEmbeddedStyle =
false;
1897 foreach ($embeddedFiles as $embeddedFile) {
1898 if ($embeddedFile->getFileType() ===
'text/css') {
1899 $hasEmbeddedStyle =
true;
1904 if ($hasEmbeddedStyle) {
1905 return $htmlContent;
1911 if (!empty($styles)) {
1913 foreach ($styles as $priorityGroup) {
1914 foreach ($priorityGroup as $htmlStyle) {
1915 $links .=
'<link rel="stylesheet" href="' . $htmlStyle[
'style'] .
'" type="text/css">' .
"\n";
1920 return str_ireplace(
'<head>',
'<head>' .
"\n" . $links, $htmlContent);
1933 if (empty($params[
'context'])) {
1934 $params[
'context'] =
'frontend';
1937 if (!defined(
'SESSION_DISABLE_INIT')) {
1939 $appVersion = defined(
'SESSION_DISABLE_INIT') ? null : $versionDao->getCurrentVersion()->getVersionString();
1940 }
else $appVersion =
null;
1947 foreach($scripts as $priorityList) {
1948 foreach($priorityList as $name => $data) {
1949 if ($data[
'inline']) {
1950 $output .=
'<script type="text/javascript">' . $data[
'script'] .
'</script>';
1952 if ($appVersion && strpos($data[
'script'],
'?') ===
false) {
1953 $data[
'script'] .=
'?v=' . $appVersion;
1955 $output .=
'<script src="' . $data[
'script'] .
'" type="text/javascript"></script>';
1973 if (empty($params[
'context'])) {
1974 $params[
'context'] =
'frontend';
1982 foreach($headers as $priorityList) {
1983 foreach($priorityList as $name => $data) {
1984 $output .=
"\n" . $data[
'header'];
2000 $areaName = $params[
'name'];
2001 $declaredMenuTemplatePath = $params[
'path'];
2002 $currentContext = $this->_request->getContext();
2003 $contextId = CONTEXT_ID_NONE;
2004 if ($currentContext) {
2005 $contextId = $currentContext->getId();
2010 if (empty($themePlugins)) {
2013 $activeThemeNavigationAreas = [];
2014 foreach ($themePlugins as $themePlugin) {
2015 if ($themePlugin->isActive()) {
2016 $areas = $themePlugin->getMenuAreas();
2017 if (!in_array($areaName, $areas)) {
2023 $menuTemplatePath =
'frontend/components/navigationMenu.tpl';
2024 if (isset($declaredMenuTemplatePath)) {
2025 $menuTemplatePath = $declaredMenuTemplatePath;
2031 $navigationMenus = $navigationMenuDao->getByArea($contextId, $areaName)->toArray();
2032 if (isset($navigationMenus[0])) {
2033 $navigationMenu = $navigationMenus[0];
2034 import(
'classes.core.Services');
2035 Services::get(
'navigationMenu')->getMenuTree($navigationMenu);
2040 'navigationMenu' => $navigationMenu,
2041 'id' => $params[
'id'],
2042 'ulClass' => $params[
'ulClass'],
2043 'liClass' => $params[
'liClass'],
2046 return $this->
fetch($menuTemplatePath);
2061 if (array_key_exists($context, $resources)) {
2062 $matches = $resources[$context];
2065 $page = $this->getTemplateVars(
'requestedPage');
2066 $page = empty( $page ) ?
'index' : $page;
2067 $op = $this->getTemplateVars(
'requestedOp');
2071 join(
'-', [$context, $page]),
2072 join(
'-', [$context, $page,
$op]),
2075 foreach($contexts as $context) {
2076 if (array_key_exists($context, $resources)) {
2077 foreach ($resources[$context] as $priority => $priorityList) {
2078 if (!array_key_exists($priority, $matches)) {
2079 $matches[$priority] = [];
2081 $matches[$priority] = array_merge($matches[$priority], $resources[$context][$priority]);
2083 $matches += $resources[$context];
2102 if (empty($params[
'assign'])) {
2103 error_log(
'Smarty: {pluck_files} function called without required `assign` param. Called in ' . __FILE__ .
':' . __LINE__);
2108 if (!is_array($params[
'files'])) {
2109 error_log(
'Smarty: {pluck_files} function called without required `files` param. Called in ' . __FILE__ .
':' . __LINE__);
2110 $smarty->assign($params[
'assign'], []);
2115 if (empty($params[
'by'])) {
2116 error_log(
'Smarty: {pluck_files} function called without required `by` param. Called in ' . __FILE__ .
':' . __LINE__);
2117 $smarty->assign($params[
'assign'], []);
2127 if (!in_array($params[
'by'], [
'chapter',
'publicationFormat',
'component',
'fileExtension',
'genre'])) {
2128 error_log(
'Smarty: {pluck_files} function called without a valid `by` param. Called in ' . __FILE__ .
':' . __LINE__);
2129 $smarty->assign($params[
'assign'], []);
2134 if (!isset($params[
'value'])) {
2135 error_log(
'Smarty: {pluck_files} function called without required `value` param. Called in ' . __FILE__ .
':' . __LINE__);
2136 $smarty->assign($params[
'assign'], []);
2140 $matching_files = [];
2143 foreach ($params[
'files'] as $file) {
2144 switch ($params[
'by']) {
2147 $genre = $genreDao->getById($file->getGenreId());
2148 if (!$genre->getDependent() && method_exists($file,
'getChapterId')) {
2149 if ($params[
'value'] ===
'any' && $file->getChapterId()) {
2150 $matching_files[] = $file;
2151 } elseif($file->getChapterId() == $params[
'value']) {
2152 $matching_files[] = $file;
2153 } elseif ($params[
'value'] == 0 && !$file->getChapterId()) {
2154 $matching_files[] = $file;
2159 case 'publicationFormat':
2160 if ($file->getAssocId() == $params[
'value']) {
2161 $matching_files[] = $file;
2166 if (get_class($file) == $params[
'value']) {
2167 $matching_files[] = $file;
2171 case 'fileExtension':
2172 if ($file->getExtension() == $params[
'value']) {
2173 $matching_files[] = $file;
2178 if ($file->getGenreId() == $params[
'value']) {
2179 $matching_files[] = $file;
2185 $smarty->assign($params[
'assign'], $matching_files);
2193 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call to Smarty2 function ' . __FUNCTION__);
2194 return $this->getTemplateVars($varname);
2204 public function register_function($name, $impl, $cacheable =
true, $cache_attrs =
null) {
2205 if (
Config::getVar(
'debug',
'deprecation_warnings')) trigger_error(
'Deprecated call to Smarty2 function ' . __FUNCTION__);
2206 $this->registerPlugin(
'function', $name, $impl, $cacheable, $cache_attrs);