Completed
Push — master ( 9af361...a55b85 )
by Rafał
09:23
created

ExportAnalyticsHandler::__invoke()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 53
rs 8.7143
c 0
b 0
f 0
cc 5
nc 16
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 FOS\ElasticaBundle\Manager\RepositoryManagerInterface;
20
use RuntimeException;
21
use SWP\Bundle\CoreBundle\AnalyticsExport\Exception\AnalyticsReportNotFoundException;
22
use SWP\Bundle\CoreBundle\Context\CachedTenantContextInterface;
23
use SWP\Bundle\CoreBundle\Model\AnalyticsReportInterface;
24
use SWP\Bundle\CoreBundle\Model\Article;
25
use SWP\Bundle\ElasticSearchBundle\Criteria\Criteria;
26
use SWP\Component\Common\Model\DateTime;
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
                $exportAnalytics->getTerm(),
93
                [
94
                    'sort' => ['articleStatistics.pageViewsNumber' => 'desc'],
95
                    'publishedBefore' => $exportAnalytics->getEnd(),
96
                    'publishedAfter' => $exportAnalytics->getStart(),
97
                    'tenantCode' => $tenantCode,
98
                    'routes' => $exportAnalytics->getRouteIds(),
99
                    'authors' => $exportAnalytics->getAuthors(),
100
                ]
101
            );
102
103
            $tenant = $this->tenantRepository->findOneBy(['code' => $tenantCode]);
104
            if (null === $tenant) {
105
                throw new RuntimeException("Tenant with code $tenantCode not found");
106
            }
107
108
            $this->cachedTenantContext->setTenant($tenant);
109
110
            $articleRepository = $this->elasticaRepositoryManager->getRepository(Article::class);
111
112
            $articles = $articleRepository->findByCriteria($criteria);
113
            $total = $articles->getTotalHits();
114
            $articles = $articles->getResults(0, 0 !== $total ? $total : 1);
115
            $data = $this->objectsToArray($articles->toArray());
116
            $path = $this->cacheDir.'/'.$fileName;
117
118
            $this->csvFileWriter->write($path, $data);
119
120
            $url = $this->reportFileUploader->upload($analyticsReport, $path);
121
122
            $this->mailer->sendReportReadyEmailNotification($exportAnalytics->getUserEmail(), $url);
123
            $analyticsReport->setStatus(AnalyticsReportInterface::STATUS_COMPLETED);
124
        } catch (Throwable $e) {
125
            $analyticsReport->setStatus(AnalyticsReportInterface::STATUS_ERRORED);
126
        }
127
128
        $analyticsReport->setUpdatedAt(DateTime::getCurrentDateTime());
129
        $this->analyticsReportRepository->flush();
130
    }
131
132
    private function objectsToArray(array $rows): array
133
    {
134
        $data = [
135
            ['Article ID', 'Publish Date', 'Total Views', 'Section', 'Title', 'Author(s)'],
136
        ];
137
138
        /** @var Article $article */
139
        foreach ($rows as $article) {
140
            $data[] = [
141
                $article->getId(),
142
                $article->getPublishedAt()->format('Y-m-d H:i'),
143
                null !== $article->getArticleStatistics() ? $article->getArticleStatistics()->getPageViewsNumber() : 0,
144
                $article->getRoute()->getName(),
145
                $article->getTitle(),
146
                implode(', ', $article->getAuthorsNames()),
147
            ];
148
        }
149
150
        return $data;
151
    }
152
}
153