Completed
Push — master ( 0543f8...4a05e9 )
by Lukas
21:56
created

OC_Helper   F

Complexity

Total Complexity 117

Size/Duplication

Total Lines 624
Duplicated Lines 3.85 %

Coupling/Cohesion

Components 3
Dependencies 18

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 117
c 2
b 0
f 0
lcom 3
cbo 18
dl 24
loc 624
rs 1.5031

22 Methods

Rating   Name   Duplication   Size   Complexity  
A linkToPublic() 0 8 4
C humanFileSize() 0 27 7
B phpFileSize() 0 18 5
B computerFileSize() 0 32 4
B copyr() 0 15 8
C rmdirr() 0 29 8
A getFileTemplateManager() 0 6 2
D canExecute() 0 35 9
C streamCopy() 0 25 8
A buildNotExistingFileName() 0 4 1
C buildNotExistingFileNameForView() 0 39 7
A isSubDirectory() 0 18 4
A mb_array_change_key_case() 0 8 3
B recursiveArraySearch() 0 14 6
A maxUploadFilesize() 0 6 3
A freeSpace() 6 9 3
B uploadLimit() 0 12 5
A is_function_enabled() 0 17 4
C findBinaryPath() 0 28 7
D getStorageInfo() 9 67 13
B getGlobalStorageInfo() 9 25 5
A isReadOnlyConfigEnabled() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like OC_Helper 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 OC_Helper, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Björn Schießle <[email protected]>
6
 * @author Christopher Schäpers <[email protected]>
7
 * @author Clark Tomlinson <[email protected]>
8
 * @author Fabian Henze <[email protected]>
9
 * @author Felix Moeller <[email protected]>
10
 * @author Georg Ehrke <[email protected]>
11
 * @author Jakob Sack <[email protected]>
12
 * @author Jan-Christoph Borchardt <[email protected]>
13
 * @author Joas Schilling <[email protected]>
14
 * @author Jörn Friedrich Dreyer <[email protected]>
15
 * @author Lukas Reschke <[email protected]>
16
 * @author Michael Gapczynski <[email protected]>
17
 * @author Morris Jobke <[email protected]>
18
 * @author Olivier Paroz <[email protected]>
19
 * @author Pellaeon Lin <[email protected]>
20
 * @author Robin Appelman <[email protected]>
21
 * @author Robin McCorkell <[email protected]>
22
 * @author Roeland Jago Douma <[email protected]>
23
 * @author Simon Könnecke <[email protected]>
24
 * @author Thomas Müller <[email protected]>
25
 * @author Thomas Tanghus <[email protected]>
26
 * @author Vincent Petry <[email protected]>
27
 *
28
 * @copyright Copyright (c) 2016, ownCloud, Inc.
29
 * @license AGPL-3.0
30
 *
31
 * This code is free software: you can redistribute it and/or modify
32
 * it under the terms of the GNU Affero General Public License, version 3,
33
 * as published by the Free Software Foundation.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
 * GNU Affero General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU Affero General Public License, version 3,
41
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
42
 *
43
 */
44
use Symfony\Component\Process\ExecutableFinder;
45
46
/**
47
 * Collection of useful functions
48
 */
49
class OC_Helper {
50
	private static $templateManager;
51
52
	/**
53
	 * Creates an absolute url for public use
54
	 * @param string $service id
55
	 * @param bool $add_slash
56
	 * @return string the url
57
	 *
58
	 * Returns a absolute url to the given service.
59
	 */
60
	public static function linkToPublic($service, $add_slash = false) {
61
		if ($service === 'files') {
62
			$url = OC::$server->getURLGenerator()->getAbsoluteURL('/s');
63
		} else {
64
			$url = OC::$server->getURLGenerator()->getAbsoluteURL(OC::$server->getURLGenerator()->linkTo('', 'public.php').'?service='.$service);
65
		}
66
		return $url . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : '');
67
	}
