Issues (1369)

classes/SnTemplate.php (28 issues)

1
<?php
2
3
use Common\Traits\TSingleton;
4
use Core\GlobalContainer;
5
use Fleet\DbFleetStatic;
6
use Note\Note;
7
use \Pages\PageTutorial;
0 ignored issues
show
The type \Pages\PageTutorial was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Planet\DBStaticPlanet;
9
use Player\playerTimeDiff;
10
use Template\TemplateMeta;
11
12
/**
13
 * Template manager
14
 */
15
class SnTemplate {
16
17
  use TSingleton;
18
19
  const TPL_HTML = '.tpl.html';
20
  /**
21
   * Partial path to templates root
22
   */
23
  const SN_TEMPLATES_PARTIAL_PATH = 'design/templates/';
24
  const SN_TEMPLATE_NAME_DEFAULT = 'OpenGame';
25
  const P_CONTENT = '__RENDERED_CONTENT';
26
27
  /**
28
   * @param template|string $template
29
   */
30
  public static function displayP($template) {
31
    if (is_object($template)) {
32
      if (empty($template->parsed)) {
33
        self::parsetemplate($template);
34
      }
35
36
      foreach ($template->files as $section => $filename) {
37
        $template->display($section);
38
      }
39
    } else {
40
      print($template);
41
    }
42
  }
43
44
  /**
45
   * @param template|string $template
46
   * @param array|bool      $array
47
   *
48
   * @return mixed
49
   */
50
  public static function parsetemplate($template, $array = false) {
51
    if (is_object($template)) {
52
      return self::templateObjectParse($template, $array);
53
    } else {
54
      $search[]  = '#\{L_([a-z0-9\-_]*?)\[([a-z0-9\-_]*?)\]\}#Ssie';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$search was never initialized. Although not strictly required by PHP, it is generally a good practice to add $search = array(); before regardless.
Loading history...
55
      $replace[] = '((isset($lang[\'\1\'][\'\2\'])) ? $lang[\'\1\'][\'\2\'] : \'{L_\1[\2]}\');';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$replace was never initialized. Although not strictly required by PHP, it is generally a good practice to add $replace = array(); before regardless.
Loading history...
56
57
      $search[]  = '#\{L_([a-z0-9\-_]*?)\}#Ssie';
58
      $replace[] = '((isset($lang[\'\1\'])) ? $lang[\'\1\'] : \'{L_\1}\');';
59
60
      $search[]  = '#\{([a-z0-9\-_]*?)\}#Ssie';
61
      $replace[] = '((isset($array[\'\1\'])) ? $array[\'\1\'] : \'{\1}\');';
62
63
      return preg_replace($search, $replace, $template);
64
    }
65
  }
66
67
  /**
68
   * @param template   $template
69
   * @param array|bool $array
70
   *
71
   * @return mixed
72
   */
73
  public static function templateObjectParse($template, $array = false) {
74
    global $user;
75
76
    if (!empty($array) && is_array($array)) {
77
      foreach ($array as $key => $data) {
78
        $template->assign_var($key, $data);
79
      }
80
    }
81
82
    $template->assign_vars(array(
83
      'SN_TIME_NOW'      => SN_TIME_NOW,
84
      'SN_TEMPLATE_NAME' => SnTemplate::getPlayerTemplateName(),
85
      'USER_AUTHLEVEL'   => isset($user['authlevel']) ? $user['authlevel'] : -1,
86
      'SN_GOOGLE'        => SN_GOOGLE,
87
    ));
88
89
    $template->parsed = true;
90
91
    return $template;
92
  }
93
94
  /**
95
   * @param array $menu
96
   * @param array $extra
97
   */
98
  public static function tpl_menu_merge_extra(&$menu, &$extra) {
99
    if (!is_array($extra) || !is_array($menu) || empty($menu)) {
0 ignored issues
show
The condition is_array($menu) is always true.
Loading history...
The condition is_array($extra) is always true.
Loading history...
100
      return;
101
    }
102
103
    foreach ($extra as $menu_item_id => $menu_item) {
104
      if (empty($menu_item['LOCATION'])) {
105
        $menu[$menu_item_id] = $menu_item;
106
        continue;
107
      }
108
109
      $item_location = $menu_item['LOCATION'];
110
      unset($menu_item['LOCATION']);
111
112
      $is_positioned = $item_location[0];
113
      if ($is_positioned == '+' || $is_positioned == '-') {
114
        $item_location = substr($item_location, 1);
115
      } else {
116
        $is_positioned = '';
117
      }
118
119
      if ($item_location) {
120
        $menu_keys       = array_keys($menu);
121
        $insert_position = array_search($item_location, $menu_keys);
122
        if ($insert_position === false) {
123
          $insert_position = count($menu) - 1;
124
          $is_positioned   = '+';
125
          $item_location   = '';
126
        }
127
      } else {
128
        $insert_position = $is_positioned == '-' ? 0 : count($menu);
129
      }
130
131
      $insert_position     += $is_positioned == '+' ? 1 : 0;
132
      $spliced             = array_splice($menu, $insert_position, count($menu) - $insert_position);
133
      $menu[$menu_item_id] = $menu_item;
134
135
      if (!$is_positioned && $item_location) {
136
        unset($spliced[$item_location]);
137
      }
138
      $menu = array_merge($menu, $spliced);
139
    }
140
141
    $extra = array();
142
  }
143
144
  /**
145
   * @param array $menu
146
   *
147
   * @return array
148
   */
149
  public static function tpl_menu_adminize($menu) {
150
    !is_array($menu) ? $menu = [] : false;
0 ignored issues
show
The condition is_array($menu) is always true.
Loading history...
151
152
    foreach ($menu as &$menuItem) {
153
      if (!isset($menuItem[MENU_FIELD_AUTH_LEVEL])) {
154
        $menuItem[MENU_FIELD_AUTH_LEVEL] = AUTH_LEVEL_ADMINISTRATOR;
155
      }
156
    }
157
158
    return $menu;
159
  }
160
161
  /**
162
   * @param array    $sn_menu
163
   * @param template $template
164
   */
165
  public static function tpl_menu_assign_to_template(&$sn_menu, &$template) {
166
    global $lang;
167
168
    if (empty($sn_menu) || !is_array($sn_menu)) {
169
      return;
170
    }
171
172
    foreach ($sn_menu as $menu_item_id => $menu_item) {
173
      if (!$menu_item) {
174
        continue;
175
      }
176
177
      if (is_string($menu_item_id)) {
178
        $menu_item['ID'] = $menu_item_id;
179
      }
180
181
      if ($menu_item['TYPE'] == 'lang') {
182
        $lang_string = &$lang;
183
        if (preg_match('#(\w+)(?:\[(\w+)\])?(?:\[(\w+)\])?(?:\[(\w+)\])?(?:\[(\w+)\])?#', $menu_item['ITEM'], $matches) && count($matches) > 1) {
184
          for ($i = 1; $i < count($matches); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
185
            if (defined($matches[$i])) {
186
              $matches[$i] = constant($matches[$i]);
187
            }
188
            $lang_string = &$lang_string[$matches[$i]];
189
          }
190
        }
191
        $menu_item['ITEM'] = $lang_string && is_string($lang_string) ? $lang_string : "{L_{$menu_item['ITEM']}}";
192
      }
193
194
      $menu_item['ALT']   = htmlentities($menu_item['ALT']);
195
      $menu_item['TITLE'] = htmlentities($menu_item['TITLE']);
196
197
      if (!empty($menu_item['ICON'])) {
198
        if (is_string($menu_item['ICON'])) {
199
          $menu_item['ICON_PATH'] = $menu_item['ICON'];
200
        } else {
201
          $menu_item['ICON'] = $menu_item_id;
202
        }
203
      }
204
205
      $template->assign_block_vars('menu', $menu_item);
206
    }
207
  }
208
209
  /**
210
   * @param template $template
211
   *
212
   * @return template
213
   */
214
  public static function tpl_render_menu($template) {
215
    global $user, $lang, $template_result, $sn_menu_admin_extra, $sn_menu_admin, $sn_menu, $sn_menu_extra;
216
217
    lng_include('admin');
218
219
    $template->assign_vars(array(
220
      'USER_AUTHLEVEL'      => $user['authlevel'],
221
      'USER_AUTHLEVEL_NAME' => $lang['user_level'][$user['authlevel']],
222
      'PAYMENT'             => SN::$gc->modules->countModulesInGroup('payment'),
223
      'MENU_START_HIDE'     => !empty($_COOKIE[SN_COOKIE . '_menu_hidden']) || SN_GOOGLE,
224
    ));
225
226
    if (isset($template_result['MENU_CUSTOMIZE'])) {
227
      $template->assign_vars(array(
228
        'PLAYER_OPTION_MENU_SHOW_ON_BUTTON'   => SN::$user_options[PLAYER_OPTION_MENU_SHOW_ON_BUTTON],
229
        'PLAYER_OPTION_MENU_HIDE_ON_BUTTON'   => SN::$user_options[PLAYER_OPTION_MENU_HIDE_ON_BUTTON],
230
        'PLAYER_OPTION_MENU_HIDE_ON_LEAVE'    => SN::$user_options[PLAYER_OPTION_MENU_HIDE_ON_LEAVE],
231
        'PLAYER_OPTION_MENU_UNPIN_ABSOLUTE'   => SN::$user_options[PLAYER_OPTION_MENU_UNPIN_ABSOLUTE],
232
        'PLAYER_OPTION_MENU_ITEMS_AS_BUTTONS' => SN::$user_options[PLAYER_OPTION_MENU_ITEMS_AS_BUTTONS],
233
        'PLAYER_OPTION_MENU_WHITE_TEXT'       => SN::$user_options[PLAYER_OPTION_MENU_WHITE_TEXT],
234
        'PLAYER_OPTION_MENU_OLD'              => SN::$user_options[PLAYER_OPTION_MENU_OLD],
235
        'PLAYER_OPTION_MENU_HIDE_SHOW_BUTTON' => empty($_COOKIE[SN_COOKIE . '_menu_hidden']) && !SN_GOOGLE
236
          ? SN::$user_options[PLAYER_OPTION_MENU_HIDE_SHOW_BUTTON] : 1,
237
      ));
238
    }
239
240
    if (defined('IN_ADMIN') && IN_ADMIN === true && !empty($user['authlevel']) && $user['authlevel'] > 0) {
241
      SnTemplate::tpl_menu_merge_extra($sn_menu_admin, $sn_menu_admin_extra);
242
      $sn_menu_admin = SnTemplate::tpl_menu_adminize($sn_menu_admin);
243
      SnTemplate::tpl_menu_assign_to_template($sn_menu_admin, $template);
244
    } else {
245
      SnTemplate::tpl_menu_merge_extra($sn_menu, $sn_menu_extra);
246
      SnTemplate::tpl_menu_assign_to_template($sn_menu, $template);
247
    }
248
249
    return $template;
250
  }
251
252
  /**
253
   * @param template[] $page
254
   * @param array      $template_result
255
   */
256
  public static function renderFooter($page, $template_result) {
0 ignored issues
show
The parameter $template_result is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

256
  public static function renderFooter($page, /** @scrutinizer ignore-unused */ $template_result) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $page is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

256
  public static function renderFooter(/** @scrutinizer ignore-unused */ $page, $template_result) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
257
    $templateFooter = self::gettemplate('_page/_99_footer', true);
0 ignored issues
show
true of type true is incompatible with the type null|template expected by parameter $template of SnTemplate::gettemplate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

257
    $templateFooter = self::gettemplate('_page/_99_footer', /** @scrutinizer ignore-type */ true);
Loading history...
258
259
    $templateFooter->assign_vars([
260
      'SN_TIME_NOW'      => SN_TIME_NOW,
261
      'SN_VERSION'       => SN_VERSION,
262
      'ADMIN_EMAIL'      => SN::$config->game_adminEmail,
263
      'CURRENT_YEAR'     => date('Y', SN_TIME_NOW),
264
      'DB_PATCH_VERSION' => dbPatchGetCurrent(),
265
    ]);
266
267
    SnTemplate::displayP($templateFooter);
268
  }
269
270
  /**
271
   * @param $page
272
   * @param $title
273
   * @param $template_result
274
   * @param $inLoginLogout
275
   * @param $user
276
   * @param $config
277
   * @param $lang
278
   * @param $planetrow
279
   */
280
  public static function renderHeader($page, $title, &$template_result, $inLoginLogout, &$user, $config, $lang, $planetrow, $renderedContent) {
281
    if (SN::$headerRendered) {
282
      return;
283
    }
284
285
    ob_end_flush();
286
287
    ob_start();
288
//  pdump(microtime(true) - SN_TIME_MICRO, 'Header render started');
289
    $isDisplayTopNav = true;
290
    $isDisplayMenu   = true;
291
292
    isset($template_result['GLOBAL_DISPLAY_MENU']) ? $isDisplayMenu = $template_result['GLOBAL_DISPLAY_MENU'] : false;
293
    isset($template_result['GLOBAL_DISPLAY_NAVBAR']) ? $isDisplayTopNav = $template_result['GLOBAL_DISPLAY_NAVBAR'] : false;
294
295
    // TODO: DEPRECATED! Use $template_result to turn menu and navbar or ond off!
296
    if (is_object($page)) {
297
      isset($page->_rootref['MENU']) ? $isDisplayMenu = $page->_rootref['MENU'] : false;
298
      isset($page->_rootref['NAVBAR']) ? $isDisplayTopNav = $page->_rootref['NAVBAR'] : false;
299
    }
300
301
    $inAdmin         = defined('IN_ADMIN') && IN_ADMIN === true;
302
    $isDisplayMenu   = ($isDisplayMenu || $inAdmin) && !isset($_COOKIE['menu_disable']);
303
    $isDisplayTopNav = $isDisplayTopNav && !$inAdmin;
304
305
    if ($inLoginLogout || empty($user['id']) || !is_numeric($user['id'])) {
306
      $isDisplayMenu   = false;
307
      $isDisplayTopNav = false;
308
    }
309
310
    $template = self::gettemplate('_page/_00_header', true);
0 ignored issues
show
true of type true is incompatible with the type null|template expected by parameter $template of SnTemplate::gettemplate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

310
    $template = self::gettemplate('_page/_00_header', /** @scrutinizer ignore-type */ true);
Loading history...
311
    $template->assign_vars([
312
      'SN_TIME_NOW'      => SN_TIME_NOW,
313
      'SN_VERSION'       => SN_VERSION,
314
      'ADMIN_EMAIL'      => SN::$config->game_adminEmail,
315
      'CURRENT_YEAR'     => date('Y', SN_TIME_NOW),
316
      'DB_PATCH_VERSION' => dbPatchGetCurrent(),
317
    ]);
318
319
    self::renderJavaScript();
320
321
    self::renderCss($inLoginLogout);
322
323
    $template->assign_vars(array(
324
      self::P_CONTENT => $renderedContent,
325
326
      'LANG_LANGUAGE'  => $lang['LANG_INFO']['LANG_NAME_ISO2'],
327
      'LANG_ENCODING'  => 'utf-8',
328
      'LANG_DIRECTION' => $lang['LANG_INFO']['LANG_DIRECTION'],
329
330
      'SN_ROOT_VIRTUAL' => SN_ROOT_VIRTUAL,
331
332
      'ADV_SEO_META_DESCRIPTION' => $config->adv_seo_meta_description,
333
      'ADV_SEO_META_KEYWORDS'    => $config->adv_seo_meta_keywords,
334
335
      // WARNING! This can be set by page!
336
      // CHANGE CODE TO MAKE IT IMPOSSIBLE!
337
      'GLOBAL_META_TAGS'         => isset($page->_rootref['GLOBAL_META_TAGS']) ? $page->_rootref['GLOBAL_META_TAGS'] : '',
338
339
      'IN_ADMIN' => $inAdmin ? 1 : '',
340
    ));
341
342
    $template->assign_vars(array(
343
      'GLOBAL_DISPLAY_MENU'   => $isDisplayMenu,
344
      'GLOBAL_DISPLAY_NAVBAR' => $isDisplayTopNav,
345
346
      'USER_AUTHLEVEL' => intval($user['authlevel']),
347
348
      'FONT_SIZE'                        => self::playerFontSize(),
349
      'FONT_SIZE_PERCENT_DEFAULT_STRING' => FONT_SIZE_PERCENT_DEFAULT_STRING,
350
351
      'SN_TIME_NOW'          => SN_TIME_NOW,
352
      'LOGIN_LOGOUT'         => $template_result['LOGIN_LOGOUT'],
353
      'GAME_MODE_CSS_PREFIX' => $config->game_mode == GAME_BLITZ ? 'blitz_' : '',
354
      'TIME_DIFF_MEASURE'    => playerTimeDiff::timeDiffTemplate(), // Проводить замер только если не выставлен флаг форсированного замера И (иссяк интервал замера ИЛИ замера еще не было)
355
356
      'title'              => ($title ? "{$title} - " : '') . "{$lang['sys_server']} {$config->game_name} - {$lang['sys_supernova']}",
357
      'ADV_SEO_JAVASCRIPT' => $config->adv_seo_javascript,
358
359
      'SOUND_ENABLED'                        => SN::$user_options[PLAYER_OPTION_SOUND_ENABLED],
360
      'PLAYER_OPTION_ANIMATION_DISABLED'     => SN::$user_options[PLAYER_OPTION_ANIMATION_DISABLED],
361
      'PLAYER_OPTION_PROGRESS_BARS_DISABLED' => SN::$user_options[PLAYER_OPTION_PROGRESS_BARS_DISABLED],
362
363
      'IMPERSONATING'                        => !empty($template_result[F_IMPERSONATE_STATUS]) ? sprintf($lang['sys_impersonated_as'], $user['username'], $template_result[F_IMPERSONATE_OPERATOR]) : '',
364
      'PLAYER_OPTION_DESIGN_DISABLE_BORDERS' => SN::$user_options[PLAYER_OPTION_DESIGN_DISABLE_BORDERS],
365
366
      'WEBP_SUPPORT_NEED_CHECK' => ($webpSupported = SN::$gc->theUser->isWebpSupported()) === null ? 1 : 0,
367
      'WEBP_SUPPORTED'          => $webpSupported ? 1 : 0,
368
    ));
369
    $template->assign_recursive($template_result);
370
371
    if ($isDisplayMenu) {
372
      SnTemplate::tpl_render_menu($template);
373
    }
374
375
    if ($isDisplayTopNav) {
376
      SN::$gc->pimp->tpl_render_topnav($user, $planetrow, $template);
377
    }
378
379
    SnTemplate::displayP($template);
380
    ob_end_flush();
381
382
    SN::$headerRendered = true;
383
384
    ob_start();
385
  }
386
387
  /**
388
   */
389
  public static function renderJavaScript() {
390
    global $sn_mvc, $sn_page_name, $template_result;
391
392
    empty($sn_mvc['javascript']) ? $sn_mvc['javascript'] = ['' => []] : false;
393
394
    $standard_js = self::addFileName([
395
      'js/lib/jquery',
396
      'js/lib/js.cookie',
397
      'js/lib/jquery-ui',
398
      'js/lib/jquery.ui.touch-punch',
399
      'js/lib/ion.sound',
400
      'js/sn_global',
401
      'js/sn_sound',
402
      'js/sn_timer',
403
    ], [], '.js');
404
405
    $standard_js = self::addFileName(!empty($sn_mvc['javascript_filenames']) ? $sn_mvc['javascript_filenames'] : [], $standard_js, '.js');
406
407
    $standard_js = self::cacheFiles($standard_js, '.js');
408
409
    // Prepending standard CSS files
410
    $sn_mvc['javascript'][''] = array_merge($standard_js, $sn_mvc['javascript']['']);
411
412
    self::renderFileListInclude($template_result, $sn_mvc, $sn_page_name, 'javascript');
413
  }
414
415
  /**
416
   * @param $is_login
417
   */
418
  public static function renderCss($is_login) {
419
    global $sn_mvc, $sn_page_name, $template_result;
420
421
    empty($sn_mvc['css']) ? $sn_mvc['css'] = ['' => []] : false;
422
423
    $standard_css = [];
424
    $standard_css = self::addFileName('design/css/jquery-ui', $standard_css);
425
    $standard_css = self::addFileName('design/css/global', $standard_css);
426
    $is_login ? $standard_css = self::addFileName('design/css/login', $standard_css) : false;
427
    $standard_css = self::addFileName('design/css/menu_icons', $standard_css);
428
429
    $standard_css = self::getCurrentTemplate()->cssAddFileName('_template', $standard_css);
430
431
    $standard_css = self::addFileName(SN::$gc->theUser->getSkinPath() . 'skin', $standard_css);
432
    $standard_css = self::addFileName('design/css/global_override', $standard_css);
433
434
    // Trying to add extra CSS to cache file
435
    foreach ($sn_mvc['css'][''] as $css => $cork) {
436
      $cssOriginal = $css;
437
438
      // At first - removing minimization flag from file name
439
      if(($rPos = strrpos($css, '.min.css')) !== false) {
440
        // 4 - string length of substring to cut `.min`
441
        $css = substr_replace($css, '', $rPos, 4);
442
      }
443
      // Also we don't need `.css` extension
444
      if(($rPos = strrpos($css, '.css')) !== false) {
445
        // 4 - string length of substring to cut `.css`
446
        $css = substr_replace($css, '', $rPos, 4);
447
      }
448
449
      // Memorizing size of css filename array
450
      $cssWas = count($standard_css);
451
      // Trying to add newly found filename
452
      $standard_css = self::addFileName($css, $standard_css);
453
      if(count($standard_css) > $cssWas) {
454
        // Removing file from extra CSS list only if everything went well and records was added to list of CSS to cache
455
        // Otherwise something went wrong - so we don't touch this
456
        unset($sn_mvc['css'][''][$cssOriginal]);
457
      }
458
    }
459
460
    // Trying to cache CSS files
461
    $standard_css = self::cacheFiles($standard_css);
462
463
    // Prepending standard CSS files
464
    $sn_mvc['css'][''] = array_merge($standard_css, $sn_mvc['css']['']);
465
466
    self::renderFileListInclude($template_result, $sn_mvc, $sn_page_name, 'css');
467
  }
468
469
  /**
470
   * @param $time
471
   * @param $event
472
   * @param $msg
473
   * @param $prefix
474
   * @param $is_decrease
475
   * @param $fleet_flying_row
476
   * @param $fleet_flying_sorter
477
   * @param $fleet_flying_events
478
   * @param $fleet_event_count
479
   */
480
  public static function tpl_topnav_event_build_helper($time, $event, $msg, $prefix, $is_decrease, $fleet_flying_row, &$fleet_flying_sorter, &$fleet_flying_events, &$fleet_event_count) {
481
    $fleet_flying_sorter[$fleet_event_count] = $time;
482
    $fleet_flying_events[$fleet_event_count] = array(
483
      'ROW'              => $fleet_flying_row,
484
      'FLEET_ID'         => $fleet_flying_row['fleet_id'],
485
      'EVENT'            => $event,
486
      'COORDINATES'      => uni_render_coordinates($fleet_flying_row, $prefix),
487
      'COORDINATES_TYPE' => $fleet_flying_row["{$prefix}type"],
488
      'TEXT'             => "{$msg}",
489
      'DECREASE'         => $is_decrease,
490
    );
491
    $fleet_event_count++;
492
  }
493
494
  /**
495
   * @param template $template
496
   * @param array    $fleet_flying_list
497
   * @param string   $type
498
   */
499
  public static function tpl_topnav_event_build(&$template, $fleet_flying_list, $type = 'fleet') {
500
    if (empty($fleet_flying_list)) {
501
      return;
502
    }
503
504
    global $lang;
505
506
    $fleet_event_count   = 0;
507
    $fleet_flying_sorter = array();
508
    $fleet_flying_events = array();
509
    foreach ($fleet_flying_list as &$fleet_flying_row) {
510
      $will_return = true;
511
      if ($fleet_flying_row['fleet_mess'] == 0) {
512
        // cut fleets on Hold and Expedition
513
        if ($fleet_flying_row['fleet_start_time'] >= SN_TIME_NOW) {
514
          $fleet_flying_row['fleet_mission'] == MT_RELOCATE ? $will_return = false : false;
515
          SnTemplate::tpl_topnav_event_build_helper($fleet_flying_row['fleet_start_time'], EVENT_FLEET_ARRIVE, $lang['sys_event_arrive'], 'fleet_end_', !$will_return, $fleet_flying_row, $fleet_flying_sorter, $fleet_flying_events, $fleet_event_count);
516
        }
517
        if ($fleet_flying_row['fleet_end_stay']) {
518
          SnTemplate::tpl_topnav_event_build_helper($fleet_flying_row['fleet_end_stay'], EVENT_FLEET_STAY, $lang['sys_event_stay'], 'fleet_end_', false, $fleet_flying_row, $fleet_flying_sorter, $fleet_flying_events, $fleet_event_count);
519
        }
520
      }
521
      if ($will_return) {
522
        SnTemplate::tpl_topnav_event_build_helper($fleet_flying_row['fleet_end_time'], EVENT_FLEET_RETURN, $lang['sys_event_return'], 'fleet_start_', true, $fleet_flying_row, $fleet_flying_sorter, $fleet_flying_events, $fleet_event_count);
523
      }
524
    }
525
526
    asort($fleet_flying_sorter);
527
528
    $fleet_flying_count = count($fleet_flying_list);
529
    foreach ($fleet_flying_sorter as $fleet_event_id => $fleet_time) {
530
      $fleet_event = &$fleet_flying_events[$fleet_event_id];
531
      $template->assign_block_vars("flying_{$type}s", array(
532
        'TIME' => max(0, $fleet_time - SN_TIME_NOW),
533
        'TEXT' => $fleet_flying_count,
534
        'HINT' => date(FMT_DATE_TIME, $fleet_time + SN_CLIENT_TIME_DIFF) . " - {$lang['sys_fleet']} {$fleet_event['TEXT']} {$fleet_event['COORDINATES']} {$lang['sys_planet_type_sh'][$fleet_event['COORDINATES_TYPE']]} {$lang['type_mission'][$fleet_event['ROW']['fleet_mission']]}",
535
      ));
536
      $fleet_event['DECREASE'] ? $fleet_flying_count-- : false;
537
    }
538
  }
539
540
  /**
541
   * @return mixed|string
542
   */
543
  public static function playerFontSize() {
544
    $font_size = !empty($_COOKIE[SN_COOKIE_F]) ? $_COOKIE[SN_COOKIE_F] : SN::$user_options[PLAYER_OPTION_BASE_FONT_SIZE];
545
    if (strpos($font_size, '%') !== false) {
546
      // Размер шрифта в процентах
547
      $font_size = min(max(floatval($font_size), FONT_SIZE_PERCENT_MIN), FONT_SIZE_PERCENT_MAX) . '%';
548
549
      return $font_size;
550
    } elseif (strpos($font_size, 'px') !== false) {
551
      // Размер шрифта в пикселях
552
      $font_size = min(max(floatval($font_size), FONT_SIZE_PIXELS_MIN), FONT_SIZE_PIXELS_MAX) . 'px';
553
554
      return $font_size;
555
    } else {
556
      // Не мышонка, не лягушка...
557
      $font_size = FONT_SIZE_PERCENT_DEFAULT_STRING;
558
559
      return $font_size;
560
    }
561
  }
562
563
  /**
564
   * Checks if minified/full-size file variant exists - and adds it if any
565
   *
566
   * @param string|string[] $fileNames
567
   * @param array  $anArray
568
   *
569
   * @return array
570
   */
571
  public static function addFileName($fileNames, $anArray, $ext = '.css') {
572
    if(!is_array($fileNames)) {
573
      $fileNames = [$fileNames];
574
    }
575
576
    foreach($fileNames as $fileName) {
577
      if (file_exists(SN_ROOT_PHYSICAL . $fileName . '.min' . $ext)) {
578
        $anArray[$fileName . '.min' . $ext] = '';
579
      } elseif (file_exists(SN_ROOT_PHYSICAL . $fileName . '.css' . $ext)) {
580
        $anArray[$fileName . $ext] = '';
581
      }
582
    }
583
584
    return $anArray;
585
  }
586
587
  /**
588
   * @param array   $template_result
589
   * @param array[] $sn_mvc
590
   * @param string  $sn_page_name
591
   * @param string  $fileType - 'css' or 'javascript'
592
   */
593
  public static function renderFileListInclude(&$template_result, &$sn_mvc, $sn_page_name, $fileType) {
594
    if (empty($sn_mvc[$fileType])) {
595
      return;
596
    }
597
598
    foreach ($sn_mvc[$fileType] as $page_name => $script_list) {
599
      if (empty($page_name) || $page_name == $sn_page_name) {
600
        foreach ($script_list as $filename => $content) {
601
          $template_result['.'][$fileType][] = array(
602
            'FILE'    => $filename,
603
            'CONTENT' => $content,
604
          );
605
        }
606
      }
607
    }
608
  }
609
610
  /**
611
   * @param $template
612
   * @param $user
613
   */
614
  public static function tpl_navbar_render_notes(&$template, &$user) {
615
    $notes_query = doquery("SELECT * FROM {{notes}} WHERE `owner` = {$user['id']} AND `sticky` = 1 ORDER BY priority DESC, time DESC");
0 ignored issues
show
Deprecated Code introduced by
The function doquery() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

615
    $notes_query = /** @scrutinizer ignore-deprecated */ doquery("SELECT * FROM {{notes}} WHERE `owner` = {$user['id']} AND `sticky` = 1 ORDER BY priority DESC, time DESC");
Loading history...
616
    while ($note_row = db_fetch($notes_query)) {
0 ignored issues
show
Deprecated Code introduced by
The function db_fetch() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

616
    while ($note_row = /** @scrutinizer ignore-deprecated */ db_fetch($notes_query)) {
Loading history...
617
      Note::note_assign($template, $note_row);
0 ignored issues
show
Deprecated Code introduced by
The function Note\Note::note_assign() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

617
      /** @scrutinizer ignore-deprecated */ Note::note_assign($template, $note_row);
Loading history...
618
    }
619
  }
620
621
  /**
622
   * @param             $template
623
   * @param             $user
624
   * @param classConfig $config
625
   */
626
  public static function tpl_navbar_render_news(&$template, &$user, $config) {
627
    if ($config->game_news_overview) {
628
      $user_last_read_safe     = intval($user['news_lastread']);
629
      $newsSql                 = "AND UNIX_TIMESTAMP(`tsTimeStamp`) >= {$user_last_read_safe} ";
630
      $newsOverviewShowSeconds = intval($config->game_news_overview_show);
631
      if ($newsOverviewShowSeconds) {
632
        $newsSql .= "AND `tsTimeStamp` >= DATE_SUB(NOW(), INTERVAL {$newsOverviewShowSeconds} SECOND) ";
633
      }
634
      nws_render($user, $template, $newsSql, $config->game_news_overview);
635
    }
636
  }
637
638
  /**
639
   * @param array  $sn_mvc
640
   * @param string $blockName
641
   *
642
   * @return array|false
643
   */
644
  public static function render_button_block(&$sn_mvc, $blockName) {
645
    $result = false;
646
647
    if (!empty($sn_mvc[$blockName]) && is_array($sn_mvc[$blockName])) {
648
      foreach ($sn_mvc[$blockName] as $navbar_button_image => $navbar_button_url) {
649
        $result[] = array(
650
          'IMAGE'        => $navbar_button_image,
651
          'URL_RELATIVE' => $navbar_button_url,
652
        );
653
      }
654
655
      $result = array(
656
        '.' => array(
657
          $blockName =>
658
            $result
659
        ),
660
      );
661
    }
662
663
    return $result;
664
  }
665
666
  /**
667
   * @param array    $sn_mvc
668
   * @param template $template
669
   */
670
  public static function tpl_navbar_extra_buttons(&$sn_mvc, $template) {
671
    ($block = SnTemplate::render_button_block($sn_mvc, 'navbar_prefix_button')) ? $template->assign_recursive($block) : false;
672
    ($block = SnTemplate::render_button_block($sn_mvc, 'navbar_main_button')) ? $template->assign_recursive($block) : false;
673
  }
674
675
  /**
676
   * @param template|string $template
677
   *
678
   * @return false|string|null
679
   */
680
  public static function templateRenderToHtml($template) {
681
    $output = null;
0 ignored issues
show
The assignment to $output is dead and can be removed.
Loading history...
682
683
    ob_start();
684
    SnTemplate::displayP($template);
685
    $output = ob_get_contents();
686
    ob_end_clean();
687
688
    return $output;
689
  }
690
691
  /**
692
   * @param template $template
693
   */
694
  public static function tpl_login_lang(&$template) {
695
    global $language;
696
697
    $url_params = array();
698
699
    $language ? $url_params[] = "lang={$language}" : false;
700
701
    ($id_ref = sys_get_param_id('id_ref')) ? $url_params[] = "id_ref={$id_ref}" : false;
702
703
    $template->assign_vars($q = array(
704
      'LANG'     => $language ? $language : '',
705
      'referral' => $id_ref ? '&id_ref=' . $id_ref : '',
706
707
      'REQUEST_PARAMS' => !empty($url_params) ? '?' . implode('&', $url_params) : '',// "?lang={$language}" . ($id_ref ? "&id_ref={$id_ref}" : ''),
708
      'FILENAME'       => basename($_SERVER['PHP_SELF']),
709
    ));
710
711
    foreach (lng_get_list() as $lng_id => $lng_data) {
712
      if (isset($lng_data['LANG_VARIANTS']) && is_array($lng_data['LANG_VARIANTS'])) {
713
        foreach ($lng_data['LANG_VARIANTS'] as $lang_variant) {
714
          $lng_data1 = $lng_data;
715
          $lng_data1 = array_merge($lng_data1, $lang_variant);
716
          $template->assign_block_vars('language', $lng_data1);
717
        }
718
      } else {
719
        $template->assign_block_vars('language', $lng_data);
720
      }
721
    }
722
  }
723
724
  /**
725
   * @param template $template
726
   * @param string   $blockName
727
   * @param mixed    $values
728
   * @param string   $keyName   - Name for key name
729
   * @param string   $valueName - Name for value name
730
   */
731
  public static function tpl_assign_select(&$template, $blockName, $values, $keyName = 'KEY', $valueName = 'VALUE') {
732
    !is_array($values) ? $values = array($values => $values) : false;
733
734
    foreach ($values as $key => $value) {
735
      $template->assign_block_vars($blockName, array(
736
        $keyName   => HelperString::htmlSafe($key),
737
        $valueName => HelperString::htmlSafe($value),
738
      ));
739
    }
740
  }
741
742
  /**
743
   * Renders unit bonus from unit data
744
   *
745
   * @param array $unitInfo
746
   *
747
   * @return string
748
   */
749
  public static function tpl_render_unit_bonus_data($unitInfo) {
750
    $strBonus = self::tplAddPlus($unitInfo[P_BONUS_VALUE]);
751
    switch ($unitInfo[P_BONUS_TYPE]) {
752
      case BONUS_PERCENT:
753
        $strBonus = "{$strBonus}% ";
754
      break;
755
756
      case BONUS_ABILITY:
757
        $strBonus = '';
758
      break;
759
760
      case BONUS_ADD:
761
      default:
762
      break;
763
    }
764
765
    return $strBonus;
766
  }
767
768
  /**
769
   * Converts number to string then adds "+" sign for positive AND ZERO numbers
770
   *
771
   * @param float $value
772
   *
773
   * @return string
774
   */
775
  public static function tplAddPlus($value) {
776
    return ($value >= 0 ? '+' : '') . $value;
777
  }
778
779
  /**
780
   * Convert number to prettified string then adds "+" sign for positive AND ZERO numbers
781
   *
782
   * @param float $value
783
   *
784
   * @return string
785
   */
786
  public static function tplPrettyPlus($value) {
787
    return ($value >= 0 ? '+' : '') . HelperString::numberFloorAndFormat($value);
788
  }
789
790
  /**
791
   * Add message to result box
792
   *
793
   * If $template specified - message would be added to template supplied. Otherwise - to $template_result
794
   *
795
   * @param string $message
796
   * @param int    $status
797
   * @param null   $template
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $template is correct as it would always require null to be passed?
Loading history...
798
   */
799
  public static function tplAddResult($message, $status = ERR_NONE, $template = null) {
800
    global $template_result;
801
802
    $block = [
803
      'STATUS'  => $status,
804
      'MESSAGE' => $message,
805
    ];
806
807
    if ($template instanceof template) {
808
      $template->assign_block_vars('result', $block);
809
    } else {
810
      $template_result['.']['result'][] = $block;
811
    }
812
  }
813
814
  /**
815
   * @param string    $message
816
   * @param string    $title
817
   * @param string    $redirectTo
818
   * @param int       $timeout
819
   * @param bool|true $showHeader
820
   */
821
  public static function messageBox($message, $title = '', $redirectTo = '', $timeout = 5, $showHeader = true) {
822
    global $lang, $template_result;
823
824
    if (empty($title)) {
825
      $title = $lang['sys_error'];
826
    }
827
828
    $template = self::gettemplate('message_body', true);
0 ignored issues
show
true of type true is incompatible with the type null|template expected by parameter $template of SnTemplate::gettemplate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

828
    $template = self::gettemplate('message_body', /** @scrutinizer ignore-type */ true);
Loading history...
829
830
    $template_result['GLOBAL_DISPLAY_NAVBAR'] = $showHeader;
831
832
    $template->assign_vars(array(
833
//    'GLOBAL_DISPLAY_NAVBAR' => $showHeader,
834
835
      'TITLE'       => $title,
836
      'MESSAGE'     => $message,
837
      'REDIRECT_TO' => $redirectTo,
838
      'TIMEOUT'     => $timeout,
839
    ));
840
841
    self::display($template, $title);
842
  }
843
844
  /**
845
   * Admin message box
846
   *
847
   * @param        $message
848
   * @param string $title
849
   * @param string $redirectTo
850
   * @param int    $timeout
851
   *
852
   * @see SnTemplate::messageBox()
853
   */
854
  public static function messageBoxAdmin($message, $title = '', $redirectTo = '', $timeout = 5) {
855
    SnTemplate::messageBox($message, $title, $redirectTo, $timeout, false);
856
  }
857
858
  public static function messageBoxAdminAccessDenied($level = AUTH_LEVEL_ADMINISTRATOR) {
859
    global $user, $lang;
860
861
    if ($user['authlevel'] < $level) {
862
      SnTemplate::messageBoxAdmin($lang['adm_err_denied'], $lang['admin_title_access_denied'], SN_ROOT_VIRTUAL . 'overview.php');
863
    }
864
  }
865
866
  /**
867
   * @param          $prevUser
868
   * @param array    $user
869
   * @param array    $planetrow
870
   * @param template $template
871
   *
872
   * @return array
873
   */
874
  public static function sn_tpl_render_topnav(&$prevUser, $user, $planetrow, $template) {
875
    global $lang, $config, $sn_mvc;
876
877
    // This call was not first one... Using results from previous call
878
    if (!empty($prevUser['username'])) {
879
      $user = $prevUser;
880
    }
881
882
    if (!is_array($user)) {
883
      return $user;
884
    }
885
886
    $GET_mode = sys_get_param_str('mode');
887
888
    $ThisUsersPlanets = DBStaticPlanet::db_planet_list_sorted($user);
889
    foreach ($ThisUsersPlanets as $CurPlanet) {
890
      if ($CurPlanet['destruyed']) {
891
        continue;
892
      }
893
894
      $fleet_listx = flt_get_fleets_to_planet($CurPlanet);
895
      if ($CurPlanet['planet_type'] == PT_MOON) {
896
        $parentPlanet = DBStaticPlanet::db_planet_by_id($CurPlanet['parent_planet']);
897
      } else {
898
        $parentPlanet = $CurPlanet;
899
      }
900
901
      $template->assign_block_vars('topnav_planets', [
902
        'ID'          => $CurPlanet['id'],
903
        'NAME'        => $CurPlanet['name'],
904
        'TYPE'        => $CurPlanet['planet_type'],
905
        'TYPE_TEXT'   => $lang['sys_planet_type_sh'][$CurPlanet['planet_type']],
906
        'IS_CAPITAL'  => $parentPlanet['id'] == $user['id_planet'],
907
        'IS_MOON'     => $CurPlanet['planet_type'] == PT_MOON,
908
        'PLIMAGE'     => $CurPlanet['image'],
909
        'FLEET_ENEMY' => $fleet_listx['enemy']['count'],
910
        'COORDS'      => uni_render_coordinates($CurPlanet),
911
        'SELECTED'    => $CurPlanet['id'] == $user['current_planet'] ? ' selected' : '',
912
      ]);
913
    }
914
915
    $fleet_flying_list = DbFleetStatic::tpl_get_fleets_flying($user);
916
    SnTemplate::tpl_topnav_event_build($template, $fleet_flying_list[0]);
917
    SnTemplate::tpl_topnav_event_build($template, $fleet_flying_list[MT_EXPLORE], 'expedition');
918
919
    que_tpl_parse($template, QUE_STRUCTURES, $user, $planetrow, null, true);
920
    que_tpl_parse($template, QUE_RESEARCH, $user, array(), null, !SN::$user_options[PLAYER_OPTION_NAVBAR_RESEARCH_WIDE]);
921
    que_tpl_parse($template, SUBQUE_FLEET, $user, $planetrow, null, true);
922
    que_tpl_parse($template, SUBQUE_DEFENSE, $user, $planetrow, null, true);
923
924
    SnTemplate::tpl_navbar_extra_buttons($sn_mvc, $template);
925
    SnTemplate::tpl_navbar_render_news($template, $user, $config);
926
    SnTemplate::tpl_navbar_render_notes($template, $user);
927
    $tutorial_enabled = PageTutorial::renderNavBar($template);
928
929
930
    $premium_lvl = mrc_get_level($user, false, UNIT_PREMIUM, true, true);
0 ignored issues
show
false of type false is incompatible with the type array expected by parameter $planet of mrc_get_level(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

930
    $premium_lvl = mrc_get_level($user, /** @scrutinizer ignore-type */ false, UNIT_PREMIUM, true, true);
Loading history...
931
932
    $str_date_format   = "%3$02d %2$0s %1$04d {$lang['top_of_year']} %4$02d:%5$02d:%6$02d";
933
    $time_now_parsed   = getdate(SN_TIME_NOW);
934
    $time_local_parsed = getdate(defined('SN_CLIENT_TIME_LOCAL') ? SN_CLIENT_TIME_LOCAL : SN_TIME_NOW);
935
936
    $template->assign_vars(array(
937
      'QUE_ID'   => QUE_RESEARCH,
938
      'QUE_HTML' => 'topnav',
939
940
      'RESEARCH_ONGOING' => (boolean)$user['que'],
941
942
      'TIME_TEXT'       => sprintf($str_date_format, $time_now_parsed['year'], $lang['months'][$time_now_parsed['mon']], $time_now_parsed['mday'],
943
        $time_now_parsed['hours'], $time_now_parsed['minutes'], $time_now_parsed['seconds']
944
      ),
945
      'TIME_TEXT_LOCAL' => sprintf($str_date_format, $time_local_parsed['year'], $lang['months'][$time_local_parsed['mon']], $time_local_parsed['mday'],
946
        $time_local_parsed['hours'], $time_local_parsed['minutes'], $time_local_parsed['seconds']
947
      ),
948
949
      'GAME_BLITZ_REGISTER'             => $config->game_blitz_register,
950
      'GAME_BLITZ_REGISTER_TEXT'        => $lang['sys_blitz_registration_mode_list'][$config->game_blitz_register],
951
      'BLITZ_REGISTER_OPEN'             => $config->game_blitz_register == BLITZ_REGISTER_OPEN,
952
      'BLITZ_REGISTER_CLOSED'           => $config->game_blitz_register == BLITZ_REGISTER_CLOSED,
953
      'BLITZ_REGISTER_SHOW_LOGIN'       => $config->game_blitz_register == BLITZ_REGISTER_SHOW_LOGIN,
954
      'BLITZ_REGISTER_DISCLOSURE_NAMES' => $config->game_blitz_register == BLITZ_REGISTER_DISCLOSURE_NAMES,
955
      'GAME_BLITZ'                      => $config->game_mode == GAME_BLITZ,
956
957
      'USERS_ONLINE'  => $config->var_online_user_count,
958
      'USERS_TOTAL'   => $config->users_amount,
959
      'USER_RANK'     => $user['total_rank'],
960
      'USER_NICK'     => $user['username'],
961
      'USER_AVATAR'   => $user['avatar'],
962
      'USER_AVATARID' => $user['id'],
963
      'USER_PREMIUM'  => $premium_lvl,
964
      'USER_RACE'     => $user[P_RACE],
965
966
      'TOPNAV_CURRENT_PLANET'       => $user['current_planet'],
967
      'TOPNAV_CURRENT_PLANET_NAME'  => uni_render_planet_full($planetrow), // htmlspecialchars($planetrow['name']),
968
      'TOPNAV_CURRENT_PLANET_IMAGE' => $planetrow['image'],
969
      'TOPNAV_COLONIES_CURRENT'     => get_player_current_colonies($user),
970
      'TOPNAV_COLONIES_MAX'         => get_player_max_colonies($user),
971
      'NAVBAR_MODE'                 => $GET_mode,
972
973
      'TOPNAV_DARK_MATTER'            => mrc_get_level($user, '', RES_DARK_MATTER),
0 ignored issues
show
'' of type string is incompatible with the type array expected by parameter $planet of mrc_get_level(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

973
      'TOPNAV_DARK_MATTER'            => mrc_get_level($user, /** @scrutinizer ignore-type */ '', RES_DARK_MATTER),
Loading history...
974
      'TOPNAV_DARK_MATTER_TEXT'       => HelperString::numberFloorAndFormat(mrc_get_level($user, '', RES_DARK_MATTER)),
0 ignored issues
show
It seems like mrc_get_level($user, '', RES_DARK_MATTER) can also be of type boolean; however, parameter $number of HelperString::numberFloorAndFormat() does only seem to accept double|integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

974
      'TOPNAV_DARK_MATTER_TEXT'       => HelperString::numberFloorAndFormat(/** @scrutinizer ignore-type */ mrc_get_level($user, '', RES_DARK_MATTER)),
Loading history...
975
      'TOPNAV_DARK_MATTER_PLAIN'      => mrc_get_level($user, '', RES_DARK_MATTER, false, true),
976
      'TOPNAV_DARK_MATTER_PLAIN_TEXT' => HelperString::numberFloorAndFormat(mrc_get_level($user, '', RES_DARK_MATTER, false, true)),
977
      'TOPNAV_METAMATTER'             => mrc_get_level($user, '', RES_METAMATTER),
978
      'TOPNAV_METAMATTER_TEXT'        => HelperString::numberFloorAndFormat(mrc_get_level($user, '', RES_METAMATTER)),
979
980
      // TODO ГРЯЗНЫЙ ХАК!!!
981
      'TOPNAV_PAYMENT'                => SN::$gc->modules->countModulesInGroup('payment') && !SN_GOOGLE,
982
983
      'TOPNAV_MESSAGES_ADMIN'    => $user['msg_admin'],
984
      'TOPNAV_MESSAGES_PLAYER'   => $user['mnl_joueur'],
985
      'TOPNAV_MESSAGES_ALLIANCE' => $user['mnl_alliance'],
986
      'TOPNAV_MESSAGES_ATTACK'   => $user['mnl_attaque'],
987
      'TOPNAV_MESSAGES_ALL'      => $user['new_message'],
988
989
      'TOPNAV_FLEETS_FLYING'      => empty($fleet_flying_list[0]) ? 0 : count($fleet_flying_list[0]),
990
      'TOPNAV_FLEETS_TOTAL'       => GetMaxFleets($user),
991
      'TOPNAV_EXPEDITIONS_FLYING' => empty($fleet_flying_list[MT_EXPLORE]) ? 0 : count($fleet_flying_list[MT_EXPLORE]),
992
      'TOPNAV_EXPEDITIONS_TOTAL'  => get_player_max_expeditons($user),
993
994
      'TOPNAV_QUEST_COMPLETE'    => get_quest_amount_complete($user['id']),
995
      'TOPNAV_QUEST_IN_PROGRESS' => get_quest_amount_in_progress($user['id']),
996
997
      'GAME_NEWS_OVERVIEW'       => $config->game_news_overview,
998
      'GAME_RESEARCH_DISABLED'   => defined('GAME_RESEARCH_DISABLED') && GAME_RESEARCH_DISABLED,
0 ignored issues
show
The constant GAME_RESEARCH_DISABLED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
999
      'GAME_DEFENSE_DISABLED'    => defined('GAME_DEFENSE_DISABLED') && GAME_DEFENSE_DISABLED,
0 ignored issues
show
The constant GAME_DEFENSE_DISABLED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1000
      'GAME_STRUCTURES_DISABLED' => defined('GAME_STRUCTURES_DISABLED') && GAME_STRUCTURES_DISABLED,
0 ignored issues
show
The constant GAME_STRUCTURES_DISABLED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1001
      'GAME_HANGAR_DISABLED'     => defined('GAME_HANGAR_DISABLED') && GAME_HANGAR_DISABLED,
0 ignored issues
show
The constant GAME_HANGAR_DISABLED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1002
1003
      'PLAYER_OPTION_NAVBAR_PLANET_VERTICAL'        => SN::$user_options[PLAYER_OPTION_NAVBAR_PLANET_VERTICAL],
1004
      'PLAYER_OPTION_NAVBAR_PLANET_OLD'             => SN::$user_options[PLAYER_OPTION_NAVBAR_PLANET_OLD],
1005
      'PLAYER_OPTION_NAVBAR_PLANET_DISABLE_STORAGE' => SN::$user_options[PLAYER_OPTION_NAVBAR_PLANET_DISABLE_STORAGE],
1006
      'PLAYER_OPTION_NAVBAR_DISABLE_RESEARCH'       => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_RESEARCH],
1007
      'PLAYER_OPTION_NAVBAR_DISABLE_PLANET'         => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_PLANET],
1008
      'PLAYER_OPTION_NAVBAR_DISABLE_HANGAR'         => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_HANGAR],
1009
      'PLAYER_OPTION_NAVBAR_DISABLE_DEFENSE'        => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_DEFENSE],
1010
      'PLAYER_OPTION_NAVBAR_DISABLE_FLYING_FLEETS'  => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_FLYING_FLEETS],
1011
      'PLAYER_OPTION_NAVBAR_DISABLE_EXPEDITIONS'    => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_EXPEDITIONS],
1012
      'PLAYER_OPTION_NAVBAR_DISABLE_QUESTS'         => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_QUESTS],
