Passed
Push — master ( 738dcd...d9f1a8 )
by MusikAnimal
04:23
created

ArticleInfoRepository::getTopEditorsByEditCount()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 35
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 5
dl 0
loc 35
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the ArticleInfoRepository class.
4
 */
5
6
namespace Xtools;
7
8
use GuzzleHttp;
9
10
/**
11
 * ArticleInfoRepository is responsible for retrieving data about a single
12
 * article on a given wiki.
13
 * @codeCoverageIgnore
14
 */
15
class ArticleInfoRepository extends Repository
16
{
17
    /**
18
     * Get the number of edits made to the page by bots or former bots.
19
     * @param  Page $page
20
     * @param  false|int $start
21
     * @param  false|int $end
22
     * @return \Doctrine\DBAL\Driver\Statement resolving with keys 'count', 'username' and 'current'.
23
     */
24
    public function getBotData(Page $page, $start, $end)
25
    {
26
        $project = $page->getProject();
27
        $userGroupsTable = $project->getTableName('user_groups');
28
        $userFormerGroupsTable = $project->getTableName('user_former_groups');
29
30
        $datesConditions = $this->getDateConditions($start, $end);
31
32
        $sql = "SELECT COUNT(DISTINCT(rev_id)) AS count, rev_user_text AS username, ug_group AS current
33
                FROM " . $project->getTableName('revision') . "
34
                LEFT JOIN $userGroupsTable ON rev_user = ug_user
35
                LEFT JOIN $userFormerGroupsTable ON rev_user = ufg_user
36
                WHERE rev_page = :pageId AND (ug_group = 'bot' OR ufg_group = 'bot') $datesConditions
37
                GROUP BY rev_user_text";
38
39
        return $this->executeProjectsQuery($sql, ['pageId' => $page->getId()]);
40
    }
41
42
    /**
43
     * Get prior deletions, page moves, and protections to the page.
44
     * @param Page $page
45
     * @param false|int $start
46
     * @param false|int $end
47
     * @return string[] each entry with keys 'log_action', 'log_type' and 'timestamp'.
48
     */
49
    public function getLogEvents(Page $page, $start, $end)
50
    {
51
        $loggingTable = $page->getProject()->getTableName('logging', 'logindex');
52
53
        $datesConditions = $this->getDateConditions($start, $end, '', 'log_timestamp');
54
55
        $sql = "SELECT log_action, log_type, log_timestamp AS 'timestamp'
56
                FROM $loggingTable
57
                WHERE log_namespace = '" . $page->getNamespace() . "'
58
                AND log_title = :title AND log_timestamp > 1 $datesConditions
59
                AND log_type IN ('delete', 'move', 'protect', 'stable')";
60
        $title = str_replace(' ', '_', $page->getTitle());
61
62
        return $this->executeProjectsQuery($sql, ['title' => $title])->fetchAll();
63
    }
64
65
    /**
66
     * Query the WikiWho service to get authorship percentages.
67
     * @see https://api.wikiwho.net/
68
     * @param Page $page
69
     * @return array[] Response from WikiWho.
70
     */
71
    public function getTextshares(Page $page)
72
    {
73
        $title = rawurlencode(str_replace(' ', '_', $page->getTitle()));
74
        $client = new GuzzleHttp\Client();
75
76
        $projectLang = $page->getProject()->getLang();
77
78
        $url = "https://api.wikiwho.net/$projectLang/api/v1.0.0-beta/rev_content/" .
79
            "$title/?o_rev_id=false&editor=true&token_id=false&out=false&in=false";
80
81
        $res = $client->request('GET', $url, ['http_errors' => false]);
82
        return json_decode($res->getBody()->getContents(), true);
83
    }
84
85
    /**
86
     * Get a map of user IDs/usernames given the user IDs.
87
     * @param Project $project
88
     * @param int[]   $userIds
89
     * @return array
90
     */
91
    public function getUsernamesFromIds(Project $project, $userIds)
92
    {
93
        $userTable = $project->getTableName('user');
94
        $userIds = implode(',', array_filter($userIds));
95
        $sql = "SELECT user_id, user_name
96
                FROM $userTable
97
                WHERE user_id IN ($userIds)";
98
        return $this->executeProjectsQuery($sql)->fetchAll();
99
    }
100
101
    /**
102
     * Get the number of categories, templates, and files that are on the page.
103
     * @param Page $page
104
     * @return array With keys 'categories', 'templates' and 'files'.
105
     */
106
    public function getTransclusionData(Page $page)
107
    {
108
        $categorylinksTable = $page->getProject()->getTableName('categorylinks');
109
        $templatelinksTable = $page->getProject()->getTableName('templatelinks');
110
        $imagelinksTable = $page->getProject()->getTableName('imagelinks');
111
        $sql = "(
112
                    SELECT 'categories' AS `key`, COUNT(*) AS val
113
                    FROM $categorylinksTable
114
                    WHERE cl_from = :pageId
115
                ) UNION (
116
                    SELECT 'templates' AS `key`, COUNT(*) AS val
117
                    FROM $templatelinksTable
118
                    WHERE tl_from = :pageId
119
                ) UNION (
120
                    SELECT 'files' AS `key`, COUNT(*) AS val
121
                    FROM $imagelinksTable
122
                    WHERE il_from = :pageId
123
                )";
124
        $resultQuery = $this->executeProjectsQuery($sql, ['pageId' => $page->getId()]);
125
        $transclusionCounts = [];
126
        while ($result = $resultQuery->fetch()) {
127
            $transclusionCounts[$result['key']] = $result['val'];
128
        }
129
130
        return $transclusionCounts;
131
    }
132
133
    /**
134
     * Get the top editors to the page by edit count.
135
     * @param Page $page
136
     * @param bool $start
137
     * @param bool $end
138
     * @param int $limit
139
     * @param bool $noBots
140
     * @return array
141
     */
142
    public function getTopEditorsByEditCount(Page $page, $start = false, $end = false, $limit = 20, $noBots = false)
143
    {
144
        $project = $page->getProject();
145
        // Faster to use revision instead of revision_userindex in this case.
146
        $revTable = $project->getTableName('revision', '');
147
148
        $dateConditions = $this->getDateConditions($start, $end);
149
150
        $sql = "SELECT rev_user_text AS username,
151
                    COUNT(rev_id) AS count,
152
                    SUM(rev_minor_edit) AS minor,
153
                    MIN(rev_timestamp) AS first_timestamp,
154
                    MIN(rev_id) AS first_revid,
155
                    MAX(rev_timestamp) AS latest_timestamp,
156
                    MAX(rev_id) AS latest_revid
157
                FROM $revTable
158
                WHERE rev_page = :pageId $dateConditions";
159
160
        if ($noBots) {
161
            $userGroupsTable = $project->getTableName('user_groups');
162
            $sql .= "AND NOT EXISTS (
163
                         SELECT 1
164
                         FROM $userGroupsTable
165
                         WHERE ug_user = rev_user
166
                         AND ug_group = 'bot'
167
                     )";
168
        }
169
170
        $sql .= "GROUP BY rev_user_text
171
                 ORDER BY count DESC
172
                 LIMIT $limit";
173
174
        return $this->executeProjectsQuery($sql, [
175
            'pageId' => $page->getId()
176
        ])->fetchAll();
177
    }
178
}
179