Completed
Push — master ( d5b4b1...d6e5b5 )
by Konstantin
03:44
created

GeoFixer   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 265
Duplicated Lines 21.51 %

Coupling/Cohesion

Components 2
Dependencies 6

Test Coverage

Coverage 96.97%

Importance

Changes 5
Bugs 1 Features 1
Metric Value
wmc 30
c 5
b 1
f 1
lcom 2
cbo 6
dl 57
loc 265
ccs 96
cts 99
cp 0.9697
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A findFiasRegion() 19 19 3
A findSimilarWord() 0 16 3
A findFiasSettlements() 19 19 3
B findKladrSettlements() 0 26 4
A findFiasStreets() 19 19 3
B findKladrStreets() 0 34 5
A findFiasHouses() 0 13 3
A isStrict() 0 4 1
A isFirstLetters() 0 6 2
A isFullSettlements() 0 4 1
A geoDataHandler() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace GeoFixer\models;
4
5
use GeoFixer\models\queries\AbstractDatabaseQuery;
6
use GeoFixer\models\queries\RegionsDatabaseQuery;
7
use GeoFixer\models\queries\SettlementsDatabaseQuery;
8
use GeoFixer\models\queries\StreetsDatabaseQuery;
9
use GeoFixer\models\queries\HousesDatabaseQuery;
10
use GeoFixer\helpers\StringHelper;
11
use GeoFixer\helpers\FuzzySearchHelper;
12
13
/**
14
 * Class GeoFixer
15
 *
16
 * @package GeoFixer\models
17
 */
