Passed
Push — development ( 5482d2...9758e9 )
by Spuds
01:22 queued 35s
created

theme_breadcrumbs()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 17
nc 3
nop 1
dl 0
loc 36
ccs 0
cts 17
cp 0
crap 30
rs 9.3888
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @package   ElkArte Forum
5
 * @copyright ElkArte Forum contributors
6
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
7
 *
8
 * This file contains code covered by:
9
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
10
 *
11
 * @version 2.0 dev
12
 *
13
 */
14
15
/**
16
 * This template is, perhaps, the most important template in the theme. It
17
 * contains the main template layer that displays the header and footer of
18
 * the forum, namely with body_above and body_below. It also contains the
19
 * menu sub template, which appropriately displays the menu; the init sub
20
 * template, which is there to set the theme up; (init can be missing.) and
21
 * the breadcrumb sub template, which sorts out the breadcrumbs.
22
 *
23
 * The init sub template should load any data and set any hardcoded options.
24
 *
25
 * The body_above sub template is what is shown above the main content, and
26
 * should contain anything that should be shown up there.
27
 *
28
 * The body_below sub template, conversely, is shown after the main content.
29
 * It should probably contain the copyright statement and some other things.
30
 *
31
 * The breadcrumb sub template should display the breadcrumbs, using the data
32
 * in the $context['breadcrumbs'] variable.
33
 *
34
 * The menu sub template should display all the relevant buttons the user
35
 * wants and or needs.
36
 */
37
38
/**
39
 * Start off the template by loading some helpers like
40
 * quick buttons, page index, etc
41
 */
42
function template_Index_init()
43
{
44
	theme()->getTemplates()->load('GenericHelpers');
45
}
46
47
/**
48
 * Simplify the use of callbacks in the templates.
49
 *
50
 * @param string $id - A prefix for the template functions the final name
51
 *                     should look like: template_{$id}_{$array[n]}
52
 * @param string[] $array - The array of function suffixes
53
 */
54
function call_template_callbacks($id, $array)
55
{
56
	if (empty($array))
57
	{
58
		return;
59
	}
60
61
	foreach ($array as $callback)
62
	{
63
		$func = 'template_' . $id . '_' . $callback;
64
		if (function_exists($func))
65
		{
66
			$func();
67
		}
68
	}
69
}
70
71
/**
72
 * The main sub template above the content.
73
 */
