PharInvocationCollection.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace TYPO3\PharStreamWrapper\Resolver;
  3. /*
  4. * This file is part of the TYPO3 project.
  5. *
  6. * It is free software; you can redistribute it and/or modify it under the terms
  7. * of the MIT License (MIT). For the full copyright and license information,
  8. * please read the LICENSE file that was distributed with this source code.
  9. *
  10. * The TYPO3 project - inspiring people to share!
  11. */
  12. use TYPO3\PharStreamWrapper\Collectable;
  13. class PharInvocationCollection implements Collectable
  14. {
  15. const UNIQUE_INVOCATION = 1;
  16. const UNIQUE_BASE_NAME = 2;
  17. const DUPLICATE_ALIAS_WARNING = 32;
  18. /**
  19. * @var PharInvocation[]
  20. */
  21. private $invocations = array();
  22. /**
  23. * @param PharInvocation $invocation
  24. * @return bool
  25. */
  26. public function has(PharInvocation $invocation)
  27. {
  28. return in_array($invocation, $this->invocations, true);
  29. }
  30. /**
  31. * @param PharInvocation $invocation
  32. * @param null|int $flags
  33. * @return bool
  34. */
  35. public function collect(PharInvocation $invocation, $flags = null)
  36. {
  37. if ($flags === null) {
  38. $flags = static::UNIQUE_INVOCATION | static::DUPLICATE_ALIAS_WARNING;
  39. }
  40. if ($invocation->getBaseName() === ''
  41. || $invocation->getAlias() === ''
  42. || !$this->assertUniqueBaseName($invocation, $flags)
  43. || !$this->assertUniqueInvocation($invocation, $flags)
  44. ) {
  45. return false;
  46. }
  47. if ($flags & static::DUPLICATE_ALIAS_WARNING) {
  48. $this->triggerDuplicateAliasWarning($invocation);
  49. }
  50. $this->invocations[] = $invocation;
  51. return true;
  52. }
  53. /**
  54. * @param callable $callback
  55. * @param bool $reverse
  56. * @return null|PharInvocation
  57. */
  58. public function findByCallback($callback, $reverse = false)
  59. {
  60. foreach ($this->getInvocations($reverse) as $invocation) {
  61. if (call_user_func($callback, $invocation) === true) {
  62. return $invocation;
  63. }
  64. }
  65. return null;
  66. }
  67. /**
  68. * Asserts that base-name is unique. This disallows having multiple invocations for
  69. * same base-name but having different alias names.
  70. *
  71. * @param PharInvocation $invocation
  72. * @param int $flags
  73. * @return bool
  74. */
  75. private function assertUniqueBaseName(PharInvocation $invocation, $flags)
  76. {
  77. if (!($flags & static::UNIQUE_BASE_NAME)) {
  78. return true;
  79. }
  80. return $this->findByCallback(
  81. function (PharInvocation $candidate) use ($invocation) {
  82. return $candidate->getBaseName() === $invocation->getBaseName();
  83. }
  84. ) === null;
  85. }
  86. /**
  87. * Asserts that combination of base-name and alias is unique. This allows having multiple
  88. * invocations for same base-name but having different alias names (for whatever reason).
  89. *
  90. * @param PharInvocation $invocation
  91. * @param int $flags
  92. * @return bool
  93. */
  94. private function assertUniqueInvocation(PharInvocation $invocation, $flags)
  95. {
  96. if (!($flags & static::UNIQUE_INVOCATION)) {
  97. return true;
  98. }
  99. return $this->findByCallback(
  100. function (PharInvocation $candidate) use ($invocation) {
  101. return $candidate->equals($invocation);
  102. }
  103. ) === null;
  104. }
  105. /**
  106. * Triggers warning for invocations with same alias and same confirmation state.
  107. *
  108. * @param PharInvocation $invocation
  109. * @see \TYPO3\PharStreamWrapper\PharStreamWrapper::collectInvocation()
  110. */
  111. private function triggerDuplicateAliasWarning(PharInvocation $invocation)
  112. {
  113. $sameAliasInvocation = $this->findByCallback(
  114. function (PharInvocation $candidate) use ($invocation) {
  115. return $candidate->isConfirmed() === $invocation->isConfirmed()
  116. && $candidate->getAlias() === $invocation->getAlias();
  117. },
  118. true
  119. );
  120. if ($sameAliasInvocation === null) {
  121. return;
  122. }
  123. trigger_error(
  124. sprintf(
  125. 'Alias %s cannot be used by %s, already used by %s',
  126. $invocation->getAlias(),
  127. $invocation->getBaseName(),
  128. $sameAliasInvocation->getBaseName()
  129. ),
  130. E_USER_WARNING
  131. );
  132. }
  133. /**
  134. * @param bool $reverse
  135. * @return PharInvocation[]
  136. */
  137. private function getInvocations($reverse = false)
  138. {
  139. if ($reverse) {
  140. return array_reverse($this->invocations);
  141. }
  142. return $this->invocations;
  143. }
  144. }