Completed
Push — 1.4 ( 85dbd7...326d11 )
by Paweł
25:51 queued 16:44
created

ArticleStatisticsService::getArticleEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Analytics 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\Service;
18
19
use SWP\Bundle\AnalyticsBundle\Model\ArticleEventInterface;
20
use SWP\Bundle\AnalyticsBundle\Model\ArticleStatisticsInterface;
21
use SWP\Bundle\AnalyticsBundle\Repository\ArticleEventRepositoryInterface;
22
use SWP\Bundle\AnalyticsBundle\Services\ArticleStatisticsServiceInterface;
23
use SWP\Bundle\ContentBundle\Doctrine\ArticleRepositoryInterface;
24
use SWP\Bundle\ContentBundle\Model\ArticleInterface;
25
use SWP\Bundle\ContentBundle\Model\RouteInterface;
26
use SWP\Component\Storage\Factory\FactoryInterface;
27
use SWP\Component\Storage\Repository\RepositoryInterface;
28
29
/**
30
 * Class ArticleStatisticsService.
31
 */
32
class ArticleStatisticsService implements ArticleStatisticsServiceInterface
33
{
34
    /**
35
     * @var ArticleRepositoryInterface
36
     */
37
    protected $articleRepository;
38
39
    /**
40
     * @var RepositoryInterface
41
     */
42
    protected $articleStatisticsRepository;
43
44
    /**
45
     * @var ArticleEventRepositoryInterface
46
     */
47
    protected $articleEventsRepository;
48
49
    /**
50
     * @var FactoryInterface
51
     */
52
    protected $articleStatisticsFactory;
53
54
    /**
55
     * @var FactoryInterface
56
     */
57
    protected $articleEventFactory;
58
59
    public function __construct(
60
        ArticleRepositoryInterface $articleRepository,
61
        RepositoryInterface $articleStatisticsRepository,
62
        ArticleEventRepositoryInterface $articleEventsRepository,
63
        FactoryInterface $articleStatisticsFactory,
64
        FactoryInterface $articleEventFactory
65
    ) {
66
        $this->articleRepository = $articleRepository;
67
        $this->articleStatisticsRepository = $articleStatisticsRepository;
68
        $this->articleEventsRepository = $articleEventsRepository;
69
        $this->articleStatisticsFactory = $articleStatisticsFactory;
70
        $this->articleEventFactory = $articleEventFactory;
71
    }
72
73
    public function addArticleEvent(int $articleId, string $action, array $extraData): ArticleStatisticsInterface
74
    {
75
        $articleStatistics = $this->getOrCreateNewArticleStatistics($articleId);
76
        switch ($action) {
77
            case ArticleEventInterface::ACTION_PAGEVIEW:
78
                $this->addNewPageViewEvent($articleStatistics, $articleId, $extraData[ArticleStatisticsServiceInterface::KEY_PAGEVIEW_SOURCE]);
79
80
                break;
81
            case ArticleEventInterface::ACTION_IMPRESSION:
82
                $sourceArticle = null;
83
                $sourceRoute = null;
84
                $type = null;
85
                if (array_key_exists(ArticleStatisticsServiceInterface::KEY_IMPRESSION_SOURCE_ARTICLE, $extraData)) {
86
                    $sourceArticle = $extraData[ArticleStatisticsServiceInterface::KEY_IMPRESSION_SOURCE_ARTICLE];
87
                }
88
                if (array_key_exists(ArticleStatisticsServiceInterface::KEY_IMPRESSION_SOURCE_ROUTE, $extraData)) {
89
                    $sourceRoute = $extraData[ArticleStatisticsServiceInterface::KEY_IMPRESSION_SOURCE_ROUTE];
90
                }
91
                if (array_key_exists(ArticleStatisticsServiceInterface::KEY_IMPRESSION_TYPE, $extraData)) {
92
                    $type = $extraData[ArticleStatisticsServiceInterface::KEY_IMPRESSION_TYPE];
93
                }
94
                $this->addNewImpressionEvent($articleStatistics, $articleId, $sourceArticle, $sourceRoute, $type);
95
96
                break;
97
        }
98
99
        return $articleStatistics;
100
    }
101
102
    protected function getOrCreateNewArticleStatistics(int $articleId): ArticleStatisticsInterface
103
    {
104
        /** @var ArticleStatisticsInterface $articleStatistics */
105
        $articleStatistics = $this->articleStatisticsRepository->findOneBy(['article' => $articleId]);
106
        if (null === $articleStatistics) {
107
            /** @var ArticleStatisticsInterface $articleStatistics */
108
            $articleStatistics = $this->articleStatisticsFactory->create();
109
        }
110
111
        return $articleStatistics;
112
    }
113
114
    protected function addNewPageViewEvent(ArticleStatisticsInterface $articleStatistics, int $articleId, string $pageViewSource): void
115
    {
116
        /** @var ArticleInterface $article */
117
        $article = $this->articleRepository->findOneBy(['id' => $articleId]);
118
        if (null === $article) {
119
            return;
120
        }
121
122
        $articleEvent = $this->getArticleEvent($articleStatistics, $article, ArticleEventInterface::ACTION_PAGEVIEW);
123
        $articleEvent->setPageViewSource($pageViewSource);
124
        $articleStatistics->increasePageViewsNumber();
125
        if (ArticleEventInterface::PAGEVIEW_SOURCE_INTERNAL === $pageViewSource) {
126
            $internalPageViewsCount = $this->articleEventsRepository->getCountForArticleInternalPageViews($article) + 1;
127
            if ($internalPageViewsCount > 0 && $articleStatistics->getImpressionsNumber() > 0) {
128
                $articleStatistics->setInternalClickRate(
129
                    \round($internalPageViewsCount / $articleStatistics->getImpressionsNumber(), 2)
130
                );
131
            } else {
132
                $articleStatistics->setInternalClickRate(0);
133
            }
134
        }
135
        $this->articleStatisticsRepository->add($articleStatistics);
136
    }
137
138
    protected function addNewImpressionEvent(
139
        ArticleStatisticsInterface $articleStatistics,
140
        int $articleId,
141
        ArticleInterface $sourceArticle = null,
142
        RouteInterface $sourceRoute = null,
143
        string $type = null
144
    ): void {
145
        /** @var ArticleInterface $article */
146
        $article = $this->articleRepository->findOneBy(['id' => $articleId]);
147
        if (null === $article) {
148
            return;
149
        }
150
151
        $articleEvent = $this->getArticleEvent($articleStatistics, $article, ArticleEventInterface::ACTION_IMPRESSION);
152
        $articleEvent->setImpressionArticle($sourceArticle);
153
        $articleEvent->setImpressionRoute($sourceRoute);
154
        $articleEvent->setImpressionType($type);
155
        $articleStatistics->increaseImpressionsNumber();
156
        $this->articleStatisticsRepository->add($articleStatistics);
157
    }
158
159
    private function getArticleEvent(
160
        ArticleStatisticsInterface $articleStatistics,
161
        ArticleInterface $article,
162
        string $action
163
    ): ArticleEventInterface {
164
        /** @var ArticleEventInterface $articleEvent */
165
        $articleEvent = $this->articleEventFactory->create();
166
        $articleEvent->setAction($action);
167
        $articleEvent->setArticleStatistics($articleStatistics);
168
        $this->articleStatisticsRepository->persist($articleEvent);
169
        $articleStatistics->addEvent($articleEvent);
170
        $articleStatistics->setArticle($article);
171
172
        return $articleEvent;
173
    }
174
}
175