68
69
	/**
70
	 * Make a human file size
71
	 * @param int $bytes file size in bytes
72
	 * @return string a human readable file size
73
	 *
74
	 * Makes 2048 to 2 kB.
75
	 */
76
	public static function humanFileSize($bytes) {
77
		if ($bytes < 0) {
78
			return "?";
79
		}
80
		if ($bytes < 1024) {
81
			return "$bytes B";
82
		}
83
		$bytes = round($bytes / 1024, 0);
84
		if ($bytes < 1024) {
85
			return "$bytes KB";
86
		}
87
		$bytes = round($bytes / 1024, 1);
88
		if ($bytes < 1024) {
89
			return "$bytes MB";
90
		}
91
		$bytes = round($bytes / 1024, 1);
92
		if ($bytes < 1024) {
93
			return "$bytes GB";
94
		}
95
		$bytes = round($bytes / 1024, 1);
96
		if ($bytes < 1024) {
97
			return "$bytes TB";
98
		}
99
100
		$bytes = round($bytes / 1024, 1);
101
		return "$bytes PB";
102
	}
103
104
	/**
105
	 * Make a php file size
106
	 * @param int $bytes file size in bytes
107
	 * @return string a php parseable file size
108
	 *
109
	 * Makes 2048 to 2k and 2^41 to 2048G
110
	 */
111
	public static function phpFileSize($bytes) {
112
		if ($bytes < 0) {
113
			return "?";
114
		}
115
		if ($bytes < 1024) {
116
			return $bytes . "B";
117
		}
118
		$bytes = round($bytes / 1024, 1);
119
		if ($bytes < 1024) {
120
			return $bytes . "K";
121
		}
122
		$bytes = round($bytes / 1024, 1);
123
		if ($bytes < 1024) {
124
			return $bytes . "M";
125
		}
126
		$bytes = round($bytes / 1024, 1);
127
		return $bytes . "G";
128
	}
129
130
	/**
131
	 * Make a computer file size
132
	 * @param string $str file size in human readable format
133
	 * @return float a file size in bytes
134
	 *
135
	 * Makes 2kB to 2048.
136
	 *
137
	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
138
	 */
139
	public static function computerFileSize($str) {
140
		$str = strtolower($str);
141
		if (is_numeric($str)) {
142
			return floatval($str);
143
		}
144
145
		$bytes_array = array(
146
			'b' => 1,
147
			'k' => 1024,
148
			'kb' => 1024,
149
			'mb' => 1024 * 1024,
150
			'm' => 1024 * 1024,
151
			'gb' => 1024 * 1024 * 1024,
152
			'g' => 1024 * 1024 * 1024,
153
			'tb' => 1024 * 1024 * 1024 * 1024,
154
			't' => 1024 * 1024 * 1024 * 1024,
155
			'pb' => 1024 * 1024 * 1024 * 1024 * 1024,
156
			'p' => 1024 * 1024 * 1024 * 1024 * 1024,
157
		);
158
159
		$bytes = floatval($str);
160
161
		if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) {
162
			$bytes *= $bytes_array[$matches[1]];
163
		} else {
164
			return false;
165
		}
166
167
		$bytes = round($bytes);
168
169
		return $bytes;
170
	}
171
172
	/**
173
	 * Recursive copying of folders
174
	 * @param string $src source folder
175
	 * @param string $dest target folder
176
	 *
177
	 */
178
	static function copyr($src, $dest) {
179
		if (is_dir($src)) {
180
			if (!is_dir($dest)) {
181
				mkdir($dest);
182
			}
183
			$files = scandir($src);
184
			foreach ($files as $file) {
185
				if ($file != "." && $file != "..") {
186
					self::copyr("$src/$file", "$dest/$file");
187
				}
188
			}
189
		} elseif (file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) {
190
			copy($src, $dest);
191
		}
192
	}
193
194
	/**
195
	 * Recursive deletion of folders
196
	 * @param string $dir path to the folder
197
	 * @param bool $deleteSelf if set to false only the content of the folder will be deleted
198
	 * @return bool
199
	 */
