AbstractStrlen   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 16
Bugs 1 Features 3
Metric Value
wmc 16
lcom 1
cbo 1
dl 0
loc 187
ccs 55
cts 55
cp 1
rs 10
c 16
b 1
f 3

7 Methods

Rating   Name   Duplication   Size   Complexity  
A iconv() 0 4 1
A substrIconv() 0 12 2
A strlenIconv() 0 12 2
A mbstring() 0 4 1
A strlen() 0 12 3
A substr() 0 13 3
B strpad() 0 37 4
1
<?php
2
/**
3
 *
4
 * This file is part of Aura for PHP.
5
 *
6
 * @license http://opensource.org/licenses/bsd-license.php BSD
7
 *
8
 */
9
namespace Aura\Filter\Rule;
10
11
use Aura\Filter\Exception;
12
13
/**
14
 *
15
 * Abstract rule for string-length filters; supports the `iconv` and `mbstring`
16
 * extensions.
17
 *
18
 * @package Aura.Filter
19
 *
20
 */
21
abstract class AbstractStrlen
22
{
23
    /**
24
     *
25
     * Is the `mbstring` extension loaded?
26
     *
27
     * @return bool
28
     *
29
     */
30 75
    protected function mbstring()
31
    {
32 75
        return extension_loaded('mbstring');
33
    }
34
35
    /**
36
     *
37
     * Is the `iconv` extension loaded?
38
     *
39
     * @return bool
40
     *
41
     */
42 119
    protected function iconv()
43
    {
44 119
        return extension_loaded('iconv');
45
    }
46
47
    /**
48
     *
49
     * Proxy to `iconv_strlen()` or `mb_strlen()` when available; fall back to
50
     * `utf8_decode()` and `strlen()` otherwise.
51
     *
52
     * @param string $str Return the number of characters in this string.
53
     *
54
     * @return int
55
     *
56
     */
57 121
    protected function strlen($str)
58
    {
59 121
        if ($this->iconv()) {
60 117
            return $this->strlenIconv($str);
61
        }
62
63 4
        if ($this->mbstring()) {
64 2
            return mb_strlen($str, 'UTF-8');
65
        }
66
67 2
        return strlen(utf8_decode($str));
68
    }
69
70
     /**
71
     *
72
     * Wrapper for `iconv_substr()` to throw an exception on malformed UTF-8.
73
     *
74
     * @param string $str The string to work with.
75
     *
76
     * @param int $start Start at this position.
77
     *
78
     * @param int $length End after this many characters.
79
     *
80
     * @return string
81
     *
82
     * @throws Exception\MalformedUtf8
83
     *
84
     */
85 49
    protected function substrIconv($str,$start,$length)
86
    {
87 49
        $level = error_reporting(0);
88 49
        $substr = iconv_substr($str,$start,$length, 'UTF-8');
89 49
        error_reporting($level);
90
91 49
        if ($substr !== false) {
92 48
            return $substr;
93
        }
94
95 1
        throw new Exception\MalformedUtf8();
96
    }
97
    
98
    /**
99
     *
100
     * Wrapper for `iconv_strlen()` to throw an exception on malformed UTF-8.
101
     *
102
     * @param string $str Return the number of characters in this string.
103
     *
104
     * @return int
105
     *
106
     * @throws Exception\MalformedUtf8
107
     *
108
     */
109 117
    protected function strlenIconv($str)
110
    {
111 117
        $level = error_reporting(0);
112 117
        $strlen = iconv_strlen($str, 'UTF-8');
113 117
        error_reporting($level);
114
115 117
        if ($strlen !== false) {
116 116
            return $strlen;
117
        }
118
119 1
        throw new Exception\MalformedUtf8();
120
    }
121
122
    /**
123
     *
124
     * Proxy to `iconv_substr()` or `mb_substr()` when the `mbstring` available;
125
     * polyfill via `preg_split()` and `array_slice()` otherwise.
126
     *
127
     * @param string $str The string to work with.
128
     *
129
     * @param int $start Start at this position.
130
     *
131
     * @param int $length End after this many characters.
132
     *
133
     * @return string
134
     *
135
     */
136 53
    protected function substr($str, $start, $length = null)
137
    {
138 53
        if ($this->iconv()) {
139 49
            return $this->substrIconv($str, $start, $length);
140
        }
141
142 4
        if ($this->mbstring()) {
143 2
            return mb_substr($str, $start, $length, 'UTF-8');
144
        }
145
146 2
        $split = preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
147 2
        return implode('', array_slice($split, $start, $length));
148
    }
149
150
    /**
151
     *
152
     * Userland UTF-8-aware implementation of `str_pad()`.
153
     *
154
     * @param string $input The input string.
155
     *
156
     * @param int $pad_length If the value of pad_length is negative, less than,
157
     * or equal to the length of the input string, no padding takes place.
158
     *
159
     * @param string $pad_str Pad with this string. The pad_string may be
160
     * truncated if the required number of padding characters can't be evenly
161
     * divided by the pad_string's length.
162
     *
163
     * @param int $pad_type Optional argument pad_type can be STR_PAD_RIGHT,
164
     * STR_PAD_LEFT, or STR_PAD_BOTH. If pad_type is not specified it is
165
     * assumed to be STR_PAD_RIGHT.
166
     *
167
     * @return string
168
     *
169
     */
170 9
    protected function strpad($input, $pad_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
171
    {
172 9
        $input_len = $this->strlen($input);
173 9
        if ($pad_length <= $input_len) {
174 3
            return $input;
175
        }
176
177 9
        $pad_str_len = $this->strlen($pad_str);
178 9
        $pad_len = $pad_length - $input_len;
179
180 9
        if ($pad_type == STR_PAD_LEFT) {
181 3
            $repeat_times = ceil($pad_len / $pad_str_len);
182 3
            $prefix = str_repeat($pad_str, $repeat_times);
183 3
            return $this->substr($prefix, 0, floor($pad_len)) . $input;
184
        }
185
186 9
        if ($pad_type == STR_PAD_BOTH) {
187 3
            $pad_len /= 2;
188 3
            $pad_amount_left = floor($pad_len);
189 3
            $pad_amount_right = ceil($pad_len);
190 3
            $repeat_times_left = ceil($pad_amount_left / $pad_str_len);
191 3
            $repeat_times_right = ceil($pad_amount_right / $pad_str_len);
192
193 3
            $prefix = str_repeat($pad_str, $repeat_times_left);
194 3
            $padding_left = $this->substr($prefix, 0, $pad_amount_left);
195
196 3
            $suffix = str_repeat($pad_str, $repeat_times_right);
197 3
            $padding_right = $this->substr($suffix, 0, $pad_amount_right);
198
199 3
            return $padding_left . $input . $padding_right;
200
        }
201
202
        // STR_PAD_RIGHT
203 9
        $repeat_times = ceil($pad_len / $pad_str_len);
204 9
        $input .= str_repeat($pad_str, $repeat_times);
205 9
        return $this->substr($input, 0, $pad_length);
206
    }
207
}
208