18
class GeoFixer
19
{
20
    protected $strict = false;
21
    protected $first_letters = false;
22
    protected $full_settlements = false;
23
24
    protected $geo_with_ids = [];
25
    protected $geo_titles = [];
26
    protected $title_name;
27
    protected $code_name;
28
29
    protected $string_helper;
30
    protected $fuzzy_helper;
31
32
    /**
33
     * GeoFixer construct
34
     */
35 3
    public function __construct()
36
    {
37 3
        $this->string_helper = new StringHelper();
38 3
        $this->fuzzy_helper = new FuzzySearchHelper();
39
40 3
        $this->title_name = AbstractDatabaseQuery::TITLE;
41 3
        $this->code_name = AbstractDatabaseQuery::FIAS_CODE;
42 3
    }
43
44
    /**
45
     * @param $region
46
     *
47
     * @return bool|mixed
48
     */
49 8 View Code Duplication
    public function findFiasRegion($region)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
50
    {
51 8
        $this->code_name = AbstractDatabaseQuery::KLADR_CODE;
52
53 8
        $regions = new RegionsDatabaseQuery();
54 8
        $regions = $regions->getRegions();
55
56 8
        if (is_integer($this->first_letters)) {
57 2
            $regions = $regions->firstLetters(substr($region, 0, $this->first_letters));
58
        }
59
60 8
        $regions = $regions->findAll();
61
62 8
        array_map(array($this, 'geoDataHandler'), $regions);
63
64 8
        $result = $this->findSimilarWord($region, $this->geo_titles);
65
66 8
        return $result ? $this->geo_with_ids[$result] : false;
67
    }
68
69
    /**
70
     * @param $word
71
     * @param $search_array
72
     *
73
     * @return string|false|null
74
     */
75 23
    public function findSimilarWord($word, $search_array)
76
    {
77 23
        if (in_array($word, $search_array)) {
78 7
            return $word;
79
        }
80
81 19
        $word = $this->string_helper->wordTranslit($word);
82
83 19
        $translited_words = $this->string_helper->arrayTranslit($search_array);
84
85 19
        $result = $this->strict === true ?
86 9
            $this->fuzzy_helper->findBestMatch($word, $translited_words) :
87 19
            key($this->fuzzy_helper->findMostSimilarWords($word, $translited_words));
88
89 19
        return $result;
90
    }
91
92
    /**
93
     * @param $city
94
     * @param $region_code
95
     *
96
     * @return bool|mixed
97
     */
98 4 View Code Duplication
    public function findFiasSettlements($city, $region_code)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
99
    {
100 4
        $this->code_name = AbstractDatabaseQuery::FIAS_CODE;
101
102 4
        $settlements = new SettlementsDatabaseQuery();
103 4
        $settlements = $settlements->getSettlements()->regionCode($region_code)->addressLevel();
104
105 4
        if (is_integer($this->first_letters)) {
106 1
            $settlements = $settlements->firstLetters(substr($city, 0, $this->first_letters));
107
        }
108
109 4
        $settlements = $settlements->findAll();
110
111 4
        array_map(array($this, 'geoDataHandler'), $settlements);
112
113 4
        $result = $this->findSimilarWord($city, $this->geo_titles);
114
115 4
        return $result ? $this->geo_with_ids[$result] : false;
116
    }
117
118
    /**
119
     * @param $city
120
     * @param $region_code
121
     *
122
     * @return bool|mixed
123
     */
124 4
    public function findKladrSettlements($city, $region_code)
125
    {
126 4
        $this->code_name = AbstractDatabaseQuery::KLADR_CODE;
127
128 4
        $settlements = new SettlementsDatabaseQuery();
129 4
        $settlements = $settlements->getSettlements()->regionCode($region_code)->addressLevel();
130
131 4
        if (is_integer($this->first_letters)) {
132 1
            $settlements = $settlements->firstLetters(substr($city, 0, $this->first_letters));
133
        }
134
135 4
        $settlements = $settlements->findAll();
136
137 4
        array_map(array($this, 'geoDataHandler'), $settlements);
138
139 4
        $result = $this->findSimilarWord($city, $this->geo_titles);
140
141 4
        if (!$result) {
142 1
            return false;
143
        }
144 3
        if (is_null($this->geo_with_ids[$result])) {
145
            return false;
146
        }
147
148 3
        return $this->geo_with_ids[$result];
149
    }
150
151
    /**
152
     * @param $street
153
     * @param $city_id
154
     *
155
     * @return bool|mixed
156
     */
157 3 View Code Duplication
    public function findFiasStreets($street, $city_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
    {
159 3
        $this->code_name = AbstractDatabaseQuery::FIAS_CODE;
160
161 3
        $streets = new StreetsDatabaseQuery();
162 3
        $streets = $streets->getStreets()->parentId($city_id)->addressLevel();
163
164 3
        if (is_integer($this->first_letters)) {
165 1
            $streets = $streets->firstLetters(substr($street, 0, $this->first_letters));
166
        }
167
168 3
        $streets = $streets->findAll();
169
170 3
        array_map(array($this, 'geoDataHandler'), $streets);
171
172 3
        $result = $this->findSimilarWord($street, $this->geo_titles);
173
174 3
        return $result ? $this->geo_with_ids[$result] : false;
175
    }
176
177
    /**
178
     * @param $street
179
     * @param $city_code
180
     *
181
     * @return bool|mixed
182
     */
183 3
    public function findKladrStreets($street, $city_code)
184
    {
185 3
        $this->code_name = AbstractDatabaseQuery::KLADR_CODE;
186
187 3
        $streets = new StreetsDatabaseQuery();
188 3
        $city = new SettlementsDatabaseQuery();
189 3
        $city_id = $city->getSettlements()->addressLevel(true)->kladrCode($city_code)->findOne();
190
191 3
        if (!$city_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $city_id of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
192
            return false;
193
        }
194
195 3
        $city_id = $city_id['address_id'];
196 3
        $streets = $streets->getStreets()->parentId($city_id)->addressLevel();
197
198 3
        if (is_integer($this->first_letters)) {
199 1
            $streets = $streets->firstLetters(substr($street, 0, $this->first_letters));
200
        }
201
202 3
        $streets = $streets->findAll();
203
204 3
        array_map(array($this, 'geoDataHandler'), $streets);
205
206 3
        $result = $this->findSimilarWord($street, $this->geo_titles);
207
208 3
        if (!$result) {
209 1
            return false;
210
        }
211 2
        if (is_null($this->geo_with_ids[$result])) {
212
            return false;
213
        }
214
215 2
        return $this->geo_with_ids[$result];
216
    }
217
218
    /**
219
     * @param $house
220
     * @param $street_id
221
     *
222
     * @return bool
223
     */
224 4
    public function findFiasHouses($house, $street_id, $building = false)
225
    {
226 4
        $house_id = new HousesDatabaseQuery();
227 4
        $house_id = $house_id->getHouses()->addressId($street_id)->houseNumber($house);
228
229 4
        if ($building !== false) {
230 2
            $house_id = $house_id->building($building);
231
        }
232
233 4
        $house_id = $house_id->findOne();
234
235 4
        return $house_id ? $house_id['house_id'] : false;
236
    }
237
238
    /**
239
     * Включаем строгий режим поиска
240
     *
241
     * @param bool $strict
242
     */
243 23
    public function isStrict($strict = false)
244
    {
245 23
        $this->strict = $strict;
246 23
    }
247
248
249
    /**
250
     * Сколько первых букв должны совпадать при поиске по базам ФИАС
251
     *
252
     * (теоретически, снизит кол-во слов, которые придется обрабатывать алгоритмом и тем самым увеличит скорость работы, но может не найти слово, если первые буквы не совпадают
253
     * из-за опечатки или префиксов)
254
     *
255
     * @param int|bool $count
256
     */
257 20
    public function isFirstLetters($count = false)
258
    {
259 20
        if (is_int($count)) {
260 6
            $this->first_letters = $count;
0 ignored issues
show
Documentation Bug introduced by
The property $first_letters was declared of type boolean, but $count is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
261
        }
262 20
    }
263
264
    /**
265
     * Только города, или города и поселения
266
     *
267
     * @param bool $is_full
268
     */
269 8
    public function isFullSettlements($is_full = false)
270
    {
271 8
        $this->full_settlements = $is_full;
272 8
    }
273
274
    /**
275
     * @param $geo_array
276
     */
277 20
    protected function geoDataHandler($geo_array)
278
    {
279 20
        $this->geo_with_ids[$geo_array[$this->title_name]] = $geo_array[$this->code_name];
280 20
        $this->geo_titles[] = $geo_array[$this->title_name];
281 20
    }
282
}
283
284