1013
      'PLAYER_OPTION_NAVBAR_DISABLE_META_MATTER'    => SN::$user_options[PLAYER_OPTION_NAVBAR_DISABLE_META_MATTER],
1014
      'PLAYER_OPTION_NAVBAR_RESEARCH_WIDE'          => SN::$user_options[PLAYER_OPTION_NAVBAR_RESEARCH_WIDE],
1015
1016
      'TUTORIAL_ENABLED' => $tutorial_enabled,
1017
1018
      'PT_MOON'        => PT_MOON,
1019
      'SUBQUE_FLEET'   => SUBQUE_FLEET,
1020
      'SUBQUE_DEFENSE' => SUBQUE_DEFENSE,
1021
      'QUE_RESEARCH'   => QUE_RESEARCH,
1022
      'QUE_STRUCTURES' => QUE_STRUCTURES,
1023
    ));
1024
1025
    if (
1026
      (defined('SN_RENDER_NAVBAR_PLANET') && SN_RENDER_NAVBAR_PLANET === true)
1027
      ||
1028
      ($user['option_list'][OPT_INTERFACE]['opt_int_navbar_resource_force'] && (!defined('SN_RENDER_NAVBAR_PLANET') || SN_RENDER_NAVBAR_PLANET !== false))
1029
    ) {
1030
      tpl_set_resource_info($template, $planetrow);
1031
      $template->assign_vars(array(
1032
        'SN_RENDER_NAVBAR_PLANET' => true,
1033
        'SN_NAVBAR_HIDE_FLEETS'   => true,
1034
      ));
1035
    }
