Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * Zend Framework (http://framework.zend.com/)
|
Chris@0
|
4 *
|
Chris@0
|
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
|
Chris@0
|
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
Chris@0
|
7 * @license http://framework.zend.com/license/new-bsd New BSD License
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 namespace Zend\Stdlib\StringWrapper;
|
Chris@0
|
11
|
Chris@0
|
12 use Zend\Stdlib\Exception;
|
Chris@0
|
13 use Zend\Stdlib\StringUtils;
|
Chris@0
|
14
|
Chris@0
|
15 abstract class AbstractStringWrapper implements StringWrapperInterface
|
Chris@0
|
16 {
|
Chris@0
|
17 /**
|
Chris@0
|
18 * The character encoding working on
|
Chris@0
|
19 * @var string|null
|
Chris@0
|
20 */
|
Chris@0
|
21 protected $encoding = 'UTF-8';
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * An optionally character encoding to convert to
|
Chris@0
|
25 * @var string|null
|
Chris@0
|
26 */
|
Chris@0
|
27 protected $convertEncoding;
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * Check if the given character encoding is supported by this wrapper
|
Chris@0
|
31 * and the character encoding to convert to is also supported.
|
Chris@0
|
32 *
|
Chris@0
|
33 * @param string $encoding
|
Chris@0
|
34 * @param string|null $convertEncoding
|
Chris@0
|
35 * @return bool
|
Chris@0
|
36 */
|
Chris@0
|
37 public static function isSupported($encoding, $convertEncoding = null)
|
Chris@0
|
38 {
|
Chris@0
|
39 $supportedEncodings = static::getSupportedEncodings();
|
Chris@0
|
40
|
Chris@12
|
41 if (! in_array(strtoupper($encoding), $supportedEncodings)) {
|
Chris@0
|
42 return false;
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@12
|
45 if ($convertEncoding !== null && ! in_array(strtoupper($convertEncoding), $supportedEncodings)) {
|
Chris@0
|
46 return false;
|
Chris@0
|
47 }
|
Chris@0
|
48
|
Chris@0
|
49 return true;
|
Chris@0
|
50 }
|
Chris@0
|
51
|
Chris@0
|
52 /**
|
Chris@0
|
53 * Set character encoding working with and convert to
|
Chris@0
|
54 *
|
Chris@0
|
55 * @param string $encoding The character encoding to work with
|
Chris@0
|
56 * @param string|null $convertEncoding The character encoding to convert to
|
Chris@0
|
57 * @return StringWrapperInterface
|
Chris@0
|
58 */
|
Chris@0
|
59 public function setEncoding($encoding, $convertEncoding = null)
|
Chris@0
|
60 {
|
Chris@0
|
61 $supportedEncodings = static::getSupportedEncodings();
|
Chris@0
|
62
|
Chris@0
|
63 $encodingUpper = strtoupper($encoding);
|
Chris@12
|
64 if (! in_array($encodingUpper, $supportedEncodings)) {
|
Chris@0
|
65 throw new Exception\InvalidArgumentException(
|
Chris@0
|
66 'Wrapper doesn\'t support character encoding "' . $encoding . '"'
|
Chris@0
|
67 );
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 if ($convertEncoding !== null) {
|
Chris@0
|
71 $convertEncodingUpper = strtoupper($convertEncoding);
|
Chris@12
|
72 if (! in_array($convertEncodingUpper, $supportedEncodings)) {
|
Chris@0
|
73 throw new Exception\InvalidArgumentException(
|
Chris@0
|
74 'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"'
|
Chris@0
|
75 );
|
Chris@0
|
76 }
|
Chris@0
|
77
|
Chris@0
|
78 $this->convertEncoding = $convertEncodingUpper;
|
Chris@0
|
79 } else {
|
Chris@0
|
80 $this->convertEncoding = null;
|
Chris@0
|
81 }
|
Chris@0
|
82 $this->encoding = $encodingUpper;
|
Chris@0
|
83
|
Chris@0
|
84 return $this;
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 /**
|
Chris@0
|
88 * Get the defined character encoding to work with
|
Chris@0
|
89 *
|
Chris@0
|
90 * @return string
|
Chris@0
|
91 * @throws Exception\LogicException If no encoding was defined
|
Chris@0
|
92 */
|
Chris@0
|
93 public function getEncoding()
|
Chris@0
|
94 {
|
Chris@0
|
95 return $this->encoding;
|
Chris@0
|
96 }
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * Get the defined character encoding to convert to
|
Chris@0
|
100 *
|
Chris@0
|
101 * @return string|null
|
Chris@0
|
102 */
|
Chris@0
|
103 public function getConvertEncoding()
|
Chris@0
|
104 {
|
Chris@0
|
105 return $this->convertEncoding;
|
Chris@0
|
106 }
|
Chris@0
|
107
|
Chris@0
|
108 /**
|
Chris@0
|
109 * Convert a string from defined character encoding to the defined convert encoding
|
Chris@0
|
110 *
|
Chris@0
|
111 * @param string $str
|
Chris@0
|
112 * @param bool $reverse
|
Chris@0
|
113 * @return string|false
|
Chris@0
|
114 */
|
Chris@0
|
115 public function convert($str, $reverse = false)
|
Chris@0
|
116 {
|
Chris@0
|
117 $encoding = $this->getEncoding();
|
Chris@0
|
118 $convertEncoding = $this->getConvertEncoding();
|
Chris@0
|
119 if ($convertEncoding === null) {
|
Chris@0
|
120 throw new Exception\LogicException(
|
Chris@0
|
121 'No convert encoding defined'
|
Chris@0
|
122 );
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 if ($encoding === $convertEncoding) {
|
Chris@0
|
126 return $str;
|
Chris@0
|
127 }
|
Chris@0
|
128
|
Chris@0
|
129 $from = $reverse ? $convertEncoding : $encoding;
|
Chris@0
|
130 $to = $reverse ? $encoding : $convertEncoding;
|
Chris@0
|
131 throw new Exception\RuntimeException(sprintf(
|
Chris@0
|
132 'Converting from "%s" to "%s" isn\'t supported by this string wrapper',
|
Chris@0
|
133 $from,
|
Chris@0
|
134 $to
|
Chris@0
|
135 ));
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 /**
|
Chris@0
|
139 * Wraps a string to a given number of characters
|
Chris@0
|
140 *
|
Chris@0
|
141 * @param string $string
|
Chris@0
|
142 * @param int $width
|
Chris@0
|
143 * @param string $break
|
Chris@0
|
144 * @param bool $cut
|
Chris@0
|
145 * @return string|false
|
Chris@0
|
146 */
|
Chris@0
|
147 public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
|
Chris@0
|
148 {
|
Chris@0
|
149 $string = (string) $string;
|
Chris@0
|
150 if ($string === '') {
|
Chris@0
|
151 return '';
|
Chris@0
|
152 }
|
Chris@0
|
153
|
Chris@0
|
154 $break = (string) $break;
|
Chris@0
|
155 if ($break === '') {
|
Chris@0
|
156 throw new Exception\InvalidArgumentException('Break string cannot be empty');
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 $width = (int) $width;
|
Chris@0
|
160 if ($width === 0 && $cut) {
|
Chris@0
|
161 throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
|
Chris@0
|
165 return wordwrap($string, $width, $break, $cut);
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 $stringWidth = $this->strlen($string);
|
Chris@0
|
169 $breakWidth = $this->strlen($break);
|
Chris@0
|
170
|
Chris@0
|
171 $result = '';
|
Chris@0
|
172 $lastStart = $lastSpace = 0;
|
Chris@0
|
173
|
Chris@0
|
174 for ($current = 0; $current < $stringWidth; $current++) {
|
Chris@0
|
175 $char = $this->substr($string, $current, 1);
|
Chris@0
|
176
|
Chris@0
|
177 $possibleBreak = $char;
|
Chris@0
|
178 if ($breakWidth !== 1) {
|
Chris@0
|
179 $possibleBreak = $this->substr($string, $current, $breakWidth);
|
Chris@0
|
180 }
|
Chris@0
|
181
|
Chris@0
|
182 if ($possibleBreak === $break) {
|
Chris@0
|
183 $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
|
Chris@0
|
184 $current += $breakWidth - 1;
|
Chris@0
|
185 $lastStart = $lastSpace = $current + 1;
|
Chris@0
|
186 continue;
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 if ($char === ' ') {
|
Chris@0
|
190 if ($current - $lastStart >= $width) {
|
Chris@0
|
191 $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
|
Chris@0
|
192 $lastStart = $current + 1;
|
Chris@0
|
193 }
|
Chris@0
|
194
|
Chris@0
|
195 $lastSpace = $current;
|
Chris@0
|
196 continue;
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
|
Chris@0
|
200 $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
|
Chris@0
|
201 $lastStart = $lastSpace = $current;
|
Chris@0
|
202 continue;
|
Chris@0
|
203 }
|
Chris@0
|
204
|
Chris@0
|
205 if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
|
Chris@0
|
206 $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break;
|
Chris@0
|
207 $lastStart = $lastSpace = $lastSpace + 1;
|
Chris@0
|
208 continue;
|
Chris@0
|
209 }
|
Chris@0
|
210 }
|
Chris@0
|
211
|
Chris@0
|
212 if ($lastStart !== $current) {
|
Chris@0
|
213 $result .= $this->substr($string, $lastStart, $current - $lastStart);
|
Chris@0
|
214 }
|
Chris@0
|
215
|
Chris@0
|
216 return $result;
|
Chris@0
|
217 }
|
Chris@0
|
218
|
Chris@0
|
219 /**
|
Chris@0
|
220 * Pad a string to a certain length with another string
|
Chris@0
|
221 *
|
Chris@0
|
222 * @param string $input
|
Chris@0
|
223 * @param int $padLength
|
Chris@0
|
224 * @param string $padString
|
Chris@0
|
225 * @param int $padType
|
Chris@0
|
226 * @return string
|
Chris@0
|
227 */
|
Chris@0
|
228 public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
|
Chris@0
|
229 {
|
Chris@0
|
230 if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
|
Chris@0
|
231 return str_pad($input, $padLength, $padString, $padType);
|
Chris@0
|
232 }
|
Chris@0
|
233
|
Chris@0
|
234 $lengthOfPadding = $padLength - $this->strlen($input);
|
Chris@0
|
235 if ($lengthOfPadding <= 0) {
|
Chris@0
|
236 return $input;
|
Chris@0
|
237 }
|
Chris@0
|
238
|
Chris@0
|
239 $padStringLength = $this->strlen($padString);
|
Chris@0
|
240 if ($padStringLength === 0) {
|
Chris@0
|
241 return $input;
|
Chris@0
|
242 }
|
Chris@0
|
243
|
Chris@0
|
244 $repeatCount = floor($lengthOfPadding / $padStringLength);
|
Chris@0
|
245
|
Chris@0
|
246 if ($padType === STR_PAD_BOTH) {
|
Chris@0
|
247 $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;
|
Chris@0
|
248
|
Chris@0
|
249 $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
|
Chris@0
|
250 $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2);
|
Chris@0
|
251 $lastStringRightLength += $lastStringLength % 2;
|
Chris@0
|
252
|
Chris@0
|
253 $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength);
|
Chris@0
|
254 $lastStringRight = $this->substr($padString, 0, $lastStringRightLength);
|
Chris@0
|
255
|
Chris@0
|
256 return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
|
Chris@0
|
257 . $input
|
Chris@0
|
258 . str_repeat($padString, $repeatCountRight) . $lastStringRight;
|
Chris@0
|
259 }
|
Chris@0
|
260
|
Chris@0
|
261 $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength);
|
Chris@0
|
262
|
Chris@0
|
263 if ($padType === STR_PAD_LEFT) {
|
Chris@0
|
264 return str_repeat($padString, $repeatCount) . $lastString . $input;
|
Chris@0
|
265 }
|
Chris@0
|
266
|
Chris@0
|
267 return $input . str_repeat($padString, $repeatCount) . $lastString;
|
Chris@0
|
268 }
|
Chris@0
|
269 }
|