Template   C
last analyzed

Complexity

Total Complexity 56

Size/Duplication

Total Lines 779
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 164
c 3
b 0
f 1
dl 0
loc 779
rs 5.5199
ccs 0
cts 609
cp 0
wmc 56

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A render() 0 39 6
A error() 0 27 5
A footer() 0 9 4
A setResponse() 0 3 1
A step2() 0 4 1
A xml() 0 4 2
A header() 0 268 6
A select_script() 0 63 5
A time_limit() 0 34 3
B renderForm() 0 94 11
A step3() 0 26 2
B status() 0 26 7
A step0() 0 21 1

How to fix   Complexity   

Complex Class

Complex classes like Template often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Template, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @name      OpenImporter
4
 * @copyright OpenImporter contributors
5
 * @license   BSD https://opensource.org/licenses/BSD-3-Clause
6
 *
7
 * @version 1.0
8
 */
9
10
namespace OpenImporter;
11
12
/**
13
 * Class Template
14
 * This is our UI
15
 *
16
 * @package OpenImporter
17
 */
18
class Template
19
{
20
	/** @var \OpenImporter\HttpResponse */
21
	protected $response;
22
23
	/** @var \OpenImporter\DummyLang */
24
	protected $language;
25
26
	/**
27
	 * Template constructor.
28
	 *
29
	 * @param $language
30
	 */
31
	public function __construct($language)
32
	{
33
		// If nothing is found, use a stub
34
		if ($language === null)
35
		{
36
			$language = new DummyLang();
37
		}
38
39
		$this->language = $language;
40
	}
41
42
	/**
43
	 * Display a specific error message.
44
	 *
45
	 * @param string $error_message
46
	 * @param int|bool $trace
47
	 * @param int|bool $line
48
	 * @param string|bool $file
49
	 */
50
	public function error($error_message, $trace = false, $line = false, $file = false)
51
	{
52
		echo '
53
			<div class="error_message">
54
				<div class="error_text">
55
					', !empty($trace) ? $this->language->get(array('error_message', $error_message)) : $error_message, '
56
				</div>';
57
58
		if (!empty($trace))
59
		{
60
			echo '
61
				<div class="error_text">', $this->language->get(array('error_trace', $trace)), '</div>';
62
		}
63
64
		if (!empty($line))
65
		{
66
			echo '
67
				<div class="error_text">', $this->language->get(array('error_line', $line)), '</div>';
68
		}
69
70
		if (!empty($file))
71
		{
72
			echo '
73
				<div class="error_text">', $this->language->get(array('error_file', $file)), '</div>';
74
		}
75
76
		echo '
77
			</div>';
78
	}
79
80
	/**
81
	 * Sets the response for the template to use
82
	 *
83
	 * @param \OpenImporter\HttpResponse $response
84
	 */
85
	public function setResponse($response)
86
	{
87
		$this->response = $response;
88
	}
89
90
	/**
91
	 * Renders the template
92
	 */
93
	public function render()
94
	{
95
		// No text? ... so sad. :(
96
		if ($this->response->no_template)
97
		{
98
			return;
99
		}
100
101
		// Set http headers as needed
102
		$this->response->sendHeaders();
103
104
		// XML ajax feedback? We can just skip everything else
105
		if ($this->response->is_xml)
106
		{
107
			$this->xml();
108
		}
109
		// Maybe showing a new page
110
		elseif ($this->response->is_page)
111
		{
112
			// Header
113
			$this->header(!$this->response->template_error);
114
115
			// Body
116
			if ($this->response->template_error)
117
			{
118
				foreach ($this->response->getErrors() as $msg)
119
				{
120
					$this->error($msg);
121
				}
122
			}
123
124
			call_user_func_array(array($this, $this->response->use_template), $this->response->params_template);
125
126
			// Footer
127
			$this->footer(!$this->response->template_error);
128
		}
129
		else
130
		{
131
			call_user_func_array(array($this, $this->response->use_template), $this->response->params_template);
132
		}
133
	}
134
135
	/**
136
	 * Show the footer.
137
	 *
138
	 * @param bool $inner
139
	 */
140
	public function footer($inner = true)
141
	{
142
		if (($this->response->step === 1 || $this->response->step === 2) && $inner === true)
143
		{
144
			echo '
145
				</p>
146
			</div>';
147
		}
148
		echo '
149
		</div>
150
	</body>
151
</html>';
152
	}
153
154
	/**
155
	 * Show the header.
156
	 *
157
	 * @param bool $inner
158
	 */
159
	public function header($inner = true)
160
	{
161
		echo '<!DOCTYPE html>
162
<html lang="', $this->language->get('locale'), '">
163
	<head>
164
		<meta charset="UTF-8" />
165
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
166
		<title>', $this->response->page_title, '</title>
167
		<script>
168
			function AJAXCall(url, callback, string)
169
			{
170
				let req = new XMLHttpRequest();
171
172
				req.onreadystatechange = processRequest;
173
174
				function processRequest()
175
				{
176
					// ReadyState of 4 signifies request is complete
177
					if (req.readyState === 4)
178
					{
179
						// Status of 200 signifies successful HTTP call
180
						if (req.status === 200)
181
							if (callback) callback(req.responseXML, string);
182
					}
183
				}
184
185
				// Make an HTTP GET request to the URL asynchronously
186
				this.doGet = function () {
187
					req.open("GET", url, true);
188
					req.send(null);
189
				};
190
			}
191
192
			function validateField(string)
193
			{
194
				let target = document.getElementById(string),
195
					url = "import.php?action=validate&xml=true&" + string + "=" + target.value.replace(/\/+$/g, "") + "&import_script=' . addslashes($this->response->script) . '",
196
					ajax = new AJAXCall(url, validateCallback, string);
197
198
				ajax.doGet();
199
			}
200
201
			function validateCallback(responseXML, string)
202
			{
203
				let msg = responseXML.getElementsByTagName("valid")[0].firstChild.nodeValue,
204
					field = document.getElementById(string),
205
					validate = document.getElementById(\'validate_\' + string),
206
					submitBtn = document.getElementById("submit_button");
207
208
				if (msg === "false")
209
				{
210
					field.className = "invalid_field";
211
					validate.innerHTML = "' . $this->language->get('invalid') . '";
212
213
					// Set the style on the div to invalid
214
					submitBtn.disabled = true;
215
				}
216
				else
217
				{
218
					field.className = "valid_field";
219
					validate.innerHTML = "' . $this->language->get('validated') . '";
220
221
					submitBtn.disabled = false;
222
				}
223
			}
224
225
			window.onload = function() {
226
				validateField(\'path_to\');
227
				validateField(\'path_from\');
228
			}
229
		</script>
230
		<style>
231
			body {
232
				background-color: #cbd9e7;
233
				margin: 0;
234
				padding: 0;
235
			}
236
			body, td {
237
				color: #000;
238
				font-size: 14px;
239
				font-family: arial;
240
			}
241
			a {
242
				color: #2a4259;
243
				text-decoration: none;
244
				border-bottom: 1px dashed #789;
245
			}
246
			#header {
247
				background-color: #809ab3;
248
				padding: 22px 4% 12px 4%;
249
				color: #fff;
250
				text-shadow: 0 0 8px #333;
251
				border-bottom: 1px solid #fff;
252
				height: 40px;
253
			}
254
			#main {
255
				padding: 20px 30px;
256
				background-color: #fff;
257
				border-radius: 5px;
258
				margin: 7px;
259
				border: 1px solid #abadb3;
260
			}
261
			#path_from, #path_to {
262
				width: 480px;
263
			}
264
			.error_message, blockquote, .error {
265
				border: 1px dashed red;
266
				border-radius: 5px;
267
				background-color: #fee;
268
				padding: 1.5ex;
269
			}
270
			.error_text {
271
				color: red;
272
			}
273
			.content {
274
				border-radius: 3px;
275
				background-color: #eee;
276
				color: #444;
277
				margin: 1ex 0;
278
				padding: 1.2ex;
279
				border: 1px solid #abadb3;
280
				border-radius: 4px;
281
				box-shadow: 0.3px 0.5px 0.7px rgba(158,158,158,.38), 0.4px 0.8px 1px -1.2px rgba(158,158,158,.38), 1px 2px 2.5px -2.5px rgba(158,158,158,.38);
282
			}
283
			.button {
284
				margin: 0 0.8em 0.8em 0.8em;
285
			}
286
			#submit_button {
287
				cursor: pointer;
288
			}
289
			h1 {
290
				margin: 0;
291
				padding: 0;
292
				font-size: 2.5em;
293
			}
294
			h2 {
295
				font-size: 1.5em;
296
				color: #809ab3;
297
				font-weight: bold;
298
			}
299
			form {
300
				margin: 0;
301
			}
302
			.textbox {
303
				padding-top: 2px;
304
				white-space: nowrap;
305
				padding-right: 1ex;
306
			}
307
			.bp_invalid {
308
				color:red;
309
				font-weight: bold;
310
			}
311
			.bp_valid {
312
				color:green;
313
			}
314
			.validate {
315
				font-style: italic;
316
				font-size: smaller;
317
			}
318
			.valid_field, .content .valid_field, input.valid_field {
319
				background-color: #DEFEDD !important;
320
				border: 1px solid green;
321
			}
322
			.invalid_field, .content .invalid_field {
323
				background-color: #fee !important;
324
				border: 1px solid red;
325
			}
326
			#progressbar {
327
				position: relative;
328
				top: -28px;
329
				left: 255px;
330
			}
