Merge #16472 - #16418 - make MariaDBMySQLKBS optional

Issue: #16418
Pull-request: #16472
Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
William Desportes 2020-11-10 22:42:21 +01:00
commit 69c9a96fd4
No known key found for this signature in database
GPG Key ID: 90A0EF1B8251A889
7 changed files with 243 additions and 54 deletions

View File

@ -7,12 +7,11 @@ namespace PhpMyAdmin\Controllers\Server;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Providers\ServerVariables\ServerVariablesProvider;
use PhpMyAdmin\Response;
use PhpMyAdmin\Template;
use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
use Williamdes\MariaDBMySQLKBS\KBException;
use Williamdes\MariaDBMySQLKBS\Search as KBSearch;
use function header;
use function htmlspecialchars;
use function implode;
@ -70,7 +69,7 @@ class VariablesController extends AbstractController
$serverVars = $this->dbi->fetchResult('SHOW GLOBAL VARIABLES;', 0, 1);
// list of static (i.e. non-editable) system variables
$staticVariables = KBSearch::getStaticVariables();
$staticVariables = ServerVariablesProvider::getImplementation()->getStaticVariables();
foreach ($serverVars as $name => $value) {
$hasSessionValue = isset($serverVarsSession[$name])
@ -130,19 +129,17 @@ class VariablesController extends AbstractController
'NUM'
);
$json = [];
try {
$type = KBSearch::getVariableType($params['name']);
if ($type !== 'byte') {
throw new KBException('Not a type=byte');
}
$json = [
'message' => $varValue[1],
];
$variableType = ServerVariablesProvider::getImplementation()->getVariableType($params['name']);
if ($variableType === 'byte') {
$json['message'] = implode(
' ',
Util::formatByteDown($varValue[1], 3, 3)
);
} catch (KBException $e) {
$json['message'] = $varValue[1];
}
$this->response->addJSON($json);
@ -164,18 +161,16 @@ class VariablesController extends AbstractController
return;
}
$value = $params['varValue'];
$value = (string) $params['varValue'];
$variableName = (string) $params['varName'];
$matches = [];
try {
$type = KBSearch::getVariableType($params['varName']);
if ($type !== 'byte' || ! preg_match(
'/^\s*(\d+(\.\d+)?)\s*(mb|kb|mib|kib|gb|gib)\s*$/i',
$value,
$matches
)) {
throw new KBException('Not a type=byte or regex not matching');
}
$variableType = ServerVariablesProvider::getImplementation()->getVariableType($variableName);
if ($variableType === 'byte' && preg_match(
'/^\s*(\d+(\.\d+)?)\s*(mb|kb|mib|kib|gb|gib)\s*$/i',
$value,
$matches
)) {
$exp = [
'kb' => 1,
'kib' => 1,
@ -188,7 +183,7 @@ class VariablesController extends AbstractController
1024,
$exp[mb_strtolower($matches[3])]
);
} catch (KBException $e) {
} else {
$value = $this->dbi->escapeString($value);
}
@ -241,12 +236,9 @@ class VariablesController extends AbstractController
$formattedValue = $value;
if (is_numeric($value)) {
try {
$type = KBSearch::getVariableType($name);
if ($type !== 'byte') {
throw new KBException('Not a type=byte or regex not matching');
}
$variableType = ServerVariablesProvider::getImplementation()->getVariableType($name);
if ($variableType === 'byte') {
$isHtmlFormatted = true;
$formattedValue = trim(
$this->template->render(
@ -257,7 +249,7 @@ class VariablesController extends AbstractController
]
)
);
} catch (KBException $e) {
} else {
$formattedValue = Util::formatNumber($value, 0);
}
}

View File

@ -10,6 +10,7 @@ namespace PhpMyAdmin\Html;
use PhpMyAdmin\Core;
use PhpMyAdmin\Message;
use PhpMyAdmin\Profiling;
use PhpMyAdmin\Providers\ServerVariables\ServerVariablesProvider;
use PhpMyAdmin\Response;
use PhpMyAdmin\Sanitize;
use PhpMyAdmin\SqlParser\Lexer;
@ -22,8 +23,6 @@ use Throwable;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Williamdes\MariaDBMySQLKBS\KBException;
use Williamdes\MariaDBMySQLKBS\Search as KBSearch;
use const ENT_COMPAT;
use function addslashes;
use function array_key_exists;
@ -87,24 +86,16 @@ class Generator
bool $useMariaDB = false,
?string $text = null
): string {
$html = '';
try {
$type = KBSearch::MYSQL;
if ($useMariaDB) {
$type = KBSearch::MARIADB;
}
$docLink = KBSearch::getByName($name, $type);
$html = MySQLDocumentation::show(
$name,
false,
$docLink,
$text
);
} catch (KBException $e) {
unset($e);// phpstan workaround
}
$kbs = ServerVariablesProvider::getImplementation();
$link = $useMariaDB ? $kbs->getDocLinkByNameMariaDb($name) :
$kbs->getDocLinkByNameMysql($name);
return $html;
return MySQLDocumentation::show(
$name,
false,
$link,
$text
);
}
/**

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Providers\ServerVariables;
use Williamdes\MariaDBMySQLKBS\KBException;
use Williamdes\MariaDBMySQLKBS\Search as KBSearch;
class MariaDbMySqlKbsProvider implements ServerVariablesProviderInterface
{
public function getVariableType(string $name): ?string
{
try {
return KBSearch::getVariableType($name);
} catch (KBException $e) {
return null;
}
}
public function getStaticVariables(): array
{
return [];
}
public function getDocLinkByNameMariaDb(string $name): ?string
{
try {
return KBSearch::getByName($name, KBSearch::MARIADB);
} catch (KBException $e) {
return null;
}
}
public function getDocLinkByNameMysql(string $name): ?string
{
try {
return KBSearch::getByName($name, KBSearch::MYSQL);
} catch (KBException $e) {
return null;
}
}
}

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Providers\ServerVariables;
use Williamdes\MariaDBMySQLKBS\Search;
use function class_exists;
class ServerVariablesProvider
{
/** @var ServerVariablesProviderInterface|null */
private static $instance = null;
public static function getImplementation(): ServerVariablesProviderInterface
{
if (self::$instance !== null) {
return self::$instance;
}
if (self::mariaDbMySqlKbsExists()) {
self::$instance = new MariaDbMySqlKbsProvider();
return self::$instance;
}
self::$instance = new VoidProvider();
return self::$instance;
}
public static function mariaDbMySqlKbsExists(): bool
{
return class_exists(Search::class);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Providers\ServerVariables;
interface ServerVariablesProviderInterface
{
public function getVariableType(string $name): ?string;
public function getStaticVariables(): array;
public function getDocLinkByNameMariaDb(string $name): ?string;
public function getDocLinkByNameMysql(string $name): ?string;
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Providers\ServerVariables;
class VoidProvider implements ServerVariablesProviderInterface
{
public function getVariableType(string $name): ?string
{
return null;
}
public function getStaticVariables(): array
{
return [];
}
public function getDocLinkByNameMariaDb(string $name): ?string
{
return null;
}
public function getDocLinkByNameMysql(string $name): ?string
{
return null;
}
}

View File

@ -7,12 +7,13 @@ namespace PhpMyAdmin\Tests\Controllers\Server;
use PhpMyAdmin\Controllers\Server\VariablesController;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Providers\ServerVariables\ServerVariablesProvider;
use PhpMyAdmin\Providers\ServerVariables\VoidProvider as ServerVariablesVoidProvider;
use PhpMyAdmin\Response;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Stubs\Response as ResponseStub;
use Williamdes\MariaDBMySQLKBS\Search as KBSearch;
use Williamdes\MariaDBMySQLKBS\SlimData as KBSlimData;
use ReflectionProperty;
use function htmlspecialchars;
use function str_replace;
@ -135,22 +136,104 @@ class VariablesControllerTest extends AbstractTestCase
$nameForValueByte = 'byte_variable';
$nameForValueNotByte = 'not_a_byte_variable';
$slimData = new KBSlimData();
$slimData->addVariable($nameForValueByte, 'byte', null);
$slimData->addVariable($nameForValueNotByte, 'string', null);
KBSearch::loadTestData($slimData);
//name is_numeric and the value type is byte
$args = [
$nameForValueByte,
'3',
];
$voidProviderMock = $this->getMockBuilder(ServerVariablesVoidProvider::class)->getMock();
$voidProviderMock
->expects($this->exactly(2))
->method('getVariableType')
->willReturnOnConsecutiveCalls(
'byte',
'string'
);
$response = new ReflectionProperty(ServerVariablesProvider::class, 'instance');
$response->setAccessible(true);
$response->setValue($voidProviderMock);
[$formattedValue, $isHtmlFormatted] = $this->callFunction(
$controller,
VariablesController::class,
'formatVariable',
$args
);
$this->assertEquals(
'<abbr title="3">3 B</abbr>',
$formattedValue
);
$this->assertTrue($isHtmlFormatted);
//name is_numeric and the value type is not byte
$args = [
$nameForValueNotByte,
'3',
];
[$formattedValue, $isHtmlFormatted] = $this->callFunction(
$controller,
VariablesController::class,
'formatVariable',
$args
);
$this->assertEquals(
'3',
$formattedValue
);
$this->assertFalse($isHtmlFormatted);
//value is not a number
$args = [
$nameForValueNotByte,
'value',
];
[$formattedValue, $isHtmlFormatted] = $this->callFunction(
$controller,
VariablesController::class,
'formatVariable',
$args
);
$this->assertEquals(
'value',
$formattedValue
);
$this->assertFalse($isHtmlFormatted);
}
/**
* Test for formatVariable()
*/
public function testFormatVariableMariaDbMySqlKbs(): void
{
if (! ServerVariablesProvider::mariaDbMySqlKbsExists()) {
$this->markTestSkipped('MariaDbMySqlKbs is missing');
}
$response = new ReflectionProperty(ServerVariablesProvider::class, 'instance');
$response->setAccessible(true);
$response->setValue(null);
$controller = new VariablesController(Response::getInstance(), new Template(), $GLOBALS['dbi']);
$nameForValueByte = 'wsrep_replicated_bytes';
$nameForValueNotByte = 'wsrep_thread_count';
//name is_numeric and the value type is byte
$args = [
$nameForValueByte,
'3',
];
[$formattedValue, $isHtmlFormatted] = $this->callFunction(
$controller,
VariablesController::class,
'formatVariable',
$args
);
$this->assertEquals(
'<abbr title="3">3 B</abbr>',
$formattedValue