1036
1037
    return $user;
1038
  }
1039
1040
  /**
1041
   * @param array|string  $files
1042
   * @param template|null $template
1043
   * @param string|null   $template_path - path to templates root
1044
   *
1045
   * @return template
1046
   */
1047
  public static function gettemplate($files, $template = null, $template_path = null, $fallBackPath = '') {
1048
    global $sn_mvc, $sn_page_name;
1049
1050
    $template = self::getCurrentTemplate()->getTemplate($template, $template_path, $fallBackPath);
1051
1052
    // TODO ГРЯЗНЫЙ ХАК! Это нужно, что бы по возможности перезаписать инфу из языковых пакетов модулей там, где она была перезаписана раньше инфой из основного пакета. Почему?
1053
    //  - сначала грузятся модули и их языковые пакеты
1054
    //  - затем по ходу дела ОСНОВНОЙ языковой пакет может перезаписать данные из МОДУЛЬНОГО языкового пакета
1055
    // Поэтому и нужен этот грязный хак
1056
    // В норме же - страницы заявляют сами, какие им пакеты нужны. Так что сначала всегда должны грузится основные языковые пакеты, а уже ПОВЕРХ них - пакеты модулей
1057
    !empty($sn_mvc['i18n']['']) ? lng_load_i18n($sn_mvc['i18n']['']) : false;
1058
    $sn_page_name ? lng_load_i18n($sn_mvc['i18n'][$sn_page_name]) : false;
1059
1060
    if (empty($files)) {
1061
      // Make sure that all empty files will translate to empty array
1062
      $files = [];
1063
    } elseif (is_string($files)) {
1064
      // If we have single filename - making array from it
1065
      $files = [basename($files) => $files];
1066
    } elseif (!is_array($files)) {
0 ignored issues
show
The condition is_array($files) is always true.
Loading history...
1067
      // And final touch - all other non-string and non-array inputs converted to empty array
1068
      $files = [];
1069
    }
1070
1071
    foreach ($files as &$filename) {
1072
      $filename = $filename . self::TPL_HTML;
1073
    }
1074
1075
    $template->set_filenames($files);
1076
1077
    return $template;
1078
  }
