Rule.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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\DependencyResolver;
  12. /**
  13. * @author Nils Adermann <naderman@naderman.de>
  14. */
  15. class Rule
  16. {
  17. const RULE_INTERNAL_ALLOW_UPDATE = 1;
  18. const RULE_JOB_INSTALL = 2;
  19. const RULE_JOB_REMOVE = 3;
  20. const RULE_PACKAGE_CONFLICT = 6;
  21. const RULE_PACKAGE_REQUIRES = 7;
  22. const RULE_PACKAGE_OBSOLETES = 8;
  23. const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
  24. const RULE_PACKAGE_SAME_NAME = 10;
  25. const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
  26. const RULE_LEARNED = 12;
  27. const RULE_PACKAGE_ALIAS = 13;
  28. protected $pool;
  29. protected $disabled;
  30. protected $literals;
  31. protected $type;
  32. protected $id;
  33. protected $job;
  34. protected $ruleHash;
  35. public function __construct(Pool $pool, array $literals, $reason, $reasonData, $job = null)
  36. {
  37. $this->pool = $pool;
  38. // sort all packages ascending by id
  39. sort($literals);
  40. $this->literals = $literals;
  41. $this->reason = $reason;
  42. $this->reasonData = $reasonData;
  43. $this->disabled = false;
  44. $this->job = $job;
  45. $this->type = -1;
  46. $this->ruleHash = substr(md5(implode(',', $this->literals)), 0, 5);
  47. }
  48. public function getHash()
  49. {
  50. return $this->ruleHash;
  51. }
  52. public function setId($id)
  53. {
  54. $this->id = $id;
  55. }
  56. public function getId()
  57. {
  58. return $this->id;
  59. }
  60. public function getJob()
  61. {
  62. return $this->job;
  63. }
  64. /**
  65. * Checks if this rule is equal to another one
  66. *
  67. * Ignores whether either of the rules is disabled.
  68. *
  69. * @param Rule $rule The rule to check against
  70. * @return bool Whether the rules are equal
  71. */
  72. public function equals(Rule $rule)
  73. {
  74. if ($this->ruleHash !== $rule->ruleHash) {
  75. return false;
  76. }
  77. if (count($this->literals) != count($rule->literals)) {
  78. return false;
  79. }
  80. for ($i = 0, $n = count($this->literals); $i < $n; $i++) {
  81. if ($this->literals[$i] !== $rule->literals[$i]) {
  82. return false;
  83. }
  84. }
  85. return true;
  86. }
  87. public function setType($type)
  88. {
  89. $this->type = $type;
  90. }
  91. public function getType()
  92. {
  93. return $this->type;
  94. }
  95. public function disable()
  96. {
  97. $this->disabled = true;
  98. }
  99. public function enable()
  100. {
  101. $this->disabled = false;
  102. }
  103. public function isDisabled()
  104. {
  105. return $this->disabled;
  106. }
  107. public function isEnabled()
  108. {
  109. return !$this->disabled;
  110. }
  111. public function getLiterals()
  112. {
  113. return $this->literals;
  114. }
  115. public function isAssertion()
  116. {
  117. return 1 === count($this->literals);
  118. }
  119. public function getPrettyString(array $installedMap = array())
  120. {
  121. $ruleText = '';
  122. foreach ($this->literals as $i => $literal) {
  123. if ($i != 0) {
  124. $ruleText .= '|';
  125. }
  126. $ruleText .= $this->pool->literalToPrettyString($literal, $installedMap);
  127. }
  128. switch ($this->reason) {
  129. case self::RULE_INTERNAL_ALLOW_UPDATE:
  130. return $ruleText;
  131. case self::RULE_JOB_INSTALL:
  132. return "Install command rule ($ruleText)";
  133. case self::RULE_JOB_REMOVE:
  134. return "Remove command rule ($ruleText)";
  135. case self::RULE_PACKAGE_CONFLICT:
  136. $package1 = $this->pool->literalToPackage($this->literals[0]);
  137. $package2 = $this->pool->literalToPackage($this->literals[1]);
  138. return $package1->getPrettyString().' conflicts with '.$package2->getPrettyString().'.';
  139. case self::RULE_PACKAGE_REQUIRES:
  140. $literals = $this->literals;
  141. $sourceLiteral = array_shift($literals);
  142. $sourcePackage = $this->pool->literalToPackage($sourceLiteral);
  143. $requires = array();
  144. foreach ($literals as $literal) {
  145. $requires[] = $this->pool->literalToPackage($literal);
  146. }
  147. $text = $this->reasonData->getPrettyString($sourcePackage);
  148. if ($requires) {
  149. $requireText = array();
  150. foreach ($requires as $require) {
  151. $requireText[] = $require->getPrettyString();
  152. }
  153. $text .= ' -> satisfiable by '.implode(', ', $requireText).'.';
  154. } else {
  155. $targetName = $this->reasonData->getTarget();
  156. // handle php extensions
  157. if (0 === strpos($targetName, 'ext-')) {
  158. $ext = substr($targetName, 4);
  159. $error = extension_loaded($ext) ? 'has the wrong version ('.phpversion($ext).') installed' : 'is missing from your system';
  160. $text .= ' -> the requested PHP extension '.$ext.' '.$error.'.';
  161. } elseif (0 === strpos($targetName, 'lib-')) {
  162. // handle linked libs
  163. $lib = substr($targetName, 4);
  164. $text .= ' -> the requested linked library '.$lib.' has the wrong version installed or is missing from your system, make sure to have the extension providing it.';
  165. } else {
  166. $text .= ' -> no matching package found.';
  167. }
  168. }
  169. return $text;
  170. case self::RULE_PACKAGE_OBSOLETES:
  171. return $ruleText;
  172. case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
  173. return $ruleText;
  174. case self::RULE_PACKAGE_SAME_NAME:
  175. $text = "Can only install one of: ";
  176. $packages = array();
  177. foreach ($this->literals as $i => $literal) {
  178. $packages[] = $this->pool->literalToPackage($literal)->getPrettyString();
  179. }
  180. return $text.implode(', ', $packages).'.';
  181. case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
  182. return $ruleText;
  183. case self::RULE_LEARNED:
  184. return 'Conclusion: '.$ruleText;
  185. case self::RULE_PACKAGE_ALIAS:
  186. return $ruleText;
  187. }
  188. }
  189. /**
  190. * Formats a rule as a string of the format (Literal1|Literal2|...)
  191. *
  192. * @return string
  193. */
  194. public function __toString()
  195. {
  196. $result = ($this->isDisabled()) ? 'disabled(' : '(';
  197. foreach ($this->literals as $i => $literal) {
  198. if ($i != 0) {
  199. $result .= '|';
  200. }
  201. $result .= $this->pool->literalToString($literal);
  202. }
  203. $result .= ')';
  204. return $result;
  205. }
  206. }