Merge pull request #18456 from MauricioFauth/triggers
Refactor the Triggers page
This commit is contained in:
commit
210521bae8
2
.github/workflows/test-selenium.yml
vendored
2
.github/workflows/test-selenium.yml
vendored
@ -66,7 +66,6 @@ jobs:
|
||||
- "Database/Operations"
|
||||
- "Database/Procedures"
|
||||
- "Database/Structure"
|
||||
- "Database/Triggers"
|
||||
- "Export"
|
||||
- "Import"
|
||||
- "Login"
|
||||
@ -79,6 +78,7 @@ jobs:
|
||||
- "Table/Operations"
|
||||
- "Table/Structure"
|
||||
- "Tracking"
|
||||
- "Triggers"
|
||||
- "Xss"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import $ from 'jquery';
|
||||
import { AJAX } from '../modules/ajax.ts';
|
||||
import { Functions } from '../modules/functions.ts';
|
||||
import { Navigation } from '../modules/navigation.ts';
|
||||
import { ajaxRemoveMessage, ajaxShowMessage } from '../modules/ajax-message.ts';
|
||||
import getJsConfirmCommonParam from '../modules/functions/getJsConfirmCommonParam.ts';
|
||||
import { AJAX } from './modules/ajax.ts';
|
||||
import { Functions } from './modules/functions.ts';
|
||||
import { Navigation } from './modules/navigation.ts';
|
||||
import { ajaxRemoveMessage, ajaxShowMessage } from './modules/ajax-message.ts';
|
||||
import getJsConfirmCommonParam from './modules/functions/getJsConfirmCommonParam.ts';
|
||||
|
||||
AJAX.registerTeardown('database/triggers.js', function () {
|
||||
AJAX.registerTeardown('triggers.js', function () {
|
||||
$(document).off('click', 'a.ajax.add_anchor, a.ajax.edit_anchor');
|
||||
$(document).off('click', 'a.ajax.export_anchor');
|
||||
$(document).off('click', '#bulkActionExportButton');
|
||||
@ -559,7 +559,7 @@ const DatabaseTriggers = {
|
||||
}
|
||||
};
|
||||
|
||||
AJAX.registerOnload('database/triggers.js', function () {
|
||||
AJAX.registerOnload('triggers.js', function () {
|
||||
/**
|
||||
* Attach Ajax event handlers for the Add/Edit functionality.
|
||||
*/
|
||||
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Controllers\Table;
|
||||
|
||||
use PhpMyAdmin\Controllers\AbstractController;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\DbTableExists;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function in_array;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Triggers management.
|
||||
*/
|
||||
class TriggersController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
ResponseRenderer $response,
|
||||
Template $template,
|
||||
private DatabaseInterface $dbi,
|
||||
private Triggers $triggers,
|
||||
) {
|
||||
parent::__construct($response, $template);
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequest $request): void
|
||||
{
|
||||
$GLOBALS['errors'] ??= null;
|
||||
$GLOBALS['urlParams'] ??= null;
|
||||
$GLOBALS['errorUrl'] ??= null;
|
||||
|
||||
$this->addScriptFiles(['database/triggers.js']);
|
||||
|
||||
if (! $this->response->isAjax()) {
|
||||
/**
|
||||
* Displays the header and tabs
|
||||
*/
|
||||
if (! empty($GLOBALS['table']) && in_array($GLOBALS['table'], $this->dbi->getTables($GLOBALS['db']))) {
|
||||
$this->checkParameters(['db', 'table']);
|
||||
|
||||
$GLOBALS['urlParams'] = ['db' => $GLOBALS['db'], 'table' => $GLOBALS['table']];
|
||||
$GLOBALS['errorUrl'] = Util::getScriptNameForOption($GLOBALS['cfg']['DefaultTabTable'], 'table');
|
||||
$GLOBALS['errorUrl'] .= Url::getCommon($GLOBALS['urlParams'], '&');
|
||||
|
||||
DbTableExists::check($GLOBALS['db'], $GLOBALS['table']);
|
||||
} else {
|
||||
$GLOBALS['table'] = '';
|
||||
|
||||
$this->checkParameters(['db']);
|
||||
|
||||
$GLOBALS['errorUrl'] = Util::getScriptNameForOption($GLOBALS['cfg']['DefaultTabDatabase'], 'database');
|
||||
$GLOBALS['errorUrl'] .= Url::getCommon(['db' => $GLOBALS['db']], '&');
|
||||
|
||||
if (! $this->hasDatabase()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} elseif (strlen($GLOBALS['db']) > 0) {
|
||||
$this->dbi->selectDb($GLOBALS['db']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep a list of errors that occurred while
|
||||
* processing an 'Add' or 'Edit' operation.
|
||||
*/
|
||||
$GLOBALS['errors'] = [];
|
||||
|
||||
$this->triggers->main();
|
||||
}
|
||||
}
|
||||
@ -2,15 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Controllers\Database;
|
||||
namespace PhpMyAdmin\Controllers\Triggers;
|
||||
|
||||
use PhpMyAdmin\Controllers\AbstractController;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\DbTableExists;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Url;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
@ -20,7 +20,7 @@ use function strlen;
|
||||
/**
|
||||
* Triggers management.
|
||||
*/
|
||||
class TriggersController extends AbstractController
|
||||
final class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
ResponseRenderer $response,
|
||||
@ -37,7 +37,7 @@ class TriggersController extends AbstractController
|
||||
$GLOBALS['urlParams'] ??= null;
|
||||
$GLOBALS['errorUrl'] ??= null;
|
||||
|
||||
$this->addScriptFiles(['database/triggers.js']);
|
||||
$this->addScriptFiles(['triggers.js']);
|
||||
|
||||
if (! $this->response->isAjax()) {
|
||||
/**
|
||||
@ -73,6 +73,19 @@ class TriggersController extends AbstractController
|
||||
*/
|
||||
$GLOBALS['errors'] = [];
|
||||
|
||||
$this->triggers->main();
|
||||
$this->triggers->handleEditor();
|
||||
$this->triggers->export();
|
||||
|
||||
$triggers = Triggers::getDetails($this->dbi, $GLOBALS['db'], $GLOBALS['table']);
|
||||
$hasTriggerPrivilege = Util::currentUserHasPrivilege('TRIGGER', $GLOBALS['db'], $GLOBALS['table']);
|
||||
$isAjax = $this->response->isAjax() && empty($_REQUEST['ajax_page_request']);
|
||||
|
||||
$this->render('triggers/list', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'triggers' => $triggers,
|
||||
'has_privilege' => $hasTriggerPrivilege,
|
||||
'is_ajax' => $isAjax,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -303,10 +303,10 @@ class Menu
|
||||
}
|
||||
|
||||
if (! $isSystemSchema && Util::currentUserHasPrivilege('TRIGGER', $this->db, $this->table) && ! $tableIsView) {
|
||||
$tabs['triggers']['route'] = '/table/triggers';
|
||||
$tabs['triggers']['route'] = '/triggers';
|
||||
$tabs['triggers']['text'] = __('Triggers');
|
||||
$tabs['triggers']['icon'] = 'b_triggers';
|
||||
$tabs['triggers']['active'] = $route === '/table/triggers';
|
||||
$tabs['triggers']['active'] = $route === '/triggers';
|
||||
}
|
||||
|
||||
return $tabs;
|
||||
@ -396,10 +396,10 @@ class Menu
|
||||
}
|
||||
|
||||
if (Util::currentUserHasPrivilege('TRIGGER', $this->db)) {
|
||||
$tabs['triggers']['route'] = '/database/triggers';
|
||||
$tabs['triggers']['route'] = '/triggers';
|
||||
$tabs['triggers']['text'] = __('Triggers');
|
||||
$tabs['triggers']['icon'] = 'b_triggers';
|
||||
$tabs['triggers']['active'] = $route === '/database/triggers';
|
||||
$tabs['triggers']['active'] = $route === '/triggers';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,11 +29,11 @@ class NodeTrigger extends Node
|
||||
$this->icon = ['image' => 'b_triggers', 'title' => __('Trigger')];
|
||||
$this->links = [
|
||||
'text' => [
|
||||
'route' => '/database/triggers',
|
||||
'route' => '/triggers',
|
||||
'params' => ['edit_item' => 1, 'db' => null, 'item_name' => null],
|
||||
],
|
||||
'icon' => [
|
||||
'route' => '/database/triggers',
|
||||
'route' => '/triggers',
|
||||
'params' => ['export_item' => 1, 'db' => null, 'item_name' => null],
|
||||
],
|
||||
];
|
||||
|
||||
@ -26,8 +26,8 @@ class NodeTriggerContainer extends Node
|
||||
|
||||
$this->icon = ['image' => 'b_triggers', 'title' => __('Triggers')];
|
||||
$this->links = [
|
||||
'text' => ['route' => '/database/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'icon' => ['route' => '/database/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'text' => ['route' => '/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'icon' => ['route' => '/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
];
|
||||
$this->realName = 'triggers';
|
||||
|
||||
@ -35,8 +35,8 @@ class NodeTriggerContainer extends Node
|
||||
$new = NodeFactory::getInstanceForNewNode($newLabel, 'new_trigger italics');
|
||||
$new->icon = ['image' => 'b_trigger_add', 'title' => $newLabel];
|
||||
$new->links = [
|
||||
'text' => ['route' => '/database/triggers', 'params' => ['add_item' => 1, 'db' => null]],
|
||||
'icon' => ['route' => '/database/triggers', 'params' => ['add_item' => 1, 'db' => null]],
|
||||
'text' => ['route' => '/triggers', 'params' => ['add_item' => 1, 'db' => null]],
|
||||
'icon' => ['route' => '/triggers', 'params' => ['add_item' => 1, 'db' => null]],
|
||||
];
|
||||
$this->addChild($new);
|
||||
}
|
||||
|
||||
@ -7,11 +7,11 @@ namespace PhpMyAdmin;
|
||||
use PhpMyAdmin\ConfigStorage\Relation;
|
||||
use PhpMyAdmin\Database\Events;
|
||||
use PhpMyAdmin\Database\Routines;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\Dbal\DatabaseName;
|
||||
use PhpMyAdmin\Engines\Innodb;
|
||||
use PhpMyAdmin\Partitioning\Partition;
|
||||
use PhpMyAdmin\Plugins\Export\ExportSql;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
|
||||
use function __;
|
||||
use function array_merge;
|
||||
|
||||
@ -7,7 +7,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Dbal\ResultInterface;
|
||||
@ -18,6 +17,7 @@ use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\RadioPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
|
||||
@ -7,7 +7,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\FieldMetadata;
|
||||
@ -19,6 +18,7 @@ use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\RadioPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
|
||||
@ -10,7 +10,6 @@ namespace PhpMyAdmin\Plugins\Export;
|
||||
use PhpMyAdmin\Charsets;
|
||||
use PhpMyAdmin\Database\Events;
|
||||
use PhpMyAdmin\Database\Routines;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\FieldMetadata;
|
||||
@ -30,6 +29,7 @@ use PhpMyAdmin\SqlParser\Context;
|
||||
use PhpMyAdmin\SqlParser\Parser;
|
||||
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
|
||||
use PhpMyAdmin\SqlParser\Token;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Version;
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Dbal\ResultInterface;
|
||||
@ -18,6 +17,7 @@ use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\RadioPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
|
||||
@ -6,7 +6,6 @@ namespace PhpMyAdmin\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Database\Events;
|
||||
use PhpMyAdmin\Database\Routines;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Plugins\ExportPlugin;
|
||||
@ -15,6 +14,7 @@ use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
|
||||
use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\HiddenPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Version;
|
||||
|
||||
|
||||
@ -8,13 +8,13 @@ declare(strict_types=1);
|
||||
namespace PhpMyAdmin\Plugins\Export\Helpers;
|
||||
|
||||
use PhpMyAdmin\ConfigStorage\Relation;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Dbal\ResultInterface;
|
||||
use PhpMyAdmin\FieldMetadata;
|
||||
use PhpMyAdmin\Pdf as PdfLib;
|
||||
use PhpMyAdmin\Transformations;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
use TCPDF_STATIC;
|
||||
|
||||
|
||||
@ -215,11 +215,10 @@ class Generator
|
||||
. ', EVENT_OBJECT_TABLE, ACTION_TIMING, ACTION_STATEMENT'
|
||||
. ', EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER'
|
||||
. ' FROM information_schema.TRIGGERS'
|
||||
. ' WHERE EVENT_OBJECT_SCHEMA ' . Util::getCollateForIS() . '='
|
||||
. ' \'' . $escapedDb . '\'';
|
||||
. ' WHERE EVENT_OBJECT_SCHEMA ' . Util::getCollateForIS() . '= ' . $escapedDb;
|
||||
|
||||
if ($escapedTable !== null) {
|
||||
$query .= ' AND EVENT_OBJECT_TABLE ' . Util::getCollateForIS() . " = '" . $escapedTable . "';";
|
||||
$query .= ' AND EVENT_OBJECT_TABLE ' . Util::getCollateForIS() . ' = ' . $escapedTable . ';';
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
||||
@ -8,7 +8,6 @@ use PhpMyAdmin\ConfigStorage\Features\DisplayFeature;
|
||||
use PhpMyAdmin\ConfigStorage\Features\RelationFeature;
|
||||
use PhpMyAdmin\ConfigStorage\Features\UiPreferencesFeature;
|
||||
use PhpMyAdmin\ConfigStorage\Relation;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\Dbal\Connection;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
use PhpMyAdmin\Html\MySQLDocumentation;
|
||||
@ -23,6 +22,7 @@ use PhpMyAdmin\SqlParser\Statements\AlterStatement;
|
||||
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
|
||||
use PhpMyAdmin\SqlParser\Statements\DropStatement;
|
||||
use PhpMyAdmin\SqlParser\Utils\Table as TableUtils;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use Stringable;
|
||||
|
||||
use function __;
|
||||
|
||||
44
libraries/classes/Triggers/Trigger.php
Normal file
44
libraries/classes/Triggers/Trigger.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Triggers;
|
||||
|
||||
use Webmozart\Assert\Assert;
|
||||
use Webmozart\Assert\InvalidArgumentException;
|
||||
|
||||
final class Trigger
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
public readonly string $timing,
|
||||
public readonly string $event,
|
||||
public readonly string $table,
|
||||
public readonly string $statement,
|
||||
public readonly string $definer,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @param mixed[] $trigger */
|
||||
public static function tryFromArray(array $trigger): self|null
|
||||
{
|
||||
try {
|
||||
$name = $trigger['Trigger'] ?? $trigger['TRIGGER_NAME'] ?? null;
|
||||
$timing = $trigger['Timing'] ?? $trigger['ACTION_TIMING'] ?? null;
|
||||
$event = $trigger['Event'] ?? $trigger['EVENT_MANIPULATION'] ?? null;
|
||||
$table = $trigger['Table'] ?? $trigger['EVENT_OBJECT_TABLE'] ?? null;
|
||||
$statement = $trigger['Statement'] ?? $trigger['ACTION_STATEMENT'] ?? null;
|
||||
$definer = $trigger['Definer'] ?? $trigger['DEFINER'] ?? null;
|
||||
Assert::string($name);
|
||||
Assert::string($timing);
|
||||
Assert::string($event);
|
||||
Assert::string($table);
|
||||
Assert::string($statement);
|
||||
Assert::string($definer);
|
||||
|
||||
return new self($name, $timing, $event, $table, $statement, $definer);
|
||||
} catch (InvalidArgumentException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Database;
|
||||
namespace PhpMyAdmin\Triggers;
|
||||
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Html\Generator;
|
||||
@ -11,6 +11,7 @@ use PhpMyAdmin\Query\Generator as QueryGenerator;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Util;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function __;
|
||||
use function array_column;
|
||||
@ -44,42 +45,6 @@ class Triggers
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function for the triggers functionality
|
||||
*/
|
||||
public function main(): void
|
||||
{
|
||||
/**
|
||||
* Process all requests
|
||||
*/
|
||||
$this->handleEditor();
|
||||
$this->export();
|
||||
|
||||
$items = self::getDetails($this->dbi, $GLOBALS['db'], $GLOBALS['table']);
|
||||
$hasTriggerPrivilege = Util::currentUserHasPrivilege('TRIGGER', $GLOBALS['db'], $GLOBALS['table']);
|
||||
$isAjax = $this->response->isAjax() && empty($_REQUEST['ajax_page_request']);
|
||||
|
||||
$rows = '';
|
||||
foreach ($items as $item) {
|
||||
$rows .= $this->template->render('database/triggers/row', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'trigger' => $item,
|
||||
'has_drop_privilege' => $hasTriggerPrivilege,
|
||||
'has_edit_privilege' => $hasTriggerPrivilege,
|
||||
'row_class' => $isAjax ? 'ajaxInsert hide' : '',
|
||||
]);
|
||||
}
|
||||
|
||||
echo $this->template->render('database/triggers/list', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'items' => $items,
|
||||
'rows' => $rows,
|
||||
'has_privilege' => $hasTriggerPrivilege,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles editor requests for adding or editing an item
|
||||
*/
|
||||
@ -197,7 +162,7 @@ class Triggers
|
||||
);
|
||||
$this->response->addJSON(
|
||||
'new_row',
|
||||
$this->template->render('database/triggers/row', [
|
||||
$this->template->render('triggers/row', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'trigger' => $trigger,
|
||||
@ -335,12 +300,9 @@ class Triggers
|
||||
*/
|
||||
public function getEditorForm(string $db, string $table, string $mode, array $item): string
|
||||
{
|
||||
$query = 'SELECT `TABLE_NAME` FROM `INFORMATION_SCHEMA`.`TABLES` ';
|
||||
$query .= 'WHERE `TABLE_SCHEMA`=\'' . $this->dbi->escapeString($db) . '\' ';
|
||||
$query .= 'AND `TABLE_TYPE` IN (\'BASE TABLE\', \'SYSTEM VERSIONED\')';
|
||||
$tables = $this->dbi->fetchResult($query);
|
||||
$tables = $this->getTables($db);
|
||||
|
||||
return $this->template->render('database/triggers/editor_form', [
|
||||
return $this->template->render('triggers/editor_form', [
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
'is_edit' => $mode === 'edit',
|
||||
@ -469,7 +431,7 @@ class Triggers
|
||||
echo $message->getDisplay();
|
||||
}
|
||||
|
||||
private function export(): void
|
||||
public function export(): void
|
||||
{
|
||||
if (empty($_GET['export_item']) || empty($_GET['item_name'])) {
|
||||
return;
|
||||
@ -496,7 +458,7 @@ class Triggers
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->response->addHTML($this->template->render('database/triggers/export', [
|
||||
$this->response->addHTML($this->template->render('triggers/export', [
|
||||
'data' => $exportData,
|
||||
'item_name' => $itemName,
|
||||
]));
|
||||
@ -539,48 +501,46 @@ class Triggers
|
||||
$result = [];
|
||||
if (! $GLOBALS['cfg']['Server']['DisableIS']) {
|
||||
$query = QueryGenerator::getInformationSchemaTriggersRequest(
|
||||
$dbi->escapeString($db),
|
||||
$table === '' ? null : $dbi->escapeString($table),
|
||||
$dbi->quoteString($db),
|
||||
$table === '' ? null : $dbi->quoteString($table),
|
||||
);
|
||||
} else {
|
||||
$query = 'SHOW TRIGGERS FROM ' . Util::backquote($db);
|
||||
if ($table !== '') {
|
||||
$query .= " LIKE '" . $dbi->escapeString($table) . "';";
|
||||
$query .= ' LIKE ' . $dbi->quoteString($table) . ';';
|
||||
}
|
||||
}
|
||||
|
||||
/** @var mixed[][] $triggers */
|
||||
$triggers = $dbi->fetchResult($query);
|
||||
|
||||
foreach ($triggers as $trigger) {
|
||||
if ($GLOBALS['cfg']['Server']['DisableIS']) {
|
||||
$trigger['TRIGGER_NAME'] = $trigger['Trigger'];
|
||||
$trigger['ACTION_TIMING'] = $trigger['Timing'];
|
||||
$trigger['EVENT_MANIPULATION'] = $trigger['Event'];
|
||||
$trigger['EVENT_OBJECT_TABLE'] = $trigger['Table'];
|
||||
$trigger['ACTION_STATEMENT'] = $trigger['Statement'];
|
||||
$trigger['DEFINER'] = $trigger['Definer'];
|
||||
$newTrigger = Trigger::tryFromArray($trigger);
|
||||
if ($newTrigger === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$oneResult = [];
|
||||
$oneResult['name'] = $trigger['TRIGGER_NAME'];
|
||||
$oneResult['table'] = $trigger['EVENT_OBJECT_TABLE'];
|
||||
$oneResult['action_timing'] = $trigger['ACTION_TIMING'];
|
||||
$oneResult['event_manipulation'] = $trigger['EVENT_MANIPULATION'];
|
||||
$oneResult['definition'] = $trigger['ACTION_STATEMENT'];
|
||||
$oneResult['definer'] = $trigger['DEFINER'];
|
||||
$oneResult['name'] = $newTrigger->name;
|
||||
$oneResult['table'] = $newTrigger->table;
|
||||
$oneResult['action_timing'] = $newTrigger->timing;
|
||||
$oneResult['event_manipulation'] = $newTrigger->event;
|
||||
$oneResult['definition'] = $newTrigger->statement;
|
||||
$oneResult['definer'] = $newTrigger->definer;
|
||||
|
||||
// do not prepend the schema name; this way, importing the
|
||||
// definition into another schema will work
|
||||
$oneResult['full_trigger_name'] = Util::backquote($trigger['TRIGGER_NAME']);
|
||||
$oneResult['drop'] = 'DROP TRIGGER IF EXISTS '
|
||||
. $oneResult['full_trigger_name'];
|
||||
$oneResult['create'] = 'CREATE TRIGGER '
|
||||
. $oneResult['full_trigger_name'] . ' '
|
||||
. $trigger['ACTION_TIMING'] . ' '
|
||||
. $trigger['EVENT_MANIPULATION']
|
||||
. ' ON ' . Util::backquote($trigger['EVENT_OBJECT_TABLE'])
|
||||
. "\n" . ' FOR EACH ROW '
|
||||
. $trigger['ACTION_STATEMENT'] . "\n" . $delimiter . "\n";
|
||||
$oneResult['full_trigger_name'] = Util::backquote($newTrigger->name);
|
||||
$oneResult['drop'] = 'DROP TRIGGER IF EXISTS ' . $oneResult['full_trigger_name'];
|
||||
$oneResult['create'] = sprintf(
|
||||
"CREATE TRIGGER %s %s %s ON %s\n FOR EACH ROW %s\n%s\n",
|
||||
$oneResult['full_trigger_name'],
|
||||
$newTrigger->timing,
|
||||
$newTrigger->event,
|
||||
Util::backquote($newTrigger->table),
|
||||
$newTrigger->statement,
|
||||
$delimiter,
|
||||
);
|
||||
|
||||
$result[] = $oneResult;
|
||||
}
|
||||
@ -591,4 +551,19 @@ class Triggers
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @return list<non-empty-string> */
|
||||
private function getTables(string $db): array
|
||||
{
|
||||
$query = sprintf(
|
||||
'SELECT `TABLE_NAME` FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=%s'
|
||||
. " AND `TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')",
|
||||
$this->dbi->quoteString($db),
|
||||
);
|
||||
$tables = $this->dbi->fetchResult($query);
|
||||
Assert::allStringNotEmpty($tables);
|
||||
Assert::isList($tables);
|
||||
|
||||
return $tables;
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,7 @@ use PhpMyAdmin\Controllers\TableController;
|
||||
use PhpMyAdmin\Controllers\ThemesController;
|
||||
use PhpMyAdmin\Controllers\ThemeSetController;
|
||||
use PhpMyAdmin\Controllers\Transformation;
|
||||
use PhpMyAdmin\Controllers\Triggers;
|
||||
use PhpMyAdmin\Controllers\UserPasswordController;
|
||||
use PhpMyAdmin\Controllers\VersionCheckController;
|
||||
use PhpMyAdmin\Controllers\View;
|
||||
@ -108,7 +109,6 @@ return static function (RouteCollector $routes): void {
|
||||
$routes->post('/show-create', Database\Structure\ShowCreateController::class);
|
||||
});
|
||||
$routes->addRoute(['GET', 'POST'], '/tracking', Database\TrackingController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/triggers', Database\TriggersController::class);
|
||||
});
|
||||
$routes->post('/databases', DatabaseController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/error-report', ErrorReportController::class);
|
||||
@ -290,7 +290,6 @@ return static function (RouteCollector $routes): void {
|
||||
$routes->post('/unique', Table\Structure\UniqueController::class);
|
||||
});
|
||||
$routes->addRoute(['GET', 'POST'], '/tracking', Table\TrackingController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/triggers', Table\TriggersController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/zoom-search', Table\ZoomSearchController::class);
|
||||
});
|
||||
$routes->post('/tables', TableController::class);
|
||||
@ -302,6 +301,7 @@ return static function (RouteCollector $routes): void {
|
||||
$routes->addRoute(['GET', 'POST'], '/overview', Transformation\OverviewController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/wrapper', Transformation\WrapperController::class);
|
||||
});
|
||||
$routes->addRoute(['GET', 'POST'], '/triggers', Triggers\IndexController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/user-password', UserPasswordController::class);
|
||||
$routes->addRoute(['GET', 'POST'], '/version-check', VersionCheckController::class);
|
||||
$routes->addGroup('/view', static function (RouteCollector $routes): void {
|
||||
|
||||
@ -14,7 +14,6 @@ use PhpMyAdmin\Database\Designer;
|
||||
use PhpMyAdmin\Database\Designer\Common;
|
||||
use PhpMyAdmin\Database\Events;
|
||||
use PhpMyAdmin\Database\Routines;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\ErrorHandler;
|
||||
use PhpMyAdmin\ErrorReport;
|
||||
@ -50,6 +49,7 @@ use PhpMyAdmin\Theme\ThemeManager;
|
||||
use PhpMyAdmin\Tracking\Tracking;
|
||||
use PhpMyAdmin\Tracking\TrackingChecker;
|
||||
use PhpMyAdmin\Transformations;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\UserPassword;
|
||||
use PhpMyAdmin\UserPreferences;
|
||||
use PhpMyAdmin\Utils\HttpRequest;
|
||||
|
||||
@ -34,6 +34,7 @@ use PhpMyAdmin\Controllers\TableController;
|
||||
use PhpMyAdmin\Controllers\ThemesController;
|
||||
use PhpMyAdmin\Controllers\ThemeSetController;
|
||||
use PhpMyAdmin\Controllers\Transformation;
|
||||
use PhpMyAdmin\Controllers\Triggers;
|
||||
use PhpMyAdmin\Controllers\UserPasswordController;
|
||||
use PhpMyAdmin\Controllers\VersionCheckController;
|
||||
use PhpMyAdmin\Controllers\View;
|
||||
@ -349,15 +350,6 @@ return [
|
||||
'$dbi' => '@dbi',
|
||||
],
|
||||
],
|
||||
Database\TriggersController::class => [
|
||||
'class' => Database\TriggersController::class,
|
||||
'arguments' => [
|
||||
'$response' => '@response',
|
||||
'$template' => '@template',
|
||||
'$dbi' => '@dbi',
|
||||
'$triggers' => '@triggers',
|
||||
],
|
||||
],
|
||||
DatabaseController::class => [
|
||||
'class' => DatabaseController::class,
|
||||
'arguments' => ['$response' => '@response', '$template' => '@template'],
|
||||
@ -1417,8 +1409,8 @@ return [
|
||||
'$trackingChecker' => '@tracking_checker',
|
||||
],
|
||||
],
|
||||
Table\TriggersController::class => [
|
||||
'class' => Table\TriggersController::class,
|
||||
Triggers\IndexController::class => [
|
||||
'class' => Triggers\IndexController::class,
|
||||
'arguments' => [
|
||||
'$response' => '@response',
|
||||
'$template' => '@template',
|
||||
|
||||
@ -3135,136 +3135,6 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Database/Search.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'ACTION_STATEMENT' on mixed\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'ACTION_TIMING' on mixed\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'DEFINER' on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Definer' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'EVENT_MANIPULATION' on mixed\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'EVENT_OBJECT_TABLE' on mixed\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Event' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Statement' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'TRIGGER_NAME' on mixed\\.$#"
|
||||
count: 3
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Table' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Timing' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'Trigger' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'action_timing' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'create' on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'definer' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'definition' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'drop' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'event_manipulation' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'name' on mixed\\.$#"
|
||||
count: 4
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'table' on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'create' does not exist on array\\|null\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'drop' does not exist on array\\|null\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$createStatement of method PhpMyAdmin\\\\Database\\\\Triggers\\:\\:checkResult\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$identifier of static method PhpMyAdmin\\\\Util\\:\\:backquote\\(\\) expects string\\|Stringable\\|null, mixed given\\.$#"
|
||||
count: 4
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$query of method PhpMyAdmin\\\\DatabaseInterface\\:\\:tryQuery\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function trim expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Database/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Binary operation \"\\+\" between string\\|null and string\\|null results in an error\\.$#"
|
||||
count: 1
|
||||
@ -5741,7 +5611,7 @@ parameters:
|
||||
path: libraries/classes/Plugins/Export/ExportXml.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$table of static method PhpMyAdmin\\\\Database\\\\Triggers\\:\\:getDetails\\(\\) expects string, mixed given\\.$#"
|
||||
message: "#^Parameter \\#3 \\$table of static method PhpMyAdmin\\\\Triggers\\\\Triggers\\:\\:getDetails\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Plugins/Export/ExportXml.php
|
||||
|
||||
@ -8500,6 +8370,76 @@ parameters:
|
||||
count: 1
|
||||
path: libraries/classes/Transformations.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'action_timing' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'create' on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'definer' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'definition' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'drop' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'event_manipulation' on mixed\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'name' on mixed\\.$#"
|
||||
count: 4
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 'table' on mixed\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'create' does not exist on array\\|null\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'drop' does not exist on array\\|null\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$createStatement of method PhpMyAdmin\\\\Triggers\\\\Triggers\\:\\:checkResult\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$identifier of static method PhpMyAdmin\\\\Util\\:\\:backquote\\(\\) expects string\\|Stringable\\|null, mixed given\\.$#"
|
||||
count: 2
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$query of method PhpMyAdmin\\\\DatabaseInterface\\:\\:tryQuery\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function trim expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: libraries/classes/Triggers/Triggers.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method object\\:\\:configure\\(\\)\\.$#"
|
||||
count: 1
|
||||
|
||||
@ -1681,22 +1681,6 @@
|
||||
<code>__construct</code>
|
||||
</PossiblyUnusedMethod>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/Database/TriggersController.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</MixedAssignment>
|
||||
<PossiblyUnusedMethod>
|
||||
<code>__construct</code>
|
||||
</PossiblyUnusedMethod>
|
||||
<PossiblyUnusedParam>
|
||||
<code>$request</code>
|
||||
</PossiblyUnusedParam>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/DatabaseController.php">
|
||||
<UnusedParam>
|
||||
<code>$request</code>
|
||||
@ -4216,19 +4200,6 @@
|
||||
<code><![CDATA[$GLOBALS['text_dir']]]></code>
|
||||
</PossiblyNullArgument>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/Table/TriggersController.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</MixedAssignment>
|
||||
<PossiblyUnusedParam>
|
||||
<code>$request</code>
|
||||
</PossiblyUnusedParam>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/Table/ZoomSearchController.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
@ -4332,6 +4303,19 @@
|
||||
<code>__construct</code>
|
||||
</PossiblyUnusedMethod>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/Triggers/IndexController.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errorUrl']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</MixedAssignment>
|
||||
<UnusedParam>
|
||||
<code>$request</code>
|
||||
</UnusedParam>
|
||||
</file>
|
||||
<file src="libraries/classes/Controllers/UserPasswordController.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['cfg']['ShowChgPassword']]]></code>
|
||||
@ -5505,159 +5489,6 @@
|
||||
<code><![CDATA[$this->searchTypeDescription]]></code>
|
||||
</MixedAssignment>
|
||||
</file>
|
||||
<file src="libraries/classes/Database/Triggers.php">
|
||||
<DeprecatedMethod>
|
||||
<code>escapeString</code>
|
||||
<code>escapeString</code>
|
||||
<code>escapeString</code>
|
||||
<code>escapeString</code>
|
||||
</DeprecatedMethod>
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code>$createItem</code>
|
||||
<code>$exportData</code>
|
||||
<code><![CDATA[$trigger['EVENT_OBJECT_TABLE']]]></code>
|
||||
<code><![CDATA[$trigger['TRIGGER_NAME']]]></code>
|
||||
</MixedArgument>
|
||||
<MixedArrayAccess>
|
||||
<code><![CDATA[$temp['action_timing']]]></code>
|
||||
<code><![CDATA[$temp['create']]]></code>
|
||||
<code><![CDATA[$temp['definer']]]></code>
|
||||
<code><![CDATA[$temp['definition']]]></code>
|
||||
<code><![CDATA[$temp['drop']]]></code>
|
||||
<code><![CDATA[$temp['event_manipulation']]]></code>
|
||||
<code><![CDATA[$temp['name']]]></code>
|
||||
<code><![CDATA[$temp['table']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_STATEMENT']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_STATEMENT']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_TIMING']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_TIMING']]]></code>
|
||||
<code><![CDATA[$trigger['DEFINER']]]></code>
|
||||
<code><![CDATA[$trigger['Definer']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_MANIPULATION']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_MANIPULATION']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_OBJECT_TABLE']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_OBJECT_TABLE']]]></code>
|
||||
<code><![CDATA[$trigger['Event']]]></code>
|
||||
<code><![CDATA[$trigger['Statement']]]></code>
|
||||
<code><![CDATA[$trigger['TRIGGER_NAME']]]></code>
|
||||
<code><![CDATA[$trigger['TRIGGER_NAME']]]></code>
|
||||
<code><![CDATA[$trigger['Table']]]></code>
|
||||
<code><![CDATA[$trigger['Timing']]]></code>
|
||||
<code><![CDATA[$trigger['Trigger']]]></code>
|
||||
<code><![CDATA[$trigger['create']]]></code>
|
||||
<code><![CDATA[$trigger['name']]]></code>
|
||||
<code><![CDATA[$trigger['table']]]></code>
|
||||
<code><![CDATA[$value['name']]]></code>
|
||||
<code><![CDATA[$value['name']]]></code>
|
||||
</MixedArrayAccess>
|
||||
<MixedArrayAssignment>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_STATEMENT']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_TIMING']]]></code>
|
||||
<code><![CDATA[$trigger['DEFINER']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_MANIPULATION']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_OBJECT_TABLE']]]></code>
|
||||
<code><![CDATA[$trigger['TRIGGER_NAME']]]></code>
|
||||
</MixedArrayAssignment>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code>$createItem</code>
|
||||
<code>$exportData</code>
|
||||
<code>$item</code>
|
||||
<code><![CDATA[$item['item_original_name']]]></code>
|
||||
<code><![CDATA[$oneResult['action_timing']]]></code>
|
||||
<code><![CDATA[$oneResult['definer']]]></code>
|
||||
<code><![CDATA[$oneResult['definition']]]></code>
|
||||
<code><![CDATA[$oneResult['event_manipulation']]]></code>
|
||||
<code><![CDATA[$oneResult['name']]]></code>
|
||||
<code><![CDATA[$oneResult['table']]]></code>
|
||||
<code><![CDATA[$retval['create']]]></code>
|
||||
<code><![CDATA[$retval['drop']]]></code>
|
||||
<code><![CDATA[$retval['item_action_timing']]]></code>
|
||||
<code><![CDATA[$retval['item_definer']]]></code>
|
||||
<code><![CDATA[$retval['item_definition']]]></code>
|
||||
<code><![CDATA[$retval['item_event_manipulation']]]></code>
|
||||
<code><![CDATA[$retval['item_name']]]></code>
|
||||
<code><![CDATA[$retval['item_table']]]></code>
|
||||
<code>$string</code>
|
||||
<code>$temp</code>
|
||||
<code>$trigger</code>
|
||||
<code>$trigger</code>
|
||||
<code>$trigger</code>
|
||||
<code><![CDATA[$trigger['ACTION_STATEMENT']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_TIMING']]]></code>
|
||||
<code><![CDATA[$trigger['DEFINER']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_MANIPULATION']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_OBJECT_TABLE']]]></code>
|
||||
<code><![CDATA[$trigger['TRIGGER_NAME']]]></code>
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
</MixedAssignment>
|
||||
<MixedOperand>
|
||||
<code>$string</code>
|
||||
<code><![CDATA[$trigger['ACTION_STATEMENT']]]></code>
|
||||
<code><![CDATA[$trigger['ACTION_TIMING']]]></code>
|
||||
<code><![CDATA[$trigger['EVENT_MANIPULATION']]]></code>
|
||||
<code><![CDATA[$trigger['drop']]]></code>
|
||||
</MixedOperand>
|
||||
<PossiblyInvalidArgument>
|
||||
<code><![CDATA[$_POST['item_definer']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_original_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_table']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
<code>$itemName</code>
|
||||
<code>$itemName</code>
|
||||
</PossiblyInvalidArgument>
|
||||
<PossiblyInvalidCast>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_original_name']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
</PossiblyInvalidCast>
|
||||
<PossiblyInvalidOperand>
|
||||
<code><![CDATA[$_POST['item_definition']]]></code>
|
||||
<code><![CDATA[$_POST['item_event']]]></code>
|
||||
<code><![CDATA[$_POST['item_timing']]]></code>
|
||||
</PossiblyInvalidOperand>
|
||||
<PossiblyNullArgument>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['message']]]></code>
|
||||
<code>$createItem</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess>
|
||||
<code><![CDATA[$trigger['create']]]></code>
|
||||
<code><![CDATA[$trigger['drop']]]></code>
|
||||
</PossiblyNullArrayAccess>
|
||||
<PossiblyNullIterator>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</PossiblyNullIterator>
|
||||
<PossiblyNullReference>
|
||||
<code>isSuccess</code>
|
||||
</PossiblyNullReference>
|
||||
</file>
|
||||
<file src="libraries/classes/DatabaseInterface.php">
|
||||
<DeprecatedMethod>
|
||||
<code>escapeString</code>
|
||||
@ -13037,6 +12868,111 @@
|
||||
<code>bool</code>
|
||||
</PossiblyUnusedReturnValue>
|
||||
</file>
|
||||
<file src="libraries/classes/Triggers/Triggers.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</InvalidArrayOffset>
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code>$createItem</code>
|
||||
<code>$exportData</code>
|
||||
</MixedArgument>
|
||||
<MixedArrayAccess>
|
||||
<code><![CDATA[$temp['action_timing']]]></code>
|
||||
<code><![CDATA[$temp['create']]]></code>
|
||||
<code><![CDATA[$temp['definer']]]></code>
|
||||
<code><![CDATA[$temp['definition']]]></code>
|
||||
<code><![CDATA[$temp['drop']]]></code>
|
||||
<code><![CDATA[$temp['event_manipulation']]]></code>
|
||||
<code><![CDATA[$temp['name']]]></code>
|
||||
<code><![CDATA[$temp['table']]]></code>
|
||||
<code><![CDATA[$trigger['create']]]></code>
|
||||
<code><![CDATA[$trigger['name']]]></code>
|
||||
<code><![CDATA[$trigger['table']]]></code>
|
||||
<code><![CDATA[$value['name']]]></code>
|
||||
<code><![CDATA[$value['name']]]></code>
|
||||
</MixedArrayAccess>
|
||||
<MixedArrayAssignment>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors'][]]]></code>
|
||||
</MixedArrayAssignment>
|
||||
<MixedAssignment>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code>$createItem</code>
|
||||
<code>$exportData</code>
|
||||
<code><![CDATA[$item['item_original_name']]]></code>
|
||||
<code><![CDATA[$retval['create']]]></code>
|
||||
<code><![CDATA[$retval['drop']]]></code>
|
||||
<code><![CDATA[$retval['item_action_timing']]]></code>
|
||||
<code><![CDATA[$retval['item_definer']]]></code>
|
||||
<code><![CDATA[$retval['item_definition']]]></code>
|
||||
<code><![CDATA[$retval['item_event_manipulation']]]></code>
|
||||
<code><![CDATA[$retval['item_name']]]></code>
|
||||
<code><![CDATA[$retval['item_table']]]></code>
|
||||
<code>$string</code>
|
||||
<code>$temp</code>
|
||||
<code>$trigger</code>
|
||||
<code>$trigger</code>
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
</MixedAssignment>
|
||||
<MixedOperand>
|
||||
<code>$string</code>
|
||||
<code><![CDATA[$trigger['drop']]]></code>
|
||||
</MixedOperand>
|
||||
<PossiblyInvalidArgument>
|
||||
<code><![CDATA[$_POST['item_definer']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_original_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_table']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
<code>$itemName</code>
|
||||
<code>$itemName</code>
|
||||
</PossiblyInvalidArgument>
|
||||
<PossiblyInvalidCast>
|
||||
<code><![CDATA[$_POST['item_name']]]></code>
|
||||
<code><![CDATA[$_POST['item_original_name']]]></code>
|
||||
<code><![CDATA[$_REQUEST['item_name']]]></code>
|
||||
</PossiblyInvalidCast>
|
||||
<PossiblyInvalidOperand>
|
||||
<code><![CDATA[$_POST['item_definition']]]></code>
|
||||
<code><![CDATA[$_POST['item_event']]]></code>
|
||||
<code><![CDATA[$_POST['item_timing']]]></code>
|
||||
</PossiblyInvalidOperand>
|
||||
<PossiblyNullArgument>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
<code><![CDATA[$GLOBALS['message']]]></code>
|
||||
<code>$createItem</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess>
|
||||
<code><![CDATA[$trigger['create']]]></code>
|
||||
<code><![CDATA[$trigger['drop']]]></code>
|
||||
</PossiblyNullArrayAccess>
|
||||
<PossiblyNullIterator>
|
||||
<code><![CDATA[$GLOBALS['errors']]]></code>
|
||||
</PossiblyNullIterator>
|
||||
<PossiblyNullReference>
|
||||
<code>isSuccess</code>
|
||||
</PossiblyNullReference>
|
||||
</file>
|
||||
<file src="libraries/classes/Twig/AssetExtension.php">
|
||||
<InvalidArrayOffset>
|
||||
<code><![CDATA[$GLOBALS['theme']]]></code>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<form class="rte_form" action="{{ url('/database/triggers') }}" method="post">
|
||||
<form class="rte_form" action="{{ url('/triggers') }}" method="post">
|
||||
{{ get_hidden_inputs(db, table) }}
|
||||
<input name="{{ is_edit ? 'edit_item' : 'add_item' }}" type="hidden" value="1">
|
||||
{% if is_edit %}
|
||||
@ -23,20 +23,20 @@
|
||||
</div>
|
||||
|
||||
<div class="ms-auto">
|
||||
<a class="ajax add_anchor btn btn-primary{{ not has_privilege ? ' disabled' }}" href="{{ url('/database/triggers', {'db': db, 'table': table, 'add_item': true}) }}" role="button"{{ not has_privilege ? ' tabindex="-1" aria-disabled="true"' }}>
|
||||
<a class="ajax add_anchor btn btn-primary{{ not has_privilege ? ' disabled' }}" href="{{ url('/triggers', {'db': db, 'table': table, 'add_item': true}) }}" role="button"{{ not has_privilege ? ' tabindex="-1" aria-disabled="true"' }}>
|
||||
{{ get_icon('b_trigger_add', 'Create new trigger'|trans) }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="rteListForm" class="ajax" action="{{ url(table is not empty ? '/table/triggers' : '/database/triggers') }}">
|
||||
<form id="rteListForm" class="ajax" action="{{ url('/triggers') }}">
|
||||
{{ get_hidden_inputs(db, table) }}
|
||||
|
||||
<div id="nothing2display"{{ items is not empty ? ' class="hide"' }}>
|
||||
<div id="nothing2display"{{ triggers is not empty ? ' class="hide"' }}>
|
||||
{% trans 'There are no triggers to display.' %}
|
||||
</div>
|
||||
|
||||
<table id="triggersTable" class="table table-striped table-hover{{ items is empty ? ' hide' }} w-auto data">
|
||||
<table id="triggersTable" class="table table-striped table-hover{{ triggers is empty ? ' hide' }} w-auto data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
@ -52,7 +52,20 @@
|
||||
<tbody>
|
||||
<tr class="hide">{% for i in 0..(table is empty ? 7 : 6) %}<td></td>{% endfor %}</tr>
|
||||
|
||||
{{ rows|raw }}
|
||||
{% for trigger in triggers %}
|
||||
{{ include(
|
||||
'triggers/row.twig',
|
||||
{
|
||||
'db': db,
|
||||
'table': table,
|
||||
'trigger': trigger,
|
||||
'has_drop_privilege': has_privilege,
|
||||
'has_edit_privilege': has_privilege,
|
||||
'row_class': is_ajax ? 'ajaxInsert hide' : '',
|
||||
},
|
||||
with_context = false
|
||||
) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
@ -8,7 +8,7 @@
|
||||
</td>
|
||||
{% if table is empty %}
|
||||
<td>
|
||||
<a href="{{ url('/table/triggers', {'db': db, 'table': trigger.table}) }}">{{ trigger.table }}</a>
|
||||
<a href="{{ url('/triggers', {'db': db, 'table': trigger.table}) }}">{{ trigger.table }}</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
@ -19,7 +19,7 @@
|
||||
</td>
|
||||
<td>
|
||||
{% if has_edit_privilege %}
|
||||
<a class="ajax edit_anchor" href="{{ url('/database/triggers', {
|
||||
<a class="ajax edit_anchor" href="{{ url('/triggers', {
|
||||
'db': db,
|
||||
'table': table,
|
||||
'edit_item': true,
|
||||
@ -32,7 +32,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="ajax export_anchor" href="{{ url('/database/triggers', {
|
||||
<a class="ajax export_anchor" href="{{ url('/triggers', {
|
||||
'db': db,
|
||||
'table': table,
|
||||
'export_item': true,
|
||||
@ -49,7 +49,7 @@
|
||||
'db': db,
|
||||
'table': table,
|
||||
'sql_query': trigger.drop,
|
||||
'goto': url('/database/triggers', {'db': db})
|
||||
'goto': url('/triggers', {'db': db})
|
||||
},
|
||||
get_icon('b_drop', 'Drop'|trans),
|
||||
{'class': 'ajax drop_anchor'}
|
||||
@ -2,19 +2,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Controllers\Table;
|
||||
namespace PhpMyAdmin\Tests\Controllers\Triggers;
|
||||
|
||||
use PhpMyAdmin\Controllers\Table\TriggersController;
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\Controllers\Triggers\IndexController;
|
||||
use PhpMyAdmin\DatabaseInterface;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Tests\AbstractTestCase;
|
||||
use PhpMyAdmin\Tests\Stubs\DbiDummy;
|
||||
use PhpMyAdmin\Tests\Stubs\ResponseRenderer;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
|
||||
/** @covers \PhpMyAdmin\Controllers\Table\TriggersController */
|
||||
class TriggersControllerTest extends AbstractTestCase
|
||||
/** @covers \PhpMyAdmin\Controllers\Triggers\IndexController */
|
||||
class IndexControllerTest extends AbstractTestCase
|
||||
{
|
||||
protected DatabaseInterface $dbi;
|
||||
|
||||
@ -49,14 +49,14 @@ class TriggersControllerTest extends AbstractTestCase
|
||||
|
||||
$template = new Template();
|
||||
$response = new ResponseRenderer();
|
||||
(new TriggersController(
|
||||
(new IndexController(
|
||||
$response,
|
||||
$template,
|
||||
$this->dbi,
|
||||
new Triggers($this->dbi, $template, $response),
|
||||
))($this->createStub(ServerRequest::class));
|
||||
|
||||
$items = [
|
||||
$triggers = [
|
||||
[
|
||||
'name' => 'test_trigger',
|
||||
'table' => 'test_table',
|
||||
@ -70,21 +70,14 @@ class TriggersControllerTest extends AbstractTestCase
|
||||
. ' FOR EACH ROW BEGIN END' . "\n" . '//' . "\n",
|
||||
],
|
||||
];
|
||||
$rows = $template->render('database/triggers/row', [
|
||||
$expected = $template->render('triggers/list', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'trigger' => $items[0],
|
||||
'has_drop_privilege' => true,
|
||||
'has_edit_privilege' => true,
|
||||
'row_class' => '',
|
||||
'triggers' => $triggers,
|
||||
'has_privilege' => true,
|
||||
'is_ajax' => false,
|
||||
]);
|
||||
|
||||
$this->expectOutputString($template->render('database/triggers/list', [
|
||||
'db' => $GLOBALS['db'],
|
||||
'table' => $GLOBALS['table'],
|
||||
'items' => $items,
|
||||
'rows' => $rows,
|
||||
'has_privilege' => true,
|
||||
]));
|
||||
$this->assertSame($expected, $response->getHTMLResult());
|
||||
}
|
||||
}
|
||||
@ -29,8 +29,8 @@ class NodeTriggerContainerTest extends AbstractTestCase
|
||||
$parent = new NodeTriggerContainer();
|
||||
$this->assertEquals(
|
||||
[
|
||||
'text' => ['route' => '/database/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'icon' => ['route' => '/database/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'text' => ['route' => '/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
'icon' => ['route' => '/triggers', 'params' => ['db' => null, 'table' => null]],
|
||||
],
|
||||
$parent->links,
|
||||
);
|
||||
|
||||
@ -30,11 +30,11 @@ class NodeTriggerTest extends AbstractTestCase
|
||||
$this->assertEquals(
|
||||
[
|
||||
'text' => [
|
||||
'route' => '/database/triggers',
|
||||
'route' => '/triggers',
|
||||
'params' => ['edit_item' => 1, 'db' => null, 'item_name' => null],
|
||||
],
|
||||
'icon' => [
|
||||
'route' => '/database/triggers',
|
||||
'route' => '/triggers',
|
||||
'params' => ['export_item' => 1, 'db' => null, 'item_name' => null],
|
||||
],
|
||||
],
|
||||
|
||||
96
test/classes/Triggers/TriggerTest.php
Normal file
96
test/classes/Triggers/TriggerTest.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Triggers;
|
||||
|
||||
use PhpMyAdmin\Triggers\Trigger;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/** @covers \PhpMyAdmin\Triggers\Trigger */
|
||||
class TriggerTest extends TestCase
|
||||
{
|
||||
public function testTryFromArrayWithEmptyArray(): void
|
||||
{
|
||||
$this->assertNull(Trigger::tryFromArray([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $trigger
|
||||
*
|
||||
* @dataProvider arrayWithValidValuesProvider
|
||||
*/
|
||||
public function testTryFromArrayWithValidValues(array $trigger): void
|
||||
{
|
||||
$actual = Trigger::tryFromArray($trigger);
|
||||
$this->assertNotNull($actual);
|
||||
$this->assertSame('trigger_name', $actual->name);
|
||||
$this->assertSame('BEFORE', $actual->timing);
|
||||
$this->assertSame('UPDATE', $actual->event);
|
||||
$this->assertSame('test_table', $actual->table);
|
||||
$this->assertSame('BEGIN END', $actual->statement);
|
||||
$this->assertSame('definer@localhost', $actual->definer);
|
||||
}
|
||||
|
||||
/** @return iterable<array-key, array{mixed[]}> */
|
||||
public static function arrayWithValidValuesProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
[
|
||||
'Trigger' => 'trigger_name',
|
||||
'Timing' => 'BEFORE',
|
||||
'Event' => 'UPDATE',
|
||||
'Table' => 'test_table',
|
||||
'Statement' => 'BEGIN END',
|
||||
'Definer' => 'definer@localhost',
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
[
|
||||
'TRIGGER_NAME' => 'trigger_name',
|
||||
'ACTION_TIMING' => 'BEFORE',
|
||||
'EVENT_MANIPULATION' => 'UPDATE',
|
||||
'EVENT_OBJECT_TABLE' => 'test_table',
|
||||
'ACTION_STATEMENT' => 'BEGIN END',
|
||||
'DEFINER' => 'definer@localhost',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $trigger
|
||||
*
|
||||
* @dataProvider arrayWithInvalidValuesProvider
|
||||
*/
|
||||
public function testTryFromArrayWithInvalidValues(array $trigger): void
|
||||
{
|
||||
$this->assertNull(Trigger::tryFromArray($trigger));
|
||||
}
|
||||
|
||||
/** @return iterable<array-key, array{mixed[]}> */
|
||||
public static function arrayWithInvalidValuesProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
[
|
||||
'Trigger' => null,
|
||||
'Timing' => null,
|
||||
'Event' => null,
|
||||
'Table' => null,
|
||||
'Statement' => null,
|
||||
'Definer' => null,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
[
|
||||
'TRIGGER_NAME' => null,
|
||||
'ACTION_TIMING' => null,
|
||||
'EVENT_MANIPULATION' => null,
|
||||
'EVENT_OBJECT_TABLE' => null,
|
||||
'ACTION_STATEMENT' => null,
|
||||
'DEFINER' => null,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -2,14 +2,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Database;
|
||||
namespace PhpMyAdmin\Tests\Triggers;
|
||||
|
||||
use PhpMyAdmin\Database\Triggers;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Template;
|
||||
use PhpMyAdmin\Tests\AbstractTestCase;
|
||||
use PhpMyAdmin\Triggers\Triggers;
|
||||
|
||||
/** @covers \PhpMyAdmin\Database\Triggers */
|
||||
/**
|
||||
* @covers \PhpMyAdmin\Triggers\Trigger
|
||||
* @covers \PhpMyAdmin\Triggers\Triggers
|
||||
*/
|
||||
class TriggersTest extends AbstractTestCase
|
||||
{
|
||||
private Triggers $triggers;
|
||||
@ -324,4 +327,132 @@ class TriggersTest extends AbstractTestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testGetDetails(): void
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['DisableIS'] = true;
|
||||
$dbiDummy = $this->createDbiDummy();
|
||||
$dbiDummy->addResult(
|
||||
'SHOW TRIGGERS FROM `test_db`',
|
||||
[
|
||||
['test_trigger', 'INSERT', 'test_table', 'BEGIN END', 'AFTER', 'definer@localhost'],
|
||||
['a_trigger', 'UPDATE', 'test_table2', 'BEGIN END', 'BEFORE', 'definer2@localhost'],
|
||||
],
|
||||
['Trigger', 'Event', 'Table', 'Statement', 'Timing', 'Definer'],
|
||||
);
|
||||
|
||||
$triggers = Triggers::getDetails($this->createDatabaseInterface($dbiDummy), 'test_db');
|
||||
$expected = [
|
||||
[
|
||||
'name' => 'a_trigger',
|
||||
'table' => 'test_table2',
|
||||
'action_timing' => 'BEFORE',
|
||||
'event_manipulation' => 'UPDATE',
|
||||
'definition' => 'BEGIN END',
|
||||
'definer' => 'definer2@localhost',
|
||||
'full_trigger_name' => '`a_trigger`',
|
||||
'drop' => 'DROP TRIGGER IF EXISTS `a_trigger`',
|
||||
'create' => "CREATE TRIGGER `a_trigger` BEFORE UPDATE ON `test_table2`\n FOR EACH ROW BEGIN END\n//\n",
|
||||
],
|
||||
[
|
||||
'name' => 'test_trigger',
|
||||
'table' => 'test_table',
|
||||
'action_timing' => 'AFTER',
|
||||
'event_manipulation' => 'INSERT',
|
||||
'definition' => 'BEGIN END',
|
||||
'definer' => 'definer@localhost',
|
||||
'full_trigger_name' => '`test_trigger`',
|
||||
'drop' => 'DROP TRIGGER IF EXISTS `test_trigger`',
|
||||
'create' => "CREATE TRIGGER `test_trigger` AFTER INSERT ON `test_table`\n FOR EACH ROW BEGIN END\n//\n",
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $triggers);
|
||||
}
|
||||
|
||||
public function testGetDetails2(): void
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['DisableIS'] = true;
|
||||
$dbiDummy = $this->createDbiDummy();
|
||||
$dbiDummy->addResult(
|
||||
"SHOW TRIGGERS FROM `test_db` LIKE 'test_table2';",
|
||||
[['a_trigger', 'UPDATE', 'test_table2', 'BEGIN END', 'BEFORE', 'definer2@localhost']],
|
||||
['Trigger', 'Event', 'Table', 'Statement', 'Timing', 'Definer'],
|
||||
);
|
||||
|
||||
$triggers = Triggers::getDetails($this->createDatabaseInterface($dbiDummy), 'test_db', 'test_table2', '$$');
|
||||
$expected = [
|
||||
[
|
||||
'name' => 'a_trigger',
|
||||
'table' => 'test_table2',
|
||||
'action_timing' => 'BEFORE',
|
||||
'event_manipulation' => 'UPDATE',
|
||||
'definition' => 'BEGIN END',
|
||||
'definer' => 'definer2@localhost',
|
||||
'full_trigger_name' => '`a_trigger`',
|
||||
'drop' => 'DROP TRIGGER IF EXISTS `a_trigger`',
|
||||
'create' => "CREATE TRIGGER `a_trigger` BEFORE UPDATE ON `test_table2`\n FOR EACH ROW BEGIN END\n$$\n",
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $triggers);
|
||||
}
|
||||
|
||||
/** @covers \PhpMyAdmin\Query\Generator */
|
||||
public function testGetDetails3(): void
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['DisableIS'] = false;
|
||||
$dbiDummy = $this->createDbiDummy();
|
||||
// phpcs:disable Generic.Files.LineLength.TooLong
|
||||
$dbiDummy->addResult(
|
||||
"SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'test_db'",
|
||||
[['test_db', 'test_trigger', 'DELETE', 'test_table', 'AFTER', 'BEGIN END', 'test_db', 'test_table', 'definer@localhost']],
|
||||
['TRIGGER_SCHEMA', 'TRIGGER_NAME', 'EVENT_MANIPULATION', 'EVENT_OBJECT_TABLE', 'ACTION_TIMING', 'ACTION_STATEMENT', 'EVENT_OBJECT_SCHEMA', 'EVENT_OBJECT_TABLE', 'DEFINER'],
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
$triggers = Triggers::getDetails($this->createDatabaseInterface($dbiDummy), 'test_db');
|
||||
$expected = [
|
||||
[
|
||||
'name' => 'test_trigger',
|
||||
'table' => 'test_table',
|
||||
'action_timing' => 'AFTER',
|
||||
'event_manipulation' => 'DELETE',
|
||||
'definition' => 'BEGIN END',
|
||||
'definer' => 'definer@localhost',
|
||||
'full_trigger_name' => '`test_trigger`',
|
||||
'drop' => 'DROP TRIGGER IF EXISTS `test_trigger`',
|
||||
'create' => "CREATE TRIGGER `test_trigger` AFTER DELETE ON `test_table`\n FOR EACH ROW BEGIN END\n//\n",
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $triggers);
|
||||
}
|
||||
|
||||
/** @covers \PhpMyAdmin\Query\Generator */
|
||||
public function testGetDetails4(): void
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['DisableIS'] = false;
|
||||
$dbiDummy = $this->createDbiDummy();
|
||||
// phpcs:disable Generic.Files.LineLength.TooLong
|
||||
$dbiDummy->addResult(
|
||||
"SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'test_db' AND EVENT_OBJECT_TABLE COLLATE utf8_bin = 'test_table';",
|
||||
[['test_db', 'test_trigger', 'DELETE', 'test_table', 'AFTER', 'BEGIN END', 'test_db', 'test_table', 'definer@localhost']],
|
||||
['TRIGGER_SCHEMA', 'TRIGGER_NAME', 'EVENT_MANIPULATION', 'EVENT_OBJECT_TABLE', 'ACTION_TIMING', 'ACTION_STATEMENT', 'EVENT_OBJECT_SCHEMA', 'EVENT_OBJECT_TABLE', 'DEFINER'],
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
$triggers = Triggers::getDetails($this->createDatabaseInterface($dbiDummy), 'test_db', 'test_table');
|
||||
$expected = [
|
||||
[
|
||||
'name' => 'test_trigger',
|
||||
'table' => 'test_table',
|
||||
'action_timing' => 'AFTER',
|
||||
'event_manipulation' => 'DELETE',
|
||||
'definition' => 'BEGIN END',
|
||||
'definer' => 'definer@localhost',
|
||||
'full_trigger_name' => '`test_trigger`',
|
||||
'drop' => 'DROP TRIGGER IF EXISTS `test_trigger`',
|
||||
'create' => "CREATE TRIGGER `test_trigger` AFTER DELETE ON `test_table`\n FOR EACH ROW BEGIN END\n//\n",
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $triggers);
|
||||
}
|
||||
}
|
||||
@ -2,9 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Selenium\Database;
|
||||
|
||||
use PhpMyAdmin\Tests\Selenium\TestBase;
|
||||
namespace PhpMyAdmin\Tests\Selenium;
|
||||
|
||||
/** @coversNothing */
|
||||
class TriggersTest extends TestBase
|
||||
@ -31,7 +31,6 @@ module.exports = [
|
||||
'database/search': rootPath + '/js/src/database/search.ts',
|
||||
'database/structure': rootPath + '/js/src/database/structure.ts',
|
||||
'database/tracking': rootPath + '/js/src/database/tracking.ts',
|
||||
'database/triggers': rootPath + '/js/src/database/triggers.ts',
|
||||
'designer/init': rootPath + '/js/src/designer/init.ts',
|
||||
'drag_drop_import': rootPath + '/js/src/drag_drop_import.ts',
|
||||
'error_report': rootPath + '/js/src/error_report.ts',
|
||||
@ -77,6 +76,7 @@ module.exports = [
|
||||
'transformations/sql_editor': rootPath + '/js/src/transformations/sql_editor.ts',
|
||||
'transformations/xml': rootPath + '/js/src/transformations/xml.ts',
|
||||
'transformations/xml_editor': rootPath + '/js/src/transformations/xml_editor.ts',
|
||||
'triggers': rootPath + '/js/src/triggers.ts',
|
||||
'u2f': rootPath + '/js/src/u2f.ts',
|
||||
'validator-messages': rootPath + '/js/src/validator-messages.ts',
|
||||
'webauthn': rootPath + '/js/src/webauthn.ts',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user