mirror of
https://github.com/processwire/processwire.git
synced 2025-08-14 10:45:54 +02:00
Add simple string diff markup generator to WireTextTools class, via diffMarkup() method
This commit is contained in:
@@ -854,6 +854,117 @@ class WireTextTools extends Wire {
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two arrays, return array of the changes with 'ins' and 'del' keys
|
||||
*
|
||||
* Based upon Paul Butler’s Simple Diff Algorithm v0.1 © 2007 (zlib/libpng) https://paulbutler.org
|
||||
*
|
||||
* @param array $oldArray
|
||||
* @param array $newArray
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
protected function diffArray(array $oldArray, array $newArray) {
|
||||
|
||||
$matrix = array();
|
||||
$maxLen = 0;
|
||||
$oldMax = 0;
|
||||
$newMax = 0;
|
||||
|
||||
foreach($oldArray as $oldKey => $oldValue){
|
||||
|
||||
$newKeys = array_keys($newArray, $oldValue);
|
||||
|
||||
foreach($newKeys as $newKey) {
|
||||
$len = 1;
|
||||
if(isset($matrix[$oldKey - 1][$newKey - 1])) {
|
||||
$len = $matrix[$oldKey - 1][$newKey - 1] + 1;
|
||||
}
|
||||
$matrix[$oldKey][$newKey] = $len;
|
||||
|
||||
if($len > $maxLen) {
|
||||
$maxLen = $len;
|
||||
$oldMax = $oldKey + 1 - $maxLen;
|
||||
$newMax = $newKey + 1 - $maxLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($maxLen == 0) {
|
||||
$result = array(
|
||||
array('del' => $oldArray, 'ins' => $newArray)
|
||||
);
|
||||
|
||||
} else {
|
||||
$result = array_merge(
|
||||
$this->diffArray(
|
||||
array_slice($oldArray, 0, $oldMax),
|
||||
array_slice($newArray, 0, $newMax)
|
||||
),
|
||||
array_slice($newArray, $newMax, $maxLen),
|
||||
$this->diffArray(
|
||||
array_slice($oldArray, $oldMax + $maxLen),
|
||||
array_slice($newArray, $newMax + $maxLen)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two strings ($old and $new) return a diff string in HTML markup
|
||||
*
|
||||
* @param string $old Old string value
|
||||
* @param string $new New string value
|
||||
* @param array $options Options to modify behavior:
|
||||
* - `ins` (string) Markup to use for diff insertions (default: `<ins>{out}</ins>`)
|
||||
* - `del` (string) Markup to use for diff deletions (default: `<del>{out}</del>`)
|
||||
* - `entityEncode` (bool): Entity encode values, other than added ins/del tags? (default=true)
|
||||
* - `split` (string): Regex used to split strings for parts to diff (default=`\s+`)
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function diffMarkup($old, $new, array $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'ins' => "<ins>{out}</ins>",
|
||||
'del' => "<del>{out}</del>",
|
||||
'entityEncode' => true,
|
||||
'split' => '\s+',
|
||||
);
|
||||
|
||||
/** @var Sanitizer $sanitizer */
|
||||
$sanitizer = $this->wire('sanitizer');
|
||||
list($old, $new) = array("$old", "$new"); // enforce as string
|
||||
$options = array_merge($defaults, $options);
|
||||
$oldArray = preg_split("!($options[split])!", $old, 0, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$newArray = preg_split("!($options[split])!", $new, 0, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$diffArray = $this->diffArray($oldArray, $newArray);
|
||||
list(,$delClose) = explode('{out}', $options['del'], 2);
|
||||
list($insOpen,) = explode('{out}', $options['ins'], 2);
|
||||
$out = '';
|
||||
|
||||
foreach($diffArray as $diff) {
|
||||
if(is_array($diff)) {
|
||||
foreach(array('del', 'ins') as $key) {
|
||||
if(empty($diff[$key])) continue;
|
||||
$diffStr = implode('', $diff[$key]);
|
||||
if($options['entityEncode']) $diffStr = $sanitizer->entities1($diffStr);
|
||||
$out .= str_replace('{out}', $diffStr, $options[$key]);
|
||||
}
|
||||
} else {
|
||||
$out .= ($options['entityEncode'] ? $sanitizer->entities1($diff) : $diff);
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($out, "$delClose$insOpen")) {
|
||||
// put a space between '</del><ins>' so that it is '</del> <ins>'
|
||||
$out = str_replace("$delClose$insOpen", "$delClose $insOpen", $out);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************
|
||||
* MULTIBYTE PHP STRING FUNCTIONS THAT FALLBACK WHEN MBSTRING NOT AVAILABLE
|
||||
|
Reference in New Issue
Block a user