Passed
Push — master ( 2f87b4...a0f968 )
by MusikAnimal
05:26
created

PageAssessments::getAssessments()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.049

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 7
nop 1
dl 0
loc 40
ccs 18
cts 20
cp 0.9
crap 7.049
rs 6.7272
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the PageAssessments class.
4
 */
5
6
namespace Xtools;
7
8
/**
9
 * A PageAssessments is responsible for handling logic around
10
 * processing page assessments of a given set of Pages on a Project.
11
 * @see https://www.mediawiki.org/wiki/Extension:PageAssessments
12
 */
13
class PageAssessments extends Model
14
{
15
    /** Namespaces in which there may be page assessments. */
16
    const SUPPORTED_NAMESPACES = [0, 4, 6, 10, 14, 100, 108, 118];
17
18
    /** @var Project The Project we're dealing with. */
19
    protected $project;
20
21
    /** @var array The assessments config. */
22
    protected $config;
23
24
    /**
25
     * Create a new PageAssessments.
26
     * @param Project $project
27
     */
28 114
    public function __construct(Project $project)
29
    {
30 114
        $this->project = $project;
31 114
    }
32
33
    /**
34
     * Get page assessments configuration for the Project and cache in static variable.
35
     * @return string[]|false As defined in config/assessments.yml, or false if none exists.
36
     */
37 4
    public function getConfig()
38
    {
39 4
        if (!isset($this->config)) {
40 4
            return $this->config = $this->getRepository()->getConfig($this->project);
41
        }
42
43 3
        return $this->config;
44
    }
45
46
    /**
47
     * Is the given namespace supported in Page Assessments?
48
     * @param  int $nsId Namespace ID.
49
     * @return bool
50
     */
51 2
    public function isSupportedNamespace($nsId)
52
    {
53 2
        return $this->isEnabled() && in_array($nsId, self::SUPPORTED_NAMESPACES);
54
    }
55
56
    /**
57
     * Does this project support page assessments?
58
     * @return bool
59
     */
60 2
    public function isEnabled()
61
    {
62 2
        return (bool)$this->getConfig();
63
    }
64
65
    /**
66
     * Does this project have importance ratings through Page Assessments?
67
     * @return bool
68
     */
69 1
    public function hasImportanceRatings()
70
    {
71 1
        $config = $this->getConfig();
72 1
        return isset($config['importance']);
73
    }
74
75
    /**
76
     * Get the image URL of the badge for the given page assessment.
77
     * @param string $class Valid classification for project, such as 'Start', 'GA', etc.
78
     * @param bool $filenameOnly Get only the filename, not the URL.
79
     * @return string URL to image.
80
     */
81 2
    public function getBadgeURL($class, $filenameOnly = false)
82
    {
83 2
        $config = $this->getConfig();
84
85 2
        if (isset($config['class'][$class])) {
86 2
            $url = 'https://upload.wikimedia.org/wikipedia/commons/'.$config['class'][$class]['badge'];
87 1
        } elseif (isset($config['class']['Unknown'])) {
88 1
            $url = 'https://upload.wikimedia.org/wikipedia/commons/'.$config['class']['Unknown']['badge'];
89
        } else {
90
            $url = "";
91
        }
92
93 2
        if ($filenameOnly) {
94 1
            $parts = explode('/', $url);
95 1
            return end($parts);
96
        }
97
98 2
        return $url;
99
    }
100
101
    /**
102
     * Get assessments for the given Page.
103
     * @param Page $page
104
     * @return string[]|false `false` if unsupported, or array in the format of:
105
     *         [
106
     *             'assessment' => 'C', // overall assessment
107
     *             'wikiprojects' => [
108
     *                 'Biography' => [
109
     *                     'assessment' => 'C',
110
     *                     'badge' => 'url',
111
     *                 ],
112
     *                 ...
113
     *             ],
114
     *             'wikiproject_prefix' => 'Wikipedia:WikiProject_',
115
     *         ]
116
     */
117 1
    public function getAssessments(Page $page)
118
    {
119 1
        if (!$this->isEnabled() || !$this->isSupportedNamespace($page->getNamespace())) {
120
            return false;
121
        }
122
123 1
        $config = $this->getConfig();
124 1
        $data = $this->getRepository()->getAssessments($page);
125
126
        // Set the default decorations for the overall quality assessment.
127
        // This will be replaced with the first valid class defined for any WikiProject.
128 1
        $overallQuality = $config['class']['Unknown'];
129 1
        $overallQuality['value'] = '???';
130 1
        $overallQuality['badge'] = $this->getBadgeURL($overallQuality['badge']);
131
132 1
        $decoratedAssessments = [];
133
134
        // Go through each raw assessment data from the database, and decorate them
135
        // with the colours and badges as retrieved from the XTools assessments config.
136 1
        foreach ($data as $assessment) {
137 1
            $assessment['class'] = $this->getClassFromAssessment($assessment);
138
139 1
            if ($overallQuality['value'] === '???') {
140 1
                $overallQuality = $assessment['class'];
141
            }
142
143 1
            $assessment['importance'] = $this->getImportanceFromAssessment($assessment);
144
145 1
            $decoratedAssessments[$assessment['wikiproject']] = $assessment;
146
        }
147
148
        // Don't shown 'Unknown' assessment outside of the mainspace.
149 1
        if ($page->getNamespace() !== 0 && $overallQuality['value'] === '???') {
150
            return false;
151
        }
152
153
        return [
154 1
            'assessment' => $overallQuality,
155 1
            'wikiprojects' => $decoratedAssessments,
156 1
            'wikiproject_prefix' => $config['wikiproject_prefix']
157
        ];
158
    }
159
160
    /**
161
     * Get the class attributes for the given class value,
162
     * as fetched from the config.
163
     * @param  string $classValue Such as 'FA', 'GA', 'Start', etc.
164
     * @return string[] Attributes as fetched from the XTools assessments config.
165
     */
166 1
    private function getClassAttrs($classValue)
167
    {
168 1
        return $this->getConfig()['class'][$classValue];
169
    }
170
171
    /**
172
     * Get the properties of the assessment class, including:
173
     *   'value' (class name in plain text),
174
     *   'color' (as hex RGB),
175
     *   'badge' (full URL to assessment badge),
176
     *   'category' (wiki path to related class category).
177
     * @param  array $assessment
178
     * @return array Decorated class assessment.
179
     */
180 1
    private function getClassFromAssessment($assessment)
181
    {
182 1
        $classValue = $assessment['class'];
183
184
        // Use ??? as the presented value when the class is unknown or is not defined in the config
185 1
        if ($classValue === 'Unknown' || $classValue === '' || !isset($this->getConfig()['class'][$classValue])) {
186
            return array_merge($this->getClassAttrs('Unknown'), [
187
                'value' => '???',
188
                'badge' => $this->getBadgeURL('Unknown'),
189
            ]);
190
        }
191
192
        // Known class.
193 1
        $classAttrs = $this->getClassAttrs($classValue);
194
        $class = [
195 1
            'value' => $classValue,
196 1
            'color' => $classAttrs['color'],
197 1
            'category' => $classAttrs['category'],
198
        ];
199
200
        // add full URL to badge icon
201 1
        if ($classAttrs['badge'] !== '') {
202 1
            $class['badge'] = $this->getBadgeURL($classValue);
203
        }
204
205 1
        return $class;
206
    }
207
208
    /**
209
     * Get the properties of the assessment importance, including:
210
     *   'value' (importance in plain text),
211
     *   'color' (as hex RGB),
212
     *   'weight' (integer, 0 is lowest importance),
213
     *   'category' (wiki path to the related importance category).
214
     * @param  array $assessment
215
     * @return array Decorated importance assessment.
216
     */
217 1
    private function getImportanceFromAssessment($assessment)
218
    {
219 1
        $importanceValue = $assessment['importance'];
220
221 1
        if ($importanceValue == '' && !isset($this->getConfig()['importance'])) {
222
            return null;
223
        }
224
225
        // Known importance level.
226 1
        $importanceUnknown = $importanceValue === 'Unknown' || $importanceValue === '';
227
228 1
        if ($importanceUnknown || !isset($this->getConfig()['importance'][$importanceValue])) {
229
            $importanceAttrs = $this->getConfig()['importance']['Unknown'];
230
231
            return array_merge($importanceAttrs, [
232
                'value' => '???',
233
                'category' => $importanceAttrs['category'],
234
            ]);
235
        } else {
236 1
            $importanceAttrs = $this->getConfig()['importance'][$importanceValue];
237
            return [
238 1
                'value' => $importanceValue,
239 1
                'color' => $importanceAttrs['color'],
240 1
                'weight' => $importanceAttrs['weight'], // numerical weight for sorting purposes
241 1
                'category' => $importanceAttrs['category'],
242
            ];
243
        }
244
    }
245
}
246