200
	static function rmdirr($dir, $deleteSelf = true) {
201
		if (is_dir($dir)) {
202
			$files = new RecursiveIteratorIterator(
203
				new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
204
				RecursiveIteratorIterator::CHILD_FIRST
205
			);
206
207
			foreach ($files as $fileInfo) {
208
				/** @var SplFileInfo $fileInfo */
209
				if ($fileInfo->isDir()) {
210
					rmdir($fileInfo->getRealPath());
211
				} else {
212
					unlink($fileInfo->getRealPath());
213
				}
214
			}
215
			if ($deleteSelf) {
216
				rmdir($dir);
217
			}
218
		} elseif (file_exists($dir)) {
219
			if ($deleteSelf) {
220
				unlink($dir);
221
			}
222
		}
223
		if (!$deleteSelf) {
224
			return true;
225
		}
226
227
		return !file_exists($dir);
228
	}
229
230
	/**
231
	 * @return \OC\Files\Type\TemplateManager
232
	 */
233
	static public function getFileTemplateManager() {
234
		if (!self::$templateManager) {
235
			self::$templateManager = new \OC\Files\Type\TemplateManager();
236
		}
237
		return self::$templateManager;
238
	}
239
240
	/**
241
	 * detect if a given program is found in the search PATH
242
	 *
243
	 * @param string $name
244
	 * @param bool $path
245
	 * @internal param string $program name
246
	 * @internal param string $optional search path, defaults to $PATH
247
	 * @return bool    true if executable program found in path
248
	 */
249
	public static function canExecute($name, $path = false) {
250
		// path defaults to PATH from environment if not set
251
		if ($path === false) {
252
			$path = getenv("PATH");
253
		}
254
		// check method depends on operating system
255
		if (!strncmp(PHP_OS, "WIN", 3)) {
256
			// on Windows an appropriate COM or EXE file needs to exist
257
			$exts = array(".exe", ".com");
258
			$check_fn = "file_exists";
259
		} else {
260
			// anywhere else we look for an executable file of that name
261
			$exts = array("");
262
			$check_fn = "is_executable";
263
		}
264
		// Default check will be done with $path directories :
265
		$dirs = explode(PATH_SEPARATOR, $path);
266
		// WARNING : We have to check if open_basedir is enabled :
267
		$obd = OC::$server->getIniWrapper()->getString('open_basedir');
268
		if ($obd != "none") {
269
			$obd_values = explode(PATH_SEPARATOR, $obd);
270
			if (count($obd_values) > 0 and $obd_values[0]) {
271
				// open_basedir is in effect !
272
				// We need to check if the program is in one of these dirs :
273
				$dirs = $obd_values;
274
			}
275
		}
276
		foreach ($dirs as $dir) {
277
			foreach ($exts as $ext) {
278
				if ($check_fn("$dir/$name" . $ext))
279
					return true;
280
			}
281
		}
282
		return false;
283
	}
284
285
	/**
286
	 * copy the contents of one stream to another
287
	 *
288
	 * @param resource $source
289
	 * @param resource $target
290
	 * @return array the number of bytes copied and result
291
	 */
292
	public static function streamCopy($source, $target) {
293
		if (!$source or !$target) {
294
			return array(0, false);
295
		}
296
		$bufSize = 8192;
297
		$result = true;
298
		$count = 0;
299
		while (!feof($source)) {
300
			$buf = fread($source, $bufSize);
301
			$bytesWritten = fwrite($target, $buf);
302
			if ($bytesWritten !== false) {
303
				$count += $bytesWritten;
304
			}
305
			// note: strlen is expensive so only use it when necessary,
306
			// on the last block
307
			if ($bytesWritten === false
308
				|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
309
			) {
310
				// write error, could be disk full ?
311
				$result = false;
312
				break;
313
			}
314
		}
315
		return array($count, $result);
316
	}
317
318
	/**
319
	 * Adds a suffix to the name in case the file exists
320
	 *
321
	 * @param string $path
322
	 * @param string $filename
323
	 * @return string
324
	 */
