NewPackFormatSniff.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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\ParameterValues;
  11. use PHPCompatibility\AbstractFunctionCallParameterSniff;
  12. use PHP_CodeSniffer_File as File;
  13. /**
  14. * Check for valid values for the `$format` passed to `pack()`.
  15. *
  16. * PHP version 5.4+
  17. *
  18. * @link https://www.php.net/manual/en/function.pack.php#refsect1-function.pack-changelog
  19. *
  20. * @since 9.0.0
  21. */
  22. class NewPackFormatSniff extends AbstractFunctionCallParameterSniff
  23. {
  24. /**
  25. * Functions to check for.
  26. *
  27. * @since 9.0.0
  28. *
  29. * @var array
  30. */
  31. protected $targetFunctions = array(
  32. 'pack' => true,
  33. );
  34. /**
  35. * List of new format character codes added to pack().
  36. *
  37. * @since 9.0.0
  38. *
  39. * @var array Regex pattern => Version array.
  40. */
  41. protected $newFormats = array(
  42. '`([Z])`' => array(
  43. '5.4' => false,
  44. '5.5' => true,
  45. ),
  46. '`([qQJP])`' => array(
  47. '5.6.2' => false,
  48. '5.6.3' => true,
  49. ),
  50. '`([eEgG])`' => array(
  51. '7.0.14' => false,
  52. '7.0.15' => true, // And 7.1.1.
  53. ),
  54. );
  55. /**
  56. * Do a version check to determine if this sniff needs to run at all.
  57. *
  58. * @since 9.0.0
  59. *
  60. * @return bool
  61. */
  62. protected function bowOutEarly()
  63. {
  64. return ($this->supportsBelow('7.1') === false);
  65. }
  66. /**
  67. * Process the parameters of a matched function.
  68. *
  69. * @since 9.0.0
  70. *
  71. * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
  72. * @param int $stackPtr The position of the current token in the stack.
  73. * @param string $functionName The token content (function name) which was matched.
  74. * @param array $parameters Array with information about the parameters.
  75. *
  76. * @return int|void Integer stack pointer to skip forward or void to continue
  77. * normal file processing.
  78. */
  79. public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters)
  80. {
  81. if (isset($parameters[1]) === false) {
  82. return;
  83. }
  84. $tokens = $phpcsFile->getTokens();
  85. $targetParam = $parameters[1];
  86. for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) {
  87. if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING
  88. && $tokens[$i]['code'] !== \T_DOUBLE_QUOTED_STRING
  89. ) {
  90. continue;
  91. }
  92. $content = $tokens[$i]['content'];
  93. if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) {
  94. $content = $this->stripVariables($content);
  95. }
  96. foreach ($this->newFormats as $pattern => $versionArray) {
  97. if (preg_match($pattern, $content, $matches) !== 1) {
  98. continue;
  99. }
  100. foreach ($versionArray as $version => $present) {
  101. if ($present === false && $this->supportsBelow($version) === true) {
  102. $phpcsFile->addError(
  103. 'Passing the $format(s) "%s" to pack() is not supported in PHP %s or lower. Found %s',
  104. $targetParam['start'],
  105. 'NewFormatFound',
  106. array(
  107. $matches[1],
  108. $version,
  109. $targetParam['raw'],
  110. )
  111. );
  112. continue 2;
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }