Test Failed
Push — trunk ( dc8fe4...b76cfb )
by SuperNova.WS
10:59
created

SnTemplate::cacheFiles()   B

Complexity

Conditions 11
Paths 24

Size

Total Lines 48
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 21
nc 24
nop 2
dl 0
loc 48
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
Bug introduced by
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
introduced by
The condition is_array($menu) is always true.
Loading history...
introduced by
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
introduced by
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
Unused Code introduced by
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...
Unused Code introduced by
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
Bug introduced by
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
Bug introduced by
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::cacheFiles($standard_js, '.js');
406
407
    // Prepending standard CSS files
408
    $sn_mvc['javascript'][''] = array_merge($standard_js, $sn_mvc['javascript']['']);
409
410
    self::renderFileListInclude($template_result, $sn_mvc, $sn_page_name, 'javascript');
411
  }
412
413
  /**
414
   * @param $is_login
415
   */
416
  public static function renderCss($is_login) {
417
    global $sn_mvc, $sn_page_name, $template_result;
418
419
    empty($sn_mvc['css']) ? $sn_mvc['css'] = ['' => []] : false;
420
421
    $standard_css = [];
422
    $standard_css = self::addFileName('design/css/jquery-ui', $standard_css);
423
    $standard_css = self::addFileName('design/css/global', $standard_css);
424
    $is_login ? $standard_css = self::addFileName('design/css/login', $standard_css) : false;
425
    $standard_css = self::addFileName('design/css/menu_icons', $standard_css);
426
427
    $standard_css = self::getCurrentTemplate()->cssAddFileName('_template', $standard_css);
428
429
    $standard_css = self::addFileName(SN::$gc->theUser->getSkinPath() . 'skin', $standard_css);
430
    $standard_css = self::addFileName('design/css/global_override', $standard_css);
431
432
    // Trying to cache CSS files
433
    $standard_css = self::cacheFiles($standard_css);
434
435
    // Prepending standard CSS files
436
    $sn_mvc['css'][''] = array_merge($standard_css, $sn_mvc['css']['']);
437
438
    self::renderFileListInclude($template_result, $sn_mvc, $sn_page_name, 'css');
439
  }
440
441
  /**
442
   * @param $time
443
   * @param $event
444
   * @param $msg
445
   * @param $prefix
446
   * @param $is_decrease
447
   * @param $fleet_flying_row
448
   * @param $fleet_flying_sorter
449
   * @param $fleet_flying_events
450
   * @param $fleet_event_count
451
   */
452
  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) {
453
    $fleet_flying_sorter[$fleet_event_count] = $time;
454
    $fleet_flying_events[$fleet_event_count] = array(
455
      'ROW'              => $fleet_flying_row,
456
      'FLEET_ID'         => $fleet_flying_row['fleet_id'],
457
      'EVENT'            => $event,
458
      'COORDINATES'      => uni_render_coordinates($fleet_flying_row, $prefix),
459
      'COORDINATES_TYPE' => $fleet_flying_row["{$prefix}type"],
460
      'TEXT'             => "{$msg}",
461
      'DECREASE'         => $is_decrease,
462
    );
463
    $fleet_event_count++;
464
  }
465
466
  /**
467
   * @param template $template
468
   * @param array    $fleet_flying_list
469
   * @param string   $type
470
   */
471
  public static function tpl_topnav_event_build(&$template, $fleet_flying_list, $type = 'fleet') {
472
    if (empty($fleet_flying_list)) {
473
      return;
474
    }
475
476
    global $lang;
477
478
    $fleet_event_count   = 0;
479
    $fleet_flying_sorter = array();
480
    $fleet_flying_events = array();
481
    foreach ($fleet_flying_list as &$fleet_flying_row) {
482
      $will_return = true;
483
      if ($fleet_flying_row['fleet_mess'] == 0) {
484
        // cut fleets on Hold and Expedition
485
        if ($fleet_flying_row['fleet_start_time'] >= SN_TIME_NOW) {
486
          $fleet_flying_row['fleet_mission'] == MT_RELOCATE ? $will_return = false : false;
487
          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);
488
        }
489
        if ($fleet_flying_row['fleet_end_stay']) {
490
          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);
491
        }
492
      }
