AdminLevelCollection.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the Geocoder package.
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. *
  8. * @license MIT License
  9. */
  10. namespace Geocoder\Model;
  11. use Geocoder\Exception\CollectionIsEmpty;
  12. use Geocoder\Exception\InvalidArgument;
  13. use Geocoder\Exception\OutOfBounds;
  14. use Traversable;
  15. /**
  16. * @author Giorgio Premi <giosh94mhz@gmail.com>
  17. */
  18. final class AdminLevelCollection implements \IteratorAggregate, \Countable
  19. {
  20. const MAX_LEVEL_DEPTH = 5;
  21. /**
  22. * @var AdminLevel[]
  23. */
  24. private $adminLevels;
  25. /**
  26. * @param AdminLevel[] $adminLevels
  27. */
  28. public function __construct(array $adminLevels = [])
  29. {
  30. $this->adminLevels = [];
  31. foreach ($adminLevels as $adminLevel) {
  32. $level = $adminLevel->getLevel();
  33. $this->checkLevel($level);
  34. if ($this->has($level)) {
  35. throw new InvalidArgument(sprintf('Administrative level %d is defined twice', $level));
  36. }
  37. $this->adminLevels[$level] = $adminLevel;
  38. }
  39. ksort($this->adminLevels, SORT_NUMERIC);
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function getIterator(): Traversable
  45. {
  46. return new \ArrayIterator($this->all());
  47. }
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function count(): int
  52. {
  53. return count($this->adminLevels);
  54. }
  55. /**
  56. * @return AdminLevel
  57. *
  58. * @throws CollectionIsEmpty
  59. */
  60. public function first(): AdminLevel
  61. {
  62. if ([] === $this->adminLevels) {
  63. throw new CollectionIsEmpty();
  64. }
  65. return reset($this->adminLevels);
  66. }
  67. /**
  68. * @param int $offset
  69. * @param int|null $length
  70. *
  71. * @return AdminLevel[]
  72. */
  73. public function slice(int $offset, int $length = null): array
  74. {
  75. return array_slice($this->adminLevels, $offset, $length, true);
  76. }
  77. /**
  78. * @return bool
  79. */
  80. public function has(int $level): bool
  81. {
  82. return isset($this->adminLevels[$level]);
  83. }
  84. /**
  85. * @return AdminLevel
  86. *
  87. * @throws \OutOfBoundsException
  88. * @throws InvalidArgument
  89. */
  90. public function get(int $level): AdminLevel
  91. {
  92. $this->checkLevel($level);
  93. if (!isset($this->adminLevels[$level])) {
  94. throw new InvalidArgument(sprintf('Administrative level %d is not set for this address', $level));
  95. }
  96. return $this->adminLevels[$level];
  97. }
  98. /**
  99. * @return AdminLevel[]
  100. */
  101. public function all(): array
  102. {
  103. return $this->adminLevels;
  104. }
  105. /**
  106. * @param int $level
  107. *
  108. * @throws \OutOfBoundsException
  109. */
  110. private function checkLevel(int $level)
  111. {
  112. if ($level <= 0 || $level > self::MAX_LEVEL_DEPTH) {
  113. throw new OutOfBounds(sprintf('Administrative level should be an integer in [1,%d], %d given', self::MAX_LEVEL_DEPTH, $level));
  114. }
  115. }
  116. }