Index: branches/5.2.x/core/kernel/utility/logger.php =================================================================== diff -u -N -r16715 -r16754 --- branches/5.2.x/core/kernel/utility/logger.php (.../logger.php) (revision 16715) +++ branches/5.2.x/core/kernel/utility/logger.php (.../logger.php) (revision 16754) @@ -1,6 +1,6 @@ _logRecord['LogSourceFileLine'] = $line; } + $code_fragment = $this->getCodeFragment( + $this->_logRecord['LogSourceFilename'], + $this->_logRecord['LogSourceFileLine'] + ); + + if ( $code_fragment !== null ) { + $this->_logRecord['LogCodeFragment'] = $code_fragment; + } + return $this; } @@ -521,6 +530,14 @@ if ( isset($trace_info['args']) ) { $trace[$trace_index]['args'] = $this->_implodeObjects($trace_info['args']); } + + if ( isset($trace_info['file'], $trace_info['line']) ) { + $code_fragment = $this->getCodeFragment($trace_info['file'], $trace_info['line']); + + if ( $code_fragment !== null ) { + $trace[$trace_index]['code_fragment'] = $code_fragment; + } + } } $this->_logRecord['LogBacktrace'] = serialize($this->_removeObjectsFromTrace($trace)); @@ -529,6 +546,57 @@ } /** + * Returns a code fragment. + * + * @param string $file Filename. + * @param integer $line Line. + * + * @return string|null + */ + protected function getCodeFragment($file, $line) + { + static $path_filter_regexp; + + // Lazy detect path filter regexp, because it's not available at construction time. + if ( $path_filter_regexp === null ) { + $application =& kApplication::Instance(); + $path_filter_regexp = $application->ConfigValue('SystemLogCodeFragmentPathFilterRegExp'); + } + + if ( strpos($file, 'eval()\'d code') !== false + || ($path_filter_regexp && !preg_match($path_filter_regexp, $file)) + ) { + return null; + } + + $from_line = max(1, $line - 10); + $to_line = $line + 10; + + // Prefix example: ">>> 5. " or " 5. ". + $prefix_length = 4 + strlen($to_line) + 2; + + $cmd_parts = array( + 'sed', + '-n', + escapeshellarg($from_line . ',' . $to_line . 'p'), + escapeshellarg($file), + ); + $command = implode(' ', $cmd_parts); + + $ret = array(); + $code_fragment = preg_replace('/(\r\n|\n|\r)$/', '', shell_exec($command), 1); + + foreach ( explode("\n", $code_fragment) as $line_offset => $code_fragment_part ) { + $line_number = $from_line + $line_offset; + $line_indicator = $line_number == $line ? '>>> ' : ' '; + + $ret[] = str_pad($line_indicator . $line_number . '.', $prefix_length) . $code_fragment_part; + } + + return implode("\n", $ret); + } + + /** * Remove objects from trace, since before PHP 5.2.5 there wasn't possible to remove them initially * * @param Array $trace