* @version 1.4.4 * @link http://aidanlister.com/repos/v/PHP_Highlight.php */ class PHP_Highlight { /** * Hold highlight colors * * Contains an associative array of token types and colours. * By default, it contains the colours as specified by php.ini * * For example, to change the colour of strings, use something * simular to $h->highlight['string'] = 'blue'; * * @var array * @access public */ var $highlight; /** * Things to be replaced for formatting or otherwise reasons * * The first element contains the match array, the second the replace * array. * * @var array * @access public */ var $replace = array( "\t" => ' ', ' ' => ' '); /** * Format of the link to the PHP manual page * * @var string * @access public */ var $manual = '%s'; /** * Format of the span tag to be wrapped around each token * * @var string * @access public */ var $span; /** * Hold the source * * @var string * @access private */ var $_source = false; /** * Hold plaintext keys * * An array of lines which are plaintext * * @var array * @access private */ var $_plaintextkeys = array(); /** * Constructor * * Populates highlight array * * @param bool $inline If inline styles rather than colors are to be used * @param bool $plaintext Do not format code outside PHP tags */ function PHP_Highlight($inline = false) { // Inline if ($inline === false) { // Default colours from php.ini $this->highlight = array( 'string' => ini_get('highlight.string'), 'comment' => ini_get('highlight.comment'), 'keyword' => ini_get('highlight.keyword'), 'bg' => ini_get('highlight.bg'), 'default' => ini_get('highlight.default'), 'html' => ini_get('highlight.html') ); $this->span = '%s'; } else { // Basic styles $this->highlight = array( 'string' => 'string', 'comment' => 'comment', 'keyword' => 'keyword', 'bg' => 'bg', 'default' => 'default', 'html' => 'html' ); $this->span = '%s'; } } /** * Load a file * * @access public * @param string $file The file to load * @return bool Returns TRUE */ function loadFile($file) { $this->_source = file_get_contents($file); return true; } /** * Load a string * * @access public * @param string $string The string to load * @return bool Returns TRUE */ function loadString($string) { $this->_source = $string; return true; } /** * Parse the loaded string into an array * Source is returned with the element key corresponding to the line number * * @access public * @param bool $funcref Reference functions to the PHP manual * @param bool $blocks Whether to ignore processing plaintext * @return array An array of highlighted source code */ function toArray($funcref = true, $blocks = false) { // Ensure source has been loaded if ($this->_source == false) { return false; } // Init $tokens = token_get_all($this->_source); $manual = $this->manual; $span = $this->span; $stringflag = false; $i = 0; $out = array(); $out[$i] = ''; // Loop through each token foreach ($tokens as $j => $token) { // Single char if (is_string($token)) { // Entering or leaving a quoted string if ($token === '"' && $tokens[$j - 1] !== '\\') { $stringflag = !$stringflag; $out[$i] .= sprintf($span, $this->highlight['string'], $token); } else { // Skip token2color check for speed $out[$i] .= sprintf($span, $this->highlight['keyword'], htmlspecialchars($token)); // Fix for bug #35655 list($tb, $val) = isset($tokens[$j - 1]) ? $tokens[$j - 1] : false; if (version_compare(PHP_VERSION, '5.1.2', '<') && $tb === T_END_HEREDOC) { $out[++$i] = ''; } } continue; } // Proper token list ($token, $value) = $token; // Make the value safe $value = htmlspecialchars($value); $value = str_replace( array_keys($this->replace), array_values($this->replace), $value); // Process if ($value === "\n") { // End this line and start the next $out[++$i] = ''; } else { // Function linking if ($funcref === true && $token === T_STRING) { // Look ahead 1, look ahead 2, and look behind 3 // For a function we expect T_FUNCTION T_STRING [T_WHITESPACE] ( if ((isset($tokens[$j + 1]) && $tokens[$j + 1] === '(' || isset($tokens[$j + 2]) && $tokens[$j + 2] === '(') && isset($tokens[$j - 3][0]) && $tokens[$j - 3][0] !== T_FUNCTION && function_exists($value)) { // Insert the manual link $value = sprintf($manual, $value, $value); } } // Explode token block $lines = explode("\n", $value); foreach ($lines as $jj => $line) { $line = trim($line); if ($line !== '') { // Uncomment for debugging //$out[$i] .= token_name($token); // Check for plaintext if ($blocks === true && $token === T_INLINE_HTML) { $this->_plaintextkeys[] = $i; $out[$i] .= $line; } else { // Highlight encased strings $colour = ($stringflag === true) ? $this->highlight['string'] : $this->_token2color($token); $out[$i] .= sprintf($span, $colour, $line); } } // Start a new line if (isset($lines[$jj + 1])) { $out[++$i] = ''; } } } } return $out; } /** * Convert the source to an ordered list. * Each line is wrapped in
$line";
}
$out .= "\n";
foreach ($source as $i => $line) {
$out .= ' ';
if ($linenum === true) {
$out .= sprintf($format, $i);
}
$out .= empty($line) ? ' ' : $line;
$out .= "
\n";
}
$out .= "\n";
if ($return === true) {
return $out;
} else {
echo $out;
}
}
/**
* Convert the source to formatted HTML blocks.
* Each line ends with > blocks.
*
* @access public
* @param bool $return Return rather than print the results
* @param bool $linenum Display line numbers
* @param string $format Specify format of line numbers displayed
* @param bool $reset Reset the line numbering each block
* @param bool $funcref Reference functions to the PHP manual
* @return string A HTML block of code
*/
function toHtmlBlocks($return = false, $linenum = false, $format = null, $reset = true, $funcref = true)
{
// Ensure source has been loaded
if ($this->_source == false) {
return false;
}
// Default line numbering
if ($linenum === true && $format === null) {
$format = '%03d ';
}
// Init
$source = $this->toArray($funcref, true);
$out = '';
$wasplain = true;
$k = 0;
// Loop through each line and decide which block to use
foreach ($source as $i => $line) {
// Empty line
if (empty($line)) {
if ($wasplain === true) {
$out .= ' ';
} else {
if (in_array($i+1, $this->_plaintextkeys)) {
$out .= "\n";
// Reset line numbers
if ($reset === true) {
$k = 0;
}
} else {
$out .= ' ';
// Add line number
if ($linenum === true) {
$out .= sprintf($format, ++$k);
}
}
}
// Plain text
} elseif (in_array($i, $this->_plaintextkeys)) {
if ($wasplain === false) {
$out .= "\n";
// Reset line numbers
if ($reset === true) {
$k = 0;
}
}
$wasplain = true;
$out .= str_replace(' ', ' ', $line);
// Code
} else {
if ($wasplain === true) {
$out .= "\n";
}
$wasplain = false;
$out .= ' ';
// Add line number
if ($linenum === true) {
$out .= sprintf($format, ++$k);
}
$out .= $line;
}
$out .= "
\n";
}
// Add final code tag
if ($wasplain === false) {
$out .= "\n";
}
// Output method
if ($return === true) {
return $out;
} else {
echo $out;
}
}
/**
* Assign a color based on the name of a token
*
* @access private
* @param int $token The token
* @return string The color of the token
*/
function _token2color($token)
{
switch ($token):
case T_CONSTANT_ENCAPSED_STRING:
return $this->highlight['string'];
break;
case T_INLINE_HTML:
return $this->highlight['html'];
break;
case T_COMMENT:
case T_DOC_COMMENT:
case T_ML_COMMENT:
return $this->highlight['comment'];
break;
case T_ABSTRACT:
case T_ARRAY:
case T_ARRAY_CAST:
case T_AS:
case T_BOOLEAN_AND:
case T_BOOLEAN_OR:
case T_BOOL_CAST:
case T_BREAK:
case T_CASE:
case T_CATCH:
case T_CLASS:
case T_CLONE:
case T_CONCAT_EQUAL:
case T_CONTINUE:
case T_DEFAULT:
case T_DOUBLE_ARROW:
case T_DOUBLE_CAST:
case T_ECHO:
case T_ELSE:
case T_ELSEIF:
case T_EMPTY:
case T_ENDDECLARE:
case T_ENDFOR:
case T_ENDFOREACH:
case T_ENDIF:
case T_ENDSWITCH:
case T_ENDWHILE:
case T_END_HEREDOC:
case T_EXIT:
case T_EXTENDS:
case T_FINAL:
case T_FOREACH:
case T_FUNCTION:
case T_GLOBAL:
case T_IF:
case T_INC:
case T_INCLUDE:
case T_INCLUDE_ONCE:
case T_INSTANCEOF:
case T_INT_CAST:
case T_ISSET:
case T_IS_EQUAL:
case T_IS_IDENTICAL:
case T_IS_NOT_IDENTICAL:
case T_IS_SMALLER_OR_EQUAL:
case T_NEW:
case T_OBJECT_CAST:
case T_OBJECT_OPERATOR:
case T_PAAMAYIM_NEKUDOTAYIM:
case T_PRIVATE:
case T_PROTECTED:
case T_PUBLIC:
case T_REQUIRE:
case T_REQUIRE_ONCE:
case T_RETURN:
case T_SL:
case T_SL_EQUAL:
case T_SR:
case T_SR_EQUAL:
case T_START_HEREDOC:
case T_STATIC:
case T_STRING_CAST:
case T_THROW:
case T_TRY:
case T_UNSET_CAST:
case T_VAR:
case T_WHILE:
return $this->highlight['keyword'];
break;
case T_CLOSE_TAG:
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
default:
return $this->highlight['default'];
endswitch;
}
}
?>