74
function template_html_above()
75
{
76
	global $context, $scripturl, $txt;
77
78
	// Show right to left and the character set for ease of translating.
79
	echo '<!DOCTYPE html>
80
<html dir=', $context['right_to_left'] ? ' "RTL"' : 'LTR', ' lang="', str_replace('_', '-', $txt['lang_locale']), '">
81
<head>
82
	<title>', $context['page_title_html_safe'], '</title>
83
	<meta charset="utf-8" />';
84
85
	$description = $context['page_title_html_safe'];
86
	if (isset($context['page_description']))
87
	{
88
		$description .= ': ' . $context['page_description'];
89
	}
90
91
	echo '
92
	<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
93
	<meta name="mobile-web-app-capable" content="yes" />
94
	<meta name="description" content="', $description, '" />
95
	<meta name="theme-color" content="', $context['theme-color'], '" />';
96
97
	// Please don't index these Mr Robot.
98
	if (!empty($context['robot_no_index']))
99
	{
100
		echo '
101
	<meta name="robots" content="noindex" />';
102
	}
103
104
	// If we have any Open Graph data, here is where is inserted.
105
	if (!empty($context['open_graph']))
106
	{
107
		echo '
108
	' .implode("\n\t", $context['open_graph']);
109
	}
110
111
	// Present a canonical url for search engines to prevent duplicate content in their indices.
112
	if (!empty($context['canonical_url']))
113
	{
114
		echo '
115
	<link rel="canonical" href="', $context['canonical_url'], '" />';
116
	}
117
118
	// Various icons and optionally a PWA manifest
119
	echo '
120
	<link rel="icon" sizes="any" href="' . $context['favicon'] . '" />
121
	<link rel="apple-touch-icon" href="' . $context['apple_touch'] . '" />';
122
123
	if (!empty($context['pwa_manifest_enabled']))
124
	{
125
		echo '
126
	<link rel="manifest" href="./elkManifest.php">';
127
	}
128
129
	// Show all the relative links, such as help, search, contents, and the like.
130
	echo '
131
	<link rel="help" href="', getUrl('action', ['action' => 'help']), '" />
132
	<link rel="contents" href="', $scripturl, '" />', ($context['allow_search'] ? '
133
	<link rel="search" href="' . getUrl('action', ['action' => 'search']) . '" />' : '');
134
135
	// If RSS feeds are enabled, advertise the presence of one.
136
	if (!empty($context['newsfeed_urls']))
137
	{
138
		echo '
139
	<link rel="alternate" type="application/rss+xml" title="', $context['forum_name_html_safe'], ' - ', $txt['rss'], '" href="', $context['newsfeed_urls']['rss'], '" />
140
	<link rel="alternate" type="application/rss+xml" title="', $context['forum_name_html_safe'], ' - ', $txt['atom'], '" href="', $context['newsfeed_urls']['atom'], '" />';
141
	}
142
143
	// If we're viewing a topic, these should be the previous and next topics, respectively.
144
	if (!empty($context['links']['next']))
145
	{
146
		echo '
147
	<link rel="next" href="', $context['links']['next'], '" />';
148
	}
149
	elseif (!empty($context['current_topic']))
150
	{
151
		echo '
152
	<link rel="next" href="', $scripturl, '?topic=', $context['current_topic'], '.0;prev_next=next" />';
153
	}
154
155
	if (!empty($context['links']['prev']))
156
	{
157
		echo '
158
	<link rel="prev" href="', $context['links']['prev'], '" />';
159
	}
160
	elseif (!empty($context['current_topic']))
161
	{
162
		echo '
163
	<link rel="prev" href="', $scripturl, '?topic=', $context['current_topic'], '.0;prev_next=prev" />';
164
	}
165
166
	// If we're in a board, or a topic for that matter, the index will be the board's index.
167
	if (!empty($context['current_board']))
168
	{
169
		echo '
170
	<link rel="index" href="', $scripturl, '?board=', $context['current_board'], '.0" />';
171
	}
172
173
	// load in css from addons or themes, do it first so overrides are possible
174
	theme()->themeCss()->template_css();
175
176
	// load in any javascript files and inline from addons and themes
177
	theme()->themeJs()->template_javascript();
178
179
	// load in any inline css files from addons and themes
180
	theme()->themeCss()->template_inlinecss();
181
182
	// Output any remaining HTML headers. (from addons, maybe?)
183
	echo $context['html_headers'];
184
185
	echo '
186
	</head>';
187
188
	// Start defining the body class
189
	$bodyClass = 'action_';
190
191
	if (!empty($context['current_action']))
192
	{
193
		$bodyClass .= htmlspecialchars($context['current_action'], ENT_COMPAT, 'UTF-8');
194
	}
195
	elseif (!empty($context['current_board']))
196
	{
197
		$bodyClass .= 'messageindex';
198
	}
199
	elseif (!empty($context['current_topic']))
200
	{
201
		$bodyClass .= 'display';
202
	}
203
	else
204
	{
205
		$bodyClass .= 'home';
206
	}
207
208
	if (!empty($context['current_board']))
209
	{
210
		$bodyClass .= ' board_' . htmlspecialchars($context['current_board'], ENT_COMPAT, 'UTF-8');
211
	}
212
213
	echo '
214
	<body class="', $bodyClass .  '">';
215
}
216
217
/**
218
 * Section above the main contents of the page, after opening the body tag
219
 */
