Skip to content

Commit 3113520

Browse files
committed
add support for multiple databases
1 parent 32c51a7 commit 3113520

File tree

9 files changed

+115
-12
lines changed

9 files changed

+115
-12
lines changed

_test/GeneralTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public function testPluginInfo(): void
3232
$this->assertArrayHasKey('url', $info);
3333

3434
$this->assertEquals('dbquery', $info['base']);
35-
$this->assertRegExp('/^https?:\/\//', $info['url']);
35+
$this->assertMatchesRegularExpression('/^https?:\/\//', $info['url']);
3636
$this->assertTrue(mail_isvalid($info['email']));
37-
$this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
37+
$this->assertMatchesRegularExpression('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
3838
$this->assertTrue(false !== strtotime($info['date']));
3939
}
4040

_test/HelperTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,33 @@ public function testPrepareStatement()
8080
$expected = 'SELECT :user, :mail, :id, :page, :ns WHERE \'foo\' in (:group0,:group1,:group2)';
8181
$this->assertEquals($expected, $actual);
8282
}
83+
84+
public function testGetDsnAliases()
85+
{
86+
$conf = "nouser mysql:host=localhost;port=3306;dbname=testdb1\n\n".
87+
"nopass mysql:host=localhost;port=3306;dbname=testdb2 user\n".
88+
"both mysql:host=localhost;port=3306;dbname=testdb3 user pass\n";
89+
90+
$expect = [
91+
'_' => ['dsn' => 'mysql:host=localhost;port=3306;dbname=testdb1', 'user' => 'dfu', 'pass' => 'dfp'],
92+
'nouser' => ['dsn' => 'mysql:host=localhost;port=3306;dbname=testdb1', 'user' => 'dfu', 'pass' => 'dfp'],
93+
'nopass' => ['dsn' => 'mysql:host=localhost;port=3306;dbname=testdb2', 'user' => 'user', 'pass' => 'dfp'],
94+
'both' => ['dsn' => 'mysql:host=localhost;port=3306;dbname=testdb3', 'user' => 'user', 'pass' => 'pass'],
95+
];
96+
97+
$actual = $this->callInaccessibleMethod($this->hlp, 'getDsnAliases', [$conf, 'dfu', 'dfp']);
98+
$this->assertEquals($expect, $actual);
99+
}
100+
101+
public function testGetDsnAliasesLegacy()
102+
{
103+
$conf = 'mysql:host=localhost;port=3306;dbname=testdb1';
104+
105+
$expect = [
106+
'_' => ['dsn' => 'mysql:host=localhost;port=3306;dbname=testdb1', 'user' => 'dfu', 'pass' => 'dfp'],
107+
];
108+
109+
$actual = $this->callInaccessibleMethod($this->hlp, 'getDsnAliases', [$conf, 'dfu', 'dfp']);
110+
$this->assertEquals($expect, $actual);
111+
}
83112
}

_test/QueryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ public function testUrlParsing($content, $expect)
4040

4141
$this->callInaccessibleMethod($plugin, 'cellFormat', [$content, $R]);
4242

43-
$this->assertRegExp($expect, $R->doc);
43+
$this->assertMatchesRegularExpression($expect, $R->doc);
4444
}
4545
}

conf/metadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
$meta['namespace'] = ['string'];
9-
$meta['dsn'] = ['string'];
9+
$meta['dsn'] = [];
1010
$meta['user'] = ['string'];
1111
$meta['pass'] = ['password'];
1212