325
	public static function buildNotExistingFileName($path, $filename) {
326
		$view = \OC\Files\Filesystem::getView();
327
		return self::buildNotExistingFileNameForView($path, $filename, $view);
328
	}
329
330
	/**
331
	 * Adds a suffix to the name in case the file exists
332
	 *
333
	 * @param string $path
334
	 * @param string $filename
335
	 * @return string
336
	 */
337
	public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
338
		if ($path === '/') {
339
			$path = '';
340
		}
341
		if ($pos = strrpos($filename, '.')) {
342
			$name = substr($filename, 0, $pos);
343
			$ext = substr($filename, $pos);
344
		} else {
345
			$name = $filename;
346
			$ext = '';
347
		}
348
349
		$newpath = $path . '/' . $filename;
350
		if ($view->file_exists($newpath)) {
351
			if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
352
				//Replace the last "(number)" with "(number+1)"
353
				$last_match = count($matches[0]) - 1;
354
				$counter = $matches[1][$last_match][0] + 1;
355
				$offset = $matches[0][$last_match][1];
356
				$match_length = strlen($matches[0][$last_match][0]);
357
			} else {
358
				$counter = 2;
359
				$match_length = 0;
360
				$offset = false;
361
			}
362
			do {
363
				if ($offset) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $offset 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...
364
					//Replace the last "(number)" with "(number+1)"
365
					$newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
366
				} else {
367
					$newname = $name . ' (' . $counter . ')';
368
				}
369
				$newpath = $path . '/' . $newname . $ext;
370
				$counter++;
371
			} while ($view->file_exists($newpath));
372
		}
373
374
		return $newpath;
375
	}
376
377
	/**
378
	 * Checks if $sub is a subdirectory of $parent
379
	 *
380
	 * @param string $sub
381
	 * @param string $parent
382
	 * @return bool
383
	 */
384
	public static function isSubDirectory($sub, $parent) {
385
		$realpathSub = realpath($sub);
386
		$realpathParent = realpath($parent);
387
388
		// realpath() may return false in case the directory does not exist
389
		// since we can not be sure how different PHP versions may behave here
390
		// we do an additional check whether realpath returned false
391
		if($realpathSub === false ||  $realpathParent === false) {
392
			return false;
393
		}
394
395
		// Check whether $sub is a subdirectory of $parent
396
		if (strpos($realpathSub, $realpathParent) === 0) {
397
			return true;
398
		}
399
400
		return false;
401
	}
402
403
	/**
404
	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
405
	 *
406
	 * @param array $input The array to work on
407
	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
408
	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
409
	 * @return array
410
	 *
411
	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
412
	 * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
413
	 *
414
	 */
415
	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
416
		$case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER;
417
		$ret = array();
418
		foreach ($input as $k => $v) {
419
			$ret[mb_convert_case($k, $case, $encoding)] = $v;
420
		}
421
		return $ret;
422
	}
423
424
	/**
425
	 * performs a search in a nested array
426
	 * @param array $haystack the array to be searched
427
	 * @param string $needle the search string
428
	 * @param string $index optional, only search this key name
429
	 * @return mixed the key of the matching field, otherwise false
430
	 *
431
	 * performs a search in a nested array
432
	 *
433
	 * taken from http://www.php.net/manual/en/function.array-search.php#97645
434
	 */
435
	public static function recursiveArraySearch($haystack, $needle, $index = null) {
436
		$aIt = new RecursiveArrayIterator($haystack);
437
		$it = new RecursiveIteratorIterator($aIt);
438
439
		while ($it->valid()) {
440
			if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
441
				return $aIt->key();
442
			}
443
444
			$it->next();
445
		}
446
447
		return false;
448
	}
449
450
	/**
451
	 * calculates the maximum upload size respecting system settings, free space and user quota
452
	 *
453
	 * @param string $dir the current folder where the user currently operates
454
	 * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
455
	 * @return int number of bytes representing
456
	 */
