Parser.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. /**
  3. * Parser Exception
  4. *
  5. * @package Less
  6. * @subpackage exception
  7. */
  8. class Less_Exception_Parser extends Exception {
  9. /**
  10. * The current file
  11. *
  12. * @var Less_ImportedFile
  13. */
  14. public $currentFile;
  15. /**
  16. * The current parser index
  17. *
  18. * @var integer
  19. */
  20. public $index;
  21. protected $input;
  22. protected $details = array();
  23. /**
  24. * Constructor
  25. *
  26. * @param string $message
  27. * @param Exception $previous Previous exception
  28. * @param integer $index The current parser index
  29. * @param Less_FileInfo|string $currentFile The file
  30. * @param integer $code The exception code
  31. */
  32. public function __construct( $message = null, Exception $previous = null, $index = null, $currentFile = null, $code = 0 ) {
  33. if ( PHP_VERSION_ID < 50300 ) {
  34. $this->previous = $previous;
  35. parent::__construct( $message, $code );
  36. } else {
  37. parent::__construct( $message, $code, $previous );
  38. }
  39. $this->currentFile = $currentFile;
  40. $this->index = $index;
  41. $this->genMessage();
  42. }
  43. protected function getInput() {
  44. if ( !$this->input && $this->currentFile && $this->currentFile['filename'] && file_exists( $this->currentFile['filename'] ) ) {
  45. $this->input = file_get_contents( $this->currentFile['filename'] );
  46. }
  47. }
  48. /**
  49. * Converts the exception to string
  50. *
  51. * @return string
  52. */
  53. public function genMessage() {
  54. if ( $this->currentFile && $this->currentFile['filename'] ) {
  55. $this->message .= ' in '.basename( $this->currentFile['filename'] );
  56. }
  57. if ( $this->index !== null ) {
  58. $this->getInput();
  59. if ( $this->input ) {
  60. $line = self::getLineNumber();
  61. $this->message .= ' on line '.$line.', column '.self::getColumn();
  62. $lines = explode( "\n", $this->input );
  63. $count = count( $lines );
  64. $start_line = max( 0, $line - 3 );
  65. $last_line = min( $count, $start_line + 6 );
  66. $num_len = strlen( $last_line );
  67. for ( $i = $start_line; $i < $last_line; $i++ ) {
  68. $this->message .= "\n".str_pad( $i + 1, $num_len, '0', STR_PAD_LEFT ).'| '.$lines[$i];
  69. }
  70. }
  71. }
  72. }
  73. /**
  74. * Returns the line number the error was encountered
  75. *
  76. * @return integer
  77. */
  78. public function getLineNumber() {
  79. if ( $this->index ) {
  80. // https://bugs.php.net/bug.php?id=49790
  81. if ( ini_get( "mbstring.func_overload" ) ) {
  82. return substr_count( substr( $this->input, 0, $this->index ), "\n" ) + 1;
  83. } else {
  84. return substr_count( $this->input, "\n", 0, $this->index ) + 1;
  85. }
  86. }
  87. return 1;
  88. }
  89. /**
  90. * Returns the column the error was encountered
  91. *
  92. * @return integer
  93. */
  94. public function getColumn() {
  95. $part = substr( $this->input, 0, $this->index );
  96. $pos = strrpos( $part, "\n" );
  97. return $this->index - $pos;
  98. }
  99. }