1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Xtools; |
4
|
|
|
|
5
|
|
|
use Mediawiki\Api\MediawikiApi; |
6
|
|
|
use Mediawiki\Api\SimpleRequest; |
7
|
|
|
|
8
|
|
|
class ProjectRepository extends Repository |
9
|
|
|
{ |
10
|
|
|
|
11
|
|
|
/** @var array Project metadata. */ |
12
|
|
|
protected $metadata; |
13
|
|
|
|
14
|
|
|
/** @var string[] */ |
15
|
|
|
protected $singleMetadata; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* For single-wiki installations, you must manually set the wiki URL and database name |
19
|
|
|
* (because there's no meta.wiki database to query). |
20
|
|
|
* @param $metadata |
21
|
|
|
* @throws \Exception |
22
|
|
|
*/ |
23
|
|
|
public function setSingleMetadata($metadata) |
24
|
|
|
{ |
25
|
|
|
if (!array_key_exists('url', $metadata) || !array_key_exists('dbname', $metadata)) { |
26
|
|
|
$error = "Single-wiki metadata should contain 'url' and 'dbname' keys."; |
27
|
|
|
throw new \Exception($error); |
28
|
|
|
} |
29
|
|
|
$this->singleMetadata = array_intersect_key($metadata, ['url' => '', 'dbname' => '']); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Get metadata about all projects. |
34
|
|
|
* @return string[] Each item has 'dbname' and 'url' keys. |
35
|
|
|
*/ |
36
|
|
|
public function getAll() |
37
|
|
|
{ |
38
|
|
|
if ($this->singleMetadata) { |
|
|
|
|
39
|
|
|
return [$this->getOne('')]; |
|
|
|
|
40
|
|
|
} |
41
|
|
|
$wikiQuery = $this->metaConnection->createQueryBuilder(); |
42
|
|
|
$wikiQuery->select(['dbname', 'url'])->from('wiki'); |
43
|
|
|
return $wikiQuery->execute()->fetchAll(); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Get metadata about one project. |
48
|
|
|
* @param string $project A project URL, domain name, or database name. |
49
|
|
|
* @return string[] With 'dbname' and 'url' keys. |
50
|
|
|
*/ |
51
|
|
|
public function getOne($project) |
52
|
|
|
{ |
53
|
|
|
// For single-wiki setups, every project is the same. |
54
|
|
|
if ($this->singleMetadata) { |
|
|
|
|
55
|
|
|
return $this->singleMetadata; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
// Otherwise, fetch the project's metadata from the meta.wiki table. |
59
|
|
|
$wikiQuery = $this->metaConnection->createQueryBuilder(); |
60
|
|
|
$wikiQuery->select(['dbname', 'url']) |
61
|
|
|
->from('wiki') |
62
|
|
|
->where($wikiQuery->expr()->eq('dbname', ':project')) |
63
|
|
|
// The meta database will have the project's URL stored as https://en.wikipedia.org |
64
|
|
|
// so we need to query for it accordingly, trying different variations the user |
65
|
|
|
// might have inputted. |
66
|
|
|
->orwhere($wikiQuery->expr()->like('url', ':projectUrl')) |
67
|
|
|
->orwhere($wikiQuery->expr() |
68
|
|
|
->like('url', ':projectUrl2')) |
69
|
|
|
->setParameter('project', $project) |
70
|
|
|
->setParameter('projectUrl', "https://$project") |
71
|
|
|
->setParameter('projectUrl2', "https://$project.org"); |
72
|
|
|
$wikiStatement = $wikiQuery->execute(); |
73
|
|
|
|
74
|
|
|
// Fetch the wiki data. |
75
|
|
|
return $wikiStatement->fetch(); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Get metadata about a project. |
80
|
|
|
* |
81
|
|
|
* @param string $projectUrl The project's URL. |
82
|
|
|
* @return array With 'general' and 'namespaces' keys: the former contains 'wikiName', |
83
|
|
|
* 'wikiId', 'url', 'lang', 'articlePath', 'scriptPath', 'script', 'timezone', and |
84
|
|
|
* 'timezoneOffset'; the latter contains all namespace names, keyed by their IDs. |
85
|
|
|
*/ |
86
|
|
|
public function getMetadata($projectUrl) |
87
|
|
|
{ |
88
|
|
|
if ($this->metadata) { |
|
|
|
|
89
|
|
|
return $this->metadata; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
$api = MediawikiApi::newFromPage($projectUrl); |
93
|
|
|
|
94
|
|
|
$params = ['meta' => 'siteinfo', 'siprop' => 'general|namespaces']; |
95
|
|
|
$query = new SimpleRequest('query', $params); |
96
|
|
|
|
97
|
|
|
$this->metadata = [ |
98
|
|
|
'general' => [], |
99
|
|
|
'namespaces' => [], |
100
|
|
|
]; |
101
|
|
|
|
102
|
|
|
$res = $api->getRequest($query); |
103
|
|
|
|
104
|
|
|
if (isset($res['query']['general'])) { |
105
|
|
|
$info = $res['query']['general']; |
106
|
|
|
$this->metadata['general'] = [ |
107
|
|
|
'wikiName' => $info['sitename'], |
108
|
|
|
'wikiId' => $info['wikiid'], |
109
|
|
|
'url' => $info['server'], |
110
|
|
|
'lang' => $info['lang'], |
111
|
|
|
'articlePath' => $info['articlepath'], |
112
|
|
|
'scriptPath' => $info['scriptpath'], |
113
|
|
|
'script' => $info['script'], |
114
|
|
|
'timezone' => $info['timezone'], |
115
|
|
|
'timeOffset' => $info['timeoffset'], |
116
|
|
|
]; |
117
|
|
|
|
118
|
|
|
// if ($this->container->getParameter('app.is_labs') && |
|
|
|
|
119
|
|
|
// substr($result['general']['dbName'], -2) != '_p' |
120
|
|
|
// ) { |
121
|
|
|
// $result['general']['dbName'] .= '_p'; |
122
|
|
|
// } |
123
|
|
|
} |
124
|
|
|
|
125
|
|
View Code Duplication |
if (isset($res['query']['namespaces'])) { |
|
|
|
|
126
|
|
|
foreach ($res['query']['namespaces'] as $namespace) { |
127
|
|
|
if ($namespace['id'] < 0) { |
128
|
|
|
continue; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
if (isset($namespace['name'])) { |
132
|
|
|
$name = $namespace['name']; |
133
|
|
|
} elseif (isset($namespace['*'])) { |
134
|
|
|
$name = $namespace['*']; |
135
|
|
|
} else { |
136
|
|
|
continue; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
// FIXME: Figure out a way to i18n-ize this |
140
|
|
|
if ($name === '') { |
141
|
|
|
$name = 'Article'; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$this->metadata['namespaces'][$namespace['id']] = $name; |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
return $this->metadata; |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.