Parser.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. }