1079
1080
  /**
1081
   * @param template|string $page
1082
   * @param string          $title
1083
   *
1084
   * @return mixed
1085
   */
1086
  public static function display($page, $title = '') {
1087
    SN::$gSomethingWasRendered = true;
1088
1089
    if (!defined('SN_TIME_RENDER_START')) {
1090
      define('SN_TIME_RENDER_START', microtime(true));
1091
    }
1092
1093
//  return sn_function_call('display', array($page, $title));
1094
//}
1095
//
1096
///**
1097
// * @param template|string $page
1098
// * @param string          $title
1099
// */
1100
//function sn_display($page, $title = '') {
1101
    global $debug, $user, $planetrow, $config, $lang, $template_result, $sn_mvc;
1102
1103
    !empty($sn_mvc['view']['']) and execute_hooks($sn_mvc['view'][''], $page, 'view', '');
1104
1105
    $exitStatus                      = true;
1106
    $template_result['LOGIN_LOGOUT'] = $inLoginLogout = defined('LOGIN_LOGOUT') && LOGIN_LOGOUT === true;
1107
1108
    if (is_object($page)) {
1109
      isset($page->_rootref['PAGE_TITLE']) && empty($title) ? $title = $page->_rootref['PAGE_TITLE'] : false;
1110
      !$title && !empty($page->_rootref['PAGE_HEADER']) ? $title = $page->_rootref['PAGE_HEADER'] : false;
1111
      !isset($page->_rootref['PAGE_HEADER']) && $title ? $page->assign_var('PAGE_HEADER', $title) : false;
1112
    }
1113
1114
    $isRenderGlobal = is_object($page) && isset($template_result['GLOBAL_DISPLAY_HEADER']) ? $template_result['GLOBAL_DISPLAY_HEADER'] : true;
1115
1116
    if (self::getCurrentTemplate()->isRenderWhole()) {
1117
      ob_start();
1118
    } else {
1119
      // Global header
1120
      if ($isRenderGlobal) {
1121
        SnTemplate::renderHeader($page, $title, $template_result, $inLoginLogout, $user, $config, $lang, $planetrow, null);
1122
      }
1123
    }
1124
1125
    // Page content
1126
    !is_array($page) ? $page = array($page) : false;
1127
    $result_added = false;
1128
    foreach ($page as $page_item) {
1129
      /**
1130
       * @var template $page_item
1131
       */
1132
      if (
1133
        !$result_added
1134
        && is_object($page_item)
1135
        && (
1136
          isset($page_item->_tpldata['result'])
1137
          ||
1138
          !empty($template_result['.']['result'])
1139
        )
1140
      ) {
1141
        $resultTemplate = SnTemplate::gettemplate('_result_message');
1142
1143
        $resultTemplate->_tpldata = $page_item->_tpldata;
1144
1145
        // Checking that no duplicates would be merged from template_result to template itself
1146
        $filtered = [];
1147
        if (!empty($template_result['.']['result']) && is_array($template_result['.']['result'])) {
1148
          foreach ($template_result['.']['result'] as $message) {
1149
            if (empty($message['MESSAGE'])) {
1150
              continue;
1151
            }
1152
1153
            foreach ($resultTemplate->_tpldata['result'] as $tplData) {
1154
              if (empty($tplData['MESSAGE'])) {
1155
                continue;
1156
              }
1157
1158
              if ($tplData['MESSAGE'] == $message['MESSAGE']) {
1159
                continue 2;
1160
              }
1161
            }
1162
1163
            $filtered['.']['result'][] = $message;
1164
          }
1165
        }
1166
        $resultTemplate->assign_recursive($filtered);
1167
1168
        SnTemplate::displayP($resultTemplate);
1169
        $result_added = true;
1170
      }
1171
1172
      SnTemplate::displayP($page_item);
1173
    }
1174
1175
    if (is_array($template_result[TEMPLATE_EXTRA_ARRAY]) && !empty($template_result[TEMPLATE_EXTRA_ARRAY])) {
1176
      foreach ($template_result[TEMPLATE_EXTRA_ARRAY] as $extraName => $extraTemplate) {
1177
        /**
1178
         * @var template $extraTemplate
1179
         */
1180
        SnTemplate::displayP($extraTemplate);
1181
      }
1182
    }
1183
1184
    if (
1185
      is_object($page[0])
1186
      &&
1187
      (
1188
        // Checking if hiding page hint flag is present
1189
        empty($template_result['PAGE_HINT_HIDE'])
1190
        &&
1191
        empty($page[0]->_rootref['PAGE_HINT_HIDE'])
1192
      )
1193
      &&
1194
      (
1195
        isset($page[0]->_tpldata['page_hint'])
1196
        ||
1197
        isset($page[0]->_rootref['PAGE_HINT'])
1198
        ||
1199
        !empty($template_result['.']['page_hint'])
1200
        ||
1201
        !empty($template_result['PAGE_HINT'])
1202
      )
1203
    ) {
1204
      $resultTemplate = self::gettemplate('page_hint');
1205
1206
      $resultTemplate->_tpldata = &$page[0]->_tpldata;
1207
      $resultTemplate->_rootref = &$page[0]->_rootref;
1208
      $resultTemplate->assign_recursive($template_result);
1209
1210
      SnTemplate::displayP($resultTemplate);
1211
    }
1212
1213
    if (self::getCurrentTemplate()->isRenderWhole()) {
1214
      $renderedContent = ob_get_clean();
1215
      // Global header
1216
      if ($isRenderGlobal) {
1217
        SnTemplate::renderHeader($page, $title, $template_result, $inLoginLogout, $user, $config, $lang, $planetrow, $renderedContent);
1218
      } else {
1219
        echo $renderedContent;
1220
      }
1221
    }
1222
1223
    // Flushing all opened buffers
1224
    while (@ob_end_flush()) {
1225
      ;
1226
    }
1227
1228
1229
    // Global footer
1230
    if ($isRenderGlobal) {
1231
      SnTemplate::renderFooter($page, $template_result);
1232
    }
1233
1234
    $user['authlevel'] >= 3 && $config->debug ? $debug->echo_log() : false;;
1235
1236
    SN::$db->db_disconnect();
1237
1238
    $exitStatus and die($exitStatus === true ? 0 : $exitStatus);
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
The condition $exitStatus === true is always true.
Loading history...
1239
1240
    return $exitStatus;
1241
  }
