Test Failed
Push — ip-ranges ( af8775 )
by MusikAnimal
07:44
created

SimpleEditCounterRepository::fetchDataNormal()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 46
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 25
c 0
b 0
f 0
nc 8
nop 5
dl 0
loc 46
rs 9.52
1
<?php
2
/**
3
 * This file contains only the SimpleEditCounterRepository class.
4
 */
5
6
declare(strict_types = 1);
7
8
namespace AppBundle\Repository;
9
10
use AppBundle\Model\Project;
11
use AppBundle\Model\User;
12
use PDO;
13
use Wikimedia\IPUtils;
14
15
/**
16
 * SimpleEditCounterRepository is responsible for retrieving data
17
 * from the database for the Simple Edit Counter tool.
18
 * @codeCoverageIgnore
19
 */
20
class SimpleEditCounterRepository extends Repository
21
{
22
    /**
23
     * Execute and return results of the query used for the Simple Edit Counter.
24
     * @param Project $project
25
     * @param User $user
26
     * @param int|string $namespace Namespace ID or 'all' for all namespaces.
27
     * @param int|false $start Unix timestamp.
28
     * @param int|false $end Unix timestamp.
29
     * @return string[] Counts, each row with keys 'source' and 'value'.
30
     */
31
    public function fetchData(Project $project, User $user, $namespace = 'all', $start = false, $end = false): array
32
    {
33
        $cacheKey = $this->getCacheKey(func_get_args(), 'simple_editcount');
34
        if ($this->cache->hasItem($cacheKey)) {
35
            return $this->cache->getItem($cacheKey)->get();
36
        }
37
38
        if ($user->isIpRange()) {
39
            $result = $this->fetchDataIpRange($project, $user, $namespace, $start, $end);
40
        } else {
41
            $result = $this->fetchDataNormal($project, $user, $namespace, $start, $end);
42
        }
43
44
        // Cache and return.
45
        return $this->setCache($cacheKey, $result);
46
    }
47
48
    /**
49
     * @param Project $project
50
     * @param User $user
51
     * @param int|string $namespace
52
     * @param int|false $start
53
     * @param int|false $end
54
     * @return string[] Counts, each row with keys 'source' and 'value'.
55
     */
56
    private function fetchDataNormal(
57
        Project $project,
58
        User $user,
59
        $namespace = 'all',
60
        $start = false,
61
        $end = false
62
    ): array {
63
        $userTable = $project->getTableName('user');
64
        $pageTable = $project->getTableName('page');
65
        $archiveTable = $project->getTableName('archive');
66
        $revisionTable = $project->getTableName('revision');
67
        $userGroupsTable = $project->getTableName('user_groups');
68
69
        $arDateConditions = $this->getDateConditions($start, $end, false, '', 'ar_timestamp');
70
        $revDateConditions = $this->getDateConditions($start, $end);
71
72
        $revNamespaceJoinSql = 'all' === $namespace ? '' : "JOIN $pageTable ON rev_page = page_id";
73
        $revNamespaceWhereSql = 'all' === $namespace ? '' : "AND page_namespace = $namespace";
74
        $arNamespaceWhereSql = 'all' === $namespace ? '' : "AND ar_namespace = $namespace";
75
76
        $sql = "SELECT 'id' AS source, user_id as value
77
                    FROM $userTable
78
                    WHERE user_name = :username
79
                UNION
80
                SELECT 'arch' AS source, COUNT(*) AS value
81
                    FROM $archiveTable
82
                    WHERE ar_actor = :actorId
83
                    $arNamespaceWhereSql
84
                    $arDateConditions
85
                UNION
86
                SELECT 'rev' AS source, COUNT(*) AS value
87
                    FROM $revisionTable
88
                    $revNamespaceJoinSql
89
                    WHERE rev_actor = :actorId
90
                    $revNamespaceWhereSql
91
                    $revDateConditions
92
                UNION
93
                SELECT 'groups' AS source, ug_group AS value
94
                    FROM $userGroupsTable
95
                    JOIN $userTable ON user_id = ug_user
96
                    WHERE user_name = :username";
97
98
        return $this->executeProjectsQuery($project, $sql, [
99
            'username' => $user->getUsername(),
100
            'actorId' => $user->getActorId($project),
101
        ])->fetchAll();
102
    }
103
104
    /**
105
     * @param Project $project
106
     * @param User $user
107
     * @param int|string $namespace
108
     * @param int|false $start
109
     * @param int|false $end
110
     * @return string[] Counts, each row with keys 'source' and 'value'.
111
     */
112
    private function fetchDataIpRange(
113
        Project $project,
114
        User $user,
115
        $namespace = 'all',
116
        $start = false,
117
        $end = false
118
    ): array {
119
        $ipcTable = $project->getTableName('ip_changes');
120
        $revTable = $project->getTableName('revision', '');
121
        $pageTable = $project->getTableName('page');
122
123
        $revDateConditions = $this->getDateConditions($start, $end, false, "$ipcTable.", 'ipc_rev_timestamp');
124
        [$startHex, $endHex] = IPUtils::parseRange($user->getUsername());
125
126
        $revNamespaceJoinSql = 'all' === $namespace ? '' : "JOIN $revTable ON rev_id = ipc_rev_id " .
127
            "JOIN $pageTable ON rev_page = page_id";
128
        $revNamespaceWhereSql = 'all' === $namespace ? '' : "AND page_namespace = $namespace";
129
130
        $sql = "SELECT 'rev' AS source, COUNT(*) AS value
131
                FROM $ipcTable
132
                $revNamespaceJoinSql
133
                WHERE ipc_hex BETWEEN :start AND :end 
134
                $revDateConditions
135
                $revNamespaceWhereSql";
136
137
        return $this->executeProjectsQuery($project, $sql, [
138
            'start' => $startHex,
139
            'end' => $endHex,
140
        ])->fetchAll();
141
    }
142
}
143