protected static function replacePHP(&$php)
	{
		// Expression that matches a $node->getAttribute() call and captures its string argument
		$getAttribute = "\\\$node->getAttribute\\(('[^']+')\\)";

		// Expression that matches a single-quoted string literal
		$string       = "'(?:[^\\\\']|\\\\.)*+'";

		$replacements = [
			'$this->out' => '$html',

			// An attribute value escaped as ENT_NOQUOTES. We only need to unescape quotes
			'(htmlspecialchars\\(' . $getAttribute . ',' . ENT_NOQUOTES . '\\))'
				=> "str_replace('&quot;','\"',\$attributes[\$1])",

			// One or several attribute values escaped as ENT_COMPAT can be used as-is
			'(htmlspecialchars\\((' . $getAttribute . '(?:\\.' . $getAttribute . ')*),' . ENT_COMPAT . '\\))'
				=> function ($m) use ($getAttribute)
				{
					return preg_replace('(' . $getAttribute . ')', '$attributes[$1]', $m[1]);
				},

			// Character replacement can be performed directly on the escaped value provided that it
			// is then escaped as ENT_COMPAT and that replacements do not interfere with the escaping
			// of the characters &<>" or their representation &amp;&lt;&gt;&quot;
			'(htmlspecialchars\\(strtr\\(' . $getAttribute . ",('[^\"&\\\\';<>aglmopqtu]+'),('[^\"&\\\\'<>]+')\\)," . ENT_COMPAT . '\\))'
				=> 'strtr($attributes[$1],$2,$3)',

			// A comparison between two attributes. No need to unescape
			'(' . $getAttribute . '(!?=+)' . $getAttribute . ')'
				=> '$attributes[$1]$2$attributes[$3]',

			// A comparison between an attribute and a literal string. Rather than unescape the
			// attribute value, we escape the literal. This applies to comparisons using XPath's
			// contains() as well (translated to PHP's strpos())
			'(' . $getAttribute . '===(' . $string . '))s'
				=> function ($m)
				{
					return '$attributes[' . $m[1] . ']===' . htmlspecialchars($m[2], ENT_COMPAT);
				},

			'((' . $string . ')===' . $getAttribute . ')s'
				=> function ($m)
				{
					return htmlspecialchars($m[1], ENT_COMPAT) . '===$attributes[' . $m[2] . ']';
				},

			'(strpos\\(' . $getAttribute . ',(' . $string . ')\\)([!=]==(?:0|false)))s'
				=> function ($m)
				{
					return 'strpos($attributes[' . $m[1] . "]," . htmlspecialchars($m[2], ENT_COMPAT) . ')' . $m[3];
				},

			'(strpos\\((' . $string . '),' . $getAttribute . '\\)([!=]==(?:0|false)))s'
				=> function ($m)
				{
					return 'strpos(' . htmlspecialchars($m[1], ENT_COMPAT) . ',$attributes[' . $m[2] . '])' . $m[3];
				},

			// An attribute value used in an arithmetic comparison or operation does not need to be
			// unescaped. The same applies to empty(), isset() and conditionals
			'(' . $getAttribute . '(?=(?:==|[-+*])\\d+))'  => '$attributes[$1]',
			'(\\b(\\d+(?:==|[-+*]))' . $getAttribute . ')' => '$1$attributes[$2]',
			'(empty\\(' . $getAttribute . '\\))'           => 'empty($attributes[$1])',
			"(\\\$node->hasAttribute\\(('[^']+')\\))"      => 'isset($attributes[$1])',
			'if($node->attributes->length)'                => 'if($this->hasNonNullValues($attributes))',

			// In all other situations, unescape the attribute value before use
			'(' . $getAttribute . ')' => 'htmlspecialchars_decode($attributes[$1])'
		];

		foreach ($replacements as $match => $replace)
		{
			if ($replace instanceof Closure)
			{
				$php = preg_replace_callback($match, $replace, $php);
			}
			elseif ($match[0] === '(')
			{
				$php = preg_replace($match, $replace, $php);
			}
			else
			{
				$php = str_replace($match, $replace, $php);
			}
		}
	}
