1 | <?php |
||
2 | |||
3 | /* |
||
4 | * @copyright 2014 Mautic Contributors. All rights reserved |
||
5 | * @author Mautic |
||
6 | * |
||
7 | * @link http://mautic.org |
||
8 | * |
||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||
10 | */ |
||
11 | |||
12 | namespace Mautic\PageBundle\Model; |
||
13 | |||
14 | use Doctrine\DBAL\Query\QueryBuilder; |
||
15 | use Mautic\CoreBundle\Helper\Chart\ChartQuery; |
||
16 | use Mautic\CoreBundle\Helper\Chart\LineChart; |
||
17 | use Mautic\CoreBundle\Helper\Chart\PieChart; |
||
18 | use Mautic\CoreBundle\Helper\CookieHelper; |
||
19 | use Mautic\CoreBundle\Helper\CoreParametersHelper; |
||
20 | use Mautic\CoreBundle\Helper\DateTimeHelper; |
||
21 | use Mautic\CoreBundle\Helper\InputHelper; |
||
22 | use Mautic\CoreBundle\Helper\IpLookupHelper; |
||
23 | use Mautic\CoreBundle\Model\BuilderModelTrait; |
||
24 | use Mautic\CoreBundle\Model\FormModel; |
||
25 | use Mautic\CoreBundle\Model\TranslationModelTrait; |
||
26 | use Mautic\CoreBundle\Model\VariantModelTrait; |
||
27 | use Mautic\LeadBundle\DataObject\LeadManipulator; |
||
28 | use Mautic\LeadBundle\Entity\Company; |
||
29 | use Mautic\LeadBundle\Entity\Lead; |
||
30 | use Mautic\LeadBundle\Entity\UtmTag; |
||
31 | use Mautic\LeadBundle\Helper\IdentifyCompanyHelper; |
||
32 | use Mautic\LeadBundle\Model\CompanyModel; |
||
33 | use Mautic\LeadBundle\Model\FieldModel; |
||
34 | use Mautic\LeadBundle\Model\LeadModel; |
||
35 | use Mautic\LeadBundle\Tracker\ContactTracker; |
||
36 | use Mautic\LeadBundle\Tracker\DeviceTracker; |
||
37 | use Mautic\PageBundle\Entity\Hit; |
||
38 | use Mautic\PageBundle\Entity\Page; |
||
39 | use Mautic\PageBundle\Entity\Redirect; |
||
40 | use Mautic\PageBundle\Event\PageBuilderEvent; |
||
41 | use Mautic\PageBundle\Event\PageEvent; |
||
42 | use Mautic\PageBundle\Event\PageHitEvent; |
||
43 | use Mautic\PageBundle\Form\Type\PageType; |
||
44 | use Mautic\PageBundle\PageEvents; |
||
45 | use Mautic\QueueBundle\Queue\QueueName; |
||
46 | use Mautic\QueueBundle\Queue\QueueService; |
||
47 | use Symfony\Component\EventDispatcher\Event; |
||
48 | use Symfony\Component\HttpFoundation\Request; |
||
49 | use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; |
||
50 | |||
51 | class PageModel extends FormModel |
||
52 | { |
||
53 | use TranslationModelTrait; |
||
54 | use VariantModelTrait; |
||
55 | use BuilderModelTrait; |
||
56 | |||
57 | /** |
||
58 | * @var bool |
||
59 | */ |
||
60 | protected $catInUrl; |
||
61 | |||
62 | /** |
||
63 | * @var CookieHelper |
||
64 | */ |
||
65 | protected $cookieHelper; |
||
66 | |||
67 | /** |
||
68 | * @var IpLookupHelper |
||
69 | */ |
||
70 | protected $ipLookupHelper; |
||
71 | |||
72 | /** |
||
73 | * @var LeadModel |
||
74 | */ |
||
75 | protected $leadModel; |
||
76 | |||
77 | /** |
||
78 | * @var FieldModel |
||
79 | */ |
||
80 | protected $leadFieldModel; |
||
81 | |||
82 | /** |
||
83 | * @var RedirectModel |
||
84 | */ |
||
85 | protected $pageRedirectModel; |
||
86 | |||
87 | /** |
||
88 | * @var TrackableModel |
||
89 | */ |
||
90 | protected $pageTrackableModel; |
||
91 | |||
92 | /** |
||
93 | * @var DateTimeHelper |
||
94 | */ |
||
95 | protected $dateTimeHelper; |
||
96 | |||
97 | /** |
||
98 | * @var QueueService |
||
99 | */ |
||
100 | protected $queueService; |
||
101 | |||
102 | /** |
||
103 | * @var CoreParametersHelper |
||
104 | */ |
||
105 | protected $coreParametersHelper; |
||
106 | |||
107 | /** |
||
108 | * @var DeviceTracker |
||
109 | */ |
||
110 | private $deviceTracker; |
||
111 | |||
112 | /** |
||
113 | * @var CompanyModel |
||
114 | */ |
||
115 | private $companyModel; |
||
116 | |||
117 | /** |
||
118 | * @var ContactTracker |
||
119 | */ |
||
120 | private $contactTracker; |
||
121 | |||
122 | /** |
||
123 | * PageModel constructor. |
||
124 | */ |
||
125 | public function __construct( |
||
126 | CookieHelper $cookieHelper, |
||
127 | IpLookupHelper $ipLookupHelper, |
||
128 | LeadModel $leadModel, |
||
129 | FieldModel $leadFieldModel, |
||
130 | RedirectModel $pageRedirectModel, |
||
131 | TrackableModel $pageTrackableModel, |
||
132 | QueueService $queueService, |
||
133 | CompanyModel $companyModel, |
||
134 | DeviceTracker $deviceTracker, |
||
135 | ContactTracker $contactTracker, |
||
136 | CoreParametersHelper $coreParametersHelper |
||
137 | ) { |
||
138 | $this->cookieHelper = $cookieHelper; |
||
139 | $this->ipLookupHelper = $ipLookupHelper; |
||
140 | $this->leadModel = $leadModel; |
||
141 | $this->leadFieldModel = $leadFieldModel; |
||
142 | $this->pageRedirectModel = $pageRedirectModel; |
||
143 | $this->pageTrackableModel = $pageTrackableModel; |
||
144 | $this->dateTimeHelper = new DateTimeHelper(); |
||
145 | $this->queueService = $queueService; |
||
146 | $this->companyModel = $companyModel; |
||
147 | $this->deviceTracker = $deviceTracker; |
||
148 | $this->contactTracker = $contactTracker; |
||
149 | $this->coreParametersHelper = $coreParametersHelper; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param $catInUrl |
||
154 | */ |
||
155 | public function setCatInUrl($catInUrl) |
||
156 | { |
||
157 | $this->catInUrl = $catInUrl; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * @return \Mautic\PageBundle\Entity\PageRepository |
||
162 | */ |
||
163 | public function getRepository() |
||
164 | { |
||
165 | $repo = $this->em->getRepository('MauticPageBundle:Page'); |
||
166 | $repo->setCurrentUser($this->userHelper->getUser()); |
||
167 | |||
168 | return $repo; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * @return \Mautic\PageBundle\Entity\HitRepository |
||
173 | */ |
||
174 | public function getHitRepository() |
||
175 | { |
||
176 | return $this->em->getRepository('MauticPageBundle:Hit'); |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * {@inheritdoc} |
||
181 | */ |
||
182 | public function getPermissionBase() |
||
183 | { |
||
184 | return 'page:pages'; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * {@inheritdoc} |
||
189 | */ |
||
190 | public function getNameGetter() |
||
191 | { |
||
192 | return 'getTitle'; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * {@inheritdoc} |
||
197 | * |
||
198 | * @param Page $entity |
||
199 | * @param bool $unlock |
||
200 | */ |
||
201 | public function saveEntity($entity, $unlock = true) |
||
202 | { |
||
203 | $pageIds = $entity->getRelatedEntityIds(); |
||
204 | |||
205 | if (empty($this->inConversion)) { |
||
206 | $alias = $entity->getAlias(); |
||
207 | if (empty($alias)) { |
||
208 | $alias = $entity->getTitle(); |
||
209 | } |
||
210 | $alias = $this->cleanAlias($alias, '', false, '-'); |
||
211 | |||
212 | //make sure alias is not already taken |
||
213 | $repo = $this->getRepository(); |
||
214 | $testAlias = $alias; |
||
215 | $count = $repo->checkPageUniqueAlias($testAlias, $pageIds); |
||
216 | $aliasTag = 1; |
||
217 | |||
218 | while ($count) { |
||
219 | $testAlias = $alias.$aliasTag; |
||
220 | $count = $repo->checkPageUniqueAlias($testAlias, $pageIds); |
||
221 | ++$aliasTag; |
||
222 | } |
||
223 | if ($testAlias != $alias) { |
||
224 | $alias = $testAlias; |
||
225 | } |
||
226 | $entity->setAlias($alias); |
||
227 | } |
||
228 | |||
229 | // Set the author for new pages |
||
230 | $isNew = $entity->isNew(); |
||
231 | if (!$isNew) { |
||
232 | //increase the revision |
||
233 | $revision = $entity->getRevision(); |
||
234 | ++$revision; |
||
235 | $entity->setRevision($revision); |
||
236 | } |
||
237 | |||
238 | // Reset a/b test if applicable |
||
239 | $variantStartDate = new \DateTime(); |
||
240 | $resetVariants = $this->preVariantSaveEntity($entity, ['setVariantHits'], $variantStartDate); |
||
241 | |||
242 | parent::saveEntity($entity, $unlock); |
||
243 | |||
244 | $this->postVariantSaveEntity($entity, $resetVariants, $pageIds, $variantStartDate); |
||
245 | $this->postTranslationEntitySave($entity); |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * @param Page $entity |
||
250 | */ |
||
251 | public function deleteEntity($entity) |
||
252 | { |
||
253 | if ($entity->isVariant() && $entity->getIsPublished()) { |
||
254 | $this->resetVariants($entity); |
||
255 | } |
||
256 | |||
257 | parent::deleteEntity($entity); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * {@inheritdoc} |
||
262 | * |
||
263 | * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException |
||
264 | */ |
||
265 | public function createForm($entity, $formFactory, $action = null, $options = []) |
||
266 | { |
||
267 | if (!$entity instanceof Page) { |
||
268 | throw new MethodNotAllowedHttpException(['Page']); |
||
269 | } |
||
270 | |||
271 | $formClass = PageType::class; |
||
272 | |||
273 | if (!empty($options['formName'])) { |
||
274 | $formClass = $options['formName']; |
||
275 | } |
||
276 | |||
277 | if (!empty($action)) { |
||
278 | $options['action'] = $action; |
||
279 | } |
||
280 | |||
281 | return $formFactory->create($formClass, $entity, $options); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * {@inheritdoc} |
||
286 | * |
||
287 | * @return Page|null |
||
288 | */ |
||
289 | public function getEntity($id = null) |
||
290 | { |
||
291 | if (null === $id) { |
||
292 | $entity = new Page(); |
||
293 | $entity->setSessionId('new_'.hash('sha1', uniqid(mt_rand()))); |
||
294 | } else { |
||
295 | $entity = parent::getEntity($id); |
||
296 | if (null !== $entity) { |
||
297 | $entity->setSessionId($entity->getId()); |
||
298 | } |
||
299 | } |
||
300 | |||
301 | return $entity; |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * {@inheritdoc} |
||
306 | * |
||
307 | * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException |
||
308 | */ |
||
309 | protected function dispatchEvent($action, &$entity, $isNew = false, Event $event = null) |
||
310 | { |
||
311 | if (!$entity instanceof Page) { |
||
312 | throw new MethodNotAllowedHttpException(['Page']); |
||
313 | } |
||
314 | |||
315 | switch ($action) { |
||
316 | case 'pre_save': |
||
317 | $name = PageEvents::PAGE_PRE_SAVE; |
||
318 | break; |
||
319 | case 'post_save': |
||
320 | $name = PageEvents::PAGE_POST_SAVE; |
||
321 | break; |
||
322 | case 'pre_delete': |
||
323 | $name = PageEvents::PAGE_PRE_DELETE; |
||
324 | break; |
||
325 | case 'post_delete': |
||
326 | $name = PageEvents::PAGE_POST_DELETE; |
||
327 | break; |
||
328 | default: |
||
329 | return null; |
||
330 | } |
||
331 | |||
332 | if ($this->dispatcher->hasListeners($name)) { |
||
333 | if (empty($event)) { |
||
334 | $event = new PageEvent($entity, $isNew); |
||
335 | $event->setEntityManager($this->em); |
||
336 | } |
||
337 | |||
338 | $this->dispatcher->dispatch($name, $event); |
||
339 | |||
340 | return $event; |
||
341 | } |
||
342 | |||
343 | return null; |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Get list of entities for autopopulate fields. |
||
348 | * |
||
349 | * @param string $type |
||
350 | * @param string $filter |
||
351 | * @param int $limit |
||
352 | * |
||
353 | * @return array |
||
354 | */ |
||
355 | public function getLookupResults($type, $filter = '', $limit = 10) |
||
356 | { |
||
357 | $results = []; |
||
358 | switch ($type) { |
||
359 | case 'page': |
||
360 | $viewOther = $this->security->isGranted('page:pages:viewother'); |
||
361 | $repo = $this->getRepository(); |
||
362 | $repo->setCurrentUser($this->userHelper->getUser()); |
||
363 | $results = $repo->getPageList($filter, $limit, 0, $viewOther); |
||
364 | break; |
||
365 | } |
||
366 | |||
367 | return $results; |
||
368 | } |
||
369 | |||
370 | /** |
||
371 | * Generate URL for a page. |
||
372 | * |
||
373 | * @param Page $entity |
||
374 | * @param bool $absolute |
||
375 | * @param array $clickthrough |
||
376 | * |
||
377 | * @return string |
||
378 | */ |
||
379 | public function generateUrl($entity, $absolute = true, $clickthrough = []) |
||
380 | { |
||
381 | // If this is a variant, then get the parent's URL |
||
382 | $parent = $entity->getVariantParent(); |
||
383 | if (null != $parent) { |
||
384 | $entity = $parent; |
||
385 | } |
||
386 | |||
387 | $slug = $this->generateSlug($entity); |
||
388 | |||
389 | return $this->buildUrl('mautic_page_public', ['slug' => $slug], $absolute, $clickthrough); |
||
390 | } |
||
391 | |||
392 | /** |
||
393 | * Generates slug string. |
||
394 | * |
||
395 | * @param $entity |
||
396 | * |
||
397 | * @return string |
||
398 | */ |
||
399 | public function generateSlug($entity) |
||
400 | { |
||
401 | $pageSlug = $entity->getAlias(); |
||
402 | |||
403 | //should the url include the category |
||
404 | if ($this->catInUrl) { |
||
405 | $category = $entity->getCategory(); |
||
406 | $catSlug = (!empty($category)) |
||
407 | ? $category->getAlias() |
||
408 | : |
||
409 | $this->translator->trans('mautic.core.url.uncategorized'); |
||
410 | } |
||
411 | |||
412 | $parent = $entity->getTranslationParent(); |
||
413 | $slugs = []; |
||
414 | if ($parent) { |
||
415 | //multiple languages so tack on the language |
||
416 | $slugs[] = $entity->getLanguage(); |
||
417 | } |
||
418 | |||
419 | if (!empty($catSlug)) { |
||
420 | // Insert category slug |
||
421 | $slugs[] = $catSlug; |
||
422 | $slugs[] = $pageSlug; |
||
423 | } else { |
||
424 | // Insert just the page slug |
||
425 | $slugs[] = $pageSlug; |
||
426 | } |
||
427 | |||
428 | return implode('/', $slugs); |
||
429 | } |
||
430 | |||
431 | /** |
||
432 | * @return array|mixed |
||
433 | */ |
||
434 | protected function generateClickThrough(Hit $hit) |
||
435 | { |
||
436 | $query = $hit->getQuery(); |
||
437 | |||
438 | // Check for any clickthrough info |
||
439 | $clickthrough = []; |
||
440 | if (!empty($query['ct'])) { |
||
441 | $clickthrough = $query['ct']; |
||
442 | if (!is_array($clickthrough)) { |
||
443 | $clickthrough = $this->decodeArrayFromUrl($clickthrough); |
||
444 | } |
||
445 | } |
||
446 | |||
447 | return $clickthrough; |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * @param Page|Redirect $page |
||
452 | * @param string $code |
||
453 | * @param array $query |
||
454 | * |
||
455 | * @throws \Exception |
||
456 | */ |
||
457 | public function hitPage($page, Request $request, $code = '200', Lead $lead = null, $query = []) |
||
458 | { |
||
459 | // Don't skew results with user hits |
||
460 | if (!$this->security->isAnonymous()) { |
||
461 | return; |
||
462 | } |
||
463 | |||
464 | // Process the query |
||
465 | if (empty($query)) { |
||
466 | $query = $this->getHitQuery($request, $page); |
||
467 | } |
||
468 | |||
469 | // Get lead if required |
||
470 | if (null == $lead) { |
||
471 | $lead = $this->leadModel->getContactFromRequest($query); |
||
472 | |||
473 | // company |
||
474 | list($company, $leadAdded, $companyEntity) = IdentifyCompanyHelper::identifyLeadsCompany($query, $lead, $this->companyModel); |
||
475 | if ($leadAdded) { |
||
476 | $lead->addCompanyChangeLogEntry('form', 'Identify Company', 'Lead added to the company, '.$company['companyname'], $company['id']); |
||
477 | } elseif ($companyEntity instanceof Company) { |
||
478 | $this->companyModel->setFieldValues($companyEntity, $query); |
||
479 | $this->companyModel->saveEntity($companyEntity); |
||
480 | } |
||
481 | |||
482 | if (!empty($company) and $companyEntity instanceof Company) { |
||
483 | // Save after the lead in for new leads created through the API and maybe other places |
||
484 | $this->companyModel->addLeadToCompany($companyEntity, $lead); |
||
485 | $this->leadModel->setPrimaryCompany($companyEntity->getId(), $lead->getId()); |
||
486 | } |
||
487 | } |
||
488 | |||
489 | if (!$lead || !$lead->getId()) { |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
490 | // Lead came from a non-trackable IP so ignore |
||
491 | return; |
||
492 | } |
||
493 | |||
494 | $hit = new Hit(); |
||
495 | $hit->setDateHit(new \Datetime()); |
||
496 | $hit->setIpAddress($this->ipLookupHelper->getIpAddress()); |
||
497 | |||
498 | // Set info from request |
||
499 | $hit->setQuery($query); |
||
500 | $hit->setCode($code); |
||
501 | |||
502 | $trackedDevice = $this->deviceTracker->createDeviceFromUserAgent($lead, $request->server->get('HTTP_USER_AGENT')); |
||
503 | |||
504 | $hit->setTrackingId($trackedDevice->getTrackingId()); |
||
505 | $hit->setDeviceStat($trackedDevice); |
||
506 | |||
507 | // Wrap in a try/catch to prevent deadlock errors on busy servers |
||
508 | try { |
||
509 | $this->em->persist($hit); |
||
510 | $this->em->flush(); |
||
511 | } catch (\Exception $exception) { |
||
512 | if (MAUTIC_ENV === 'dev') { |
||
513 | throw $exception; |
||
514 | } else { |
||
515 | $this->logger->addError( |
||
516 | $exception->getMessage(), |
||
517 | ['exception' => $exception] |
||
518 | ); |
||
519 | } |
||
520 | } |
||
521 | |||
522 | //save hit to the cookie to use to update the exit time |
||
523 | if ($hit) { |
||
0 ignored issues
–
show
|
|||
524 | $this->cookieHelper->setCookie('mautic_referer_id', $hit->getId() ?: null); |
||
525 | } |
||
526 | |||
527 | if ($this->queueService->isQueueEnabled()) { |
||
528 | $msg = [ |
||
529 | 'hitId' => $hit->getId(), |
||
530 | 'pageId' => $page ? $page->getId() : null, |
||
531 | 'request' => $request, |
||
532 | 'leadId' => $lead ? $lead->getId() : null, |
||
0 ignored issues
–
show
|
|||
533 | 'isNew' => $this->deviceTracker->wasDeviceChanged(), |
||
534 | 'isRedirect' => ($page instanceof Redirect), |
||
535 | ]; |
||
536 | $this->queueService->publishToQueue(QueueName::PAGE_HIT, $msg); |
||
537 | } else { |
||
538 | $this->processPageHit($hit, $page, $request, $lead, $this->deviceTracker->wasDeviceChanged()); |
||
539 | } |
||
540 | } |
||
541 | |||
542 | /** |
||
543 | * Process page hit. |
||
544 | * |
||
545 | * @param Page|Redirect $page |
||
546 | * @param bool $trackingNewlyGenerated |
||
547 | * @param bool $activeRequest |
||
548 | * |
||
549 | * @throws \Exception |
||
550 | */ |
||
551 | public function processPageHit(Hit $hit, $page, Request $request, Lead $lead, $trackingNewlyGenerated, $activeRequest = true) |
||
552 | { |
||
553 | // Store Page/Redirect association |
||
554 | if ($page) { |
||
555 | if ($page instanceof Page) { |
||
556 | $hit->setPage($page); |
||
557 | } else { |
||
558 | $hit->setRedirect($page); |
||
559 | } |
||
560 | } |
||
561 | |||
562 | // Check for any clickthrough info |
||
563 | $clickthrough = $this->generateClickThrough($hit); |
||
564 | if (!empty($clickthrough)) { |
||
565 | if (!empty($clickthrough['channel'])) { |
||
566 | if (1 === count($clickthrough['channel'])) { |
||
567 | $channelId = reset($clickthrough['channel']); |
||
568 | $channel = key($clickthrough['channel']); |
||
569 | } else { |
||
570 | $channel = $clickthrough['channel'][0]; |
||
571 | $channelId = (int) $clickthrough['channel'][1]; |
||
572 | } |
||
573 | $hit->setSource($channel); |
||
574 | $hit->setSourceId($channelId); |
||
575 | } elseif (!empty($clickthrough['source'])) { |
||
576 | $hit->setSource($clickthrough['source'][0]); |
||
577 | $hit->setSourceId($clickthrough['source'][1]); |
||
578 | } |
||
579 | |||
580 | if (!empty($clickthrough['email'])) { |
||
581 | $emailRepo = $this->em->getRepository('MauticEmailBundle:Email'); |
||
582 | if ($emailEntity = $emailRepo->getEntity($clickthrough['email'])) { |
||
583 | $hit->setEmail($emailEntity); |
||
584 | } |
||
585 | } |
||
586 | } |
||
587 | |||
588 | $query = $hit->getQuery() ? $hit->getQuery() : []; |
||
589 | |||
590 | if (isset($query['timezone_offset']) && !$lead->getTimezone()) { |
||
591 | // timezone_offset holds timezone offset in minutes. Multiply by 60 to get seconds. |
||
592 | // Multiply by -1 because Firgerprint2 seems to have it the other way around. |
||
593 | $timezone = (-1 * $query['timezone_offset'] * 60); |
||
594 | $lead->setTimezone($this->dateTimeHelper->guessTimezoneFromOffset($timezone)); |
||
595 | } |
||
596 | |||
597 | $query = $this->cleanQuery($query); |
||
598 | |||
599 | if (isset($query['page_referrer'])) { |
||
600 | $hit->setReferer($query['page_referrer']); |
||
601 | } |
||
602 | if (isset($query['page_language'])) { |
||
603 | $hit->setPageLanguage($query['page_language']); |
||
604 | } |
||
605 | if (isset($query['page_title'])) { |
||
606 | // Transliterate page titles. |
||
607 | if ($this->coreParametersHelper->get('transliterate_page_title')) { |
||
608 | $safeTitle = InputHelper::transliterate($query['page_title']); |
||
609 | $hit->setUrlTitle($safeTitle); |
||
610 | $query['page_title'] = $safeTitle; |
||
611 | } else { |
||
612 | $hit->setUrlTitle($query['page_title']); |
||
613 | } |
||
614 | } |
||
615 | |||
616 | $hit->setQuery($query); |
||
617 | $hit->setUrl((isset($query['page_url'])) ? $query['page_url'] : $request->getRequestUri()); |
||
618 | |||
619 | // Add entry to contact log table |
||
620 | $this->setLeadManipulator($page, $hit, $lead); |
||
621 | |||
622 | // Store tracking ID |
||
623 | $hit->setLead($lead); |
||
624 | |||
625 | if (!$activeRequest) { |
||
626 | // Queue is consuming this hit outside of the lead's active request so this must be set in order for listeners to know who the request belongs to |
||
627 | $this->contactTracker->setSystemContact($lead); |
||
628 | } |
||
629 | $trackingId = $hit->getTrackingId(); |
||
630 | if (!$trackingNewlyGenerated) { |
||
631 | $lastHit = $request->cookies->get('mautic_referer_id'); |
||
632 | if (!empty($lastHit)) { |
||
633 | //this is not a new session so update the last hit if applicable with the date/time the user left |
||
634 | $this->getHitRepository()->updateHitDateLeft($lastHit); |
||
635 | } |
||
636 | } |
||
637 | |||
638 | // Check if this is a unique page hit |
||
639 | $isUnique = $this->getHitRepository()->isUniquePageHit($page, $trackingId, $lead); |
||
640 | |||
641 | if (!empty($page)) { |
||
642 | if ($page instanceof Page) { |
||
643 | $hit->setPageLanguage($page->getLanguage()); |
||
644 | |||
645 | $isVariant = ($isUnique) ? $page->getVariantStartDate() : false; |
||
646 | |||
647 | try { |
||
648 | $this->getRepository()->upHitCount($page->getId(), 1, $isUnique, !empty($isVariant)); |
||
649 | } catch (\Exception $exception) { |
||
650 | $this->logger->addError( |
||
651 | $exception->getMessage(), |
||
652 | ['exception' => $exception] |
||
653 | ); |
||
654 | } |
||
655 | } elseif ($page instanceof Redirect) { |
||
656 | try { |
||
657 | $this->pageRedirectModel->getRepository()->upHitCount($page->getId(), 1, $isUnique); |
||
658 | |||
659 | // If this is a trackable, up the trackable counts as well |
||
660 | if ($hit->getSource() && $hit->getSourceId()) { |
||
661 | $this->pageTrackableModel->getRepository()->upHitCount( |
||
662 | $page->getId(), |
||
663 | $hit->getSource(), |
||
664 | $hit->getSourceId(), |
||
665 | 1, |
||
666 | $isUnique |
||
667 | ); |
||
668 | } |
||
669 | } catch (\Exception $exception) { |
||
670 | if (MAUTIC_ENV === 'dev') { |
||
671 | throw $exception; |
||
672 | } else { |
||
673 | $this->logger->addError( |
||
674 | $exception->getMessage(), |
||
675 | ['exception' => $exception] |
||
676 | ); |
||
677 | } |
||
678 | } |
||
679 | } |
||
680 | } |
||
681 | |||
682 | //glean info from the IP address |
||
683 | $ipAddress = $hit->getIpAddress(); |
||
684 | if ($details = $ipAddress->getIpDetails()) { |
||
685 | $hit->setCountry($details['country']); |
||
686 | $hit->setRegion($details['region']); |
||
687 | $hit->setCity($details['city']); |
||
688 | $hit->setIsp($details['isp']); |
||
689 | $hit->setOrganization($details['organization']); |
||
690 | } |
||
691 | |||
692 | if (!$hit->getReferer()) { |
||
693 | $hit->setReferer($request->server->get('HTTP_REFERER')); |
||
694 | } |
||
695 | |||
696 | $hit->setUserAgent($request->server->get('HTTP_USER_AGENT')); |
||
697 | $hit->setRemoteHost($request->server->get('REMOTE_HOST')); |
||
698 | |||
699 | if ($isUnique) { |
||
700 | // Add UTM tags entry if a UTM tag exist |
||
701 | $queryHasUtmTags = false; |
||
702 | if (!is_array($query)) { |
||
703 | parse_str($query, $query); |
||
704 | } |
||
705 | |||
706 | foreach ($query as $key => $value) { |
||
707 | if (false !== strpos($key, 'utm_')) { |
||
708 | $queryHasUtmTags = true; |
||
709 | break; |
||
710 | } |
||
711 | } |
||
712 | |||
713 | if ($queryHasUtmTags && $lead) { |
||
714 | $utmTags = new UtmTag(); |
||
715 | $utmTags->setDateAdded($hit->getDateHit()); |
||
716 | $utmTags->setUrl($hit->getUrl()); |
||
717 | $utmTags->setReferer($hit->getReferer()); |
||
718 | $utmTags->setQuery($hit->getQuery()); |
||
719 | $utmTags->setUserAgent($hit->getUserAgent()); |
||
720 | $utmTags->setRemoteHost($hit->getRemoteHost()); |
||
721 | $utmTags->setLead($lead); |
||
722 | |||
723 | if (array_key_exists('utm_campaign', $query)) { |
||
724 | $utmTags->setUtmCampaign($query['utm_campaign']); |
||
725 | } |
||
726 | if (array_key_exists('utm_term', $query)) { |
||
727 | $utmTags->setUtmTerm($query['utm_term']); |
||
728 | } |
||
729 | if (array_key_exists('utm_content', $query)) { |
||
730 | $utmTags->setUtmContent($query['utm_content']); |
||
731 | } |
||
732 | if (array_key_exists('utm_medium', $query)) { |
||
733 | $utmTags->setUtmMedium($query['utm_medium']); |
||
734 | } |
||
735 | if (array_key_exists('utm_source', $query)) { |
||
736 | $utmTags->setUtmSource($query['utm_source']); |
||
737 | } |
||
738 | |||
739 | $repo = $this->em->getRepository('MauticLeadBundle:UtmTag'); |
||
740 | $repo->saveEntity($utmTags); |
||
741 | |||
742 | $this->leadModel->setUtmTags($lead, $utmTags); |
||
743 | } |
||
744 | } |
||
745 | //get a list of the languages the user prefers |
||
746 | $browserLanguages = $request->server->get('HTTP_ACCEPT_LANGUAGE'); |
||
747 | if (!empty($browserLanguages)) { |
||
748 | $languages = explode(',', $browserLanguages); |
||
749 | foreach ($languages as $k => $l) { |
||
750 | if ($pos = false !== strpos(';q=', $l)) { |
||
751 | //remove weights |
||
752 | $languages[$k] = substr($l, 0, $pos); |
||
753 | } |
||
754 | } |
||
755 | $hit->setBrowserLanguages($languages); |
||
756 | } |
||
757 | |||
758 | // Wrap in a try/catch to prevent deadlock errors on busy servers |
||
759 | try { |
||
760 | $this->em->persist($hit); |
||
761 | $this->em->flush(); |
||
762 | } catch (\Exception $exception) { |
||
763 | if (MAUTIC_ENV === 'dev') { |
||
764 | throw $exception; |
||
765 | } else { |
||
766 | $this->logger->addError( |
||
767 | $exception->getMessage(), |
||
768 | ['exception' => $exception] |
||
769 | ); |
||
770 | } |
||
771 | } |
||
772 | |||
773 | if ($this->dispatcher->hasListeners(PageEvents::PAGE_ON_HIT)) { |
||
774 | $event = new PageHitEvent($hit, $request, $hit->getCode(), $clickthrough, $isUnique); |
||
775 | $this->dispatcher->dispatch(PageEvents::PAGE_ON_HIT, $event); |
||
776 | } |
||
777 | } |
||
778 | |||
779 | /** |
||
780 | * @param Redirect|Page|null $page |
||
781 | * |
||
782 | * @return array |
||
783 | */ |
||
784 | public function getHitQuery(Request $request, $page = null) |
||
785 | { |
||
786 | $get = $request->query->all(); |
||
787 | $post = $request->request->all(); |
||
788 | |||
789 | $query = \array_merge($get, $post); |
||
790 | |||
791 | // Set generated page url |
||
792 | $query['page_url'] = $this->getPageUrl($request, $page); |
||
793 | |||
794 | // Process clickthrough if applicable |
||
795 | if (!empty($query['ct'])) { |
||
796 | $query['ct'] = $this->decodeArrayFromUrl($query['ct']); |
||
797 | } |
||
798 | |||
799 | return $query; |
||
800 | } |
||
801 | |||
802 | /** |
||
803 | * Get array of page builder tokens from bundles subscribed PageEvents::PAGE_ON_BUILD. |
||
804 | * |
||
805 | * @param array|string $requestedComponents all | tokens | abTestWinnerCriteria |
||
806 | * @param string|null $tokenFilter |
||
807 | * |
||
808 | * @return array |
||
809 | */ |
||
810 | public function getBuilderComponents(Page $page = null, $requestedComponents = 'all', $tokenFilter = null) |
||
811 | { |
||
812 | $event = new PageBuilderEvent($this->translator, $page, $requestedComponents, $tokenFilter); |
||
813 | $this->dispatcher->dispatch(PageEvents::PAGE_ON_BUILD, $event); |
||
814 | |||
815 | return $this->getCommonBuilderComponents($requestedComponents, $event); |
||
816 | } |
||
817 | |||
818 | /** |
||
819 | * Get number of page bounces. |
||
820 | * |
||
821 | * @param \DateTime $fromDate |
||
822 | * |
||
823 | * @return int |
||
824 | */ |
||
825 | public function getBounces(Page $page, \DateTime $fromDate = null) |
||
826 | { |
||
827 | return $this->getHitRepository()->getBounces($page->getId(), $fromDate); |
||
828 | } |
||
829 | |||
830 | /** |
||
831 | * Joins the page table and limits created_by to currently logged in user. |
||
832 | */ |
||
833 | public function limitQueryToCreator(QueryBuilder &$q) |
||
834 | { |
||
835 | $q->join('t', MAUTIC_TABLE_PREFIX.'pages', 'p', 'p.id = t.page_id') |
||
836 | ->andWhere('p.created_by = :userId') |
||
837 | ->setParameter('userId', $this->userHelper->getUser()->getId()); |
||
838 | } |
||
839 | |||
840 | /** |
||
841 | * Get line chart data of hits. |
||
842 | * |
||
843 | * @param char $unit {@link php.net/manual/en/function.date.php#refsect1-function.date-parameters} |
||
0 ignored issues
–
show
The type
Mautic\PageBundle\Model\char was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||
844 | * @param string $dateFormat |
||
845 | * @param array $filter |
||
846 | * @param bool $canViewOthers |
||
847 | * |
||
848 | * @return array |
||
849 | */ |
||
850 | public function getHitsLineChartData($unit, \DateTime $dateFrom, \DateTime $dateTo, $dateFormat = null, $filter = [], $canViewOthers = true) |
||
851 | { |
||
852 | $flag = null; |
||
853 | |||
854 | if (isset($filter['flag'])) { |
||
855 | $flag = $filter['flag']; |
||
856 | unset($filter['flag']); |
||
857 | } |
||
858 | |||
859 | $chart = new LineChart($unit, $dateFrom, $dateTo, $dateFormat); |
||
860 | $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo); |
||
861 | |||
862 | if (!$flag || 'total_and_unique' == $flag) { |
||
863 | $q = $query->prepareTimeDataQuery('page_hits', 'date_hit', $filter); |
||
864 | |||
865 | if (!$canViewOthers) { |
||
866 | $this->limitQueryToCreator($q); |
||
867 | } |
||
868 | |||
869 | $data = $query->loadAndBuildTimeData($q); |
||
870 | $chart->setDataset($this->translator->trans('mautic.page.show.total.visits'), $data); |
||
871 | } |
||
872 | |||
873 | if ('unique' == $flag || 'total_and_unique' == $flag) { |
||
874 | $q = $query->prepareTimeDataQuery('page_hits', 'date_hit', $filter, 'distinct(t.lead_id)'); |
||
875 | |||
876 | if (!$canViewOthers) { |
||
877 | $this->limitQueryToCreator($q); |
||
878 | } |
||
879 | |||
880 | $data = $query->loadAndBuildTimeData($q); |
||
881 | $chart->setDataset($this->translator->trans('mautic.page.show.unique.visits'), $data); |
||
882 | } |
||
883 | |||
884 | return $chart->render(); |
||
885 | } |
||
886 | |||
887 | /** |
||
888 | * Get data for pie chart showing new vs returning leads. |
||
889 | * Returning leads are even leads who visits 2 different page once. |
||
890 | * |
||
891 | * @param \DateTime $dateFrom |
||
892 | * @param \DateTime $dateTo |
||
893 | * @param array $filters |
||
894 | * @param bool $canViewOthers |
||
895 | * |
||
896 | * @return array |
||
897 | */ |
||
898 | public function getNewVsReturningPieChartData($dateFrom, $dateTo, $filters = [], $canViewOthers = true) |
||
899 | { |
||
900 | $chart = new PieChart(); |
||
901 | $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo); |
||
902 | $allQ = $query->getCountQuery('page_hits', 'id', 'date_hit', $filters); |
||
903 | $filters['lead_id'] = [ |
||
904 | 'expression' => 'isNull', |
||
905 | ]; |
||
906 | $returnQ = $query->getCountQuery('page_hits', 'id', 'date_hit', $filters); |
||
907 | |||
908 | if (!$canViewOthers) { |
||
909 | $this->limitQueryToCreator($allQ); |
||
910 | $this->limitQueryToCreator($returnQ); |
||
911 | } |
||
912 | |||
913 | $all = $query->fetchCount($allQ); |
||
914 | $returning = $query->fetchCount($returnQ); |
||
915 | $unique = $all - $returning; |
||
916 | $chart->setDataset($this->translator->trans('mautic.page.unique'), $unique); |
||
917 | $chart->setDataset($this->translator->trans('mautic.page.graph.pie.new.vs.returning.returning'), $returning); |
||
918 | |||
919 | return $chart->render(); |
||
920 | } |
||
921 | |||
922 | /** |
||
923 | * Get pie chart data of dwell times. |
||
924 | * |
||
925 | * @param array $filters |
||
926 | * @param bool $canViewOthers |
||
927 | * |
||
928 | * @return array |
||
929 | */ |
||
930 | public function getDwellTimesPieChartData(\DateTime $dateFrom, \DateTime $dateTo, $filters = [], $canViewOthers = true) |
||
931 | { |
||
932 | $timesOnSite = $this->getHitRepository()->getDwellTimeLabels(); |
||
933 | $chart = new PieChart(); |
||
934 | $query = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo); |
||
935 | |||
936 | foreach ($timesOnSite as $time) { |
||
937 | $q = $query->getCountDateDiffQuery('page_hits', 'date_hit', 'date_left', $time['from'], $time['till'], $filters); |
||
938 | |||
939 | if (!$canViewOthers) { |
||
940 | $this->limitQueryToCreator($q); |
||
941 | } |
||
942 | |||
943 | $data = $query->fetchCountDateDiff($q); |
||
944 | $chart->setDataset($time['label'], $data); |
||
945 | } |
||
946 | |||
947 | return $chart->render(); |
||
948 | } |
||
949 | |||
950 | /** |
||
951 | * Get bar chart data of hits. |
||
952 | * |
||
953 | * @param DateTime $dateFrom |
||
954 | * @param DateTime $dateTo |
||
955 | * |
||
956 | * @return array |
||
957 | */ |
||
958 | public function getDeviceGranularityData(\DateTime $dateFrom, \DateTime $dateTo, $filters = [], $canViewOthers = true) |
||
959 | { |
||
960 | $q = $this->em->getConnection()->createQueryBuilder(); |
||
961 | |||
962 | $q->select('count(h.id) as count, ds.device as device') |
||
963 | ->from(MAUTIC_TABLE_PREFIX.'page_hits', 'h') |
||
964 | ->join('h', MAUTIC_TABLE_PREFIX.'lead_devices', 'ds', 'ds.id=h.device_id') |
||
965 | ->orderBy('device', 'DESC') |
||
966 | ->andWhere($q->expr()->gte('h.date_hit', ':date_from')) |
||
967 | ->setParameter('date_from', $dateFrom->format('Y-m-d')) |
||
968 | ->andWhere($q->expr()->lte('h.date_hit', ':date_to')) |
||
969 | ->setParameter('date_to', $dateTo->format('Y-m-d'.' 23:59:59')); |
||
970 | $q->groupBy('ds.device'); |
||
971 | |||
972 | $results = $q->execute()->fetchAll(); |
||
973 | $chart = new PieChart(); |
||
974 | |||
975 | if (empty($results)) { |
||
976 | $results[] = [ |
||
977 | 'device' => $this->translator->trans('mautic.report.report.noresults'), |
||
978 | 'count' => 0, |
||
979 | ]; |
||
980 | } |
||
981 | |||
982 | foreach ($results as $result) { |
||
983 | $label = empty($result['device']) ? $this->translator->trans('mautic.core.no.info') : $result['device']; |
||
984 | |||
985 | $chart->setDataset($label, $result['count']); |
||
986 | } |
||
987 | |||
988 | return $chart->render(); |
||
989 | } |
||
990 | |||
991 | /** |
||
992 | * Get a list of popular (by hits) pages. |
||
993 | * |
||
994 | * @param int $limit |
||
995 | * @param \DateTime $dateFrom |
||
996 | * @param \DateTime $dateTo |
||
997 | * @param array $filters |
||
998 | * @param bool $canViewOthers |
||
999 | * |
||
1000 | * @return array |
||
1001 | */ |
||
1002 | public function getPopularPages($limit = 10, \DateTime $dateFrom = null, \DateTime $dateTo = null, $filters = [], $canViewOthers = true) |
||
1003 | { |
||
1004 | $q = $this->em->getConnection()->createQueryBuilder(); |
||
1005 | $q->select('COUNT(DISTINCT t.id) AS hits, p.id, p.title, p.alias') |
||
1006 | ->from(MAUTIC_TABLE_PREFIX.'page_hits', 't') |
||
1007 | ->join('t', MAUTIC_TABLE_PREFIX.'pages', 'p', 'p.id = t.page_id') |
||
1008 | ->orderBy('hits', 'DESC') |
||
1009 | ->groupBy('p.id') |
||
1010 | ->setMaxResults($limit); |
||
1011 | |||
1012 | if (!$canViewOthers) { |
||
1013 | $q->andWhere('p.created_by = :userId') |
||
1014 | ->setParameter('userId', $this->userHelper->getUser()->getId()); |
||
1015 | } |
||
1016 | |||
1017 | $chartQuery = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo); |
||
1018 | $chartQuery->applyFilters($q, $filters); |
||
1019 | $chartQuery->applyDateFilters($q, 'date_hit'); |
||
1020 | |||
1021 | return $q->execute()->fetchAll(); |
||
1022 | } |
||
1023 | |||
1024 | /** |
||
1025 | * Get a list of pages created in a date range. |
||
1026 | * |
||
1027 | * @param int $limit |
||
1028 | * @param \DateTime $dateFrom |
||
1029 | * @param \DateTime $dateTo |
||
1030 | * @param array $filters |
||
1031 | * @param bool $canViewOthers |
||
1032 | * |
||
1033 | * @return array |
||
1034 | */ |
||
1035 | public function getPageList($limit = 10, \DateTime $dateFrom = null, \DateTime $dateTo = null, $filters = [], $canViewOthers = true) |
||
1036 | { |
||
1037 | $q = $this->em->getConnection()->createQueryBuilder(); |
||
1038 | $q->select('t.id, t.title AS name, t.date_added, t.date_modified') |
||
1039 | ->from(MAUTIC_TABLE_PREFIX.'pages', 't') |
||
1040 | ->setMaxResults($limit); |
||
1041 | |||
1042 | if (!$canViewOthers) { |
||
1043 | $q->andWhere('t.created_by = :userId') |
||
1044 | ->setParameter('userId', $this->userHelper->getUser()->getId()); |
||
1045 | } |
||
1046 | |||
1047 | $chartQuery = new ChartQuery($this->em->getConnection(), $dateFrom, $dateTo); |
||
1048 | $chartQuery->applyFilters($q, $filters); |
||
1049 | $chartQuery->applyDateFilters($q, 'date_added'); |
||
1050 | |||
1051 | return $q->execute()->fetchAll(); |
||
1052 | } |
||
1053 | |||
1054 | /** |
||
1055 | * @param $page |
||
1056 | */ |
||
1057 | private function setLeadManipulator($page, Hit $hit, Lead $lead) |
||
1058 | { |
||
1059 | // Only save the lead and dispatch events if needed |
||
1060 | $source = 'hit'; |
||
1061 | $sourceId = $hit->getId(); |
||
1062 | if ($page) { |
||
1063 | $source = $page instanceof Page ? 'page' : 'redirect'; |
||
1064 | $sourceId = $page->getId(); |
||
1065 | } |
||
1066 | |||
1067 | $lead->setManipulator( |
||
1068 | new LeadManipulator( |
||
1069 | 'page', |
||
1070 | $source, |
||
1071 | $sourceId, |
||
1072 | $hit->getUrl() |
||
1073 | ) |
||
1074 | ); |
||
1075 | |||
1076 | $this->leadModel->saveEntity($lead); |
||
1077 | } |
||
1078 | |||
1079 | /** |
||
1080 | * @param $page |
||
1081 | * |
||
1082 | * @return mixed|string |
||
1083 | */ |
||
1084 | private function getPageUrl(Request $request, $page) |
||
1085 | { |
||
1086 | // Default to page_url set in the query from tracking pixel and/or contactfield token |
||
1087 | if ($pageURL = $request->get('page_url')) { |
||
1088 | return $pageURL; |
||
1089 | } |
||
1090 | |||
1091 | if ($page instanceof Redirect) { |
||
1092 | //use the configured redirect URL |
||
1093 | return $page->getUrl(); |
||
1094 | } |
||
1095 | |||
1096 | // Use the current URL |
||
1097 | $isPageEvent = false; |
||
1098 | if (false !== strpos($request->server->get('REQUEST_URI'), $this->router->generate('mautic_page_tracker'))) { |
||
1099 | // Tracking pixel is used |
||
1100 | if ($request->server->get('QUERY_STRING')) { |
||
1101 | parse_str($request->server->get('QUERY_STRING'), $query); |
||
1102 | $isPageEvent = true; |
||
1103 | } |
||
1104 | } elseif (false !== strpos($request->server->get('REQUEST_URI'), $this->router->generate('mautic_page_tracker_cors'))) { |
||
1105 | $query = $request->request->all(); |
||
1106 | $isPageEvent = true; |
||
1107 | } |
||
1108 | |||
1109 | if ($isPageEvent) { |
||
1110 | $pageURL = $request->server->get('HTTP_REFERER'); |
||
1111 | |||
1112 | // if additional data were sent with the tracking pixel |
||
1113 | if (isset($query)) { |
||
1114 | // URL attr 'd' is encoded so let's decode it first. |
||
1115 | $decoded = false; |
||
1116 | if (isset($query['d'])) { |
||
1117 | // parse_str auto urldecodes |
||
1118 | $query = $this->decodeArrayFromUrl($query['d'], false); |
||
1119 | $decoded = true; |
||
1120 | } |
||
1121 | |||
1122 | if (is_array($query) && !empty($query)) { |
||
1123 | if (isset($query['page_url'])) { |
||
1124 | $pageURL = $query['page_url']; |
||
1125 | if (!$decoded) { |
||
1126 | $pageURL = urldecode($pageURL); |
||
1127 | } |
||
1128 | } |
||
1129 | |||
1130 | if (isset($query['page_referrer'])) { |
||
1131 | if (!$decoded) { |
||
1132 | $query['page_referrer'] = urldecode($query['page_referrer']); |
||
1133 | } |
||
1134 | } |
||
1135 | |||
1136 | if (isset($query['page_language'])) { |
||
1137 | if (!$decoded) { |
||
1138 | $query['page_language'] = urldecode($query['page_language']); |
||
1139 | } |
||
1140 | } |
||
1141 | |||
1142 | if (isset($query['page_title'])) { |
||
1143 | if (!$decoded) { |
||
1144 | $query['page_title'] = urldecode($query['page_title']); |
||
1145 | } |
||
1146 | } |
||
1147 | |||
1148 | if (isset($query['tags'])) { |
||
1149 | if (!$decoded) { |
||
1150 | $query['tags'] = urldecode($query['tags']); |
||
1151 | } |
||
1152 | } |
||
1153 | } |
||
1154 | } |
||
1155 | |||
1156 | return $pageURL; |
||
1157 | } |
||
1158 | |||
1159 | $pageURL = 'http'; |
||
1160 | if ('on' == $request->server->get('HTTPS')) { |
||
1161 | $pageURL .= 's'; |
||
1162 | } |
||
1163 | $pageURL .= '://'; |
||
1164 | |||
1165 | if (!in_array((int) $request->server->get('SERVER_PORT', 80), [80, 8080, 443])) { |
||
1166 | return $pageURL.$request->server->get('SERVER_NAME').':'.$request->server->get('SERVER_PORT'). |
||
1167 | $request->server->get('REQUEST_URI'); |
||
1168 | } |
||
1169 | |||
1170 | return $pageURL.$request->server->get('SERVER_NAME').$request->server->get('REQUEST_URI'); |
||
1171 | } |
||
1172 | |||
1173 | /* |
||
1174 | * Cleans query params saving url values. |
||
1175 | * |
||
1176 | * @param $query array |
||
1177 | * |
||
1178 | * @return array |
||
1179 | */ |
||
1180 | private function cleanQuery($query) |
||
1181 | { |
||
1182 | foreach ($query as $key => $value) { |
||
1183 | if (filter_var($value, FILTER_VALIDATE_URL)) { |
||
1184 | $query[$key] = InputHelper::url($value); |
||
1185 | } else { |
||
1186 | $query[$key] = InputHelper::clean($value); |
||
1187 | } |
||
1188 | } |
||
1189 | |||
1190 | return $query; |
||
1191 | } |
||
1192 | } |
||
1193 |