Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — master ( 2b39bd...8870e8 )
by Dan
12:21
created

Template::checkDisableAJAX()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
class Template {
4
	private $data = array();
5
	private $ignoreMiddle = false;
6
	private $nestedIncludes = 0;
7
	private $ajaxJS = array();
8
	protected $jsAlerts = array();
9
	private $displayCalled = false;
10
	private $listjsInclude = null;
11
	private $jsSources = [];
12
13
	public function __destruct() {
14
		if (!$this->displayCalled && !empty($this->data)) {
15
			error_log('Template destroyed before displaying the following assigned keys: ' . join(', ', array_keys($this->data)));
16
		}
17
	}
18
19
	public function hasTemplateVar($var) {
20
		return isset($this->data[$var]);
21
	}
22
	
23
	public function assign($var, $value) {
24
		if (!isset($this->data[$var])) {
25
			$this->data[$var] = $value;
26
		} else {
27
			// We insist that template variables not change once they are set
28
			throw new Exception("Cannot re-assign template variable '$var'!");
29
		}
30
	}
31
	
32
	public function unassign($var) {
33
		unset($this->data[$var]);
34
	}
35
36
	/**
37
	 * Displays the template HTML. Stores any ajax-enabled elements for future
38
	 * comparison, and outputs modified elements in XML for ajax if requested.
39
	 */
40
	public function display($templateName, $outputXml = false) {
41
		// If we already started output buffering before calling `display`,
42
		// we may have unwanted content in the buffer that we need to remove
43
		// before we send the Content-Type headers below.
44
		// Skip this for debug builds to help discover offending output.
45
		if (!ENABLE_DEBUG) {
46
			if (ob_get_length() > 0) {
47
				ob_clean();
48
			}
49
		}
50
		ob_start();
51
		$this->includeTemplate($templateName);
52
		$output = ob_get_clean();
53
		$this->trimWhiteSpace($output);
54
55
		$ajaxEnabled = ($this->data['AJAX_ENABLE_REFRESH'] ?? false) !== false;
56
		if ($ajaxEnabled) {
57
			$ajaxXml = $this->convertHtmlToAjaxXml($output, $outputXml);
58
			if ($outputXml) {
59
				/* Left out for size: <?xml version="1.0" encoding="ISO-8859-1"?>*/
60
				$output = '<all>' . $ajaxXml . '</all>';
61
			}
62
			SmrSession::saveAjaxReturns();
63
		}
64
65
		// Now that we are completely done processing, we can output
66
		if ($outputXml) {
67
			header('Content-Type: text/xml; charset=utf-8');
68
		} else {
69
			header('Content-Type: text/html; charset=utf-8');
70
		}
71
		echo $output;
72
73
		// Record that display was called for error-checking in dtor
74
		$this->displayCalled = true;
75
	}
76
	
77
	
78
	protected function getTemplateLocation($templateName) {
79
		$templateDir = TEMPLATES_DIR;
80
		if (isset($this->data['ThisAccount']) && is_object($this->data['ThisAccount']) && $this->data['ThisAccount'] instanceof SmrAccount) {
81
			$templateDir .= $this->data['ThisAccount']->getTemplate() . '/';
82
		} else {
83
			$templateDir .= 'Default/';
84
		}
85
86
		if (SmrSession::hasGame()) {
87
			$gameDir = Globals::getGameType(SmrSession::getGameID()) . '/';
88
		} else {
89
			$gameDir = 'Default/';
90
		}
91
92
		if (file_exists($templateDir . 'engine/' . $gameDir . $templateName)) {
93
			return $templateDir . 'engine/' . $gameDir . $templateName;
94
		} elseif (file_exists($templateDir . 'engine/Default/' . $templateName)) {
95
			return $templateDir . 'engine/Default/' . $templateName;
96
		} elseif (file_exists(TEMPLATES_DIR . 'Default/engine/' . $gameDir . $templateName)) {
97
			return TEMPLATES_DIR . 'Default/engine/' . $gameDir . $templateName;
98
		} elseif (file_exists(TEMPLATES_DIR . 'Default/engine/Default/' . $templateName)) {
99
			return TEMPLATES_DIR . 'Default/engine/Default/' . $templateName;
100
		} elseif (file_exists($templateDir . 'admin/' . $gameDir . $templateName)) {
101
			return $templateDir . 'admin/' . $gameDir . $templateName;
102
		} elseif (file_exists($templateDir . 'admin/Default/' . $templateName)) {
103
			return $templateDir . 'admin/Default/' . $templateName;
104
		} elseif (file_exists(TEMPLATES_DIR . 'Default/admin/' . $gameDir . $templateName)) {
105
			return TEMPLATES_DIR . 'Default/admin/' . $gameDir . $templateName;
106
		} elseif (file_exists(TEMPLATES_DIR . 'Default/admin/Default/' . $templateName)) {
107
			return TEMPLATES_DIR . 'Default/admin/Default/' . $templateName;
108
		} elseif (file_exists($templateDir . $templateName)) {
109
			return $templateDir . $templateName;
110
		} elseif (file_exists(TEMPLATES_DIR . 'Default/' . $templateName)) {
111
			return TEMPLATES_DIR . 'Default/' . $templateName;
112
		} else {
113
			throw new Exception('No template found for ' . $templateName);
114
		}
115
	}
116
	
117
	protected function includeTemplate($templateName, array $assignVars = null) {
118
		if ($this->nestedIncludes > 15) {
119
			throw new Exception('Nested more than 15 template includes, is something wrong?');
120
		}
121
		foreach ($this->data as $key => $value) {
122
			$$key = $value;
123
		}
124
		if ($assignVars !== null) {
125
			foreach ($assignVars as $key => $value) {
126
				$$key = $value;
127
			}
128
		}
129
		$this->nestedIncludes++;
130
		require($this->getTemplateLocation($templateName));
131
		$this->nestedIncludes--;
132
	}
133
	
134
	protected function checkDisableAJAX($html) {
135
		return preg_match('/<input' . '[^>]*' . '[^(submit)(hidden)(image)]' . '[^>]*' . '>/i', $html) != 0;
136
	}
137
	
138
	protected function trimWhiteSpace(&$html) {
139
		// Pull out the script blocks
140
		/*	preg_match_all("!<script[^>]*?>.*?</script>!is", $source, $match);
141
		 $_script_blocks = $match[0];
142
		 $source = preg_replace("!<script[^>]*?>.*?</script>!is",
143
		 '@@@SMARTY:TRIM:SCRIPT@@@', $source);
144
		 */
145
		// Pull out the pre blocks
146
		preg_match_all("!<pre[^>]*?>.*?</pre>!is", $html, $match);
147
		$_pre_blocks = $match[0];
148
		$html = preg_replace("!<pre[^>]*?>.*?</pre>!is",
149
			'@@@SMARTY:TRIM:PRE@@@', $html);
150
		
151
		// Pull out the textarea blocks
152
		preg_match_all("!<textarea[^>]*?>.*?</textarea>!is", $html, $match);
153
		$_textarea_blocks = $match[0];
154
		$html = preg_replace("!<textarea[^>]*?>.*?</textarea>!is",
155
			'@@@SMARTY:TRIM:TEXTAREA@@@', $html);
156
		
157
		// remove all leading spaces, tabs and carriage returns NOT
158
		// preceeded by a php close tag.
159
		$html = preg_replace('/[\s]+/', ' ', $html);
160
		
161
		// Pull out the span> <span blocks
162
		preg_match_all("!</span> <span!is", $html, $match);
163
		$_span_blocks = $match[0];
164
		$html = preg_replace("!</span> <span!is",
165
			'@@@SMARTY:TRIM:SPAN@@@', $html);
166
		
167
		$html = trim(preg_replace('/> </', '><', $html));
168
		
169
		// replace span blocks
170
		$this->replaceTrimHolder("@@@SMARTY:TRIM:SPAN@@@", $_span_blocks, $html);
171
		
172
		// replace textarea blocks
173
		$this->replaceTrimHolder("@@@SMARTY:TRIM:TEXTAREA@@@", $_textarea_blocks, $html);
174
		
175
		// replace pre blocks
176
		$this->replaceTrimHolder("@@@SMARTY:TRIM:PRE@@@", $_pre_blocks, $html);
177
		
178
		// replace script blocks
179
//		$this->replaceTrimHolder("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $html);
180
	}
181
	protected function replaceTrimHolder($search_str, $replace, &$subject) {
182
		$_len = strlen($search_str);
183
		$_pos = 0;
184
		for ($_i = 0, $_count = count($replace); $_i < $_count; $_i++) {
185
			if (($_pos = strpos($subject, $search_str, $_pos)) !== false) {
186
				$subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
187
			} else {
188
				break;
189
			}
190
		}
191
	}
192
	
193
	protected function doDamageTypeReductionDisplay(&$damageTypes) {
194
		if ($damageTypes == 3) {
195
			echo ', ';
196
		} elseif ($damageTypes == 2) {
197
			echo ' and ';
198
		}
199
		$damageTypes--;
200
	}
201
202
	protected function doAn($wordAfter) {
203
		$char = strtoupper($wordAfter[0]);
204
		if ($char == 'A' || $char == 'E' || $char == 'I' || $char == 'O' || $char == 'U') {
205
			echo 'an';
206
		} else {
207
			echo 'a';
208
		}
209
	}
210
211
	/**
212
	 * Sets a listjs_include.js function to call at the end of the HTML body.
213
	 */
214
	public function setListjsInclude($func) {
215
		$this->listjsInclude = $func;
216
	}
217
218
	/*
219
	 * EVAL is special (well, will be when needed and implemented in the javascript).
220
	 */
221
	public function addJavascriptForAjax($varName, $obj) {
222
		if ($varName == 'EVAL') {
223
			if (!isset($this->ajaxJS['EVAL'])) {
224
				return $this->ajaxJS['EVAL'] = $obj;
225
			}
226
			return $this->ajaxJS['EVAL'] .= ';' . $obj;
227
		}
228
		
229
		if (isset($this->ajaxJS[$varName])) {
230
			throw new Exception('Trying to set javascript val twice: ' . $varName);
231
		}
232
		return $this->ajaxJS[$varName] = json_encode($obj);
233
	}
234
	
235
	protected function addJavascriptAlert($string) {
236
		if (!SmrSession::addAjaxReturns('ALERT:' . $string, $string)) {
237
			$this->jsAlerts[] = $string;
238
		}
239
	}
240
241
	/**
242
	 * Registers a JS target for inclusion at the end of the HTML body.
243
	 */
244
	protected function addJavascriptSource($src) {
245
		array_push($this->jsSources, $src);
246
	}
247
248
	protected function convertHtmlToAjaxXml($str, $returnXml) {
249
		if (empty($str)) {
250
			return '';
251
		}
252
253
		// To get inner html, we need to construct a separate DOMDocument.
254
		// See PHP Bug #76285.
255
		$getInnerHTML = function(DOMNode $node) {
256
			$dom = new DOMDocument();
257
			$dom->formatOutput = false;
258
			foreach ($node->childNodes as $child) {
259
				$dom->appendChild($dom->importNode($child, true));
260
			}
261
			// Trim to remove trailing newlines
262
			return trim(@$dom->saveHTML());
263
		};
264
265
		$xml = '';
266
		$dom = new DOMDocument();
267
		$dom->loadHTML($str);
268
		$xpath = new DOMXpath($dom);
269
		$ajaxSelectors = array('//span[@id]', '//*[contains(@class,"ajax")]');
270
		foreach ($ajaxSelectors as $selector) {
271
			$matchNodes = $xpath->query($selector);
272
			foreach ($matchNodes as $node) {
273
				$id = $node->getAttribute('id');
274
				$inner = $getInnerHTML($node);
275
				if (!SmrSession::addAjaxReturns($id, $inner) && $returnXml) {
276
					$xml .= '<' . $id . '>' . xmlify($inner) . '</' . $id . '>';
277
				}
278
			}
279
		}
280
281
		if (!$this->ignoreMiddle) {
282
			$mid = $dom->getElementById('middle_panel');
283
284
			$doAjaxMiddle = true;
285
			if ($mid === null) {
286
				// Skip if there is no middle_panel.
287
				$doAjaxMiddle = false;
288
			} else {
289
				// Skip if middle_panel has ajax-enabled children.
290
				$domMid = new DOMDocument();
291
				$domMid->appendChild($domMid->importNode($mid, true));
292
				$xpathMid = new DOMXpath($domMid);
293
				foreach ($ajaxSelectors as $selector) {
294
					if (count($xpathMid->query($selector)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $xpathMid->query($selector) can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, 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

294
					if (count(/** @scrutinizer ignore-type */ $xpathMid->query($selector)) > 0) {
Loading history...
295
						$doAjaxMiddle = false;
296
						break;
297
					}
298
				}
299
			}
300
301
			if ($doAjaxMiddle) {
302
				$inner = $getInnerHTML($mid);
303
				if (!$this->checkDisableAJAX($inner)) {
304
					$id = $mid->getAttribute('id');
305
					if (!SmrSession::addAjaxReturns($id, $inner) && $returnXml) {
306
						$xml .= '<' . $id . '>' . xmlify($inner) . '</' . $id . '>';
307
					}
308
				}
309
			}
310
		}
311
312
		$js = '';
313
		foreach ($this->ajaxJS as $varName => $JSON) {
314
			if (!SmrSession::addAjaxReturns('JS:' . $varName, $JSON) && $returnXml) {
315
				$js .= '<' . $varName . '>' . xmlify($JSON) . '</' . $varName . '>';
316
			}
317
		}
318
		if ($returnXml && count($this->jsAlerts) > 0) {
319
			$js = '<ALERT>' . json_encode($this->jsAlerts) . '</ALERT>';
320
		}
321
		if (strlen($js) > 0) {
322
			$xml .= '<JS>' . $js . '</JS>';
323
		}
324
		return $xml;
325
	}
326
	
327
	public function ignoreMiddle() {
328
		$this->ignoreMiddle = true;
329
	}
330
}
331