220
function template_body_above()
221
{
222
	global $context, $settings, $txt;
223
224
	// Go to top/bottom of page links and skipnav link for a11y.
225
	echo '
226
	<a id="top" href="#skipnav" tabindex="0">', $txt['skip_nav'], '</a>
227
	<a id="gotop" href="#top_section"  title="', $txt['go_up'], '">&#8593;</a>
228
	<a id="gobottom" href="#footer_section" title="', $txt['go_down'], '">&#8595;</a>';
229
230
	echo '
231
	<header id="top_section" class="', (empty($context['minmax_preferences']['upshrink']) ? 'th_expand' : 'th_collapse'), '">
232
		<aside id="top_header" class="wrapper">';
233
234
	// Load in all register header templates
235
	call_template_callbacks('th', $context['theme_header_callbacks']);
236
237
	echo '
238
		</aside>
239
		<section id="header" class="wrapper', empty($settings['header_layout']) ? '' : ($settings['header_layout'] == 1 ? ' centerheader' : ' rightheader'), empty($context['minmax_preferences']['upshrink']) ? '"' : ' hide" aria-hidden="true"', '>
240
			<h1 id="forumtitle">
241
				<a class="forumlink" href="', getUrl('boardindex', []), '">', $context['forum_name'], '</a>';
242
243
	echo '
244
				<span id="logobox">
245
					<img id="logo" src="', $context['header_logo_url_html_safe'], '" alt="', $context['forum_name_html_safe'], '" title="', $context['forum_name_html_safe'], '" />', empty($settings['site_slogan']) ? '' : '
246
					<span id="siteslogan">' . $settings['site_slogan'] . '</span>', '
247
				</span>
248
			</h1>';
249
250
	// Show the menu here, according to the menu sub template.
251
	echo '
252
		</section>';
253
254
	template_menu();
255
256
	echo '
257
	</header>
258
	<div id="wrapper" class="wrapper">
259
		<aside id="upper_section"', empty($context['minmax_preferences']['upshrink']) ? '' : ' class="hide" aria-hidden="true"', '>';
260
261
	// Load in all registered upper content templates
262
	call_template_callbacks('uc', $context['upper_content_callbacks']);
263
264
	echo '
265
		</aside>';
266
267
	// Show the navigation tree.
268
	theme_breadcrumbs();
269
270
	// The main content should go here.
271
	echo '
272
		<div id="main_content_section">
273
			<a id="skipnav"></a>';
274
}
275
276
/**
277
 * More or less a place holder for now, sits at the very page top.
278
 * The maintenance mode warning for admins is an obvious one, but this could also be used for moderation notifications.
279
 * I also assumed this would be an obvious place for sites to put a string of icons to link to their FB, Twitter, etc.
280
 * This could still be done via conditional, so that administration and moderation notices were still active when
281
 * applicable.
282
 */
283
function template_th_header_bar()
284
{
285
	global $context, $txt, $scripturl;
286
287
	echo '
288
			<div id="top_section_notice" class="user', (empty($context['minmax_preferences']['upshrink']) ? '' : ' hide'), '">
289
			</div>';
290
}
291
292
/**
293
 * Search bar form, expands to input form when search icon is clicked
294
 */
