Completed
Push — master ( ab3599...a9f481 )
by Roeland
12:13
created

URLGenerator::imagePath()   F

Complexity

Conditions 33
Paths 253

Size

Total Lines 67

Duplication

Lines 16
Ratio 23.88 %

Importance

Changes 0
Metric Value
cc 33
nc 253
nop 2
dl 16
loc 67
rs 2.6708
c 0
b 0
f 0

How to fix   Long Method    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
declare(strict_types=1);
3
/**
4
 * @copyright Copyright (c) 2016, ownCloud, Inc.
5
 *
6
 * @author Bart Visscher <[email protected]>
7
 * @author Felix Epp <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Julius Haertl <[email protected]>
10
 * @author Julius Härtl <[email protected]>
11
 * @author Jörn Friedrich Dreyer <[email protected]>
12
 * @author Lukas Reschke <[email protected]>
13
 * @author mmccarn <[email protected]>
14
 * @author Morris Jobke <[email protected]>
15
 * @author Robin Appelman <[email protected]>
16
 * @author Robin McCorkell <[email protected]>
17
 * @author Thomas Müller <[email protected]>
18
 * @author Thomas Tanghus <[email protected]>
19
 *
20
 * @license AGPL-3.0
21
 *
22
 * This code is free software: you can redistribute it and/or modify
23
 * it under the terms of the GNU Affero General Public License, version 3,
24
 * as published by the Free Software Foundation.
25
 *
26
 * This program is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
 * GNU Affero General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU Affero General Public License, version 3,
32
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
33
 *
34
 */
35
36
namespace OC;
37
38
use OCA\Theming\ThemingDefaults;
39
use OCP\ICacheFactory;
40
use OCP\IConfig;
41
use OCP\IRequest;
42
use OCP\IURLGenerator;
43
use RuntimeException;
44
45
/**
46
 * Class to generate URLs
47
 */
48
class URLGenerator implements IURLGenerator {
49
	/** @var IConfig */
50
	private $config;
51
	/** @var ICacheFactory */
52
	private $cacheFactory;
53
	/** @var IRequest */
54
	private $request;
55
56
	/**
57
	 * @param IConfig $config
58
	 * @param ICacheFactory $cacheFactory
59
	 * @param IRequest $request
60
	 */
61
	public function __construct(IConfig $config,
62
								ICacheFactory $cacheFactory,
63
								IRequest $request) {
64
		$this->config = $config;
65
		$this->cacheFactory = $cacheFactory;
66
		$this->request = $request;
67
	}
68
69
	/**
70
	 * Creates an url using a defined route
71
	 * @param string $route
72
	 * @param array $parameters args with param=>value, will be appended to the returned url
73
	 * @return string the url
74
	 *
75
	 * Returns a url to the given route.
76
	 */
77
	public function linkToRoute(string $route, array $parameters = array()): string {
78
		// TODO: mock router
79
		return \OC::$server->getRouter()->generate($route, $parameters);
80
	}
81
82
	/**
83
	 * Creates an absolute url using a defined route
84
	 * @param string $routeName
85
	 * @param array $arguments args with param=>value, will be appended to the returned url
86
	 * @return string the url
87
	 *
88
	 * Returns an absolute url to the given route.
89
	 */
90
	public function linkToRouteAbsolute(string $routeName, array $arguments = array()): string {
91
		return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
92
	}
93
94
	public function linkToOCSRouteAbsolute(string $routeName, array $arguments = []): string {
95
		$route = \OC::$server->getRouter()->generate('ocs.'.$routeName, $arguments, false);
96
97
		if (strpos($route, '/index.php') === 0) {
98
			$route = substr($route, 10);
99
		}
100
101
		$route = substr($route, 7);
102
		$route = '/ocs/v2.php' . $route;
103
104
		return $this->getAbsoluteURL($route);
105
	}
106
107
	/**
108
	 * Creates an url
109
	 * @param string $app app
110
	 * @param string $file file
111
	 * @param array $args array with param=>value, will be appended to the returned url
112
	 *    The value of $args will be urlencoded
113
	 * @return string the url
114
	 *
115
	 * Returns a url to the given app and file.
116
	 */
117
	public function linkTo(string $app, string $file, array $args = array()): string {
118
		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
119
120
		if( $app !== '' ) {
121
			$app_path = \OC_App::getAppPath($app);
122
			// Check if the app is in the app folder
123
			if ($app_path && file_exists($app_path . '/' . $file)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $app_path of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
124
				if (substr($file, -3) === 'php') {
125
126
					$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
127
					if ($frontControllerActive) {
128
						$urlLinkTo = \OC::$WEBROOT . '/apps/' . $app;
129
					}
130
					$urlLinkTo .= ($file !== 'index.php') ? '/' . $file : '';
131
				} else {
132
					$urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file;
133
				}
134
			} else {
135
				$urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file;
136
			}
137
		} else {
138
			if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) {
139
				$urlLinkTo = \OC::$WEBROOT . '/core/' . $file;
140
			} else {
141
				if ($frontControllerActive && $file === 'index.php') {
142
					$urlLinkTo = \OC::$WEBROOT . '/';
143
				} else {
144
					$urlLinkTo = \OC::$WEBROOT . '/' . $file;
145
				}
146
			}
147
		}
148
149
		if ($args && $query = http_build_query($args, '', '&')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $args of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
150
			$urlLinkTo .= '?' . $query;
151
		}
152
153
		return $urlLinkTo;
154
	}
