Passed
Push — release-11.5.x ( 385fe8...cd49eb )
by Rafael
53:22 queued 14:05
created

StatisticsWriterProcessor::getTSFE()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace ApacheSolrForTypo3\Solr\Domain\Search\Statistics;
17
18
use ApacheSolrForTypo3\Solr\Domain\Search\Query\Query;
19
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSet;
20
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResultSetProcessor;
21
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
22
use ApacheSolrForTypo3\Solr\HtmlContentExtractor;
23
use ApacheSolrForTypo3\Solr\Util;
24
use TYPO3\CMS\Core\Context\Context;
25
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Core\Utility\IpAnonymizationUtility;
28
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
29
30
/**
31
 * Writes statistics after searches have been conducted.
32
 *
33
 * @author Ingo Renner <[email protected]>
34
 * @author Dimitri Ebert <[email protected]>
35
 * @author Timo Hund <[email protected]>
36
 */
37
class StatisticsWriterProcessor implements SearchResultSetProcessor
38
{
39
    /**
40
     * @var StatisticsRepository
41
     */
42
    protected $statisticsRepository;
43
44
    /**
45
     * @var SiteRepository
46
     */
47
    protected $siteRepository;
48
49
    /**
50
     * @param StatisticsRepository|null $statisticsRepository
51
     * @param SiteRepository|null $siteRepository
52
     */
53 1
    public function __construct(
54
        StatisticsRepository $statisticsRepository = null,
55
        SiteRepository $siteRepository = null
56
    ) {
57 1
        $this->statisticsRepository = $statisticsRepository ?? GeneralUtility::makeInstance(StatisticsRepository::class);
58 1
        $this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class);
59
    }
60
61
    /**
62
     * @param SearchResultSet $resultSet
63
     * @return SearchResultSet
64
     * @throws AspectNotFoundException
65
     */
66 1
    public function process(SearchResultSet $resultSet): SearchResultSet
67
    {
68 1
        $searchRequest = $resultSet->getUsedSearchRequest();
69 1
        $response = $resultSet->getResponse();
70 1
        $configuration = $searchRequest->getContextTypoScriptConfiguration();
71 1
        $keywords = $this->getProcessedKeywords($resultSet->getUsedQuery(), $configuration->getSearchFrequentSearchesUseLowercaseKeywords());
0 ignored issues
show
Bug introduced by
It seems like $resultSet->getUsedQuery() can also be of type null; however, parameter $query of ApacheSolrForTypo3\Solr\...:getProcessedKeywords() does only seem to accept ApacheSolrForTypo3\Solr\Domain\Search\Query\Query, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
        $keywords = $this->getProcessedKeywords(/** @scrutinizer ignore-type */ $resultSet->getUsedQuery(), $configuration->getSearchFrequentSearchesUseLowercaseKeywords());
Loading history...
72
73 1
        if (empty($keywords)) {
74
            // do not track empty queries
75
            return $resultSet;
76
        }
77
78 1
        $filters = $searchRequest->getActiveFacets();
79 1
        $sorting = $this->sanitizeString($searchRequest->getSorting());
80 1
        $page = (int)$searchRequest->getPage();
81 1
        $ipMaskLength = $configuration->getStatisticsAnonymizeIP();
82
83 1
        $TSFE = $this->getTSFE();
84 1
        $root_pid = $this->siteRepository->getSiteByPageId($TSFE->id)->getRootPageId();
0 ignored issues
show
Bug introduced by
It seems like $TSFE->id can also be of type string; however, parameter $pageId of ApacheSolrForTypo3\Solr\...tory::getSiteByPageId() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

84
        $root_pid = $this->siteRepository->getSiteByPageId(/** @scrutinizer ignore-type */ $TSFE->id)->getRootPageId();
Loading history...
85 1
        $statisticData = [
86 1
            'pid' => $TSFE->id,
87 1
            'root_pid' => $root_pid,
88 1
            'tstamp' => $this->getTime(),
89 1
            'language' => Util::getLanguageUid(),
90
            // @extensionScannerIgnoreLine
91 1
            'num_found' => $resultSet->getAllResultCount(),
92 1
            'suggestions_shown' => is_object($response->spellcheck->suggestions ?? null) ? (int)get_object_vars($response->spellcheck->suggestions) : 0,
93
            // @extensionScannerIgnoreLine
94 1
            'time_total' => $response->debug->timing->time ?? 0,
95
            // @extensionScannerIgnoreLine
96 1
            'time_preparation' => $response->debug->timing->prepare->time ?? 0,
97
            // @extensionScannerIgnoreLine
98 1
            'time_processing' => $response->debug->timing->process->time ?? 0,
99 1
            'feuser_id' => isset($TSFE->fe_user->user) ? (int)$TSFE->fe_user->user['uid'] ?? 0 : 0,
100 1
            'cookie' => $TSFE->fe_user->id ?? '',
101 1
            'ip' => IpAnonymizationUtility::anonymizeIp($this->getUserIp(), $ipMaskLength),
102 1
            'page' => $page,
103 1
            'keywords' => $keywords,
104 1
            'filters' => serialize($filters),
105 1
            'sorting' => $sorting,
106 1
            'parameters' => isset($response->responseHeader->params) ? serialize($response->responseHeader->params) : '',
107 1
        ];
108
109 1
        $this->statisticsRepository->saveStatisticsRecord($statisticData);
110
111 1
        return $resultSet;
112
    }
113
114
    /**
115
     * @param Query $query
116
     * @param bool $lowerCaseQuery
117
     * @return string
118
     */
119 1
    protected function getProcessedKeywords(
120
        Query $query,
121
        bool $lowerCaseQuery = false
122
    ): string {
123 1
        $keywords = $query->getQuery();
124 1
        $keywords = $this->sanitizeString($keywords);
0 ignored issues
show
Bug introduced by
It seems like $keywords can also be of type null; however, parameter $string of ApacheSolrForTypo3\Solr\...essor::sanitizeString() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

124
        $keywords = $this->sanitizeString(/** @scrutinizer ignore-type */ $keywords);
Loading history...
125
        // Ensure string does not exceed database field length
126 1
        $keywords = substr($keywords, 0, 128);
127 1
        if ($lowerCaseQuery) {
128
            $keywords = mb_strtolower($keywords);
129
        }
130
131 1
        return $keywords;
132
    }
133
134
    /**
135
     * Sanitizes a string
136
     *
137
     * @param $string String to sanitize
138
     * @return string Sanitized string
139
     */
140 1
    protected function sanitizeString(string $string): string
141
    {
142
        // clean content
143 1
        $string = HtmlContentExtractor::cleanContent($string);
144 1
        $string = htmlspecialchars(strip_tags($string), ENT_QUOTES); // after entity decoding we might have tags again
145 1
        return trim($string);
146
    }
147
148
    /**
149
     * @return TypoScriptFrontendController
150
     */
151
    protected function getTSFE(): ?TypoScriptFrontendController
152
    {
153
        return $GLOBALS['TSFE'];
154
    }
155
156
    /**
157
     * @return string
158
     */
159
    protected function getUserIp(): string
160
    {
161
        return GeneralUtility::getIndpEnv('REMOTE_ADDR');
162
    }
163
164
    /**
165
     * @return mixed
166
     * @throws AspectNotFoundException
167
     */
168
    protected function getTime()
169
    {
170
        return GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('date', 'timestamp');
171
    }
172
}
173