295
function template_search_form()
296
{
297
	global $context, $modSettings, $txt;
298
299
	echo '
300
			<form id="search_form_menu" action="', getUrl('action', ['action' => 'search', 'sa' => 'results']), '" method="post" role="search" accept-charset="UTF-8">';
301
302
	// Using the quick search dropdown?
303
	if (!empty($modSettings['search_dropdown']))
304
	{
305
		$selected = empty($context['current_topic']) ? (!empty($context['current_board']) ? 'current_board' : 'all') : ('current_topic');
306
		echo '
307
				<label for="search_selection">
308
					<select name="search_selection" id="search_selection" class="linklevel1" aria-label="search selection">
309
						<option value="all"', ($selected === 'all' ? ' selected="selected"' : ''), '>', $txt['search_entireforum'], ' </option>';
310
311
		// Can't limit it to a specific topic if we are not in one
312
		if (!empty($context['current_topic']))
313
		{
314
			echo '
315
						<option value="topic"', ($selected === 'current_topic' ? ' selected="selected"' : ''), '>', $txt['search_thistopic'], '</option>';
316
		}
317
318
		// Can't limit it to a specific board if we are not in one
319
		if (!empty($context['current_board']))
320
		{
321
			echo '
322
						<option value="board"', ($selected === 'current_board' ? ' selected="selected"' : ''), '>', $txt['search_thisbrd'], '</option>';
323
		}
324
325
		if (!empty($context['additional_dropdown_search']))
326
		{
327
			foreach ($context['additional_dropdown_search'] as $name => $engine)
328
			{
329
				echo '
330
						<option value="', $name, '">', $engine['name'], '</option>';
331
			}
332
		}
333
334
		echo '
335
						<option value="members"', ($selected === 'members' ? ' selected="selected"' : ''), '>', $txt['search_members'], ' </option>
336
					</select>
337
				</label>';
338
	}
339
340
	// Search within current topic?
341
	if (!empty($context['current_topic']))
342
	{
343
		echo '
344
				<input type="hidden" name="', (empty($modSettings['search_dropdown']) ? 'topic' : 'sd_topic'), '" value="', $context['current_topic'], '" />';
345
	}
346
347
	// If we're on a certain board, limit it to this board ;).
348
	if (!empty($context['current_board']))
349
	{
350
		echo '
351
				<input type="hidden" name="', (empty($modSettings['search_dropdown']) ? 'brd[' : 'sd_brd['), $context['current_board'], ']"', ' value="', $context['current_board'], '" />';
352
	}
353
354
	echo '					
355
				<label for="quicksearch" class="hide">', $txt['search'], '</label>
356
				<input type="search" name="search" id="quicksearch" value="" class="linklevel1" placeholder="', $txt['search'], '" />
357
				<button type="submit" aria-label="' . $txt['search'] . '" name="search;sa=results" class="', (empty($modSettings['search_dropdown'])) ? '' : 'with_select', '">
358
					<i class="icon i-search"><s>', $txt['search'], '</s></i>
359
				</button>
360
				<button type="button" aria-label="' . $txt['find_close'] . '">
361
					<label for="search_form_check">
362
						<i class="icon i-close"><s>', $txt['find_close'], '</s></i>
363
					</label>
364
				</button>
365
				<input type="hidden" name="advanced" value="0" />
366
			</form>';
367
}
368
369
/**
370
 * Search bar main menu icon
371
 */
372
function template_mb_search_bar()
373
{
374
	global $txt;
375
376
	echo '
377
						<li id="search_form_button" class="listlevel1" role="none">
378
							<label for="search_form_check">
379
								<a class="linklevel1 panel_search" role="menuitem">
380
									<i class="main-menu-icon i-search colorize-white"><s>', $txt['search'], '</s></i>
381
								</a>
382
							</label>
383
						</li>';
384
}
385
386
/**
387
 * The news fader wrapped in a div and with "news" text
388
 */
389
function template_uc_news_fader()
390
{
391
	global $settings, $context, $txt;
392
393
	// Display either news fader and random news lines (not both). These now run most of the same mark up and CSS. Less complication = happier n00bz. :)
394
	if (!empty($settings['enable_news']) && !empty($context['random_news_line']))
395
	{
396
		echo '
397
			<div id="news">
398
				<h2>', $txt['news'], '</h2>';
399
400
		template_news_fader();
401
402
		echo '
403
			</div>';
404
	}
405
}
406
407
/**
408
 * Section down the page, before closing body
409
 */
410
function template_body_below()
411
{
412
	global $context, $txt;
413
414
	echo '
415
		</div>
416
	</div>';
417
418
	// Show RSS link, as well as the copyright.
419
	// Footer is full-width. Wrapper inside automatically matches admin width setting.
420
	echo '
421
	<footer id="footer_section">
422
		<div class="wrapper">
423
			<ul>
424
				<li class="copyright">',
425
					theme_copyright(), '
0 ignored issues
show
Bug introduced by
Are you sure theme_copyright() of type void can be used in echo? ( Ignorable by Annotation )

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

425
					/** @scrutinizer ignore-type */ theme_copyright(), '
Loading history...
Bug introduced by
Are you sure the usage of theme_copyright() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
426
				</li>',
427
				empty($context['newsfeed_urls']['rss']) ? '' : '
428
				<li>
429
					<a id="button_rss" href="' . $context['newsfeed_urls']['rss'] . '" class="rssfeeds new_win">
430
						<i class="icon icon-margin i-rss icon-big"><s>' . $txt['rss'] . '</s></i>
431
					</a>
432
				</li>', '
433
			</ul>';
434
435
	// Show the load time?
436
	if ($context['show_load_time'])
437
	{
438
		echo '
439
			<p>', sprintf($txt['page_created_full'], $context['load_time'], $context['load_queries']), '</p>';
440
	}
441
}
442
443
/**
444
 * Section down the page, at closing html tag
445
 */
