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:
Complex classes like TrackingProcessor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TrackingProcessor, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class TrackingProcessor implements LoggerAwareInterface |
||
30 | { |
||
31 | use LoggerAwareTrait; |
||
32 | |||
33 | const TRACKING_EVENT_ENTITY = 'OroTrackingBundle:TrackingEvent'; |
||
34 | const TRACKING_VISIT_ENTITY = 'OroTrackingBundle:TrackingVisit'; |
||
35 | const TRACKING_VISIT_EVENT_ENTITY = 'OroTrackingBundle:TrackingVisitEvent'; |
||
36 | |||
37 | /** Batch size for tracking events */ |
||
38 | const BATCH_SIZE = 100; |
||
39 | |||
40 | /** Max retries to identify tracking visit */ |
||
41 | const MAX_RETRIES = 5; |
||
42 | |||
43 | /** @var ManagerRegistry */ |
||
44 | protected $doctrine; |
||
45 | |||
46 | /** @var array */ |
||
47 | protected $collectedVisits = []; |
||
48 | |||
49 | /** @var array */ |
||
50 | protected $eventDictionary = []; |
||
51 | |||
52 | /** @var TrackingEventIdentificationProvider */ |
||
53 | protected $trackingIdentification; |
||
54 | |||
55 | /** @var int */ |
||
56 | protected $processedBatches = 0; |
||
57 | |||
58 | /** @var array */ |
||
59 | protected $skipList = []; |
||
60 | |||
61 | /** @var DeviceDetectorFactory */ |
||
62 | protected $deviceDetector; |
||
63 | |||
64 | /** @var \DateTime start time */ |
||
65 | protected $startTime = null; |
||
66 | |||
67 | /** @var \DateInterval|bool */ |
||
68 | protected $maxExecTimeout = false; |
||
69 | |||
70 | /** Default max execution time (in minutes) */ |
||
71 | protected $maxExecTime = 5; |
||
72 | |||
73 | /** |
||
74 | * @param ManagerRegistry $doctrine |
||
75 | * @param TrackingEventIdentificationProvider $trackingIdentification |
||
76 | */ |
||
77 | public function __construct(ManagerRegistry $doctrine, TrackingEventIdentificationProvider $trackingIdentification) |
||
78 | { |
||
79 | $this->doctrine = $doctrine; |
||
80 | $this->trackingIdentification = $trackingIdentification; |
||
81 | $this->deviceDetector = new DeviceDetectorFactory(); |
||
82 | |||
83 | $this->startTime = $this->getCurrentUtcDateTime(); |
||
84 | $this->maxExecTimeout = $this->maxExecTime > 0 |
||
85 | ? new \DateInterval('PT' . $this->maxExecTime . 'M') |
||
86 | : false; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * @param integer $minutes |
||
91 | */ |
||
92 | public function setMaxExecutionTime($minutes = null) |
||
93 | { |
||
94 | if ($minutes !== null) { |
||
95 | $this->maxExecTime = $minutes; |
||
96 | $this->maxExecTimeout = $minutes > 0 ? new \DateInterval('PT' . $minutes . 'M') : false; |
||
97 | } |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Process tracking data |
||
102 | */ |
||
103 | public function process() |
||
104 | { |
||
105 | /** To avoid memory leaks, we turn off doctrine logger */ |
||
106 | $this->getEntityManager()->getConnection()->getConfiguration()->setSQLLogger(null); |
||
107 | |||
108 | if ($this->logger === null) { |
||
109 | $this->logger = new NullLogger(); |
||
110 | } |
||
111 | |||
112 | $this->logger->info('Check new visits...'); |
||
113 | $totalEvents = $this->getEventsCount(); |
||
114 | if ($totalEvents > 0) { |
||
115 | $totalBatches = number_format(ceil($totalEvents / $this->getBatchSize())); |
||
116 | $this->logger->info( |
||
117 | sprintf( |
||
118 | '<info>Total visits to be processed - %s (%s batches).</info>', |
||
119 | number_format($totalEvents), |
||
120 | $totalBatches |
||
121 | ) |
||
122 | ); |
||
123 | while ($this->processVisits()) { |
||
124 | $this->logBatch(++$this->processedBatches, $totalBatches); |
||
125 | if ($this->checkMaxExecutionTime()) { |
||
126 | return; |
||
127 | } |
||
128 | } |
||
129 | } |
||
130 | |||
131 | $this->logger->info('Recheck previous visit identifiers...'); |
||
132 | $totalEvents = $this->getIdentifyPrevVisitsCount(); |
||
133 | View Code Duplication | if ($totalEvents > 0) { |
|
134 | $totalBatches = number_format(ceil($totalEvents / $this->getBatchSize())); |
||
135 | $this->processedBatches = 0; |
||
136 | $this->logger->info( |
||
137 | sprintf( |
||
138 | '<info>Total previous visit identifiers to be processed - %s (%s batches).</info>', |
||
139 | number_format($totalEvents), |
||
140 | $totalBatches |
||
141 | ) |
||
142 | ); |
||
143 | while ($this->identifyPrevVisits()) { |
||
144 | $this->logBatch(++$this->processedBatches, $totalBatches); |
||
145 | if ($this->checkMaxExecutionTime()) { |
||
146 | return; |
||
147 | } |
||
148 | } |
||
149 | } |
||
150 | |||
151 | $this->logger->info('Recheck previous visit events...'); |
||
152 | $totalEvents = $this->getIdentifyPrevVisitEventsCount(); |
||
153 | View Code Duplication | if ($totalEvents > 0) { |
|
154 | $totalBatches = number_format(ceil($totalEvents / $this->getBatchSize())); |
||
155 | $this->processedBatches = 0; |
||
156 | $this->logger->info( |
||
157 | sprintf( |
||
158 | '<info>Total previous visit events to be processed - %s (%s batches).</info>', |
||
159 | number_format($totalEvents), |
||
160 | $totalBatches |
||
161 | ) |
||
162 | ); |
||
163 | $this->skipList = []; |
||
164 | while ($this->identifyPrevVisitEvents()) { |
||
165 | $this->logBatch(++$this->processedBatches, $totalBatches); |
||
166 | if ($this->checkMaxExecutionTime()) { |
||
167 | return; |
||
168 | } |
||
169 | } |
||
170 | } |
||
171 | |||
172 | $this->logger->info('<info>Done</info>'); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * @param integer $processed |
||
177 | * @param string $total |
||
178 | */ |
||
179 | protected function logBatch($processed, $total) |
||
180 | { |
||
181 | $this->logger->info( |
||
182 | sprintf( |
||
183 | 'Batch #%s of %s processed at <info>%s</info>.', |
||
184 | number_format($processed), |
||
185 | $total, |
||
186 | date('Y-m-d H:i:s') |
||
187 | ) |
||
188 | ); |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * Checks of process max execution time |
||
193 | * |
||
194 | * @return bool |
||
195 | */ |
||
196 | protected function checkMaxExecutionTime() |
||
197 | { |
||
198 | if ($this->maxExecTimeout !== false) { |
||
199 | $date = $this->getCurrentUtcDateTime(); |
||
200 | if ($date->sub($this->maxExecTimeout) >= $this->startTime) { |
||
201 | $this->logger->info('<comment>Exit because allocated time frame elapsed.</comment>'); |
||
202 | |||
203 | return true; |
||
204 | } |
||
205 | } |
||
206 | |||
207 | return false; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Returns count of web events to be processed. |
||
212 | * |
||
213 | * @return integer |
||
214 | */ |
||
215 | protected function getEventsCount() |
||
216 | { |
||
217 | $em = $this->getEntityManager(); |
||
218 | $queryBuilder = $em |
||
219 | ->getRepository(self::TRACKING_EVENT_ENTITY) |
||
220 | ->createQueryBuilder('entity') |
||
221 | ->select('COUNT (entity.id)') |
||
222 | ->where('entity.parsed = false'); |
||
223 | |||
224 | return $queryBuilder->getQuery()->getSingleScalarResult(); |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Returns count of not identified web visits to be processed. |
||
229 | * |
||
230 | * @return integer |
||
231 | */ |
||
232 | View Code Duplication | protected function getIdentifyPrevVisitsCount() |
|
233 | { |
||
234 | $em = $this->getEntityManager(); |
||
235 | $queryBuilder = $em |
||
236 | ->getRepository(self::TRACKING_VISIT_ENTITY) |
||
237 | ->createQueryBuilder('entity'); |
||
238 | $queryBuilder |
||
239 | ->select('COUNT (entity.id)') |
||
240 | ->where('entity.identifierDetected = false') |
||
241 | ->andWhere('entity.parsedUID > 0') |
||
242 | ->andWhere('entity.parsingCount < :maxRetries') |
||
243 | ->setParameter('maxRetries', $this->getMaxRetriesCount()); |
||
244 | |||
245 | if (count($this->skipList)) { |
||
246 | $queryBuilder->andWhere('entity.id not in(' . implode(',', $this->skipList) . ')'); |
||
247 | } |
||
248 | |||
249 | return $queryBuilder->getQuery()->getSingleScalarResult(); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Returns count of tracking visit events to be processed. |
||
254 | * |
||
255 | * @return integer |
||
256 | */ |
||
257 | View Code Duplication | protected function getIdentifyPrevVisitEventsCount() |
|
258 | { |
||
259 | $em = $this->getEntityManager(); |
||
260 | $queryBuilder = $em |
||
261 | ->getRepository(self::TRACKING_VISIT_EVENT_ENTITY) |
||
262 | ->createQueryBuilder('entity'); |
||
263 | $queryBuilder |
||
264 | ->select('COUNT (entity.id)') |
||
265 | ->andWhere('entity.parsingCount < :maxRetries') |
||
266 | ->setParameter('maxRetries', $this->getMaxRetriesCount()); |
||
267 | |||
268 | if (count($this->skipList)) { |
||
269 | $queryBuilder->andWhere('entity.id not in(' . implode(',', $this->skipList) . ')'); |
||
270 | } |
||
271 | |||
272 | return $queryBuilder->getQuery()->getSingleScalarResult(); |
||
273 | } |
||
274 | |||
275 | /** |
||
276 | * Process previous visit events |
||
277 | * |
||
278 | * @return bool |
||
279 | */ |
||
280 | protected function identifyPrevVisitEvents() |
||
281 | { |
||
282 | $em = $this->getEntityManager(); |
||
283 | $queryBuilder = $em |
||
284 | ->getRepository(self::TRACKING_VISIT_EVENT_ENTITY) |
||
285 | ->createQueryBuilder('entity'); |
||
286 | $queryBuilder |
||
287 | ->select('entity') |
||
288 | ->andWhere('entity.parsingCount < :maxRetries') |
||
289 | ->setParameter('maxRetries', $this->getMaxRetriesCount()) |
||
290 | ->setMaxResults($this->getBatchSize()); |
||
291 | |||
292 | if (count($this->skipList)) { |
||
293 | $queryBuilder->andWhere('entity.id not in(' . implode(',', $this->skipList) . ')'); |
||
294 | } |
||
295 | |||
296 | /** @var TrackingVisitEvent[] $entities */ |
||
297 | $entities = $queryBuilder->getQuery()->getResult(); |
||
298 | if ($entities) { |
||
|
|||
299 | foreach ($entities as $visitEvent) { |
||
300 | $visitEvent->setParsingCount($visitEvent->getParsingCount() + 1); |
||
301 | $this->skipList[] = $visitEvent->getId(); |
||
302 | $targets = $this->trackingIdentification->processEvent($visitEvent); |
||
303 | if (!empty($targets)) { |
||
304 | foreach ($targets as $target) { |
||
305 | $visitEvent->addAssociationTarget($target); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | $em->persist($visitEvent); |
||
310 | } |
||
311 | |||
312 | $em->flush(); |
||
313 | $em->clear(); |
||
314 | |||
315 | return true; |
||
316 | } |
||
317 | |||
318 | return false; |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * Identify previous visits in case than we haven't data to identify visit previously |
||
323 | */ |
||
324 | protected function identifyPrevVisits() |
||
325 | { |
||
326 | $em = $this->getEntityManager(); |
||
327 | $queryBuilder = $em |
||
328 | ->getRepository(self::TRACKING_VISIT_ENTITY) |
||
329 | ->createQueryBuilder('entity'); |
||
330 | $queryBuilder |
||
331 | ->select('entity') |
||
332 | ->where('entity.identifierDetected = false') |
||
333 | ->andWhere('entity.parsedUID > 0') |
||
334 | ->andWhere('entity.parsingCount < :maxRetries') |
||
335 | ->orderBy('entity.firstActionTime', 'ASC') |
||
336 | ->setParameter('maxRetries', $this->getMaxRetriesCount()) |
||
337 | ->setMaxResults($this->getBatchSize()); |
||
338 | |||
339 | if (count($this->skipList)) { |
||
340 | $queryBuilder->andWhere('entity.id not in(' . implode(',', $this->skipList) . ')'); |
||
341 | } |
||
342 | |||
343 | $entities = $queryBuilder->getQuery()->getResult(); |
||
344 | if ($entities) { |
||
345 | /** @var TrackingVisit $visit */ |
||
346 | foreach ($entities as $visit) { |
||
347 | $idObj = $this->trackingIdentification->identify($visit); |
||
348 | if ($idObj && $idObj['targetObject']) { |
||
349 | $visit->setIdentifierTarget($idObj['targetObject']); |
||
350 | $visit->setIdentifierDetected(true); |
||
351 | |||
352 | $this->logger->info('-- <comment>parsed UID "' . $idObj['parsedUID'] . '"</comment>'); |
||
353 | } else { |
||
354 | $visit->setParsingCount($visit->getParsingCount() + 1); |
||
355 | $this->skipList[] = $visit->getId(); |
||
356 | } |
||
357 | |||
358 | $em->persist($visit); |
||
359 | $this->collectedVisits[] = $visit; |
||
360 | } |
||
361 | |||
362 | $em->flush(); |
||
363 | |||
364 | $this->updateVisits($this->collectedVisits); |
||
365 | |||
366 | $this->collectedVisits = []; |
||
367 | $em->clear(); |
||
368 | |||
369 | return true; |
||
370 | } |
||
371 | |||
372 | return false; |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | * Identify previous visits |
||
377 | * |
||
378 | * @param array $entities |
||
379 | */ |
||
380 | protected function updateVisits($entities) |
||
381 | { |
||
382 | /** @var TrackingVisit $visit */ |
||
383 | foreach ($entities as $visit) { |
||
384 | $this->logger->info( |
||
385 | sprintf( |
||
386 | 'Process visit id: %s, visitorUid: %s', |
||
387 | $visit->getId(), |
||
388 | $visit->getVisitorUid() |
||
389 | ) |
||
390 | ); |
||
391 | |||
392 | $identifier = $visit->getIdentifierTarget(); |
||
393 | if ($identifier) { |
||
394 | // update tracking event identifiers |
||
395 | $associationName = ExtendHelper::buildAssociationName( |
||
396 | ClassUtils::getClass($identifier), |
||
397 | VisitEventAssociationExtension::ASSOCIATION_KIND |
||
398 | ); |
||
399 | |||
400 | $qb = $this->getEntityManager() |
||
401 | ->createQueryBuilder(); |
||
402 | |||
403 | $subSelect = $qb->select('entity.id') |
||
404 | ->from(self::TRACKING_VISIT_ENTITY, 'entity') |
||
405 | ->where('entity.visitorUid = :visitorUid') |
||
406 | ->andWhere('entity.firstActionTime < :maxDate') |
||
407 | ->andWhere('entity.identifierDetected = false') |
||
408 | ->andWhere('entity.parsedUID = 0') |
||
409 | ->andWhere('entity.trackingWebsite = :website') |
||
410 | ->setParameter('visitorUid', $visit->getVisitorUid()) |
||
411 | ->setParameter('maxDate', $visit->getFirstActionTime()) |
||
412 | ->setParameter('website', $visit->getTrackingWebsite()) |
||
413 | ->getQuery() |
||
414 | ->getArrayResult(); |
||
415 | if (!empty($subSelect)) { |
||
416 | array_walk( |
||
417 | $subSelect, |
||
418 | function (&$value) { |
||
419 | $value = $value['id']; |
||
420 | } |
||
421 | ); |
||
422 | |||
423 | $this->getEntityManager()->createQueryBuilder() |
||
424 | ->update(self::TRACKING_VISIT_EVENT_ENTITY, 'event') |
||
425 | ->set('event.' . $associationName, ':identifier') |
||
426 | ->where('event.visit in(' . implode(',', $subSelect) . ')') |
||
427 | ->setParameter('identifier', $identifier) |
||
428 | ->getQuery() |
||
429 | ->execute(); |
||
430 | } |
||
431 | |||
432 | $associationName = ExtendHelper::buildAssociationName( |
||
433 | ClassUtils::getClass($identifier), |
||
434 | IdentifierEventExtension::ASSOCIATION_KIND |
||
435 | ); |
||
436 | |||
437 | $this->getEntityManager() |
||
438 | ->createQueryBuilder() |
||
439 | ->update(self::TRACKING_VISIT_ENTITY, 'entity') |
||
440 | ->set('entity.' . $associationName, ':identifier') |
||
441 | ->set('entity.identifierDetected', ':detected') |
||
442 | ->where('entity.visitorUid = :visitorUid') |
||
443 | ->andWhere('entity.firstActionTime < :maxDate') |
||
444 | ->andWhere('entity.identifierDetected = false') |
||
445 | ->andWhere('entity.parsedUID = 0') |
||
446 | ->andWhere('entity.trackingWebsite = :website') |
||
447 | ->setParameter('visitorUid', $visit->getVisitorUid()) |
||
448 | ->setParameter('maxDate', $visit->getFirstActionTime()) |
||
449 | ->setParameter('website', $visit->getTrackingWebsite()) |
||
450 | ->setParameter('identifier', $identifier) |
||
451 | ->setParameter('detected', true) |
||
452 | ->getQuery() |
||
453 | ->execute(); |
||
454 | } |
||
455 | } |
||
456 | |||
457 | $this->deviceDetector->clearInstances(); |
||
458 | } |
||
459 | |||
460 | /** |
||
461 | * Collect new tracking visits with tracking visit events |
||
462 | */ |
||
463 | protected function processVisits() |
||
464 | { |
||
465 | $queryBuilder = $this->getEntityManager() |
||
466 | ->getRepository(self::TRACKING_EVENT_ENTITY) |
||
467 | ->createQueryBuilder('entity') |
||
468 | ->where('entity.parsed = false') |
||
469 | ->orderBy('entity.id', 'ASC') |
||
470 | ->setMaxResults($this->getBatchSize()); |
||
471 | |||
472 | $entities = $queryBuilder->getQuery()->getResult(); |
||
473 | |||
474 | if ($entities) { |
||
475 | $this->processTrackingVisits($entities); |
||
476 | |||
477 | return true; |
||
478 | } |
||
479 | |||
480 | return false; |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * @param array|TrackingEvent[] $entities |
||
485 | */ |
||
486 | protected function processTrackingVisits($entities) |
||
487 | { |
||
488 | $em = $this->getEntityManager(); |
||
489 | |||
490 | /** @var TrackingEvent $event */ |
||
491 | foreach ($entities as $event) { |
||
492 | $this->logger->info('Processing event - ' . $event->getId()); |
||
493 | |||
494 | $trackingVisitEvent = new TrackingVisitEvent(); |
||
495 | $trackingVisitEvent->setParsingCount(0); |
||
496 | $trackingVisitEvent->setEvent($this->getEventType($event)); |
||
497 | |||
498 | $eventData = $event->getEventData(); |
||
499 | $decodedData = json_decode($eventData->getData(), true); |
||
500 | |||
501 | $trackingVisit = $this->getTrackingVisit($event, $decodedData); |
||
502 | $trackingVisitEvent->setVisit($trackingVisit); |
||
503 | $trackingVisitEvent->setWebEvent($event); |
||
504 | $trackingVisitEvent->setWebsite($event->getWebsite()); |
||
505 | |||
506 | $targets = $this->trackingIdentification->processEvent($trackingVisitEvent); |
||
507 | if (!empty($targets)) { |
||
508 | foreach ($targets as $target) { |
||
509 | $trackingVisitEvent->addAssociationTarget($target); |
||
510 | } |
||
511 | } |
||
512 | |||
513 | $event->setParsed(true); |
||
514 | |||
515 | $em->persist($event); |
||
516 | $em->persist($trackingVisitEvent); |
||
517 | $em->persist($trackingVisit); |
||
518 | } |
||
519 | |||
520 | $em->flush(); |
||
521 | |||
522 | $this->updateVisits($this->collectedVisits); |
||
523 | |||
524 | $this->collectedVisits = []; |
||
525 | $this->eventDictionary = []; |
||
526 | $em->clear(); |
||
527 | |||
528 | $this->logger->info( |
||
529 | sprintf( |
||
530 | '<comment>Memory usage (currently) %dMB/ (max) %dMB</comment>', |
||
531 | round(memory_get_usage(true) / 1024 / 1024), |
||
532 | memory_get_peak_usage(true) / 1024 / 1024 |
||
533 | ) |
||
534 | ); |
||
535 | } |
||
536 | |||
537 | /** |
||
538 | * @param TrackingEvent $trackingEvent |
||
539 | * @param array $decodedData |
||
540 | * |
||
541 | * @return TrackingVisit |
||
542 | */ |
||
543 | protected function getTrackingVisit(TrackingEvent $trackingEvent, $decodedData) |
||
544 | { |
||
545 | $visitorUid = $decodedData['_id']; |
||
546 | $userIdentifier = $trackingEvent->getUserIdentifier(); |
||
547 | |||
548 | $hash = md5($visitorUid . $userIdentifier); |
||
549 | |||
550 | // try to find existing visit |
||
551 | if (!empty($this->collectedVisits) && array_key_exists($hash, $this->collectedVisits)) { |
||
552 | $visit = $this->collectedVisits[$hash]; |
||
553 | } else { |
||
554 | $visit = $this->doctrine->getRepository(self::TRACKING_VISIT_ENTITY)->findOneBy( |
||
555 | [ |
||
556 | 'visitorUid' => $visitorUid, |
||
557 | 'userIdentifier' => $trackingEvent->getUserIdentifier(), |
||
558 | 'trackingWebsite' => $trackingEvent->getWebsite() |
||
559 | ] |
||
560 | ); |
||
561 | } |
||
562 | |||
563 | if (!$visit) { |
||
564 | $visit = new TrackingVisit(); |
||
565 | $visit->setParsedUID(0); |
||
566 | $visit->setParsingCount(0); |
||
567 | $visit->setUserIdentifier($trackingEvent->getUserIdentifier()); |
||
568 | $visit->setVisitorUid($visitorUid); |
||
569 | $visit->setFirstActionTime($trackingEvent->getCreatedAt()); |
||
570 | $visit->setLastActionTime($trackingEvent->getCreatedAt()); |
||
571 | $visit->setTrackingWebsite($trackingEvent->getWebsite()); |
||
572 | $visit->setIdentifierDetected(false); |
||
573 | |||
574 | if (!empty($decodedData['cip'])) { |
||
575 | $visit->setIp($decodedData['cip']); |
||
576 | } |
||
577 | |||
578 | if (!empty($decodedData['ua'])) { |
||
579 | $this->processUserAgentString($visit, $decodedData['ua']); |
||
580 | } |
||
581 | |||
582 | $this->identifyTrackingVisit($visit); |
||
583 | |||
584 | $this->collectedVisits[$hash] = $visit; |
||
585 | } else { |
||
586 | if ($visit->getFirstActionTime() > $trackingEvent->getCreatedAt()) { |
||
587 | $visit->setFirstActionTime($trackingEvent->getCreatedAt()); |
||
588 | } |
||
589 | if ($visit->getLastActionTime() < $trackingEvent->getCreatedAt()) { |
||
590 | $visit->setLastActionTime($trackingEvent->getCreatedAt()); |
||
591 | } |
||
592 | } |
||
593 | |||
594 | return $visit; |
||
595 | } |
||
596 | |||
597 | /** |
||
598 | * @param TrackingVisit $visit |
||
599 | * @param string $ua |
||
600 | * |
||
601 | * @SuppressWarnings(PHPMD.NPathComplexity) |
||
602 | * because of ternary operators which in current case is clear enough to replace it with 'if' statement. |
||
603 | */ |
||
604 | protected function processUserAgentString(TrackingVisit $visit, $ua) |
||
605 | { |
||
606 | $device = $this->deviceDetector->getInstance($ua); |
||
607 | $os = $device->getOs(); |
||
608 | if (is_array($os)) { |
||
609 | $visit->setOs(isset($os['name']) ? $os['name'] : null); |
||
610 | $visit->setOsVersion(isset($os['version']) ? $os['version'] : null); |
||
611 | } |
||
612 | |||
613 | $client = $device->getClient(); |
||
614 | if (is_array($client)) { |
||
615 | $visit->setClient(isset($client['name']) ? $client['name'] : null); |
||
616 | $visit->setClientType(isset($client['type']) ? $client['type'] : null); |
||
617 | $visit->setClientVersion(isset($client['version']) ? $client['version'] : null); |
||
618 | } |
||
619 | |||
620 | $visit->setDesktop($device->isDesktop()); |
||
621 | $visit->setMobile($device->isMobile()); |
||
622 | $visit->setBot($device->isBot()); |
||
623 | } |
||
624 | |||
625 | /** |
||
626 | * Get Event dictionary for given tracking event |
||
627 | * |
||
628 | * @param TrackingEvent $event |
||
629 | * @return TrackingEventDictionary |
||
630 | */ |
||
631 | protected function getEventType(TrackingEvent $event) |
||
632 | { |
||
633 | $eventWebsite = $event->getWebsite(); |
||
634 | if ($eventWebsite |
||
635 | && isset( |
||
636 | $this->eventDictionary[$eventWebsite->getId()], |
||
637 | $this->eventDictionary[$eventWebsite->getId()][$event->getName()] |
||
638 | ) |
||
639 | ) { |
||
640 | $eventType = $this->eventDictionary[$eventWebsite->getId()][$event->getName()]; |
||
641 | } else { |
||
642 | $eventType = $this->getEntityManager() |
||
643 | ->getRepository('OroTrackingBundle:TrackingEventDictionary') |
||
644 | ->findOneBy( |
||
645 | [ |
||
646 | 'name' => $event->getName(), |
||
647 | 'website' => $eventWebsite |
||
648 | ] |
||
649 | ); |
||
650 | } |
||
651 | |||
652 | if (!$eventType) { |
||
653 | $eventType = new TrackingEventDictionary(); |
||
654 | $eventType->setName($event->getName()); |
||
655 | $eventType->setWebsite($eventWebsite); |
||
656 | |||
657 | $this->getEntityManager()->persist($eventType); |
||
658 | |||
659 | $this->eventDictionary[$eventWebsite ? $eventWebsite->getId() : null][$event->getName()] = $eventType; |
||
660 | } |
||
661 | |||
662 | return $eventType; |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * @param TrackingVisit $visit |
||
667 | */ |
||
668 | protected function identifyTrackingVisit(TrackingVisit $visit) |
||
669 | { |
||
670 | /** |
||
671 | * try to identify visit |
||
672 | */ |
||
673 | $idObj = $this->trackingIdentification->identify($visit); |
||
674 | if ($idObj) { |
||
675 | /** |
||
676 | * if identification was successful we should: |
||
677 | * - assign visit to target |
||
678 | * - assign all previous visits to same identified object(s). |
||
679 | */ |
||
680 | $this->logger->info('-- <comment>parsed UID "' . $idObj['parsedUID'] . '"</comment>'); |
||
681 | if ($idObj['parsedUID'] !== null) { |
||
682 | $visit->setParsedUID($idObj['parsedUID']); |
||
683 | if ($idObj['targetObject']) { |
||
684 | $visit->setIdentifierTarget($idObj['targetObject']); |
||
685 | $visit->setIdentifierDetected(true); |
||
686 | } |
||
687 | } |
||
688 | } |
||
689 | } |
||
690 | |||
691 | /** |
||
692 | * Returns default entity manager |
||
693 | * |
||
694 | * @return EntityManager |
||
695 | */ |
||
696 | View Code Duplication | protected function getEntityManager() |
|
697 | { |
||
698 | /** @var EntityManager $em */ |
||
699 | $em = $this->doctrine->getManager(); |
||
700 | if (!$em->isOpen()) { |
||
701 | $this->doctrine->resetManager(); |
||
702 | $em = $this->doctrine->getManager(); |
||
703 | } |
||
704 | |||
705 | return $em; |
||
706 | } |
||
707 | |||
708 | /** |
||
709 | * Get max retries to identify tracking visit |
||
710 | * |
||
711 | * @return int |
||
712 | */ |
||
713 | protected function getMaxRetriesCount() |
||
717 | |||
718 | /** |
||
719 | * Get batch size for tracking events |
||
720 | * |
||
721 | * @return int |
||
722 | */ |
||
723 | protected function getBatchSize() |
||
727 | |||
728 | /** |
||
729 | * Gets a DateTime object that is set to the current date and time in UTC. |
||
730 | * |
||
731 | * @return \DateTime |
||
732 | */ |
||
733 | protected function getCurrentUtcDateTime() |
||
737 | } |
||
738 |
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.