|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Xtools; |
|
4
|
|
|
|
|
5
|
|
|
use Doctrine\DBAL\Connection; |
|
6
|
|
|
use Mediawiki\Api\MediawikiApi; |
|
7
|
|
|
use Psr\Cache\CacheItemPoolInterface; |
|
8
|
|
|
use Psr\Log\LoggerInterface; |
|
9
|
|
|
use Symfony\Component\DependencyInjection\Container; |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* A repository is responsible for retrieving data from wherever it lives (databases, APIs, |
|
13
|
|
|
* filesystems, etc.) |
|
14
|
|
|
*/ |
|
15
|
|
|
abstract class Repository |
|
16
|
|
|
{ |
|
17
|
|
|
|
|
18
|
|
|
/** @var Container */ |
|
19
|
|
|
protected $container; |
|
20
|
|
|
|
|
21
|
|
|
/** @var Connection */ |
|
22
|
|
|
private $metaConnection; |
|
23
|
|
|
|
|
24
|
|
|
/** @var Connection */ |
|
25
|
|
|
private $projectsConnection; |
|
26
|
|
|
|
|
27
|
|
|
/** @var Connection */ |
|
28
|
|
|
private $toolsConnection; |
|
29
|
|
|
|
|
30
|
|
|
/** @var CacheItemPoolInterface */ |
|
31
|
|
|
protected $cache; |
|
32
|
|
|
|
|
33
|
|
|
/** @var LoggerInterface */ |
|
34
|
|
|
protected $log; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @param Container $container |
|
38
|
|
|
*/ |
|
39
|
|
|
public function setContainer(Container $container) |
|
40
|
|
|
{ |
|
41
|
|
|
$this->container = $container; |
|
42
|
|
|
$this->cache = $container->get('cache.app'); |
|
43
|
|
|
$this->log = $container->get('logger'); |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* Get the database connection for the 'meta' database. |
|
48
|
|
|
* @return Connection |
|
49
|
|
|
*/ |
|
50
|
|
|
protected function getMetaConnection() |
|
51
|
|
|
{ |
|
52
|
|
|
if (!$this->metaConnection instanceof Connection) { |
|
53
|
|
|
$this->metaConnection = $this->container |
|
54
|
|
|
->get('doctrine') |
|
55
|
|
|
->getManager("meta") |
|
56
|
|
|
->getConnection(); |
|
57
|
|
|
} |
|
58
|
|
|
return $this->metaConnection; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* Get the database connection for the 'projects' database. |
|
63
|
|
|
* @return Connection |
|
64
|
|
|
*/ |
|
65
|
|
|
protected function getProjectsConnection() |
|
66
|
|
|
{ |
|
67
|
|
|
if (!$this->projectsConnection instanceof Connection) { |
|
68
|
|
|
$this->projectsConnection = $this->container |
|
69
|
|
|
->get('doctrine') |
|
70
|
|
|
->getManager("replicas") |
|
71
|
|
|
->getConnection(); |
|
72
|
|
|
} |
|
73
|
|
|
return $this->projectsConnection; |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* Get the database connection for the 'tools' database |
|
78
|
|
|
* (the one that other tools store data in). |
|
79
|
|
|
* @return Connection |
|
80
|
|
|
*/ |
|
81
|
|
|
protected function getToolsConnection() |
|
82
|
|
|
{ |
|
83
|
|
|
if (!$this->toolsConnection instanceof Connection) { |
|
84
|
|
|
$this->toolsConnection = $this->container |
|
85
|
|
|
->get('doctrine') |
|
86
|
|
|
->getManager("toolsdb") |
|
87
|
|
|
->getConnection(); |
|
88
|
|
|
} |
|
89
|
|
|
return $this->toolsConnection; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* Get the API object for the given project. |
|
94
|
|
|
* @param Project $project |
|
95
|
|
|
* @return MediawikiApi |
|
96
|
|
|
*/ |
|
97
|
|
|
protected function getMediawikiApi(Project $project) |
|
98
|
|
|
{ |
|
99
|
|
|
// @TODO use newFromApiEndpoint instead. |
|
100
|
|
|
$api = MediawikiApi::newFromPage($project->getUrl()); |
|
101
|
|
|
return $api; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* Is XTools connecting to MMF Labs? |
|
106
|
|
|
* @return boolean |
|
107
|
|
|
*/ |
|
108
|
|
|
public function isLabs() |
|
109
|
|
|
{ |
|
110
|
|
|
return (bool)$this->container->getParameter('app.is_labs'); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Normalize and quote a table name for use in SQL. |
|
115
|
|
|
* |
|
116
|
|
|
* @param string $databaseName |
|
117
|
|
|
* @param string $tableName |
|
118
|
|
|
* @return string Fully-qualified and quoted table name. |
|
119
|
|
|
*/ |
|
120
|
|
|
public function getTableName($databaseName, $tableName) |
|
121
|
|
|
{ |
|
122
|
|
|
// Use the table specified in the table mapping configuration, if present. |
|
123
|
|
|
$mapped = false; |
|
124
|
|
View Code Duplication |
if ($this->container->hasParameter("app.table.$tableName")) { |
|
|
|
|
|
|
125
|
|
|
$mapped = true; |
|
126
|
|
|
$tableName = $this->container->getParameter("app.table.$tableName"); |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
// For 'revision' and 'logging' tables (actually views) on Labs, use the indexed versions |
|
130
|
|
|
// (that have some rows hidden, e.g. for revdeleted users). |
|
131
|
|
|
$isLoggingOrRevision = in_array($tableName, ['revision', 'logging', 'archive']); |
|
132
|
|
|
if (!$mapped && $isLoggingOrRevision && $this->isLabs()) { |
|
133
|
|
|
$tableName = $tableName."_userindex"; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
// Figure out database name. |
|
137
|
|
|
// Use class variable for the database name if not set via function parameter. |
|
138
|
|
|
if ($this->isLabs() && substr($databaseName, -2) != '_p') { |
|
139
|
|
|
// Append '_p' if this is labs. |
|
140
|
|
|
$databaseName .= '_p'; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
return "`$databaseName`.`$tableName`"; |
|
144
|
|
|
} |
|
145
|
|
|
} |
|
146
|
|
|
|
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.