493
      if ($will_return) {
494
        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);
495
      }
496
    }
497
498
    asort($fleet_flying_sorter);
499
500
    $fleet_flying_count = count($fleet_flying_list);
501
    foreach ($fleet_flying_sorter as $fleet_event_id => $fleet_time) {
502
      $fleet_event = &$fleet_flying_events[$fleet_event_id];
503
      $template->assign_block_vars("flying_{$type}s", array(
504
        'TIME' => max(0, $fleet_time - SN_TIME_NOW),
505
        'TEXT' => $fleet_flying_count,
506
        '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']]}",
507
      ));
508
      $fleet_event['DECREASE'] ? $fleet_flying_count-- : false;
509
    }
510
  }
511
512
  /**
513
   * @return mixed|string
514
   */
515
  public static function playerFontSize() {
516
    $font_size = !empty($_COOKIE[SN_COOKIE_F]) ? $_COOKIE[SN_COOKIE_F] : SN::$user_options[PLAYER_OPTION_BASE_FONT_SIZE];
517
    if (strpos($font_size, '%') !== false) {
518
      // Размер шрифта в процентах
519
      $font_size = min(max(floatval($font_size), FONT_SIZE_PERCENT_MIN), FONT_SIZE_PERCENT_MAX) . '%';
520
521
      return $font_size;
522
    } elseif (strpos($font_size, 'px') !== false) {
523
      // Размер шрифта в пикселях
524
      $font_size = min(max(floatval($font_size), FONT_SIZE_PIXELS_MIN), FONT_SIZE_PIXELS_MAX) . 'px';
525
526
      return $font_size;
527
    } else {
528
      // Не мышонка, не лягушка...
529
      $font_size = FONT_SIZE_PERCENT_DEFAULT_STRING;
530
531
      return $font_size;
532
    }
533
  }
534
535
  /**
536
   * Checks if minified/full-size file variant exists - and adds it if any
537
   *
538
   * @param string|string[] $fileNames
539
   * @param array  $anArray
540
   *
541
   * @return array
542
   */
543
  public static function addFileName($fileNames, $anArray, $ext = '.css') {
544
    if(!is_array($fileNames)) {
545
      $fileNames = [$fileNames];
546
    }
547
548
    foreach($fileNames as $fileName) {
549
      if (file_exists(SN_ROOT_PHYSICAL . $fileName . '.min' . $ext)) {
550
        $anArray[$fileName . '.min' . $ext] = '';
551
      } elseif (file_exists(SN_ROOT_PHYSICAL . $fileName . '.css' . $ext)) {
552
        $anArray[$fileName . $ext] = '';
553
      }
554
    }
555
556
    return $anArray;
557
  }
558
559
  /**
560
   * @param array   $template_result
561
   * @param array[] $sn_mvc
562
   * @param string  $sn_page_name
563
   * @param string  $fileType - 'css' or 'javascript'
564
   */
565
  public static function renderFileListInclude(&$template_result, &$sn_mvc, $sn_page_name, $fileType) {
566
    if (empty($sn_mvc[$fileType])) {
567
      return;
568
    }
569
570
    foreach ($sn_mvc[$fileType] as $page_name => $script_list) {
571
      if (empty($page_name) || $page_name == $sn_page_name) {
572
        foreach ($script_list as $filename => $content) {
573
          $template_result['.'][$fileType][] = array(
574
            'FILE'    => $filename,
575
            'CONTENT' => $content,
576
          );
577
        }
578
      }
579
    }
580
  }
581
582
  /**
583
   * @param $template
584
   * @param $user
585
   */
