Passed
Push — task/2976_TYPO3.11_compatibili... ( 4d1a77...3b9190 )
by Rafael
03:39
created

StatisticsRepository   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Test Coverage

Coverage 61.83%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 69
dl 0
loc 189
ccs 47
cts 76
cp 0.6183
rs 10
c 1
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getTopKeyWordsWithoutHits() 0 3 1
A saveStatisticsRecord() 0 4 1
A getTopKeyWordsWithHits() 0 3 1
A getSearchStatistics() 0 8 1
A getTopKeyWordsWithOrWithoutHits() 0 14 2
A countByRootPageId() 0 8 1
A getPreparedQueryBuilderForSearchStatisticsAndTopKeywords() 0 21 1
A getQueriesOverTime() 0 22 1
A getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguration() 0 15 1
1
<?php declare(strict_types = 1);
2
namespace ApacheSolrForTypo3\Solr\Domain\Search\Statistics;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2016 Thomas Hohn <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\System\Records\AbstractRepository;
28
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
29
30
/**
31
 * Calculates the SearchQueryStatistics
32
 *
33
 * @author Thomas Hohn <[email protected]>
34
 */
35
class StatisticsRepository extends AbstractRepository
36
{
37
    /**
38
     * @var string
39
     */
40
    protected $table = 'tx_solr_statistics';
41
42
    /**
43
     * Fetches must popular search keys words from the table tx_solr_statistics
44
     *
45
     * @param int $rootPageId
46
     * @param int $days number of days of history to query
47
     * @param int $limit
48
     * @return mixed
49
     */
50 1
    public function getSearchStatistics(int $rootPageId, int $days = 30, $limit = 10)
51
    {
52 1
        $now = time();
53 1
        $timeStart = (int)($now - 86400 * $days); // 86400 seconds/day
54 1
        $limit = (int)$limit;
55
56 1
        return $this->getPreparedQueryBuilderForSearchStatisticsAndTopKeywords($rootPageId, $timeStart, $limit)
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

56
        return /** @scrutinizer ignore-deprecated */ $this->getPreparedQueryBuilderForSearchStatisticsAndTopKeywords($rootPageId, $timeStart, $limit)

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
57 1
            ->execute()->fetchAll();
58
    }
59
60
    /**
61
     * Returns prepared QueryBuilder for two purposes:
62
     * for getSearchStatistics() and getTopKeyWordsWithOrWithoutHits() methods
63
     *
64
     * @param int $rootPageId
65
     * @param int $timeStart
66
     * @param int $limit
67
     * @return QueryBuilder
68
     */
69 4
    protected function getPreparedQueryBuilderForSearchStatisticsAndTopKeywords(int $rootPageId, int $timeStart, int $limit) : QueryBuilder
70
    {
71 4
        $countRows = $this->countByRootPageId($rootPageId);
72 4
        $queryBuilder = $this->getQueryBuilder();
73 4
        $statisticsQueryBuilder = $queryBuilder
74 4
            ->select('keywords')
75 4
            ->add('select', $queryBuilder->expr()->count('keywords', 'count'), true)
76 4
            ->add('select', $queryBuilder->expr()->avg('num_found', 'hits'), true)
77 4
            ->add('select', '(' . $queryBuilder->expr()->count('keywords') . ' * 100 / ' . $countRows . ') AS percent', true)
78 4
            ->from($this->table)
79 4
            ->andWhere(
80 4
                $queryBuilder->expr()->gt('tstamp', $timeStart),
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->gt('tstamp', $timeStart) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...n|array<integer,string> expected by parameter $where of TYPO3\CMS\Core\Database\...ueryBuilder::andWhere(). ( Ignorable by Annotation )

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

80
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->gt('tstamp', $timeStart),
Loading history...
81 4
                $queryBuilder->expr()->eq('root_pid', $rootPageId)
82
            )
83 4
            ->groupBy('keywords')
84 4
            ->orderBy('count', 'DESC')
85 4
            ->addOrderBy('hits', 'DESC')
86 4
            ->addOrderBy('keywords', 'ASC')
87 4
            ->setMaxResults($limit);
88
89 4
        return $statisticsQueryBuilder;
90
    }
91
92
    /**
93
     * Find Top search keywords with results
94
     *
95
     * @param int $rootPageId
96
     * @param int $days number of days of history to query
97
     * @param int $limit
98
     * @return array
99
     */
100 1
    public function getTopKeyWordsWithHits(int $rootPageId, int $days = 30, int $limit = 10) : array
101
    {
102 1
        return $this->getTopKeyWordsWithOrWithoutHits($rootPageId, $days, $limit, false);
103
    }
104
105
    /**
106
     * Find Top search keywords without results
107
     *
108
     * @param int $rootPageId
109
     * @param int $days number of days of history to query
110
     * @param int $limit
111
     * @return array
112
     */
113 2
    public function getTopKeyWordsWithoutHits(int $rootPageId, int $days = 30, int $limit = 10) : array
114
    {
115 2
        return $this->getTopKeyWordsWithOrWithoutHits($rootPageId, $days, $limit, true);
116
    }
117
118
    /**
119
     * Find Top search keywords with or without results
120
     *
121
     * @param int $rootPageId
122
     * @param int $days number of days of history to query
123
     * @param int $limit
124
     * @param bool $withoutHits
125
     * @return array
126
     */
127 3
    protected function getTopKeyWordsWithOrWithoutHits(int $rootPageId, int $days = 30, int $limit = 10, bool $withoutHits = false) : array
128
    {
129 3
        $now = time();
130 3
        $timeStart = $now - 86400 * $days; // 86400 seconds/day
131
132 3
        $queryBuilder = $this->getPreparedQueryBuilderForSearchStatisticsAndTopKeywords($rootPageId, $timeStart, $limit);
133
        // Check if we want without or with hits
134 3
        if ($withoutHits === true) {
135 2
            $queryBuilder->andWhere($queryBuilder->expr()->eq('num_found', 0));
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->eq('num_found', 0) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...n|array<integer,string> expected by parameter $where of TYPO3\CMS\Core\Database\...ueryBuilder::andWhere(). ( Ignorable by Annotation )

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

135
            $queryBuilder->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('num_found', 0));
Loading history...
136
        } else {
137 1
            $queryBuilder->andWhere($queryBuilder->expr()->gt('num_found', 0));
138
        }
139
140 3
        return $queryBuilder->execute()->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

140
        return /** @scrutinizer ignore-deprecated */ $queryBuilder->execute()->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
141
    }
