|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2009-08-25 15:58 UTC] code-it at mail dot ru
 Description:
------------
wordwrapping suppose that
wordwrap(wordwrap($s,$n,$d),$n,$d) is equal to wordwrap($s,$n,$d) and yes, sometimes php works that way:
$s0 = 'a a a a a a a a';
$s1 = wordwrap($s0,7,'XX');
$s2 = wordwrap($s1,7,'XX');
gives $s1==$s2=='a a a aXXa a a a'
but if we add an extra space to the end of $s0, the result will be
'a a a aXXa a a aXX' != 'a a a aXXa a aXXaXX'
if we construct $s0 as (a )+a? we get $s1!=$s2 if and only if strlen($s0)%8==0. more, the diff between $s1 and $s2 every time is the same: trailing 'XXaXX' in $s2 instead of ' aXX' in $s1.
----------------------------
now lets take a look at the case of 1-char-length thing as the 3rd argument to wordwrap
$s0 = 'a a a a a a a a a a a'; // as above, $s0 is constructed as (a )+a?
$s1 = wordwrap($s0,5,'X');
$s2 = wordwrap($s1,5,'X');
here we only get $s1==$s2 having strlen($s0)<11!
this bug is related to line 828 in /php-src/branches/PHP_5_3/ext/standard/string.c?revision=287264:
current line: 	laststart = lastspace = current;
should be:		laststart = lastspace = current+1;
+1 is obviuos: if we found a breakchar in the string, we can forget about everything to the left of it INCLUDING itself and restart the whole algorythm at the NEXT character as the first character in our new string. so the very first `laststart = lastspace = 0;` to start becomes `laststart = lastspace = current+1;` to restart. this patch completely removes the strange behaviour.
when strlen(3rd argument to wordwrap)>1 another section of code works and the above patch doesnt affect it
Reproduce code:
---------------
<?
function f( $len, $breakstr, $n) {
	echo "\n-------- \$len=$len, \$breakstr='$breakstr', \$n=$n -------\n";
	for ( $i=1, $c = 'a ', $s0='', $x=1, $k=0; $i<=$n; $i++) {
		$s0 .= $c[$x^=1];
		$s1 = wordwrap($s0,$len,$breakstr);
		$s2 = wordwrap($s1,$len,$breakstr);
		if ($s1==$s2) {
			$k++;
			continue;
		}
		echo "strlen(\$s0)=$i -> FAIL\n";
	}
	if ($k==$n) {
		echo "passed all, no fails\n";
	}
}
f(5,'X',20);
f(7,'XX',50);
?>
Expected result:
----------------
-------- $len=5, $breakstr='X', $n=20 -------
passed all, no fails
-------- $len=7, $breakstr='XX', $n=50 -------
passed all, no fails
Actual result:
--------------
-------- $len=5, $breakstr='X', $n=20 -------
strlen($s0)=11 -> FAIL
strlen($s0)=12 -> FAIL
strlen($s0)=13 -> FAIL
strlen($s0)=14 -> FAIL
strlen($s0)=15 -> FAIL
strlen($s0)=16 -> FAIL
strlen($s0)=17 -> FAIL
strlen($s0)=18 -> FAIL
strlen($s0)=19 -> FAIL
strlen($s0)=20 -> FAIL
-------- $len=7, $breakstr='XX', $n=50 -------
strlen($s0)=8 -> FAIL
strlen($s0)=16 -> FAIL
strlen($s0)=24 -> FAIL
strlen($s0)=32 -> FAIL
strlen($s0)=40 -> FAIL
strlen($s0)=48 -> FAIL
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 01:00:01 2025 UTC | 
Thank you for your bug report. Your report is too long and too hard to understand. However, I did the best I could to make a simple script which reproduces the problem you describe and is more like real-life usage of wordwrap. <?php $lines = array( "The quick brown fox just", "jumped over the lazy dog", "which laid on the ground" ); $text = implode("\n", $lines); $wrapped = wordwrap($text, 24); echo "Expected:\n".$text."\n"; echo "Actual:\n".$wrapped."\n"; ?> Expected: The quick brown fox just jumped over the lazy dog which laid on the ground Actual: The quick brown fox just jumped over the lazy dog which laid on the ground