Merge pull request #16745 from mauriciofauth/flash-messages
Add a flash messages service provider
This commit is contained in:
commit
5af5fb3fae
@ -10,6 +10,7 @@ use PhpMyAdmin\Config\PageSettings;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\Database\CentralColumns;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\FlashMessages;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\Operations;
|
||||
@ -91,6 +92,9 @@ class StructureController extends AbstractController
|
||||
/** @var DatabaseInterface */
|
||||
private $dbi;
|
||||
|
||||
/** @var FlashMessages */
|
||||
private $flash;
|
||||
|
||||
/**
|
||||
* @param Response $response
|
||||
* @param string $db Database name
|
||||
@ -106,7 +110,8 @@ class StructureController extends AbstractController
|
||||
$replication,
|
||||
RelationCleanup $relationCleanup,
|
||||
Operations $operations,
|
||||
$dbi
|
||||
$dbi,
|
||||
FlashMessages $flash
|
||||
) {
|
||||
parent::__construct($response, $template, $db);
|
||||
$this->relation = $relation;
|
||||
@ -114,6 +119,7 @@ class StructureController extends AbstractController
|
||||
$this->relationCleanup = $relationCleanup;
|
||||
$this->operations = $operations;
|
||||
$this->dbi = $dbi;
|
||||
$this->flash = $flash;
|
||||
|
||||
$this->replicationInfo = new ReplicationInfo($this->dbi);
|
||||
}
|
||||
@ -1552,15 +1558,9 @@ class StructureController extends AbstractController
|
||||
$selected = $_POST['selected'] ?? [];
|
||||
|
||||
if ($mult_btn !== __('Yes')) {
|
||||
$message = Message::success(__('No change'));
|
||||
$this->flash->addMessage('success', __('No change'));
|
||||
|
||||
if (empty($_POST['message'])) {
|
||||
$_POST['message'] = Message::success();
|
||||
}
|
||||
|
||||
unset($_POST['mult_btn']);
|
||||
|
||||
$this->index();
|
||||
Core::sendHeaderLocation('./index.php?route=/database/structure' . Url::getCommonRaw(['db' => $db], '&'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
54
libraries/classes/FlashMessages.php
Normal file
54
libraries/classes/FlashMessages.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class FlashMessages
|
||||
{
|
||||
private const STORAGE_KEY = 'flashMessages';
|
||||
|
||||
/** @var array */
|
||||
private $storage;
|
||||
|
||||
/** @var array<string, string[]> */
|
||||
private $previousMessages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (! isset($_SESSION)) {
|
||||
throw new RuntimeException(__('Session not found.'));
|
||||
}
|
||||
|
||||
$this->storage = &$_SESSION;
|
||||
|
||||
if (isset($this->storage[self::STORAGE_KEY])) {
|
||||
$this->previousMessages = $this->storage[self::STORAGE_KEY];
|
||||
}
|
||||
|
||||
$this->storage[self::STORAGE_KEY] = [];
|
||||
}
|
||||
|
||||
public function addMessage(string $key, string $message): void
|
||||
{
|
||||
if (! isset($this->storage[self::STORAGE_KEY][$key])) {
|
||||
$this->storage[self::STORAGE_KEY][$key] = [];
|
||||
}
|
||||
|
||||
$this->storage[self::STORAGE_KEY][$key][] = $message;
|
||||
}
|
||||
|
||||
/** @return string[]|null */
|
||||
public function getMessage(string $key): ?array
|
||||
{
|
||||
return $this->previousMessages[$key] ?? null;
|
||||
}
|
||||
|
||||
/** @return array<string, string[]> */
|
||||
public function getMessages(): array
|
||||
{
|
||||
return $this->previousMessages;
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ namespace PhpMyAdmin;
|
||||
use PhpMyAdmin\Twig\AssetExtension;
|
||||
use PhpMyAdmin\Twig\CoreExtension;
|
||||
use PhpMyAdmin\Twig\Extensions\Node\TransNode;
|
||||
use PhpMyAdmin\Twig\FlashMessagesExtension;
|
||||
use PhpMyAdmin\Twig\I18nExtension;
|
||||
use PhpMyAdmin\Twig\MessageExtension;
|
||||
use PhpMyAdmin\Twig\PluginsExtension;
|
||||
@ -25,6 +26,7 @@ use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Extension\DebugExtension;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\RuntimeLoader\ContainerRuntimeLoader;
|
||||
use Twig\TemplateWrapper;
|
||||
|
||||
use function sprintf;
|
||||
@ -61,7 +63,7 @@ class Template
|
||||
|
||||
public static function getTwigEnvironment(?string $cacheDir): Environment
|
||||
{
|
||||
global $cfg;
|
||||
global $cfg, $containerBuilder;
|
||||
|
||||
/* Twig expects false when cache is not configured */
|
||||
if ($cacheDir === null) {
|
||||
@ -74,6 +76,8 @@ class Template
|
||||
'cache' => $cacheDir,
|
||||
]);
|
||||
|
||||
$twig->addRuntimeLoader(new ContainerRuntimeLoader($containerBuilder));
|
||||
|
||||
if ($cfg['environment'] === 'development') {
|
||||
$twig->enableDebug();
|
||||
$twig->addExtension(new DebugExtension());
|
||||
@ -89,6 +93,7 @@ class Template
|
||||
|
||||
$twig->addExtension(new AssetExtension());
|
||||
$twig->addExtension(new CoreExtension());
|
||||
$twig->addExtension(new FlashMessagesExtension());
|
||||
$twig->addExtension(new I18nExtension());
|
||||
$twig->addExtension(new MessageExtension());
|
||||
$twig->addExtension(new PluginsExtension());
|
||||
|
||||
18
libraries/classes/Twig/FlashMessagesExtension.php
Normal file
18
libraries/classes/Twig/FlashMessagesExtension.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Twig;
|
||||
|
||||
use PhpMyAdmin\FlashMessages;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
final class FlashMessagesExtension extends AbstractExtension
|
||||
{
|
||||
/** @return TwigFunction[] */
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [new TwigFunction('flash', [FlashMessages::class, 'getMessages'])];
|
||||
}
|
||||
}
|
||||
@ -84,6 +84,9 @@ return [
|
||||
'expression_language' => [
|
||||
'class' => Symfony\Component\ExpressionLanguage\ExpressionLanguage::class,
|
||||
],
|
||||
'flash' => [
|
||||
'class' => PhpMyAdmin\FlashMessages::class,
|
||||
],
|
||||
'http_request' => [
|
||||
'class' => PhpMyAdmin\Utils\HttpRequest::class,
|
||||
],
|
||||
@ -214,7 +217,8 @@ return [
|
||||
'user_preferences' => [
|
||||
'class' => PhpMyAdmin\UserPreferences::class,
|
||||
],
|
||||
PhpMyAdmin\Response::class => 'response',
|
||||
PhpMyAdmin\DatabaseInterface::class => 'dbi',
|
||||
PhpMyAdmin\FlashMessages::class => 'flash',
|
||||
PhpMyAdmin\Response::class => 'response',
|
||||
],
|
||||
];
|
||||
|
||||
@ -201,6 +201,7 @@ return [
|
||||
'$relationCleanup' => '@relation_cleanup',
|
||||
'$operations' => '@operations',
|
||||
'$dbi' => '@dbi',
|
||||
'$flash' => '@flash',
|
||||
],
|
||||
],
|
||||
PhpMyAdmin\Controllers\Database\TrackingController::class => [
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
use PhpMyAdmin\Command\CacheWarmupCommand;
|
||||
use PhpMyAdmin\Command\SetVersionCommand;
|
||||
use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Tests\Stubs\DbiDummy;
|
||||
@ -24,6 +25,7 @@ if (! class_exists(Application::class)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$containerBuilder = Core::getContainerBuilder();
|
||||
$cfg['environment'] = 'production';
|
||||
$config = new Config(CONFIG_FILE);
|
||||
$config->set('environment', $cfg['environment']);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<form action="{{ url('/database/structure/empty-table') }}" method="post">
|
||||
<form action="{{ url('/database/structure/empty-table') }}" class="disableAjax" method="post">
|
||||
{{ get_hidden_inputs(url_params) }}
|
||||
|
||||
<fieldset class="pma-fieldset confirmation">
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
{% for flash_key, flash_messages in flash() %}
|
||||
{% for flash_message in flash_messages %}
|
||||
<div class="alert alert-{{ flash_key }}" role="alert">
|
||||
{{ flash_message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% if has_tables %}
|
||||
<div id="tableslistcontainer">
|
||||
{{ list_navigator_html|raw }}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Core;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\MoTranslator\Loader;
|
||||
use PhpMyAdmin\Tests\Stubs\DbiDummy;
|
||||
@ -47,6 +48,8 @@ require_once ROOT_PATH . 'libraries/vendor_config.php';
|
||||
require_once AUTOLOAD_FILE;
|
||||
Loader::loadFunctions();
|
||||
|
||||
$GLOBALS['containerBuilder'] = Core::getContainerBuilder();
|
||||
|
||||
$GLOBALS['config'] = new Config();
|
||||
$GLOBALS['config']->set('environment', 'development');
|
||||
$GLOBALS['cfg']['environment'] = 'development';
|
||||
|
||||
@ -11,6 +11,7 @@ namespace PhpMyAdmin\Tests\Controllers\Database;
|
||||
|
||||
use PhpMyAdmin\Controllers\Database\StructureController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\FlashMessages;
|
||||
use PhpMyAdmin\Operations;
|
||||
use PhpMyAdmin\RecentFavoriteTable;
|
||||
use PhpMyAdmin\Relation;
|
||||
@ -53,6 +54,9 @@ class StructureControllerTest extends AbstractTestCase
|
||||
/** @var Operations */
|
||||
private $operations;
|
||||
|
||||
/** @var FlashMessages */
|
||||
private $flash;
|
||||
|
||||
/**
|
||||
* Prepares environment for the test.
|
||||
*/
|
||||
@ -95,6 +99,7 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication = new Replication();
|
||||
$this->relationCleanup = new RelationCleanup($dbi, $this->relation);
|
||||
$this->operations = new Operations($dbi, $this->relation);
|
||||
$this->flash = new FlashMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +118,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
// Showing statistics
|
||||
$property = $class->getProperty('isShowStats');
|
||||
@ -173,7 +179,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
|
||||
$currentTable['ENGINE'] = 'InnoDB';
|
||||
@ -216,7 +223,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
// Showing statistics
|
||||
$property = $class->getProperty('isShowStats');
|
||||
@ -280,7 +288,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
[$currentTable, , , , , , $sumSize] = $method->invokeArgs(
|
||||
$controller,
|
||||
@ -304,7 +313,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
[$currentTable] = $method->invokeArgs(
|
||||
$controller,
|
||||
@ -338,7 +348,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
|
||||
// When parameter $db is empty
|
||||
@ -376,7 +387,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
|
||||
$_SESSION['tmpval']['favoriteTables'][$GLOBALS['server']] = [
|
||||
@ -414,7 +426,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
|
||||
// The user hash for test
|
||||
@ -474,7 +487,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
// Showing statistics
|
||||
$class = new ReflectionClass(StructureController::class);
|
||||
@ -524,7 +538,8 @@ class StructureControllerTest extends AbstractTestCase
|
||||
$this->replication,
|
||||
$this->relationCleanup,
|
||||
$this->operations,
|
||||
$GLOBALS['dbi']
|
||||
$GLOBALS['dbi'],
|
||||
$this->flash
|
||||
);
|
||||
// Showing statistics
|
||||
$class = new ReflectionClass(StructureController::class);
|
||||
|
||||
63
test/classes/FlashMessagesTest.php
Normal file
63
test/classes/FlashMessagesTest.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests;
|
||||
|
||||
use PhpMyAdmin\FlashMessages;
|
||||
use RuntimeException;
|
||||
|
||||
class FlashMessagesTest extends AbstractTestCase
|
||||
{
|
||||
private const STORAGE_KEY = 'flashMessages';
|
||||
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$this->assertArrayNotHasKey(self::STORAGE_KEY, $_SESSION);
|
||||
$flash = new FlashMessages();
|
||||
$this->assertIsArray($_SESSION[self::STORAGE_KEY]);
|
||||
|
||||
$_SESSION = null;
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Session not found.');
|
||||
$flash = new FlashMessages();
|
||||
}
|
||||
|
||||
public function testAddMessage(): void
|
||||
{
|
||||
$flash = new FlashMessages();
|
||||
$this->assertArrayNotHasKey('error', $_SESSION[self::STORAGE_KEY]);
|
||||
$flash->addMessage('error', 'Error');
|
||||
$this->assertArrayHasKey('error', $_SESSION[self::STORAGE_KEY]);
|
||||
$this->assertIsArray($_SESSION[self::STORAGE_KEY]['error']);
|
||||
$this->assertEquals(['Error'], $_SESSION[self::STORAGE_KEY]['error']);
|
||||
}
|
||||
|
||||
public function testGetMessage(): void
|
||||
{
|
||||
$_SESSION[self::STORAGE_KEY] = ['warning' => ['Warning']];
|
||||
$flash = new FlashMessages();
|
||||
$message = $flash->getMessage('error');
|
||||
$this->assertNull($message);
|
||||
$message = $flash->getMessage('warning');
|
||||
$this->assertEquals(['Warning'], $message);
|
||||
}
|
||||
|
||||
public function testGetMessages(): void
|
||||
{
|
||||
$_SESSION[self::STORAGE_KEY] = [
|
||||
'error' => ['Error1', 'Error2'],
|
||||
'warning' => ['Warning'],
|
||||
];
|
||||
$flash = new FlashMessages();
|
||||
$flash->addMessage('notice', 'Notice');
|
||||
$messages = $flash->getMessages();
|
||||
$this->assertEquals(
|
||||
[
|
||||
'error' => ['Error1', 'Error2'],
|
||||
'warning' => ['Warning'],
|
||||
],
|
||||
$messages
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,8 @@ class TemplateTest extends AbstractTestCase
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
$this->loadContainerBuilder();
|
||||
|
||||
$cfg['environment'] = 'production';
|
||||
$twig = Template::getTwigEnvironment(null);
|
||||
$this->assertFalse($twig->isDebug());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user