446
function template_html_below()
447
{
448
	global $context;
449
450
	echo '
451
		</div>
452
	</footer>';
453
454
	// This is here to catch any late loading of JS files via templates
455
	theme()->themeJs()->outputJavascriptFiles(theme()->themeJs()->getJSFiles());
456
457
	// load inline javascript that needed to be deferred to the end of the page
458
	theme()->themeJs()->template_inline_javascript(true);
459
460
	// Schema microdata about the organization?
461
	if (!empty($context['smd_site']))
462
	{
463
		echo '
464
	<script type="application/ld+json">
465
	', json_encode($context['smd_site'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), '
466
	</script>';
467
	}
468
469
	// Schema microdata about the post?
470
	if (!empty($context['smd_article']))
471
	{
472
		echo '
473
	<script type="application/ld+json">
474
	', json_encode($context['smd_article'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), '
475
	</script>';
476
	}
477
478
	// Anything special to put out?
479
	if (!empty($context['insert_after_template']))
480
	{
481
		echo $context['insert_after_template'];
482
	}
483
484
	echo '
485
</body>
486
</html>';
487
}
488
489
/**
490
 * Show breadcrumbs. This is that thing that shows
491
 * "My Community | General Category | General Discussion"..
492
 *
493
 * @param string $default a string representing the index in $context where
494
 *               the breadcrumbs are stored (default value is 'breadcrumbs')
495
 */
496
function theme_breadcrumbs($default = 'breadcrumbs')
497
{
498
	global $context, $settings, $txt;
499
500
	// If breadcrumbs is empty, just return - also allow an override.
501
	if (empty($context[$default]))
502
	{
503
		return;
504
	}
505
506
	echo '
507
		<nav class="breadcrumb" aria-label="breadcrumbs">';
508
509
	// Each tree item has a URL and name. Some may have extra_before and extra_after.
510
	// Added a crumb class to make targeting dividers easy.
511
	foreach ($context[$default] as $pos => $tree)
512
	{
513
		$tree['name'] = ($tree['extra_before'] ?? '') . $tree['name'] . ($tree['extra_after'] ?? '');
514
515
		// Show the link, including a URL if it should have one.
516
		echo isset($tree['url'])
517
			? '
518
			<span class="crumb">
519
				<a href="' . $tree['url'] . '">' .
520
					($pos === 0
521
						? '<i class="icon i-home"><s>' . $txt['home'] . '</s></i>'
522
						: $tree['name']) . '
523
				</a>
524
			</span>'
525
			: '
526
			<span class="crumb">
527
				' . $tree['name'] . '
528
			</span>';
529
	}
530
531
	echo '
532
		</nav>';
533
}
534
535
/**
536
 * Show the menu up top. Something like [home] [help] [profile] [logout]...
537
 */
