VersionConstraint.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Package\LinkConstraint;
  12. /**
  13. * Constrains a package link based on package version
  14. *
  15. * Version numbers must be compatible with version_compare
  16. *
  17. * @author Nils Adermann <naderman@naderman.de>
  18. */
  19. class VersionConstraint extends SpecificConstraint
  20. {
  21. private $operator;
  22. private $version;
  23. /**
  24. * Sets operator and version to compare a package with
  25. *
  26. * @param string $operator A comparison operator
  27. * @param string $version A version to compare to
  28. */
  29. public function __construct($operator, $version)
  30. {
  31. if ('=' === $operator) {
  32. $operator = '==';
  33. }
  34. if ('<>' === $operator) {
  35. $operator = '!=';
  36. }
  37. $this->operator = $operator;
  38. $this->version = $version;
  39. }
  40. public function versionCompare($a, $b, $operator, $compareBranches = false)
  41. {
  42. $aIsBranch = 'dev-' === substr($a, 0, 4);
  43. $bIsBranch = 'dev-' === substr($b, 0, 4);
  44. if ($aIsBranch && $bIsBranch) {
  45. return $operator == '==' && $a === $b;
  46. }
  47. // when branches are not comparable, we make sure dev branches never match anything
  48. if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
  49. return false;
  50. }
  51. return version_compare($a, $b, $operator);
  52. }
  53. /**
  54. * @param VersionConstraint $provider
  55. * @param bool $compareBranches
  56. * @return bool
  57. */
  58. public function matchSpecific(VersionConstraint $provider, $compareBranches = false)
  59. {
  60. static $cache = array();
  61. if (isset($cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches])) {
  62. return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches];
  63. }
  64. return $cache[$this->operator][$this->version][$provider->operator][$provider->version][$compareBranches] =
  65. $this->doMatchSpecific($provider, $compareBranches);
  66. }
  67. /**
  68. * @param VersionConstraint $provider
  69. * @param bool $compareBranches
  70. * @return bool
  71. */
  72. private function doMatchSpecific(VersionConstraint $provider, $compareBranches = false)
  73. {
  74. $noEqualOp = str_replace('=', '', $this->operator);
  75. $providerNoEqualOp = str_replace('=', '', $provider->operator);
  76. $isEqualOp = '==' === $this->operator;
  77. $isNonEqualOp = '!=' === $this->operator;
  78. $isProviderEqualOp = '==' === $provider->operator;
  79. $isProviderNonEqualOp = '!=' === $provider->operator;
  80. // '!=' operator is match when other operator is not '==' operator or version is not match
  81. // these kinds of comparisons always have a solution
  82. if ($isNonEqualOp || $isProviderNonEqualOp) {
  83. return !$isEqualOp && !$isProviderEqualOp
  84. || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
  85. }
  86. // an example for the condition is <= 2.0 & < 1.0
  87. // these kinds of comparisons always have a solution
  88. if ($this->operator != '==' && $noEqualOp == $providerNoEqualOp) {
  89. return true;
  90. }
  91. if ($this->versionCompare($provider->version, $this->version, $this->operator, $compareBranches)) {
  92. // special case, e.g. require >= 1.0 and provide < 1.0
  93. // 1.0 >= 1.0 but 1.0 is outside of the provided interval
  94. if ($provider->version == $this->version && $provider->operator == $providerNoEqualOp && $this->operator != $noEqualOp) {
  95. return false;
  96. }
  97. return true;
  98. }
  99. return false;
  100. }
  101. public function __toString()
  102. {
  103. return $this->operator.' '.$this->version;
  104. }
  105. }