Completed
Push — master ( 7ee0d9...1aff7f )
by Rafał
24:06 queued 15:30
created

ExportAnalyticsHandler   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 10

Importance

Changes 0
Metric Value
wmc 7
lcom 0
cbo 10
dl 0
loc 119
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 1
A __invoke() 0 51 4
A objectsToArray() 0 20 2
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 2020 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 2020 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\CoreBundle\AnalyticsExport;
18
19
use DateTime;
20
use FOS\ElasticaBundle\Manager\RepositoryManagerInterface;
21
use RuntimeException;
22
use SWP\Bundle\CoreBundle\AnalyticsExport\Exception\AnalyticsReportNotFoundException;
23
use SWP\Bundle\CoreBundle\Context\CachedTenantContextInterface;
24
use SWP\Bundle\CoreBundle\Model\AnalyticsReportInterface;
25
use SWP\Bundle\CoreBundle\Model\Article;
26
use SWP\Bundle\ElasticSearchBundle\Criteria\Criteria;
27
use SWP\Component\MultiTenancy\Repository\TenantRepositoryInterface;
28
use SWP\Component\Storage\Repository\RepositoryInterface;
29
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
30
use Throwable;
31
32
final class ExportAnalyticsHandler implements MessageHandlerInterface
33
{
34
    /** @var RepositoryManagerInterface */
35
    private $elasticaRepositoryManager;
36
37
    /** @var string */
38
    private $cacheDir;
39
40
    /** @var ReportMailer */
41
    private $mailer;
42
43
    /** @var ReportFileUploader */
44
    private $reportFileUploader;
45
46
    /** @var CsvFileWriter */
47
    private $csvFileWriter;
48
49
    /** @var RepositoryInterface */
50
    private $analyticsReportRepository;
51
52
    /** @var CachedTenantContextInterface */
53
    private $cachedTenantContext;
54
55
    /** @var TenantRepositoryInterface */
56
    private $tenantRepository;
57
58
    public function __construct(
59
        RepositoryManagerInterface $elasticaRepositoryManager,
60
        string $cacheDir,
61
        ReportMailer $mailer,
62
        ReportFileUploader $reportFileUploader,
63
        CsvFileWriter $csvFileWriter,
64
        RepositoryInterface $analyticsReportRepository,
65
        CachedTenantContextInterface $cachedTenantContext,
66
        TenantRepositoryInterface $tenantRepository
67
    ) {
68
        $this->elasticaRepositoryManager = $elasticaRepositoryManager;
69
        $this->cacheDir = $cacheDir;
70
        $this->mailer = $mailer;
71
        $this->reportFileUploader = $reportFileUploader;
72
        $this->csvFileWriter = $csvFileWriter;
73
        $this->analyticsReportRepository = $analyticsReportRepository;
74
        $this->cachedTenantContext = $cachedTenantContext;
75
        $this->tenantRepository = $tenantRepository;
76
    }
77
78
    public function __invoke(ExportAnalytics $exportAnalytics)
79
    {
80
        $fileName = $exportAnalytics->getFileName();
81
82
        /** @var AnalyticsReportInterface $analyticsReport */
83
        $analyticsReport = $this->analyticsReportRepository->findOneBy(['assetId' => $fileName]);
84
85
        if (null === $analyticsReport) {
86
            throw new AnalyticsReportNotFoundException("Analytics report $fileName not found.");
87
        }
88
89
        try {
90
            $tenantCode = $exportAnalytics->getTenantCode();
91
            $criteria = Criteria::fromQueryParameters(
92
                '',
93
                [
94
                    'sort' => ['articleStatistics.pageViewsNumber' => 'desc'],
95
                    'publishedBefore' => $exportAnalytics->getEnd(),
96
                    'publishedAfter' => $exportAnalytics->getStart(),
97
                    'tenantCode' => $tenantCode,
98
                ]
99
            );
100
101
            $tenant = $this->tenantRepository->findOneBy(['code' => $tenantCode]);
102
            if (null === $tenant) {
103
                throw new RuntimeException("Tenant with code $tenantCode not found");
104
            }
105
106
            $this->cachedTenantContext->setTenant($tenant);
107
108
            $articleRepository = $this->elasticaRepositoryManager->getRepository(Article::class);
109
110
            $articles = $articleRepository->findByCriteria($criteria);
111
            $total = $articles->getTotalHits();
112
            $articles = $articles->getResults(0, $total);
113
            $data = $this->objectsToArray($articles->toArray());
114
            $path = $this->cacheDir.'/'.$fileName;
115
116
            $this->csvFileWriter->write($path, $data);
117
118
            $url = $this->reportFileUploader->upload($analyticsReport, $path);
119
120
            $this->mailer->sendReportReadyEmailNotification($exportAnalytics->getUserEmail(), $url);
121
            $analyticsReport->setStatus(AnalyticsReportInterface::STATUS_COMPLETED);
122
        } catch (Throwable $e) {
123
            $analyticsReport->setStatus(AnalyticsReportInterface::STATUS_ERRORED);
124
        }
125
126
        $analyticsReport->setUpdatedAt(new DateTime());
127
        $this->analyticsReportRepository->flush();
128
    }
129
130
    private function objectsToArray(array $rows): array
131
    {
132
        $data = [
133
            ['Article ID', 'Publish Date', 'Total Views', 'Section', 'Title', 'Author(s)'],
134
        ];
135
136
        /** @var Article $article */
137
        foreach ($rows as $article) {
138
            $data[] = [
139
                $article->getId(),
140
                $article->getPublishedAt()->format('Y-m-d H:i'),
141
                $article->getArticleStatistics()->getPageViewsNumber(),
142
                $article->getRoute()->getName(),
143
                $article->getTitle(),
144
                implode(', ', $article->getAuthorsNames()),
145
            ];
146
        }
147
148
        return $data;
149
    }
150
}
151