Passed
Push — master ( b5f949...4c08df )
by Pauli
04:24
created

StringUtil::caselessEqual()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 2
rs 10
c 1
b 0
f 0
1
<?php declare(strict_types=1);
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 2025
11
 */
12
13
namespace OCA\Music\Utility;
14
15
/**
16
 * Static utility functions to work with strings
17
 */
18
class StringUtil {
19
20
	/**
21
	 * Truncate the given string to maximum number of bytes, appending ellipsis character
22
	 * (or other given marker) if the truncation happened. Note that for multi-byte encoding (like utf8),
23
	 * the number of bytes may not be the same as the number of characters.
24
	 * Also null argument may be safely passed and it remains unaltered.
25
	 */
26
	public static function truncate(?string $string, int $maxBytes, string $trimMarker="\u{2026}") : ?string {
27
		if ($string === null) {
28
			return null;
29
		} else if (\strlen($string) > $maxBytes) {
30
			$string = \mb_strcut($string, 0, $maxBytes - \strlen($trimMarker));
31
			return $string . $trimMarker;
32
		} else {
33
			return $string;
34
		}
35
	}
36
37
	/**
38
	 * Test if given string starts with another given string
39
	 */
40
	public static function startsWith(string $string, string $potentialStart, bool $ignoreCase=false) : bool {
41
		$actualStart = \substr($string, 0, \strlen($potentialStart));
42
		if ($ignoreCase) {
43
			$actualStart = \mb_strtolower($actualStart);
44
			$potentialStart = \mb_strtolower($potentialStart);
45
		}
46
		return $actualStart === $potentialStart;
47
	}
48
49
	/**
50
	 * Test if given string ends with another given string
51
	 */
52
	public static function endsWith(string $string, string $potentialEnd, bool $ignoreCase=false) : bool {
53
		$actualEnd = \substr($string, -\strlen($potentialEnd));
54
		if ($ignoreCase) {
55
			$actualEnd = \mb_strtolower($actualEnd);
56
			$potentialEnd = \mb_strtolower($potentialEnd);
57
		}
58
		return $actualEnd === $potentialEnd;
59
	}
60
61
	/**
62
	 * Multi-byte safe case-insensitive string comparison
63
	 * @return int negative value if $a is less than $b, positive value if $a is greater than $b, and 0 if they are equal.
64
	 */
65
	public static function caselessCompare(?string $a, ?string $b) : int {
66
		return \strcmp(\mb_strtolower($a ?? ''), \mb_strtolower($b ?? ''));
67
	}
68
69
	public static function caselessEqual(?string $a, ?string $b) : bool {
70
		return (self::caselessCompare($a, $b) === 0);
71
	}
72
73
	/** 
74
	 * Convert snake case string (like_this) to camel case (likeThis).
75
	 */
76
	public static function snakeToCamelCase(string $input): string {
77
		return \lcfirst(\str_replace('_', '', \ucwords($input, '_')));
78
	}
79
80
	/**
81
	 * Test if $item is a string and not empty or only consisting of whitespace
82
	 */
83
	public static function isNonEmptyString(/*mixed*/ $item) : bool {
84
		return \is_string($item) && \trim($item) !== '';
85
	}
86
87
	/**
88
	 * Split given string to a prefix and a basename (=the remaining part after the prefix), considering the possible
89
	 * prefixes given as an array. If none of the prefixes match, the returned basename will be the original string
90
	 * and the prefix will be null.
91
	 * @param string[] $potentialPrefixes
92
	 */
93
	public static function splitPrefixAndBasename(?string $name, array $potentialPrefixes) : array {
94
		$parts = ['prefix' => null, 'basename' => $name];
95
96
		if ($name !== null) {
97
			foreach ($potentialPrefixes as $prefix) {
98
				if (self::startsWith($name, $prefix . ' ', /*ignoreCase=*/true)) {
99
					$parts['prefix'] = $prefix;
100
					$parts['basename'] = \substr($name, \strlen($prefix) + 1);
101
					break;
102
				}
103
			}
104
		}
105
106
		return $parts;
107
	}
108
109
}