457
	public static function maxUploadFilesize($dir, $freeSpace = null) {
458
		if (is_null($freeSpace) || $freeSpace < 0){
459
			$freeSpace = self::freeSpace($dir);
460
		}
461
		return min($freeSpace, self::uploadLimit());
462
	}
463
464
	/**
465
	 * Calculate free space left within user quota
466
	 *
467
	 * @param string $dir the current folder where the user currently operates
468
	 * @return int number of bytes representing
469
	 */
470
	public static function freeSpace($dir) {
471
		$freeSpace = \OC\Files\Filesystem::free_space($dir);
472 View Code Duplication
		if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
473
			$freeSpace = max($freeSpace, 0);
474
			return $freeSpace;
475
		} else {
476
			return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
477
		}
478
	}
479
480
	/**
481
	 * Calculate PHP upload limit
482
	 *
483
	 * @return int PHP upload file size limit
484
	 */
485
	public static function uploadLimit() {
486
		$ini = \OC::$server->getIniWrapper();
487
		$upload_max_filesize = OCP\Util::computerFileSize($ini->get('upload_max_filesize'));
488
		$post_max_size = OCP\Util::computerFileSize($ini->get('post_max_size'));
489
		if ((int)$upload_max_filesize === 0 and (int)$post_max_size === 0) {
490
			return INF;
491
		} elseif ((int)$upload_max_filesize === 0 or (int)$post_max_size === 0) {
492
			return max($upload_max_filesize, $post_max_size); //only the non 0 value counts
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression max($upload_max_filesize, $post_max_size); of type double|false adds false to the return on line 492 which is incompatible with the return type documented by OC_Helper::uploadLimit of type integer. It seems like you forgot to handle an error condition.
Loading history...
493
		} else {
494
			return min($upload_max_filesize, $post_max_size);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression min($upload_max_filesize, $post_max_size); of type double|false adds false to the return on line 494 which is incompatible with the return type documented by OC_Helper::uploadLimit of type integer. It seems like you forgot to handle an error condition.
Loading history...
495
		}
496
	}
497
498
	/**
499
	 * Checks if a function is available
500
	 *
501
	 * @param string $function_name
502
	 * @return bool
503
	 */
504
	public static function is_function_enabled($function_name) {
505
		if (!function_exists($function_name)) {
506
			return false;
507
		}
508
		$ini = \OC::$server->getIniWrapper();
509
		$disabled = explode(',', $ini->get('disable_functions'));
510
		$disabled = array_map('trim', $disabled);
511
		if (in_array($function_name, $disabled)) {
512
			return false;
513
		}
514
		$disabled = explode(',', $ini->get('suhosin.executor.func.blacklist'));
515
		$disabled = array_map('trim', $disabled);
516
		if (in_array($function_name, $disabled)) {
517
			return false;
518
		}
519
		return true;
520
	}
521
522
	/**
523
	 * Try to find a program
524
	 * Note: currently windows is not supported
525
	 *
526
	 * @param string $program
527
	 * @return null|string
528
	 */
529
	public static function findBinaryPath($program) {
530
		$memcache = \OC::$server->getMemCacheFactory()->create('findBinaryPath');
531
		if ($memcache->hasKey($program)) {
532
			return $memcache->get($program);
533
		}
534
		$result = null;
535
		if (!\OC_Util::runningOnWindows() && self::is_function_enabled('exec')) {
536
			$exeSniffer = new ExecutableFinder();
537
			// Returns null if nothing is found
538
			$result = $exeSniffer->find($program);
539
			if (empty($result)) {
540
				$paths = getenv('PATH');
541
				if (empty($paths)) {
542
					$paths = '/usr/local/bin /usr/bin /opt/bin /bin';
543
				} else {
544
					$paths = str_replace(':',' ',getenv('PATH'));
545
				}
546
				$command = 'find ' . $paths . ' -name ' . escapeshellarg($program) . ' 2> /dev/null';
547
				exec($command, $output, $returnCode);
548
				if (count($output) > 0) {
549
					$result = escapeshellcmd($output[0]);
550
				}
551
			}
552
		}
553
		// store the value for 5 minutes
554
		$memcache->set($program, $result, 300);
555
		return $result;
556
	}