1242
1243
  /**
1244
   * @var GlobalContainer|null $gc
1245
   */
1246
  protected $gc = null;
1247
1248
  /**
1249
   * @var TemplateMeta[] $templates
1250
   */
1251
  protected $templates = [];
1252
1253
  public function __construct($gc = null) {
1254
    $this->gc = empty($gc) ? SN::$gc : $gc;
1255
  }
1256
1257
  public function registerTemplate($templateName) {
1258
    if (empty($this->templates[$templateName])) {
1259
      $this->templates[$templateName] = new TemplateMeta($this, $templateName);
1260
    }
1261
1262
    return $this->templates[$templateName];
1263
  }
1264
1265
1266
  /**
1267
   * Дефолтное имя темплейта на сервере
1268
   *
1269
   * @return string
1270
   */
1271
  public static function getServerDefaultTemplateName() {
1272
    return SN::$config->game_default_template ? SN::$config->game_default_template : self::SN_TEMPLATE_NAME_DEFAULT;
1273
  }
1274
1275
  /**
1276
   * Имя темплейта у игрока
1277
   *
1278
   * @return string
1279
   */
1280
  public static function getPlayerTemplateName() {
1281
    return SN::$gc->theUser->getTemplateName();
1282
  }
1283
1284
  /**
1285
   * Относительный путь к сконфигурированному темплейту
1286
   * 'design/templates/(имя_темплейта)
1287
   *
1288
   * @return string
1289
   * @deprecated
1290
   */
