Completed
Push — master ( 68735c...ea470f )
by Björn
11:25
created

OC_Template::isAssetPipelineEnabled()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 37
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 8
nop 0
dl 0
loc 37
rs 6.7272
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Adam Williamson <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Björn Schießle <[email protected]>
6
 * @author Brice Maron <[email protected]>
7
 * @author Frank Karlitschek <[email protected]>
8
 * @author Hendrik Leppelsack <[email protected]>
9
 * @author Individual IT Services <[email protected]>
10
 * @author Jakob Sack <[email protected]>
11
 * @author Jan-Christoph Borchardt <[email protected]>
12
 * @author Joas Schilling <[email protected]>
13
 * @author Jörn Friedrich Dreyer <[email protected]>
14
 * @author Lukas Reschke <[email protected]>
15
 * @author Morris Jobke <[email protected]>
16
 * @author Raghu Nayyar <[email protected]>
17
 * @author Robin Appelman <[email protected]>
18
 * @author Roeland Jago Douma <[email protected]>
19
 * @author Thomas Müller <[email protected]>
20
 * @author Vincent Petry <[email protected]>
21
 *
22
 * @copyright Copyright (c) 2016, ownCloud, Inc.
23
 * @license AGPL-3.0
24
 *
25
 * This code is free software: you can redistribute it and/or modify
26
 * it under the terms of the GNU Affero General Public License, version 3,
27
 * as published by the Free Software Foundation.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
 * GNU Affero General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU Affero General Public License, version 3,
35
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
36
 *
37
 */
38
39
use OC\TemplateLayout;
40
41
require_once __DIR__.'/template/functions.php';
42
43
/**
44
 * This class provides the templates for ownCloud.
45
 */
46
class OC_Template extends \OC\Template\Base {
47
48
	/** @var string */
49
	private $renderAs; // Create a full page?
50
51
	/** @var string */
52
	private $path; // The path to the template
53
54
	/** @var array */
55
	private $headers = array(); //custom headers
56
57
	/** @var string */
58
	protected $app; // app id
59
60
	protected static $initTemplateEngineFirstRun = true;
61
62
	/**
63
	 * Constructor
64
	 *
65
	 * @param string $app app providing the template
66
	 * @param string $name of the template file (without suffix)
67
	 * @param string $renderAs If $renderAs is set, OC_Template will try to
68
	 *                         produce a full page in the according layout. For
69
	 *                         now, $renderAs can be set to "guest", "user" or
70
	 *                         "admin".
71
	 * @param bool $registerCall = true
72
	 */
73
	public function __construct( $app, $name, $renderAs = "", $registerCall = true ) {
74
		// Read the selected theme from the config file
75
		self::initTemplateEngine($renderAs);
76
77
		$theme = OC_Util::getTheme();
78
79
		$requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : '';
80
81
		$parts = explode('/', $app); // fix translation when app is something like core/lostpassword
82
		$l10n = \OC::$server->getL10N($parts[0]);
83
		$themeDefaults = \OC::$server->getThemingDefaults();
84
85
		list($path, $template) = $this->findTemplate($theme, $app, $name);
86
87
		// Set the private data
88
		$this->renderAs = $renderAs;
89
		$this->path = $path;
90
		$this->app = $app;
91
92
		parent::__construct($template, $requestToken, $l10n, $themeDefaults);
93
	}
94
95
	/**
96
	 * @param string $renderAs
97
	 */
98
	public static function initTemplateEngine($renderAs) {
99
		if (self::$initTemplateEngineFirstRun){
100
101
			//apps that started before the template initialization can load their own scripts/styles
102
			//so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true
103
			//meaning the last script/style in this list will be loaded first
104
			if (\OC::$server->getSystemConfig()->getValue ('installed', false) && $renderAs !== 'error' && !\OCP\Util::needUpgrade()) {
105
				if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') {
106
					OC_Util::addScript ( 'backgroundjobs', null, true );
107
				}
108
			}
109
110
			OC_Util::addStyle("tooltip",null,true);
111
			OC_Util::addStyle('jquery-ui-fixes',null,true);
112
			OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true);
113
			OC_Util::addStyle("mobile",null,true);
114
			OC_Util::addStyle("multiselect",null,true);
115
			OC_Util::addStyle("fixes",null,true);
116
			OC_Util::addStyle("global",null,true);
117
			OC_Util::addStyle("apps",null,true);
118
			OC_Util::addStyle("fonts",null,true);
119
			OC_Util::addStyle("icons",null,true);
120
			OC_Util::addStyle("header",null,true);
121
			OC_Util::addStyle("inputs",null,true);
122
			OC_Util::addStyle("styles",null,true);
123
124
			// avatars
125
			if (\OC::$server->getSystemConfig()->getValue('enable_avatars', true) === true) {
126
				\OC_Util::addScript('jquery.avatar', null, true);
127
				\OC_Util::addScript('placeholder', null, true);
128
			}
129
130
			OC_Util::addScript('oc-backbone', null, true);
131
			OC_Util::addVendorScript('core', 'backbone/backbone', true);
132
			OC_Util::addVendorScript('snapjs/dist/latest/snap', null, true);
133
			OC_Util::addScript('mimetypelist', null, true);
134
			OC_Util::addScript('mimetype', null, true);
135
			OC_Util::addScript("apps", null, true);
136
			OC_Util::addScript("oc-requesttoken", null, true);
137
			OC_Util::addScript('search', 'search', true);
138
			OC_Util::addScript("config", null, true);
139
			OC_Util::addScript("eventsource", null, true);
140
			OC_Util::addScript("octemplate", null, true);
141
			OC_Util::addTranslations("core", null, true);
142
			OC_Util::addScript("l10n", null, true);
143
			OC_Util::addScript("js", null, true);
144
			OC_Util::addScript("oc-dialogs", null, true);
145
			OC_Util::addScript("jquery.ocdialog", null, true);
146
			OC_Util::addStyle("jquery.ocdialog");
147
			OC_Util::addScript("compatibility", null, true);
148
			OC_Util::addScript("placeholders", null, true);
149
			OC_Util::addScript('files/fileinfo');
150
			OC_Util::addScript('files/client');
151
152
			// Add the stuff we need always
153
			// following logic will import all vendor libraries that are
154
			// specified in core/js/core.json
155
			$fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json');
156
			if($fileContent !== false) {
157
				$coreDependencies = json_decode($fileContent, true);
158
				foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) {
159
					// remove trailing ".js" as addVendorScript will append it
160
					OC_Util::addVendorScript(
161
							substr($vendorLibrary, 0, strlen($vendorLibrary) - 3),null,true);
162
				}
163
			} else {
164
				throw new \Exception('Cannot read core/js/core.json');
165
			}
