Blame | Last modification | View Log | RSS feed
<?php/*** Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)** Licensed under The MIT License* Redistributions of files must retain the above copyright notice.** @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)* @link http://cakephp.org CakePHP(tm) Project* @since v 1.0 (22-Jun-2009)* @license http://www.opensource.org/licenses/mit-license.php MIT License*/App::uses('File', 'Utility');/*** TidyHelper class** Passes html through tidy on the command line, and reports markup errors** @uses AppHelper* @since v 1.0 (22-Jun-2009)*/class TidyHelper extends AppHelper {/*** helpers property** @var array*/public $helpers = array('DebugKit.Toolbar');/*** results property** @var mixed null*/public $results = null;/*** Return a nested array of errors for the passed html string* Fudge the markup slightly so that the tag which is invalid is highlighted** @param string $html ''* @param string $out ''* @return array*/public function process($html = '', &$out = '') {$errors = $this->tidyErrors($html, $out);if (!$errors) {return array();}$result = array('Error' => array(), 'Warning' => array(), 'Misc' => array());$errors = explode("\n", $errors);$markup = explode("\n", $out);foreach ($errors as $error) {preg_match('@line (\d+) column (\d+) - (\w+): (.*)@', $error, $matches);if ($matches) {list($original, $line, $column, $type, $message) = $matches;$line = $line - 1;$string = '</strong>';if (isset($markup[$line - 1])) {$string .= h($markup[$line - 1]);}$string .= '<strong>' . h(@$markup[$line]) . '</strong>';if (isset($markup[$line + 1])) {$string .= h($markup[$line + 1]);}$string .= '</strong>';$result[$type][$string][] = h($message);} elseif ($error) {$message = $error;$result['Misc'][h($message)][] = h($message);}}$this->results = $result;return $result;}/*** report method** Call process if a string is passed, or no prior results exist - and return the results using* the toolbar helper to generate a nested navigatable array** @param mixed $html null* @return string*/public function report($html = null) {if ($html) {$this->process($html);} elseif ($this->results === null) {$this->process($this->_View->output);}if (!$this->results) {return '<p>' . __d('debug_kit', 'No markup errors found') . '</p>';}foreach ($this->results as &$results) {foreach ($results as $type => &$messages) {foreach ($messages as &$message) {$message = html_entity_decode($message, ENT_COMPAT, Configure::read('App.encoding'));}}}return $this->Toolbar->makeNeatArray(array_filter($this->results), 0, 0, false);}/*** Run the html string through tidy, and return the (raw) errors. pass back a reference to the* normalized string so that the error messages can be linked to the line that caused them.** @param string $in ''* @param string $out ''* @return string*/public function tidyErrors($in = '', &$out = '') {$out = preg_replace('@>\s*<@s', ">\n<", $in);// direct access? windows etcif (function_exists('tidy_parse_string')) {$tidy = tidy_parse_string($out, array(), 'UTF8');$tidy->cleanRepair();$errors = $tidy->errorBuffer . "\n";return $errors;}// cli$File = new File(rtrim(TMP, DS) . DS . rand() . '.html', true);$File->write($out);$path = $File->pwd();$errors = $path . '.err';$this->_exec("tidy -eq -utf8 -f $errors $path");$File->delete();if (!file_exists($errors)) {return '';}$Error = new File($errors);$errors = $Error->read();$Error->delete();return $errors;}/*** exec method** @param mixed $cmd* @param mixed $out null* @return boolean True if successful*/protected function _exec($cmd, &$out = null) {if (DS === '/') {$_out = exec($cmd . ' 2>&1', $out, $return);} else {$_out = exec($cmd, $out, $return);}if (Configure::read('debug')) {$source = Debugger::trace(array('depth' => 1, 'start' => 2)) . "\n";//CakeLog::write('system_calls_' . date('Y-m-d'), "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));//CakeLog::write('system_calls', "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));}if ($return) {return false;}return $_out ? $_out : true;}}