1291
  public static function pathRelativeToCurrentTemplate() {
1292
    return self::SN_TEMPLATES_PARTIAL_PATH . self::getPlayerTemplateName();
1293
  }
1294
1295
  /**
1296
   * @return TemplateMeta
1297
   */
1298
  public static function getCurrentTemplate() {
1299
    $templateName = SnTemplate::getPlayerTemplateName();
1300
    $tMeta        = static::me()->registerTemplate($templateName);
0 ignored issues
show
It seems like registerTemplate() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1300
    $tMeta        = static::me()->/** @scrutinizer ignore-call */ registerTemplate($templateName);
Loading history...
1301
1302
    return $tMeta;
1303
  }
1304
1305
  /**
1306
   * @param array  $fileList
1307
   * @param string $extension
1308
   *
1309
   * @return array|string[]
1310
   */
1311
  protected static function cacheFiles($fileList, $extension = '.css') {
1312
    // Calculating file key which include all used filenames and modification time for them
1313
    $key          = '';
1314
    $filesToMerge = [];
1315
    foreach ($fileList as $fileName => $aContent) {
1316
      // If content empty - index is a filename
1317
      if (empty($aContent)) {
1318
        // Checking file modification time. Also we will check if file exists
1319
        if ($fileMTime = filemtime(SN_ROOT_PHYSICAL . $fileName)) {
1320
          // Generating key
1321
          $key .= "$fileName:" . date(FMT_DATE_TIME_SQL, $fileMTime) . "\n";
1322
          // Adding filename to list of merge
1323
          $filesToMerge[$fileName] = "$fileName:" . date(FMT_DATE_TIME_SQL, $fileMTime);
1324
        }
1325
      }
1326
    }
1327
    // Name we will be using to address this file
1328
    $cacheFileName = 'design/cache/' . md5($key) . $extension;
1329
    // If no file exists - trying to create it
1330
    if (!file_exists($fullCacheFileName = SN_ROOT_PHYSICAL . $cacheFileName)) {
1331
      // Caching several files into one
1332
      $contentToCache = '';
1333
      foreach ($filesToMerge as $fileName => $temp) {
1334
        if (file_exists($fName = SN_ROOT_PHYSICAL . $fileName) && !empty($content = file_get_contents($fName))) {
1335
          // Adding content of cached file
1336
          $contentToCache .= $content . "\n";
1337
          // Marking that file was read OK - for future debug purposes if any
1338
          $filesToMerge[$fileName] .= " - OK\n";
1339
        }
1340
      }
1341
      // If we have something to cache...
1342
      if (!empty($contentToCache)) {
1343
        // /* */ works as comment for both JS and CSS
1344
        file_put_contents($fullCacheFileName, "/* Generated content. Safe to delete\n" . implode('', $filesToMerge) . "*/\n\n" . $contentToCache);
1345
      }
1346
    }
1347
1348
    // If CSS cache exists for current combination of files
1349
    if (file_exists($fullCacheFileName)) {
1350
      // Removing from list all CSS files that already in cache
1351
      foreach ($filesToMerge as $fileName => $temp) {
1352
        unset($fileList[$fileName]);
1353
      }
1354
      // Adding to list cache file
1355
      $fileList = [$cacheFileName => ''] + $fileList;
1356
    }
1357
1358
    return $fileList;
1359
  }
1360
1361
}
1362