Completed
Push — master ( 6debb6...9fccc1 )
by
unknown
02:50
created

Repository::getTableName()   D

Complexity

Conditions 9
Paths 12

Size

Total Lines 33
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 4.909
c 0
b 0
f 0
cc 9
eloc 14
nc 12
nop 3
1
<?php
2
/**
3
 * This file contains only the Repository class.
4
 */
5
6
namespace Xtools;
7
8
use Doctrine\DBAL\Connection;
9
use Mediawiki\Api\MediawikiApi;
10
use Psr\Cache\CacheItemPoolInterface;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
use Symfony\Component\DependencyInjection\Container;
14
use Symfony\Component\Stopwatch\Stopwatch;
15
16
/**
17
 * A repository is responsible for retrieving data from wherever it lives (databases, APIs,
18
 * filesystems, etc.)
19
 */
20
abstract class Repository
21
{
22
23
    /** @var Container The application's DI container. */
24
    protected $container;
25
26
    /** @var Connection The database connection to the meta database. */
27
    private $metaConnection;
28
29
    /** @var Connection The database connection to the projects' databases. */
30
    private $projectsConnection;
31
32
    /** @var Connection The database connection to other tools' databases.  */
33
    private $toolsConnection;
34
35
    /** @var CacheItemPoolInterface The cache. */
36
    protected $cache;
37
38
    /** @var LoggerInterface The log. */
39
    protected $log;
40
41
    /** @var Stopwatch The stopwatch for time profiling. */
42
    protected $stopwatch;
43
44
    /**
45
     * Create a new Repository with nothing but a null-logger.
46
     */
47
    public function __construct()
48
    {
49
        $this->log = new NullLogger();
50
    }
51
52
    /**
53
     * Set the DI container.
54
     * @param Container $container
55
     */
56
    public function setContainer(Container $container)
57
    {
58
        $this->container = $container;
59
        $this->cache = $container->get('cache.app');
60
        $this->log = $container->get('logger');
61
        $this->stopwatch = $container->get('debug.stopwatch');
62
    }
63
64
    /**
65
     * Get the database connection for the 'meta' database.
66
     * @return Connection
67
     */
68
    protected function getMetaConnection()
69
    {
70
        if (!$this->metaConnection instanceof Connection) {
71
            $this->metaConnection = $this->container
72
                ->get('doctrine')
73
                ->getManager("meta")
74
                ->getConnection();
75
        }
76
        return $this->metaConnection;
77
    }
78
79
    /**
80
     * Get the database connection for the 'projects' database.
81
     * @return Connection
82
     */
83
    protected function getProjectsConnection()
84
    {
85
        if (!$this->projectsConnection instanceof Connection) {
86
            $this->projectsConnection = $this->container
87
                ->get('doctrine')
88
                ->getManager('replicas')
89
                ->getConnection();
90
        }
91
        return $this->projectsConnection;
92
    }
93
94
    /**
95
     * Get the database connection for the 'tools' database
96
     * (the one that other tools store data in).
97
     * @return Connection
98
     */
99
    protected function getToolsConnection()
100
    {
101
        if (!$this->toolsConnection instanceof Connection) {
102
            $this->toolsConnection = $this->container
103
                ->get('doctrine')
104
                ->getManager("toolsdb")
105
                ->getConnection();
106
        }
107
        return $this->toolsConnection;
108
    }
109
110
    /**
111
     * Get the API object for the given project.
112
     *
113
     * @param Project $project
114
     * @return MediawikiApi
115
     */
116
    public function getMediawikiApi(Project $project)
117
    {
118
        $apiPath = $this->container->getParameter('api_path');
119
        if ($apiPath) {
120
            $api = MediawikiApi::newFromApiEndpoint($project->getUrl().$apiPath);
121
        } else {
122
            $api = MediawikiApi::newFromPage($project->getUrl());
123
        }
124
        return $api;
125
    }
126
127
    /**
128
     * Is XTools connecting to MMF Labs?
129
     * @return boolean
130
     */
131
    public function isLabs()
132
    {
133
        return (bool)$this->container->getParameter('app.is_labs');
134
    }
135
136
    /**
137
     * Normalize and quote a table name for use in SQL.
138
     *
139
     * @param string $databaseName
140
     * @param string $tableName
141
     * @param string|null [$tableExtension] Optional table extension, which will only get used if we're on labs.
142
     * @return string Fully-qualified and quoted table name.
143
     */
144
    public function getTableName($databaseName, $tableName, $tableExtension = null)
145
    {
146
        $mapped = false;
147
148
        // This is a workaround for a one-to-many mapping
149
        // as required by Labs. We combine $tableName with
150
        // $tableExtension in order to generate the new table name
151
        if ($this->isLabs() && $tableExtension !== null) {
152
            $mapped = true;
153
            $tableName = $tableName . '_' . $tableExtension;
154
        } elseif ($this->container->hasParameter("app.table.$tableName")) {
155
            // Use the table specified in the table mapping configuration, if present.
156
            $mapped = true;
157
            $tableName = $this->container->getParameter("app.table.$tableName");
158
        }
159
160
        // For 'revision' and 'logging' tables (actually views) on Labs, use the indexed versions
161
        // (that have some rows hidden, e.g. for revdeleted users).
162
        // This is a safeguard in case table mapping isn't properly set up.
163
        $isLoggingOrRevision = in_array($tableName, ['revision', 'logging', 'archive']);
164
        if (!$mapped && $isLoggingOrRevision && $this->isLabs()) {
165
            $tableName = $tableName."_userindex";
166
        }
167
168
        // Figure out database name.
169
        // Use class variable for the database name if not set via function parameter.
170
        if ($this->isLabs() && substr($databaseName, -2) != '_p') {
171
            // Append '_p' if this is labs.
172
            $databaseName .= '_p';
173
        }
174
175
        return "`$databaseName`.`$tableName`";
176
    }
177
}
178