Base for a static organization website

TidyHelper.php 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  4. *
  5. * Licensed under The MIT License
  6. * Redistributions of files must retain the above copyright notice.
  7. *
  8. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. * @link http://cakephp.org CakePHP(tm) Project
  10. * @since v 1.0 (22-Jun-2009)
  11. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  12. */
  13. App::uses('File', 'Utility');
  14. /**
  15. * TidyHelper class
  16. *
  17. * Passes html through tidy on the command line, and reports markup errors
  18. *
  19. * @uses AppHelper
  20. * @since v 1.0 (22-Jun-2009)
  21. */
  22. class TidyHelper extends AppHelper {
  23. /**
  24. * helpers property
  25. *
  26. * @var array
  27. */
  28. public $helpers = array('DebugKit.Toolbar');
  29. /**
  30. * results property
  31. *
  32. * @var mixed null
  33. */
  34. public $results = null;
  35. /**
  36. * Return a nested array of errors for the passed html string
  37. * Fudge the markup slightly so that the tag which is invalid is highlighted
  38. *
  39. * @param string $html ''
  40. * @param string $out ''
  41. * @return array
  42. */
  43. public function process($html = '', &$out = '') {
  44. $errors = $this->tidyErrors($html, $out);
  45. if (!$errors) {
  46. return array();
  47. }
  48. $result = array('Error' => array(), 'Warning' => array(), 'Misc' => array());
  49. $errors = explode("\n", $errors);
  50. $markup = explode("\n", $out);
  51. foreach ($errors as $error) {
  52. preg_match('@line (\d+) column (\d+) - (\w+): (.*)@', $error, $matches);
  53. if ($matches) {
  54. list($original, $line, $column, $type, $message) = $matches;
  55. $line = $line - 1;
  56. $string = '</strong>';
  57. if (isset($markup[$line - 1])) {
  58. $string .= h($markup[$line - 1]);
  59. }
  60. $string .= '<strong>' . h(@$markup[$line]) . '</strong>';
  61. if (isset($markup[$line + 1])) {
  62. $string .= h($markup[$line + 1]);
  63. }
  64. $string .= '</strong>';
  65. $result[$type][$string][] = h($message);
  66. } elseif ($error) {
  67. $message = $error;
  68. $result['Misc'][h($message)][] = h($message);
  69. }
  70. }
  71. $this->results = $result;
  72. return $result;
  73. }
  74. /**
  75. * report method
  76. *
  77. * Call process if a string is passed, or no prior results exist - and return the results using
  78. * the toolbar helper to generate a nested navigatable array
  79. *
  80. * @param mixed $html null
  81. * @return string
  82. */
  83. public function report($html = null) {
  84. if ($html) {
  85. $this->process($html);
  86. } elseif ($this->results === null) {
  87. $this->process($this->_View->output);
  88. }
  89. if (!$this->results) {
  90. return '<p>' . __d('debug_kit', 'No markup errors found') . '</p>';
  91. }
  92. foreach ($this->results as &$results) {
  93. foreach ($results as $type => &$messages) {
  94. foreach ($messages as &$message) {
  95. $message = html_entity_decode($message, ENT_COMPAT, Configure::read('App.encoding'));
  96. }
  97. }
  98. }
  99. return $this->Toolbar->makeNeatArray(array_filter($this->results), 0, 0, false);
  100. }
  101. /**
  102. * Run the html string through tidy, and return the (raw) errors. pass back a reference to the
  103. * normalized string so that the error messages can be linked to the line that caused them.
  104. *
  105. * @param string $in ''
  106. * @param string $out ''
  107. * @return string
  108. */
  109. public function tidyErrors($in = '', &$out = '') {
  110. $out = preg_replace('@>\s*<@s', ">\n<", $in);
  111. // direct access? windows etc
  112. if (function_exists('tidy_parse_string')) {
  113. $tidy = tidy_parse_string($out, array(), 'UTF8');
  114. $tidy->cleanRepair();
  115. $errors = $tidy->errorBuffer . "\n";
  116. return $errors;
  117. }
  118. // cli
  119. $File = new File(rtrim(TMP, DS) . DS . rand() . '.html', true);
  120. $File->write($out);
  121. $path = $File->pwd();
  122. $errors = $path . '.err';
  123. $this->_exec("tidy -eq -utf8 -f $errors $path");
  124. $File->delete();
  125. if (!file_exists($errors)) {
  126. return '';
  127. }
  128. $Error = new File($errors);
  129. $errors = $Error->read();
  130. $Error->delete();
  131. return $errors;
  132. }
  133. /**
  134. * exec method
  135. *
  136. * @param mixed $cmd
  137. * @param mixed $out null
  138. * @return boolean True if successful
  139. */
  140. protected function _exec($cmd, &$out = null) {
  141. if (DS === '/') {
  142. $_out = exec($cmd . ' 2>&1', $out, $return);
  143. } else {
  144. $_out = exec($cmd, $out, $return);
  145. }
  146. if (Configure::read('debug')) {
  147. $source = Debugger::trace(array('depth' => 1, 'start' => 2)) . "\n";
  148. //CakeLog::write('system_calls_' . date('Y-m-d'), "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
  149. //CakeLog::write('system_calls', "\n" . $source . Debugger::exportVar(compact('cmd','out','return')));
  150. }
  151. if ($return) {
  152. return false;
  153. }
  154. return $_out ? $_out : true;
  155. }
  156. }