Location: PHPKode > projects > Maintainable PHP Framework > vendor/Mad/Controller/Rescue/SourceExtractor.php
<?php
/**
 * @category   Mad
 * @package    Mad_Controller
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD
 */

/**
 * Extract source code to help examine errors.
 *
 * @category   Mad
 * @package    Mad_Controller
 * @copyright  (c) 2007-2009 Maintainable Software, LLC
 * @license    http://opensource.org/licenses/bsd-license.php BSD
 */
class Mad_Controller_Rescue_SourceExtractor
{
    /**
     * Given an exception, attempt to read the source code
     * and return a snippet.
     *
     * @param  Exception  $exception    Exception
     * @return stdClass                 stdClass(->line, ->source)
     */
    public function extractSourceFromException($exception)
    {
        $line = $exception->getLine();
        if (empty($line)) { return false; }

        $source = @file($exception->getFile());
        if (empty($source)) { return false; }
        
        $source = $this->linesAround($source, $line);
        $source = $this->convertTabsToSpaces($source);
        $source = $this->stripWhitespace($source);

        return (object)array('line' => $line, 'source' => $source);
    }

    /**
     * Given an array of $lines, start at $center and return
     * lines $above and $below.  These indexes start at 1, i.e.
     * the source is numbered starting at line 1 and not line 0.
     *
     * Returns an array where each key is a line number and
     * each value a line of source code.
     *
     * @param  array    $lines   All lines of source code
     * @param  integer  $center  Center line number (1..)
     * @param  integer  $above   Number of lines to extract above center
     * @param  integer  $below   Number of lines to extract below center
     * @return array             Array of extracted lines
     */
    public function linesAround($lines, $center, $above=3, $below=3)
    {
        $extracted = array();
        
        // extract source at error line and above
        $lbound = ($center - $above) -2;
        for ($i=$center; $i>0 && $i>$lbound; $i--) {
            $extracted[$i+1] = $lines[$i];
        }

        // extract source below error line
        $ubound = sizeof($lines) -1; 
        if ($center+$below <= $ubound) { $ubound = $center+$below; }
        
        for ($i=$center; $i<$ubound; $i++) {
            $extracted[$i+1] = $lines[$i];
        }

        // order lines of extracted source
        ksort($extracted);
        return $extracted;
    }

    /**
     * Given an array of $lines, replace any tab characters
     * with spaces computed from $tabstop.
     *
     * @param  array  $lines    Lines possibly containing tabs
     * @param  array  $tabstop  Tab stop
     * @return array            Lines with tabs replaced by spaces
     */
    public function convertTabsToSpaces($lines, $tabstop=4)
    {
        foreach ($lines as &$line) {
            while (($pos = strpos($line, "\t")) !== false) {
                $line = substr($line, 0, $pos)
                      . str_repeat(' ', $tabstop - $pos % $tabstop)
                      . substr($line, $pos +1);
            }
        }
        return $lines;
    }

    /**
     * Given an array of $lines, strip only the leading spaces
     * that are common to all lines so indentation is preserved.
     *
     * Also strip any trailing whitespace for all lines.
     *
     * @param  array  $lines    Lines with leading/trailing whitespace
     * @return array            Stripped lines
     */
    public function stripWhitespace($lines) {
        $leaders = array();
        foreach ($lines as &$l) {
            // right-trim line 
            $l = rtrim($l);
            if (! strlen($l)) { 
                continue; // skip blank line
            }

            // count leading spaces of line
            if (! preg_match('/^[ ]*/', $l, $matches)) {
                $leaders[] = 0;
                break;
            } else {
                $leaders[] = strlen($matches[0]);
            }
        }

        // strip leading spaces common to all lines
        $leading = min($leaders);
        foreach ($lines as &$l) { 
            $l = substr($l, $leading); 
        }
        
        return $lines;
    }
    
}
Return current item: Maintainable PHP Framework