Test Setup Failed
Push — master ( 480f5e...83b6f9 )
by Denis
01:50
created

Generator   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 203
rs 10
c 0
b 0
f 0
wmc 26

11 Methods

Rating   Name   Duplication   Size   Complexity  
A makeAddresses() 0 16 4
A setCities() 0 11 3
A getCityNames() 0 3 1
A getRandomAddress() 0 11 2
A getCities() 0 3 2
A __construct() 0 7 1
A addCities() 0 12 4
A addCity() 0 9 2
A getCityIdByName() 0 9 2
A makeCities() 0 15 4
A clearCities() 0 5 1
1
<?php
2
3
namespace Ngtfkx\LaradeckAddressGenerator;
4
5
6
use Illuminate\Support\Collection;
7
use Ngtfkx\LaradeckAddressGenerator\Exceptions\CityNotFound;
8
9
class Generator
10
{
11
    /**
12
     * @var Collection Список городов для которых будем генерировать адреса
13
     */
14
    protected $cities;
15
16
    /**
17
     * @var Collection Список доступных для поиска имен городов городов
18
     */
19
    protected $searchableCityNames;
20
21
    /**
22
     * @var Collection Список достпупных гордов
23
     */
24
    protected $availableCities;
25
26
    /**
27
     * @var Collection Список достпупных адресов
28
     */
29
    protected $availableAddresses;
30
31
    /**
32
     * Generator constructor.
33
     */
34
    public function __construct()
35
    {
36
        $this->cities = new Collection();
37
38
        $this->makeCities();
39
40
        $this->makeAddresses();
41
    }
42
43
    /**
44
     * Получить случайный адрес
45
     *
46
     * @param string|null $forCity Имя города, для которого генерировать адрес. По умолчанию null - из любого установленного
47
     * @return Address
48
     * @throws CityNotFound Город не найден в списке доступных
49
     */
50
    public function getRandomAddress($forCity = null): Address
51
    {
52
        $forCity = $forCity ?: $this->getCities()->random();
53
54
        $forCity = Helper::prepare($forCity);
55
56
        $cityId = $this->getCityIdByName($forCity);
57
58
        $address = $this->availableAddresses->get($cityId)->random();
59
60
        return $address;
61
    }
62
63
    /**
64
     * Добавить город в список, для которого будем генерировать адреса
65
     *
66
     * @param string $city
67
     * @return Generator
68
     * @throws CityNotFound Город не найден в списке доступных
69
     */
70
    public function addCity(string $city): Generator
71
    {
72
        $key = $this->getCityIdByName($city);
73
74
        if (!$this->cities->contains($city)) {
75
            $this->cities->put($key, $city);
76
        }
77
78
        return $this;
79
    }
80
81
    /**
82
     * Добавить несколько городо в список, для которого будем генерировать адреса
83
     *
84
     * @param array ...$cities
85
     * @return Generator
86
     */
87
    public function addCities(...$cities): Generator
88
    {
89
        foreach ($cities as $city) {
90
            if (!is_array($city)) {
91
                $city = [$city];
92
            }
93
            foreach ($city as $item) {
94
                $this->addCity($item);
95
            }
96
        }
97
98
        return $this;
99
    }
100
101
    /**
102
     * Установить список городов, для которого будем генерировать адреса
103
     *
104
     * @param array ...$cities
105
     * @return Generator
106
     */
107
    public function setCities(...$cities): Generator
108
    {
109
        $this->clearCities();
110
111
        if (sizeof($cities) === 1 && is_array($cities[0])) {
112
            $cities = $cities[0];
113
        }
114
115
        $this->addCities($cities);
116
117
        return $this;
118
    }
119
120
    /**
121
     * Очистить список гордов, для которых можно генерировать адреса
122
     *
123
     * @return Generator
124
     */
125
    public function clearCities(): Generator
126
    {
127
        $this->cities = new Collection();
128
129
        return $this;
130
    }
131
132
    /**
133
     * Получить коллекцию городов, для которых можно получать адреса.
134
     *
135
     * Если города заданы, то их. Если нет, то все доступные города.
136
     *
137
     * @return Collection
138
     */
139
    public function getCities(): Collection
140
    {
141
        return $this->cities->isEmpty() ? $this->availableCities : $this->cities;
142
    }
143
144
    /**
145
     * Получить имена городов, установленные для которых можно получать адреса
146
     *
147
     * @return Collection
148
     */
149
    public function getCityNames(): Collection
150
    {
151
        return $this->cities->values();
152
    }
153
154
    /**
155
     * Получить ID города по его имени
156
     *
157
     * @param string $name
158
     * @return int
159
     * @throws CityNotFound
160
     */
161
    protected function getCityIdByName(string $name): int
162
    {
163
        $key = $this->searchableCityNames->get(Helper::prepare($name));
164
165
        if (empty($key)) {
166
            throw new CityNotFound();
167
        }
168
169
        return $key;
170
    }
171
172
    /**
173
     * Генерируем коллекцию всех доступных адресов
174
     */
175
    private function makeAddresses(): void
176
    {
177
        $this->availableAddresses = new Collection();
178
179
        foreach ($this->availableCities as $key => $city) {
180
            $rawData = include('data/ru/' . $key . '.php');
181
            $addresses = new Collection();
182
183
            foreach ($rawData as $street => $buildings) {
184
                foreach ($buildings as $building) {
185
                    $address = new Address($city, $street, $building);
186
                    $addresses->push($address);
187
                }
188
            }
189
190
            $this->availableAddresses->put($key, $addresses);
191
        }
192
    }
193
194
    /**
195
     * Генерирум коллекцию всех доступных городов
196
     */
197
    private function makeCities(): void
198
    {
199
        $this->availableCities = new Collection();
200
201
        $this->searchableCityNames = new Collection();
202
203
        foreach (include('data/cities.php') as $key => $items) {
204
205
            $this->availableCities->put($key, $items[0]);
206
207
            foreach ($items as $item) {
208
                $item = Helper::prepare($item);
209
210
                if (!$this->searchableCityNames->contains($item)) {
211
                    $this->searchableCityNames->put($item, $key);
212
                }
213
            }
214
        }
215
    }
216
}