166
167
			if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE])) {
168
				// polyfill for btoa/atob for IE friends
169
				OC_Util::addVendorScript('base64/base64');
170
				// shim for the davclient.js library
171
				\OCP\Util::addScript('files/iedavclient');
172
			}
173
174
			self::$initTemplateEngineFirstRun = false;
175
		}
176
177
	}
178
179
180
	/**
181
	 * find the template with the given name
182
	 * @param string $name of the template file (without suffix)
183
	 *
184
	 * Will select the template file for the selected theme.
185
	 * Checking all the possible locations.
186
	 * @param string $theme
187
	 * @param string $app
188
	 * @return string[]
189
	 */
190
	protected function findTemplate($theme, $app, $name) {
191
		// Check if it is a app template or not.
192
		if( $app !== '' ) {
193
			$dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app));
194
		} else {
195
			$dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT);
196
		}
197
		$locator = new \OC\Template\TemplateFileLocator( $dirs );
198
		$template = $locator->find($name);
199
		$path = $locator->getPath();
200
		return array($path, $template);
201
	}
202
203
	/**
204
	 * Add a custom element to the header
205
	 * @param string $tag tag name of the element
206
	 * @param array $attributes array of attributes for the element
207
	 * @param string $text the text content for the element. If $text is null then the
208
	 * element will be written as empty element. So use "" to get a closing tag.
209
	 */
210 View Code Duplication
	public function addHeader($tag, $attributes, $text=null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
211
		$this->headers[]= array(
212
			'tag' => $tag,
213
			'attributes' => $attributes,
214
			'text' => $text
215
		);
216
	}
217
218
	/**
219
	 * Process the template
220
	 * @return boolean|string
221
	 *
222
	 * This function process the template. If $this->renderAs is set, it
223
	 * will produce a full page.
224
	 */
225
	public function fetchPage($additionalParams = null) {
226
		$data = parent::fetchPage($additionalParams);
227
228
		if( $this->renderAs ) {
229
			$page = new TemplateLayout($this->renderAs, $this->app);
230
231
			// Add custom headers
232
			$headers = '';
233
			foreach(OC_Util::$headers as $header) {
234
				$headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']);
235
				foreach($header['attributes'] as $name=>$value) {
236
					$headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"';
237
				}
238
				if ($header['text'] !== null) {
239
					$headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>';
240
				} else {
241
					$headers .= '/>';
242
				}
243
			}
244
245
			$page->assign('headers', $headers);
246
247
			$page->assign('content', $data);
248
			return $page->fetchPage();
0 ignored issues
show
Bug Compatibility introduced by
The expression $page->fetchPage(); of type boolean|string adds the type boolean to the return on line 248 which is incompatible with the return type of the parent method OC\Template\Base::fetchPage of type string.
Loading history...
249
		}
250
251
		return $data;
252
	}
253
254
	/**
255
	 * Include template
256
	 *
257
	 * @param string $file
258
	 * @param array|null $additionalParams
259
	 * @return string returns content of included template
260
	 *
261
	 * Includes another template. use <?php echo $this->inc('template'); ?> to
262
	 * do this.
263
	 */