331
			progress {
332
				width: 300px;
333
			}
334
			#advanced_options {
335
  				columns: 2;
336
  				margin-left: 20%;
337
			}
338
			#advanced_options dt {
339
				break-after: avoid;
340
				width: 50%;
341
				float: none;
342
			}
343
			#advanced_options dd {
344
				break-before: avoid;
345
				float: none;
346
			}
347
			dl {
348
				clear: right;
349
				overflow: auto;
350
				margin: 0 0 0 0;
351
				padding: 0;
352
			}
353
			dt {
354
				width: 20%;
355
				float: left;
356
				margin: 6px 5px 10px 0;
357
				padding: 0;
358
				clear: both;
359
			}
360
			dd {
361
				width: 78%;
362
				float: right;
363
				margin: 6px 0 3px 0;
364
				padding: 0;
365
			}
366
			#arrow_up {
367
				display: none;
368
			}
369
			#toggle_button {
370
				display: block;
371
				color: #2a4259;
372
				margin-bottom: 4px;
373
				cursor: pointer;
374
			}
375
			.arrow {
376
				font-size: 10px;
377
			}
378
			#destinations ul, #source {
379
				padding: 0 1em;
380
			}
381
			#destinations ul li a {
382
				display: block;
383
				margin-bottom: 3px;
