Completed
Push — master ( 34d315...a20938 )
by Garrett
09:58
created

AString::offsetGet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace StringObject;
4
5
class AString extends AnyString implements \ArrayAccess, \Countable, \Iterator
6
{
7
    // CONSTANTS
8
9
    const START = 0;
10
    const END = 1;
11
    const BOTH_ENDS = 2;
12
    const NORMAL = 0;
13
    const CASE_INSENSITIVE = 1;
14
    const REVERSE = 2;
15
    const EXACT_POSITION = 4;
16
    const CURRENT_LOCALE = 2;
17
    const NATURAL_ORDER = 4;
18
    const FIRST_N = 8;
19
    const C_STYLE = 1;
20
    const META = 2;
21
    const GREEDY = 0;
22
    const LAZY = 1;
23
24
    // PROPERTIES
25
26
    protected $raw;
27
    protected $token = false;
28
    protected $caret = 0;
29
30
    // MAGIC METHODS
31
32
    /**
33
     * @return mixed
34
     */
35
    public function __get($name)
36
    {
37
        return $this->$name;
38
    }
39
40
    /**
41
     * @return string
42
     */
43
    public function __toString()
44
    {
45
        return $this->raw;
46
    }
47
48 View Code Duplication
    public function toArray($delim = '', $limit = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
49
    {
50
        if (empty($delim)) {
51
            return \str_split($this->raw);
52
        }
53
        if (is_int($delim)) {
54
            return \str_split($this->raw, $delim);
55
        }
56
        if ($limit === null) {
57
            return \explode($delim, $this->raw);
58
        }
59
        return \explode($delim, $this->raw, $limit);
60
    }
61
62
    // INFORMATIONAL METHODS
63
64
    public function charAt($offset)
65
    {
66
        return new self($this->raw{$offset});
67
    }
68
69
    /**
70
     * @param integer $offset
71
     */
72
    public function charCodeAt($offset)
73
    {
74
        return \ord($this->raw{$offset});
75
    }
76
77
    public function compareTo($str, $flags = self::NORMAL, $length = 1)
78
    {
79
        // strip out bits we don't understand
80
        $flags &= (self::CASE_INSENSITIVE | self::CURRENT_LOCALE | self::NATURAL_ORDER | self::FIRST_N);
81
82
        $flagsmap = [
83
            self::NORMAL => 'strcmp',
84
            self::CASE_INSENSITIVE => 'strcasecmp',
85
            self::CURRENT_LOCALE => 'strcoll',
86
            self::NATURAL_ORDER => 'strnatcmp',
87
            (self::NATURAL_ORDER | self::CASE_INSENSITIVE) => 'strnatcasecmp',
88
            self::FIRST_N => 'strncmp',
89
            (self::FIRST_N | self::CASE_INSENSITIVE) => 'strncasecmp',
90
        ];
91
92
        if ($flags & self::FIRST_N) {
93
            return \call_user_func($flagsmap[$flags], $this->raw, $str, $length);
94
        }
95
        return \call_user_func($flagsmap[$flags], $this->raw, $str);
96
    }
97
98
    public function indexOf($needle, $offset = 0, $flags = self::NORMAL)
99
    {
100
        // strip out bits we don't understand
101
        $flags &= (self::REVERSE | self::CASE_INSENSITIVE);
102
103
        $flagsmap = [
104
            self::NORMAL => 'strpos',
105
            self::CASE_INSENSITIVE => 'stripos',
106
            self::REVERSE => 'strrpos',
107
            (self::REVERSE | self::CASE_INSENSITIVE) => 'strripos',
108
        ];
109
        return \call_user_func($flagsmap[$flags], $this->raw, $needle, $offset);
110
    }
111
112
    public function length()
113
    {
114
        return \strlen($this->raw);
115
    }
116
117
    // MODIFYING METHODS
118
119
    public function append($str)
120
    {
121
        return new self($this->raw . $str);
122
    }
123
124
    public function chunk($length = 76, $ending = "\r\n")
125
    {
126
        return new self(\chunk_split($this->raw, $length, $ending));
127
    }
128
129
    public function concat($str)
130
    {
131
        return $this->append($str);
132
    }
133
134
    public function escape($flags = self::NORMAL, $charlist = '')
135
    {
136
        // strip out bits we don't understand
137
        $flags &= (self::C_STYLE | self::META);
138
139
        $flagsmap = [
140
            self::NORMAL => 'addslashes',
141
            self::C_STYLE => 'addcslashes',
142
            self::META => 'quotemeta',
143
        ];
144 View Code Duplication
        if ($flags === self::C_STYLE) {
1 ignored issue
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...
145
            return new self(\call_user_func($flagsmap[$flags], $this->raw, $charlist));
146
        }
147
        return new self(\call_user_func($flagsmap[$flags], $this->raw));
148
    }
149
150
    public function insertAt($str, $offset)
151
    {
152
        return $this->replaceSubstr($str, $offset, 0);
153
    }
154
155
    public function nextToken($delim)
156
    {
157
        if ($this->token) {
158
            return new self(\strtok($delim));
159
        }
160
        $this->token = true;
161
        return new self(\strtok($this->raw, $delim));
162
    }
163
164
    public function pad($newlength, $padding = ' ', $flags = self::END)
165
    {
166
        return new self(\str_pad($this->raw, $newlength, $padding, $flags));
167
    }
168
169
    public function prepend($str)
170
    {
171
        return new self($str . $this->raw);
172
    }
173
174
    public function remove($str, $flags = self::NORMAL)
175
    {
176
        return $this->replace($str, '', $flags);
177
    }
178
179
    public function removeSubstr($start, $length = null)
180
    {
181
        return $this->replaceSubstr('', $start, $length);
182
    }
183
184
    public function repeat($times)
185
    {
186
        return new self(\str_repeat($this->raw, $times));
187
    }
188
189
    /**
190
     * @param string $replace
191
     */
192
    public function replace($search, $replace, $flags = self::NORMAL)
193
    {
194
        if ($flags & self::CASE_INSENSITIVE) {
195
            return new self(\str_ireplace($search, $replace, $this->raw));
196
        }
197
        return new self(\str_replace($search, $replace, $this->raw));
198
    }
199
200 View Code Duplication
    public function replaceSubstr($replacement, $start, $length = null)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in 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...
201
    {
202
        if ($length === null) {
203
            $length = $this->length();
204
        }
205
        return new self(\substr_replace($this->raw, $replacement, $start, $length));
206
    }
207
208
    public function replaceWhole($replacement = '')
209
    {
210
        return new self($replacement);
211
    }
212
213
    public function resetToken()
214
    {
215
        $this->token = false;
216
    }
217
218
    public function reverse()
219
    {
220
        return new self(\strrev($this->raw));
221
    }
222
223
    public function shuffle()
224
    {
225
        return new self(\str_shuffle($this->raw));
226
    }
227
228
    public function substr($start, $length = 'omitted')
229
    {
230
        if ($length === 'omitted') {
231
            return new self(\substr($this->raw, $start));
232
        }
233
        return new self(\substr($this->raw, $start, $length));
234
    }
235
236
    public function times($times)
237
    {
238
        return $this->repeat($times);
239
    }
240
241
    public function translate($search, $replace = '')
242
    {
243
        if (is_array($search)) {
244
            return new self(\strtr($this->raw, $search));
245
        }
246
        return new self(\strtr($this->raw, $search, $replace));
247
    }
248
249 View Code Duplication
    public function trim($mask = " \t\n\r\0\x0B", $flags = self::BOTH_ENDS)
250
    {
251
        // strip out bits we don't understand
252
        $flags &= (self::END | self::BOTH_ENDS);
253
254
        $flagsmap = [
255
            self::START => 'ltrim',
256
            self::END => 'rtrim',
257
            self::BOTH_ENDS => 'trim',
258
        ];
259
        return new self(\call_user_func($flagsmap[$flags], $this->raw, $mask));
260
    }
261
262 View Code Duplication
    public function unescape($flags = self::NORMAL)
263
    {
264
        // strip out bits we don't understand
265
        $flags &= (self::C_STYLE | self::META);
266
267
        $flagsmap = [
268
            self::NORMAL => 'stripslashes',
269
            self::C_STYLE => 'stripcslashes',
270
            self::META => 'stripslashes',
271
        ];
272
        return new self(\call_user_func($flagsmap[$flags], $this->raw));
273
    }
274
275
    public function uuDecode()
276
    {
277
        return new self(\convert_uudecode($this->raw));
278
    }
279
280
    public function uuEncode()
281
    {
282
        return new self(\convert_uuencode($this->raw));
283
    }
284
285
    public function wordwrap($width = 75, $break = "\n")
286
    {
287
        return new self(\wordwrap($this->raw, $width, $break, false));
288
    }
289
290
    public function wordwrapBreaking($width = 75, $break = "\n")
291
    {
292
        return new self(\wordwrap($this->raw, $width, $break, true));
293
    }
294
295
    // TESTING METHODS
296
297
    public function contains($needle, $offset = 0, $flags = self::NORMAL)
298
    {
299
        if ($flags & self::EXACT_POSITION) {
300
            return ($this->indexOf($needle, $offset, $flags) === $offset);
301
        }
302
        return ($this->indexOf($needle, $offset, $flags) !== false);
303
    }
304
305
    public function countSubstr($needle, $offset = 0, $length = null)
306
    {
307
        if ($length === null) {
308
            return \substr_count($this->raw, $needle, $offset);
309
        }
310
        return \substr_count($this->raw, $needle, $offset, $length);
311
    }
312
313
    public function endsWith($str, $flags = self::NORMAL)
314
    {
315
        $flags &= self::CASE_INSENSITIVE;
316
        $offset = $this->length() - \strlen($str);
317
        return $this->contains($str, $offset, $flags | self::EXACT_POSITION | self::REVERSE);
318
    }
319
320
    public function equals($str)
321
    {
322
        self::testStringableObject($str);
323
324
        $str = (string) $str;
325
        return ($str == $this->raw);
326
    }
327
328
    public function isAscii()
329
    {
330
        $len = $this->length();
331
332
        for ($i = 0; $i < $len; $i++) {
333
            if ($this->charCodeAt($i) >= 128) {
334
                return false;
335
            }
336
        }
337
        return true;
338
    }
339
340
    public function isEmpty()
341
    {
342
        return empty($this->raw);
343
    }
344
345
    public function startsWith($str, $flags = self::NORMAL)
346
    {
347
        $flags &= self::CASE_INSENSITIVE;
348
        return $this->contains($str, 0, $flags | self::EXACT_POSITION);
349
    }
350
351
    // INTERFACE IMPLEMENTATION METHODS
352
353
    public function count()
354
    {
355
        return \strlen($this->raw);
356
    }
357
358
    public function current()
359
    {
360
        return $this->raw[$this->caret];
361
    }
362
363
    public function key()
364
    {
365
        return $this->caret;
366
    }
367
368
    public function next()
369
    {
370
        $this->caret++;
371
    }
372
373
    public function rewind()
374
    {
375
        $this->caret = 0;
376
    }
377
378
    public function valid()
379
    {
380
        return ($this->caret < \strlen($this->raw));
381
    }
382
383
    public function offsetExists($offset)
384
    {
385
        $offset = (int) $offset;
386
        return ($offset >= 0 && $offset < \strlen($this->raw));
387
    }
388
389
    public function offsetGet($offset)
390
    {
391
        return $this->raw{$offset};
392
    }
393
394
    public function offsetSet($offset, $value)
395
    {
396
        throw new \LogicException('Cannot assign ' . $value . ' to immutable AString instance at index ' . $offset);
397
    }
398
399
    public function offsetUnset($offset)
400
    {
401
        throw new \LogicException('Cannot unset index ' . $offset . ' on immutable AString instance');
402
    }
403
}
404