4 * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
5 * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
6 * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
9 namespace Laminas\Stdlib\StringWrapper;
11 use Laminas\Stdlib\Exception;
12 use Laminas\Stdlib\StringUtils;
14 abstract class AbstractStringWrapper implements StringWrapperInterface
17 * The character encoding working on
20 protected $encoding = 'UTF-8';
23 * An optionally character encoding to convert to
26 protected $convertEncoding;
29 * Check if the given character encoding is supported by this wrapper
30 * and the character encoding to convert to is also supported.
32 * @param string $encoding
33 * @param string|null $convertEncoding
36 public static function isSupported($encoding, $convertEncoding = null)
38 $supportedEncodings = static::getSupportedEncodings();
40 if (! in_array(strtoupper($encoding), $supportedEncodings)) {
44 if ($convertEncoding !== null && ! in_array(strtoupper($convertEncoding), $supportedEncodings)) {
52 * Set character encoding working with and convert to
54 * @param string $encoding The character encoding to work with
55 * @param string|null $convertEncoding The character encoding to convert to
56 * @return StringWrapperInterface
58 public function setEncoding($encoding, $convertEncoding = null)
60 $supportedEncodings = static::getSupportedEncodings();
62 $encodingUpper = strtoupper($encoding);
63 if (! in_array($encodingUpper, $supportedEncodings)) {
64 throw new Exception\InvalidArgumentException(
65 'Wrapper doesn\'t support character encoding "' . $encoding . '"'
69 if ($convertEncoding !== null) {
70 $convertEncodingUpper = strtoupper($convertEncoding);
71 if (! in_array($convertEncodingUpper, $supportedEncodings)) {
72 throw new Exception\InvalidArgumentException(
73 'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"'
77 $this->convertEncoding = $convertEncodingUpper;
79 $this->convertEncoding = null;
81 $this->encoding = $encodingUpper;
87 * Get the defined character encoding to work with
90 * @throws Exception\LogicException If no encoding was defined
92 public function getEncoding()
94 return $this->encoding;
98 * Get the defined character encoding to convert to
100 * @return string|null
102 public function getConvertEncoding()
104 return $this->convertEncoding;
108 * Convert a string from defined character encoding to the defined convert encoding
111 * @param bool $reverse
112 * @return string|false
114 public function convert($str, $reverse = false)
116 $encoding = $this->getEncoding();
117 $convertEncoding = $this->getConvertEncoding();
118 if ($convertEncoding === null) {
119 throw new Exception\LogicException(
120 'No convert encoding defined'
124 if ($encoding === $convertEncoding) {
128 $from = $reverse ? $convertEncoding : $encoding;
129 $to = $reverse ? $encoding : $convertEncoding;
130 throw new Exception\RuntimeException(sprintf(
131 'Converting from "%s" to "%s" isn\'t supported by this string wrapper',
138 * Wraps a string to a given number of characters
140 * @param string $string
142 * @param string $break
144 * @return string|false
146 public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
148 $string = (string) $string;
149 if ($string === '') {
153 $break = (string) $break;
155 throw new Exception\InvalidArgumentException('Break string cannot be empty');
158 $width = (int) $width;
159 if ($width === 0 && $cut) {
160 throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
163 if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
164 return wordwrap($string, $width, $break, $cut);
167 $stringWidth = $this->strlen($string);
168 $breakWidth = $this->strlen($break);
171 $lastStart = $lastSpace = 0;
173 for ($current = 0; $current < $stringWidth; $current++) {
174 $char = $this->substr($string, $current, 1);
176 $possibleBreak = $char;
177 if ($breakWidth !== 1) {
178 $possibleBreak = $this->substr($string, $current, $breakWidth);
181 if ($possibleBreak === $break) {
182 $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
183 $current += $breakWidth - 1;
184 $lastStart = $lastSpace = $current + 1;
189 if ($current - $lastStart >= $width) {
190 $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
191 $lastStart = $current + 1;
194 $lastSpace = $current;
198 if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
199 $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
200 $lastStart = $lastSpace = $current;
204 if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
205 $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break;
206 $lastStart = $lastSpace = $lastSpace + 1;
211 if ($lastStart !== $current) {
212 $result .= $this->substr($string, $lastStart, $current - $lastStart);
219 * Pad a string to a certain length with another string
221 * @param string $input
222 * @param int $padLength
223 * @param string $padString
224 * @param int $padType
227 public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
229 if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
230 return str_pad($input, $padLength, $padString, $padType);
233 $lengthOfPadding = $padLength - $this->strlen($input);
234 if ($lengthOfPadding <= 0) {
238 $padStringLength = $this->strlen($padString);
239 if ($padStringLength === 0) {
243 $repeatCount = floor($lengthOfPadding / $padStringLength);
245 if ($padType === STR_PAD_BOTH) {
246 $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;
248 $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
249 $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2);
250 $lastStringRightLength += $lastStringLength % 2;
252 $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength);
253 $lastStringRight = $this->substr($padString, 0, $lastStringRightLength);
255 return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
257 . str_repeat($padString, $repeatCountRight) . $lastStringRight;
260 $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength);
262 if ($padType === STR_PAD_LEFT) {
263 return str_repeat($padString, $repeatCount) . $lastString . $input;
266 return $input . str_repeat($padString, $repeatCount) . $lastString;