384
				padding-bottom: 3px;
385
				border-bottom: medium none;
386
				line-height: 4em;
387
			}
388
			#destinations ul li, #source li {
389
				cursor: pointer;
390
				float: left;
391
				list-style: none;
392
				padding: 0.5em;
393
				margin: 0 0.5em;
394
				border: 1px solid #abadb3;
395
				border-radius: 3px;
396
			}
397
			#destinations ul li {
398
				width: 20%;
399
				float: none;
400
				display: inline-block;
401
				height: 4em;
402
				cursor: default;
403
				vertical-align: middle;
404
				margin-top: 1em;
405
			}
406
			#destinations ul li.active, #source li.active {
407
				background-color: #fff;
408
			}
409
			#destinations ul:after, #source:after {
410
				content: "";
411
				display: block;
412
				clear: both;
413
			}
414
		</style>
415
	</head>
416
	<body>
417
		<div id="header">
418
			<h1>', isset($this->response->importer->xml->general->{'name'}) ? $this->response->importer->xml->general->{'name'} . ' to ' : '', 'OpenImporter</h1>
0 ignored issues
show
Bug Best Practice introduced by
The property importer does not exist on OpenImporter\HttpResponse. Since you implemented __get, consider adding a @property annotation.
Loading history...
419
		</div>
420
		<div id="main">';
421
422
		if (!empty($_GET['step'])
423
			&& ((int) $_GET['step'] === 1 || (int) $_GET['step'] === 2) && $inner === true)
424
		{
425
			echo '
426
			<h2 style="margin-top: 2ex">', $this->language->get('importing'), '...</h2>
427
			<div class="content"><p>';
428
		}
429
	}
430
431
	/**
432
	 * This is the template part for selecting the importer script.
433
	 *
434
	 * @param array $scripts The available "From" forums
435
	 * @param string[] $destination_names The available "To" forums
436
	 */