264
	public function inc( $file, $additionalParams = null ) {
265
		return $this->load($this->path.$file.'.php', $additionalParams);
266
	}
267
268
	/**
269
	 * Shortcut to print a simple page for users
270
	 * @param string $application The application we render the template for
271
	 * @param string $name Name of the template
272
	 * @param array $parameters Parameters for the template
273
	 * @return boolean|null
274
	 */
275 View Code Duplication
	public static function printUserPage( $application, $name, $parameters = array() ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
		$content = new OC_Template( $application, $name, "user" );
277
		foreach( $parameters as $key => $value ) {
278
			$content->assign( $key, $value );
279
		}
280
		print $content->printPage();
281
	}
282
283
	/**
284
	 * Shortcut to print a simple page for admins
285
	 * @param string $application The application we render the template for
286
	 * @param string $name Name of the template
287
	 * @param array $parameters Parameters for the template
288
	 * @return bool
289
	 */
290 View Code Duplication
	public static function printAdminPage( $application, $name, $parameters = array() ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
291
		$content = new OC_Template( $application, $name, "admin" );
292
		foreach( $parameters as $key => $value ) {
293
			$content->assign( $key, $value );
294
		}
295
		return $content->printPage();
296
	}
297
298
	/**
299
	 * Shortcut to print a simple page for guests
300
	 * @param string $application The application we render the template for
301
	 * @param string $name Name of the template
302
	 * @param array|string $parameters Parameters for the template
303
	 * @return bool
304
	 */
305 View Code Duplication
	public static function printGuestPage( $application, $name, $parameters = array() ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
306
		$content = new OC_Template( $application, $name, "guest" );
307
		foreach( $parameters as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $parameters of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
308
			$content->assign( $key, $value );
309
		}
310
		return $content->printPage();
311
	}
312
313
	/**
314
		* Print a fatal error page and terminates the script
315
		* @param string $error_msg The error message to show
316
		* @param string $hint An optional hint message - needs to be properly escaped
317
		*/
318
	public static function printErrorPage( $error_msg, $hint = '' ) {
319
		if ($error_msg === $hint) {
320
			// If the hint is the same as the message there is no need to display it twice.
321
			$hint = '';
322
		}
323
324
		try {
325
			$content = new \OC_Template( '', 'error', 'error', false );
326
			$errors = array(array('error' => $error_msg, 'hint' => $hint));
327
			$content->assign( 'errors', $errors );
328
			$content->printPage();
329
		} catch (\Exception $e) {
330
			$logger = \OC::$server->getLogger();
331
			$logger->error("$error_msg $hint", ['app' => 'core']);
332
			$logger->logException($e, ['app' => 'core']);
333
334
			header(self::getHttpProtocol() . ' 500 Internal Server Error');
335
			header('Content-Type: text/plain; charset=utf-8');
336
			print("$error_msg $hint");
337
		}
338
		die();
339
	}
340
341
	/**
342
	 * print error page using Exception details
343
	 * @param Exception | Throwable $exception
344
	 */
345
	public static function printExceptionErrorPage($exception, $fetchPage = false) {
346
		try {
347
			$request = \OC::$server->getRequest();
348
			$content = new \OC_Template('', 'exception', 'error', false);
349
			$content->assign('errorClass', get_class($exception));
350
			$content->assign('errorMsg', $exception->getMessage());
351
			$content->assign('errorCode', $exception->getCode());
352
			$content->assign('file', $exception->getFile());
353
			$content->assign('line', $exception->getLine());
354
			$content->assign('trace', $exception->getTraceAsString());
355
			$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
356
			$content->assign('remoteAddr', $request->getRemoteAddress());
357
			$content->assign('requestID', $request->getId());
358
			if ($fetchPage) {
359
				return $content->fetchPage();
360
			}
361
			$content->printPage();
362
		} catch (\Exception $e) {
363
			$logger = \OC::$server->getLogger();
364
			$logger->logException($exception, ['app' => 'core']);
365
			$logger->logException($e, ['app' => 'core']);
366
367
			header(self::getHttpProtocol() . ' 500 Internal Server Error');
368
			header('Content-Type: text/plain; charset=utf-8');
369
			print("Internal Server Error\n\n");
370
			print("The server encountered an internal error and was unable to complete your request.\n");
371
			print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
372
			print("More details can be found in the server log.\n");
373
		}
374
		die();
375
	}
376
377
	/**
378
	 * This is only here to reduce the dependencies in case of an exception to
379
	 * still be able to print a plain error message.
380
	 *
381
	 * Returns the used HTTP protocol.
382
	 *
383
	 * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
384
	 * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead
385
	 */
386 View Code Duplication
	protected static function getHttpProtocol() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
387
		$claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
388
		$validProtocols = [
389
			'HTTP/1.0',
390
			'HTTP/1.1',
391
			'HTTP/2',
392
		];
393
		if(in_array($claimedProtocol, $validProtocols, true)) {
394
			return $claimedProtocol;
395
		}
396
		return 'HTTP/1.1';
397
	}
398
}
399