latest update
[namibia] / module / Stock / src / Stock / Utility / ImportHelper.php
1 <?php
2 namespace Stock\Utility;
3
4 use Doctrine\ORM\EntityManager;
5 use Utility\Debug;
6 use Workspace\Service\DataBin as DataBinCore;
7
8
9 /**
10  * Class ImportHelper
11  * @package Stock\Utility
12  */
13 class ImportHelper extends DataBinCore
14 {
15
16
17
18         /**
19          * @var \Doctrine\ORM\EntityManager
20          */
21         protected $em;
22         /**
23          * @var \Stock\Utility\ImportUtility
24          */
25         protected $util;
26         /**
27          * @var \Stock\Utility\DataStore
28          */
29         protected $store;
30         /**
31          * @var bool
32          */
33         protected $simulateExecution = false;
34         /**
35          * @var array
36          */
37         protected $categoryMap = array(
38                 'T' => 1,
39                 'A' => 2,
40                 'C' => 3,
41                 'B' => 4,
42                 'M' => 5,
43                 'H' => 6,
44                 'Z' => 7
45         );
46         /**
47          * @var array
48          */
49         protected $typeFieldsToMatch = array(
50                 'cylinders', 'cubicCapacity', 'kilowatts', 'bodyType', 'doors'
51         );
52         /**
53          * @var array
54          */
55         protected $numericFields = array(
56                 'cylinders', 'cubicCapacity', 'kilowatts', 'doors'
57         );
58         /**
59          * @var array
60          */
61         protected $makes = array();
62         /**
63          * @var array
64          */
65         protected $models = array();
66
67
68         public function __construct(EntityManager $em, DataStore &$store)
69         {
70                 $this->em    = $em;
71                 $this->util  = new ImportUtility($this->em);
72                 $this->store = $store;
73         }
74
75
76         #-------------------------------------------------------------------------- SECTION
77         /**
78          * @param $fileName
79          */
80         public function executeOfflineTransunionDataImport($fileName)
81         {
82                 if ($this->simulateExecution)
83                 {
84                         error_log('php /var/www/namibia/public/index.php vehicle import '
85                                   . $fileName
86                                   . ' >>/log/php.log &');
87                 }
88                 else
89                 {
90                         exec(
91                                 'php /var/www/namibia/public/index.php vehicle import '
92                                 . $fileName
93                                 . ' >>/log/php.log &'
94                         );
95                 }
96         }
97
98
99         #-------------------------------------------------------------------------- SECTION
100         /**
101          * Ensure that synchronization versions have a full sequence.
102          * return null
103          */
104         public function ensureSynchronizationVersionSequence()
105         {
106                 #-> Get current latest versions.
107                 $makeVersion  = $this->util->getLatestSynchVersion('Stock\\Entity\\Make');
108                 $modelVersion = $this->util->getLatestSynchVersion('Stock\\Entity\\Model');
109                 $typeVersion  = $this->util->getLatestSynchVersion('Stock\\Entity\\Type');
110
111                 #-> Establish highest current version.
112                 $maxVersion = $this->getMaxVersion($makeVersion, $modelVersion, $typeVersion);
113
114                 #-> Where do we need updates?
115                 if ($maxVersion > $makeVersion)
116                 {
117                         $this->updateSynchVersionSequence('Stock\\Entity\\Make', $makeVersion + 1, $maxVersion);
118                 }
119                 if ($maxVersion > $modelVersion)
120                 {
121                         $this->updateSynchVersionSequence('Stock\\Entity\\Model', $modelVersion + 1, $maxVersion);
122                 }
123                 if ($maxVersion > $typeVersion)
124                 {
125                         $this->updateSynchVersionSequence('Stock\\Entity\\Type', $typeVersion + 1, $maxVersion);
126                 }
127         }
128
129         /**
130          * @param $makeVersion
131          * @param $modelVersion
132          * @param $typeVersion
133          * @return mixed
134          */
135         public function getMaxVersion($makeVersion, $modelVersion, $typeVersion)
136         {
137                 $maxVersion = $makeVersion > $modelVersion
138                         ? $makeVersion
139                         : $modelVersion;
140                 $maxVersion = $maxVersion > $typeVersion
141                         ? $maxVersion
142                         : $typeVersion;
143                 return $maxVersion;
144         }
145
146         /**
147          * @param string  $entityName
148          * @param integer $startVersion
149          * @param integer $endVersion
150          * @throws \Exception
151          */
152         public function updateSynchVersionSequence($entityName, $startVersion, $endVersion)
153         {
154                 #-> Get entries we can update.
155                 $numEntriesNeeded     = ((int)$endVersion) - ((int)$startVersion) + 1;
156                 $entries              = $this->em->getRepository($entityName)
157                         ->findBy(
158                                 array('updateVersion' => null),
159                                 array('id' => 'ASC'),
160                                 $numEntriesNeeded,
161                                 0
162                         );
163                 $this->store->version = ((int)$startVersion) + 1;
164                 if ($numEntriesNeeded != count($entries))
165                 {
166                         throw new \Exception(
167                                 'Cannot synchronize data versions on ' . $entityName . '. Not enough entries available.'
168                         );
169                 }
170                 foreach ($entries as $entry)
171                 {
172                         $entry->updateVersion = $this->store->version;
173                         $this->store->version++;
174                 }
175                 $this->em->flush();
176         }
177
178
179         #-------------------------------------------------------------------------- SECTION
180         /**
181          * MAKE THIS PUBLIC!!!!!!
182          * @param array $packet
183          * @return array
184          */
185         public function cleanupNumericInputFields(array $packet)
186         {
187                 foreach ($this->numericFields as $field)
188                 {
189                         if (array_key_exists($field, $packet))
190                         {
191                                 $packet[$field] = ('' == $packet[$field])
192                                         ? null
193                                         : $packet[$field];
194                         }
195                 }
196                 return $packet;
197         }
198
199
200         #-------------------------------------------------------------------------- SECTION
201         /**
202          * MAKE THIS PUBLIC!!!!!!
203          * @param array $packet
204          * @return mixed
205          */
206         public function createOrUpdateVehicleMakeEntry(array $packet)
207         {
208                 if (!isset($this->makes[$packet['Make']]))
209                 {
210                         $makeId                       = $this->getOrCreateMakeEntry($packet);
211                         $this->makes[$packet['Make']] = $makeId;
212                 }
213                 return $this->makes[$packet['Make']];
214         }
215
216         /**
217          * MAKE THIS PUBLIC!!!!!!
218          * @param array $packet
219          * @return mixed
220          */
221         public function getOrCreateMakeEntry($packet)
222         {
223                 $makeId = $this->util->getId(
224                         'Stock\\Entity\\Make',
225                         array(
226                                 'name' => $packet['Make']
227                         )
228                 );
229                 if (false == $makeId)
230                 {
231                         $makeId = $this->util->createEntry(
232                                 'Stock\\Entity\\Make',
233                                 array(
234                                         'name'          => $packet['Make'],
235                                         'createVersion' => $this->store->version,
236                                         'updateVersion' => $this->store->version
237                                 )
238                         );
239                         $this->store->numItems++;
240                         return $makeId;
241                 }
242                 return $makeId;
243         }
244
245
246         #-------------------------------------------------------------------------- SECTION
247         /**
248          * MAKE THIS PUBLIC!!!!!!
249          * @param array $packet
250          * @param $makeId
251          * @return mixed
252          * @throws \Doctrine\ORM\ORMException
253          */
254         public function createOrUpdateVehicleModel(array $packet, $makeId)
255         {
256                 if (!isset($this->models[$makeId]) || !isset($this->models[$makeId][$packet['Model']]))
257                 {
258                         $modelId                                 = $this->getOrCreateModelEntry(
259                                 $packet, $makeId
260                         );
261                         $this->models[$makeId][$packet['Model']] = $modelId;
262                 }
263                 return $this->models[$makeId][$packet['Model']];
264         }
265
266         /**
267          * @param array $packet
268          * @param       $makeId
269          * @return mixed
270          */
271         public function getOrCreateModelEntry(array $packet, $makeId)
272         {
273                 if (!isset($this->models[$makeId]))
274                 {
275                         $this->models[$makeId] = array();
276                 }
277                 $modelId = $this->util->getId(
278                         'Stock\\Entity\\Model',
279                         array(
280                                 'make' => $makeId,
281                                 'name' => $packet['Model']
282                         )
283                 );
284                 if (false == $modelId)
285                 {
286                         $modelId = $this->util->createEntry(
287                                 'Stock\Entity\Model',
288                                 array(
289                                         'make'          => $this->em->getReference('Stock\\Entity\\Make', $makeId),
290                                         'name'          => $packet['Model'],
291                                         'createVersion' => $this->store->version,
292                                         'updateVersion' => $this->store->version
293                                 )
294                         );
295                         $this->store->numItems++;
296                         return $modelId;
297                 }
298                 return $modelId;
299         }
300
301
302         #-------------------------------------------------------------------------- SECTION
303         /**
304          * @param array $packet
305          * @param $modelId
306          * @return mixed
307          * @throws \Doctrine\ORM\ORMException
308          */
309         public function createOrUpdateVehicleType(array $packet, $modelId)
310         {
311                 #-> Do data preparations.
312                 $packet['name'] = $packet['Variant'];
313                 $packet         = $this->prepareAdditionalVehicleTypeData($packet);
314                 $years          = $this->buildYearMapArray();
315                 $packet         = $this->prepareDateVehicleTypeData($packet, $years);
316
317                 /**
318                  * Here we ensure that we remove spaces and retain leading zeroes to prevent data duplication.
319                  * Previously, this field was cast to int which lead to duplications. - FP
320                 */
321                 $packet['mmCode'] = (string)$packet['MMCode'];
322                 $packet['mmCode'] = preg_replace('/\s+/', '', $packet['mmCode']);
323
324                 #-> Find entry.
325                 $type             = $this->util->getEntry('Stock\\Entity\\Type', array(
326                         'model'  => $modelId,
327                         'mmCode' => $packet['mmCode']
328                 ));
329                 if (false == $type)
330                 {
331                         $packet = $this->prepareVehicleTypeDataForNewEntry($packet, $modelId);
332                         $this->util->createEntry('Stock\\Entity\\Type', $packet);
333                         $this->store->numItems++;
334                 }
335                 else if ($this->vehicleTypeUpdateIsNeeded($packet, $type))
336                 {
337                         $type->updateVersion = $this->store->version;
338                         $this->em->flush($type);
339                         $this->store->numItems++;
340                 }
341                 return $packet;
342         }
343
344         /**
345          * @param array $packet
346          * @return array
347          */
348         public function prepareAdditionalVehicleTypeData(array $packet)
349         {
350                 $packet['cylinders']     = $packet['NoCylinders'];
351                 $packet['cubicCapacity'] = $packet['CubicCapacity'];
352                 $packet['kilowatts']     = $packet['Kilowatts'];
353                 $packet['bodyType']      = $packet['BodyType'];
354                 $packet['doors']         = $packet['NoOfDoors'];
355                 return $packet;
356         }
357
358         /**
359          * @return array
360          */
361         public function buildYearMapArray()
362         {
363                 $nextYear = ((int)date('Y')) + 1;
364                 $years    = array();
365                 $i        = 1;
366                 for ($y = 1970; $y < $nextYear; $y++)
367                 {
368                         $years[$y] = $i;
369                         $i++;
370                 }
371                 return $years;
372         }
373
374         /**
375          * @param array $packet
376          * @param array $years
377          * @return array
378          * @throws \Doctrine\ORM\ORMException
379          */
380         public function prepareDateVehicleTypeData(array $packet, $years)
381         {
382                 list($introMonth, $introYear) = explode('/', $packet['IntroDate']);
383                 $discontinueYear  = false;
384                 $discontinueMonth = false;
385                 if (!empty($packet['DiscDate']))
386                 {
387                         list($discontinueMonth, $discontinueYear) = explode('/', $packet['DiscDate']);
388                 }
389                 unset($packet['IntroDate']);
390                 unset($packet['DiscDate']);
391                 $packet['introYear']  = $this->em->getReference(
392                         '\Stock\Entity\Year',
393                         $years[$introYear]
394                 );
395                 $packet['introMonth'] = $introMonth;
396                 $packet['discYear']   = null;
397                 if ($discontinueYear)
398                 {
399                         $packet['discYear']  = $this->em->getReference(
400                                 'Stock\\Entity\\Year', $years[$discontinueYear]
401                         );
402                         $packet['discMonth'] = $discontinueMonth;
403                         return $packet;
404                 }
405                 return $packet;
406         }
407
408         /**
409          * @param array $packet
410          * @param       $modelId
411          * @return array
412          * @throws \Doctrine\ORM\ORMException
413          */
414         public function prepareVehicleTypeDataForNewEntry(array $packet, $modelId)
415         {
416                 $packet['VehicleType']   = $this->em->getReference(
417                         'Stock\\Entity\\Category',
418                         $this->categoryMap[$packet['VehicleType']]
419                 );
420                 $packet['Model']         = $this->em->getReference(
421                         '\Stock\\Entity\\Model',
422                         $modelId
423                 );
424                 $packet['name']          = $packet['Variant'];
425                 $packet['createVersion'] = $this->store->version;
426                 $packet['updateVersion'] = $this->store->version;
427                 return $packet;
428         }
429
430         /**
431          * @param array $packet
432          * @param       $type
433          * @return bool
434          */
435         public function vehicleTypeUpdateIsNeeded(array $packet, $type)
436         {
437                 $needUpdate = false;
438                 foreach ($this->typeFieldsToMatch as $field)
439                 {
440                         if ($packet[$field] != $type->$field)
441                         {
442                                 $needUpdate   = true;
443                                 $type->$field = $packet[$field];
444                         }
445                         if (!$needUpdate)
446                         {
447                                 if (false != $packet['discYear'] && is_null($type->discYear))
448                                 {
449                                         $needUpdate      = true;
450                                         $type->discYear  = $packet['discYear'];
451                                         $type->discMonth = $packet['discMonth'];
452                                 }
453                         }
454                 }
455                 return $needUpdate;
456         }
457
458
459         #-------------------------------------------------------------------------- SECTION
460         /**
461          * @return null
462          */
463         public function processBatch()
464         {
465                 usleep(500);
466                 $this->em->flush();
467                 $this->em->commit();
468                 $this->em->clear();
469                 $this->em->getConnection()->close();
470                 $this->em->beginTransaction();
471                 $this->store->version++;
472                 $this->store->numItems = 0;
473         }
474
475 }