538
function template_menu()
539
{
540
	global $context, $txt;
541
542
	// WAI-ARIA a11y tweaks have been applied here.
543
	echo '
544
				
545
				<nav id="menu_nav" aria-label="', $txt['main_menu'], '">
546
					<div class="wrapper no_js">
547
					<input type="checkbox" id="search_form_check" aria-hidden="true" />
548
					<ul id="main_menu" aria-label="', $txt['main_menu'], '" role="menubar">';
549
550
	// Add any additional menu buttons from addons
551
	call_template_callbacks('mb', $context['theme_header_callbacks']);
552
553
	// This defines the start of right aligned buttons, simply set your button order > 10
554
	echo '
555
						<li id="button_none" class="listlevel1" role="none">
556
							<a role="none"></a>
557
						</li>';
558
559
	// The upshrink image.
560
	echo '
561
						<li id="collapse_button" class="listlevel1" role="none">
562
							<a class="linklevel1 panel_toggle" role="menuitem">
563
								<i id="upshrink" class="hide main-menu-icon i-chevron-up" title="', $txt['upshrink_description'], '"></i>
564
							</a>
565
						</li>';
566
567
	// Now all the buttons from menu.subs
568
	foreach ($context['menu_buttons'] as $act => $button)
569
	{
570
		// Top link details, easier to maintain broken out
571
		$class = 'class="linklevel1' . (empty($button['active_button']) ? '' : ' active') . (empty($button['indicator']) ? '' : ' indicator') . '"';
572
		$href = ' href="' . $button['href'] . '"';
573
		$target = isset($button['target']) ? ' target="' . $button['target'] . '"' : '';
574
		$onclick = isset($button['onclick']) ? ' onclick="' . $button['onclick'] . '"' : '';
575
		$altTitle = 'title="' . (empty($button['alttitle']) ? $button['title'] : $button['alttitle']) . '"';
576
		$ally = empty($button['active_button']) ? '' : ' aria-current="page"';
577
578
		echo '
579
						<li id="button_', $act, '" class="listlevel1', empty($button['sub_buttons']) ? '"' : ' subsections"', ' role="none">
580
							<a ', $class, $href, $target, $ally, $onclick, ' role="menuitem"', empty($button['sub_buttons']) ? '' : ' aria-haspopup="true"', '>',
581
								(empty($button['data-icon']) ? '' : '<i class="icon icon-menu icon-lg ' . $button['data-icon'] . (empty($button['active_button']) ? '' : ' enabled') . '" ' . $altTitle . '></i> '),
582
								'<span class="button_title" aria-hidden="', (empty($button['sub_buttons']) ? 'false' : 'true'), '">', $button['title'], '</span>
583
							</a>';
584
585
		// Any 2nd level menus?
586
		if (!empty($button['sub_buttons']))
587
		{
588
			echo '
589
							<ul class="menulevel2" role="menu">';
590
591
			foreach ($button['sub_buttons'] as $childact => $childbutton)
592
			{
593
				echo '
594
								<li id="button_', $childact, '" class="listlevel2', empty($childbutton['sub_buttons']) ? '"' : ' subsections"', ' role="none">
595
									<a class="linklevel2" href="', $childbutton['href'], '" ', isset($childbutton['target']) ? 'target="' . $childbutton['target'] . '"' : '', isset($childbutton['onclick']) ? ' onclick="' . $childbutton['onclick'] . '"' : '', empty($childbutton['sub_buttons']) ? '' : ' aria-haspopup="true"', ' role="menuitem">',
596
										$childbutton['title'], '
597
									</a>';
598
599
				// 3rd level menus :)
600
				if (!empty($childbutton['sub_buttons']))
601
				{
602
					echo '
603
									<ul class="menulevel3" role="menu">';
604
605
					foreach ($childbutton['sub_buttons'] as $grandchildact => $grandchildbutton)
606
					{
607
						echo '
608
										<li id="button_', $grandchildact, '" class="listlevel3" role="none">
609
											<a class="linklevel3" href="', $grandchildbutton['href'], '" ', isset($grandchildbutton['target']) ? 'target="' . $grandchildbutton['target'] . '"' : '', isset($grandchildbutton['onclick']) ? ' onclick="' . $grandchildbutton['onclick'] . '"' : '', ' role="menuitem">',
610
												$grandchildbutton['title'], '
611
											</a>
612
										</li>';
613
					}
614
615
					echo '
616
									</ul>';
617
				}
618
619
				echo '
620
								</li>';
621
			}
622
623
			echo '
624
							</ul>';
625
		}
626
627
		echo '
628
						</li>';
629
	}
630
631
	echo '
632
						
633
					</ul>';
634
635
	// If search is enabled, plop in the form
636
	if ($context['allow_search'])
637
	{
638
		template_search_form();
639
	}
640
641
	echo '	</div>
642
				</nav>';
643
644
	// Define the upper_section toggle in javascript.
645
	theme()->themeJs()->addInlineJavascript('
646
		var oMainHeaderToggle = new elk_Toggle({
647
			bToggleEnabled: true,
648
			bCurrentlyCollapsed: ' . (empty($context['minmax_preferences']['upshrink']) ? 'false' : 'true') . ',
649
			aSwappableContainers: [
650
				\'upper_section\',\'header\',\'top_header\'
651
			],
652
			aSwapClasses: [
653
				{
654
					sId: \'upshrink\',
655
					classExpanded: \'chevricon i-chevron-up icon-lg\',
656
					titleExpanded: ' . JavaScriptEscape($txt['upshrink_description']) . ',
657
					classCollapsed: \'chevricon i-chevron-down icon-lg\',
658
					titleCollapsed: ' . JavaScriptEscape($txt['upshrink_description']) . '
659
				},
660
			],
661
			oThemeOptions: {
662
				bUseThemeSettings: ' . ($context['user']['is_guest'] ? 'false' : 'true') . ',
663
				sOptionName: \'minmax_preferences\',
664
				sSessionId: elk_session_id,
665
				sSessionVar: elk_session_var,
666
				sAdditionalVars: \';minmax_key=upshrink\'
667
			},
668
			oCookieOptions: {
669
				bUseCookie: elk_member_id == 0 ? true : false,
670
				sCookieName: \'upshrink\'
671
			},
672
			funcOnBeforeCollapse: function () {
673
				let header = document.getElementById(\'top_section\');
674
				header.classList.add(\'th_collapse\');
675
				header.classList.remove(\'th_expand\');
676
			},
677
			funcOnBeforeExpand: function () {
678
				let header = document.getElementById(\'top_section\');
679
				header.classList.add(\'th_expand\');
680
				header.classList.remove(\'th_collapse\');
681
			},
682
		});
683
	', true);
684
}
685
686
/**
687
 * Very simple and basic template to display a legend explaining the meaning
688
 * of some icons used in the messages listing (locked, sticky, etc.)
689
 */
690
function template_basicicons_legend()
691
{
692
	global $context, $modSettings, $txt;
693
694
	echo '
695
		<p class="floatleft">', !empty($modSettings['enableParticipation']) && $context['user']['is_logged'] ? '
696
			<span class="topicicon i-profile"></span> ' . $txt['participation_caption'] : '<span class="topicicon img_normal"> </span>' . $txt['normal_topic'], '<br />
697
			' . (empty($modSettings['pollMode']) ? '' : '<span class="topicicon i-poll"> </span>' . $txt['poll']) . '
698
		</p>
699
		<p>
700
			<span class="topicicon i-locked"> </span>' . $txt['locked_topic'] . '<br />
701
			<span class="topicicon i-sticky"> </span>' . $txt['sticky_topic'] . '<br />
702
		</p>';
703
}
704
705
/**
706
 * Show a box with a message, mostly used to show errors, but can be used to show
707
 * success as well
708
 *
709
 * Looks for the display information in the $context[$error_id] array
710
 * Keys of array are 'type'
711
 *  - empty or success for successbox
712
 *  - serious for error box
713
 *  - warning for warning box
714
 * 'title' - optional value to place above list
715
 * 'errors' - array of text strings to display in the box
716
 *
717
 * @param string $error_id
718
 */
719
function template_show_error($error_id)
720
{
721
	global $context;
722
723
	if (empty($error_id))
724
	{
725
		return;
726
	}
727
728
	$error = $context[$error_id] ?? array();
729
730
	echo '
731
					<div id="', $error_id, '" class="', (isset($error['type']) ? ($error['type'] === 'serious' ? 'errorbox' : 'warningbox') : 'successbox'), empty($error['errors']) ? ' hide"' : '"', '>';
732
733
	// Optional title for our results
734
	if (!empty($error['title']))
735
	{
736
		echo '
737
						<dl>
738
							<dt>
739
								<strong id="', $error_id, '_title">', $error['title'], '</strong>
740
							</dt>
741
							<dd>';
742
	}
743
744
	// Everything that went wrong, or correctly :)
745
	if (!empty($error['errors']))
746
	{
747
		echo '
748
								<ul', (isset($error['type']) ? ' class="error"' : ''), ' id="', $error_id, '_list">';
749
750
		foreach ($error['errors'] as $key => $err)
751
		{
752
			echo '
753
									<li id="', $error_id, '_', $key, '">', $err, '</li>';
754
		}
755
756
		echo '
757
								</ul>';
758
	}
759
760
	// All done
761
	if (!empty($error['title']))
762
	{
763
		echo '
764
							</dd>
765
						</dl>';
766
	}
767
768
	echo '
769
					</div>';
770
}
771
772
/**
773
 * Is this used?
774
 */
775
function template_uc_generic_infobox()
776
{
777
	global $context;
778
779
	if (empty($context['generic_infobox']))
780
	{
781
		return;
782
	}
783
784
	foreach ($context['generic_infobox'] as $key)
785
	{
786
		template_show_error($key);
787
	}
788
}
789
790
/**
791
 * This is the news fader
792
 */
793
function template_news_fader()
794
{
795
	global $settings, $context;
796
797
	echo '
798
				<ul id="elkFadeScroller">
799
					<li>
800
						', $settings['enable_news'] == 2 ? implode('</li><li>', $context['news_lines']) : $context['random_news_line'], '
801
					</li>
802
				</ul>
803
				<script type="module">
804
					Elk_NewsFader("elkFadeScroller", {' .  (empty($settings['newsfader_time']) ? '' : 'iFadeDelay: ' . $settings['newsfader_time']) . '})
805
				</script>';
806
}
807
808
/**
809
 *
810
 * @TODO: These need to be moved somewhere appropriate >_>
811
 *
812
 * @param array $member
813
 * @param bool $link
814
 *
815
 * @return string
816
 */
817
function template_member_online($member, $link = true)
818
{
819
	global $context;
820
821
	return ((!empty($context['can_send_pm']) && $link) ? '<a href="' . $member['online']['href'] . '" title="' . $member['online']['text'] . '">' : '') .
822
		   '<i class="' . ($member['online']['is_online'] ? 'iconline' : 'icoffline') . '" title="' . $member['online']['text'] . '"></i>' .
823
		   ((!empty($context['can_send_pm']) && $link) ? '</a>' : '');
824
}
825
826
/**
827
 * Similar to the above. Wanted to centralize this to make it easier to pull out the emailuser action and replace with
828
 * a mailto: href, which many sane board admins would prefer.
829
 *
830
 * @param array $member
831
 * @param bool $text
832
 *
833
 * @return string
834
 */
835
function template_member_email($member, $text = false)
836
{
837
	global $context, $txt;
838
839
	if ($context['can_send_email'])
840
	{
841
		if ($text)
842
		{
843
			if ($member !== false && $member['show_email'])
844
			{
845
				return '<a class="linkbutton" href="mailto:' . $member['email'] . '" rel="nofollow">' . $txt['email'] . '</a>';
846
			}
847
848
			return $txt['hidden'];
849
		}
850
851
		if ($member !== false && $member['show_email'])
852
		{
853
			return '<a href="mailto:' . $member['email'] . '" rel="nofollow" class="icon i-envelope-o' . ($member['online']['is_online'] ? '' : '-blank') . '" title="' . $txt['email'] . ' ' . $member['name'] . '"><s>' . $txt['email'] . ' ' . $member['name'] . '</s></a>';
854
		}
855
856
		return '<i class="icon i-envelope-o" title="' . $txt['email'] . ' ' . $txt['hidden'] . '"><s>' . $txt['email'] . ' ' . $txt['hidden'] . '</s></i>';
857
	}
858
859
	return '';
860
}
861