586
  public static function tpl_navbar_render_notes(&$template, &$user) {
587
    $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

587
    $notes_query = /** @scrutinizer ignore-deprecated */ doquery("SELECT * FROM {{notes}} WHERE `owner` = {$user['id']} AND `sticky` = 1 ORDER BY priority DESC, time DESC");
Loading history...
588
    while ($note_row = db_fetch($notes_query)) {
589
      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

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

800
    $template = self::gettemplate('message_body', /** @scrutinizer ignore-type */ true);
Loading history...
801
802
    $template_result['GLOBAL_DISPLAY_NAVBAR'] = $showHeader;
803
804
    $template->assign_vars(array(
805
//    'GLOBAL_DISPLAY_NAVBAR' => $showHeader,
806
807
      'TITLE'       => $title,
808
      'MESSAGE'     => $message,
809
      'REDIRECT_TO' => $redirectTo,
810
      'TIMEOUT'     => $timeout,
811
    ));
812
813
    self::display($template, $title);
814
  }
815
816
  /**
817
   * Admin message box
818
   *
819
   * @param        $message
820
   * @param string $title
821
   * @param string $redirectTo
822
   * @param int    $timeout
823
   *
824
   * @see SnTemplate::messageBox()
825
   */
826
  public static function messageBoxAdmin($message, $title = '', $redirectTo = '', $timeout = 5) {
827
    SnTemplate::messageBox($message, $title, $redirectTo, $timeout, false);
828
  }
829
830
  public static function messageBoxAdminAccessDenied($level = AUTH_LEVEL_ADMINISTRATOR) {
831
    global $user, $lang;
832
833
    if ($user['authlevel'] < $level) {
834
      SnTemplate::messageBoxAdmin($lang['adm_err_denied'], $lang['admin_title_access_denied'], SN_ROOT_VIRTUAL . 'overview.php');
835
    }
836
  }
837
838
  /**
839
   * @param          $prevUser
840
   * @param array    $user
841
   * @param array    $planetrow
842
   * @param template $template
843
   *
844
   * @return array
845
   */
846
  public static function sn_tpl_render_topnav(&$prevUser, $user, $planetrow, $template) {
847
    global $lang, $config, $sn_mvc;
848
849
    // This call was not first one... Using results from previous call
850
    if (!empty($prevUser['username'])) {
851
      $user = $prevUser;
852
    }
853
854
    if (!is_array($user)) {
855
      return $user;
856
    }
857
858
    $GET_mode = sys_get_param_str('mode');
859
860
    $ThisUsersPlanets = DBStaticPlanet::db_planet_list_sorted($user);
861
    foreach ($ThisUsersPlanets as $CurPlanet) {
0 ignored issues
show
Bug introduced by
The expression $ThisUsersPlanets of type false is not traversable.
Loading history...
862
      if ($CurPlanet['destruyed']) {
863
        continue;
864
      }
865
866
      $fleet_listx = flt_get_fleets_to_planet($CurPlanet);
867
      if ($CurPlanet['planet_type'] == PT_MOON) {
868
        $parentPlanet = DBStaticPlanet::db_planet_by_id($CurPlanet['parent_planet']);
869
      } else {
870
        $parentPlanet = $CurPlanet;
871
      }
872
873
      $template->assign_block_vars('topnav_planets', [
874
        'ID'          => $CurPlanet['id'],
875
        'NAME'        => $CurPlanet['name'],
876
        'TYPE'        => $CurPlanet['planet_type'],
877
        'TYPE_TEXT'   => $lang['sys_planet_type_sh'][$CurPlanet['planet_type']],
878
        'IS_CAPITAL'  => $parentPlanet['id'] == $user['id_planet'],
879
        'IS_MOON'     => $CurPlanet['planet_type'] == PT_MOON,
880
        'PLIMAGE'     => $CurPlanet['image'],
881
        'FLEET_ENEMY' => $fleet_listx['enemy']['count'],
882
        'COORDS'      => uni_render_coordinates($CurPlanet),
883
        'SELECTED'    => $CurPlanet['id'] == $user['current_planet'] ? ' selected' : '',
884
      ]);
885
    }
886
887
    $fleet_flying_list = DbFleetStatic::tpl_get_fleets_flying($user);
888
    SnTemplate::tpl_topnav_event_build($template, $fleet_flying_list[0]);
889
    SnTemplate::tpl_topnav_event_build($template, $fleet_flying_list[MT_EXPLORE], 'expedition');
890
891
    que_tpl_parse($template, QUE_STRUCTURES, $user, $planetrow, null, true);
892
    que_tpl_parse($template, QUE_RESEARCH, $user, array(), null, !SN::$user_options[PLAYER_OPTION_NAVBAR_RESEARCH_WIDE]);
893
    que_tpl_parse($template, SUBQUE_FLEET, $user, $planetrow, null, true);
894
    que_tpl_parse($template, SUBQUE_DEFENSE, $user, $planetrow, null, true);
895
896
    SnTemplate::tpl_navbar_extra_buttons($sn_mvc, $template);
897
    SnTemplate::tpl_navbar_render_news($template, $user, $config);
898
    SnTemplate::tpl_navbar_render_notes($template, $user);
899
    $tutorial_enabled = PageTutorial::renderNavBar($template);
900
901
902
    $premium_lvl = mrc_get_level($user, false, UNIT_PREMIUM, true, true);
0 ignored issues
show
Bug introduced by
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

902
    $premium_lvl = mrc_get_level($user, /** @scrutinizer ignore-type */ false, UNIT_PREMIUM, true, true);
Loading history...
903
904
    $str_date_format   = "%3$02d %2$0s %1$04d {$lang['top_of_year']} %4$02d:%5$02d:%6$02d";
905
    $time_now_parsed   = getdate(SN_TIME_NOW);
906
    $time_local_parsed = getdate(defined('SN_CLIENT_TIME_LOCAL') ? SN_CLIENT_TIME_LOCAL : SN_TIME_NOW);
907
908
    $template->assign_vars(array(
909
      'QUE_ID'   => QUE_RESEARCH,
910
      'QUE_HTML' => 'topnav',
911
912
      'RESEARCH_ONGOING' => (boolean)$user['que'],
913
914
      'TIME_TEXT'       => sprintf($str_date_format, $time_now_parsed['year'], $lang['months'][$time_now_parsed['mon']], $time_now_parsed['mday'],
915
        $time_now_parsed['hours'], $time_now_parsed['minutes'], $time_now_parsed['seconds']
916
      ),
917
      'TIME_TEXT_LOCAL' => sprintf($str_date_format, $time_local_parsed['year'], $lang['months'][$time_local_parsed['mon']], $time_local_parsed['mday'],
918
        $time_local_parsed['hours'], $time_local_parsed['minutes'], $time_local_parsed['seconds']
919
      ),
920
921
      'GAME_BLITZ_REGISTER'             => $config->game_blitz_register,
922
      'GAME_BLITZ_REGISTER_TEXT'        => $lang['sys_blitz_registration_mode_list'][$config->game_blitz_register],
923
      'BLITZ_REGISTER_OPEN'             => $config->game_blitz_register == BLITZ_REGISTER_OPEN,
924
      'BLITZ_REGISTER_CLOSED'           => $config->game_blitz_register == BLITZ_REGISTER_CLOSED,
925
      'BLITZ_REGISTER_SHOW_LOGIN'       => $config->game_blitz_register == BLITZ_REGISTER_SHOW_LOGIN,
926
      'BLITZ_REGISTER_DISCLOSURE_NAMES' => $config->game_blitz_register == BLITZ_REGISTER_DISCLOSURE_NAMES,
927
      'GAME_BLITZ'                      => $config->game_mode == GAME_BLITZ,
928
929
      'USERS_ONLINE'  => $config->var_online_user_count,
930
      'USERS_TOTAL'   => $config->users_amount,
931
      'USER_RANK'     => $user['total_rank'],
932
      'USER_NICK'     => $user['username'],
933
      'USER_AVATAR'   => $user['avatar'],
934
      'USER_AVATARID' => $user['id'],
935
      'USER_PREMIUM'  => $premium_lvl,
936
      'USER_RACE'     => $user['player_race'],
937
938
      'TOPNAV_CURRENT_PLANET'       => $user['current_planet'],
939
      'TOPNAV_CURRENT_PLANET_NAME'  => uni_render_planet_full($planetrow), // htmlspecialchars($planetrow['name']),
940
      'TOPNAV_CURRENT_PLANET_IMAGE' => $planetrow['image'],
941
      'TOPNAV_COLONIES_CURRENT'     => get_player_current_colonies($user),
942
      'TOPNAV_COLONIES_MAX'         => get_player_max_colonies($user),
943
      'NAVBAR_MODE'                 => $GET_mode,
944
945
      'TOPNAV_DARK_MATTER'            => mrc_get_level($user, '', RES_DARK_MATTER),
0 ignored issues
show
Bug introduced by
'' 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

945
      'TOPNAV_DARK_MATTER'            => mrc_get_level($user, /** @scrutinizer ignore-type */ '', RES_DARK_MATTER),
Loading history...
946
      'TOPNAV_DARK_MATTER_TEXT'       => HelperString::numberFloorAndFormat(mrc_get_level($user, '', RES_DARK_MATTER)),
0 ignored issues
show
Bug introduced by
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

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

1268
    $tMeta        = static::me()->/** @scrutinizer ignore-call */ registerTemplate($templateName);
Loading history...
1269
1270
    return $tMeta;
1271
  }
1272
1273
  /**
1274
   * @param array  $fileList
1275
   * @param string $extension
1276
   *
1277
   * @return array|string[]
1278
   */
1279
  protected static function cacheFiles($fileList, $extension = '.css') {
1280
    // Calculating file key which include all used filenames and modification time for them
1281
    $key          = '';
1282
    $filesToMerge = [];
1283
    foreach ($fileList as $fileName => $aContent) {
1284
      // If content empty - index is a filename
1285
      if (empty($aContent)) {
1286
        // Checking file modification time. Also we will check if file exists
1287
        if ($fileMTime = filemtime(SN_ROOT_PHYSICAL . $fileName)) {
1288
          // Generating key
1289
          $key .= "$fileName:" . date(FMT_DATE_TIME_SQL, $fileMTime) . "\n";
1290
          // Adding filename to list of merge
1291
          $filesToMerge[$fileName] = "$fileName:" . date(FMT_DATE_TIME_SQL, $fileMTime);
1292
        }
1293
      }
1294
    }
1295
    // Name we will be using to address this file
1296
    $cacheFileName = 'design/cache/' . md5($key) . $extension;
1297
    // If no file exists - trying to create it
1298
    if (!file_exists($fullCacheFileName = SN_ROOT_PHYSICAL . $cacheFileName)) {
1299
      // Caching several files into one
1300
      $contentToCache = '';
1301
      foreach ($filesToMerge as $fileName => $temp) {
1302
        if (file_exists($fName = SN_ROOT_PHYSICAL . $fileName) && !empty($content = file_get_contents($fName))) {
1303
          // Adding content of cached file
1304
          $contentToCache .= $content . "\n";
1305
          // Marking that file was read OK - for future debug purposes if any
1306
          $filesToMerge[$fileName] .= " - OK\n";
1307
        }
1308
      }
1309
      // If we have something to cache...
1310
      if (!empty($contentToCache)) {
1311
        // /* */ works as comment for both JS and CSS
1312
        file_put_contents($fullCacheFileName, "/* Generated content. Safe to delete\n" . implode('', $filesToMerge) . "*/\n\n" . $contentToCache);
1313
      }
1314
    }
1315
1316
    // If CSS cache exists for current combination of files
1317
    if (file_exists($fullCacheFileName)) {
1318
      // Removing from list all CSS files that already in cache
1319
      foreach ($filesToMerge as $fileName => $temp) {
1320
        unset($fileList[$fileName]);
1321
      }
1322
      // Adding to list cache file
1323
      $fileList = [$cacheFileName => ''] + $fileList;
1324
    }
1325
1326
    return $fileList;
1327
  }
1328
1329
}
1330