It seems the regex used to search the block doesn't work with a template we use, the problem seems to be in relation with the lazy quantifiers, large strings and PHP v7.3 and superior, it works well with PHP v7.2.
public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null)
$idx_tag = mb_strpos($this->tempDocumentMainPart, '${'.$blockname.'}');
if ( $idx_tag === false )
return null;
$idx_start = mb_strrpos(mb_substr($this->tempDocumentMainPart, 0, $idx_tag), '<w:p ' );
$idx_end = mb_strpos( $this->tempDocumentMainPart, '${/'.$blockname.'}', $idx_tag);
if ( $idx_start === false || $idx_end === false )
return null;
$idx_end = mb_strpos($this->tempDocumentMainPart, '</w:p>', $idx_end);
if ( $idx_end === false )
return null;
$idx_end += 6;
$what = mb_substr($this->tempDocumentMainPart, $idx_start, $idx_end - $idx_start);
// --- //
$idx_content_start = mb_strpos($what, 'p>');
$idx_content_end = mb_strrpos($what, '<w:p ');
if ( $idx_content_start === false || $idx_content_end === false )
return null;
$idx_content_start += 2;
$xmlBlock = mb_substr($what, $idx_content_start, $idx_content_end - $idx_content_start);
// --- //
if ( $replace )
$by = array();
if ( $indexVariables )
$by = $this->indexClonedVariables($clones, $xmlBlock);
elseif ( $variableReplacements !== null && is_array($variableReplacements) )
$by = $this->replaceClonedVariables($variableReplacements, $xmlBlock);
for ( $i = 1 ; $i <= $clones ; $i++ )
$by[] = $xmlBlock;
$by = implode('', $by);
$this->tempDocumentMainPart = str_replace($what, $by, $this->tempDocumentMainPart);
return $xmlBlock;
cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.
Increasing pcre.backtrack_limit fixes this.
Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)
PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor
cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.
Increasing pcre.backtrack_limit fixes this.
Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)
PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor
This worked, although had to keep increasing the limit... Might need to also check for a newer version of PHPOffice. But Thanks for the quick fix in my case!
cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.
Increasing pcre.backtrack_limit fixes this.
Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)
PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor
This works fine for me on PHP 5.6+, i added ini_set("pcre.backtrack_limit", "2000000"); at the beggining of cloneBlock function and voilà.
p.s. (still had to max out the limit for larger docx)