xref: /plugin/combo/ComboStrap/StringUtility.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1<?php
2
3namespace ComboStrap;
4
5/**
6 * Class StringUtility
7 * @package ComboStrap
8 * A class with string utility
9 */
10class StringUtility
11{
12
13
14    /**
15     * Generate a text with a max length of $length
16     * and add ... if above
17     * @param $myString
18     * @param $length
19     * @return string
20     */
21    static function truncateString($myString, $length): string
22    {
23
24        if (strlen($myString) > $length) {
25            $suffix = ' ...';
26            $myString = substr($myString, 0, ($length - 1) - strlen($suffix)) . $suffix;
27        }
28        return $myString;
29    }
30
31    /**
32     * @param $string
33     * @return string - the string without any carriage return
34     * Used to compare string without worrying about carriage return
35     */
36    public static function normalized($string)
37    {
38        return str_replace("\n", "", $string);
39    }
40
41    /**
42     * @param $needle
43     * @param $haystack
44     * @return bool
45     */
46    public static function contain($needle, $haystack)
47    {
48        $pos = strpos($haystack, $needle);
49        if ($pos === FALSE) {
50            return false;
51        } else {
52            return true;
53        }
54    }
55
56    public static function toString($value)
57    {
58        /**
59         * No transformation if it's a string
60         * var_export below is not idempotent
61         * ie \ would become \\
62         */
63        if (is_string($value)) {
64            return $value;
65        }
66
67        if (is_array($value)) {
68            $string = var_export($value, true);
69
70            // An array value gets command in var_export
71            $lastCharacterIndex = strlen($string) - 1;
72            if ($string[0] === "'" && $string[$lastCharacterIndex] === "'") {
73                $string = substr($string, 1, strlen($string) - 2);
74            }
75            return $string;
76        }
77
78        if (is_object($value)) {
79            if (method_exists($value, "__toString")) {
80                return strval($value);
81            } else {
82                return get_class($value);
83            }
84        }
85
86        if (is_numeric($value)) {
87            return strval($value);
88        }
89
90        if (is_bool($value)) {
91            return var_export($value, true);
92        }
93
94        $string = var_export($value, true);
95        LogUtility::msg("The type of the value ($string) is unknown and could not be properly cast to string", LogUtility::LVL_MSG_WARNING);
96        return $string;
97
98    }
99
100    /**
101     * Add an EOL if not present at the end of the string
102     * @param $doc
103     */
104    public static function addEolCharacterIfNotPresent(&$doc)
105    {
106        if ($doc[strlen($doc) - 1] != DOKU_LF) {
107            $doc .= DOKU_LF;
108        }
109    }
110
111    /**
112     * Delete the string from the end
113     * This is used generally to delete the previous opening tag of an header or a blockquote
114     * @param $doc
115     * @param $string
116     */
117    public static function rtrim(&$doc, $string)
118    {
119
120        /**
121         * We trim because in the process, we may get extra {@link DOKU_LF} at the end
122         */
123        $doc = trim($doc);
124        $string = trim($string);
125        $length = strlen($doc) - strlen($string);
126        if (substr($doc, $length) === $string) {
127            $doc = substr($doc, 0, $length);
128        }
129
130    }
131
132    /**
133     * Delete the string from the beginning
134     * This is used to delete a tag for instance
135     * @param $doc
136     * @param $string
137     */
138    public static function ltrim(&$doc, $string)
139    {
140
141        $doc = trim($doc);
142        $string = trim($string);
143        $length = strlen($string);
144        if (substr($doc, 0, $length) === $string) {
145            $doc = substr($doc, $length);
146        }
147
148    }
149
150    /**
151     * The word count does not take into account
152     * words with non-words characters such as < =
153     * Therefore the node <node> and attribute name=value are not taken in the count
154     * @param $text
155     * @return int the number of words
156     */
157    public static function getWordCount($text)
158    {
159        /**
160         * Delete the frontmatter
161         */
162        $text = preg_replace("/^---(json)?$.*^---$/Ums", "", $text);
163        /**
164         * New line for node
165         */
166        $text = str_replace("<", "\n<", $text);
167        $text = str_replace(">", ">\n", $text);
168        // \s shorthand for whitespace
169        // | the table and links are separated with a |
170        // / to take into account expression such as and/or
171        // /u for unicode support (https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php)
172        $wordSeparator = '/[\s|\/]/u';
173        $preg_split = preg_split($wordSeparator, $text);
174        $wordsWithoutEmpty = array_filter($preg_split, 'self::isWord');
175        return count($wordsWithoutEmpty);
176    }
177
178    public static function normalize($expected)
179    {
180        $expected = preg_replace("/[\s]/", " ", $expected);
181        $expected = str_replace("  ", " ", $expected);
182        $expected = str_replace("  ", " ", $expected);
183        $expected = str_replace("  ", " ", $expected);
184        $expected = str_replace("  ", " ", $expected);
185        return trim($expected);
186
187    }
188
189    /**
190     * @param $text
191     * @return bool
192     */
193    public static function isWord($text)
194    {
195        if (empty($text)) {
196            return false;
197        }
198        /**
199         * We also allow `-` minus
200         *
201         * And because otherwise the words are not counted:
202         *   * `'` (used to highlight words)
203         *   * `[]` used in links
204         *   * `,` used at the end of a sentenct
205         */
206        $preg_match = preg_match("/^[\w\-'\]\[,]*$/u", $text);
207        return $preg_match == 1;
208    }
209
210    public static function match($subject, $pattern)
211    {
212        return preg_match("/$pattern/", $subject) === 1;
213    }
214
215    public static function endWiths($string, $suffix)
216    {
217        $suffixStartPosition = strlen($string) - strlen($suffix);
218        return strrpos($string, $suffix) === $suffixStartPosition;
219    }
220
221    public static function explodeAndTrim($string, $delimiter = ",")
222    {
223        return array_map('trim', explode($delimiter, $string));
224    }
225
226    public static function lastIndexOf($haystack, $needle)
227    {
228        /**
229         * strRpos
230         * and not strpos
231         */
232        return strrpos($haystack, $needle);
233    }
234
235    public static function startWiths($string, $prefix)
236    {
237        return strrpos($string, $prefix) === 0;
238    }
239
240}
241