helper.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ public function getPDO($dsn = null, $user = null, $pass = null)
6565
* @throws \PDOException
6666
* @throws Exception
6767
*/
68-
public function executeQuery($query)
68+
public function executeQuery($query, $dsnalias = null)
6969
{
7070
if (!preg_match('/^select /i', trim($query))) {
7171
throw new \Exception('For security reasons only SELECT statements are allowed in dbquery');
7272
}
7373

74-
$pdo = $this->getPDO();
74+
[$dsn, $user, $pass] = $this->getDSN($dsnalias);
75+
$pdo = $this->getPDO($dsn, $user, $pass);
7576
$params = $this->gatherVariables();
7677
$sth = $this->prepareStatement($pdo, $query, $params);
7778
$sth->execute();
@@ -138,4 +139,69 @@ public function gatherVariables()
138139
':ns' => ':' . getNS($INFO['id']),
139140
];
140141
}
142+
143+
/**
144+
* Get the DSN, user and pass for a given alias
145+
*
146+
* @param string|null $alias null for default
147+
* @return [string, string, string] DSN, user, pass
148+
* @throws Exception
149+
*/
150+
public function getDSN($alias = null)
151+
{
152+
static $aliases = null;
153+
if ($aliases === null) {
154+
$aliases = $this->getDsnAliases(
155+
$this->getConf('dsn'),
156+
$this->getConf('user'),
157+
$this->getConf('pass')
158+
);
159+
}
160+
161+
if ($aliases === []) throw new \Exception('No DSN aliases defined');
162+
163+
if ($alias === null || !isset($aliases[$alias])) {
164+
$alias = '_';
165+
}
166+
167+
return [$aliases[$alias]['dsn'], $aliases[$alias]['user'], $aliases[$alias]['pass']];
168+
}
169+
170+
/**
171+
* Load and parse the DSN configuration
172+
*
173+
* @param string $config
174+
* @param string $defaultuser
175+
* @param string $defaultpass
176+
* @return array
177+
*/
178+
protected function getDsnAliases($config, $defaultuser, $defaultpass)
179+
{
180+
$aliases = [];
181+
$lines = explode("\n", $config);
182+
foreach ($lines as $line) {
183+
$line = trim($line);
184+
if (!$line) continue;
185+
$parts = preg_split('/\s+/', $line, 4);
186+
187+
if (count($parts) > 1) {
188+
$aliases[$parts[0]] = [
189+
'dsn' => $parts[1],
190+
'user' => $parts[2] ?? $defaultuser,
191+
'pass' => $parts[3] ?? $defaultpass
192+
];
193+
} else {
194+
$parts = ['', $parts[0]];
195+
}
196+
197+
if (!isset($aliases['_'])) {
198+
$aliases['_'] = [
199+
'dsn' => $parts[1],
200+
'user' => $parts[2] ?? $defaultuser,
201+
'pass' => $parts[3] ?? $defaultpass
202+
];
203+
}
204+
}
205+
return $aliases;
206+
}
141207
}

lang/en/settings.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @author Andreas Gohr <[email protected]>
66
*/
77

8-
$meta['namespace'] = 'The namespace in which your queries are created. Be sure to use the proper ACL restrictions to prevent unauthorized user to do arbitrary SQL queries.';
9-
$meta['dsn'] = 'The connection <a href="https://www.php.net/manual/en/pdo.construct.php">DSN string</a> for your database.';
10-
$meta['user'] = 'The user name to connect to your database.';
11-
$meta['pass'] = 'The password to connect to your database';
8+
$lang['namespace'] = 'The namespace in which your queries are created. Be sure to use the proper ACL restrictions to prevent unauthorized user to do arbitrary SQL queries.';
9+
$lang['dsn'] = 'The connection <a href="https://www.php.net/manual/en/pdo.construct.php">DSN strings</a> for your databases.';
10+
$lang['user'] = 'The user name to connect to your database (if not supplied above).';
11+
$lang['pass'] = 'The password to connect to your database (if not supplied above).';

style.less

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
textarea[name="config[plugin____dbquery____dsn]"] {
2+
white-space: nowrap;
3+
}

syntax/macro.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ public function handle($match, $state, $pos, Doku_Handler $handler)
4242
/** @inheritDoc */
4343
public function render($mode, Doku_Renderer $renderer, $data)
4444
{
45-
$renderer->info['dbquery'][$data[0]] = true;
45+
[$name, $value] = sexplode('=', $data[0], 2);
46+
$name = trim($name);
47+
$value = trim($value);
48+
if(!$value) $value = true;
49+
50+
$renderer->info['dbquery'][$name] = $value;
4651
return true;
4752
}
4853
}

syntax/query.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function render($mode, Doku_Renderer $renderer, $data)
4949
$hlp = plugin_load('helper', 'dbquery');
5050
try {
5151
$qdata = $hlp->loadDataFromPage($data['name']);
52-
$result = $hlp->executeQuery($qdata['codeblocks']['_']);
52+
$result = $hlp->executeQuery($qdata['codeblocks']['_'], $qdata['macros']['dsn'] ?? null);
5353
} catch (\Exception $e) {
5454
msg(hsc($e->getMessage()), -1);
5555
return true;

0 commit comments

Comments
 (0)