Completed
Push — master ( 98f37a...19732d )
by Paweł
07:58
created

AnalyticsEventConsumer::getImpressionSource()   B

Complexity

Conditions 8
Paths 5

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.4444
c 0
b 0
f 0
cc 8
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Core Bundle.
7
 *
8
 * Copyright 2017 Sourcefabric z.ú. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2017 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\CoreBundle\Consumer;
18
19
use OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface;
20
use PhpAmqpLib\Message\AMQPMessage;
21
use SWP\Bundle\AnalyticsBundle\Model\ArticleEventInterface;
22
use SWP\Bundle\AnalyticsBundle\Services\ArticleStatisticsServiceInterface;
23
use SWP\Bundle\ContentBundle\Model\RouteInterface;
24
use SWP\Bundle\CoreBundle\Model\ArticleInterface;
25
use SWP\Component\MultiTenancy\Context\TenantContextInterface;
26
use SWP\Component\MultiTenancy\Resolver\TenantResolver;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
29
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
30
31
/**
32
 * Class AnalyticsEventConsumer.
33
 */
34
class AnalyticsEventConsumer implements ConsumerInterface
35
{
36
    /**
37
     * @var ArticleStatisticsServiceInterface
38
     */
39
    protected $articleStatisticsService;
40
41
    /**
42
     * @var TenantResolver
43
     */
44
    protected $tenantResolver;
45
46
    /**
47
     * @var TenantContextInterface
48
     */
49
    protected $tenantContext;
50
51
    /**
52
     * @var UrlMatcherInterface
53
     */
54
    protected $matcher;
55
56
    /**
57
     * AnalyticsEventConsumer constructor.
58
     *
59
     * @param ArticleStatisticsServiceInterface $articleStatisticsService
60
     * @param TenantResolver                    $tenantResolver
61
     * @param TenantContextInterface            $tenantContext
62
     */
63
    public function __construct(
64
        ArticleStatisticsServiceInterface $articleStatisticsService,
65
        TenantResolver $tenantResolver,
66
        TenantContextInterface $tenantContext,
67
        UrlMatcherInterface $matcher
68
    ) {
69
        $this->articleStatisticsService = $articleStatisticsService;
70
        $this->tenantResolver = $tenantResolver;
71
        $this->tenantContext = $tenantContext;
72
        $this->matcher = $matcher;
73
    }
74
75
    /**
76
     * @param AMQPMessage $message
77
     *
78
     * @return bool|mixed
79
     */
80
    public function execute(AMQPMessage $message)
81
    {
82
        /** @var Request $request */
83
        $request = unserialize($message->getBody());
84
        if (!$request instanceof Request) {
85
            return ConsumerInterface::MSG_REJECT;
86
        }
87
88
        $this->setTenant($request);
89
90
        if ($request->query->has('articleId')) {
91
            $this->handleArticlePageviews($request);
92
        }
93
94
        if ($request->attributes->has('data') && ArticleEventInterface::ACTION_IMPRESSION === $request->query->get('type')) {
95
            $this->handleArticleImpressions($request);
96
        }
97
98
        return ConsumerInterface::MSG_ACK;
99
    }
100
101
    private function handleArticleImpressions(Request $request): void
102
    {
103
        $articles = [];
104
        $extraData = [];
0 ignored issues
show
Unused Code introduced by
$extraData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
105
        foreach ($request->attributes->get('data') as $url) {
106
            try {
107
                $route = $this->matcher->match($this->getPathFromUrl($url));
108
                if (isset($route['_article_meta']) && $route['_article_meta']->getValues() instanceof ArticleInterface) {
109
                    $articleId = $route['_article_meta']->getValues()->getId();
110
                    if (!\array_key_exists($articleId, $articles)) {
111
                        $articles[$articleId] = $route['_article_meta']->getValues();
112
                    }
113
                }
114
            } catch (ResourceNotFoundException $e) {
115
                //ignore
116
            }
117
        }
118
119
        foreach ($articles as $article) {
120
            $this->articleStatisticsService->addArticleEvent(
121
                (int) $article->getId(),
122
                ArticleEventInterface::ACTION_IMPRESSION,
123
                $this->getImpressionSource($request)
124
            );
125
        }
126
    }
127
128
    private function getImpressionSource(Request $request): array
129
    {
130
        $source = [];
131
        $referrer = $request->server->get('HTTP_REFERER');
132
        if (null === $referrer) {
133
            return $source;
134
        }
135
136
        $route = $this->matcher->match($this->getPathFromUrl($referrer));
137
        if (isset($route['_article_meta']) && $route['_article_meta']->getValues() instanceof ArticleInterface) {
138
            $source['type'] = 'article';
139
            $source['sourceArticle'] = $route['_article_meta']->getValues();
140
        } elseif (isset($route['_route_meta']) && $route['_route_meta']->getValues() instanceof RouteInterface) {
141
            $source['type'] = 'route';
142
            $source['sourceRoute'] = $route['_route_meta']->getValues();
143
        } elseif (isset($route['_route']) && 'homepage' === $route['_route']) {
144
            $source['type'] = 'homepage';
145
        }
146
147
        return $source;
148
    }
149
150
    private function getPathFromUrl(string $url): string
151
    {
152
        $fragments = \parse_url($url);
153
154
        return str_replace('/app_dev.php', '', $fragments['path']);
155
    }
156
157
    private function handleArticlePageviews(Request $request): void
158
    {
159
        $articleId = $request->query->get('articleId', null);
160
        if (null !== $articleId) {
161
            $this->articleStatisticsService->addArticleEvent((int) $articleId, ArticleEventInterface::ACTION_PAGEVIEW, []);
162
        }
163
    }
164
165
    /**
166
     * @param Request $request
167
     */
168
    private function setTenant(Request $request): void
169
    {
170
        $this->tenantContext->setTenant($this->tenantResolver->resolve($request->getHost()));
171
    }
172
}
173