Passed
Push — master ( e9dfe5...fa6a28 )
by MusikAnimal
05:21
created

UserRightsRepository::getGlobalRightsChanges()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the UserRightsRepository class.
4
 */
5
6
namespace Xtools;
7
8
use Mediawiki\Api\SimpleRequest;
9
10
/**
11
 * An UserRightsRepository is responsible for retrieving information around a user's
12
 * rights on a given wiki. It doesn't do any post-processing of that information.
13
 * @codeCoverageIgnore
14
 */
15
class UserRightsRepository extends Repository
16
{
17
    /**
18
     * Get user rights changes of the given user, including those made on Meta.
19
     * @param Project $project
20
     * @param User $user
21
     * @return array
22
     */
23
    public function getRightsChanges(Project $project, User $user)
24
    {
25
        $changes = $this->queryRightsChanges($project, $user);
26
27
        if ((bool)$this->container->hasParameter('app.is_labs')) {
28
            $changes = array_merge(
29
                $changes,
30
                $this->queryRightsChanges($project, $user, 'meta')
31
            );
32
        }
33
34
        return $changes;
35
    }
36
37
    /**
38
     * Get global user rights changes of the given user.
39
     * @param Project $project Global rights are always on Meta, so this
40
     *     Project instance is re-used if it is already Meta, otherwise
41
     *     a new Project instance is created.
42
     * @param User $user
43
     * @return array
44
     */
45
    public function getGlobalRightsChanges(Project $project, User $user)
46
    {
47
        return $this->queryRightsChanges($project, $user, 'global');
48
    }
49
50
    /**
51
     * User rights changes for given project, optionally fetched from Meta.
52
     * @param Project $project Global rights and Meta-changed rights will
53
     *     automatically use the Meta Project. This Project instance is re-used
54
     *     if it is already Meta, otherwise a new Project instance is created.
55
     * @param User $user
56
     * @param string $type One of 'local' - query the local rights log,
57
     *     'meta' - query for username@dbname for local rights changes made on Meta, or
58
     *     'global' - query for global rights changes.
59
     * @return array
60
     */
61
    private function queryRightsChanges(Project $project, User $user, $type = 'local')
62
    {
63
        $dbName = $project->getDatabaseName();
64
65
        // Global rights and Meta-changed rights should use a Meta Project.
66
        if ($type !== 'local') {
67
            $dbName = 'metawiki';
68
        }
69
70
        $loggingTable = $this->getTableName($dbName, 'logging', 'logindex');
71
        $userTable = $this->getTableName($dbName, 'user');
72
        $username = str_replace(' ', '_', $user->getUsername());
73
74
        if ($type === 'meta') {
75
            // Reference the original Project.
76
            $username = $username.'@'.$project->getDatabaseName();
77
        }
78
79
        // Way back when it was possible to have usernames with lowercase characters.
80
        // Some log entires are caught unless we look for both variations.
81
        $usernameLower = lcfirst($username);
82
83
        $logType = $type == 'global' ? 'gblrights' : 'rights';
84
85
        $sql = "SELECT log_id, log_timestamp, log_comment, log_params, log_action,
86
                    IF(log_user_text != '', log_user_text, (
87
                        SELECT user_name
88
                        FROM $userTable
89
                        WHERE user_id = log_user
90
                    )) AS log_user_text,
91
                    '$type' AS type
92
                FROM $loggingTable
93
                WHERE log_type = '$logType'
94
                AND log_namespace = 2
95
                AND log_title IN (:username, :username2)
96
                ORDER BY log_timestamp DESC";
97
98
        return $this->executeProjectsQuery($sql, [
99
            'username' => $username,
100
            'username2' => $usernameLower,
101
        ])->fetchAll();
102
    }
103
104
    /**
105
     * Get the localized names for the user groups, fetched from on-wiki system messages.
106
     * @param Project $project
107
     * @param string[] $rights Database values for the rights we want the names of.
108
     * @param string $lang Language code to pass in.
109
     * @return string[] Localized names keyed by database value.
110
     */
111
    public function getRightsNames(Project $project, $rights, $lang)
112
    {
113
        $rightsPaths = array_map(function ($right) {
114
            return "Group-$right-member";
115
        }, $rights);
116
117
        $params = [
118
            'action' => 'query',
119
            'meta' => 'allmessages',
120
            'ammessages' => implode('|', $rightsPaths),
121
            'amlang' => $lang,
122
            'amenableparser' => 1,
123
            'formatversion' => 2,
124
        ];
125
        $api = $this->getMediawikiApi($project);
126
        $query = new SimpleRequest('query', $params);
127
        $result = $api->getRequest($query);
128
129
        $allmessages = $result['query']['allmessages'];
130
131
        $localized = [];
132
133
        foreach ($allmessages as $msg) {
134
            $normalized = preg_replace('/^group-|-member$/', '', $msg['normalizedname']);
135
            $localized[$normalized] = $msg['content'];
136
        }
137
138
        return $localized;
139
    }
140
}
141