155
156
	/**
157
	 * Creates path to an image
158
	 * @param string $app app
159
	 * @param string $image image name
160
	 * @throws \RuntimeException If the image does not exist
161
	 * @return string the url
162
	 *
163
	 * Returns the path to the image.
164
	 */
165
	public function imagePath(string $app, string $image): string {
166
		$cache = $this->cacheFactory->createDistributed('imagePath-'.md5($this->getBaseUrl()).'-');
167
		$cacheKey = $app.'-'.$image;
168
		if($key = $cache->get($cacheKey)) {
169
			return $key;
170
		}
171
172
		// Read the selected theme from the config file
173
		$theme = \OC_Util::getTheme();
174
175
		//if a theme has a png but not an svg always use the png
176
		$basename = substr(basename($image),0,-4);
177
178
		$appPath = \OC_App::getAppPath($app);
179
180
		// Check if the app is in the app folder
181
		$path = '';
182
		$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
183
		$themingImagePath = false;
184
		if($themingEnabled) {
185
			$themingDefaults = \OC::$server->getThemingDefaults();
186
			if ($themingDefaults instanceof ThemingDefaults) {
187
				$themingImagePath = $themingDefaults->replaceImagePath($app, $image);
188
			}
189
		}
190
191
		if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
192
			$path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
193
		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
194
			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) {
195
			$path =  \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png";
196
		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) {
197
			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$image";
198 View Code Duplication
		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg")
199
			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) {
200
			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png";
201
		} elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) {
202
			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$image";
203 View Code Duplication
		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
204
			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
205
			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
206
		} elseif($themingEnabled && $themingImagePath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $themingImagePath of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
207
			$path = $themingImagePath;
208
		} elseif ($appPath && file_exists($appPath . "/img/$image")) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $appPath of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
209
			$path =  \OC_App::getAppWebPath($app) . "/img/$image";
210
		} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
0 ignored issues
show
Bug Best Practice introduced by
The expression $appPath of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
211
			&& file_exists($appPath . "/img/$basename.png")) {
212
			$path =  \OC_App::getAppWebPath($app) . "/img/$basename.png";
213
		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) {
214
			$path =  \OC::$WEBROOT . "/$app/img/$image";
215 View Code Duplication
		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg")
216
				&& file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) {
217
			$path =  \OC::$WEBROOT . "/$app/img/$basename.png";
218
		} elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) {
219
			$path =  \OC::$WEBROOT . "/core/img/$image";
220 View Code Duplication
		} elseif (!file_exists(\OC::$SERVERROOT . "/core/img/$basename.svg")
221
			&& file_exists(\OC::$SERVERROOT . "/core/img/$basename.png")) {
222
			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
223
		}
224
225
		if($path !== '') {
226
			$cache->set($cacheKey, $path);
227
			return $path;
228
		}
229
230
		throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT);
231
	}
232
233
234
	/**
235
	 * Makes an URL absolute
236
	 * @param string $url the url in the ownCloud host
237
	 * @return string the absolute version of the url
238
	 */
239
	public function getAbsoluteURL(string $url): string {
240
		$separator = $url[0] === '/' ? '' : '/';
241
242
		if (\OC::$CLI && !\defined('PHPUNIT_RUN')) {
243
			return rtrim($this->config->getSystemValue('overwrite.cli.url'), '/') . '/' . ltrim($url, '/');
244
		}
245
		// The ownCloud web root can already be prepended.
246
		if(substr($url, 0, \strlen(\OC::$WEBROOT)) === \OC::$WEBROOT) {
247
			$url = substr($url, \strlen(\OC::$WEBROOT));
248
		}
249
250
		return $this->getBaseUrl() . $separator . $url;
251
	}
252
253
	/**
254
	 * @param string $key
255
	 * @return string url to the online documentation
256
	 */
257
	public function linkToDocs(string $key): string {
258
		$theme = \OC::$server->getThemingDefaults();
259
		return $theme->buildDocLinkToKey($key);
260
	}
261
262
	/**
263
	 * @return string base url of the current request
264
	 */
265
	public function getBaseUrl(): string {
266
		return $this->request->getServerProtocol() . '://' . $this->request->getServerHost() . \OC::$WEBROOT;
267
	}
268
}
269