protected static function replacePHP(&$php)
	{
		// Expression that matches a $node->getAttribute() call and captures its string argument
		$getAttribute = "\\\$node->getAttribute\\(('[^']+')\\)";

		// Expression that matches a single-quoted string literal
		$string       = "'(?:[^\\\\']|\\\\.)*+'";

		$replacements = [
			'$this->out' => '$html',

			// An attribute value escaped as ENT_NOQUOTES. We only need to unescape quotes
			'(htmlspecialchars\\(' . $getAttribute . ',' . ENT_NOQUOTES . '\\))'
				=> "str_replace('&quot;','\"',\$attributes[\$1])",

			// One or several attribute values escaped as ENT_COMPAT can be used as-is
			'(htmlspecialchars\\((' . $getAttribute . '(?:\\.' . $getAttribute . ')*),' . ENT_COMPAT . '\\))'
				=> function ($m) use ($getAttribute)
				{
					return preg_replace('(' . $getAttribute . ')', '$attributes[$1]', $m[1]);
				},

			// Character replacement can be performed directly on the escaped value provided that it
			// is then escaped as ENT_COMPAT and that replacements do not interfere with the escaping
			// of the characters &<>" or their representation &amp;&lt;&gt;&quot;
			'(htmlspecialchars\\(strtr\\(' . $getAttribute . ",('[^\"&\\\\';<>aglmopqtu]+'),('[^\"&\\\\'<>]+')\\)," . ENT_COMPAT . '\\))'
				=> 'strtr($attributes[$1],$2,$3)',

			// A comparison between two attributes. No need to unescape
			'(' . $getAttribute . '(!?=+)' . $getAttribute . ')'
				=> '$attributes[$1]$2$attributes[$3]',

			// A comparison between an attribute and a literal string. Rather than unescape the
			// attribute value, we escape the literal. This applies to comparisons using XPath's
			// contains() as well (translated to PHP's strpos())
			'(' . $getAttribute . '===(' . $string . '))s'
				=> function ($m)
				{
					return '$attributes[' . $m[1] . ']===' . htmlspecialchars($m[2], ENT_COMPAT);
				},

			'((' . $string . ')===' . $getAttribute . ')s'
				=> function ($m)
				{
					return htmlspecialchars($m[1], ENT_COMPAT) . '===$attributes[' . $m[2] . ']';
				},

			'(strpos\\(' . $getAttribute . ',(' . $string . ')\\)([!=]==(?:0|false)))s'
				=> function ($m)
				{
					return 'strpos($attributes[' . $m[1] . "]," . htmlspecialchars($m[2], ENT_COMPAT) . ')' . $m[3];
				},

			'(strpos\\((' . $string . '),' . $getAttribute . '\\)([!=]==(?:0|false)))s'
				=> function ($m)
				{
					return 'strpos(' . htmlspecialchars($m[1], ENT_COMPAT) . ',$attributes[' . $m[2] . '])' . $m[3];
				},

			// An attribute value used in an arithmetic comparison or operation does not need to be
			// unescaped. The same applies to empty(), isset() and conditionals
			'(' . $getAttribute . '(?=(?:==|[-+*])\\d+))'  => '$attributes[$1]',
			'(\\b(\\d+(?:==|[-+*]))' . $getAttribute . ')' => '$1$attributes[$2]',
			'(empty\\(' . $getAttribute . '\\))'           => 'empty($attributes[$1])',
			"(\\\$node->hasAttribute\\(('[^']+')\\))"      => 'isset($attributes[$1])',
			'if($node->attributes->length)'                => 'if($this->hasNonNullValues($attributes))',

			// In all other situations, unescape the attribute value before use
			'(' . $getAttribute . ')' => 'htmlspecialchars_decode($attributes[$1])'
		];

		foreach ($replacements as $match => $replace)
		{
			if ($replace instanceof Closure)
			{
				$php = preg_replace_callback($match, $replace, $php);
			}
			elseif ($match[0] === '(')
			{
				$php = preg_replace($match, $replace, $php);
			}
			else
			{
				$php = str_replace($match, $replace, $php);
			}
		}
	}
