1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-15 11:14:12 +02:00

Some optimizations to WireMarkupRegions class, and add a hasField property to Inputfield modules when paired with a Fieldtype (similar to existing hasFieldtype property, except is a Field object rather than Fieldtype object).

This commit is contained in:
Ryan Cramer
2017-02-01 06:11:15 -05:00
parent 1886f132b5
commit 81adf00b8f
3 changed files with 89 additions and 39 deletions

View File

@@ -218,7 +218,7 @@ class Field extends WireData implements Saveable, Exportable {
* *
* @param string $key Property name to set * @param string $key Property name to set
* @param mixed $value * @param mixed $value
* @return $this * @return Field|WireData
* *
*/ */
public function set($key, $value) { public function set($key, $value) {
@@ -810,8 +810,9 @@ class Field extends WireData implements Saveable, Exportable {
$inputfield->attr('name', $this->name . $contextStr); $inputfield->attr('name', $this->name . $contextStr);
$inputfield->set('label', $this->label); $inputfield->set('label', $this->label);
// just in case an Inputfield needs to know it's Fieldtype context, or lack of it // just in case an Inputfield needs to know its Fieldtype/Field context, or lack of it
$inputfield->set('hasFieldtype', $this->type); $inputfield->set('hasFieldtype', $this->type);
$inputfield->set('hasField', $this);
// custom field settings // custom field settings
foreach($this->data as $key => $value) { foreach($this->data as $key => $value) {

View File

@@ -68,6 +68,7 @@
* @property string $requiredIf Optional conditions under which input is required (selector string). #pw-group-behavior * @property string $requiredIf Optional conditions under which input is required (selector string). #pw-group-behavior
* @property InputfieldWrapper|null $parent The parent InputfieldWrapper for this Inputfield or null if not set. #pw-internal * @property InputfieldWrapper|null $parent The parent InputfieldWrapper for this Inputfield or null if not set. #pw-internal
* @property null|bool|Fieldtype $hasFieldtype The Fieldtype using this Inputfield, or boolean false when known not to have a Fieldtype, or null when not known. #pw-group-other * @property null|bool|Fieldtype $hasFieldtype The Fieldtype using this Inputfield, or boolean false when known not to have a Fieldtype, or null when not known. #pw-group-other
* @property null|Field $hasField The Field object associated with this Inputfield, or or null when not applicable or not known. #pw-group-other
* @property bool|null $useLanguages When multi-language support active, can be set to true to make it provide inputs for each language, where supported (default=false). #pw-group-behavior * @property bool|null $useLanguages When multi-language support active, can be set to true to make it provide inputs for each language, where supported (default=false). #pw-group-behavior
* @property null|bool|int $entityEncodeLabel Set to boolean false to specifically disable entity encoding of field header/label (default=true). #pw-group-output * @property null|bool|int $entityEncodeLabel Set to boolean false to specifically disable entity encoding of field header/label (default=true). #pw-group-output
* @property null|bool $entityEncodeText Set to boolean false to specifically disable entity encoding for other text: description, notes, etc. (default=true). #pw-group-output * @property null|bool $entityEncodeText Set to boolean false to specifically disable entity encoding for other text: description, notes, etc. (default=true). #pw-group-output

View File

@@ -17,6 +17,12 @@ class WireMarkupRegions extends Wire {
* *
*/ */
const debug = false; const debug = false;
/**
* @var array
*
*/
protected $debugNotes = array();
/** /**
* HTML tag names that require no closing tag * HTML tag names that require no closing tag
@@ -87,7 +93,11 @@ class WireMarkupRegions extends Wire {
$findTag = $selectorInfo['findTag']; $findTag = $selectorInfo['findTag'];
$hasClass = $selectorInfo['hasClass']; $hasClass = $selectorInfo['hasClass'];
$regions = array(); $regions = array();
$removeMarkups = array(); $_markup = self::debug ? $markup : '';
if(self::debug) {
$options['debugNote'] = (empty($options['debugNote']) ? "" : "$options[debugNote] => ") . "find($selector)";
}
// strip out comments if markup isn't required to stay the same // strip out comments if markup isn't required to stay the same
if(!$options['exact']) $markup = $this->stripRegions('<!--', $markup); if(!$options['exact']) $markup = $this->stripRegions('<!--', $markup);
@@ -97,8 +107,11 @@ class WireMarkupRegions extends Wire {
$startPos = 0; $startPos = 0;
$whileCnt = 0; $whileCnt = 0;
$iterations = 0;
do { do {
$iterations++;
// find all the positions where each test appears // find all the positions where each test appears
$positions = array(); $positions = array();
foreach($tests as $str) { foreach($tests as $str) {
@@ -120,7 +133,7 @@ class WireMarkupRegions extends Wire {
$markupAfter = substr($markup, $pos); $markupAfter = substr($markup, $pos);
$openTagPos = strrpos($markupBefore, '<'); $openTagPos = strrpos($markupBefore, '<');
$closeOpenTagPos = strpos($markupAfter, '>'); $closeOpenTagPos = strpos($markupAfter, '>');
$startPos += $closeOpenTagPos; // for next iteration $startPos += $closeOpenTagPos; // for next iteration, if a continue occurs
// if the orders of "<" and ">" aren't what's expected in our markupBefore and markupAfter, then abort // if the orders of "<" and ">" aren't what's expected in our markupBefore and markupAfter, then abort
$testPos = strpos($markupAfter, '<'); $testPos = strpos($markupAfter, '<');
@@ -136,8 +149,8 @@ class WireMarkupRegions extends Wire {
if(!$tagInfo['action'] && $hasClass && !$this->hasClass($hasClass, $tagInfo['classes'])) continue; if(!$tagInfo['action'] && $hasClass && !$this->hasClass($hasClass, $tagInfo['classes'])) continue;
// build the region (everything in $markupAfter that starts after the ">") // build the region (everything in $markupAfter that starts after the ">")
$region = empty($tagInfo['close']) ? '' : substr($markupAfter, $closeOpenTagPos + 1); $regionMarkup = empty($tagInfo['close']) ? '' : substr($markupAfter, $closeOpenTagPos + 1);
$region = $this->getTagRegion($region, $tagInfo, $options); $region = $this->getTagRegion($regionMarkup, $tagInfo, $options);
if($options['single']) { if($options['single']) {
// single mode means we just return the markup // single mode means we just return the markup
@@ -148,17 +161,12 @@ class WireMarkupRegions extends Wire {
while(isset($regions[$pos])) $pos++; while(isset($regions[$pos])) $pos++;
$regions[$pos] = $region; $regions[$pos] = $region;
} }
if($options['leftover']) { $markup = trim(str_replace($region['html'], '', $markup));
$removeMarkups[] = $region['html']; if(empty($markup)) break;
} $startPos = 0;
} while(++$whileCnt < $options['max']); } while(++$whileCnt < $options['max']);
if(count($removeMarkups)) {
$markup = str_replace($removeMarkups, '', $markup);
}
/* /*
foreach($regions as $regionKey => $region) { foreach($regions as $regionKey => $region) {
@@ -167,17 +175,28 @@ class WireMarkupRegions extends Wire {
if(strpos($region['html'], $r['html']) !== false) { if(strpos($region['html'], $r['html']) !== false) {
$regions[$regionKey]['region'] = str_replace($r['html'], '', $region['region']); $regions[$regionKey]['region'] = str_replace($r['html'], '', $region['region']);
//$k = 'html'; //$k = 'html';
//echo "<pre>" . //$this->debugNotes[] =
// "\nREPLACE “" . htmlentities($r[$k]) . "”". // "\nREPLACE “" . htmlentities($r[$k]) . "”".
// "\nIN “" . htmlentities($region[$k]) . "”" . // "\nIN “" . htmlentities($region[$k]) . "”" .
// "\nRESULT “" . htmlentities($regions[$regionKey][$k]) . "”" . // "\nRESULT “" . htmlentities($regions[$regionKey][$k]) . "”";
// "\n</pre>";
} }
} }
} }
*/ */
if($options['leftover']) $regions["leftover"] = $markup; if($options['leftover']) $regions["leftover"] = trim($markup);
if(self::debug) {
$debugNote = "$options[debugNote] in [sm]" . $this->debugNoteStr($_markup, 50) . " …[/sm] => ";
$numRegions = 0;
foreach($regions as $key => $region) {
if($key == 'leftover') continue;
$debugNote .= "$region[name]#$region[pwid], ";
$numRegions++;
}
if(!$numRegions) $debugNote .= 'NONE';
$this->debugNotes[] = rtrim($debugNote, ", ") . " [sm](iterations=$iterations)[/sm]";
}
return $regions; return $regions;
} }
@@ -462,6 +481,14 @@ class WireMarkupRegions extends Wire {
if($verbose) { if($verbose) {
$verboseRegion['region'] = $region; $verboseRegion['region'] = $region;
$verboseRegion['html'] = $wrapRegion; $verboseRegion['html'] = $wrapRegion;
/*
if(self::debug) {
$debugNote = (isset($options['debugNote']) ? "$options[debugNote] => " : "") .
"getTagRegion() => $verboseRegion[name]#$verboseRegion[pwid] " .
"[sm]$verboseRegion[details][/sm]";
$this->debugNotes[] = $debugNote;
}
*/
return $verboseRegion; return $verboseRegion;
} }
@@ -927,6 +954,10 @@ class WireMarkupRegions extends Wire {
'exact' => true, 'exact' => true,
); );
if(self::debug) {
$findOptions['debugNote'] = "update.$options[action]($selector)";
}
$findRegions = $this->find($selector, $markup, $findOptions); $findRegions = $this->find($selector, $markup, $findOptions);
foreach($findRegions as $region) { foreach($findRegions as $region) {
@@ -1132,13 +1163,18 @@ class WireMarkupRegions extends Wire {
* *
* @param string $htmlDocument Document to populate regions to * @param string $htmlDocument Document to populate regions to
* @param string|array $htmlRegions Markup containing regions (or regions array from a find call) * @param string|array $htmlRegions Markup containing regions (or regions array from a find call)
* @param array $options
* @return int Number of updates made to $htmlDocument * @return int Number of updates made to $htmlDocument
* *
*/ */
public function populate(&$htmlDocument, $htmlRegions) { public function populate(&$htmlDocument, $htmlRegions, array $options = array()) {
static $recursionLevel = 0; static $recursionLevel = 0;
static $callQty = 0;
$recursionLevel++; $recursionLevel++;
$callQty++;
$leftoverMarkup = ''; $leftoverMarkup = '';
$debugLandmark = "<!--PW-REGION-DEBUG-->"; $debugLandmark = "<!--PW-REGION-DEBUG-->";
@@ -1153,7 +1189,8 @@ class WireMarkupRegions extends Wire {
} else if($this->hasRegions($htmlRegions)) { } else if($this->hasRegions($htmlRegions)) {
$regions = $this->find(".pw-*, id=", $htmlRegions, array( $regions = $this->find(".pw-*, id=", $htmlRegions, array(
'verbose' => true, 'verbose' => true,
'leftover' => true 'leftover' => true,
'debugNote' => (isset($options['debugNote']) ? "$options[debugNote] => " : "") . "populate($callQty)",
)); ));
$leftoverMarkup = trim($regions["leftover"]); $leftoverMarkup = trim($regions["leftover"]);
unset($regions["leftover"]); unset($regions["leftover"]);
@@ -1178,7 +1215,7 @@ class WireMarkupRegions extends Wire {
if(empty($region['action'])) $region['action'] = 'auto'; // replace if(empty($region['action'])) $region['action'] = 'auto'; // replace
if(empty($region['actionTarget'])) $region['actionTarget'] = $region['pwid']; // replace if(empty($region['actionTarget'])) $region['actionTarget'] = $region['pwid']; // replace
$xregion = $region; // $xregion = $region;
$action = $region['action']; $action = $region['action'];
$actionTarget = $region['actionTarget']; $actionTarget = $region['actionTarget'];
$regionHTML = $region['region']; $regionHTML = $region['region'];
@@ -1203,15 +1240,20 @@ class WireMarkupRegions extends Wire {
$debugAction = $region['action']; $debugAction = $region['action'];
if($debugAction == 'auto') $debugAction = $isNew ? 'insert' : 'replace'; if($debugAction == 'auto') $debugAction = $isNew ? 'insert' : 'replace';
if($debugAction == 'replace' && empty($region['close'])) $debugAction = 'attr-update'; if($debugAction == 'replace' && empty($region['close'])) $debugAction = 'attr-update';
$debugBytes = strlen($region['region']);
$pwid = empty($region['pwid']) ? $region['actionTarget'] : $region['pwid']; $pwid = empty($region['pwid']) ? $region['actionTarget'] : $region['pwid'];
$open = $region['open']; $open = $region['open'];
$openLen = strlen($open); $openLen = strlen($open);
if($openLen > 50) $open = substr($open, 0, 50) . '[small]... +' . ($openLen-50) . ' bytes[/small]>'; if($openLen > 50) $open = substr($open, 0, 30) . '[sm]... +' . ($openLen - 30) . ' bytes[/sm]>';
$debugRegionStart = substr($region['region'], 0, 50);
$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 " . $region['note'] = "$debugAction => #$pwid " .
($region['actionTarget'] != $pwid ? "(target=$region[actionTarget])" : "") . ($region['actionTarget'] != $pwid ? "(target=$region[actionTarget])" : "") .
"... $open" . ($region['close'] ? "[small]$debugBytes bytes[/small]$region[close]" : ""); "... $open" . ($region['close'] ? "[sm]{$debugRegion}[/sm]$region[close]" : "");
$regionNote = "$regionKey. $region[note]"; $regionNote = "$regionKey. $region[note]";
} else { } else {
$regionNote = ''; $regionNote = '';
@@ -1224,7 +1266,6 @@ class WireMarkupRegions extends Wire {
} else { } else {
// update the markup // update the markup
//echo "<pre>UPDATE('#$actionTarget', " . htmlentities($regionHTML) . ", mergeAttr=" . print_r($mergeAttr, true) . "</pre>";
$updates[] = array( $updates[] = array(
'actionTarget' => "#$actionTarget", 'actionTarget' => "#$actionTarget",
'regionHTML' => $regionHTML, 'regionHTML' => $regionHTML,
@@ -1252,21 +1293,22 @@ class WireMarkupRegions extends Wire {
if($debug) { if($debug) {
$bull = "\n"; $bull = "\n";
$n = $recursionLevel;
$leftoverBytes = strlen($leftoverMarkup); $leftoverBytes = strlen($leftoverMarkup);
$debugNotes = ""; // "\nProcessWire markup regions debug #$n "; $debugNotes = ""; // "\nProcessWire markup regions debug #$n ";
if(count($populatedNotes)) $debugNotes .= $bull . implode($bull, $populatedNotes); if(count($populatedNotes)) $debugNotes .= $bull . implode($bull, $populatedNotes);
if(count($rejectedNotes)) $debugNotes .= "\nSKIPPED: $bull" . implode($bull, $rejectedNotes); if(count($rejectedNotes)) $debugNotes .= "\nSKIPPED: $bull" . implode($bull, $rejectedNotes);
if($leftoverBytes) $debugNotes .= "\n $leftoverBytes non-region bytes skipped: $leftoverMarkup"; if($leftoverBytes) $debugNotes .= "\n $leftoverBytes non-region bytes skipped: [sm]{$leftoverMarkup}[/sm]";
$debugNotes .= "\n[small]" . Debug::timer($debugTimer) . " seconds[/small]"; if(count($this->debugNotes)) {
if(strpos($htmlDocument, $debugLandmark) !== false) { $debugNotes .= "\n---------------";
$debugNotes = $this->wire('sanitizer')->entities($debugNotes); foreach($this->debugNotes as $n => $s) {
$debugNotes = str_replace(array('[small]', '[/small]'), array('<small style="opacity:0.7">', '</small>'), $debugNotes); $debugNotes .= "\n$n. " . $this->debugNoteStr($s);
$debugNotes = "<pre class='pw-debug'>$debugNotes</pre>$debugLandmark"; }
$htmlDocument = str_replace($debugLandmark, $debugNotes, $htmlDocument);
} else {
$htmlDocument .= "<!--" . $debugNotes . "\n-->";
} }
$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 = "<pre class='pw-debug pw-region-debug'>$debugNotes</pre>$debugLandmark";
$htmlDocument = str_replace($debugLandmark, $debugNotes, $htmlDocument);
} else if($hasDebugLandmark) { } else if($hasDebugLandmark) {
$htmlDocument = str_replace($debugLandmark, '', $htmlDocument); $htmlDocument = str_replace($debugLandmark, '', $htmlDocument);
} }
@@ -1296,6 +1338,12 @@ class WireMarkupRegions extends Wire {
if(strpos($html, ' id=') === false && strpos($html, 'pw-') === false) return false; if(strpos($html, ' id=') === false && strpos($html, 'pw-') === false) return false;
return true; return true;
} }
protected function debugNoteStr($str, $maxLength = 0) {
$str = str_replace(array("\r", "\n", "\t"), ' ', $str);
while(strpos($str, ' ') !== false) $str= str_replace(' ', ' ', $str);
if($maxLength) $str = substr($str, 0, $maxLength);
return trim($str);
}
} }