557
558
	/**
559
	 * Calculate the disc space for the given path
560
	 *
561
	 * @param string $path
562
	 * @param \OCP\Files\FileInfo $rootInfo (optional)
563
	 * @return array
564
	 * @throws \OCP\Files\NotFoundException
565
	 */
566
	public static function getStorageInfo($path, $rootInfo = null) {
567
		// return storage info without adding mount points
568
		$includeExtStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
569
570
		if (!$rootInfo) {
571
			$rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
572
		}
573
		if (!$rootInfo instanceof \OCP\Files\FileInfo) {
574
			throw new \OCP\Files\NotFoundException();
575
		}
576
		$used = $rootInfo->getSize();
577
		if ($used < 0) {
578
			$used = 0;
579
		}
580
		$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
581
		$storage = $rootInfo->getStorage();
582
		$sourceStorage = $storage;
583
		if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) {
584
			$includeExtStorage = false;
585
			$sourceStorage = $storage->getSourceStorage();
586
		}
587
		if ($includeExtStorage) {
588
			$quota = OC_Util::getUserQuota(\OCP\User::getUser());
589
			if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
590
				// always get free space / total space from root + mount points
591
				return self::getGlobalStorageInfo();
592
			}
593
		}
594
595
		// TODO: need a better way to get total space from storage
596
		if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
597
			/** @var \OC\Files\Storage\Wrapper\Quota $storage */
598
			$quota = $sourceStorage->getQuota();
599
		}
600
		$free = $sourceStorage->free_space('');
601
		if ($free >= 0) {
602
			$total = $free + $used;
603
		} else {
604
			$total = $free; //either unknown or unlimited
605
		}
606 View Code Duplication
		if ($total > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
607
			if ($quota > 0 && $total > $quota) {
608
				$total = $quota;
609
			}
610
			// prevent division by zero or error codes (negative values)
611
			$relative = round(($used / $total) * 10000) / 100;
612
		} else {
613
			$relative = 0;
614
		}
615
616
		$ownerId = $storage->getOwner($path);
617
		$ownerDisplayName = '';
618
		$owner = \OC::$server->getUserManager()->get($ownerId);
619
		if($owner) {
620
			$ownerDisplayName = $owner->getDisplayName();
621
		}
622
623
		return [
624
			'free' => $free,
625
			'used' => $used,
626
			'quota' => $quota,
627
			'total' => $total,
628
			'relative' => $relative,
629
			'owner' => $ownerId,
630
			'ownerDisplayName' => $ownerDisplayName,
631
		];
632
	}
633
634
	/**
635
	 * Get storage info including all mount points and quota
636
	 *
637
	 * @return array
638
	 */
639
	private static function getGlobalStorageInfo() {
640
		$quota = OC_Util::getUserQuota(\OCP\User::getUser());
641
642
		$rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
0 ignored issues
show
Documentation introduced by
'ext' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
643
		$used = $rootInfo['size'];
644
		if ($used < 0) {
645
			$used = 0;
646
		}
647
648
		$total = $quota;
649
		$free = $quota - $used;
650
651 View Code Duplication
		if ($total > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
652
			if ($quota > 0 && $total > $quota) {
653
				$total = $quota;
654
			}
655
			// prevent division by zero or error codes (negative values)
656
			$relative = round(($used / $total) * 10000) / 100;
657
		} else {
658
			$relative = 0;
659
		}
660
661
		return array('free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative);
662
663
	}
664
665
	/**
666
	 * Returns whether the config file is set manually to read-only
667
	 * @return bool
668
	 */
669
	public static function isReadOnlyConfigEnabled() {
670
		return \OC::$server->getConfig()->getSystemValue('config_is_read_only', false);
671
	}
672
}
673