Open Preprint Systems  3.3.0
PKPTemplateManager.inc.php
1 <?php
2 
22 /* This definition is required by Smarty */
23 define('SMARTY_DIR', Core::getBaseDir() . '/lib/pkp/lib/vendor/smarty/smarty/libs/');
24 
25 require_once('./lib/pkp/lib/vendor/smarty/smarty/libs/plugins/modifier.escape.php'); // Seems to be needed?
26 
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');
32 
33 define('STYLE_SEQUENCE_CORE', 0);
34 define('STYLE_SEQUENCE_NORMAL', 10);
35 define('STYLE_SEQUENCE_LATE', 15);
36 define('STYLE_SEQUENCE_LAST', 20);
37 
38 define('CDN_JQUERY_VERSION', '3.3.1');
39 define('CDN_JQUERY_UI_VERSION', '1.12.0');
40 
41 define('CSS_FILENAME_SUFFIX', 'css');
42 
43 define('PAGE_WIDTH_NARROW', 'narrow');
44 define('PAGE_WIDTH_NORMAL', 'normal');
45 define('PAGE_WIDTH_WIDE', 'wide');
46 define('PAGE_WIDTH_FULL', 'full');
47 
48 import('lib.pkp.classes.template.PKPTemplateResource');
49 
50 class PKPTemplateManager extends Smarty {
52  private $_styleSheets = [];
53 
55  private $_javaScripts = [];
56 
58  private $_htmlHeaders = [];
59 
61  private $_constants = [];
62 
64  private $_localeKeys = [];
65 
67  private $_state = [];
68 
70  private $_cacheability;
71 
73  private $_fbv;
74 
76  private $_request;
77 
82  function __construct() {
83  parent::__construct();
84 
85  // Set up Smarty configuration
86  $baseDir = Core::getBaseDir();
87  $cachePath = CacheManager::getFileCachePath();
88 
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';
92 
93  $this->_cacheability = CACHEABILITY_NO_STORE; // Safe default
94 
95  // Register the template resources.
96  $this->registerResource('core', new PKPTemplateResource($coreTemplateDir = 'lib' . DIRECTORY_SEPARATOR . 'pkp' . DIRECTORY_SEPARATOR . 'templates'));
97  $this->registerResource('app', new PKPTemplateResource(['templates', $coreTemplateDir]));
98  $this->default_resource_type = 'app';
99 
100  $this->error_reporting = E_ALL & ~E_NOTICE;
101  }
102 
107  function initialize($request) {
108  assert(is_a($request, 'PKPRequest'));
109  $this->_request = $request;
110 
111  $locale = AppLocale::getLocale();
112  $application = Application::get();
113  $router = $request->getRouter();
114  assert(is_a($router, 'PKPRouter'));
115 
116  AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON, LOCALE_COMPONENT_PKP_COMMON);
117  $currentContext = $request->getContext();
118 
119  $this->assign([
120  'defaultCharset' => Config::getVar('i18n', 'client_charset'),
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'),
127  'timeFormat' => Config::getVar('general', 'time_format'),
128  'currentContext' => $currentContext,
129  'currentLocale' => $locale,
130  'currentLocaleLangDir' => AppLocale::getLocaleDirection($locale),
131  'applicationName' => __($application->getNameKey()),
132  ]);
133 
134  // Assign meta tags
135  if ($currentContext) {
136  $favicon = $currentContext->getLocalizedFavicon();
137  if (!empty($favicon)) {
138  $publicFileManager = new PublicFileManager();
139  $faviconDir = $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($currentContext->getId());
140  $this->addHeader('favicon', '<link rel="icon" href="' . $faviconDir . '/' . $favicon['uploadName'] . '">');
141  }
142  }
143 
144  if (Config::getVar('general', 'installed')) {
145  $activeTheme = null;
146  $contextOrSite = $currentContext ? $currentContext : $request->getSite();
147  $allThemes = PluginRegistry::getPlugins('themes');
148  foreach ($allThemes as $theme) {
149  if ($contextOrSite->getData('themePluginPath') === $theme->getDirName()) {
150  $activeTheme = $theme;
151  break;
152  }
153  }
154  $this->assign(['activeTheme' => $activeTheme]);
155  }
156 
157  if (is_a($router, 'PKPPageRouter')) {
158  $this->assign([
159  'requestedPage' => $router->getRequestedPage($request),
160  'requestedOp' => $router->getRequestedOp($request),
161  ]);
162 
163  // A user-uploaded stylesheet
164  if ($currentContext) {
165  $contextStyleSheet = $currentContext->getData('styleSheet');
166  if ($contextStyleSheet) {
167  import('classes.file.PublicFileManager');
168  $publicFileManager = new PublicFileManager();
169  $this->addStyleSheet(
170  'contextStylesheet',
171  $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($currentContext->getId()) . '/' . $contextStyleSheet['uploadName'],
172  ['priority' => STYLE_SEQUENCE_LATE]
173  );
174  }
175  }
176 
177  // Register recaptcha on relevant pages
178  if (Config::getVar('captcha', 'recaptcha') && Config::getVar('captcha', 'captcha_on_register')) {
179  $this->addJavaScript(
180  'recaptcha',
181  'https://www.recaptcha.net/recaptcha/api.js?hl=' . substr(AppLocale::getLocale(),0,2),
182  [
183  'contexts' => ['frontend-user-register', 'frontend-user-registerUser'],
184  ]
185  );
186  }
187 
188  // Register meta tags
189  if (Config::getVar('general', 'installed')) {
190  if (($request->getRequestedPage()=='' || $request->getRequestedPage() == 'index') && $currentContext && $currentContext->getLocalizedData('searchDescription')) {
191  $this->addHeader('searchDescription', '<meta name="description" content="' . $currentContext->getLocalizedData('searchDescription') . '">');
192  }
193 
194  $this->addHeader(
195  'generator',
196  '<meta name="generator" content="' . __($application->getNameKey()) . ' ' . $application->getCurrentVersion()->getVersionString(false) . '">',
197  [
198  'contexts' => ['frontend', 'backend'],
199  ]
200  );
201 
202  if ($currentContext) {
203  $customHeaders = $currentContext->getLocalizedData('customHeaders');
204  if (!empty($customHeaders)) {
205  $this->addHeader('customHeaders', $customHeaders);
206  }
207  }
208  }
209 
210  if ($currentContext && !$currentContext->getEnabled()) {
211  $this->addHeader(
212  'noindex',
213  '<meta name="robots" content="noindex,nofollow">',
214  [
215  'contexts' => ['frontend', 'backend'],
216  ]
217  );
218  }
219 
220  // Register Navigation Menus
221  import('classes.core.Services');
222  $nmService = Services::get('navigationMenu');
223 
224  if (Config::getVar('general', 'installed')) {
225  \HookRegistry::register('LoadHandler', [$nmService, '_callbackHandleCustomNavigationMenuItems']);
226  }
227  }
228 
229  // Register custom functions
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']);
251 
252  $this->registerPlugin('function','title', [$this, 'smartyTitle']);
253  $this->registerPlugin('function', 'url', [$this, 'smartyUrl']);
254 
255  // load stylesheets/scripts/headers from a given context
256  $this->registerPlugin('function', 'load_stylesheet', [$this, 'smartyLoadStylesheet']);
257  $this->registerPlugin('function', 'load_script', [$this, 'smartyLoadScript']);
258  $this->registerPlugin('function', 'load_header', [$this, 'smartyLoadHeader']);
259 
260  // load NavigationMenu Areas from context
261  $this->registerPlugin('function', 'load_menu', [$this, 'smartyLoadNavigationMenuArea']);
262 
263  // Load form builder vocabulary
264  $fbv = $this->getFBV();
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());
271 
272  // ajax load into a div or any element
273  $this->registerPlugin('function', 'load_url_in_el', [$this, 'smartyLoadUrlInEl']);
274  $this->registerPlugin('function', 'load_url_in_div', [$this, 'smartyLoadUrlInDiv']);
275 
276  // Always pass these ListBuilder constants to the browser
277  // because a ListBuilder may be loaded in an ajax request
278  // and won't have an opportunity to pass its constants to
279  // the template manager. This is not a recommended practice,
280  // but these are the only constants from a controller that are
281  // required on the frontend. We can remove them once the
282  // ListBuilderHandler is no longer needed.
283  import('lib.pkp.classes.controllers.listbuilder.ListbuilderHandler');
284  $this->setConstants([
285  'LISTBUILDER_SOURCE_TYPE_TEXT',
286  'LISTBUILDER_SOURCE_TYPE_SELECT',
287  'LISTBUILDER_OPTGROUP_LABEL',
288  ]);
289 
294  if (!defined('SESSION_DISABLE_INIT')) {
295  $this->assign([
296  'isUserLoggedIn' => Validation::isLoggedIn(),
297  'isUserLoggedInAs' => Validation::isLoggedInAs(),
298  'itemsPerPage' => Config::getVar('interface', 'items_per_page'),
299  'numPageLinks' => Config::getVar('interface', 'page_links'),
300  'siteTitle' => $request->getSite()->getLocalizedData('title'),
301  ]);
302 
303  $user = $request->getUser();
304  if ($user) {
305  $this->assign([
306  'currentUser' => $user,
307  ]);
308 
309  // Assign the user name to be used in the sitenav
310  $this->assign([
311  'loggedInUsername' => $user->getUserName(),
312  ]);
313  }
314  }
315 
316  if (Config::getVar('general', 'installed')) {
317  // Respond to the sidebar hook
318  if ($currentContext) {
319  $this->assign('hasSidebar', !empty($currentContext->getData('sidebar')));
320  } else {
321  $this->assign('hasSidebar', !empty($request->getSite()->getData('sidebar')));
322  }
323  HookRegistry::register('Templates::Common::Sidebar', [$this, 'displaySidebar']);
324 
325  // Clear the cache whenever the active theme is changed
326  HookRegistry::register('Context::edit', [$this, 'clearThemeTemplateCache']);
327  HookRegistry::register('Site::edit', [$this, 'clearThemeTemplateCache']);
328  }
329  }
330 
331 
336  function setCacheability($cacheability = CACHEABILITY_PUBLIC) {
337  $this->_cacheability = $cacheability;
338  }
339 
350  public function compileLess($name, $lessFile, $args = []) {
351  $less = new Less_Parser([
352  'relativeUrls' => false,
353  'compress' => true,
354  ]);
355 
356  $request = $this->_request;
357 
358  // Allow plugins to intervene
359  HookRegistry::call('PageHandler::compileLess', [&$less, &$lessFile, &$args, $name, $request]);
360 
361  // Read the stylesheet
362  $less->parseFile($lessFile);
363 
364  // Add extra LESS files before compiling
365  if (isset($args['addLess']) && is_array($args['addLess'])) {
366  foreach ($args['addLess'] as $addless) {
367  $less->parseFile($addless);
368  }
369  }
370 
371  // Add extra LESS variables before compiling
372  if (isset($args['addLessVariables'])) {
373  foreach ((array) $args['addLessVariables'] as $addlessVariables) {
374  $less->parse($addlessVariables);
375  }
376  }
377 
378  // Set the @baseUrl variable
379  $baseUrl = !empty($args['baseUrl']) ? $args['baseUrl'] : $request->getBaseUrl(true);
380  $less->parse("@baseUrl: '$baseUrl';");
381 
382  return $less->getCSS();
383  }
384 
392  public function cacheLess($path, $styles) {
393  if (file_put_contents($path, $styles) === false) {
394  error_log("Unable to write \"$path\".");
395  return false;
396  }
397 
398  return true;
399  }
400 
407  public function getCachedLessFilePath($name) {
408  $cacheDirectory = CacheManager::getFileCachePath();
409  $context = $this->_request->getContext();
410  $contextId = is_a($context, 'Context') ? $context->getId() : 0;
411  return $cacheDirectory . DIRECTORY_SEPARATOR . $contextId . '-' . $name . '.css';
412  }
413 
428  function addStyleSheet($name, $style, $args = []) {
429 
430  $args = array_merge(
431  [
432  'priority' => STYLE_SEQUENCE_NORMAL,
433  'contexts' => ['frontend'],
434  'inline' => false,
435  ],
436  $args
437  );
438 
439  $args['contexts'] = (array) $args['contexts'];
440  foreach($args['contexts'] as $context) {
441  $this->_styleSheets[$context][$args['priority']][$name] = [
442  'style' => $style,
443  'inline' => $args['inline'],
444  ];
445  }
446  }
447 
462  function addJavaScript($name, $script, $args = []) {
463 
464  $args = array_merge(
465  [
466  'priority' => STYLE_SEQUENCE_NORMAL,
467  'contexts' => ['frontend'],
468  'inline' => false,
469  ],
470  $args
471  );
472 
473  $args['contexts'] = (array) $args['contexts'];
474  foreach($args['contexts'] as $context) {
475  $this->_javaScripts[$context][$args['priority']][$name] = [
476  'script' => $script,
477  'inline' => $args['inline'],
478  ];
479  }
480  }
481 
493  function addHeader($name, $header, $args = []) {
494 
495  $args = array_merge(
496  [
497  'priority' => STYLE_SEQUENCE_NORMAL,
498  'contexts' => ['frontend'],
499  ],
500  $args
501  );
502 
503  $args['contexts'] = (array) $args['contexts'];
504  foreach($args['contexts'] as $context) {
505  $this->_htmlHeaders[$context][$args['priority']][$name] = [
506  'header' => $header,
507  ];
508  }
509  }
510 
516  function setConstants($names) {
517  foreach ($names as $name) {
518  $this->_constants[$name] = constant($name);
519  }
520  }
521 
527  function setLocaleKeys($keys) {
528  foreach ($keys as $key) {
529  if (!array_key_exists($key, $this->_localeKeys)) {
530  $this->_localeKeys[$key] = __($key);
531  }
532  }
533  }
534 
541  function getState($key) {
542  return array_key_exists($key, $this->_state)
543  ? $this->_state[$key]
544  : null;
545  }
546 
552  function setState($data) {
553  $this->_state = array_merge($this->_state, $data);
554  }
555 
559  function registerJSLibrary() {
560  $baseUrl = $this->_request->getBaseUrl();
561  $localeChecks = [AppLocale::getLocale(), strtolower(substr(AppLocale::getLocale(), 0, 2))];
562 
563  // Common $args array used for all our core JS files
564  $args = [
565  'priority' => STYLE_SEQUENCE_CORE,
566  'contexts' => 'backend',
567  ];
568 
569  // Load jQuery validate separately because it can not be linted
570  // properly by our build script
571  $this->addJavaScript(
572  'jqueryValidate',
573  $baseUrl . '/lib/pkp/js/lib/jquery/plugins/validate/jquery.validate.min.js',
574  $args
575  );
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);
580  }
581  }
582 
583  $this->addJavaScript(
584  'plUpload',
585  $baseUrl . '/lib/pkp/lib/vendor/moxiecode/plupload/js/plupload.full.min.js',
586  $args
587  );
588  $this->addJavaScript(
589  'jQueryPlUpload',
590  $baseUrl . '/lib/pkp/lib/vendor/moxiecode/plupload/js/jquery.ui.plupload/jquery.ui.plupload.js',
591  $args
592  );
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);
597  }
598  }
599 
600  // Load new component library bundle
601  $this->addJavaScript(
602  'pkpApp',
603  $baseUrl . '/js/build.js',
604  [
605  'priority' => STYLE_SEQUENCE_LATE,
606  'contexts' => ['backend']
607  ]
608  );
609 
610  // Load minified file if it exists
611  if (Config::getVar('general', 'enable_minified')) {
612  $this->addJavaScript(
613  'pkpLib',
614  $baseUrl . '/js/pkp.min.js',
615  [
616  'priority' => STYLE_SEQUENCE_CORE,
617  'contexts' => ['backend']
618  ]
619  );
620  return;
621  }
622 
623  // Otherwise retrieve and register all script files
624  $minifiedScripts = array_filter(array_map('trim', file('registry/minifiedScripts.txt')), function($s) {
625  return strlen($s) && $s[0] != '#'; // Exclude empty and commented (#) lines
626  });
627  foreach ($minifiedScripts as $key => $script) {
628  $this->addJavaScript( 'pkpLib' . $key, "$baseUrl/$script", $args);
629  }
630  }
631 
642  function registerJSLibraryData() {
643 
644  $context = $this->_request->getContext();
645 
646  // Instantiate the namespace
647  $output = '$.pkp = $.pkp || {};';
648 
649  // Load data intended for general use by the app
650  import('lib.pkp.classes.security.Role');
651 
652  $app_data = [
653  'cdnEnabled' => Config::getVar('general', 'enable_cdn'),
654  'currentLocale' => AppLocale::getLocale(),
655  'primaryLocale' => AppLocale::getPrimaryLocale(),
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' : '',
663  ];
664 
665  $output .= '$.pkp.app = ' . json_encode($app_data) . ';';
666 
667  // Load exposed constants
668  $output .= '$.pkp.cons = ' . json_encode($this->_constants) . ';';
669 
670  // Allow plugins to load data within their own namespace
671  $output .= '$.pkp.plugins = {};';
672 
673  $this->addJavaScript(
674  'pkpLibData',
675  $output,
676  [
677  'priority' => STYLE_SEQUENCE_CORE,
678  'contexts' => 'backend',
679  'inline' => true,
680  ]
681  );
682  }
683 
687  function setupBackendPage() {
688 
689  $request = Application::get()->getRequest();
690  $dispatcher = $request->getDispatcher();
691  $router = $request->getRouter();
692 
693  if (empty($this->get_template_vars('pageComponent'))) {
694  $this->assign('pageComponent', 'Page');
695  }
696 
697  $this->setConstants([
698  'REALLY_BIG_NUMBER',
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',
707  'ROLE_ID_MANAGER',
708  'ROLE_ID_SITE_ADMIN',
709  'ROLE_ID_AUTHOR',
710  'ROLE_ID_REVIEWER',
711  'ROLE_ID_ASSISTANT',
712  'ROLE_ID_READER',
713  'ROLE_ID_SUB_EDITOR',
714  'ROLE_ID_SUBSCRIPTION_MANAGER',
715  ]);
716 
717  // Common locale keys available in the browser for every page
718  $this->setLocaleKeys([
719  'common.cancel',
720  'common.clearSearch',
721  'common.close',
722  'common.commaListSeparator',
723  'common.confirm',
724  'common.delete',
725  'common.edit',
726  'common.error',
727  'common.filter',
728  'common.filterAdd',
729  'common.filterRemove',
730  'common.loading',
731  'common.no',
732  'common.noItemsFound',
733  'common.none',
734  'common.ok',
735  'common.orderUp',
736  'common.orderDown',
737  'common.pageNumber',
738  'common.pagination.goToPage',
739  'common.pagination.label',
740  'common.pagination.next',
741  'common.pagination.previous',
742  'common.remove',
743  'common.required',
744  'common.save',
745  'common.saving',
746  'common.search',
747  'common.selectWithName',
748  'common.unknownError',
749  'common.view',
750  'common.viewLess',
751  'common.viewMore',
752  'common.viewWithName',
753  'common.yes',
754  'form.dataHasChanged',
755  'form.errorA11y',
756  'form.errorGoTo',
757  'form.errorMany',
758  'form.errorOne',
759  'form.errors',
760  'form.multilingualLabel',
761  'form.multilingualProgress',
762  'form.saved',
763  'help.help',
764  'navigation.backTo',
765  'validator.required'
766  ]);
767 
768  // Register the jQuery script
769  $min = Config::getVar('general', 'enable_minified') ? '.min' : '';
770  if (Config::getVar('general', 'enable_cdn')) {
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';
773  } else {
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';
776  }
777  $this->addJavaScript(
778  'jquery',
779  $jquery,
780  [
781  'priority' => STYLE_SEQUENCE_CORE,
782  'contexts' => 'backend',
783  ]
784  );
785  $this->addJavaScript(
786  'jqueryUI',
787  $jqueryUI,
788  [
789  'priority' => STYLE_SEQUENCE_CORE,
790  'contexts' => 'backend',
791  ]
792  );
793 
794  // Load Noto Sans font from Google Font CDN
795  // To load extended latin or other character sets, see:
796  // https://www.google.com/fonts#UsePlace:use/Collection:Noto+Sans
797  if (Config::getVar('general', 'enable_cdn')) {
798  $this->addStyleSheet(
799  'pkpLibNotoSans',
800  '//fonts.googleapis.com/css?family=Noto+Sans:400,400italic,700,700italic',
801  [
802  'priority' => STYLE_SEQUENCE_CORE,
803  'contexts' => 'backend',
804  ]
805  );
806  }
807 
808  // Register the pkp-lib JS library
809  $this->registerJSLibraryData();
810  $this->registerJSLibrary();
811 
812  // FontAwesome - http://fontawesome.io/
813  if (Config::getVar('general', 'enable_cdn')) {
814  $url = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css';
815  } else {
816  $url = $request->getBaseUrl() . '/lib/pkp/styles/fontawesome/fontawesome.css';
817  }
818  $this->addStyleSheet(
819  'fontAwesome',
820  $url,
821  [
822  'priority' => STYLE_SEQUENCE_CORE,
823  'contexts' => 'backend',
824  ]
825  );
826 
827  // Stylesheet compiled from Vue.js single-file components
828  $this->addStyleSheet(
829  'build',
830  $request->getBaseUrl() . '/styles/build.css',
831  [
832  'priority' => STYLE_SEQUENCE_CORE,
833  'contexts' => 'backend',
834  ]
835  );
836 
837  // The legacy stylesheet for the backend
838  $this->addStyleSheet(
839  'pkpLib',
840  $dispatcher->url($request, ROUTE_COMPONENT, null, 'page.PageHandler', 'css'),
841  [
842  'priority' => STYLE_SEQUENCE_CORE,
843  'contexts' => 'backend',
844  ]
845  );
846 
847  // If there's a locale-specific stylesheet, add it.
848  if (($localeStyleSheet = AppLocale::getLocaleStyleSheet(AppLocale::getLocale())) != null) {
849  $this->addStyleSheet(
850  'pkpLibLocale',
851  $request->getBaseUrl() . '/' . $localeStyleSheet,
852  [
853  'contexts' => ['backend'],
854  ]
855  );
856  }
857 
858  // Set up required state properties
859  $this->setState([
860  'menu' => [],
861  ]);
862 
867  if (Config::getVar('general', 'installed') && !defined('SESSION_DISABLE_INIT')) {
868 
869  if ($request->getUser()) {
870 
871  // Get a count of unread tasks
872  $notificationDao = DAORegistry::getDAO('NotificationDAO'); /* @var $notificationDao NotificationDAO */
873  import('lib.pkp.controllers.grid.notifications.TaskNotificationsGridHandler');
874  $unreadTasksCount = (int) $notificationDao->getNotificationCount(false, $request->getUser()->getId(), null, NOTIFICATION_LEVEL_TASK);
875 
876  // Get a URL to load the tasks grid
877  $tasksUrl = $request->getDispatcher()->url($request, ROUTE_COMPONENT, null, 'page.PageHandler', 'tasks');
878 
879  // Load system notifications in SiteHandler.js
880  $notificationDao = DAORegistry::getDAO('NotificationDAO'); /* @var $notificationDao NotificationDAO */
881  $notifications = $notificationDao->getByUserId($request->getUser()->getId(), NOTIFICATION_LEVEL_TRIVIAL);
882 
883  // Load context switcher
884  if (in_array(ROLE_ID_SITE_ADMIN, $this->get_template_vars('userRoles'))) {
885  $args = [];
886  } else {
887  $args = ['userId' => $request->getUser()->getId()];
888  }
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();
893  });
894  }
895  $requestedPage = $router->getRequestedPage($request);
896  foreach ($availableContexts as $availableContext) {
897  // Site admins redirected to the same page. Everyone else to submission lists
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));
900  } else {
901  $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath, 'submissions');
902  }
903  }
904 
905  // Create main navigation menu
906  $userRoles = (array) $router->getHandler()->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
907 
908  $menu = [];
909 
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',
916  ];
917  } elseif (count($userRoles) === 1 && in_array(ROLE_ID_READER, $userRoles)) {
918  AppLocale::requireComponents(LOCALE_COMPONENT_APP_AUTHOR);
919  $menu['submit'] = [
920  'name' => __('author.submit'),
921  'url' => $router->url($request, null, 'submission', 'wizard'),
922  'isCurrent' => $router->getRequestedPage($request) === 'submission',
923  ];
924  }
925 
926  if (count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR], $userRoles))) {
927  $menu['statistics'] = [
928  'name' => __('navigation.tools.statistics'),
929  'submenu' => [
930  'publications' => [
931  'name' => __('common.publications'),
932  'url' => $router->url($request, null, 'stats', 'publications', 'publications'),
933  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'publications',
934  ],
935  'editorial' => [
936  'name' => __('stats.editorialActivity'),
937  'url' => $router->url($request, null, 'stats', 'editorial', 'editorial'),
938  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'editorial',
939  ],
940  'users' => [
941  'name' => __('manager.users'),
942  'url' => $router->url($request, null, 'stats', 'users', 'users'),
943  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'users',
944  ]
945  ]
946  ];
947  }
948 
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)),
955  ];
956  }
957  $menu['statistics']['submenu'] += [
958  'reports' => [
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',
962  ]
963  ];
964  $menu['settings'] = [
965  'name' => __('navigation.settings'),
966  'submenu' => [
967  'context' => [
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)),
971  ],
972  'website' => [
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)),
976  ],
977  'workflow' => [
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)),
981  ],
982  'distribution' => [
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)),
986  ],
987  'access' => [
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)),
991  ]
992  ]
993  ];
994  $menu['tools'] = [
995  'name' => __('navigation.tools'),
996  'url' => $router->url($request, null, 'management', 'tools'),
997  'isCurrent' => $router->getRequestedPage($request) === 'management' && $router->getRequestedOp($request) === 'tools',
998  ];
999  }
1000 
1001  if (in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
1002  $menu['admin'] = [
1003  'name' => __('navigation.admin'),
1004  'url' => $router->url($request, 'index', 'admin'),
1005  'isCurrent' => $router->getRequestedPage($request) === 'admin',
1006  ];
1007  }
1008  }
1009 
1010  $this->setState([
1011  'menu' => $menu,
1012  'tasksUrl' => $tasksUrl,
1013  'unreadTasksCount' => $unreadTasksCount,
1014  ]);
1015 
1016  $this->assign([
1017  'availableContexts' => $availableContexts,
1018  'hasSystemNotifications' => $notifications->getCount() > 0,
1019  ]);
1020  }
1021  }
1022 
1023  HookRegistry::call('TemplateManager::setupBackendPage');
1024  }
1025 
1029  function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null) {
1030 
1031  // If no compile ID was assigned, get one.
1032  if (!$compile_id) $compile_id = $this->getCompileId($template);
1033 
1034  // Give hooks an opportunity to override
1035  $result = null;
1036  if (HookRegistry::call('TemplateManager::fetch', [$this, $template, $cache_id, $compile_id, &$result])) return $result;
1037 
1038  return parent::fetch($template, $cache_id, $compile_id, $parent);
1039  }
1040 
1048  function fetchAjax($id, $url, $element = 'div') {
1049  return new JSONMessage(true, $this->smartyLoadUrlInEl(
1050  [
1051  'url' => $url,
1052  'id' => $id,
1053  'el' => $element,
1054  ],
1055  $this
1056  ));
1057  }
1058 
1064  function getCompileId($resourceName) {
1065 
1066  if ( Config::getVar('general', 'installed' ) ) {
1067  $context = $this->_request->getContext();
1068  if (is_a($context, 'Context')) {
1069  $resourceName .= $context->getData('themePluginPath');
1070  }
1071  }
1072 
1073  return sha1($resourceName);
1074  }
1082  function fetchJson($template, $status = true) {
1083  import('lib.pkp.classes.core.JSONMessage');
1084  return new JSONMessage($status, $this->fetch($template));
1085  }
1086 
1090  function display($template = null, $cache_id = null, $compile_id = null, $parent = null) {
1092  // Output global constants and locale keys used in new component library
1093  $output = '';
1094  if (!empty($this->_constants)) {
1095  $output .= 'pkp.const = ' . json_encode($this->_constants) . ';';
1096  }
1097  if (!empty($this->_localeKeys)) {
1098  $output .= 'pkp.localeKeys = ' . json_encode($this->_localeKeys) . ';';
1099  }
1100 
1101  // Load current user data
1102  if (Config::getVar('general', 'installed')) {
1103  $user = $this->_request->getUser();
1104  if ($user) {
1105  $userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
1106  $userGroupsResult = $userGroupDao->getByUserId($user->getId());
1107  $userRoles = [];
1108  while ($userGroup = $userGroupsResult->next()) {
1109  $userRoles[] = (int) $userGroup->getRoleId();
1110  }
1111  $currentUser = [
1112  'csrfToken' => $this->_request->getSession()->getCSRFToken(),
1113  'id' => (int) $user->getId(),
1114  'roles' => array_values(array_unique($userRoles)),
1115  ];
1116  $output .= 'pkp.currentUser = ' . json_encode($currentUser) . ';';
1117  }
1118  }
1119 
1120  $this->addJavaScript(
1121  'pkpAppData',
1122  $output,
1123  [
1124  'priority' => STYLE_SEQUENCE_LATE,
1125  'contexts' => ['backend'],
1126  'inline' => true,
1127  ]
1128  );
1129 
1130  // Give any hooks registered against the TemplateManager
1131  // the opportunity to modify behavior; otherwise, display
1132  // the template as usual.
1133  $output = null;
1134  if (HookRegistry::call('TemplateManager::display', [$this, &$template, &$output])) {
1135  echo $output;
1136  return;
1137  }
1138 
1139  // Pass the initial state data for this page
1140  $this->assign('state', $this->_state);
1141 
1142  // Explicitly set the character encoding. Required in
1143  // case server is using Apache's AddDefaultCharset
1144  // directive (which can prevent browser auto-detection
1145  // of the proper character set).
1146  header('Content-Type: text/html; charset=' . Config::getVar('i18n', 'client_charset'));
1147  header('Cache-Control: ' . $this->_cacheability);
1148 
1149  // If no compile ID was assigned, get one.
1150  if (!$compile_id) $compile_id = $this->getCompileId($template);
1151 
1152  // Actually display the template.
1153  parent::display($template, $cache_id, $compile_id, $parent);
1154  }
1155 
1156 
1160  function clearTemplateCache() {
1161  $this->clearCompiledTemplate();
1162  $this->clearAllCache();
1163  }
1164 
1168  public function clearCssCache() {
1169  $cacheDirectory = CacheManager::getFileCachePath();
1170  $files = scandir($cacheDirectory);
1171  array_map('unlink', glob(CacheManager::getFileCachePath() . DIRECTORY_SEPARATOR . '*.' . CSS_FILENAME_SUFFIX));
1172  }
1173 
1185  public function clearThemeTemplateCache($hookName, $args) {
1186  $newContextOrSite = $args[0];
1187  $contextOrSite = $args[1];
1188  if ($newContextOrSite->getData('themePluginPath') !== $contextOrSite->getData('themePluginPath')) {
1189  $this->clearTemplateCache();
1190  $this->clearCssCache();
1191  }
1192  }
1193 
1199  static function &getManager($request = null) {
1200  if (!isset($request)) {
1201  $request = Registry::get('request');
1202  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call without request object.');
1203  }
1204  assert(is_a($request, 'PKPRequest'));
1205 
1206  $instance =& Registry::get('templateManager', true, null); // Reference required
1207 
1208  if ($instance === null) {
1209  $instance = new TemplateManager();
1210  $themes = PluginRegistry::getPlugins('themes');
1211  if (empty($themes)) {
1212  $themes = PluginRegistry::loadCategory('themes', true);
1213  }
1214  $instance->initialize($request);
1215  }
1216 
1217  return $instance;
1218  }
1219 
1224  function getFBV() {
1225  if(!$this->_fbv) {
1226  import('lib.pkp.classes.form.FormBuilderVocabulary');
1227  $this->_fbv = new FormBuilderVocabulary();
1228  }
1229  return $this->_fbv;
1230  }
1231 
1242  public function displaySidebar($hookName, $args) {
1243  $params =& $args[0];
1244  $smarty =& $args[1];
1245  $output =& $args[2];
1246 
1247  if ($this->_request->getContext()) {
1248  $blocks = $this->_request->getContext()->getData('sidebar');
1249  } else {
1250  $blocks = $this->_request->getSite()->getData('sidebar');
1251  }
1252 
1253  if (empty($blocks)) {
1254  return false;
1255  }
1256 
1257  $plugins = PluginRegistry::loadCategory('blocks', true);
1258  if (empty($plugins)) {
1259  return false;
1260  }
1261 
1262  foreach ($blocks as $pluginName) {
1263  if (!empty($plugins[$pluginName])) {
1264  $output .= $plugins[$pluginName]->getContents($smarty, $this->_request);
1265  }
1266  }
1267 
1268  return false;
1269  }
1270 
1271 
1272  //
1273  // Custom template functions, modifiers, etc.
1274  //
1275 
1287  function smartyTranslate($params, $smarty) {
1288  if (isset($params) && !empty($params)) {
1289  if (!isset($params['key'])) return __('');
1290 
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);
1297  }
1298  return __($key, $params);
1299  }
1300  }
1301 
1310  function smartyNullLinkAction($params, $smarty) {
1311  assert(isset($params['id']));
1312 
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;
1318 
1319  import('lib.pkp.classes.linkAction.request.NullAction');
1320  import('lib.pkp.classes.linkAction.LinkAction');
1321  $key = $translate ? __($key) : $key;
1322  $this->assign('action', new LinkAction(
1323  $id, new NullAction(), $key, $image
1324  ));
1325 
1326  $this->assign('hoverTitle', $hoverTitle);
1327  return $this->fetch('linkAction/linkAction.tpl');
1328  }
1329 
1337  function smartyHelp($params, $smarty) {
1338  assert(isset($params['file']));
1339 
1340  $params = array_merge(
1341  [
1342  'file' => null, // The name of the Markdown file
1343  'section' => null, // The (optional) anchor within the Markdown file
1344  'textKey' => 'help.help', // An (optional) locale key for the link
1345  'text' => null, // An (optional) literal text for the link
1346  'class' => null, // An (optional) CSS class string for the link
1347  ],
1348  $params
1349  );
1350 
1351  $this->assign([
1352  'helpFile' => $params['file'],
1353  'helpSection' => $params['section'],
1354  'helpTextKey' => $params['textKey'],
1355  'helpText' => $params['text'],
1356  'helpClass' => $params['class'],
1357  ]);
1358 
1359  return $this->fetch('common/helpLink.tpl');
1360  }
1361 
1370  function smartyHtmlOptionsTranslate($params, $smarty) {
1371  if (isset($params['options'])) {
1372  if (isset($params['translateValues'])) {
1373  // Translate values AND output
1374  $newOptions = [];
1375  foreach ($params['options'] as $k => $v) {
1376  $newOptions[__($k)] = __($v);
1377  }
1378  $params['options'] = $newOptions;
1379  } else {
1380  // Just translate output
1381  $params['options'] = array_map('AppLocale::translate', $params['options']);
1382  }
1383  }
1384 
1385  if (isset($params['output'])) {
1386  $params['output'] = array_map('AppLocale::translate', $params['output']);
1387  }
1388 
1389  if (isset($params['values']) && isset($params['translateValues'])) {
1390  $params['values'] = array_map('AppLocale::translate', $params['values']);
1391  }
1392 
1393  require_once('lib/pkp/lib/vendor/smarty/smarty/libs/plugins/function.html_options.php');
1394  return smarty_function_html_options($params, $smarty);
1395  }
1396 
1405  function smartyIterate($params, $content, $smarty, &$repeat) {
1406  $iterator = $smarty->getTemplateVars($params['from']);
1407 
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);
1411  }
1412 
1413  // If the iterator is empty, we're finished.
1414  if (!$iterator || $iterator->eof()) {
1415  if (!$repeat) return $content;
1416  $repeat = false;
1417  return '';
1418  }
1419 
1420  $repeat = true;
1421 
1422  if (isset($params['key'])) {
1423  list($key, $value) = $iterator->nextWithKey();
1424  $smarty->assign($params['item'], $value);
1425  $smarty->assign($params['key'], $key);
1426  } else {
1427  $smarty->assign($params['item'], $iterator->next());
1428  }
1429  return $content;
1430  }
1431 
1438  function smartyPageInfo($params, $smarty) {
1439  $iterator = $params['iterator'];
1440 
1441  if (isset($params['itemsPerPage'])) {
1442  $itemsPerPage = $params['itemsPerPage'];
1443  } else {
1444  $itemsPerPage = $smarty->getTemplateVars('itemsPerPage');
1445  if (!is_numeric($itemsPerPage)) $itemsPerPage=25;
1446  }
1447 
1448  $page = $iterator->getPage();
1449  $pageCount = $iterator->getPageCount();
1450  $itemTotal = $iterator->getCount();
1451 
1452  if ($pageCount<1) return '';
1453 
1454  $from = (($page - 1) * $itemsPerPage) + 1;
1455  $to = min($itemTotal, $page * $itemsPerPage);
1456 
1457  return __('navigation.items', [
1458  'from' => ($to===0?0:$from),
1459  'to' => $to,
1460  'total' => $itemTotal
1461  ]);
1462  }
1463 
1469  function smartyFlush($params, $smarty) {
1470  $smarty->flush();
1471  }
1472 
1473  function flush() {
1474  while (ob_get_level()) {
1475  ob_end_flush();
1476  }
1477  flush();
1478  }
1479 
1483  function smartyCallHook($params, $smarty) {
1484  $output = null;
1485  HookRegistry::call($params['name'], [&$params, $smarty, &$output]);
1486  return $output;
1487  }
1488 
1504  function smartyUrl($parameters, $smarty) {
1505  if ( !isset($parameters['context']) ) {
1506  // Extract the variables named in $paramList, and remove them
1507  // from the parameters array. Variables remaining in params will be
1508  // passed along to Request::url as extra parameters.
1509  $context = [];
1510  $application = Application::get();
1511  $contextList = $application->getContextList();
1512  foreach ($contextList as $contextName) {
1513  if (isset($parameters[$contextName])) {
1514  $context[$contextName] = $parameters[$contextName];
1515  unset($parameters[$contextName]);
1516  } else {
1517  $context[$contextName] = null;
1518  }
1519  }
1520  $parameters['context'] = $context;
1521  }
1522 
1523  // Extract the reserved variables named in $paramList, and remove them
1524  // from the parameters array. Variables remaining in parameters will be passed
1525  // along to Request::url as extra parameters.
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]);
1531  } else {
1532  $$parameter = null;
1533  }
1534  }
1535 
1536  // Merge parameters specified in the {url paramName=paramValue} format with
1537  // those optionally supplied in {url params=$someAssociativeArray} format
1538  $parameters = array_merge($parameters, (array) $params);
1539 
1540  // Set the default router
1541  if (is_null($router)) {
1542  if (is_a($this->_request->getRouter(), 'PKPComponentRouter')) {
1543  $router = ROUTE_COMPONENT;
1544  } else {
1545  $router = ROUTE_PAGE;
1546  }
1547  }
1548 
1549  // Check the router
1550  $dispatcher = Application::get()->getDispatcher();
1551  $routerShortcuts = array_keys($dispatcher->getRouterNames());
1552  assert(in_array($router, $routerShortcuts));
1553 
1554  // Identify the handler
1555  switch($router) {
1556  case ROUTE_PAGE:
1557  $handler = $page;
1558  break;
1559 
1560  case ROUTE_COMPONENT:
1561  $handler = $component;
1562  break;
1563 
1564  default:
1565  // Unknown router type
1566  assert(false);
1567  }
1568 
1569  // Let the dispatcher create the url
1570  return $dispatcher->url($this->_request, $router, $context, $handler, $op, $path, $parameters, $anchor, !isset($escape) || $escape);
1571  }
1572 
1591  function smartyTitle($parameters, $smarty) {
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');
1597  } else {
1598  $siteTitle = __('common.software');
1599  }
1600 
1601  if (empty($parameters['value'])) {
1602  return $siteTitle;
1603  }
1604 
1605  return $parameters['value'] . __('common.titleSeparator') . $siteTitle;
1606  }
1607 
1618  function smartyPageLinks($params, $smarty) {
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);
1625  }
1626  if (isset($params['anchor'])) {
1627  $anchor = $params['anchor'];
1628  unset($params['anchor']);
1629  } else {
1630  $anchor = null;
1631  }
1632  if (isset($params['all_extra'])) {
1633  $allExtra = ' ' . $params['all_extra'];
1634  unset($params['all_extra']);
1635  } else {
1636  $allExtra = '';
1637  }
1638 
1639  unset($params['iterator']);
1640  unset($params['name']);
1641 
1642  $numPageLinks = $smarty->getTemplateVars('numPageLinks');
1643  if (!is_numeric($numPageLinks)) $numPageLinks=10;
1644 
1645  $page = $iterator->getPage();
1646  $pageCount = $iterator->getPageCount();
1647 
1648  $pageBase = max($page - floor($numPageLinks / 2), 1);
1649  $paramName = $name . 'Page';
1650 
1651  if ($pageCount<=1) return '';
1652 
1653  $value = '';
1654 
1655  $router = $this->_request->getRouter();
1656  $requestedArgs = null;
1657  if (is_a($router, 'PageRouter')) {
1658  $requestedArgs = $router->getRequestedArgs($this->_request);
1659  }
1660 
1661  if ($page>1) {
1662  $params[$paramName] = 1;
1663  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&lt;&lt;</a>&nbsp;';
1664  $params[$paramName] = $page - 1;
1665  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&lt;</a>&nbsp;';
1666  }
1667 
1668  for ($i=$pageBase; $i<min($pageBase+$numPageLinks, $pageCount+1); $i++) {
1669  if ($i == $page) {
1670  $value .= "<strong>$i</strong>&nbsp;";
1671  } else {
1672  $params[$paramName] = $i;
1673  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>' . $i . '</a>&nbsp;';
1674  }
1675  }
1676  if ($page < $pageCount) {
1677  $params[$paramName] = $page + 1;
1678  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&gt;</a>&nbsp;';
1679  $params[$paramName] = $pageCount;
1680  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&gt;&gt;</a>&nbsp;';
1681  }
1682 
1683  return $value;
1684  }
1685 
1689  function smartyToArray() {
1690  return func_get_args();
1691  }
1692 
1696  function smartyConcat() {
1697  $args = func_get_args();
1698  return implode('', $args);
1699  }
1700 
1708  function smartyCompare($a, $b, $strict = false, $invert = false) {
1709  $result = $strict?$a===$b:$a==$b;
1710  return $invert?!$result:$result;
1711  }
1712 
1716  function smartyStrtotime($string) {
1717  return strtotime($string);
1718  }
1719 
1723  function smartyExplode($string, $separator) {
1724  return explode($separator, $string);
1725  }
1726 
1731  function smartyEscape($string, $esc_type = 'html', $char_set = 'ISO-8859-1') {
1732  $pattern = "/(:|\.|\[|\]|,|=|@)/";
1733  $replacement = "\\\\\\\\$1";
1734  switch ($esc_type) {
1735  // Because jQuery uses CSS syntax for selecting elements
1736  // some characters are interpreted as CSS notation.
1737  // In order to tell jQuery to treat these characters literally rather
1738  // than as CSS notation, they must be escaped by placing two backslashes
1739  // in front of them.
1740  case 'jqselector':
1741  $result = smarty_modifier_escape($string, 'html', $char_set);
1742  $result = preg_replace($pattern, $replacement, $result);
1743  return $result;
1744 
1745  case 'jsid':
1746  $result = smarty_modifier_escape($string, 'javascript', $char_set);
1747  $result = preg_replace($pattern, $replacement, $result);
1748  return $result;
1749 
1750  default:
1751  return smarty_modifier_escape($string, $esc_type, $char_set);
1752  }
1753  }
1754 
1763  function smartyLoadUrlInEl($params, $smarty) {
1764  // Required Params
1765  if (!isset($params['el'])) {
1766  throw new Exception("el parameter is missing from load_url_in_el");
1767  }
1768  if (!isset($params['url'])) {
1769  throw new Exception("url parameter is missing from load_url_in_el");
1770  }
1771  if (!isset($params['id'])) {
1772  throw new Exception("id parameter is missing from load_url_in_el");
1773  }
1774 
1775  $this->assign([
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,
1781  ]);
1782 
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));
1788  } else {
1789  $this->assign('inElPlaceholder', $this->fetch('common/loadingContainer.tpl'));
1790  }
1791 
1792  return $this->fetch('common/urlInEl.tpl');
1793  }
1794 
1804  function smartyLoadUrlInDiv($params, $smarty) {
1805  $params['el'] = 'div';
1806  return $this->smartyLoadUrlInEl( $params, $smarty );
1807  }
1808 
1817  function smartyCSRF($params, $smarty) {
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);
1822  case 'html':
1823  default:
1824  return '<input type="hidden" name="csrfToken" value="' . htmlspecialchars($csrfToken) . '">';
1825  }
1826  }
1827 
1836  function smartyLoadStylesheet($params, $smarty) {
1837 
1838  if (empty($params['context'])) {
1839  $params['context'] = 'frontend';
1840  }
1841 
1842  if (!defined('SESSION_DISABLE_INIT')) {
1843  $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */
1844  $appVersion = $versionDao->getCurrentVersion()->getVersionString();
1845  } else $appVersion = null;
1846 
1847  $stylesheets = $this->getResourcesByContext($this->_styleSheets, $params['context']);
1848 
1849  ksort($stylesheets);
1850 
1851  $output = '';
1852  foreach($stylesheets as $priorityList) {
1853  foreach($priorityList as $style) {
1854  if (!empty($style['inline'])) {
1855  $output .= '<style type="text/css">' . $style['style'] . '</style>';
1856  } else {
1857  if ($appVersion && strpos($style['style'], '?') === false) {
1858  $style['style'] .= '?v=' . $appVersion;
1859  }
1860  $output .= '<link rel="stylesheet" href="' . $style['style'] . '" type="text/css" />';
1861  }
1862  }
1863  }
1864 
1865  return $output;
1866  }
1867 
1877  function loadHtmlGalleyStyles($htmlContent, $embeddedFiles) {
1878 
1879  if (empty($htmlContent)) {
1880  return $htmlContent;
1881  }
1882 
1883  $hasEmbeddedStyle = false;
1884  foreach ($embeddedFiles as $embeddedFile) {
1885  if ($embeddedFile->getFileType() === 'text/css') {
1886  $hasEmbeddedStyle = true;
1887  break;
1888  }
1889  }
1890 
1891  if ($hasEmbeddedStyle) {
1892  return $htmlContent;
1893  }
1894 
1895  $links = '';
1896  $styles = $this->getResourcesByContext($this->_styleSheets, 'htmlGalley');
1897 
1898  if (!empty($styles)) {
1899  ksort($styles);
1900  foreach ($styles as $priorityGroup) {
1901  foreach ($priorityGroup as $htmlStyle) {
1902  $links .= '<link rel="stylesheet" href="' . $htmlStyle['style'] . '" type="text/css">' . "\n";
1903  }
1904  }
1905  }
1906 
1907  return str_ireplace('<head>', '<head>' . "\n" . $links, $htmlContent);
1908  }
1909 
1918  function smartyLoadScript($params, $smarty) {
1919 
1920  if (empty($params['context'])) {
1921  $params['context'] = 'frontend';
1922  }
1923 
1924  if (!defined('SESSION_DISABLE_INIT')) {
1925  $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */
1926  $appVersion = defined('SESSION_DISABLE_INIT') ? null : $versionDao->getCurrentVersion()->getVersionString();
1927  } else $appVersion = null;
1928 
1929  $scripts = $this->getResourcesByContext($this->_javaScripts, $params['context']);
1930 
1931  ksort($scripts);
1932 
1933  $output = '';
1934  foreach($scripts as $priorityList) {
1935  foreach($priorityList as $name => $data) {
1936  if ($data['inline']) {
1937  $output .= '<script type="text/javascript">' . $data['script'] . '</script>';
1938  } else {
1939  if ($appVersion && strpos($data['script'], '?') === false) {
1940  $data['script'] .= '?v=' . $appVersion;
1941  }
1942  $output .= '<script src="' . $data['script'] . '" type="text/javascript"></script>';
1943  }
1944  }
1945  }
1946 
1947  return $output;
1948  }
1949 
1958  function smartyLoadHeader($params, $smarty) {
1959 
1960  if (empty($params['context'])) {
1961  $params['context'] = 'frontend';
1962  }
1963 
1964  $headers = $this->getResourcesByContext($this->_htmlHeaders, $params['context']);
1965 
1966  ksort($headers);
1967 
1968  $output = '';
1969  foreach($headers as $priorityList) {
1970  foreach($priorityList as $name => $data) {
1971  $output .= "\n" . $data['header'];
1972  }
1973  }
1974 
1975  return $output;
1976  }
1977 
1986  function smartyLoadNavigationMenuArea($params, $smarty) {
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();
1993  }
1994 
1995  // Don't load menus for an area that's not registered by the active theme
1996  $themePlugins = PluginRegistry::getPlugins('themes');
1997  if (empty($themePlugins)) {
1998  $themePlugins = PluginRegistry::loadCategory('themes', true);
1999  }
2000  $activeThemeNavigationAreas = [];
2001  foreach ($themePlugins as $themePlugin) {
2002  if ($themePlugin->isActive()) {
2003  $areas = $themePlugin->getMenuAreas();
2004  if (!in_array($areaName, $areas)) {
2005  return '';
2006  }
2007  }
2008  }
2009 
2010  $menuTemplatePath = 'frontend/components/navigationMenu.tpl';
2011  if (isset($declaredMenuTemplatePath)) {
2012  $menuTemplatePath = $declaredMenuTemplatePath;
2013  }
2014 
2015  $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /* @var $navigationMenuDao NavigationMenuDAO */
2016 
2017  $output = '';
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);
2023  }
2024 
2025 
2026  $this->assign([
2027  'navigationMenu' => $navigationMenu,
2028  'id' => $params['id'],
2029  'ulClass' => $params['ulClass'],
2030  'liClass' => $params['liClass'],
2031  ]);
2032 
2033  return $this->fetch($menuTemplatePath);
2034  }
2035 
2045  function getResourcesByContext($resources, $context) {
2046  $matches = [];
2047 
2048  if (array_key_exists($context, $resources)) {
2049  $matches = $resources[$context];
2050  }
2051 
2052  $page = $this->getTemplateVars('requestedPage');
2053  $page = empty( $page ) ? 'index' : $page;
2054  $op = $this->getTemplateVars('requestedOp');
2055  $op = empty( $op ) ? 'index' : $op;
2056 
2057  $contexts = [
2058  join('-', [$context, $page]),
2059  join('-', [$context, $page, $op]),
2060  ];
2061 
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] = [];
2067  }
2068  $matches[$priority] = array_merge($matches[$priority], $resources[$context][$priority]);
2069  }
2070  $matches += $resources[$context];
2071  }
2072  }
2073 
2074  return $matches;
2075  }
2076 
2086  function smartyPluckFiles($params, $smarty) {
2087 
2088  // The variable to assign the result to.
2089  if (empty($params['assign'])) {
2090  error_log('Smarty: {pluck_files} function called without required `assign` param. Called in ' . __FILE__ . ':' . __LINE__);
2091  return;
2092  }
2093 
2094  // $params['files'] should be an array of SubmissionFile objects
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'], []);
2098  return;
2099  }
2100 
2101  // $params['by'] is one of an approved list of attributes to select by
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'], []);
2105  return;
2106  }
2107 
2108  // The approved list of `by` attributes
2109  // chapter Any files assigned to a chapter ID. A value of `any` will return files assigned to any chapter. A value of 0 will return files not assigned to chapter
2110  // publicationFormat Any files in a given publicationFormat ID
2111  // component Any files of a component type by class name: SubmissionFile|SubmissionArtworkFile|SupplementaryFile
2112  // fileExtension Any files with a file extension in all caps: PDF
2113  // genre Any files with a genre ID (file genres are configurable but typically refer to Manuscript, Bibliography, etc)
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'], []);
2117  return;
2118  }
2119 
2120  // The value to match against. See docs for `by` param
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'], []);
2124  return;
2125  }
2126 
2127  $matching_files = [];
2128 
2129  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
2130  foreach ($params['files'] as $file) {
2131  switch ($params['by']) {
2132 
2133  case 'chapter':
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;
2142  }
2143  }
2144  break;
2145 
2146  case 'publicationFormat':
2147  if ($file->getAssocId() == $params['value']) {
2148  $matching_files[] = $file;
2149  }
2150  break;
2151 
2152  case 'component':
2153  if (get_class($file) == $params['value']) {
2154  $matching_files[] = $file;
2155  }
2156  break;
2157 
2158  case 'fileExtension':
2159  if ($file->getExtension() == $params['value']) {
2160  $matching_files[] = $file;
2161  }
2162  break;
2163 
2164  case 'genre':
2165  if ($file->getGenreId() == $params['value']) {
2166  $matching_files[] = $file;
2167  }
2168  break;
2169  }
2170  }
2171 
2172  $smarty->assign($params['assign'], $matching_files);
2173  }
2174 
2179  public function get_template_vars($varname = null) {
2180  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call to Smarty2 function ' . __FUNCTION__);
2181  return $this->getTemplateVars($varname);
2182  }
2183 
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);
2194  }
2195 }
PKPTemplateManager\addStyleSheet
addStyleSheet($name, $style, $args=[])
Definition: PKPTemplateManager.inc.php:455
PKPLocale\getLocaleStyleSheet
static getLocaleStyleSheet($locale)
Definition: PKPLocale.inc.php:446
$op
$op
Definition: lib/pkp/pages/help/index.php:18
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
PluginRegistry\getPlugins
static & getPlugins($category=null)
Definition: PluginRegistry.inc.php:30
PKPTemplateManager
Definition: PKPTemplateManager.inc.php:50
PKPTemplateManager\getState
getState($key)
Definition: PKPTemplateManager.inc.php:568
PKPTemplateManager\fetchJson
fetchJson($template, $status=true)
Definition: PKPTemplateManager.inc.php:1109
Validation\isLoggedInAs
static isLoggedInAs()
Definition: Validation.inc.php:388
PKPTemplateManager\registerJSLibraryData
registerJSLibraryData()
Definition: PKPTemplateManager.inc.php:669
PKPTemplateManager\smartyTranslate
smartyTranslate($params, $smarty)
Definition: PKPTemplateManager.inc.php:1314
CacheManager\getFileCachePath
static getFileCachePath()
Definition: CacheManager.inc.php:112
PKPTemplateManager\setLocaleKeys
setLocaleKeys($keys)
Definition: PKPTemplateManager.inc.php:554
Validation\isLoggedIn
static isLoggedIn()
Definition: Validation.inc.php:376
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
PKPTemplateManager\smartyHelp
smartyHelp($params, $smarty)
Definition: PKPTemplateManager.inc.php:1364
PKPTemplateManager\getCachedLessFilePath
getCachedLessFilePath($name)
Definition: PKPTemplateManager.inc.php:434
PKPTemplateManager\smartyFlush
smartyFlush($params, $smarty)
Definition: PKPTemplateManager.inc.php:1496
PKPTemplateManager\clearThemeTemplateCache
clearThemeTemplateCache($hookName, $args)
Definition: PKPTemplateManager.inc.php:1212
PKPTemplateManager\setState
setState($data)
Definition: PKPTemplateManager.inc.php:579
PKPTemplateManager\register_function
register_function($name, $impl, $cacheable=true, $cache_attrs=null)
Definition: PKPTemplateManager.inc.php:2218
PKPTemplateManager\smartyCallHook
smartyCallHook($params, $smarty)
Definition: PKPTemplateManager.inc.php:1510
PKPTemplateManager\smartyHtmlOptionsTranslate
smartyHtmlOptionsTranslate($params, $smarty)
Definition: PKPTemplateManager.inc.php:1397
AppLocale\getPrimaryLocale
static getPrimaryLocale()
Definition: env1/MockAppLocale.inc.php:95
PKPLocale\getLocaleDirection
static getLocaleDirection($locale)
Definition: PKPLocale.inc.php:465
PKPTemplateManager\setConstants
setConstants($names)
Definition: PKPTemplateManager.inc.php:543
PKPTemplateManager\smartyIterate
smartyIterate($params, $content, $smarty, &$repeat)
Definition: PKPTemplateManager.inc.php:1432
PKPTemplateManager\smartyPageInfo
smartyPageInfo($params, $smarty)
Definition: PKPTemplateManager.inc.php:1465
PublicFileManager
Wrapper class for uploading files to a site/journal's public directory.
Definition: PublicFileManager.inc.php:18
PKPTemplateManager\smartyLoadUrlInDiv
smartyLoadUrlInDiv($params, $smarty)
Definition: PKPTemplateManager.inc.php:1831
PKPTemplateManager\smartyCompare
smartyCompare($a, $b, $strict=false, $invert=false)
Definition: PKPTemplateManager.inc.php:1735
PKPTemplateManager\smartyExplode
smartyExplode($string, $separator)
Definition: PKPTemplateManager.inc.php:1750
PluginRegistry\loadCategory
static loadCategory($category, $enabledOnly=false, $mainContextId=null)
Definition: PluginRegistry.inc.php:103
PKPTemplateResource
Representation for a PKP template resource (template directory).
Definition: PKPTemplateResource.inc.php:16
TemplateManager
Class for accessing the underlying template engine. Currently integrated with Smarty (from http://sma...
Definition: TemplateManager.inc.php:22
PKPTemplateManager\smartyToArray
smartyToArray()
Definition: PKPTemplateManager.inc.php:1716
PKPTemplateManager\clearTemplateCache
clearTemplateCache()
Definition: PKPTemplateManager.inc.php:1187
PKPTemplateManager\setCacheability
setCacheability($cacheability=CACHEABILITY_PUBLIC)
Definition: PKPTemplateManager.inc.php:363
Registry\get
static & get($key, $createIfEmpty=false, $createWithDefault=null)
Definition: Registry.inc.php:35
NullAction
This action does nothing.
Definition: NullAction.inc.php:18
JSONMessage
Class to represent a JSON (Javascript Object Notation) message.
Definition: JSONMessage.inc.php:18
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
PKPTemplateManager\loadHtmlGalleyStyles
loadHtmlGalleyStyles($htmlContent, $embeddedFiles)
Definition: PKPTemplateManager.inc.php:1904
LinkAction
Base class defining an action that can be performed by the user in the user interface.
Definition: LinkAction.inc.php:22
PKPTemplateManager\smartyStrtotime
smartyStrtotime($string)
Definition: PKPTemplateManager.inc.php:1743
PKPTemplateManager\smartyConcat
smartyConcat()
Definition: PKPTemplateManager.inc.php:1723
PKPTemplateManager\fetch
fetch($template=null, $cache_id=null, $compile_id=null, $parent=null)
Definition: PKPTemplateManager.inc.php:1056
PKPTemplateManager\registerJSLibrary
registerJSLibrary()
Definition: PKPTemplateManager.inc.php:586
PKPTemplateManager\smartyLoadUrlInEl
smartyLoadUrlInEl($params, $smarty)
Definition: PKPTemplateManager.inc.php:1790
PKPTemplateManager\getFBV
getFBV()
Definition: PKPTemplateManager.inc.php:1251
PKPTemplateManager\flush
flush()
Definition: PKPTemplateManager.inc.php:1500
PKPTemplateManager\__construct
__construct()
Definition: PKPTemplateManager.inc.php:109
PKPTemplateManager\smartyCSRF
smartyCSRF($params, $smarty)
Definition: PKPTemplateManager.inc.php:1844
PKPTemplateManager\getManager
static & getManager($request=null)
Definition: PKPTemplateManager.inc.php:1226
PKPTemplateManager\smartyEscape
smartyEscape($string, $esc_type='html', $char_set='ISO-8859-1')
Definition: PKPTemplateManager.inc.php:1758
PKPTemplateManager\get_template_vars
get_template_vars($varname=null)
Definition: PKPTemplateManager.inc.php:2206
FormBuilderVocabulary
Definition: FormBuilderVocabulary.inc.php:57
PKPTemplateManager\clearCssCache
clearCssCache()
Definition: PKPTemplateManager.inc.php:1195
PKPTemplateManager\addJavaScript
addJavaScript($name, $script, $args=[])
Definition: PKPTemplateManager.inc.php:489
PKPTemplateManager\smartyLoadStylesheet
smartyLoadStylesheet($params, $smarty)
Definition: PKPTemplateManager.inc.php:1863
PKPTemplateManager\smartyPageLinks
smartyPageLinks($params, $smarty)
Definition: PKPTemplateManager.inc.php:1645
PKPTemplateManager\smartyLoadScript
smartyLoadScript($params, $smarty)
Definition: PKPTemplateManager.inc.php:1945
PKPTemplateManager\smartyUrl
smartyUrl($parameters, $smarty)
Definition: PKPTemplateManager.inc.php:1531
PKPTemplateManager\getCompileId
getCompileId($resourceName)
Definition: PKPTemplateManager.inc.php:1091
PKPTemplateManager\setupBackendPage
setupBackendPage()
Definition: PKPTemplateManager.inc.php:714
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
PKPTemplateManager\smartyLoadNavigationMenuArea
smartyLoadNavigationMenuArea($params, $smarty)
Definition: PKPTemplateManager.inc.php:2013
PKPTemplateManager\displaySidebar
displaySidebar($hookName, $args)
Definition: PKPTemplateManager.inc.php:1269
Core\getBaseDir
static getBaseDir()
Definition: Core.inc.php:37
PKPTemplateManager\smartyLoadHeader
smartyLoadHeader($params, $smarty)
Definition: PKPTemplateManager.inc.php:1985
PKPTemplateManager\compileLess
compileLess($name, $lessFile, $args=[])
Definition: PKPTemplateManager.inc.php:377
PKPTemplateManager\fetchAjax
fetchAjax($id, $url, $element='div')
Definition: PKPTemplateManager.inc.php:1075
PKPTemplateManager\addHeader
addHeader($name, $header, $args=[])
Definition: PKPTemplateManager.inc.php:520
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
PKPTemplateManager\smartyPluckFiles
smartyPluckFiles($params, $smarty)
Definition: PKPTemplateManager.inc.php:2113
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PKPTemplateManager\display
display($template=null, $cache_id=null, $compile_id=null, $parent=null)
Definition: PKPTemplateManager.inc.php:1117
AppLocale\getLocale
static getLocale()
Definition: env1/MockAppLocale.inc.php:40
PKPTemplateManager\getResourcesByContext
getResourcesByContext($resources, $context)
Definition: PKPTemplateManager.inc.php:2072
PKPTemplateManager\smartyTitle
smartyTitle($parameters, $smarty)
Definition: PKPTemplateManager.inc.php:1618
PKPTemplateManager\smartyNullLinkAction
smartyNullLinkAction($params, $smarty)
Definition: PKPTemplateManager.inc.php:1337
PKPTemplateManager\initialize
initialize($request)
Definition: PKPTemplateManager.inc.php:134
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49
PKPTemplateManager\cacheLess
cacheLess($path, $styles)
Definition: PKPTemplateManager.inc.php:419