Passed
Push — master ( 9c80d9...628b52 )
by MusikAnimal
05:31
created

CategoryEditsRepository::getCategoryEdits()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 45
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 30
nc 2
nop 6
dl 0
loc 45
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the CategoryEditsRepository class.
4
 */
5
6
namespace Xtools;
7
8
use AppBundle\Helper\AutomatedEditsHelper;
9
use DateInterval;
10
use Symfony\Component\Config\Definition\Exception\Exception;
11
12
/**
13
 * CategoryEditsRepository is responsible for retrieving data from the database
14
 * about the edits made by a user to pages in a set of given categories.
15
 * @codeCoverageIgnore
16
 */
17
class CategoryEditsRepository extends Repository
18
{
19
    /** @var AutomatedEditsHelper Used for fetching the tool list and filtering it. */
20
    private $aeh;
21
22
    /**
23
     * Method to give the repository access to the AutomatedEditsHelper.
24
     */
25
    public function getHelper()
26
    {
27
        if (!isset($this->aeh)) {
28
            $this->aeh = $this->container->get('app.automated_edits_helper');
29
        }
30
        return $this->aeh;
31
    }
32
33
    /**
34
     * Get the number of edits this user made to the given categories.
35
     * @param Project $project
36
     * @param User $user
37
     * @param string[] $categories
38
     * @param string $start Start date in a format accepted by strtotime()
39
     * @param string $end End date in a format accepted by strtotime()
40
     * @return int Result of query, see below.
41
     */
42
    public function countCategoryEdits(
43
        Project $project,
44
        User $user,
45
        array $categories,
46
        $start = '',
47
        $end = ''
48
    ) {
49
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_categoryeditcount');
50
        if ($this->cache->hasItem($cacheKey)) {
51
            return $this->cache->getItem($cacheKey)->get();
52
        }
53
        $this->stopwatch->start($cacheKey, 'XTools');
54
55
        $revisionTable = $project->getTableName('revision');
56
        $categorylinksTable = $project->getTableName('categorylinks');
57
58
        $query = $this->getProjectsConnection()->createQueryBuilder();
59
        $query->select(['COUNT(DISTINCT(revs.rev_id))'])
60
            ->from($revisionTable, 'revs')
61
            ->join('revs', $categorylinksTable, null, 'cl_from = rev_page')
62
            ->where('revs.rev_user_text = :username')
63
            ->andWhere($query->expr()->in('cl_to', ':categories'));
64
65
        $result = (int)$this->executeStmt($query, $user, $categories, $start, $end)->fetchColumn();
66
67
        // Cache and return.
68
        $this->stopwatch->stop($cacheKey);
69
        return $this->setCache($cacheKey, $result);
70
    }
71
72
    /**
73
     * Get number of edits within each individual category.
74
     * @param  Project $project
75
     * @param  User    $user
76
     * @param  array   $categories
77
     * @param  string  $start
78
     * @param  string  $end
79
     * @return string[] With categories as keys, counts as values.
80
     */
81
    public function getCategoryCounts(
82
        Project $project,
83
        User $user,
84
        array $categories,
85
        $start = '',
86
        $end = ''
87
    ) {
88
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_categorycounts');
89
        if ($this->cache->hasItem($cacheKey)) {
90
            return $this->cache->getItem($cacheKey)->get();
91
        }
92
        $this->stopwatch->start($cacheKey, 'XTools');
93
94
        $revisionTable = $project->getTableName('revision');
95
        $categorylinksTable = $project->getTableName('categorylinks');
96
97
        $query = $this->getProjectsConnection()->createQueryBuilder();
98
        $query->select(['cl_to', 'COUNT(rev_id)'])
99
            ->from($revisionTable, 'revs')
100
            ->join('revs', $categorylinksTable, null, 'cl_from = rev_page')
101
            ->where('revs.rev_user_text = :username')
102
            ->andWhere($query->expr()->in('cl_to', ':categories'))
103
            ->groupBy('cl_to');
104
105
        $result = $this->executeStmt($query, $user, $categories, $start, $end)->fetchAll(\PDO::FETCH_KEY_PAIR);
106
107
        // Cache and return.
108
        $this->stopwatch->stop($cacheKey);
109
        return $this->setCache($cacheKey, $result);
110
    }
111
112
    /**
113
     * Get contributions made to the given categories.
114
     * @param Project $project
115
     * @param User $user
116
     * @param string[] $categories
117
     * @param string $start Start date in a format accepted by strtotime()
118
     * @param string $end End date in a format accepted by strtotime()
119
     * @param int $offset Used for pagination, offset results by N edits
120
     * @return string[] Result of query, with columns 'page_title',
121
     *   'page_namespace', 'rev_id', 'timestamp', 'minor',
122
     *   'length', 'length_change', 'comment'
123
     */
124
    public function getCategoryEdits(
125
        Project $project,
126
        User $user,
127
        array $categories,
128
        $start = '',
129
        $end = '',
130
        $offset = 0
131
    ) {
132
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_categoryedits');
133
        if ($this->cache->hasItem($cacheKey)) {
134
            return $this->cache->getItem($cacheKey)->get();
135
        }
136
        $this->stopwatch->start($cacheKey, 'XTools');
137
138
        $pageTable = $project->getTableName('page');
139
        $revisionTable = $project->getTableName('revision');
140
        $categorylinksTable = $project->getTableName('categorylinks');
141
142
        $query = $this->getProjectsConnection()->createQueryBuilder();
143
        $query->select([
144
                'page_title',
145
                'page_namespace',
146
                'revs.rev_id AS rev_id',
147
                'revs.rev_timestamp AS timestamp',
148
                'revs.rev_minor_edit AS minor',
149
                'revs.rev_len AS length',
150
                '(CAST(revs.rev_len AS SIGNED) - IFNULL(parentrevs.rev_len, 0)) AS length_change',
151
                'revs.rev_comment AS comment',
152
            ])
153
            ->from($pageTable)
154
            ->join($pageTable, $revisionTable, 'revs', 'page_id = revs.rev_page')
155
            ->join('revs', $categorylinksTable, null, 'cl_from = rev_page')
156
            ->leftJoin('revs', $revisionTable, 'parentrevs', 'revs.rev_parent_id = parentrevs.rev_id')
157
            ->where('revs.rev_user_text = :username')
158
            ->andWhere($query->expr()->in('cl_to', ':categories'))
159
            ->groupBy('revs.rev_id')
160
            ->orderBy('revs.rev_timestamp', 'DESC')
161
            ->setMaxResults(50)
162
            ->setFirstResult($offset);
163
164
        $result = $this->executeStmt($query, $user, $categories, $start, $end)->fetchAll();
165
166
        // Cache and return.
167
        $this->stopwatch->stop($cacheKey);
168
        return $this->setCache($cacheKey, $result);
169
    }
170
171
    /**
172
     * Bind dates, username and categories then execute the query.
173
     * @param  \Doctrine\DBAL\Query\QueryBuilder $query
174
     * @param User $user
175
     * @param string[] $categories
176
     * @param string $start Start date in a format accepted by strtotime()
177
     * @param string $end End date in a format accepted by strtotime()
178
     * @return \Doctrine\DBAL\Driver\Statement
179
     */
180
    private function executeStmt(\Doctrine\DBAL\Query\QueryBuilder $query, User $user, array $categories, $start, $end)
181
    {
182
        if (!empty($start)) {
183
            $query->andWhere('revs.rev_timestamp >= :start');
184
            $query->setParameter(':start', $start);
185
        }
186
        if (!empty($end)) {
187
            $query->andWhere('revs.rev_timestamp <= DATE_FORMAT(:end, "%Y%m%d235959")');
188
            $query->setParameter(':end', $end);
189
        }
190
191
        $username = $user->getUsername();
192
        $query->setParameter(':username', $username);
193
        $query->setParameter('categories', $categories, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
194
195
        return $this->executeQueryBuilder($query);
196
    }
197
}
198