|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace ADiaz\AML\OpenList\parsers; |
|
4
|
|
|
|
|
5
|
|
|
use ADiaz\AML\OpenList\models\Address; |
|
6
|
|
|
use ADiaz\AML\OpenList\models\Aka; |
|
7
|
|
|
use ADiaz\AML\OpenList\models\Citizenship; |
|
8
|
|
|
use ADiaz\AML\OpenList\models\DateOfBirth; |
|
9
|
|
|
use ADiaz\AML\OpenList\models\Entity; |
|
10
|
|
|
use ADiaz\AML\OpenList\models\Id; |
|
11
|
|
|
use ADiaz\AML\OpenList\models\Nationality; |
|
12
|
|
|
use ADiaz\AML\OpenList\models\PlaceOfBirth; |
|
13
|
|
|
use ADiaz\AML\OpenList\models\Program; |
|
14
|
|
|
|
|
15
|
|
|
/** |
|
16
|
|
|
* This file is part of the OpenList Parser utility. |
|
17
|
|
|
* |
|
18
|
|
|
* @category PHP |
|
19
|
|
|
* |
|
20
|
|
|
* @author Alberto Diaz <[email protected]> |
|
21
|
|
|
* @copyright 2016 Alberto Diaz <[email protected]> |
|
22
|
|
|
* @license This source file is subject to the MIT license that is bundled |
|
23
|
|
|
* |
|
24
|
|
|
* @version Release: @package_version@ |
|
25
|
|
|
* |
|
26
|
|
|
* @link http://tytem.com |
|
27
|
|
|
*/ |
|
28
|
|
|
class Ukhmt implements ListInterface |
|
29
|
|
|
{ |
|
30
|
|
|
protected $prime_alias; |
|
31
|
|
|
protected $aka_fka_rows; |
|
32
|
|
|
protected $list_file_content; |
|
33
|
|
|
protected $path_source; |
|
34
|
|
|
protected $entities = []; |
|
35
|
|
|
protected $date; |
|
36
|
|
|
|
|
37
|
|
|
const ERROR_DIVIDING_ROWS = 'Error dividing the rows.'; |
|
38
|
|
|
const ERROR_FILE = 'Error. The sanction list was not found. Have you executed the downloader?.'; |
|
39
|
|
|
const ERROR_VERIFYING_ENTITIES = 'Error. The sanction list was not found. Please verify if it was downloaded and the list configuration file.'; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* Add the entity if it doesn't exsist already in teh array of entities |
|
43
|
|
|
* if it exists it does nothing. |
|
44
|
|
|
* |
|
45
|
|
|
* @param Entity $entity |
|
46
|
|
|
* |
|
47
|
|
|
* @return null|bool if the entity is added to the array |
|
48
|
|
|
*/ |
|
49
|
2 |
|
protected function addEntity(Entity $entity) |
|
50
|
|
|
{ |
|
51
|
2 |
|
foreach ($this->entities as $ent) { |
|
52
|
2 |
|
if ($ent->external_id === $entity->external_id) { |
|
53
|
2 |
|
return; |
|
54
|
|
|
} |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
2 |
|
$this->entities [] = $entity; |
|
58
|
|
|
|
|
59
|
2 |
|
return true; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* Get the value from one or multiple cols. |
|
64
|
|
|
* |
|
65
|
|
|
* @param string $value |
|
66
|
|
|
* @param array $cols |
|
67
|
|
|
* |
|
68
|
|
|
* @return string|null |
|
69
|
|
|
*/ |
|
70
|
2 |
|
protected function getCols($value, $cols) |
|
71
|
|
|
{ |
|
72
|
2 |
|
$mValue = $this->getMap()[$value]; |
|
73
|
|
|
|
|
74
|
2 |
|
if (is_array($mValue)) { |
|
75
|
2 |
|
$str = ''; |
|
76
|
2 |
|
foreach ($mValue as $subIdMapper) { |
|
77
|
2 |
|
$str .= $cols[$subIdMapper].' '; |
|
78
|
|
|
} |
|
79
|
|
|
} else { |
|
80
|
2 |
|
$str = $cols[$mValue]; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
2 |
|
$strNoExtraSpaces = trim(preg_replace('/\s+/', ' ', $str)); |
|
84
|
|
|
|
|
85
|
2 |
|
return ($strNoExtraSpaces !== '') ? $strNoExtraSpaces : null; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
public function getDate() |
|
89
|
|
|
{ |
|
90
|
|
|
return $this->date; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
2 |
|
public function getEntities() |
|
94
|
|
|
{ |
|
95
|
2 |
|
return $this->entities; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* Get the ids of the entities. |
|
100
|
|
|
* |
|
101
|
|
|
* @return array |
|
102
|
|
|
*/ |
|
103
|
2 |
|
protected function getEntitiesIds() |
|
104
|
|
|
{ |
|
105
|
2 |
|
$entitiesIds = []; |
|
106
|
|
|
|
|
107
|
2 |
|
foreach ($this->entities as $entity) { |
|
108
|
2 |
|
$entitiesIds[] = $entity->external_id; |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
2 |
|
return $entitiesIds; |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* Get a new entity if it doesn't exist, or get the entity created |
|
116
|
|
|
* if already exists. |
|
117
|
|
|
* |
|
118
|
|
|
* @param int $id |
|
119
|
|
|
* |
|
120
|
|
|
* @return Entity |
|
121
|
|
|
*/ |
|
122
|
2 |
|
protected function getEntity($id) |
|
123
|
|
|
{ |
|
124
|
2 |
|
foreach ($this->entities as $entity) { |
|
125
|
2 |
|
if ($entity->external_id === $id) { |
|
126
|
2 |
|
return $entity; |
|
127
|
|
|
} |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
2 |
|
return new Entity($id); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* Get the ids of the list. |
|
135
|
|
|
* |
|
136
|
|
|
* @return array |
|
137
|
|
|
*/ |
|
138
|
2 |
|
protected function getGroupsIdsFromSource() |
|
139
|
|
|
{ |
|
140
|
2 |
|
$group_ids = []; |
|
141
|
2 |
|
$i = 0; |
|
142
|
|
|
|
|
143
|
|
|
// iterate over each line |
|
144
|
2 |
|
foreach (preg_split("/((\r?\n)|(\r\n?))/", $this->list_file_content) as $line) { |
|
145
|
2 |
|
$cols = str_getcsv($line); |
|
146
|
|
|
|
|
147
|
2 |
|
if ($i > 1) { |
|
148
|
2 |
|
$group_id = $cols[$this->getMap()['group_id']]; |
|
149
|
|
|
|
|
150
|
2 |
|
$group_ids [$group_id] = $group_id; |
|
151
|
|
|
} |
|
152
|
2 |
|
++$i; |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
2 |
|
return $group_ids; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Return the mappers the fields with the columns of the excel document. |
|
160
|
|
|
* |
|
161
|
|
|
* @return array with the mapping |
|
162
|
|
|
*/ |
|
163
|
2 |
|
protected function getMap() |
|
164
|
|
|
{ |
|
165
|
|
|
$fields = [ |
|
166
|
2 |
|
'last_name' => 0, |
|
167
|
|
|
'first_name' => [1, 2, 3, 4, 5], |
|
168
|
|
|
'title' => 6, |
|
169
|
|
|
'dob' => 7, |
|
170
|
|
|
'tob' => 8, |
|
171
|
|
|
'cob' => 9, |
|
172
|
|
|
'nationality' => 10, |
|
173
|
|
|
'passport' => 11, |
|
174
|
|
|
'ni_number' => 12, |
|
175
|
|
|
'position' => 13, |
|
176
|
|
|
'address' => [14, 15, 16, 17, 18], |
|
177
|
|
|
'city' => 19, |
|
178
|
|
|
'postcode' => 20, |
|
179
|
|
|
'country' => 21, |
|
180
|
|
|
'other_information' => 22, |
|
181
|
|
|
'group_type' => 23, |
|
182
|
|
|
'row_type' => 24, |
|
183
|
|
|
'regime' => 25, |
|
184
|
|
|
'listen_on' => 26, |
|
185
|
|
|
'last_updated' => 27, |
|
186
|
|
|
'group_id' => 28, |
|
187
|
|
|
]; |
|
188
|
|
|
|
|
189
|
2 |
|
return $fields; |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
/** |
|
193
|
|
|
* Check if if a row (after str_getcsv) is prime alias. |
|
194
|
|
|
* |
|
195
|
|
|
* @param array $cols |
|
196
|
|
|
* |
|
197
|
|
|
* @return bool true if yes |
|
198
|
|
|
*/ |
|
199
|
2 |
|
protected function isPrimeAlias(array $cols) |
|
200
|
|
|
{ |
|
201
|
2 |
|
return $cols[$this->getMap()['row_type']] === Entity::ALIAS_TYPE_PRIME_ALIAS; |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* Check if if a row (after str_getcsv) is an AKA. |
|
206
|
|
|
* |
|
207
|
|
|
* @param array $cols |
|
208
|
|
|
* |
|
209
|
|
|
* @return bool true if yes |
|
210
|
|
|
*/ |
|
211
|
2 |
|
protected function isAka(array $cols) |
|
212
|
|
|
{ |
|
213
|
2 |
|
return $cols[$this->getMap()['row_type']] === Entity::ALIAS_TYPE_AKA; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* Check if if a row (after str_getcsv) is an FKA. |
|
218
|
|
|
* |
|
219
|
|
|
* @param array $cols |
|
220
|
|
|
* |
|
221
|
|
|
* @return bool true if yes |
|
222
|
|
|
*/ |
|
223
|
2 |
|
protected function isFka(array $cols) |
|
224
|
|
|
{ |
|
225
|
2 |
|
return $cols[$this->getMap()['row_type']] === Entity::ALIAS_TYPE_FKA; |
|
226
|
|
|
} |
|
227
|
|
|
|
|
228
|
|
|
/** |
|
229
|
|
|
* A separate record is provided for each permutation of data involving “Name”, “Date of Birth”, |
|
230
|
|
|
* “Address” and “Regime”. |
|
231
|
|
|
*/ |
|
232
|
2 |
|
protected function processAkasAndFkas() |
|
233
|
|
|
{ |
|
234
|
2 |
|
foreach ($this->aka_fka_rows as $row) { |
|
235
|
2 |
|
$cols = str_getcsv($row); |
|
236
|
|
|
|
|
237
|
|
|
// get the entity to fill it with info |
|
238
|
2 |
|
$entity = $this->getEntity($this->getCols('group_id', $cols)); |
|
239
|
|
|
|
|
240
|
|
|
//add aka |
|
241
|
2 |
|
$aka = new Aka(); |
|
242
|
2 |
|
$aka->last_name = $this->getCols('last_name', $cols); |
|
243
|
2 |
|
$aka->first_name = $this->getCols('first_name', $cols); |
|
244
|
2 |
|
$entity->addAka($aka); |
|
245
|
|
|
|
|
246
|
|
|
// add dob |
|
247
|
2 |
|
$entity->addDateOfBirth(new DateOfBirth($this->getCols('dob', $cols))); |
|
|
|
|
|
|
248
|
|
|
|
|
249
|
|
|
// add address |
|
250
|
2 |
|
$address = new Address(); |
|
251
|
2 |
|
$address->address1 = $this->getCols('address', $cols); |
|
252
|
2 |
|
$address->city = $this->getCols('city', $cols); |
|
253
|
2 |
|
$address->country = $this->getCols('country', $cols); |
|
254
|
2 |
|
$address->postal_code = $this->getCols('postcode', $cols); |
|
255
|
2 |
|
$entity->addAddress($address); |
|
256
|
|
|
|
|
257
|
|
|
// add program |
|
258
|
2 |
|
$entity->addProgram(new Program($this->getCols('regime', $cols))); |
|
|
|
|
|
|
259
|
|
|
} |
|
260
|
2 |
|
} |
|
261
|
|
|
|
|
262
|
2 |
|
public function processEntities() |
|
263
|
|
|
{ |
|
264
|
2 |
|
$this->processPrimeAlias(); |
|
265
|
2 |
|
$this->processAkasAndFkas(); |
|
266
|
2 |
|
} |
|
267
|
|
|
|
|
268
|
2 |
|
public function run() |
|
269
|
|
|
{ |
|
270
|
2 |
|
$this->readEntities(); |
|
271
|
2 |
|
$this->processEntities(); |
|
272
|
2 |
|
$this->setDate(); |
|
273
|
|
|
|
|
274
|
2 |
|
return $this->verifyEntities(); |
|
275
|
|
|
//log die(self::ERROR_VERIFYING_ENTITIES); |
|
|
|
|
|
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
/** |
|
279
|
|
|
* Process entity prime alias. |
|
280
|
|
|
*/ |
|
281
|
2 |
|
protected function processPrimeAlias() |
|
282
|
|
|
{ |
|
283
|
2 |
|
foreach ($this->prime_alias as $row) { |
|
284
|
2 |
|
$cols = str_getcsv($row); |
|
285
|
|
|
|
|
286
|
2 |
|
$entity = $this->getEntity($this->getCols('group_id', $cols)); |
|
287
|
|
|
|
|
288
|
2 |
|
$entity->setter('last_name', $this->getCols('last_name', $cols)); |
|
289
|
2 |
|
$entity->setter('first_name', $this->getCols('first_name', $cols)); |
|
290
|
2 |
|
$entity->setter('title', $this->getCols('title', $cols)); |
|
291
|
2 |
|
$entity->setType($this->getCols('group_type', $cols)); |
|
292
|
2 |
|
$entity->setter('position', $this->getCols('position', $cols)); |
|
293
|
2 |
|
$entity->setter('remarks', $this->getCols('other_information', $cols)); |
|
294
|
|
|
|
|
295
|
|
|
// add address |
|
296
|
2 |
|
$address = new Address(); |
|
297
|
2 |
|
$address->address1 = $this->getCols('address', $cols); |
|
298
|
2 |
|
$address->city = $this->getCols('city', $cols); |
|
299
|
2 |
|
$address->country = $this->getCols('country', $cols); |
|
300
|
2 |
|
$address->postal_code = $this->getCols('postcode', $cols); |
|
301
|
2 |
|
$entity->addAddress($address); |
|
302
|
|
|
|
|
303
|
|
|
// add dob |
|
304
|
2 |
|
$dateOfBirth = new DateOfBirth(); |
|
305
|
2 |
|
$dateOfBirth->date_of_birth = $this->getCols('dob', $cols); |
|
306
|
2 |
|
$entity->addDateOfBirth($dateOfBirth); |
|
307
|
|
|
|
|
308
|
|
|
// add POB town of birth |
|
309
|
2 |
|
$placeOfBirth = new PlaceOfBirth(); |
|
310
|
2 |
|
$placeOfBirth->place_of_birth = $this->getCols('tob', $cols); |
|
311
|
2 |
|
$entity->addPlaceOfBirth($placeOfBirth); |
|
312
|
|
|
|
|
313
|
|
|
// add COB country of birth to the place of birth |
|
314
|
2 |
|
$countryOfBirth = new PlaceOfBirth(); |
|
315
|
2 |
|
$countryOfBirth->place_of_birth = $this->getCols('cob', $cols); |
|
316
|
2 |
|
$entity->addPlaceOfBirth($countryOfBirth); |
|
317
|
|
|
|
|
318
|
|
|
// add program |
|
319
|
2 |
|
$program = new Program(); |
|
320
|
2 |
|
$program->program = $this->getCols('regime', $cols); |
|
321
|
2 |
|
$entity->addProgram($program); |
|
322
|
|
|
|
|
323
|
|
|
// add citizenship |
|
324
|
2 |
|
$citizenship = new Citizenship(); |
|
325
|
2 |
|
$citizenship->country = $this->getCols('nationality', $cols); |
|
326
|
2 |
|
$entity->addCitizenship($citizenship); |
|
327
|
|
|
|
|
328
|
|
|
// add nationality |
|
329
|
2 |
|
$nationality = new Nationality(); |
|
330
|
2 |
|
$nationality->country = $this->getCols('nationality', $cols); |
|
331
|
2 |
|
$entity->addNationality($nationality); |
|
332
|
|
|
|
|
333
|
|
|
// add Passport number(s) - where issued, issued/expiry dates |
|
334
|
2 |
|
$passport = new Id(); |
|
335
|
2 |
|
$passport->type = Id::TYPE_PASSPORT; |
|
336
|
2 |
|
$passport->mixed = $this->getCols('passport', $cols); |
|
337
|
2 |
|
$entity->addId($passport); |
|
338
|
|
|
|
|
339
|
|
|
// add ids (ssn, national ids, passports) |
|
340
|
2 |
|
$nid = new Id(); |
|
341
|
2 |
|
$nid->type = Id::TYPE_NATIONAL_ID_OR_SSN; |
|
342
|
2 |
|
$nid->mixed = $this->getCols('nationality', $cols); |
|
343
|
2 |
|
$entity->addId($nid); |
|
344
|
|
|
|
|
345
|
2 |
|
$this->addEntity($entity); |
|
346
|
|
|
} |
|
347
|
2 |
|
} |
|
348
|
|
|
|
|
349
|
2 |
|
public function readEntities() |
|
350
|
|
|
{ |
|
351
|
|
|
// change encoding, review it in the future since https://www.gov.uk/government/publications/open-standards-for-government/cross-platform-character-encoding-profile |
|
352
|
2 |
|
$this->list_file_content = utf8_encode(file_get_contents($this->path_source)); |
|
353
|
|
|
|
|
354
|
|
|
// check the file |
|
355
|
2 |
|
if (!$this->list_file_content) { |
|
356
|
|
|
throw new \UnexpectedValueException(self::ERROR_FILE); |
|
357
|
|
|
} |
|
358
|
|
|
|
|
359
|
2 |
|
$this->setPrimaryEntitiesAkasFkas(); |
|
360
|
2 |
|
} |
|
361
|
|
|
|
|
362
|
2 |
|
public function setDate() |
|
363
|
|
|
{ |
|
364
|
2 |
|
$lines = preg_split("/((\r?\n)|(\r\n?))/", $this->list_file_content); |
|
365
|
|
|
|
|
366
|
2 |
|
$dateLine = str_getcsv($lines[0]); |
|
367
|
|
|
|
|
368
|
2 |
|
$this->date = $dateLine[1]; |
|
369
|
2 |
|
} |
|
370
|
|
|
|
|
371
|
|
|
/** |
|
372
|
|
|
* Divide the entities in primary, akas and fkas. |
|
373
|
|
|
*/ |
|
374
|
2 |
|
protected function setPrimaryEntitiesAkasFkas() |
|
375
|
|
|
{ |
|
376
|
2 |
|
$firstLine = true; |
|
377
|
|
|
|
|
378
|
|
|
// iterate over each line |
|
379
|
2 |
|
foreach (preg_split("/((\r?\n)|(\r\n?))/", $this->list_file_content) as $line) { |
|
380
|
2 |
|
$cols = str_getcsv($line); |
|
381
|
|
|
|
|
382
|
2 |
|
if ($firstLine) { |
|
383
|
2 |
|
$firstLine = false; |
|
384
|
2 |
|
continue; |
|
385
|
|
|
} |
|
386
|
|
|
|
|
387
|
2 |
|
if ($this->isPrimeAlias($cols)) { |
|
388
|
2 |
|
$this->prime_alias[] = $line; |
|
389
|
2 |
|
} elseif ($this->isAka($cols) || $this->isFka($cols)) { |
|
390
|
2 |
|
$this->aka_fka_rows[] = $line; |
|
391
|
|
|
} |
|
392
|
|
|
} |
|
393
|
2 |
|
} |
|
394
|
|
|
|
|
395
|
2 |
|
public function setSourcePath($pathSource) |
|
396
|
|
|
{ |
|
397
|
2 |
|
$this->path_source = $pathSource; |
|
398
|
2 |
|
} |
|
399
|
|
|
|
|
400
|
|
|
/** |
|
401
|
|
|
* Check the number of entities math with the total of entities of the document. |
|
402
|
|
|
*/ |
|
403
|
2 |
|
public function verifyEntities() |
|
404
|
|
|
{ |
|
405
|
2 |
|
return $this->verifyIds(); |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
/** |
|
409
|
|
|
* Check if the ids of the entities are the same that the ids from the list file. |
|
410
|
|
|
* |
|
411
|
|
|
* @return bool |
|
412
|
|
|
*/ |
|
413
|
2 |
|
protected function verifyIds() |
|
414
|
|
|
{ |
|
415
|
2 |
|
return count(array_diff($this->getGroupsIdsFromSource(), $this->getEntitiesIds())) == 0 |
|
416
|
2 |
|
&& count($this->getEntitiesIds()) > 0; |
|
417
|
|
|
} |
|
418
|
|
|
} |
|
419
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.