LowPHPSniff.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. /**
  3. * PHPCompatibility, an external standard for PHP_CodeSniffer.
  4. *
  5. * @package PHPCompatibility
  6. * @copyright 2012-2019 PHPCompatibility Contributors
  7. * @license https://opensource.org/licenses/LGPL-3.0 LGPL3
  8. * @link https://github.com/PHPCompatibility/PHPCompatibility
  9. */
  10. namespace PHPCompatibility\Sniffs\Upgrade;
  11. use PHPCompatibility\Sniff;
  12. use PHPCompatibility\PHPCSHelper;
  13. use PHP_CodeSniffer_File as File;
  14. /**
  15. * Add a notification for users of low PHP versions.
  16. *
  17. * Originally PHPCompatibility supported PHP 5.1 and higher.
  18. * As of PHPCompatibility 8.0.0, support for PHP < 5.3 has been dropped.
  19. *
  20. * The intention is to drop support for PHP 5.3 in the (near) future.
  21. *
  22. * This sniff adds an explicit error/warning for users of the standard
  23. * using a PHP version below the recommended version.
  24. *
  25. * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/835
  26. *
  27. * @since 9.3.0
  28. */
  29. class LowPHPSniff extends Sniff
  30. {
  31. /**
  32. * The minimum supported PHP version.
  33. *
  34. * Users on PHP versions below this will see an ERROR message.
  35. *
  36. * @since 9.3.0
  37. *
  38. * @var string
  39. */
  40. const MIN_SUPPORTED_VERSION = '5.3';
  41. /**
  42. * The minimum recommended PHP version.
  43. *
  44. * Users on PHP versions below this will see a WARNING.
  45. *
  46. * @since 9.3.0
  47. *
  48. * @var string
  49. */
  50. const MIN_RECOMMENDED_VERSION = '5.4';
  51. /**
  52. * Keep track of whether this sniff needs to actually run.
  53. *
  54. * This will be set to `false` when either a high enough PHP
  55. * version is detected or once the error/warning has been thrown,
  56. * to make sure that the notice will only be thrown once per run.
  57. *
  58. * @since 9.3.0
  59. *
  60. * @var bool
  61. */
  62. private $examine = true;
  63. /**
  64. * Returns an array of tokens this test wants to listen for.
  65. *
  66. * @since 9.3.0
  67. *
  68. * @return array
  69. */
  70. public function register()
  71. {
  72. return array(
  73. \T_OPEN_TAG,
  74. );
  75. }
  76. /**
  77. * Processes this test, when one of its tokens is encountered.
  78. *
  79. * @since 9.3.0
  80. *
  81. * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
  82. * @param int $stackPtr The position of the current token in the
  83. * stack passed in $tokens.
  84. *
  85. * @return int|void Integer stack pointer to skip forward or void to continue
  86. * normal file processing.
  87. */
  88. public function process(File $phpcsFile, $stackPtr)
  89. {
  90. // Don't do anything if the warning has already been thrown or is not necessary.
  91. if ($this->examine === false) {
  92. return ($phpcsFile->numTokens + 1);
  93. }
  94. $phpVersion = phpversion();
  95. // Don't do anything if the PHPCS version used is above the minimum recommended version.
  96. if (version_compare($phpVersion, self::MIN_RECOMMENDED_VERSION, '>=')) {
  97. $this->examine = false;
  98. return ($phpcsFile->numTokens + 1);
  99. }
  100. if (version_compare($phpVersion, self::MIN_SUPPORTED_VERSION, '<')) {
  101. $isError = true;
  102. $message = 'IMPORTANT: Please be advised that the minimum PHP version the PHPCompatibility standard supports is %s. You are currently using PHP %s. Please upgrade your PHP installation. The recommended version of PHP for PHPCompatibility is %s or higher.';
  103. $errorCode = 'Unsupported_' . $this->stringToErrorCode(self::MIN_SUPPORTED_VERSION);
  104. $replacements = array(
  105. self::MIN_SUPPORTED_VERSION,
  106. $phpVersion,
  107. self::MIN_RECOMMENDED_VERSION,
  108. $errorCode,
  109. );
  110. } else {
  111. $isError = false;
  112. $message = 'IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP %s. Please upgrade your PHP installation to version %s or higher.';
  113. $errorCode = 'BelowRecommended_' . $this->stringToErrorCode(self::MIN_RECOMMENDED_VERSION);
  114. $replacements = array(
  115. self::MIN_RECOMMENDED_VERSION,
  116. $phpVersion,
  117. self::MIN_RECOMMENDED_VERSION,
  118. $errorCode,
  119. );
  120. }
  121. /*
  122. * Figure out the report width to determine how long the delimiter lines should be.
  123. *
  124. * This is not an exact calculation as there are a number of unknowns at the time the
  125. * notice is thrown (whether there are other notices for the file, whether those are
  126. * warnings or errors, whether there are auto-fixable issues etc).
  127. *
  128. * In other words, this is just an approximation to get a reasonably stable and
  129. * readable message layout format.
  130. *
  131. * {@internal
  132. * PHPCS has had some changes as to how the messages display over the years.
  133. * Most significantly in 2.4.0 it was attempted to solve an issue with messages
  134. * containing new lines. Unfortunately, that solution is buggy.
  135. * An improved version has been pulled upstream and will hopefully make it
  136. * into PHPCS 3.3.1/3.4.0.
  137. *
  138. * Anyway, this means that instead of new lines, delimiter lines will be used to improved
  139. * the readability of the (long) message.
  140. *
  141. * Also, as of PHPCS 2.2.0, the report width when using the `-s` option is 8 wider than
  142. * it should be. A patch for that is included in the same upstream PR.
  143. *
  144. * If/when the upstream PR has been merged and the minimum supported/recommended version
  145. * of PHPCompatibility would go beyond that, the below code should be adjusted.}
  146. */
  147. $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth');
  148. if (empty($reportWidth)) {
  149. $reportWidth = 80;
  150. }
  151. $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources');
  152. if ($showSources === true) {
  153. $reportWidth += 6;
  154. }
  155. $messageWidth = ($reportWidth - 15); // 15 is length of " # | WARNING | ".
  156. $delimiterLine = str_repeat('-', ($messageWidth));
  157. $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHP to your command or add <exclude name="PHPCompatibility.Upgrade.LowPHP.%s"/> to your custom ruleset. ';
  158. $thankYou = 'Thank you for using PHPCompatibility!';
  159. $message .= ' ' . $delimiterLine;
  160. $message .= ' ' . $disableNotice;
  161. $message .= ' ' . $delimiterLine;
  162. $message .= ' ' . $thankYou;
  163. $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements);
  164. $this->examine = false;
  165. }
  166. }