1: <?php namespace Laravel;
2:
3: class Str {
4:
5: /**
6: * The pluralizer instance.
7: *
8: * @var Pluralizer
9: */
10: public static $pluralizer;
11:
12: /**
13: * Cache application encoding locally to save expensive calls to Config::get().
14: *
15: * @var string
16: */
17: public static $encoding = null;
18:
19: /**
20: * Get the appliction.encoding without needing to request it from Config::get() each time.
21: *
22: * @return string
23: */
24: protected static function encoding()
25: {
26: return static::$encoding ?: static::$encoding = Config::get('application.encoding');
27: }
28:
29: /**
30: * Get the length of a string.
31: *
32: * <code>
33: * // Get the length of a string
34: * $length = Str::length('Taylor Otwell');
35: *
36: * // Get the length of a multi-byte string
37: * $length = Str::length('Τάχιστη')
38: * </code>
39: *
40: * @param string $value
41: * @return int
42: */
43: public static function length($value)
44: {
45: return (MB_STRING) ? mb_strlen($value, static::encoding()) : strlen($value);
46: }
47:
48: /**
49: * Convert a string to lowercase.
50: *
51: * <code>
52: * // Convert a string to lowercase
53: * $lower = Str::lower('Taylor Otwell');
54: *
55: * // Convert a multi-byte string to lowercase
56: * $lower = Str::lower('Τάχιστη');
57: * </code>
58: *
59: * @param string $value
60: * @return string
61: */
62: public static function lower($value)
63: {
64: return (MB_STRING) ? mb_strtolower($value, static::encoding()) : strtolower($value);
65: }
66:
67: /**
68: * Convert a string to uppercase.
69: *
70: * <code>
71: * // Convert a string to uppercase
72: * $upper = Str::upper('Taylor Otwell');
73: *
74: * // Convert a multi-byte string to uppercase
75: * $upper = Str::upper('Τάχιστη');
76: * </code>
77: *
78: * @param string $value
79: * @return string
80: */
81: public static function upper($value)
82: {
83: return (MB_STRING) ? mb_strtoupper($value, static::encoding()) : strtoupper($value);
84: }
85:
86: /**
87: * Convert a string to title case (ucwords equivalent).
88: *
89: * <code>
90: * // Convert a string to title case
91: * $title = Str::title('taylor otwell');
92: *
93: * // Convert a multi-byte string to title case
94: * $title = Str::title('νωθρού κυνός');
95: * </code>
96: *
97: * @param string $value
98: * @return string
99: */
100: public static function title($value)
101: {
102: if (MB_STRING)
103: {
104: return mb_convert_case($value, MB_CASE_TITLE, static::encoding());
105: }
106:
107: return ucwords(strtolower($value));
108: }
109:
110: /**
111: * Limit the number of characters in a string.
112: *
113: * <code>
114: * // Returns "Tay..."
115: * echo Str::limit('Taylor Otwell', 3);
116: *
117: * // Limit the number of characters and append a custom ending
118: * echo Str::limit('Taylor Otwell', 3, '---');
119: * </code>
120: *
121: * @param string $value
122: * @param int $limit
123: * @param string $end
124: * @return string
125: */
126: public static function limit($value, $limit = 100, $end = '...')
127: {
128: if (static::length($value) <= $limit) return $value;
129:
130: if (MB_STRING)
131: {
132: return mb_substr($value, 0, $limit, static::encoding()).$end;
133: }
134:
135: return substr($value, 0, $limit).$end;
136: }
137:
138: /**
139: * Limit the number of chracters in a string including custom ending
140: *
141: * <code>
142: * // Returns "Taylor..."
143: * echo Str::limit_exact('Taylor Otwell', 9);
144: *
145: * // Limit the number of characters and append a custom ending
146: * echo Str::limit_exact('Taylor Otwell', 9, '---');
147: * </code>
148: *
149: * @param string $value
150: * @param int $limit
151: * @param string $end
152: * @return string
153: */
154: public static function limit_exact($value, $limit = 100, $end = '...')
155: {
156: if (static::length($value) <= $limit) return $value;
157:
158: $limit -= static::length($end);
159:
160: return static::limit($value, $limit, $end);
161: }
162:
163: /**
164: * Limit the number of words in a string.
165: *
166: * <code>
167: * // Returns "This is a..."
168: * echo Str::words('This is a sentence.', 3);
169: *
170: * // Limit the number of words and append a custom ending
171: * echo Str::words('This is a sentence.', 3, '---');
172: * </code>
173: *
174: * @param string $value
175: * @param int $words
176: * @param string $end
177: * @return string
178: */
179: public static function words($value, $words = 100, $end = '...')
180: {
181: if (trim($value) == '') return '';
182:
183: preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
184:
185: if (static::length($value) == static::length($matches[0]))
186: {
187: $end = '';
188: }
189:
190: return rtrim($matches[0]).$end;
191: }
192:
193: /**
194: * Get the singular form of the given word.
195: *
196: * @param string $value
197: * @return string
198: */
199: public static function singular($value)
200: {
201: return static::pluralizer()->singular($value);
202: }
203:
204: /**
205: * Get the plural form of the given word.
206: *
207: * <code>
208: * // Returns the plural form of "child"
209: * $plural = Str::plural('child', 10);
210: *
211: * // Returns the singular form of "octocat" since count is one
212: * $plural = Str::plural('octocat', 1);
213: * </code>
214: *
215: * @param string $value
216: * @param int $count
217: * @return string
218: */
219: public static function plural($value, $count = 2)
220: {
221: return static::pluralizer()->plural($value, $count);
222: }
223:
224: /**
225: * Get the pluralizer instance.
226: *
227: * @return Pluralizer
228: */
229: protected static function pluralizer()
230: {
231: $config = Config::get('strings');
232:
233: return static::$pluralizer ?: static::$pluralizer = new Pluralizer($config);
234: }
235:
236: /**
237: * Generate a URL friendly "slug" from a given string.
238: *
239: * <code>
240: * // Returns "this-is-my-blog-post"
241: * $slug = Str::slug('This is my blog post!');
242: *
243: * // Returns "this_is_my_blog_post"
244: * $slug = Str::slug('This is my blog post!', '_');
245: * </code>
246: *
247: * @param string $title
248: * @param string $separator
249: * @return string
250: */
251: public static function slug($title, $separator = '-')
252: {
253: $title = static::ascii($title);
254:
255: // Remove all characters that are not the separator, letters, numbers, or whitespace.
256: $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', static::lower($title));
257:
258: // Replace all separator characters and whitespace by a single separator
259: $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
260:
261: return trim($title, $separator);
262: }
263:
264: /**
265: * Convert a string to 7-bit ASCII.
266: *
267: * This is helpful for converting UTF-8 strings for usage in URLs, etc.
268: *
269: * @param string $value
270: * @return string
271: */
272: public static function ascii($value)
273: {
274: $foreign = Config::get('strings.ascii');
275:
276: $value = preg_replace(array_keys($foreign), array_values($foreign), $value);
277:
278: return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $value);
279: }
280:
281: /**
282: * Convert a string to an underscored, camel-cased class name.
283: *
284: * This method is primarily used to format task and controller names.
285: *
286: * <code>
287: * // Returns "Task_Name"
288: * $class = Str::classify('task_name');
289: *
290: * // Returns "Taylor_Otwell"
291: * $class = Str::classify('taylor otwell')
292: * </code>
293: *
294: * @param string $value
295: * @return string
296: */
297: public static function classify($value)
298: {
299: $search = array('_', '-', '.', '/');
300:
301: return str_replace(' ', '_', static::title(str_replace($search, ' ', $value)));
302: }
303:
304: /**
305: * Return the "URI" style segments in a given string.
306: *
307: * @param string $value
308: * @return array
309: */
310: public static function segments($value)
311: {
312: return array_diff(explode('/', trim($value, '/')), array(''));
313: }
314:
315: /**
316: * Generate a random alpha or alpha-numeric string.
317: *
318: * <code>
319: * // Generate a 40 character random alpha-numeric string
320: * echo Str::random(40);
321: *
322: * // Generate a 16 character random alphabetic string
323: * echo Str::random(16, 'alpha');
324: * <code>
325: *
326: * @param int $length
327: * @param string $type
328: * @return string
329: */
330: public static function random($length, $type = 'alnum')
331: {
332: return substr(str_shuffle(str_repeat(static::pool($type), 5)), 0, $length);
333: }
334:
335: /**
336: * Determine if a given string matches a given pattern.
337: *
338: * @param string $pattern
339: * @param string $value
340: * @return bool
341: */
342: public static function is($pattern, $value)
343: {
344: // Asterisks are translated into zero-or-more regular expression wildcards
345: // to make it convenient to check if the URI starts with a given pattern
346: // such as "library/*". This is only done when not root.
347: if ($pattern !== '/')
348: {
349: $pattern = str_replace('*', '(.*)', $pattern).'\z';
350: }
351: else
352: {
353: $pattern = '^/$';
354: }
355:
356: return preg_match('#'.$pattern.'#', $value);
357: }
358:
359: /**
360: * Get the character pool for a given type of random string.
361: *
362: * @param string $type
363: * @return string
364: */
365: protected static function pool($type)
366: {
367: switch ($type)
368: {
369: case 'alpha':
370: return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
371:
372: case 'alnum':
373: return '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
374:
375: default:
376: throw new \Exception("Invalid random string type [$type].");
377: }
378: }
379:
380: }