142
143
    /**
144
     * Get number of queries over time
145
     *
146
     * @param int $rootPageId
147
     * @param int $days number of days of history to query
148
     * @param int $bucketSeconds Seconds per bucket
149
     * @return array [labels, data]
150
     */
151
    public function getQueriesOverTime(int $rootPageId, int $days = 30, int $bucketSeconds = 3600) : array
152
    {
153
        $now = time();
154
        $timeStart = $now - 86400 * intval($days); // 86400 seconds/day
155
156
        $queryBuilder = $this->getQueryBuilder();
157
        $result = $queryBuilder
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

157
        $result = /** @scrutinizer ignore-deprecated */ $queryBuilder

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
158
            ->addSelectLiteral(
159
                'FLOOR(tstamp/' . $bucketSeconds . ') AS bucket',
160
                '(tstamp - (tstamp % 86400)) AS timestamp',
161
                $queryBuilder->expr()->count('*', 'numQueries')
162
            )
163
            ->from($this->table)
164
            ->andWhere(
165
                $queryBuilder->expr()->gt('tstamp', $timeStart),
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->gt('tstamp', $timeStart) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...n|array<integer,string> expected by parameter $where of TYPO3\CMS\Core\Database\...ueryBuilder::andWhere(). ( Ignorable by Annotation )

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

165
                /** @scrutinizer ignore-type */ $queryBuilder->expr()->gt('tstamp', $timeStart),
Loading history...
166
                $queryBuilder->expr()->eq('root_pid', $rootPageId)
167
            )
168
            ->groupBy('bucket', 'timestamp')
169
            ->orderBy('bucket', 'ASC')
170
            ->execute()->fetchAll();
171
172
        return $result;
173
    }
174
175
    /**
176
     * Regurns a result set by given plugin.tx_solr.search.frequentSearches.select configuration.
177
     *
178
     * @param array $frequentSearchConfiguration
179
     * @return array Array of frequent search terms, keys are the terms, values are hits
180
     */
181
    public function getFrequentSearchTermsFromStatisticsByFrequentSearchConfiguration(array $frequentSearchConfiguration) : array
182
    {
183
        $queryBuilder = $this->getQueryBuilder();
184
        $resultSet = $queryBuilder
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

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

184
        $resultSet = /** @scrutinizer ignore-deprecated */ $queryBuilder

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
185
            ->addSelectLiteral(
186
                $frequentSearchConfiguration['select.']['SELECT']
187
            )
188
            ->from($frequentSearchConfiguration['select.']['FROM'])
189
            ->add('where', $frequentSearchConfiguration['select.']['ADD_WHERE'], true)
190
            ->add('groupBy', $frequentSearchConfiguration['select.']['GROUP_BY'], true)
191
            ->add('orderBy', $frequentSearchConfiguration['select.']['ORDER_BY'])
192
            ->setMaxResults((int)$frequentSearchConfiguration['limit'])
193
            ->execute()->fetchAll();
194
195
        return $resultSet;
196
    }
197
198
    /**
199
     * Persists statistics record
200
     *
201
     * @param array $statisticsRecord
202
     * @return void
203
     */
204 1
    public function saveStatisticsRecord(array $statisticsRecord)
205
    {
206 1
        $queryBuilder = $this->getQueryBuilder();
207 1
        $queryBuilder->insert($this->table)->values($statisticsRecord)->execute();
208 1
    }
209
210
    /**
211
     * Counts rows for specified site
212
     *
213
     * @param int $rootPageId
214
     * @return int
215
     */
216 5
    public function countByRootPageId(int $rootPageId): int
217
    {
218 5
        $queryBuilder = $this->getQueryBuilder();
219 5
        return (int)$this->getQueryBuilder()
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...y\Result::fetchColumn() has been deprecated: Use fetchOne() instead. ( Ignorable by Annotation )

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

219
        return (int)/** @scrutinizer ignore-deprecated */ $this->getQueryBuilder()

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
220 5
            ->count('*')
221 5
            ->from($this->table)
222 5
            ->andWhere($queryBuilder->expr()->eq('root_pid', $rootPageId))
0 ignored issues
show
Bug introduced by
$queryBuilder->expr()->e...root_pid', $rootPageId) of type string is incompatible with the type Doctrine\DBAL\Query\Expr...n|array<integer,string> expected by parameter $where of TYPO3\CMS\Core\Database\...ueryBuilder::andWhere(). ( Ignorable by Annotation )

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

222
            ->andWhere(/** @scrutinizer ignore-type */ $queryBuilder->expr()->eq('root_pid', $rootPageId))
Loading history...
223 5
            ->execute()->fetchColumn(0);
224
    }
225
}
226