Passed
Push — master ( 5f527e...bcf4fb )
by MusikAnimal
04:22
created

Project::getArticlePath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 6
Ratio 100 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 6
loc 6
ccs 5
cts 5
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the Project class.
4
 */
5
6
namespace Xtools;
7
8
use Mediawiki\Api\MediawikiApi;
9
use Symfony\Component\VarDumper\VarDumper;
10
11
/**
12
 * A Project is a single wiki that XTools is querying.
13
 */
14
class Project extends Model
15
{
16
17
    /** @var string The project name as supplied by the user. */
18
    protected $nameUnnormalized;
19
20
    /** @var string[] Basic metadata about the project */
21
    protected $metadata;
22
23
    /** @var string[] Project's 'dbName', 'url' and 'lang'. */
24
    protected $basicInfo;
25
26
    /**
27
     * Whether the user being queried for in this session
28
     *   has opted in to restricted statistics
29
     * @var bool
30
     */
31
    protected $userOptedIn;
32
33
    /**
34
     * Create a new Project.
35
     * @param string $nameOrUrl The project's database name or URL.
36
     */
37 94
    public function __construct($nameOrUrl)
38
    {
39 94
        $this->nameUnnormalized = $nameOrUrl;
40 94
    }
41
42
    /**
43
     * Unique identifier this Project, to be used in cache keys.
44
     * @see Repository::getCacheKey()
45
     * @return string
46
     */
47
    public function getCacheKey()
48
    {
49
        return $this->getDatabaseName();
50
    }
51
52
    /**
53
     * Get 'dbName', 'url' and 'lang' of the project, the relevant basic info
54
     *   we can get from the meta database. This is all you need to make
55
     *   database queries. More comprehensive metadata can be fetched with
56
     *   getMetadata() at the expense of an API call, which may be cached.
57
     * @return string[]
58
     */
59 42
    protected function getBasicInfo()
60
    {
61 42
        if (empty($this->basicInfo)) {
62 42
            $this->basicInfo = $this->getRepository()->getOne($this->nameUnnormalized);
1 ignored issue
show
Bug introduced by
The method getOne() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

62
            $this->basicInfo = $this->getRepository()->/** @scrutinizer ignore-call */ getOne($this->nameUnnormalized);
Loading history...
63
        }
64 41
        return $this->basicInfo;
65
    }
66
67
    /**
68
     * Get full metadata about the project. See ProjectRepository::getMetadata
69
     *   for more information.
70
     * @return string[]
71
     */
72 16
    protected function getMetadata()
73
    {
74 16
        if (empty($this->metadata)) {
75 16
            $url = $this->getBasicInfo()['url'];
76 15
            $this->metadata = $this->getRepository()->getMetadata($url);
1 ignored issue
show
Bug introduced by
The method getMetadata() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

76
            $this->metadata = $this->getRepository()->/** @scrutinizer ignore-call */ getMetadata($url);
Loading history...
77
        }
78 15
        return $this->metadata;
79
    }
80
81
    /**
82
     * Does this project exist?
83
     * @return bool
84
     */
85 10
    public function exists()
86
    {
87 10
        return !empty($this->getDomain());
88
    }
89
90
    /**
91
     * The unique domain name of this project, without protocol or path components.
92
     * This should be used as the canonical project identifier.
93
     *
94
     * @return string
95
     */
96 22
    public function getDomain()
97
    {
98 22
        $url = isset($this->getBasicInfo()['url']) ? $this->getBasicInfo()['url'] : '';
99 22
        return parse_url($url, PHP_URL_HOST);
100
    }
101
102
    /**
103
     * The name of the database for this project.
104
     *
105
     * @return string
106
     */
107 13
    public function getDatabaseName()
108
    {
109 13
        return isset($this->getBasicInfo()['dbName']) ? $this->getBasicInfo()['dbName'] : '';
110
    }
111
112
    /**
113
     * The language for this project.
114
     *
115
     * @return string
116
     */
117 2
    public function getLang()
118
    {
119 2
        return isset($this->getBasicInfo()['lang']) ? $this->getBasicInfo()['lang'] : '';
120
    }
121
122
    /**
123
     * The project URL is the fully-qualified domain name, with protocol and trailing slash.
124
     *
125
     * @param bool $withTrailingSlash Whether to append a slash.
126
     * @return string
127
     */
128 15
    public function getUrl($withTrailingSlash = true)
129
    {
130 15
        return rtrim($this->getBasicInfo()['url'], '/') . ($withTrailingSlash ? '/' : '');
131
    }
132
133
    /**
134
     * Get a MediawikiApi object for this Project.
135
     *
136
     * @return MediawikiApi
137
     */
138
    public function getApi()
139
    {
140
        return $this->getRepository()->getMediawikiApi($this);
141
    }
142
143
    /**
144
     * The base URL path of this project (that page titles are appended to).
145
     * For some wikis the title (apparently) may not be at the end.
146
     * Replace $1 with the article name.
147
     *
148
     * @link https://www.mediawiki.org/wiki/Manual:$wgArticlePath
149
     *
150
     * @return string
151
     */
152 4 View Code Duplication
    public function getArticlePath()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
    {
154 4
        $metadata = $this->getMetadata();
155 4
        return isset($metadata['general']['articlePath'])
156 4
            ? $metadata['general']['articlePath']
157 4
            : '/wiki/$1';
158
    }
159
160
    /**
161
     * The URL path of the directory that contains index.php, with no trailing slash.
162
     * Defaults to '/w' which is the same as the normal WMF set-up.
163
     *
164
     * @link https://www.mediawiki.org/wiki/Manual:$wgScriptPath
165
     *
166
     * @return string
167
     */
168 2 View Code Duplication
    public function getScriptPath()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
    {
170 2
        $metadata = $this->getMetadata();
171 2
        return isset($metadata['general']['scriptPath'])
172 2
            ? $metadata['general']['scriptPath']
173 2
            : '/w';
174
    }
175
176
    /**
177
     * The URL path to index.php
178
     * Defaults to '/w/index.php' which is the same as the normal WMF set-up.
179
     *
180
     * @return string
181
     */
182 1
    public function getScript()
183
    {
184 1
        $metadata = $this->getMetadata();
185 1
        return isset($metadata['general']['script'])
186 1
            ? $metadata['general']['script']
187 1
            : $this->getScriptPath() . '/index.php';
188
    }
189
190
    /**
191
     * The full URL to api.php
192
     *
193
     * @return string
194
     */
195 8
    public function getApiUrl()
196
    {
197 8
        return rtrim($this->getUrl(), '/') . $this->getRepository()->getApiPath();
1 ignored issue
show
Bug introduced by
The method getApiPath() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

197
        return rtrim($this->getUrl(), '/') . $this->getRepository()->/** @scrutinizer ignore-call */ getApiPath();
Loading history...
198
    }
199
200
    /**
201
     * Get this project's title, the human-language full title of the wiki (e.g. "English
202
     * Wikipedia" or
203
     */
204 1
    public function getTitle()
205
    {
206 1
        $metadata = $this->getMetadata();
207
        return $metadata['general']['wikiName'].' ('.$this->getDomain().')';
208
    }
209
210
    /**
211
     * Get an array of this project's namespaces and their IDs.
212
     *
213
     * @return string[] Keys are IDs, values are names.
214
     */
215 9
    public function getNamespaces()
216
    {
217 9
        $metadata = $this->getMetadata();
218 9
        return $metadata['namespaces'];
219
    }
220
221
    /**
222
     * Get the title of the Main Page.
223
     * @return string
224
     */
225 1 View Code Duplication
    public function getMainPage()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
226
    {
227 1
        $metadata = $this->getMetadata();
228 1
        return isset($metadata['general']['mainpage'])
229 1
            ? $metadata['general']['mainpage']
230 1
            : '';
231
    }
232
233
    /**
234
     * Get a list of users who are in one of the given user groups.
235
     * @param string[] User groups to search for.
236
     * @return string[] User groups keyed by user name.
237
     */
238 1
    public function getUsersInGroups($groups)
239
    {
240 1
        $users = [];
241 1
        $usersAndGroups = $this->getRepository()->getUsersInGroups($this, $groups);
1 ignored issue
show
Bug introduced by
The method getUsersInGroups() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

241
        $usersAndGroups = $this->getRepository()->/** @scrutinizer ignore-call */ getUsersInGroups($this, $groups);
Loading history...
242 1
        foreach ($usersAndGroups as $userAndGroup) {
243 1
            $username = $userAndGroup['user_name'];
244 1
            if (isset($users[$username])) {
245 1
                array_push($users[$username], $userAndGroup['ug_group']);
246
            } else {
247 1
                $users[$username] = [$userAndGroup['ug_group']];
248
            }
249
        }
250 1
        return $users;
251
    }
252
253
    /**
254
     * Get the name of the page on this project that the user must create in order to opt in for
255
     * restricted statistics display.
256
     * @param User $user
257
     * @return string
258
     */
259 2
    public function userOptInPage(User $user)
260
    {
261 2
        $localPageName = 'User:' . $user->getUsername() . '/EditCounterOptIn.js';
262 2
        return $localPageName;
263
    }
264
265
    /**
266
     * Has a user opted in to having their restricted statistics displayed to anyone?
267
     * @param User $user
268
     * @return bool
269
     */
270 3
    public function userHasOptedIn(User $user)
271
    {
272
        // 1. First check to see if the whole project has opted in.
273 3
        if (!$this->userOptedIn) {
274 3
            $optedInProjects = $this->getRepository()->optedIn();
1 ignored issue
show
Bug introduced by
The method optedIn() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

274
            $optedInProjects = $this->getRepository()->/** @scrutinizer ignore-call */ optedIn();
Loading history...
275 3
            $this->userOptedIn = in_array($this->getDatabaseName(), $optedInProjects);
276
        }
277 3
        if ($this->userOptedIn) {
278 1
            return true;
279
        }
280
281
        // 2. Then see if the currently-logged-in user is requesting their own statistics.
282 2
        if ($user->isCurrentlyLoggedIn()) {
283
            return true;
284
        }
285
286
        // 3. Then see if the user has opted in on this project.
287 2
        $userNsId = 2;
288
        // Remove namespace since we're querying the database and supplying a namespace ID.
289 2
        $optInPage = preg_replace('/^User:/', '', $this->userOptInPage($user));
290 2
        $localExists = $this->getRepository()->pageHasContent($this, $userNsId, $optInPage);
1 ignored issue
show
Bug introduced by
The method pageHasContent() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

290
        $localExists = $this->getRepository()->/** @scrutinizer ignore-call */ pageHasContent($this, $userNsId, $optInPage);
Loading history...
291 2
        if ($localExists) {
292
            return true;
293
        }
294
295
        // 4. Lastly, see if they've opted in globally on the default project or Meta.
296 2
        $globalPageName = $user->getUsername() . '/EditCounterGlobalOptIn.js';
297 2
        $globalProject = $this->getRepository()->getGlobalProject();
1 ignored issue
show
Bug introduced by
The method getGlobalProject() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

297
        $globalProject = $this->getRepository()->/** @scrutinizer ignore-call */ getGlobalProject();
Loading history...
298 2
        if ($globalProject instanceof Project) {
299
            $globalExists = $globalProject->getRepository()
300
                ->pageHasContent($globalProject, $userNsId, $globalPageName);
301
            if ($globalExists) {
302
                return true;
303
            }
304
        }
305
306 2
        return false;
307
    }
308
309
    /**
310
     * Does this project support page assessments?
311
     * @return bool
312
     */
313 3
    public function hasPageAssessments()
314
    {
315 3
        return (bool) $this->getRepository()->getAssessmentsConfig($this->getDomain());
1 ignored issue
show
Bug introduced by
The method getAssessmentsConfig() does not exist on Xtools\Repository. It seems like you code against a sub-type of Xtools\Repository such as Xtools\ProjectRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

315
        return (bool) $this->getRepository()->/** @scrutinizer ignore-call */ getAssessmentsConfig($this->getDomain());
Loading history...
316
    }
317
318
    /**
319
     * Get the image URL of the badge for the given page assessment
320
     * @param  string $class  Valid classification for project, such as 'Start', 'GA', etc.
321
     * @return string         URL to image
322
     */
323 3
    public function getAssessmentBadgeURL($class)
324
    {
325 3
        $config = $this->getRepository()->getAssessmentsConfig($this->getDomain());
326
327 3
        if (isset($config['class'][$class])) {
328 2
            return "https://upload.wikimedia.org/wikipedia/commons/" . $config['class'][$class]['badge'];
329 3
        } elseif (isset($config['class']['Unknown'])) {
330 2
            return "https://upload.wikimedia.org/wikipedia/commons/" . $config['class']['Unknown']['badge'];
331
        } else {
332 1
            return "";
333
        }
334
    }
335
336
    /**
337
     * Normalize and quote a table name for use in SQL.
338
     * @param string $tableName
339
     * @param string|null $tableExtension Optional table extension, which will only get used if we're on Labs.
340
     * @return string Fully-qualified and quoted table name.
341
     */
342 1
    public function getTableName($tableName, $tableExtension = null)
343
    {
344 1
        return $this->getRepository()->getTableName($this->getDatabaseName(), $tableName, $tableExtension);
345
    }
346
}
347