Open Journal 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();
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  'currentContext' => $currentContext,
123  'currentLocale' => $locale,
124  'currentLocaleLangDir' => AppLocale::getLocaleDirection($locale),
125  'applicationName' => __($application->getNameKey()),
126  ]);
127 
128  // Assign date and time format
129  if ($currentContext) {
130  $this->assign(array(
131  'dateFormatShort' => $currentContext->getLocalizedDateFormatShort(),
132  'dateFormatLong' => $currentContext->getLocalizedDateFormatLong(),
133  'datetimeFormatShort' => $currentContext->getLocalizedDateTimeFormatShort(),
134  'datetimeFormatLong' => $currentContext->getLocalizedDateTimeFormatLong(),
135  'timeFormat' => $currentContext->getLocalizedTimeFormat(),
136  ));
137  } else {
138  $this->assign(array(
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'),
143  'timeFormat' => Config::getVar('general', 'time_format'),
144  ));
145  }
146 
147  // Assign meta tags
148  if ($currentContext) {
149  $favicon = $currentContext->getLocalizedFavicon();
150  if (!empty($favicon)) {
151  $publicFileManager = new PublicFileManager();
152  $faviconDir = $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($currentContext->getId());
153  $this->addHeader('favicon', '<link rel="icon" href="' . $faviconDir . '/' . $favicon['uploadName'] . '">');
154  }
155  }
156 
157  if (Config::getVar('general', 'installed')) {
158  $activeTheme = null;
159  $contextOrSite = $currentContext ? $currentContext : $request->getSite();
160  $allThemes = PluginRegistry::getPlugins('themes');
161  foreach ($allThemes as $theme) {
162  if ($contextOrSite->getData('themePluginPath') === $theme->getDirName()) {
163  $activeTheme = $theme;
164  break;
165  }
166  }
167  $this->assign(['activeTheme' => $activeTheme]);
168  }
169 
170  if (is_a($router, 'PKPPageRouter')) {
171  $this->assign([
172  'requestedPage' => $router->getRequestedPage($request),
173  'requestedOp' => $router->getRequestedOp($request),
174  ]);
175 
176  // A user-uploaded stylesheet
177  if ($currentContext) {
178  $contextStyleSheet = $currentContext->getData('styleSheet');
179  if ($contextStyleSheet) {
180  import('classes.file.PublicFileManager');
181  $publicFileManager = new PublicFileManager();
182  $this->addStyleSheet(
183  'contextStylesheet',
184  $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($currentContext->getId()) . '/' . $contextStyleSheet['uploadName'],
185  ['priority' => STYLE_SEQUENCE_LATE]
186  );
187  }
188  }
189 
190  // Register recaptcha on relevant pages
191  if (Config::getVar('captcha', 'recaptcha') && Config::getVar('captcha', 'captcha_on_register')) {
192  $this->addJavaScript(
193  'recaptcha',
194  'https://www.recaptcha.net/recaptcha/api.js?hl=' . substr(AppLocale::getLocale(),0,2),
195  [
196  'contexts' => ['frontend-user-register', 'frontend-user-registerUser'],
197  ]
198  );
199  }
200 
201  // Register meta tags
202  if (Config::getVar('general', 'installed')) {
203  if (($request->getRequestedPage()=='' || $request->getRequestedPage() == 'index') && $currentContext && $currentContext->getLocalizedData('searchDescription')) {
204  $this->addHeader('searchDescription', '<meta name="description" content="' . $currentContext->getLocalizedData('searchDescription') . '">');
205  }
206 
207  $this->addHeader(
208  'generator',
209  '<meta name="generator" content="' . __($application->getNameKey()) . ' ' . $application->getCurrentVersion()->getVersionString(false) . '">',
210  [
211  'contexts' => ['frontend', 'backend'],
212  ]
213  );
214 
215  if ($currentContext) {
216  $customHeaders = $currentContext->getLocalizedData('customHeaders');
217  if (!empty($customHeaders)) {
218  $this->addHeader('customHeaders', $customHeaders);
219  }
220  }
221  }
222 
223  if ($currentContext && !$currentContext->getEnabled()) {
224  $this->addHeader(
225  'noindex',
226  '<meta name="robots" content="noindex,nofollow">',
227  [
228  'contexts' => ['frontend', 'backend'],
229  ]
230  );
231  }
232 
233  // Register Navigation Menus
234  import('classes.core.Services');
235  $nmService = Services::get('navigationMenu');
236 
237  if (Config::getVar('general', 'installed')) {
238  \HookRegistry::register('LoadHandler', [$nmService, '_callbackHandleCustomNavigationMenuItems']);
239  }
240  }
241 
242  // Register custom functions
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']);
264 
265  $this->registerPlugin('function','title', [$this, 'smartyTitle']);
266  $this->registerPlugin('function', 'url', [$this, 'smartyUrl']);
267 
268  // load stylesheets/scripts/headers from a given context
269  $this->registerPlugin('function', 'load_stylesheet', [$this, 'smartyLoadStylesheet']);
270  $this->registerPlugin('function', 'load_script', [$this, 'smartyLoadScript']);
271  $this->registerPlugin('function', 'load_header', [$this, 'smartyLoadHeader']);
272 
273  // load NavigationMenu Areas from context
274  $this->registerPlugin('function', 'load_menu', [$this, 'smartyLoadNavigationMenuArea']);
275 
276  // Load form builder vocabulary
277  $fbv = $this->getFBV();
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());
284 
285  // ajax load into a div or any element
286  $this->registerPlugin('function', 'load_url_in_el', [$this, 'smartyLoadUrlInEl']);
287  $this->registerPlugin('function', 'load_url_in_div', [$this, 'smartyLoadUrlInDiv']);
288 
289  // Always pass these ListBuilder constants to the browser
290  // because a ListBuilder may be loaded in an ajax request
291  // and won't have an opportunity to pass its constants to
292  // the template manager. This is not a recommended practice,
293  // but these are the only constants from a controller that are
294  // required on the frontend. We can remove them once the
295  // ListBuilderHandler is no longer needed.
296  import('lib.pkp.classes.controllers.listbuilder.ListbuilderHandler');
297  $this->setConstants([
298  'LISTBUILDER_SOURCE_TYPE_TEXT',
299  'LISTBUILDER_SOURCE_TYPE_SELECT',
300  'LISTBUILDER_OPTGROUP_LABEL',
301  ]);
302 
307  if (!defined('SESSION_DISABLE_INIT')) {
308  $this->assign([
309  'isUserLoggedIn' => Validation::isLoggedIn(),
310  'isUserLoggedInAs' => Validation::isLoggedInAs(),
311  'itemsPerPage' => Config::getVar('interface', 'items_per_page'),
312  'numPageLinks' => Config::getVar('interface', 'page_links'),
313  'siteTitle' => $request->getSite()->getLocalizedData('title'),
314  ]);
315 
316  $user = $request->getUser();
317  if ($user) {
318  $this->assign([
319  'currentUser' => $user,
320  ]);
321 
322  // Assign the user name to be used in the sitenav
323  $this->assign([
324  'loggedInUsername' => $user->getUserName(),
325  ]);
326  }
327  }
328 
329  if (Config::getVar('general', 'installed')) {
330  // Respond to the sidebar hook
331  if ($currentContext) {
332  $this->assign('hasSidebar', !empty($currentContext->getData('sidebar')));
333  } else {
334  $this->assign('hasSidebar', !empty($request->getSite()->getData('sidebar')));
335  }
336  HookRegistry::register('Templates::Common::Sidebar', [$this, 'displaySidebar']);
337 
338  // Clear the cache whenever the active theme is changed
339  HookRegistry::register('Context::edit', [$this, 'clearThemeTemplateCache']);
340  HookRegistry::register('Site::edit', [$this, 'clearThemeTemplateCache']);
341  }
342  }
343 
344 
349  function setCacheability($cacheability = CACHEABILITY_PUBLIC) {
350  $this->_cacheability = $cacheability;
351  }
352 
363  public function compileLess($name, $lessFile, $args = []) {
364  $less = new Less_Parser([
365  'relativeUrls' => false,
366  'compress' => true,
367  ]);
368 
369  $request = $this->_request;
370 
371  // Allow plugins to intervene
372  HookRegistry::call('PageHandler::compileLess', [&$less, &$lessFile, &$args, $name, $request]);
373 
374  // Read the stylesheet
375  $less->parseFile($lessFile);
376 
377  // Add extra LESS files before compiling
378  if (isset($args['addLess']) && is_array($args['addLess'])) {
379  foreach ($args['addLess'] as $addless) {
380  $less->parseFile($addless);
381  }
382  }
383 
384  // Add extra LESS variables before compiling
385  if (isset($args['addLessVariables'])) {
386  foreach ((array) $args['addLessVariables'] as $addlessVariables) {
387  $less->parse($addlessVariables);
388  }
389  }
390 
391  // Set the @baseUrl variable
392  $baseUrl = !empty($args['baseUrl']) ? $args['baseUrl'] : $request->getBaseUrl(true);
393  $less->parse("@baseUrl: '$baseUrl';");
394 
395  return $less->getCSS();
396  }
397 
405  public function cacheLess($path, $styles) {
406  if (file_put_contents($path, $styles) === false) {
407  error_log("Unable to write \"$path\".");
408  return false;
409  }
410 
411  return true;
412  }
413 
420  public function getCachedLessFilePath($name) {
421  $cacheDirectory = CacheManager::getFileCachePath();
422  $context = $this->_request->getContext();
423  $contextId = is_a($context, 'Context') ? $context->getId() : 0;
424  return $cacheDirectory . DIRECTORY_SEPARATOR . $contextId . '-' . $name . '.css';
425  }
426 
441  function addStyleSheet($name, $style, $args = []) {
442 
443  $args = array_merge(
444  [
445  'priority' => STYLE_SEQUENCE_NORMAL,
446  'contexts' => ['frontend'],
447  'inline' => false,
448  ],
449  $args
450  );
451 
452  $args['contexts'] = (array) $args['contexts'];
453  foreach($args['contexts'] as $context) {
454  $this->_styleSheets[$context][$args['priority']][$name] = [
455  'style' => $style,
456  'inline' => $args['inline'],
457  ];
458  }
459  }
460 
475  function addJavaScript($name, $script, $args = []) {
476 
477  $args = array_merge(
478  [
479  'priority' => STYLE_SEQUENCE_NORMAL,
480  'contexts' => ['frontend'],
481  'inline' => false,
482  ],
483  $args
484  );
485 
486  $args['contexts'] = (array) $args['contexts'];
487  foreach($args['contexts'] as $context) {
488  $this->_javaScripts[$context][$args['priority']][$name] = [
489  'script' => $script,
490  'inline' => $args['inline'],
491  ];
492  }
493  }
494 
506  function addHeader($name, $header, $args = []) {
507 
508  $args = array_merge(
509  [
510  'priority' => STYLE_SEQUENCE_NORMAL,
511  'contexts' => ['frontend'],
512  ],
513  $args
514  );
515 
516  $args['contexts'] = (array) $args['contexts'];
517  foreach($args['contexts'] as $context) {
518  $this->_htmlHeaders[$context][$args['priority']][$name] = [
519  'header' => $header,
520  ];
521  }
522  }
523 
529  function setConstants($names) {
530  foreach ($names as $name) {
531  $this->_constants[$name] = constant($name);
532  }
533  }
534 
540  function setLocaleKeys($keys) {
541  foreach ($keys as $key) {
542  if (!array_key_exists($key, $this->_localeKeys)) {
543  $this->_localeKeys[$key] = __($key);
544  }
545  }
546  }
547 
554  function getState($key) {
555  return array_key_exists($key, $this->_state)
556  ? $this->_state[$key]
557  : null;
558  }
559 
565  function setState($data) {
566  $this->_state = array_merge($this->_state, $data);
567  }
568 
572  function registerJSLibrary() {
573  $baseUrl = $this->_request->getBaseUrl();
574  $localeChecks = [AppLocale::getLocale(), strtolower(substr(AppLocale::getLocale(), 0, 2))];
575 
576  // Common $args array used for all our core JS files
577  $args = [
578  'priority' => STYLE_SEQUENCE_CORE,
579  'contexts' => 'backend',
580  ];
581 
582  // Load jQuery validate separately because it can not be linted
583  // properly by our build script
584  $this->addJavaScript(
585  'jqueryValidate',
586  $baseUrl . '/lib/pkp/js/lib/jquery/plugins/validate/jquery.validate.min.js',
587  $args
588  );
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);
593  }
594  }
595 
596  $this->addJavaScript(
597  'plUpload',
598  $baseUrl . '/lib/pkp/lib/vendor/moxiecode/plupload/js/plupload.full.min.js',
599  $args
600  );
601  $this->addJavaScript(
602  'jQueryPlUpload',
603  $baseUrl . '/lib/pkp/lib/vendor/moxiecode/plupload/js/jquery.ui.plupload/jquery.ui.plupload.js',
604  $args
605  );
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);
610  }
611  }
612 
613  // Load new component library bundle
614  $this->addJavaScript(
615  'pkpApp',
616  $baseUrl . '/js/build.js',
617  [
618  'priority' => STYLE_SEQUENCE_LATE,
619  'contexts' => ['backend']
620  ]
621  );
622 
623  // Load minified file if it exists
624  if (Config::getVar('general', 'enable_minified')) {
625  $this->addJavaScript(
626  'pkpLib',
627  $baseUrl . '/js/pkp.min.js',
628  [
629  'priority' => STYLE_SEQUENCE_CORE,
630  'contexts' => ['backend']
631  ]
632  );
633  return;
634  }
635 
636  // Otherwise retrieve and register all script files
637  $minifiedScripts = array_filter(array_map('trim', file('registry/minifiedScripts.txt')), function($s) {
638  return strlen($s) && $s[0] != '#'; // Exclude empty and commented (#) lines
639  });
640  foreach ($minifiedScripts as $key => $script) {
641  $this->addJavaScript( 'pkpLib' . $key, "$baseUrl/$script", $args);
642  }
643  }
644 
655  function registerJSLibraryData() {
656 
657  $context = $this->_request->getContext();
658 
659  // Instantiate the namespace
660  $output = '$.pkp = $.pkp || {};';
661 
662  // Load data intended for general use by the app
663  import('lib.pkp.classes.security.Role');
664 
665  $app_data = [
666  'cdnEnabled' => Config::getVar('general', 'enable_cdn'),
667  'currentLocale' => AppLocale::getLocale(),
668  'primaryLocale' => AppLocale::getPrimaryLocale(),
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' : '',
676  ];
677 
678  $output .= '$.pkp.app = ' . json_encode($app_data) . ';';
679 
680  // Load exposed constants
681  $output .= '$.pkp.cons = ' . json_encode($this->_constants) . ';';
682 
683  // Allow plugins to load data within their own namespace
684  $output .= '$.pkp.plugins = {};';
685 
686  $this->addJavaScript(
687  'pkpLibData',
688  $output,
689  [
690  'priority' => STYLE_SEQUENCE_CORE,
691  'contexts' => 'backend',
692  'inline' => true,
693  ]
694  );
695  }
696 
700  function setupBackendPage() {
701 
702  $request = Application::get()->getRequest();
703  $dispatcher = $request->getDispatcher();
704  $router = $request->getRouter();
705 
706  if (empty($this->get_template_vars('pageComponent'))) {
707  $this->assign('pageComponent', 'Page');
708  }
709 
710  $this->setConstants([
711  'REALLY_BIG_NUMBER',
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',
720  'ROLE_ID_MANAGER',
721  'ROLE_ID_SITE_ADMIN',
722  'ROLE_ID_AUTHOR',
723  'ROLE_ID_REVIEWER',
724  'ROLE_ID_ASSISTANT',
725  'ROLE_ID_READER',
726  'ROLE_ID_SUB_EDITOR',
727  'ROLE_ID_SUBSCRIPTION_MANAGER',
728  ]);
729 
730  // Common locale keys available in the browser for every page
731  $this->setLocaleKeys([
732  'common.cancel',
733  'common.clearSearch',
734  'common.close',
735  'common.commaListSeparator',
736  'common.confirm',
737  'common.delete',
738  'common.edit',
739  'common.error',
740  'common.filter',
741  'common.filterAdd',
742  'common.filterRemove',
743  'common.loading',
744  'common.no',
745  'common.noItemsFound',
746  'common.none',
747  'common.ok',
748  'common.orderUp',
749  'common.orderDown',
750  'common.pageNumber',
751  'common.pagination.goToPage',
752  'common.pagination.label',
753  'common.pagination.next',
754  'common.pagination.previous',
755  'common.remove',
756  'common.required',
757  'common.save',
758  'common.saving',
759  'common.search',
760  'common.selectWithName',
761  'common.unknownError',
762  'common.view',
763  'common.viewLess',
764  'common.viewMore',
765  'common.viewWithName',
766  'common.yes',
767  'form.dataHasChanged',
768  'form.errorA11y',
769  'form.errorGoTo',
770  'form.errorMany',
771  'form.errorOne',
772  'form.errors',
773  'form.multilingualLabel',
774  'form.multilingualProgress',
775  'form.saved',
776  'help.help',
777  'navigation.backTo',
778  'validator.required'
779  ]);
780 
781  // Register the jQuery script
782  $min = Config::getVar('general', 'enable_minified') ? '.min' : '';
783  if (Config::getVar('general', 'enable_cdn')) {
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';
786  } else {
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';
789  }
790  $this->addJavaScript(
791  'jquery',
792  $jquery,
793  [
794  'priority' => STYLE_SEQUENCE_CORE,
795  'contexts' => 'backend',
796  ]
797  );
798  $this->addJavaScript(
799  'jqueryUI',
800  $jqueryUI,
801  [
802  'priority' => STYLE_SEQUENCE_CORE,
803  'contexts' => 'backend',
804  ]
805  );
806 
807  // Load Noto Sans font from Google Font CDN
808  // To load extended latin or other character sets, see:
809  // https://www.google.com/fonts#UsePlace:use/Collection:Noto+Sans
810  if (Config::getVar('general', 'enable_cdn')) {
811  $this->addStyleSheet(
812  'pkpLibNotoSans',
813  '//fonts.googleapis.com/css?family=Noto+Sans:400,400italic,700,700italic',
814  [
815  'priority' => STYLE_SEQUENCE_CORE,
816  'contexts' => 'backend',
817  ]
818  );
819  }
820 
821  // Register the pkp-lib JS library
822  $this->registerJSLibraryData();
823  $this->registerJSLibrary();
824 
825  // FontAwesome - http://fontawesome.io/
826  if (Config::getVar('general', 'enable_cdn')) {
827  $url = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css';
828  } else {
829  $url = $request->getBaseUrl() . '/lib/pkp/styles/fontawesome/fontawesome.css';
830  }
831  $this->addStyleSheet(
832  'fontAwesome',
833  $url,
834  [
835  'priority' => STYLE_SEQUENCE_CORE,
836  'contexts' => 'backend',
837  ]
838  );
839 
840  // Stylesheet compiled from Vue.js single-file components
841  $this->addStyleSheet(
842  'build',
843  $request->getBaseUrl() . '/styles/build.css',
844  [
845  'priority' => STYLE_SEQUENCE_CORE,
846  'contexts' => 'backend',
847  ]
848  );
849 
850  // The legacy stylesheet for the backend
851  $this->addStyleSheet(
852  'pkpLib',
853  $dispatcher->url($request, ROUTE_COMPONENT, null, 'page.PageHandler', 'css'),
854  [
855  'priority' => STYLE_SEQUENCE_CORE,
856  'contexts' => 'backend',
857  ]
858  );
859 
860  // If there's a locale-specific stylesheet, add it.
861  if (($localeStyleSheet = AppLocale::getLocaleStyleSheet(AppLocale::getLocale())) != null) {
862  $this->addStyleSheet(
863  'pkpLibLocale',
864  $request->getBaseUrl() . '/' . $localeStyleSheet,
865  [
866  'contexts' => ['backend'],
867  ]
868  );
869  }
870 
871  // Set up required state properties
872  $this->setState([
873  'menu' => [],
874  ]);
875 
880  if (Config::getVar('general', 'installed') && !defined('SESSION_DISABLE_INIT')) {
881 
882  if ($request->getUser()) {
883 
884  // Get a count of unread tasks
885  $notificationDao = DAORegistry::getDAO('NotificationDAO'); /* @var $notificationDao NotificationDAO */
886  import('lib.pkp.controllers.grid.notifications.TaskNotificationsGridHandler');
887  $unreadTasksCount = (int) $notificationDao->getNotificationCount(false, $request->getUser()->getId(), null, NOTIFICATION_LEVEL_TASK);
888 
889  // Get a URL to load the tasks grid
890  $tasksUrl = $request->getDispatcher()->url($request, ROUTE_COMPONENT, null, 'page.PageHandler', 'tasks');
891 
892  // Load system notifications in SiteHandler.js
893  $notificationDao = DAORegistry::getDAO('NotificationDAO'); /* @var $notificationDao NotificationDAO */
894  $notifications = $notificationDao->getByUserId($request->getUser()->getId(), NOTIFICATION_LEVEL_TRIVIAL);
895 
896  // Load context switcher
897  if (in_array(ROLE_ID_SITE_ADMIN, $this->get_template_vars('userRoles'))) {
898  $args = [];
899  } else {
900  $args = ['userId' => $request->getUser()->getId()];
901  }
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();
906  });
907  }
908  $requestedPage = $router->getRequestedPage($request);
909  foreach ($availableContexts as $availableContext) {
910  // Site admins redirected to the same page. Everyone else to submission lists
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));
913  } else {
914  $availableContext->url = $dispatcher->url($request, ROUTE_PAGE, $availableContext->urlPath, 'submissions');
915  }
916  }
917 
918  // Create main navigation menu
919  $userRoles = (array) $router->getHandler()->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
920 
921  $menu = [];
922 
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',
929  ];
930  } elseif (count($userRoles) === 1 && in_array(ROLE_ID_READER, $userRoles)) {
931  AppLocale::requireComponents(LOCALE_COMPONENT_APP_AUTHOR);
932  $menu['submit'] = [
933  'name' => __('author.submit'),
934  'url' => $router->url($request, null, 'submission', 'wizard'),
935  'isCurrent' => $router->getRequestedPage($request) === 'submission',
936  ];
937  }
938 
939  if (count(array_intersect([ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR], $userRoles))) {
940  $menu['statistics'] = [
941  'name' => __('navigation.tools.statistics'),
942  'submenu' => [
943  'publications' => [
944  'name' => __('common.publications'),
945  'url' => $router->url($request, null, 'stats', 'publications', 'publications'),
946  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'publications',
947  ],
948  'editorial' => [
949  'name' => __('stats.editorialActivity'),
950  'url' => $router->url($request, null, 'stats', 'editorial', 'editorial'),
951  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'editorial',
952  ],
953  'users' => [
954  'name' => __('manager.users'),
955  'url' => $router->url($request, null, 'stats', 'users', 'users'),
956  'isCurrent' => $router->getRequestedPage($request) === 'stats' && $router->getRequestedOp($request) === 'users',
957  ]
958  ]
959  ];
960  }
961 
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)),
968  ];
969  }
970  $menu['statistics']['submenu'] += [
971  'reports' => [
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',
975  ]
976  ];
977  $menu['settings'] = [
978  'name' => __('navigation.settings'),
979  'submenu' => [
980  'context' => [
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)),
984  ],
985  'website' => [
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)),
989  ],
990  'workflow' => [
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)),
994  ],
995  'distribution' => [
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)),
999  ],
1000  'access' => [
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)),
1004  ]
1005  ]
1006  ];
1007  $menu['tools'] = [
1008  'name' => __('navigation.tools'),
1009  'url' => $router->url($request, null, 'management', 'tools'),
1010  'isCurrent' => $router->getRequestedPage($request) === 'management' && $router->getRequestedOp($request) === 'tools',
1011  ];
1012  }
1013 
1014  if (in_array(ROLE_ID_SITE_ADMIN, $userRoles)) {
1015  $menu['admin'] = [
1016  'name' => __('navigation.admin'),
1017  'url' => $router->url($request, 'index', 'admin'),
1018  'isCurrent' => $router->getRequestedPage($request) === 'admin',
1019  ];
1020  }
1021  }
1022 
1023  $this->setState([
1024  'menu' => $menu,
1025  'tasksUrl' => $tasksUrl,
1026  'unreadTasksCount' => $unreadTasksCount,
1027  ]);
1028 
1029  $this->assign([
1030  'availableContexts' => $availableContexts,
1031  'hasSystemNotifications' => $notifications->getCount() > 0,
1032  ]);
1033  }
1034  }
1035 
1036  HookRegistry::call('TemplateManager::setupBackendPage');
1037  }
1038 
1042  function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null) {
1043 
1044  // If no compile ID was assigned, get one.
1045  if (!$compile_id) $compile_id = $this->getCompileId($template);
1046 
1047  // Give hooks an opportunity to override
1048  $result = null;
1049  if (HookRegistry::call('TemplateManager::fetch', [$this, $template, $cache_id, $compile_id, &$result])) return $result;
1050 
1051  return parent::fetch($template, $cache_id, $compile_id, $parent);
1052  }
1053 
1061  function fetchAjax($id, $url, $element = 'div') {
1062  return new JSONMessage(true, $this->smartyLoadUrlInEl(
1063  [
1064  'url' => $url,
1065  'id' => $id,
1066  'el' => $element,
1067  ],
1068  $this
1069  ));
1070  }
1071 
1077  function getCompileId($resourceName) {
1078 
1079  if ( Config::getVar('general', 'installed' ) ) {
1080  $context = $this->_request->getContext();
1081  if (is_a($context, 'Context')) {
1082  $resourceName .= $context->getData('themePluginPath');
1083  }
1084  }
1085 
1086  return sha1($resourceName);
1087  }
1095  function fetchJson($template, $status = true) {
1096  import('lib.pkp.classes.core.JSONMessage');
1097  return new JSONMessage($status, $this->fetch($template));
1098  }
1099 
1103  function display($template = null, $cache_id = null, $compile_id = null, $parent = null) {
1105  // Output global constants and locale keys used in new component library
1106  $output = '';
1107  if (!empty($this->_constants)) {
1108  $output .= 'pkp.const = ' . json_encode($this->_constants) . ';';
1109  }
1110  if (!empty($this->_localeKeys)) {
1111  $output .= 'pkp.localeKeys = ' . json_encode($this->_localeKeys) . ';';
1112  }
1113 
1114  // Load current user data
1115  if (Config::getVar('general', 'installed')) {
1116  $user = $this->_request->getUser();
1117  if ($user) {
1118  $userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
1119  $userGroupsResult = $userGroupDao->getByUserId($user->getId());
1120  $userRoles = [];
1121  while ($userGroup = $userGroupsResult->next()) {
1122  $userRoles[] = (int) $userGroup->getRoleId();
1123  }
1124  $currentUser = [
1125  'csrfToken' => $this->_request->getSession()->getCSRFToken(),
1126  'id' => (int) $user->getId(),
1127  'roles' => array_values(array_unique($userRoles)),
1128  ];
1129  $output .= 'pkp.currentUser = ' . json_encode($currentUser) . ';';
1130  }
1131  }
1132 
1133  $this->addJavaScript(
1134  'pkpAppData',
1135  $output,
1136  [
1137  'priority' => STYLE_SEQUENCE_LATE,
1138  'contexts' => ['backend'],
1139  'inline' => true,
1140  ]
1141  );
1142 
1143  // Give any hooks registered against the TemplateManager
1144  // the opportunity to modify behavior; otherwise, display
1145  // the template as usual.
1146  $output = null;
1147  if (HookRegistry::call('TemplateManager::display', [$this, &$template, &$output])) {
1148  echo $output;
1149  return;
1150  }
1151 
1152  // Pass the initial state data for this page
1153  $this->assign('state', $this->_state);
1154 
1155  // Explicitly set the character encoding. Required in
1156  // case server is using Apache's AddDefaultCharset
1157  // directive (which can prevent browser auto-detection
1158  // of the proper character set).
1159  header('Content-Type: text/html; charset=' . Config::getVar('i18n', 'client_charset'));
1160  header('Cache-Control: ' . $this->_cacheability);
1161 
1162  // If no compile ID was assigned, get one.
1163  if (!$compile_id) $compile_id = $this->getCompileId($template);
1164 
1165  // Actually display the template.
1166  parent::display($template, $cache_id, $compile_id, $parent);
1167  }
1168 
1169 
1173  function clearTemplateCache() {
1174  $this->clearCompiledTemplate();
1175  $this->clearAllCache();
1176  }
1177 
1181  public function clearCssCache() {
1182  $cacheDirectory = CacheManager::getFileCachePath();
1183  $files = scandir($cacheDirectory);
1184  array_map('unlink', glob(CacheManager::getFileCachePath() . DIRECTORY_SEPARATOR . '*.' . CSS_FILENAME_SUFFIX));
1185  }
1186 
1198  public function clearThemeTemplateCache($hookName, $args) {
1199  $newContextOrSite = $args[0];
1200  $contextOrSite = $args[1];
1201  if ($newContextOrSite->getData('themePluginPath') !== $contextOrSite->getData('themePluginPath')) {
1202  $this->clearTemplateCache();
1203  $this->clearCssCache();
1204  }
1205  }
1206 
1212  static function &getManager($request = null) {
1213  if (!isset($request)) {
1214  $request = Registry::get('request');
1215  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call without request object.');
1216  }
1217  assert(is_a($request, 'PKPRequest'));
1218 
1219  $instance =& Registry::get('templateManager', true, null); // Reference required
1220 
1221  if ($instance === null) {
1222  $instance = new TemplateManager();
1223  $themes = PluginRegistry::getPlugins('themes');
1224  if (empty($themes)) {
1225  $themes = PluginRegistry::loadCategory('themes', true);
1226  }
1227  $instance->initialize($request);
1228  }
1229 
1230  return $instance;
1231  }
1232 
1237  function getFBV() {
1238  if(!$this->_fbv) {
1239  import('lib.pkp.classes.form.FormBuilderVocabulary');
1240  $this->_fbv = new FormBuilderVocabulary();
1241  }
1242  return $this->_fbv;
1243  }
1244 
1255  public function displaySidebar($hookName, $args) {
1256  $params =& $args[0];
1257  $smarty =& $args[1];
1258  $output =& $args[2];
1259 
1260  if ($this->_request->getContext()) {
1261  $blocks = $this->_request->getContext()->getData('sidebar');
1262  } else {
1263  $blocks = $this->_request->getSite()->getData('sidebar');
1264  }
1265 
1266  if (empty($blocks)) {
1267  return false;
1268  }
1269 
1270  $plugins = PluginRegistry::loadCategory('blocks', true);
1271  if (empty($plugins)) {
1272  return false;
1273  }
1274 
1275  foreach ($blocks as $pluginName) {
1276  if (!empty($plugins[$pluginName])) {
1277  $output .= $plugins[$pluginName]->getContents($smarty, $this->_request);
1278  }
1279  }
1280 
1281  return false;
1282  }
1283 
1284 
1285  //
1286  // Custom template functions, modifiers, etc.
1287  //
1288 
1300  function smartyTranslate($params, $smarty) {
1301  if (isset($params) && !empty($params)) {
1302  if (!isset($params['key'])) return __('');
1303 
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);
1310  }
1311  return __($key, $params);
1312  }
1313  }
1314 
1323  function smartyNullLinkAction($params, $smarty) {
1324  assert(isset($params['id']));
1325 
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;
1331 
1332  import('lib.pkp.classes.linkAction.request.NullAction');
1333  import('lib.pkp.classes.linkAction.LinkAction');
1334  $key = $translate ? __($key) : $key;
1335  $this->assign('action', new LinkAction(
1336  $id, new NullAction(), $key, $image
1337  ));
1338 
1339  $this->assign('hoverTitle', $hoverTitle);
1340  return $this->fetch('linkAction/linkAction.tpl');
1341  }
1342 
1350  function smartyHelp($params, $smarty) {
1351  assert(isset($params['file']));
1352 
1353  $params = array_merge(
1354  [
1355  'file' => null, // The name of the Markdown file
1356  'section' => null, // The (optional) anchor within the Markdown file
1357  'textKey' => 'help.help', // An (optional) locale key for the link
1358  'text' => null, // An (optional) literal text for the link
1359  'class' => null, // An (optional) CSS class string for the link
1360  ],
1361  $params
1362  );
1363 
1364  $this->assign([
1365  'helpFile' => $params['file'],
1366  'helpSection' => $params['section'],
1367  'helpTextKey' => $params['textKey'],
1368  'helpText' => $params['text'],
1369  'helpClass' => $params['class'],
1370  ]);
1371 
1372  return $this->fetch('common/helpLink.tpl');
1373  }
1374 
1383  function smartyHtmlOptionsTranslate($params, $smarty) {
1384  if (isset($params['options'])) {
1385  if (isset($params['translateValues'])) {
1386  // Translate values AND output
1387  $newOptions = [];
1388  foreach ($params['options'] as $k => $v) {
1389  $newOptions[__($k)] = __($v);
1390  }
1391  $params['options'] = $newOptions;
1392  } else {
1393  // Just translate output
1394  $params['options'] = array_map('AppLocale::translate', $params['options']);
1395  }
1396  }
1397 
1398  if (isset($params['output'])) {
1399  $params['output'] = array_map('AppLocale::translate', $params['output']);
1400  }
1401 
1402  if (isset($params['values']) && isset($params['translateValues'])) {
1403  $params['values'] = array_map('AppLocale::translate', $params['values']);
1404  }
1405 
1406  require_once('lib/pkp/lib/vendor/smarty/smarty/libs/plugins/function.html_options.php');
1407  return smarty_function_html_options($params, $smarty);
1408  }
1409 
1418  function smartyIterate($params, $content, $smarty, &$repeat) {
1419  $iterator = $smarty->getTemplateVars($params['from']);
1420 
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);
1424  }
1425 
1426  // If the iterator is empty, we're finished.
1427  if (!$iterator || $iterator->eof()) {
1428  if (!$repeat) return $content;
1429  $repeat = false;
1430  return '';
1431  }
1432 
1433  $repeat = true;
1434 
1435  if (isset($params['key'])) {
1436  list($key, $value) = $iterator->nextWithKey();
1437  $smarty->assign($params['item'], $value);
1438  $smarty->assign($params['key'], $key);
1439  } else {
1440  $smarty->assign($params['item'], $iterator->next());
1441  }
1442  return $content;
1443  }
1444 
1451  function smartyPageInfo($params, $smarty) {
1452  $iterator = $params['iterator'];
1453 
1454  if (isset($params['itemsPerPage'])) {
1455  $itemsPerPage = $params['itemsPerPage'];
1456  } else {
1457  $itemsPerPage = $smarty->getTemplateVars('itemsPerPage');
1458  if (!is_numeric($itemsPerPage)) $itemsPerPage=25;
1459  }
1460 
1461  $page = $iterator->getPage();
1462  $pageCount = $iterator->getPageCount();
1463  $itemTotal = $iterator->getCount();
1464 
1465  if ($pageCount<1) return '';
1466 
1467  $from = (($page - 1) * $itemsPerPage) + 1;
1468  $to = min($itemTotal, $page * $itemsPerPage);
1469 
1470  return __('navigation.items', [
1471  'from' => ($to===0?0:$from),
1472  'to' => $to,
1473  'total' => $itemTotal
1474  ]);
1475  }
1476 
1482  function smartyFlush($params, $smarty) {
1483  $smarty->flush();
1484  }
1485 
1486  function flush() {
1487  while (ob_get_level()) {
1488  ob_end_flush();
1489  }
1490  flush();
1491  }
1492 
1496  function smartyCallHook($params, $smarty) {
1497  $output = null;
1498  HookRegistry::call($params['name'], [&$params, $smarty, &$output]);
1499  return $output;
1500  }
1501 
1517  function smartyUrl($parameters, $smarty) {
1518  if ( !isset($parameters['context']) ) {
1519  // Extract the variables named in $paramList, and remove them
1520  // from the parameters array. Variables remaining in params will be
1521  // passed along to Request::url as extra parameters.
1522  $context = [];
1524  $contextList = $application->getContextList();
1525  foreach ($contextList as $contextName) {
1526  if (isset($parameters[$contextName])) {
1527  $context[$contextName] = $parameters[$contextName];
1528  unset($parameters[$contextName]);
1529  } else {
1530  $context[$contextName] = null;
1531  }
1532  }
1533  $parameters['context'] = $context;
1534  }
1535 
1536  // Extract the reserved variables named in $paramList, and remove them
1537  // from the parameters array. Variables remaining in parameters will be passed
1538  // along to Request::url as extra parameters.
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]);
1544  } else {
1545  $$parameter = null;
1546  }
1547  }
1548 
1549  // Merge parameters specified in the {url paramName=paramValue} format with
1550  // those optionally supplied in {url params=$someAssociativeArray} format
1551  $parameters = array_merge($parameters, (array) $params);
1552 
1553  // Set the default router
1554  if (is_null($router)) {
1555  if (is_a($this->_request->getRouter(), 'PKPComponentRouter')) {
1556  $router = ROUTE_COMPONENT;
1557  } else {
1558  $router = ROUTE_PAGE;
1559  }
1560  }
1561 
1562  // Check the router
1563  $dispatcher = Application::get()->getDispatcher();
1564  $routerShortcuts = array_keys($dispatcher->getRouterNames());
1565  assert(in_array($router, $routerShortcuts));
1566 
1567  // Identify the handler
1568  switch($router) {
1569  case ROUTE_PAGE:
1570  $handler = $page;
1571  break;
1572 
1573  case ROUTE_COMPONENT:
1574  $handler = $component;
1575  break;
1576 
1577  default:
1578  // Unknown router type
1579  assert(false);
1580  }
1581 
1582  // Let the dispatcher create the url
1583  return $dispatcher->url($this->_request, $router, $context, $handler, $op, $path, $parameters, $anchor, !isset($escape) || $escape);
1584  }
1585 
1604  function smartyTitle($parameters, $smarty) {
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');
1610  } else {
1611  $siteTitle = __('common.software');
1612  }
1613 
1614  if (empty($parameters['value'])) {
1615  return $siteTitle;
1616  }
1617 
1618  return $parameters['value'] . __('common.titleSeparator') . $siteTitle;
1619  }
1620 
1631  function smartyPageLinks($params, $smarty) {
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);
1638  }
1639  if (isset($params['anchor'])) {
1640  $anchor = $params['anchor'];
1641  unset($params['anchor']);
1642  } else {
1643  $anchor = null;
1644  }
1645  if (isset($params['all_extra'])) {
1646  $allExtra = ' ' . $params['all_extra'];
1647  unset($params['all_extra']);
1648  } else {
1649  $allExtra = '';
1650  }
1651 
1652  unset($params['iterator']);
1653  unset($params['name']);
1654 
1655  $numPageLinks = $smarty->getTemplateVars('numPageLinks');
1656  if (!is_numeric($numPageLinks)) $numPageLinks=10;
1657 
1658  $page = $iterator->getPage();
1659  $pageCount = $iterator->getPageCount();
1660 
1661  $pageBase = max($page - floor($numPageLinks / 2), 1);
1662  $paramName = $name . 'Page';
1663 
1664  if ($pageCount<=1) return '';
1665 
1666  $value = '';
1667 
1668  $router = $this->_request->getRouter();
1669  $requestedArgs = null;
1670  if (is_a($router, 'PageRouter')) {
1671  $requestedArgs = $router->getRequestedArgs($this->_request);
1672  }
1673 
1674  if ($page>1) {
1675  $params[$paramName] = 1;
1676  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&lt;&lt;</a>&nbsp;';
1677  $params[$paramName] = $page - 1;
1678  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&lt;</a>&nbsp;';
1679  }
1680 
1681  for ($i=$pageBase; $i<min($pageBase+$numPageLinks, $pageCount+1); $i++) {
1682  if ($i == $page) {
1683  $value .= "<strong>$i</strong>&nbsp;";
1684  } else {
1685  $params[$paramName] = $i;
1686  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>' . $i . '</a>&nbsp;';
1687  }
1688  }
1689  if ($page < $pageCount) {
1690  $params[$paramName] = $page + 1;
1691  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&gt;</a>&nbsp;';
1692  $params[$paramName] = $pageCount;
1693  $value .= '<a href="' . $this->_request->url(null, null, null, $requestedArgs, $params, $anchor) . '"' . $allExtra . '>&gt;&gt;</a>&nbsp;';
1694  }
1695 
1696  return $value;
1697  }
1698 
1702  function smartyToArray() {
1703  return func_get_args();
1704  }
1705 
1709  function smartyConcat() {
1710  $args = func_get_args();
1711  return implode('', $args);
1712  }
1713 
1721  function smartyCompare($a, $b, $strict = false, $invert = false) {
1722  $result = $strict?$a===$b:$a==$b;
1723  return $invert?!$result:$result;
1724  }
1725 
1729  function smartyStrtotime($string) {
1730  return strtotime($string);
1731  }
1732 
1736  function smartyExplode($string, $separator) {
1737  return explode($separator, $string);
1738  }
1739 
1744  function smartyEscape($string, $esc_type = 'html', $char_set = 'ISO-8859-1') {
1745  $pattern = "/(:|\.|\[|\]|,|=|@)/";
1746  $replacement = "\\\\\\\\$1";
1747  switch ($esc_type) {
1748  // Because jQuery uses CSS syntax for selecting elements
1749  // some characters are interpreted as CSS notation.
1750  // In order to tell jQuery to treat these characters literally rather
1751  // than as CSS notation, they must be escaped by placing two backslashes
1752  // in front of them.
1753  case 'jqselector':
1754  $result = smarty_modifier_escape($string, 'html', $char_set);
1755  $result = preg_replace($pattern, $replacement, $result);
1756  return $result;
1757 
1758  case 'jsid':
1759  $result = smarty_modifier_escape($string, 'javascript', $char_set);
1760  $result = preg_replace($pattern, $replacement, $result);
1761  return $result;
1762 
1763  default:
1764  return smarty_modifier_escape($string, $esc_type, $char_set);
1765  }
1766  }
1767 
1776  function smartyLoadUrlInEl($params, $smarty) {
1777  // Required Params
1778  if (!isset($params['el'])) {
1779  throw new Exception("el parameter is missing from load_url_in_el");
1780  }
1781  if (!isset($params['url'])) {
1782  throw new Exception("url parameter is missing from load_url_in_el");
1783  }
1784  if (!isset($params['id'])) {
1785  throw new Exception("id parameter is missing from load_url_in_el");
1786  }
1787 
1788  $this->assign([
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,
1794  ]);
1795 
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));
1801  } else {
1802  $this->assign('inElPlaceholder', $this->fetch('common/loadingContainer.tpl'));
1803  }
1804 
1805  return $this->fetch('common/urlInEl.tpl');
1806  }
1807 
1817  function smartyLoadUrlInDiv($params, $smarty) {
1818  $params['el'] = 'div';
1819  return $this->smartyLoadUrlInEl( $params, $smarty );
1820  }
1821 
1830  function smartyCSRF($params, $smarty) {
1831  $csrfToken = $this->_request->getSession()->getCSRFToken();
1832  switch (isset($params['type'])?$params['type']:null) {
1833  case 'raw': return $csrfToken;
1834  case 'json': return json_encode($csrfToken);
1835  case 'html':
1836  default:
1837  return '<input type="hidden" name="csrfToken" value="' . htmlspecialchars($csrfToken) . '">';
1838  }
1839  }
1840 
1849  function smartyLoadStylesheet($params, $smarty) {
1850 
1851  if (empty($params['context'])) {
1852  $params['context'] = 'frontend';
1853  }
1854 
1855  if (!defined('SESSION_DISABLE_INIT')) {
1856  $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */
1857  $appVersion = $versionDao->getCurrentVersion()->getVersionString();
1858  } else $appVersion = null;
1859 
1860  $stylesheets = $this->getResourcesByContext($this->_styleSheets, $params['context']);
1861 
1862  ksort($stylesheets);
1863 
1864  $output = '';
1865  foreach($stylesheets as $priorityList) {
1866  foreach($priorityList as $style) {
1867  if (!empty($style['inline'])) {
1868  $output .= '<style type="text/css">' . $style['style'] . '</style>';
1869  } else {
1870  if ($appVersion && strpos($style['style'], '?') === false) {
1871  $style['style'] .= '?v=' . $appVersion;
1872  }
1873  $output .= '<link rel="stylesheet" href="' . $style['style'] . '" type="text/css" />';
1874  }
1875  }
1876  }
1877 
1878  return $output;
1879  }
1880 
1890  function loadHtmlGalleyStyles($htmlContent, $embeddedFiles) {
1891 
1892  if (empty($htmlContent)) {
1893  return $htmlContent;
1894  }
1895 
1896  $hasEmbeddedStyle = false;
1897  foreach ($embeddedFiles as $embeddedFile) {
1898  if ($embeddedFile->getFileType() === 'text/css') {
1899  $hasEmbeddedStyle = true;
1900  break;
1901  }
1902  }
1903 
1904  if ($hasEmbeddedStyle) {
1905  return $htmlContent;
1906  }
1907 
1908  $links = '';
1909  $styles = $this->getResourcesByContext($this->_styleSheets, 'htmlGalley');
1910 
1911  if (!empty($styles)) {
1912  ksort($styles);
1913  foreach ($styles as $priorityGroup) {
1914  foreach ($priorityGroup as $htmlStyle) {
1915  $links .= '<link rel="stylesheet" href="' . $htmlStyle['style'] . '" type="text/css">' . "\n";
1916  }
1917  }
1918  }
1919 
1920  return str_ireplace('<head>', '<head>' . "\n" . $links, $htmlContent);
1921  }
1922 
1931  function smartyLoadScript($params, $smarty) {
1932 
1933  if (empty($params['context'])) {
1934  $params['context'] = 'frontend';
1935  }
1936 
1937  if (!defined('SESSION_DISABLE_INIT')) {
1938  $versionDao = DAORegistry::getDAO('VersionDAO'); /* @var $versionDao VersionDAO */
1939  $appVersion = defined('SESSION_DISABLE_INIT') ? null : $versionDao->getCurrentVersion()->getVersionString();
1940  } else $appVersion = null;
1941 
1942  $scripts = $this->getResourcesByContext($this->_javaScripts, $params['context']);
1943 
1944  ksort($scripts);
1945 
1946  $output = '';
1947  foreach($scripts as $priorityList) {
1948  foreach($priorityList as $name => $data) {
1949  if ($data['inline']) {
1950  $output .= '<script type="text/javascript">' . $data['script'] . '</script>';
1951  } else {
1952  if ($appVersion && strpos($data['script'], '?') === false) {
1953  $data['script'] .= '?v=' . $appVersion;
1954  }
1955  $output .= '<script src="' . $data['script'] . '" type="text/javascript"></script>';
1956  }
1957  }
1958  }
1959 
1960  return $output;
1961  }
1962 
1971  function smartyLoadHeader($params, $smarty) {
1972 
1973  if (empty($params['context'])) {
1974  $params['context'] = 'frontend';
1975  }
1976 
1977  $headers = $this->getResourcesByContext($this->_htmlHeaders, $params['context']);
1978 
1979  ksort($headers);
1980 
1981  $output = '';
1982  foreach($headers as $priorityList) {
1983  foreach($priorityList as $name => $data) {
1984  $output .= "\n" . $data['header'];
1985  }
1986  }
1987 
1988  return $output;
1989  }
1990 
1999  function smartyLoadNavigationMenuArea($params, $smarty) {
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();
2006  }
2007 
2008  // Don't load menus for an area that's not registered by the active theme
2009  $themePlugins = PluginRegistry::getPlugins('themes');
2010  if (empty($themePlugins)) {
2011  $themePlugins = PluginRegistry::loadCategory('themes', true);
2012  }
2013  $activeThemeNavigationAreas = [];
2014  foreach ($themePlugins as $themePlugin) {
2015  if ($themePlugin->isActive()) {
2016  $areas = $themePlugin->getMenuAreas();
2017  if (!in_array($areaName, $areas)) {
2018  return '';
2019  }
2020  }
2021  }
2022 
2023  $menuTemplatePath = 'frontend/components/navigationMenu.tpl';
2024  if (isset($declaredMenuTemplatePath)) {
2025  $menuTemplatePath = $declaredMenuTemplatePath;
2026  }
2027 
2028  $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /* @var $navigationMenuDao NavigationMenuDAO */
2029 
2030  $output = '';
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);
2036  }
2037 
2038 
2039  $this->assign([
2040  'navigationMenu' => $navigationMenu,
2041  'id' => $params['id'],
2042  'ulClass' => $params['ulClass'],
2043  'liClass' => $params['liClass'],
2044  ]);
2045 
2046  return $this->fetch($menuTemplatePath);
2047  }
2048 
2058  function getResourcesByContext($resources, $context) {
2059  $matches = [];
2060 
2061  if (array_key_exists($context, $resources)) {
2062  $matches = $resources[$context];
2063  }
2064 
2065  $page = $this->getTemplateVars('requestedPage');
2066  $page = empty( $page ) ? 'index' : $page;
2067  $op = $this->getTemplateVars('requestedOp');
2068  $op = empty( $op ) ? 'index' : $op;
2069 
2070  $contexts = [
2071  join('-', [$context, $page]),
2072  join('-', [$context, $page, $op]),
2073  ];
2074 
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] = [];
2080  }
2081  $matches[$priority] = array_merge($matches[$priority], $resources[$context][$priority]);
2082  }
2083  $matches += $resources[$context];
2084  }
2085  }
2086 
2087  return $matches;
2088  }
2089 
2099  function smartyPluckFiles($params, $smarty) {
2100 
2101  // The variable to assign the result to.
2102  if (empty($params['assign'])) {
2103  error_log('Smarty: {pluck_files} function called without required `assign` param. Called in ' . __FILE__ . ':' . __LINE__);
2104  return;
2105  }
2106 
2107  // $params['files'] should be an array of SubmissionFile objects
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'], []);
2111  return;
2112  }
2113 
2114  // $params['by'] is one of an approved list of attributes to select by
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'], []);
2118  return;
2119  }
2120 
2121  // The approved list of `by` attributes
2122  // 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
2123  // publicationFormat Any files in a given publicationFormat ID
2124  // component Any files of a component type by class name: SubmissionFile|SubmissionArtworkFile|SupplementaryFile
2125  // fileExtension Any files with a file extension in all caps: PDF
2126  // genre Any files with a genre ID (file genres are configurable but typically refer to Manuscript, Bibliography, etc)
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'], []);
2130  return;
2131  }
2132 
2133  // The value to match against. See docs for `by` param
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'], []);
2137  return;
2138  }
2139 
2140  $matching_files = [];
2141 
2142  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
2143  foreach ($params['files'] as $file) {
2144  switch ($params['by']) {
2145 
2146  case 'chapter':
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;
2155  }
2156  }
2157  break;
2158 
2159  case 'publicationFormat':
2160  if ($file->getAssocId() == $params['value']) {
2161  $matching_files[] = $file;
2162  }
2163  break;
2164 
2165  case 'component':
2166  if (get_class($file) == $params['value']) {
2167  $matching_files[] = $file;
2168  }
2169  break;
2170 
2171  case 'fileExtension':
2172  if ($file->getExtension() == $params['value']) {
2173  $matching_files[] = $file;
2174  }
2175  break;
2176 
2177  case 'genre':
2178  if ($file->getGenreId() == $params['value']) {
2179  $matching_files[] = $file;
2180  }
2181  break;
2182  }
2183  }
2184 
2185  $smarty->assign($params['assign'], $matching_files);
2186  }
2187 
2192  public function get_template_vars($varname = null) {
2193  if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated call to Smarty2 function ' . __FUNCTION__);
2194  return $this->getTemplateVars($varname);
2195  }
2196 
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);
2207  }
2208 }
PKPTemplateManager\addStyleSheet
addStyleSheet($name, $style, $args=[])
Definition: PKPTemplateManager.inc.php:468
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:581
PKPTemplateManager\fetchJson
fetchJson($template, $status=true)
Definition: PKPTemplateManager.inc.php:1122
Validation\isLoggedInAs
static isLoggedInAs()
Definition: Validation.inc.php:388
PKPTemplateManager\registerJSLibraryData
registerJSLibraryData()
Definition: PKPTemplateManager.inc.php:682
PKPTemplateManager\smartyTranslate
smartyTranslate($params, $smarty)
Definition: PKPTemplateManager.inc.php:1327
CacheManager\getFileCachePath
static getFileCachePath()
Definition: CacheManager.inc.php:112
$application
$application
Definition: index.php:65
PKPTemplateManager\setLocaleKeys
setLocaleKeys($keys)
Definition: PKPTemplateManager.inc.php:567
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:1377
PKPTemplateManager\getCachedLessFilePath
getCachedLessFilePath($name)
Definition: PKPTemplateManager.inc.php:447
PKPTemplateManager\smartyFlush
smartyFlush($params, $smarty)
Definition: PKPTemplateManager.inc.php:1509
PKPTemplateManager\clearThemeTemplateCache
clearThemeTemplateCache($hookName, $args)
Definition: PKPTemplateManager.inc.php:1225
PKPTemplateManager\setState
setState($data)
Definition: PKPTemplateManager.inc.php:592
PKPTemplateManager\register_function
register_function($name, $impl, $cacheable=true, $cache_attrs=null)
Definition: PKPTemplateManager.inc.php:2231
PKPTemplateManager\smartyCallHook
smartyCallHook($params, $smarty)
Definition: PKPTemplateManager.inc.php:1523
PKPTemplateManager\smartyHtmlOptionsTranslate
smartyHtmlOptionsTranslate($params, $smarty)
Definition: PKPTemplateManager.inc.php:1410
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:556
PKPTemplateManager\smartyIterate
smartyIterate($params, $content, $smarty, &$repeat)
Definition: PKPTemplateManager.inc.php:1445
PKPTemplateManager\smartyPageInfo
smartyPageInfo($params, $smarty)
Definition: PKPTemplateManager.inc.php:1478
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:1844
PKPTemplateManager\smartyCompare
smartyCompare($a, $b, $strict=false, $invert=false)
Definition: PKPTemplateManager.inc.php:1748
PKPTemplateManager\smartyExplode
smartyExplode($string, $separator)
Definition: PKPTemplateManager.inc.php:1763
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:1729
PKPTemplateManager\clearTemplateCache
clearTemplateCache()
Definition: PKPTemplateManager.inc.php:1200
PKPTemplateManager\setCacheability
setCacheability($cacheability=CACHEABILITY_PUBLIC)
Definition: PKPTemplateManager.inc.php:376
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:1917
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:1756
PKPTemplateManager\smartyConcat
smartyConcat()
Definition: PKPTemplateManager.inc.php:1736
Seboettg\Collection\count
count()
Definition: ArrayListTrait.php:253
PKPTemplateManager\fetch
fetch($template=null, $cache_id=null, $compile_id=null, $parent=null)
Definition: PKPTemplateManager.inc.php:1069
PKPTemplateManager\registerJSLibrary
registerJSLibrary()
Definition: PKPTemplateManager.inc.php:599
PKPTemplateManager\smartyLoadUrlInEl
smartyLoadUrlInEl($params, $smarty)
Definition: PKPTemplateManager.inc.php:1803
PKPTemplateManager\getFBV
getFBV()
Definition: PKPTemplateManager.inc.php:1264
PKPTemplateManager\flush
flush()
Definition: PKPTemplateManager.inc.php:1513
PKPTemplateManager\__construct
__construct()
Definition: PKPTemplateManager.inc.php:109
PKPTemplateManager\smartyCSRF
smartyCSRF($params, $smarty)
Definition: PKPTemplateManager.inc.php:1857
PKPTemplateManager\getManager
static & getManager($request=null)
Definition: PKPTemplateManager.inc.php:1239
PKPTemplateManager\smartyEscape
smartyEscape($string, $esc_type='html', $char_set='ISO-8859-1')
Definition: PKPTemplateManager.inc.php:1771
PKPTemplateManager\get_template_vars
get_template_vars($varname=null)
Definition: PKPTemplateManager.inc.php:2219
FormBuilderVocabulary
Definition: FormBuilderVocabulary.inc.php:57
PKPTemplateManager\clearCssCache
clearCssCache()
Definition: PKPTemplateManager.inc.php:1208
PKPTemplateManager\addJavaScript
addJavaScript($name, $script, $args=[])
Definition: PKPTemplateManager.inc.php:502
PKPTemplateManager\smartyLoadStylesheet
smartyLoadStylesheet($params, $smarty)
Definition: PKPTemplateManager.inc.php:1876
PKPTemplateManager\smartyPageLinks
smartyPageLinks($params, $smarty)
Definition: PKPTemplateManager.inc.php:1658
PKPTemplateManager\smartyLoadScript
smartyLoadScript($params, $smarty)
Definition: PKPTemplateManager.inc.php:1958
PKPTemplateManager\smartyUrl
smartyUrl($parameters, $smarty)
Definition: PKPTemplateManager.inc.php:1544
PKPTemplateManager\getCompileId
getCompileId($resourceName)
Definition: PKPTemplateManager.inc.php:1104
PKPTemplateManager\setupBackendPage
setupBackendPage()
Definition: PKPTemplateManager.inc.php:727
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
PKPTemplateManager\smartyLoadNavigationMenuArea
smartyLoadNavigationMenuArea($params, $smarty)
Definition: PKPTemplateManager.inc.php:2026
PKPTemplateManager\displaySidebar
displaySidebar($hookName, $args)
Definition: PKPTemplateManager.inc.php:1282
Core\getBaseDir
static getBaseDir()
Definition: Core.inc.php:37
PKPTemplateManager\smartyLoadHeader
smartyLoadHeader($params, $smarty)
Definition: PKPTemplateManager.inc.php:1998
PKPTemplateManager\compileLess
compileLess($name, $lessFile, $args=[])
Definition: PKPTemplateManager.inc.php:390
PKPTemplateManager\fetchAjax
fetchAjax($id, $url, $element='div')
Definition: PKPTemplateManager.inc.php:1088
PKPTemplateManager\addHeader
addHeader($name, $header, $args=[])
Definition: PKPTemplateManager.inc.php:533
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
PKPTemplateManager\smartyPluckFiles
smartyPluckFiles($params, $smarty)
Definition: PKPTemplateManager.inc.php:2126
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:1130
AppLocale\getLocale
static getLocale()
Definition: env1/MockAppLocale.inc.php:40
PKPTemplateManager\getResourcesByContext
getResourcesByContext($resources, $context)
Definition: PKPTemplateManager.inc.php:2085
GuzzleHttp\json_encode
json_encode($value, $options=0, $depth=512)
Definition: guzzlehttp/guzzle/src/functions.php:324
PKPTemplateManager\smartyTitle
smartyTitle($parameters, $smarty)
Definition: PKPTemplateManager.inc.php:1631
PKPTemplateManager\smartyNullLinkAction
smartyNullLinkAction($params, $smarty)
Definition: PKPTemplateManager.inc.php:1350
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:432