Factory.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of sebastian/comparator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\Comparator;
  11. use function array_unshift;
  12. final class Factory
  13. {
  14. private static ?Factory $instance = null;
  15. /**
  16. * @psalm-var list<Comparator>
  17. */
  18. private array $customComparators = [];
  19. /**
  20. * @psalm-var list<Comparator>
  21. */
  22. private array $defaultComparators = [];
  23. public static function getInstance(): self
  24. {
  25. if (self::$instance === null) {
  26. self::$instance = new self; // @codeCoverageIgnore
  27. }
  28. return self::$instance;
  29. }
  30. public function __construct()
  31. {
  32. $this->registerDefaultComparators();
  33. }
  34. public function getComparatorFor(mixed $expected, mixed $actual): Comparator
  35. {
  36. foreach ($this->customComparators as $comparator) {
  37. if ($comparator->accepts($expected, $actual)) {
  38. return $comparator;
  39. }
  40. }
  41. foreach ($this->defaultComparators as $comparator) {
  42. if ($comparator->accepts($expected, $actual)) {
  43. return $comparator;
  44. }
  45. }
  46. throw new RuntimeException('No suitable Comparator implementation found');
  47. }
  48. /**
  49. * Registers a new comparator.
  50. *
  51. * This comparator will be returned by getComparatorFor() if its accept() method
  52. * returns TRUE for the compared values. It has higher priority than the
  53. * existing comparators, meaning that its accept() method will be invoked
  54. * before those of the other comparators.
  55. */
  56. public function register(Comparator $comparator): void
  57. {
  58. array_unshift($this->customComparators, $comparator);
  59. $comparator->setFactory($this);
  60. }
  61. /**
  62. * Unregisters a comparator.
  63. *
  64. * This comparator will no longer be considered by getComparatorFor().
  65. */
  66. public function unregister(Comparator $comparator): void
  67. {
  68. foreach ($this->customComparators as $key => $_comparator) {
  69. if ($comparator === $_comparator) {
  70. unset($this->customComparators[$key]);
  71. }
  72. }
  73. }
  74. public function reset(): void
  75. {
  76. $this->customComparators = [];
  77. }
  78. private function registerDefaultComparators(): void
  79. {
  80. $this->registerDefaultComparator(new MockObjectComparator);
  81. $this->registerDefaultComparator(new DateTimeComparator);
  82. $this->registerDefaultComparator(new DOMNodeComparator);
  83. $this->registerDefaultComparator(new SplObjectStorageComparator);
  84. $this->registerDefaultComparator(new ExceptionComparator);
  85. $this->registerDefaultComparator(new ObjectComparator);
  86. $this->registerDefaultComparator(new ResourceComparator);
  87. $this->registerDefaultComparator(new ArrayComparator);
  88. $this->registerDefaultComparator(new NumericComparator);
  89. $this->registerDefaultComparator(new ScalarComparator);
  90. $this->registerDefaultComparator(new TypeComparator);
  91. }
  92. private function registerDefaultComparator(Comparator $comparator): void
  93. {
  94. $this->defaultComparators[] = $comparator;
  95. $comparator->setFactory($this);
  96. }
  97. }