1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 09:44:38 +02:00

Add 2nd pass support to Markup Regions, so that a region added in 1st pass can be manipulated by commands in the 2nd pass. Also, some optimizations to region hints, and debug mode improvements.

This commit is contained in:
Ryan Cramer
2017-08-02 10:56:26 -04:00
parent a1e1f25dff
commit fa1ff60b97

View File

@@ -84,7 +84,7 @@ class WireMarkupRegions extends Wire {
* - `leftover` (bool): Specify true if you want to return a "leftover" key in return value with leftover markup.
* @return array Returns one of the following:
* - Associative array of [ 'id' => 'markup' ] when finding specific attributes or #id attributes.
* - Regular array of markup regions when finding region shaving a specific class attribute.
* - Regular array of markup regions when finding regions having a specific class attribute.
* - Associative array of verbose information when the verbose option is used.
* @throws WireException if given invalid $find string
*
@@ -498,7 +498,14 @@ class WireMarkupRegions extends Wire {
'html' => '', // region with wrapping tags
);
if($tagInfo['pwid']) $tagID = $tagInfo['pwid'];
else if(!empty($tagInfo['id'])) $tagID = $tagInfo['id'];
else if(!empty($tagInfo['attrs']['id'])) $tagID = $tagInfo['attrs']['id'];
else if(!empty($tagInfo['actionTarget'])) $tagID = $tagInfo['actionTarget'];
else $tagID = '';
$selfClose = empty($tagInfo['close']);
$closeHint = "$tagInfo[close]<!--#$tagID-->";
$closeQty = $selfClose ? 1 : substr_count($region, $tagInfo['close']);
if(!$closeQty) {
@@ -508,19 +515,17 @@ class WireMarkupRegions extends Wire {
} else if($selfClose) {
$region = '';
if($verbose) $verboseRegion['details'] = 'Self closing tag (empty region)';
} else if($tagID && false !== ($pos = strpos($region, $closeHint))) {
// close tag indicates what it closes, i.e. “</div><!--#content-->”
$region = substr($region, 0, $pos);
$tagInfo['close'] = $closeHint;
if($verbose) $verboseRegion['details'] = "Fast match with HTML comment hint";
} else if($closeQty === 1) {
// just one close tag present, making our job easy
$region = substr($region, 0, strrpos($region, $tagInfo['close']));
if($verbose) {
$verboseRegion['details'] = 'Only 1 possible closing tag: ' . $tagInfo['close'];
}
} else if($tagInfo['pwid'] && false !== ($pos = strpos($region, "$tagInfo[close]<!--#$tagInfo[pwid]-->"))) {
// close tag indicates what it closes, i.e. “</div><!--#content-->”
$region = substr($region, 0, $pos);
$tagInfo['close'] = "$tagInfo[close]<!--#$tagInfo[pwid]-->";
if($verbose) $verboseRegion['details'] = "Fast match with HTML comment hint";
if($verbose) $verboseRegion['details'] = "Only 1 possible closing tag: $tagInfo[close]";
} else {
// multiple close tags present, must figure out which is the right one
@@ -1293,6 +1298,7 @@ class WireMarkupRegions extends Wire {
$leftoverMarkup = '';
} else if($this->hasRegions($htmlRegions)) {
$htmlRegions = $this->stripRegions('<!--', $htmlRegions);
$selector = $options['useClassActions'] ? ".pw-*, id=" : "[pw-action], id=";
$regions = $this->find($selector, $htmlRegions, array(
'verbose' => true,
@@ -1356,17 +1362,21 @@ class WireMarkupRegions extends Wire {
$open = $region['open'];
$openLen = strlen($open);
if($openLen > 50) $open = substr($open, 0, 30) . '[sm]... +' . ($openLen - 30) . ' bytes[/sm]>';
$debugRegionStart = substr($region['region'], 0, 50);
$debugRegionStart = "[sm]" . trim(substr($region['region'], 0, 80));
$pos = strrpos($debugRegionStart, '>');
if($pos) $debugRegionStart = substr($debugRegionStart, 0, $pos+1);
$debugRegionEnd = substr($region['region'], -30);
$pos = strpos($debugRegionEnd, '</');
if($pos !== false) $debugRegionEnd = substr($debugRegionEnd, $pos);
$debugRegion = $this->debugNoteStr("$debugRegionStart ... $debugRegionEnd");
$region['note'] = "$debugAction => #$pwid " .
$debugRegionStart .= " … [b]" . strlen($region['html']) . " bytes[/b][/sm]";
//$debugRegionEnd = substr($region['region'], -30);
//$pos = strpos($debugRegionEnd, '</');
//if($pos !== false) $debugRegionEnd = substr($debugRegionEnd, $pos);
$region['note'] = strtoupper($debugAction) . " [b]#{$pwid}[/b] " .
($region['actionTarget'] != $pwid ? "(target=$region[actionTarget])" : "") .
"... $open" . ($region['close'] ? "[sm]{$debugRegion}[/sm]$region[close]" : "");
$regionNote = "$regionKey. $region[note]";
"[sm]with[/sm] $open";
if($region['close']) {
$region['note'] .= $this->debugNoteStr($debugRegionStart) . $region['close'];
}
$regionNote = $region['note']; // [sm](position=$regionKey)[/sm]";
} else {
$regionNote = '';
}
@@ -1384,12 +1394,10 @@ class WireMarkupRegions extends Wire {
'action' => $action,
'mergeAttr' => $mergeAttr,
);
/*
$htmlDocument = $this->update("#$actionTarget", $regionHTML, $htmlDocument, array(
'action' => $action,
'mergeAttr' => $mergeAttr,
));
*/
if(is_string($htmlRegions)) {
// remove region markup from $htmlRegions so we can later determine whats left
$htmlRegions = str_replace($region['html'], '', $htmlRegions);
}
$populatedNotes[] = $regionNote;
$numUpdates++;
}
@@ -1402,23 +1410,37 @@ class WireMarkupRegions extends Wire {
));
}
$htmlRegions = trim($htmlRegions);
if($debug) {
$bull = "\n";
$leftoverBytes = strlen($leftoverMarkup);
$debugNotes = ""; // "\nProcessWire markup regions debug #$n ";
if(count($populatedNotes)) $debugNotes .= $bull . implode($bull, $populatedNotes);
if(count($rejectedNotes)) $debugNotes .= "\nSKIPPED: $bull" . implode($bull, $rejectedNotes);
if($leftoverBytes) $debugNotes .= "\n $leftoverBytes non-region bytes skipped: [sm]{$leftoverMarkup}[/sm]";
if(count($this->debugNotes)) {
$debugNotes .= "\n---------------";
foreach($this->debugNotes as $n => $s) {
$debugNotes .= "\n$n. " . $this->debugNoteStr($s);
$htmlRegionsLen = strlen($htmlRegions);
$debugNotes = array();
if($recursionLevel > 1) $debugNotes[] = "PASS: $recursionLevel";
if(count($populatedNotes)) $debugNotes = array_merge($debugNotes, $populatedNotes); // implode($bull, $populatedNotes);
if(count($rejectedNotes)) foreach($rejectedNotes as $note) $debugNotes[] = "SKIPPED: $note";
if($leftoverBytes) $debugNotes[] = "$leftoverBytes non-region bytes skipped: [sm]{$leftoverMarkup}[/sm]";
if($htmlRegionsLen) {
if($recursionLevel > 1) {
$debugNotes[] = "$htmlRegionsLen HTML-region bytes found no home after 2nd pass: [sm]{$htmlRegions}[/sm]";
} else if($this->hasRegions($htmlRegions)) {
$debugNotes[] = "$htmlRegionsLen HTML-region bytes remaining for 2nd pass: [sm]{$htmlRegions}[/sm]";
} else {
$debugNotes[] = "$htmlRegionsLen HTML bytes remaining, but no regions present: [sm]{$htmlRegions}[/sm]";
}
}
if(count($this->debugNotes)) {
$debugNotes[] = "---------------";
foreach($this->debugNotes as $n => $s) {
$debugNotes[] = $this->debugNoteStr($s);
}
}
if(!count($debugNotes)) $debugNotes[] = "Nothing found";
$debugNotes = "" . implode("\n", $debugNotes);
$debugNotes = $this->wire('sanitizer')->entities($debugNotes);
$debugNotes .= "\n[sm]" . Debug::timer($debugTimer) . " seconds[/sm]";
$debugNotes = str_replace(array('[sm]', '[/sm]'), array('<small style="opacity:0.7">', '</small>'), $debugNotes);
$debugNotes = str_replace(array('[b]', '[/b]'), array('<strong>', '</strong>'), $debugNotes);
$debugNotes = "<pre class='pw-debug pw-region-debug'>$debugNotes</pre>$debugLandmark";
$htmlDocument = str_replace($debugLandmark, $debugNotes, $htmlDocument);
} else if($hasDebugLandmark) {
@@ -1429,7 +1451,12 @@ class WireMarkupRegions extends Wire {
// see if they can be populated now
$numUpdates += $this->populate($htmlDocument, $xregions, $options);
}
if($recursionLevel === 1 && strlen($htmlRegions) && $this->hasRegions($htmlRegions)) {
// see if more regions can be pulled from leftover $htmlRegions
$numUpdates += $this->populate($htmlDocument, $htmlRegions, $options);
}
// remove region tags and pw-id attributes
if($recursionLevel === 1 && $this->removeRegionTags($htmlDocument)) $numUpdates++;
@@ -1481,6 +1508,29 @@ class WireMarkupRegions extends Wire {
if(strpos($html, ' id=') === false && strpos($html, 'pw-') === false) return false;
return true;
}
/**
* Does the given HTML markup have references to any pw-actions?
*
* Note: not currently used by this class.
*
* @param string $html
* @return bool
*
*/
public function hasRegionActions(&$html) {
$has = false;
foreach($this->actions as $action) {
if(strpos($html, "pw-$action") !== false) {
// found pw-action, now perform a more thorough check
if(preg_match('![="\'\s]pw-' . $action . '(?:["\'\s=][^<>]*>|>)!', $html)) {
$has = true;
break;
}
}
}
return $has;
}
protected function debugNoteStr($str, $maxLength = 0) {
$str = str_replace(array("\r", "\n", "\t"), ' ', $str);