CompilingMatcher.php 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <?php
  2. /*
  3. * This file is part of composer/semver.
  4. *
  5. * (c) Composer <https://github.com/composer>
  6. *
  7. * For the full copyright and license information, please view
  8. * the LICENSE file that was distributed with this source code.
  9. */
  10. namespace Composer\Semver;
  11. use Composer\Semver\Constraint\Constraint;
  12. use Composer\Semver\Constraint\ConstraintInterface;
  13. /**
  14. * Helper class to evaluate constraint by compiling and reusing the code to evaluate
  15. */
  16. class CompilingMatcher
  17. {
  18. /**
  19. * @var array
  20. * @phpstan-var array<string, callable>
  21. */
  22. private static $compiledCheckerCache = array();
  23. /**
  24. * @var array
  25. * @phpstan-var array<string, bool>
  26. */
  27. private static $resultCache = array();
  28. /** @var bool */
  29. private static $enabled;
  30. /**
  31. * @phpstan-var array<Constraint::OP_*, Constraint::STR_OP_*>
  32. */
  33. private static $transOpInt = array(
  34. Constraint::OP_EQ => Constraint::STR_OP_EQ,
  35. Constraint::OP_LT => Constraint::STR_OP_LT,
  36. Constraint::OP_LE => Constraint::STR_OP_LE,
  37. Constraint::OP_GT => Constraint::STR_OP_GT,
  38. Constraint::OP_GE => Constraint::STR_OP_GE,
  39. Constraint::OP_NE => Constraint::STR_OP_NE,
  40. );
  41. /**
  42. * Clears the memoization cache once you are done
  43. *
  44. * @return void
  45. */
  46. public static function clear()
  47. {
  48. self::$resultCache = array();
  49. self::$compiledCheckerCache = array();
  50. }
  51. /**
  52. * Evaluates the expression: $constraint match $operator $version
  53. *
  54. * @param ConstraintInterface $constraint
  55. * @param int $operator
  56. * @phpstan-param Constraint::OP_* $operator
  57. * @param string $version
  58. *
  59. * @return mixed
  60. */
  61. public static function match(ConstraintInterface $constraint, $operator, $version)
  62. {
  63. $resultCacheKey = $operator.$constraint.';'.$version;
  64. if (isset(self::$resultCache[$resultCacheKey])) {
  65. return self::$resultCache[$resultCacheKey];
  66. }
  67. if (self::$enabled === null) {
  68. self::$enabled = !\in_array('eval', explode(',', (string) ini_get('disable_functions')), true);
  69. }
  70. if (!self::$enabled) {
  71. return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version));
  72. }
  73. $cacheKey = $operator.$constraint;
  74. if (!isset(self::$compiledCheckerCache[$cacheKey])) {
  75. $code = $constraint->compile($operator);
  76. self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return '.$code.';};');
  77. } else {
  78. $function = self::$compiledCheckerCache[$cacheKey];
  79. }
  80. return self::$resultCache[$resultCacheKey] = $function($version, strpos($version, 'dev-') === 0);
  81. }
  82. }