protected static function replacePHP ( & $ php ) { // Expression that matches a $node->getAttribute() call and captures its string argument $ getAttribute = "\\\$node->getAttribute\\(('[^']+')\\)" ; // Expression that matches a single-quoted string literal $ string = "'(?:[^\\\\']|\\\\.)*+'" ; $ replacements = [ '$this->out' => '$html' , // An attribute value escaped as ENT_NOQUOTES. We only need to unescape quotes '(htmlspecialchars\\(' . $ getAttribute . ',' . ENT_NOQUOTES . '\\))' => "str_replace('&quot;','\"',\$attributes[\$1])" , // One or several attribute values escaped as ENT_COMPAT can be used as-is '(htmlspecialchars\\((' . $ getAttribute . '(?:\\.' . $ getAttribute . ')*),' . ENT_COMPAT . '\\))' => function ( $ m ) use ( $ getAttribute ) { return preg_replace ( '(' . $ getAttribute . ')' , '$attributes[$1]' , $ m [ 1 ] ) ; } , // Character replacement can be performed directly on the escaped value provided that it // is then escaped as ENT_COMPAT and that replacements do not interfere with the escaping // of the characters &<>" or their representation &amp;&lt;&gt;&quot; '(htmlspecialchars\\(strtr\\(' . $ getAttribute . ",('[^\"&\\\\';<>aglmopqtu]+'),('[^\"&\\\\'<>]+')\\)," . ENT_COMPAT . '\\))' => 'strtr($attributes[$1],$2,$3)' , // A comparison between two attributes. No need to unescape '(' . $ getAttribute . '(!?=+)' . $ getAttribute . ')' => '$attributes[$1]$2$attributes[$3]' , // A comparison between an attribute and a literal string. Rather than unescape the // attribute value, we escape the literal. This applies to comparisons using XPath's // contains() as well (translated to PHP's strpos()) '(' . $ getAttribute . '===(' . $ string . '))s' => function ( $ m ) { return '$attributes[' . $ m [ 1 ] . ']===' . htmlspecialchars ( $ m [ 2 ] , ENT_COMPAT ) ; } , '((' . $ string . ')===' . $ getAttribute . ')s' => function ( $ m ) { return htmlspecialchars ( $ m [ 1 ] , ENT_COMPAT ) . '===$attributes[' . $ m [ 2 ] . ']' ; } , '(strpos\\(' . $ getAttribute . ',(' . $ string . ')\\)([!=]==(?:0|false)))s' => function ( $ m ) { return 'strpos($attributes[' . $ m [ 1 ] . "]," . htmlspecialchars ( $ m [ 2 ] , ENT_COMPAT ) . ')' . $ m [ 3 ] ; } , '(strpos\\((' . $ string . '),' . $ getAttribute . '\\)([!=]==(?:0|false)))s' => function ( $ m ) { return 'strpos(' . htmlspecialchars ( $ m [ 1 ] , ENT_COMPAT ) . ',$attributes[' . $ m [ 2 ] . '])' . $ m [ 3 ] ; } , // An attribute value used in an arithmetic comparison or operation does not need to be // unescaped. The same applies to empty(), isset() and conditionals '(' . $ getAttribute . '(?=(?:==|[-+*])\\d+))' => '$attributes[$1]' , '(\\b(\\d+(?:==|[-+*]))' . $ getAttribute . ')' => '$1$attributes[$2]' , '(empty\\(' . $ getAttribute . '\\))' => 'empty($attributes[$1])' , "(\\\$node->hasAttribute\\(('[^']+')\\))" => 'isset($attributes[$1])' , 'if($node->attributes->length)' => 'if($this->hasNonNullValues($attributes))' , // In all other situations, unescape the attribute value before use '(' . $ getAttribute . ')' => 'htmlspecialchars_decode($attributes[$1])' ] ; foreach ( $ replacements as $ match => $ replace ) { if ( $ replace instanceof Closure ) { $ php = preg_replace_callback ( $ match , $ replace , $ php ) ; } elseif ( $ match [ 0 ] === '(' ) { $ php = preg_replace ( $ match , $ replace , $ php ) ; } else { $ php = str_replace ( $ match , $ replace , $ php ) ; } } }
Replace the PHP code used in a compiled template to be used by the Quick renderer

@param  string &$php
@return void
Replace the PHP code used in a compiled template to be used by the Quick renderer