Passed
Push — feature/playlist_improvements ( 2a396d )
by Pauli
14:09
created

Util::relativePath()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 8
nc 4
nop 2
dl 0
loc 16
rs 9.6111
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2018 - 2020
11
 */
12
13
namespace OCA\Music\Utility;
14
15
/**
16
 * Miscellaneous static utility functions
17
 */
18
class Util {
19
20
	/**
21
	 * Extract ID of each array element by calling getId and return
22
	 * the IDs as an array
23
	 * @param array $arr
24
	 * @return array
25
	 */
26
	public static function extractIds(array $arr) {
27
		return \array_map(function ($i) {
28
			return $i->getId();
29
		}, $arr);
30
	}
31
32
	/**
33
	 * Extract User ID of each array element by calling getUserId and return
34
	 * the IDs as an array
35
	 * @param array $arr
36
	 * @return array
37
	 */
38
	public static function extractUserIds(array $arr) {
39
		return \array_map(function ($i) {
40
			return $i->getUserId();
41
		}, $arr);
42
	}
43
44
	/**
45
	 * Create look-up table from given array of items which have a `getId` function.
46
	 * @param array $array
47
	 * @return array where keys are the values returned by `getId` of each item
48
	 */
49
	public static function createIdLookupTable(array $array) {
50
		$lut = [];
51
		foreach ($array as $item) {
52
			$lut[$item->getId()] = $item;
53
		}
54
		return $lut;
55
	}
56
57
	/**
58
	 * Get difference of two arrays, i.e. elements belonging to $b but not $a.
59
	 * This function is faster than the built-in array_diff for large arrays but
60
	 * at the expense of higher RAM usage and can be used only for arrays of
61
	 * integers or strings.
62
	 * From https://stackoverflow.com/a/8827033
63
	 * @param array $b
64
	 * @param array $a
65
	 * @return array
66
	 */
67
	public static function arrayDiff(array $b, array $a) {
68
		$at = \array_flip($a);
69
		$d = [];
70
		foreach ($b as $i) {
71
			if (!isset($at[$i])) {
72
				$d[] = $i;
73
			}
74
		}
75
		return $d;
76
	}
77
78
	/**
79
	 * Get multiple items from @a $array, as indicated by a second array @a $indices.
80
	 * @param array $array
81
	 * @param array $indices
82
	 * @return array
83
	 */
84
	public static function arrayMultiGet(array $array, array $indices) {
85
		$result = [];
86
		foreach ($indices as $index) {
87
			$result[] = $array[$index];
88
		}
89
		return $result;
90
	}
91
92
	/**
93
	 * Convert the given array $arr so that keys of the potentially multi-dimensional array
94
	 * are converted using the mapping given in $dictionary. Keys not found from $dictionary
95
	 * are not altered. 
96
	 * @param array $arr
97
	 * @param array $dictionary
98
	 * @return array
99
	 */
100
	public static function convertArrayKeys(array $arr, array $dictionary) {
101
		$newArr = [];
102
103
		foreach ($arr as $k => $v) {
104
			$key = self::arrayGetOrDefault($dictionary, $k, $k);
105
			$newArr[$key] = is_array($v) ? self::convertArrayKeys($v, $dictionary) : $v;
106
		}
107
108
		return $newArr;
109
	}
110
111
	/**
112
	 * Get array value if exists, otherwise return a default value or null
113
	 * @param array $array
114
	 * @param int|string $key
115
	 * @param mixed|null $default
116
	 * @return mixed|null
117
	 */
118
	public static function arrayGetOrDefault(array $array, $key, $default=null) {
119
		return isset($array[$key]) ? $array[$key] : $default;
120
	}
121
122
	/**
123
	 * Truncate the given string to maximum length, appendig ellipsis character
124
	 * if the truncation happened. Also null argument may be safely passed and
125
	 * it remains unaltered.
126
	 * @param string|null $string
127
	 * @param int $maxLength
128
	 * @return string|null
129
	 */
130
	public static function truncate($string, $maxLength) {
131
		if ($string === null) {
132
			return null;
133
		} else {
134
			return \mb_strimwidth($string, 0, $maxLength, "\u{2026}");
135
		}
136
	}
137
138
	/**
139
	 * Test if given string starts with another given string
140
	 * @param string $string
141
	 * @param string $potentialStart
142
	 * @return boolean
143
	 */
144
	public static function startsWith($string, $potentialStart) {
145
		return \substr($string, 0, \strlen($potentialStart)) === $potentialStart;
146
	}
147
148
	/**
149
	 * Test if given string ends with another given string
150
	 * @param string $string
151
	 * @param string $potentialEnd
152
	 * @return boolean
153
	 */
154
	public static function endsWith($string, $potentialEnd) {
155
		return \substr($string, -\strlen($potentialEnd)) === $potentialEnd;
156
	}
157
158
	/**
159
	 * Multi-byte safe case-insensitive string comparison
160
	 * @param string $a
161
	 * @param string $b
162
	 */
163
	public static function stringCaseCompare($a, $b) {
164
		return \strcmp(\mb_strtolower($a), \mb_strtolower($b));
165
	}
166
167
	/**
168
	 * Convert file size given in bytes to human-readable format
169
	 * @param int $bytes
170
	 * @param int $decimals
171
	 * @return string
172
	 */
173
	public static function formatFileSize($bytes, $decimals = 1) {
174
		$units = 'BKMGTP';
175
		$factor = \floor((\strlen($bytes) - 1) / 3);
176
		return \sprintf("%.{$decimals}f", $bytes / \pow(1024, $factor)) . @$units[(int)$factor];
177
	}
178
179
	/**
180
	 * @param Folder $parentFolder
0 ignored issues
show
Bug introduced by
The type OCA\Music\Utility\Folder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
181
	 * @param string $relativePath
182
	 * @return Folder
183
	 */
184
	public static function getFolderFromRelativePath($parentFolder, $relativePath) {
185
		if ($relativePath !== null && $relativePath !== '/' && $relativePath !== '') {
186
			return $parentFolder->get($relativePath);
187
		} else {
188
			return $parentFolder;
189
		}
190
	}
191
192
	/**
193
	 * Create relative path from the given working dir (CWD) to the given target path
194
	 * @param string $cwdPath Absolute CWD path
195
	 * @param string $targetPath Absolute target path
196
	 * @return string
197
	 */
198
	public static function relativePath($cwdPath, $targetPath) {
199
		$cwdParts = \explode('/', $cwdPath);
200
		$targetParts = \explode('/', $targetPath);
201
202
		// remove the common prefix of the paths
203
		while (\count($cwdParts) > 0 && \count($targetParts) > 0 && $cwdParts[0] === $targetParts[0]) {
204
			\array_shift($cwdParts);
205
			\array_shift($targetParts);
206
		}
207
208
		// prepend up-navigation from CWD to the closest common parent folder with the target
209
		for ($i = 0; $i < \count($cwdParts); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
210
			\array_unshift($targetParts, '..');
211
		}
212
213
		return \implode('/', $targetParts);
214
	}
215
216
	/**
217
	 * Swap values of two variables in place
218
	 * @param mixed $a
219
	 * @param mixed $b
220
	 */
221
	public static function swap(&$a, &$b) {
222
		$temp = $a;
223
		$a = $b;
224
		$b = $temp;
225
	}
226
}
227