437
	public function select_script($scripts, $destination_names)
438
	{
439
		echo '
440
			<h2>', $this->language->get('to_what'), '</h2>
441
			<div class="content">
442
				<p><label for="source">', $this->language->get('locate_source'), '</label></p>
443
				<ul id="source">';
444
445
		// Who can we import into?
446
		foreach ($destination_names as $key => $values)
447
		{
448
			echo '
449
					<li onclick="toggle_to(this);" data-value="', preg_replace('~[^\w]~', '_', $key), '">', $values, '</li>';
450
		}
451
452
		echo '
453
				</ul>
454
			</div>';
455
456
		echo '
457
			<h2>', $this->language->get('which_software'), '</h2>
458
			<div id="destinations" class="content">';
459
460
		// We found at least one?
461
		if (!empty($scripts))
462
		{
463
			echo '
464
				<p>', $this->language->get('multiple_files'), '</p>';
465
466
			foreach ($scripts as $key => $value)
467
			{
468
				echo '
469
				<ul id="', preg_replace('~[^\w]~', '_', $key), '">';
470
471
				// Let's loop and output all the found scripts.
472
				foreach ($value as $script)
473
				{
474
					echo '
475
					<li>
476
						<a href="', $_SERVER['PHP_SELF'], '?import_script=', $script['path'], '">', $script['name'], '</a>
477
					</li>';
478
				}
479
480
				echo '
481
				</ul>';
482
			}
483
484
			echo '
485
			</div>
486
			<h2>', $this->language->get('not_here'), '</h2>
487
			<div class="content">
488
				<p>', $this->language->get('check_more'), '</p>
489
				<p>', $this->language->get('having_problems'), '</p>';
490
		}
491
		else
492
		{
493
			echo '
494
				<p>', $this->language->get('not_found'), '</p>
495
				<p>', $this->language->get('not_found_download'), '</p>
496
				<a href="', $_SERVER['PHP_SELF'], '?import_script=">', $this->language->get('try_again'), '</a>';
497
		}
498
499
		echo '
500
			<script>
501
				function toggle_to(e)
502
				{
503
					let dest_container = document.getElementById(\'destinations\'),
504
						dests = dest_container.getElementsByTagName(\'ul\'),
505
						sources = document.getElementById(\'source\').getElementsByTagName(\'li\'),
506
						i;
507
508
					for (i = 0; i < dests.length; i++)
509
						dests[i].style.display = \'none\';
510
511
					if (typeof e === \'undefined\')
512
						e = sources[0];
513
514
					for (i = 0; i < sources.length; i++)
515
						sources[i].removeAttribute("class");
516
517
					e.setAttribute("class", "active");
518
					document.getElementById(e.getAttribute(\'data-value\')).style.display = \'block\';
519
				}
520
521
				toggle_to();
522
			</script>
523
			</div>';
524
	}
525
526
	/**
527
	 * Everyone has to start somewhere, we start and 0,0,0,0
528
	 *
529
	 * Called from doStep0 from the ImportManager
530
	 *
531
	 * @param \OpenImporter\ImportManager $object
532
	 * @param \OpenImporter\Form $form
533
	 */
534
	public function step0($object, $form)
535
	{
536
		echo '
537
			<h2>', $this->language->get('before_continue'), '</h2>
538
			<div class="content">
539
				<p>', sprintf($this->language->get('before_details'), (string) $object->importer->xml->general->name), '</p>
540
			</div>';
541
542
		$form->title = $this->language->get('where');
543
		$form->description = $this->language->get('locate_destination');
544
		$form->submit = array(
545
			'name' => 'submit_button',
546
			'value' => $this->language->get('continue'),
547
		);
548
549
		$this->renderForm($form);
550
551
		echo '
552
			<h2>', $this->language->get('not_this'), '</h2>
553
			<div class="content">
554
				<p>', sprintf($this->language->get('pick_different'), $_SERVER['PHP_SELF']), '</p>
555
			</div>';
556
	}
557
558
	/**
559
	 * Display notification with the given status
560
	 *
561
	 * @param int $substep
562
	 * @param int $status
563
	 * @param string $title
564
	 * @param bool $hide = false
565
	 */
566
	public function status($substep, $status, $title, $hide = false)
567
	{
568
		$status = (int) $status;
569
		if (isset($title) && $hide === false)
570
		{
571
			echo '<span style="width: 250px; display: inline-block">' . $title . '...</span> ';
572
		}
573
574
		if ($status === 1)
575
		{
576
			echo '<span style="color: green">&#x2714</span>';
577
		}
578
579
		if ($status === 2)
580
		{
581
			echo '<span style="color: grey">&#x2714</span> (', $this->language->get('skipped'), ')';
582
		}
583
584
		if ($status === 3)
585
		{
586
			echo '<span style="color: red">&#x2718</span> (', $this->language->get('not_found_skipped'), ')';
587
		}
588
589
		if ($status !== 0)
590
		{
591
			echo '<br />';
592
		}
593
	}
594
595
	/**
596
	 * Display information related to step2
597
	 */
598
	public function step2()
599
	{
600
		echo '
601
				<span style="width: 250px; display: inline-block">', $this->language->get('recalculate'), '...</span> ';
602
	}
603
604
	/**
605
	 * Display last step UI, completion status and allow eventually
606
	 * to delete the scripts
607
	 *
608
	 * @param string $name
609
	 * @param string $boardurl
610
	 * @param bool $writable if the files are writable, the UI will allow deletion
611
	 */
612
	public function step3($name, $boardurl, $writable)
613
	{
614
		echo '
615
			</div>
616
			<h2 style="margin-top: 2ex">', $this->language->get('complete'), '</h2>
617
			<div class="content">
618
			<p>', $this->language->get('congrats'), '</p>';
619
620
		if ($writable)
621
		{
622
			echo '
623
				<div style="margin: 1ex; font-weight: bold">
624
					<label for="delete_self"><input type="checkbox" id="delete_self" onclick="doTheDelete()" />', $this->language->get('check_box'), '</label>
625
				</div>
626
				<script>
627
					function doTheDelete()
628
					{
629
						new Image().src = "', $_SERVER['PHP_SELF'], '?delete=1&" + (+Date());
630
						(document.getElementById ? document.getElementById("delete_self") : document.all.delete_self).disabled = true;
631
					}
632
				</script>';
633
		}
634
635
		echo '
636
				<p>', sprintf($this->language->get('all_imported'), $name), '</p>
637
				<p>', $this->language->get('smooth_transition'), '</p>';
638
	}
639
640
	/**
641
	 * Display the progress bar,
642
	 * and inform the user about when the script is paused and re-run.
643
	 *
644
	 * @param int $bar
645
	 * @param int $value
646
	 * @param int $max
647
	 */
648
	public function time_limit($bar, $value, $max)
649
	{
650
		if (!empty($bar))
651
		{
652
			echo '
653
			<div id="progressbar">
654
				<progress value="', $bar, '" max="100">', $bar, '%</progress>
655
			</div>';
656
		}
657
658
		echo '
659
		</div>
660
		<h2 style="margin-top: 2ex">', $this->language->get('not_done'), '</h2>
661
		<div class="content">
662
			<div style="margin-bottom: 15px; margin-top: 10px;"><span style="width: 250px; display: inline-block">', $this->language->get('overall_progress'), '</span><progress value="', $value, '" max="', $max, '"></progress></div>
663
			<p>', $this->language->get('importer_paused'), '</p>
664
665
			<form action="', $_SERVER['PHP_SELF'], '?step=', $_GET['step'], isset($_GET['substep']) ? '&amp;substep=' . $_GET['substep'] : '', '&amp;start=', $_REQUEST['start'], '" method="post" name="autoSubmit">
666
				<div align="right" style="margin: 1ex"><input name="b" type="submit" value="', $this->language->get('continue'), '" /></div>
667
			</form>
668
669
			<script>
670
				let countdown = 3;
671
				
672
				window.onload = doAutoSubmit;
673
674
				function doAutoSubmit()
675
				{
676
					if (countdown === 0)
677
						document.autoSubmit.submit();
678
					else if (countdown === -1)
679
						return;
680
681
					document.autoSubmit.b.value = "', $this->language->get('continue'), ' (" + countdown + ")";
682
					countdown--;
683
684
					setTimeout("doAutoSubmit();", 1000);
685
				}
686
			</script>';
687
	}
688
689
	/**
690
	 * Ajax's response. Whether the paths to the source and destination
691
	 * software are correctly set.
692
	 */
693
	public function xml()
694
	{
695
		echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
696
	<valid>', $this->response->valid ? 'true' : 'false', '</valid>';
697
	}
698
699
	/**
700
	 * Function to generate a form from a set of form options
701
	 * @param $form
702
	 */
703
	public function renderForm($form)
704
	{
705
		$toggle = false;
706
707
		echo '
708
			<h2>', $form->title, '</h2>
709
			<div class="content">
710
				<form action="', $form->action_url, '" method="post">
711
					<p>', $form->description, '</p>
712
					<dl>';
713
714
		foreach ($form->options as $option)
715
		{
716
			if (empty($option))
717
			{
718
				$toggle = true;
719
				echo '
720
					</dl>
721
					<div id="toggle_button">', $this->language->get('advanced_options'), ' <span id="arrow_down" class="arrow">&#9660</span><span id="arrow_up" class="arrow">&#9650</span></div>
722
					<dl id="advanced_options" style="display: none; margin-top: 5px">';
723
				continue;
724
			}
725
726
			switch ($option['type'])
727
			{
728
				case 'text':
729
				{
730
					echo '
731
						<dt>
732
							<label for="', $option['id'], '">', $option['label'], ':</label>
733
						</dt>
734
						<dd>
735
							<input type="text" name="', $option['id'], '" id="', $option['id'], '" value="', $option['value'], '" ', !empty($option['validate']) ? 'onblur="validateField(\'' . $option['id'] . '\')"' : '', ' class="text" />
736
							<div id="validate_', $option['id'], '" class="validate">', $option['correct'], '</div>
737
						</dd>';
738
					break;
739
				}
740
				case 'checkbox':
741
				{
742
					echo '
743
						<dt></dt>
744
						<dd>
745
							<label for="', $option['id'], '">', $option['label'], ':
746
								<input type="checkbox" name="', $option['id'], '" id="', $option['id'], '" value="', $option['value'], '" ', $option['attributes'], '/>
747
							</label>
748
						</dd>';
749
					break;
750
				}
751
				case 'password':
752
				{
753
					echo '
754
						<dt>
755
							<label for="', $option['id'], '">', $option['label'], ':</label>
756
						</dt>
757
						<dd>
758
							<input type="password" name="', $option['id'], '" id="', $option['id'], '" class="text" />
759
							<div style="font-style: italic; font-size: smaller">', $option['correct'], '</div>
760
						</dd>';
761
					break;
762
				}
763
				case 'steps':
764
				{
765
					echo '
766
						<dt>
767
							<label for="', $option['id'], '">', $option['label'], ':</label>
768
						</dt>
769
						<dd>';
770
771
					foreach ($option['value'] as $key => $step)
772
					{
773
						echo '
774
							<label>
775
								<input type="checkbox" name="do_steps[', $key, ']" id="do_steps[', $key, ']" value="', $step['count'], '"', $step['mandatory'] ? 'readonly="readonly" ' : ' ', $step['checked'], '" /> ', $step['label'], '
776
							</label><br />';
777
					}
778
779
					echo '
780
						</dd>';
781
					break;
782
				}
783
			}
784
		}
785
786
		echo '
787
					</dl>
788
					<div class="button">
789
						<input id="submit_button" name="', $form->submit['name'], '" type="submit" value="', $form->submit['value'], '" class="submit" />
790
					</div>
791
				</form>
792
			</div>';
793
794
		if ($toggle)
795
		{
796
			echo '
797
			<script>
798
				document.getElementById(\'toggle_button\').onclick = function ()
799
				{
800
					let elem = document.getElementById(\'advanced_options\'),
801
						arrow_up = document.getElementById(\'arrow_up\'),
802
						arrow_down = document.getElementById(\'arrow_down\');
803
804
					if (!elem)
805
						return true;
806
807
					if (elem.style.display === \'none\')
808
					{
809
						elem.style.display = \'block\';
810
						arrow_down.style.display = \'none\';
811
						arrow_up.style.display = \'inline\';
812
					}
813
					else
814
					{
815
						elem.style.display = \'none\';
816
						arrow_down.style.display = \'inline\';
817
						arrow_up.style.display = \'none\';
818
					}
819
820
					return true;
821
				}
822
			</script>';
823
		}
824
	}
825
}
826