Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
This commit is contained in:
commit
1d9ef02608
@ -36,6 +36,8 @@ phpMyAdmin - ChangeLog
|
||||
- bug #3354356 [interface] Timepicker does not work in AJAX dialogs
|
||||
+ AJAX for table Structure Indexes Edit
|
||||
+ AJAX for table Structure column Change
|
||||
+ [interface] Improved support for events
|
||||
+ [interface] Improved support for triggers
|
||||
|
||||
3.4.4.0 (not yet released)
|
||||
- bug #3323060 [parser] SQL parser breaks AJAX requests if query has unclosed quotes
|
||||
|
||||
@ -2143,7 +2143,7 @@ setfacl -d -m "g:www-data:rwx" tmp
|
||||
identify what they mean.
|
||||
</dd>
|
||||
|
||||
<dt id="cfg_ShowDisplayDir">$cfg['ShowDisplayDir'] boolean</dt>
|
||||
<dt id="cfg_ShowDisplayDirection">$cfg['ShowDisplayDirection'] boolean</dt>
|
||||
<dd>
|
||||
Defines whether or not type display direction option is shown
|
||||
when browsing a table.
|
||||
|
||||
@ -1,40 +1,33 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Events management.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Include required files
|
||||
*/
|
||||
require_once './libraries/common.inc.php';
|
||||
require_once './libraries/common.lib.php';
|
||||
|
||||
/**
|
||||
* Include JavaScript libraries
|
||||
*/
|
||||
$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
|
||||
$GLOBALS['js_include'][] = 'db_events.js';
|
||||
$GLOBALS['js_include'][] = 'jquery/timepicker.js';
|
||||
$GLOBALS['js_include'][] = 'rte/common.js';
|
||||
$GLOBALS['js_include'][] = 'rte/events.js';
|
||||
|
||||
/**
|
||||
* Create labels for the list
|
||||
* Include all other files
|
||||
*/
|
||||
$titles = PMA_buildActionTitles();
|
||||
require_once './libraries/rte/rte_events.lib.php';
|
||||
|
||||
/**
|
||||
* Displays the header
|
||||
* Do the magic
|
||||
*/
|
||||
require_once './libraries/db_common.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the tabs
|
||||
*/
|
||||
require_once './libraries/db_info.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the list of events
|
||||
*/
|
||||
require_once './libraries/db_events.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the footer
|
||||
*/
|
||||
require './libraries/footer.inc.php';
|
||||
|
||||
require_once './libraries/rte/rte_main.inc.php';
|
||||
|
||||
?>
|
||||
|
||||
428
db_routines.php
428
db_routines.php
@ -11,7 +11,6 @@
|
||||
*/
|
||||
require_once './libraries/common.inc.php';
|
||||
require_once './libraries/common.lib.php';
|
||||
require_once './libraries/db_routines.lib.php';
|
||||
require_once './libraries/mysql_charsets.lib.php';
|
||||
require_once './libraries/data_mysql.inc.php';
|
||||
|
||||
@ -20,432 +19,17 @@ require_once './libraries/data_mysql.inc.php';
|
||||
*/
|
||||
$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
|
||||
$GLOBALS['js_include'][] = 'jquery/timepicker.js';
|
||||
$GLOBALS['js_include'][] = 'db_routines.js';
|
||||
$GLOBALS['js_include'][] = 'rte/common.js';
|
||||
$GLOBALS['js_include'][] = 'rte/routines.js';
|
||||
|
||||
/**
|
||||
* Create labels for the list
|
||||
* Include all other files
|
||||
*/
|
||||
$titles = PMA_buildActionTitles();
|
||||
|
||||
if ($GLOBALS['is_ajax_request'] != true) {
|
||||
/**
|
||||
* Displays the header
|
||||
*/
|
||||
require_once './libraries/db_common.inc.php';
|
||||
/**
|
||||
* Displays the tabs
|
||||
*/
|
||||
require_once './libraries/db_info.inc.php';
|
||||
} else {
|
||||
if (strlen($db)) {
|
||||
PMA_DBI_select_db($db);
|
||||
if (! isset($url_query)) {
|
||||
$url_query = PMA_generate_common_url($db);
|
||||
}
|
||||
}
|
||||
}
|
||||
require_once './libraries/rte/rte_routines.lib.php';
|
||||
|
||||
/**
|
||||
* Process all requests
|
||||
* Do the magic
|
||||
*/
|
||||
|
||||
// Some definitions
|
||||
$param_directions = array('IN',
|
||||
'OUT',
|
||||
'INOUT');
|
||||
$param_opts_num = array('UNSIGNED',
|
||||
'ZEROFILL',
|
||||
'UNSIGNED ZEROFILL');
|
||||
$param_sqldataaccess = array('NO SQL',
|
||||
'CONTAINS SQL',
|
||||
'READS SQL DATA',
|
||||
'MODIFIES SQL DATA');
|
||||
|
||||
/**
|
||||
* Generate the conditional classes that will be used to attach jQuery events to links.
|
||||
*/
|
||||
$ajax_class = array(
|
||||
'add' => '',
|
||||
'edit' => '',
|
||||
'exec' => '',
|
||||
'drop' => '',
|
||||
'export' => ''
|
||||
);
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$ajax_class['add'] = 'class="add_routine_anchor"';
|
||||
$ajax_class['edit'] = 'class="edit_routine_anchor"';
|
||||
$ajax_class['exec'] = 'class="exec_routine_anchor"';
|
||||
$ajax_class['drop'] = 'class="drop_routine_anchor"';
|
||||
$ajax_class['export'] = 'class="export_routine_anchor"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep a list of errors that occured while processing an 'Add' or 'Edit' operation.
|
||||
*/
|
||||
$routine_errors = array();
|
||||
|
||||
/**
|
||||
* Handle all user requests other than the default of listing routines
|
||||
*/
|
||||
if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['routine_name'])) {
|
||||
// Build the queries
|
||||
$routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name'], false);
|
||||
if ($routine !== false) {
|
||||
$queries = array();
|
||||
$end_query = array();
|
||||
$args = array();
|
||||
for ($i=0; $i<$routine['num_params']; $i++) {
|
||||
if (isset($_REQUEST['params'][$routine['param_name'][$i]])) {
|
||||
$value = $_REQUEST['params'][$routine['param_name'][$i]];
|
||||
if (is_array($value)) { // is SET type
|
||||
$value = implode(',', $value);
|
||||
}
|
||||
$value = PMA_sqlAddSlashes($value);
|
||||
if (! empty($_REQUEST['funcs'][$routine['param_name'][$i]])
|
||||
&& in_array($_REQUEST['funcs'][$routine['param_name'][$i]], $cfg['Functions'])) {
|
||||
$queries[] = "SET @p$i={$_REQUEST['funcs'][$routine['param_name'][$i]]}('$value');\n";
|
||||
} else {
|
||||
$queries[] = "SET @p$i='$value';\n";
|
||||
}
|
||||
$args[] = "@p$i";
|
||||
} else {
|
||||
$args[] = "@p$i";
|
||||
}
|
||||
if ($routine['type'] == 'PROCEDURE') {
|
||||
if ($routine['param_dir'][$i] == 'OUT' || $routine['param_dir'][$i] == 'INOUT') {
|
||||
$end_query[] = "@p$i AS " . PMA_backquote($routine['param_name'][$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($routine['type'] == 'PROCEDURE') {
|
||||
$queries[] = "CALL " . PMA_backquote($routine['name'])
|
||||
. "(" . implode(', ', $args) . ");\n";
|
||||
if (count($end_query)) {
|
||||
$queries[] = "SELECT " . implode(', ', $end_query) . ";\n";
|
||||
}
|
||||
} else {
|
||||
$queries[] = "SELECT " . PMA_backquote($routine['name'])
|
||||
. "(" . implode(', ', $args) . ") "
|
||||
. "AS " . PMA_backquote($routine['name']) . ";\n";
|
||||
}
|
||||
// Execute the queries
|
||||
$affected = 0;
|
||||
$result = null;
|
||||
$outcome = true;
|
||||
foreach ($queries as $num => $query) {
|
||||
$resource = PMA_DBI_try_query($query);
|
||||
if ($resource === false) {
|
||||
$outcome = false;
|
||||
break;
|
||||
}
|
||||
while (true) {
|
||||
if(! PMA_DBI_more_results()) {
|
||||
break;
|
||||
}
|
||||
PMA_DBI_next_result();
|
||||
}
|
||||
if (substr($query, 0, 6) == 'SELECT') {
|
||||
$result = $resource;
|
||||
} else if (substr($query, 0, 4) == 'CALL') {
|
||||
$affected = PMA_DBI_affected_rows() - PMA_DBI_num_rows($resource);
|
||||
}
|
||||
}
|
||||
// Generate output
|
||||
if ($outcome) {
|
||||
$message = __('Your SQL query has been executed successfully');
|
||||
if ($routine['type'] == 'PROCEDURE') {
|
||||
$message .= '<br />';
|
||||
$message .= sprintf(_ngettext('%d row affected by the last statement inside the procedure', '%d rows affected by the last statement inside the procedure', $affected), $affected);
|
||||
}
|
||||
$message = PMA_message::success($message);
|
||||
// Pass the SQL queries through the "pretty printer"
|
||||
$output = '<code class="sql" style="margin-bottom: 1em;">';
|
||||
$output .= PMA_SQP_formatHtml(PMA_SQP_parse(implode($queries)));
|
||||
$output .= '</code>';
|
||||
// Display results
|
||||
if ($result) {
|
||||
$output .= "<fieldset><legend>";
|
||||
$output .= sprintf(__('Execution results of routine %s'),
|
||||
PMA_backquote(htmlspecialchars($routine['name'])));
|
||||
$output .= "</legend>";
|
||||
$output .= "<table><tr>";
|
||||
foreach (PMA_DBI_get_fields_meta($result) as $key => $field) {
|
||||
$output .= "<th>" . htmlspecialchars($field->name) . "</th>";
|
||||
}
|
||||
$output .= "</tr>";
|
||||
// Stored routines can only ever return ONE ROW.
|
||||
$data = PMA_DBI_fetch_single_row($result);
|
||||
foreach ($data as $key => $value) {
|
||||
if ($value === null) {
|
||||
$value = '<i>NULL</i>';
|
||||
} else {
|
||||
$value = htmlspecialchars($value);
|
||||
}
|
||||
$output .= "<td class='odd'>" . $value . "</td>";
|
||||
}
|
||||
$output .= "</table></fieldset>";
|
||||
} else {
|
||||
$notice = __('MySQL returned an empty result set (i.e. zero rows).');
|
||||
$output .= PMA_message::notice($notice)->getDisplay();
|
||||
}
|
||||
} else {
|
||||
$output = '';
|
||||
$message = PMA_message::error(sprintf(__('The following query has failed: "%s"'), $query) . '<br /><br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null));
|
||||
}
|
||||
// Print/send output
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array('dialog' => false);
|
||||
PMA_ajaxResponse($message->getDisplay() . $output, $message->isSuccess(), $extra_data);
|
||||
} else {
|
||||
echo $message->getDisplay() . $output;
|
||||
if ($message->isError()) {
|
||||
// At least one query has failed, so shouldn't
|
||||
// execute any more queries, so we quit.
|
||||
exit;
|
||||
}
|
||||
unset($_POST);
|
||||
// Now deliberately fall through to displaying the routines list
|
||||
}
|
||||
} else {
|
||||
$message = __('Error in processing request') . ' : '
|
||||
. sprintf(__('No routine with name %1$s found in database %2$s'),
|
||||
htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])),
|
||||
htmlspecialchars(PMA_backquote($db)));
|
||||
$message = PMA_message::error($message);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
PMA_ajaxResponse($message, $message->isSuccess());
|
||||
} else {
|
||||
echo $message->getDisplay();
|
||||
unset($_POST);
|
||||
}
|
||||
}
|
||||
} else if (! empty($_GET['execute_dialog']) && ! empty($_GET['routine_name'])) {
|
||||
/**
|
||||
* Display the execute form for a routine.
|
||||
*/
|
||||
$routine = PMA_RTN_getRoutineDataFromName($db, $_GET['routine_name'], false);
|
||||
if ($routine !== false) {
|
||||
$form = PMA_RTN_getExecuteForm($routine, $GLOBALS['is_ajax_request']);
|
||||
if ($GLOBALS['is_ajax_request'] == true) {
|
||||
$extra_data = array();
|
||||
$extra_data['dialog'] = true;
|
||||
$extra_data['title'] = __("Execute routine") . " ";
|
||||
$extra_data['title'] .= PMA_backquote(htmlentities($_GET['routine_name'], ENT_QUOTES));
|
||||
PMA_ajaxResponse($form, true, $extra_data);
|
||||
} else {
|
||||
echo "\n\n<h2>" . __("Execute routine") . "</h2>\n\n";
|
||||
echo $form;
|
||||
require './libraries/footer.inc.php';
|
||||
// exit;
|
||||
}
|
||||
} else if (($GLOBALS['is_ajax_request'] == true)) {
|
||||
$message = __('Error in processing request') . ' : '
|
||||
. sprintf(__('No routine with name %1$s found in database %2$s'),
|
||||
htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])),
|
||||
htmlspecialchars(PMA_backquote($db)));
|
||||
$message = PMA_message::error($message);
|
||||
PMA_ajaxResponse($message, false);
|
||||
}
|
||||
} else if (! empty($_GET['exportroutine']) && ! empty($_GET['routine_name'])) {
|
||||
/**
|
||||
* Display the export for a routine.
|
||||
*/
|
||||
$routine_name = htmlspecialchars(PMA_backquote($_GET['routine_name']));
|
||||
$routine_type = PMA_DBI_fetch_value("SELECT ROUTINE_TYPE "
|
||||
. "FROM INFORMATION_SCHEMA.ROUTINES "
|
||||
. "WHERE ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' "
|
||||
. "AND SPECIFIC_NAME='" . PMA_sqlAddSlashes($_GET['routine_name']) . "';");
|
||||
if (! empty($routine_type) && $create_proc = PMA_DBI_get_definition($db, $routine_type, $_GET['routine_name'])) {
|
||||
$create_proc = '<textarea cols="40" rows="15" style="width: 100%;">' . htmlspecialchars($create_proc) . '</textarea>';
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array('title' => sprintf(__('Export of routine %s'), $routine_name));
|
||||
PMA_ajaxResponse($create_proc, true, $extra_data);
|
||||
} else {
|
||||
echo '<fieldset>' . "\n"
|
||||
. ' <legend>' . sprintf(__('Export of routine %s'), $routine_name) . '</legend>' . "\n"
|
||||
. $create_proc . "\n"
|
||||
. '</fieldset>';
|
||||
}
|
||||
} else {
|
||||
$response = __('Error in processing request') . ' : '
|
||||
. sprintf(__('No routine with name %1$s found in database %2$s'),
|
||||
$routine_name, htmlspecialchars(PMA_backquote($db)));
|
||||
$response = PMA_message::error($response);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
PMA_ajaxResponse($response, false);
|
||||
} else {
|
||||
$response->display();
|
||||
}
|
||||
}
|
||||
} else if (! empty($_REQUEST['routine_process_addroutine']) || ! empty($_REQUEST['routine_process_editroutine'])) {
|
||||
/**
|
||||
* Handle a request to create/edit a routine
|
||||
*/
|
||||
$sql_query = '';
|
||||
$routine_query = PMA_RTN_getQueryFromRequest();
|
||||
if (! count($routine_errors)) { // set by PMA_RTN_getQueryFromRequest()
|
||||
// Execute the created query
|
||||
if (! empty($_REQUEST['routine_process_editroutine'])) {
|
||||
if (! in_array($_REQUEST['routine_original_type'], array('PROCEDURE', 'FUNCTION'))) {
|
||||
$routine_errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_original_type']));
|
||||
} else {
|
||||
// Backup the old routine, in case something goes wrong
|
||||
$create_routine = PMA_DBI_get_definition($db, $_REQUEST['routine_original_type'], $_REQUEST['routine_original_name']);
|
||||
$drop_routine = "DROP {$_REQUEST['routine_original_type']} " . PMA_backquote($_REQUEST['routine_original_name']) . ";\n";
|
||||
$result = PMA_DBI_try_query($drop_routine);
|
||||
if (! $result) {
|
||||
$routine_errors[] = sprintf(__('The following query has failed: "%s"'), $drop_routine) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$result = PMA_DBI_try_query($routine_query);
|
||||
if (! $result) {
|
||||
$routine_errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
// We dropped the old routine, but were unable to create the new one
|
||||
// Try to restore the backup query
|
||||
$result = PMA_DBI_try_query($create_routine);
|
||||
if (! $result) {
|
||||
// OMG, this is really bad! We dropped the query, failed to create a new one
|
||||
// and now even the backup query does not execute!
|
||||
// This should not happen, but we better handle this just in case.
|
||||
$routine_errors[] = __('Sorry, we failed to restore the dropped routine.') . '<br />'
|
||||
. __('The backed up query was:') . "\"$create_routine\"" . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
}
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Routine %1$s has been modified.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['routine_name']));
|
||||
$sql_query = $drop_routine . $routine_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 'Add a new routine' mode
|
||||
$result = PMA_DBI_try_query($routine_query);
|
||||
if (! $result) {
|
||||
$routine_errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '<br /><br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Routine %1$s has been created.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['routine_name']));
|
||||
$sql_query = $routine_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($routine_errors)) {
|
||||
$message = PMA_Message::error(__('<b>One or more errors have occured while processing your request:</b>'));
|
||||
$message->addString('<ul>');
|
||||
foreach ($routine_errors as $num => $string) {
|
||||
$message->addString('<li>' . $string . '</li>');
|
||||
}
|
||||
$message->addString('</ul>');
|
||||
}
|
||||
|
||||
$output = PMA_showMessage($message, $sql_query);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array();
|
||||
if ($message->isSuccess()) {
|
||||
$columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`, `DTD_IDENTIFIER`, `ROUTINE_DEFINITION`";
|
||||
$where = "ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' AND ROUTINE_NAME='" . PMA_sqlAddSlashes($_REQUEST['routine_name']) . "'";
|
||||
$routine = PMA_DBI_fetch_single_row("SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE $where;");
|
||||
$extra_data['name'] = htmlspecialchars(strtoupper($_REQUEST['routine_name']));
|
||||
$extra_data['new_row'] = PMA_RTN_getRowForRoutinesList($routine, 0, true);
|
||||
$response = $output;
|
||||
} else {
|
||||
$response = $message;
|
||||
}
|
||||
PMA_ajaxResponse($response, $message->isSuccess(), $extra_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a form used to add/edit a routine, if necessary
|
||||
*/
|
||||
if (count($routine_errors) || ( empty($_REQUEST['routine_process_addroutine']) && empty($_REQUEST['routine_process_editroutine']) &&
|
||||
(! empty($_REQUEST['addroutine']) || ! empty($_REQUEST['editroutine'])
|
||||
|| ! empty($_REQUEST['routine_addparameter']) || ! empty($_REQUEST['routine_removeparameter'])
|
||||
|| ! empty($_REQUEST['routine_changetype'])))) { // FIXME: this must be simpler than that
|
||||
// Handle requests to add/remove parameters and changing routine type
|
||||
// This is necessary when JS is disabled
|
||||
$operation = '';
|
||||
if (! empty($_REQUEST['routine_addparameter'])) {
|
||||
$operation = 'add';
|
||||
} else if (! empty($_REQUEST['routine_removeparameter'])) {
|
||||
$operation = 'remove';
|
||||
} else if (! empty($_REQUEST['routine_changetype'])) {
|
||||
$operation = 'change';
|
||||
}
|
||||
// Get the data for the form (if any)
|
||||
if (! empty($_REQUEST['addroutine'])) {
|
||||
$title = __("Create routine");
|
||||
$routine = PMA_RTN_getRoutineDataFromRequest();
|
||||
$mode = 'add';
|
||||
} else if (! empty($_REQUEST['editroutine'])) {
|
||||
$title = __("Edit routine");
|
||||
if (! $operation && ! empty($_REQUEST['routine_name']) && empty($_REQUEST['routine_process_editroutine'])) {
|
||||
$routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name']);
|
||||
if ($routine !== false) {
|
||||
$routine['original_name'] = $routine['name'];
|
||||
$routine['original_type'] = $routine['type'];
|
||||
}
|
||||
} else {
|
||||
$routine = PMA_RTN_getRoutineDataFromRequest();
|
||||
}
|
||||
$mode = 'edit';
|
||||
}
|
||||
if ($routine !== false) {
|
||||
// Show form
|
||||
$editor = PMA_RTN_getEditorForm($mode, $operation, $routine, $routine_errors, $GLOBALS['is_ajax_request']);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$template = PMA_RTN_getParameterRow();
|
||||
$extra_data = array('title' => $title, 'param_template' => $template, 'type' => $routine['type']);
|
||||
PMA_ajaxResponse($editor, true, $extra_data);
|
||||
}
|
||||
echo "\n\n<h2>$title</h2>\n\n$editor";
|
||||
require './libraries/footer.inc.php';
|
||||
// exit;
|
||||
} else {
|
||||
$message = __('Error in processing request') . ' : '
|
||||
. sprintf(__('No routine with name %1$s found in database %2$s'),
|
||||
htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])),
|
||||
htmlspecialchars(PMA_backquote($db)));
|
||||
$message = PMA_message::error($message);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
PMA_ajaxResponse($message, false);
|
||||
} else {
|
||||
$message->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of available routines
|
||||
*/
|
||||
echo PMA_RTN_getRoutinesList();
|
||||
|
||||
/**
|
||||
* Display the form for adding a new routine, if the user has the privileges.
|
||||
*/
|
||||
echo PMA_RTN_getAddRoutineLink();
|
||||
|
||||
/**
|
||||
* Display a warning for users with PHP's old "mysql" extension.
|
||||
*/
|
||||
if ($GLOBALS['cfg']['Server']['extension'] === 'mysql') {
|
||||
trigger_error(__('You are using PHP\'s deprecated \'mysql\' extension, '
|
||||
. 'which is not capable of handling multi queries. '
|
||||
. '<b>The execution of some stored routines may fail!</b> '
|
||||
. 'Please use the improved \'mysqli\' extension to '
|
||||
. 'avoid any problems.'), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if ($GLOBALS['is_ajax_request'] != true) {
|
||||
/**
|
||||
* Displays the footer
|
||||
*/
|
||||
require './libraries/footer.inc.php';
|
||||
}
|
||||
require_once './libraries/rte/rte_main.inc.php';
|
||||
|
||||
?>
|
||||
|
||||
@ -1,38 +1,32 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Triggers management.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Include required files
|
||||
*/
|
||||
require_once './libraries/common.inc.php';
|
||||
require_once './libraries/common.lib.php';
|
||||
|
||||
/**
|
||||
* Include JavaScript libraries
|
||||
*/
|
||||
$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
|
||||
$GLOBALS['js_include'][] = 'display_triggers.js';
|
||||
$GLOBALS['js_include'][] = 'rte/common.js';
|
||||
$GLOBALS['js_include'][] = 'rte/triggers.js';
|
||||
|
||||
/**
|
||||
* Create labels for the list
|
||||
* Include all other files
|
||||
*/
|
||||
$titles = PMA_buildActionTitles();
|
||||
require_once './libraries/rte/rte_triggers.lib.php';
|
||||
|
||||
/**
|
||||
* Displays the header
|
||||
* Do the magic
|
||||
*/
|
||||
require_once './libraries/db_common.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the tabs
|
||||
*/
|
||||
require_once './libraries/db_info.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the list of triggers
|
||||
*/
|
||||
require_once './libraries/display_triggers.inc.php';
|
||||
|
||||
/**
|
||||
* Displays the footer
|
||||
*/
|
||||
require './libraries/footer.inc.php';
|
||||
|
||||
require_once './libraries/rte/rte_main.inc.php';
|
||||
|
||||
?>
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
@ -1,568 +0,0 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* Validate routine editor form fields.
|
||||
*
|
||||
* @param syntaxHiglighter an object containing the reference to the
|
||||
* codemirror editor. This will be used to
|
||||
* focus the form on the codemirror editor
|
||||
* if it contains invalid data.
|
||||
*/
|
||||
function validateRoutineEditor(syntaxHiglighter) {
|
||||
/**
|
||||
* @var inputname Will contain the value of the name
|
||||
* attribute of input fields being checked.
|
||||
*/
|
||||
var inputname = '';
|
||||
/**
|
||||
* @var $elm a jQuery object containing the reference
|
||||
* to an element that is being validated.
|
||||
*/
|
||||
var $elm = null;
|
||||
/**
|
||||
* @var isError Stores the outcome of the validation.
|
||||
*/
|
||||
var isError = false;
|
||||
|
||||
$elm = $('.rte_table').last().find('input[name=routine_name]');
|
||||
if ($elm.val() == '') {
|
||||
$elm.focus();
|
||||
isError = true;
|
||||
} else if ($elm.val().length > 64) {
|
||||
alert(PMA_messages['strValueTooLong']);
|
||||
$elm.focus().select();
|
||||
return false;
|
||||
}
|
||||
if (! isError) {
|
||||
$elm = $('.rte_table').find('textarea[name=routine_definition]');
|
||||
if ($elm.val() == '') {
|
||||
syntaxHiglighter.focus();
|
||||
isError = true;
|
||||
}
|
||||
}
|
||||
if (! isError) {
|
||||
$('.routine_params_table').last().find('tr').each(function() {
|
||||
if (! isError) {
|
||||
$(this).find(':input').each(function() {
|
||||
inputname = $(this).attr('name');
|
||||
if (inputname.substr(0, 17) == 'routine_param_dir' ||
|
||||
inputname.substr(0, 18) == 'routine_param_name' ||
|
||||
inputname.substr(0, 18) == 'routine_param_type') {
|
||||
if ($(this).val() == '') {
|
||||
$(this).focus();
|
||||
isError = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (! isError) {
|
||||
// SET, ENUM, VARCHAR and VARBINARY fields must have length/values
|
||||
$('.routine_params_table').last().find('tr').each(function() {
|
||||
var $inputtyp = $(this).find('select[name^=routine_param_type]');
|
||||
var $inputlen = $(this).find('input[name^=routine_param_length]');
|
||||
if ($inputtyp.length && $inputlen.length) {
|
||||
if (($inputtyp.val() == 'ENUM' || $inputtyp.val() == 'SET' || $inputtyp.val().substr(0,3) == 'VAR')
|
||||
&& $inputlen.val() == '') {
|
||||
$inputlen.focus();
|
||||
isError = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (! isError && $('select[name=routine_type]').find(':selected').val() == 'FUNCTION') {
|
||||
// The length/values of return variable for functions must
|
||||
// be set, if the type is SET, ENUM, VARCHAR or VARBINARY.
|
||||
var $returntyp = $('select[name=routine_returntype]');
|
||||
var $returnlen = $('input[name=routine_returnlength]');
|
||||
if (($returntyp.val() == 'ENUM' || $returntyp.val() == 'SET' || $returntyp.val().substr(0,3) == 'VAR')
|
||||
&& $returnlen.val() == '') {
|
||||
$returnlen.focus();
|
||||
isError = true;
|
||||
}
|
||||
}
|
||||
if (! isError && $('select[name=routine_type]').find(':selected').val() == 'FUNCTION') {
|
||||
if ($('.rte_table').find('textarea[name=routine_definition]').val().toLowerCase().indexOf('return') < 0) {
|
||||
syntaxHiglighter.focus();
|
||||
alert(PMA_messages['MissingReturn']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (! isError) {
|
||||
$elm = $('.rte_table').last().find('input[name=routine_comment]');
|
||||
if ($elm.val().length > 64) {
|
||||
alert(PMA_messages['strValueTooLong']);
|
||||
$elm.focus().select();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (! isError) {
|
||||
return true;
|
||||
} else {
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
} // end validateRoutineEditor()
|
||||
|
||||
/**
|
||||
* Enable/disable the "options" dropdown and "length" input for
|
||||
* parameters and the return variable in the routine editor
|
||||
* as necessary.
|
||||
*
|
||||
* @param $type a jQuery object containing the reference
|
||||
* to the "Type" dropdown box
|
||||
* @param $len a jQuery object containing the reference
|
||||
* to the "Length" input box
|
||||
* @param $text a jQuery object containing the reference
|
||||
* to the dropdown box with options for
|
||||
* parameters of text type
|
||||
* @param $num a jQuery object containing the reference
|
||||
* to the dropdown box with options for
|
||||
* parameters of numeric type
|
||||
*/
|
||||
function setOptionsForParameter($type, $len, $text, $num) {
|
||||
// Process for parameter options
|
||||
switch ($type.val()) {
|
||||
case 'TINYINT':
|
||||
case 'SMALLINT':
|
||||
case 'MEDIUMINT':
|
||||
case 'INT':
|
||||
case 'BIGINT':
|
||||
case 'DECIMAL':
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
case 'REAL':
|
||||
$text.parent().hide();
|
||||
$num.parent().show();
|
||||
break;
|
||||
case 'TINYTEXT':
|
||||
case 'TEXT':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGTEXT':
|
||||
case 'CHAR':
|
||||
case 'VARCHAR':
|
||||
case 'SET':
|
||||
case 'ENUM':
|
||||
$text.parent().show();
|
||||
$text.show();
|
||||
$num.parent().hide();
|
||||
break;
|
||||
default:
|
||||
$text.parent().show();
|
||||
$text.hide();
|
||||
$num.parent().hide();
|
||||
break;
|
||||
}
|
||||
// Process for parameter length
|
||||
switch ($type.val()) {
|
||||
case 'DATE':
|
||||
case 'DATETIME':
|
||||
case 'TIME':
|
||||
case 'TINYBLOB':
|
||||
case 'TINYTEXT':
|
||||
case 'BLOB':
|
||||
case 'TEXT':
|
||||
case 'MEDIUMBLOB':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGBLOB':
|
||||
case 'LONGTEXT':
|
||||
$len.hide();
|
||||
break;
|
||||
default:
|
||||
$len.show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Routines functionalities.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
/**
|
||||
* @var $ajaxDialog jQuery object containing the reference to the
|
||||
* dialog that contains the routine editor.
|
||||
*/
|
||||
var $ajaxDialog = null;
|
||||
/**
|
||||
* @var param_template This variable contains the template for one row
|
||||
* of the parameters table that is attached to the
|
||||
* dialog when a new parameter is added.
|
||||
*/
|
||||
var param_template = '';
|
||||
/**
|
||||
* @var syntaxHiglighter Reference to the codemirror editor.
|
||||
*/
|
||||
var syntaxHiglighter = null;
|
||||
/**
|
||||
* @var button_options Object containing options for jQueryUI dialog buttons
|
||||
*/
|
||||
var button_options = {};
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Add/Edit routine functionality.
|
||||
*
|
||||
* @uses PMA_ajaxShowMessage()
|
||||
* @uses PMA_ajaxRemoveMessage()
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('.add_routine_anchor, .edit_routine_anchor').live('click', function(event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $edit_row jQuery object containing the reference to
|
||||
* the row of the the routine being edited
|
||||
* from the list of routines .
|
||||
*/
|
||||
var $edit_row = null;
|
||||
if ($(this).hasClass('edit_routine_anchor')) {
|
||||
// Remeber the row of the routine being edited for later,
|
||||
// so that if the edit is successful, we can replace the
|
||||
// row with info about the modified routine.
|
||||
$edit_row = $(this).parents('tr');
|
||||
}
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user.
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function(data) {
|
||||
if(data.success == true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
button_options[PMA_messages['strGo']] = function() {
|
||||
syntaxHiglighter.save();
|
||||
// Validate editor and submit request, if passed.
|
||||
if (validateRoutineEditor(syntaxHiglighter)) {
|
||||
/**
|
||||
* @var data Form data to be sent in the AJAX request.
|
||||
*/
|
||||
var data = $('.rte_form').last().serialize();
|
||||
$msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
$.post('db_routines.php', data, function (data) {
|
||||
if(data.success == true) {
|
||||
// Routine created successfully
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
PMA_slidingMessage(data.message);
|
||||
$ajaxDialog.dialog('close');
|
||||
// If we are in 'edit' mode, we must remove the reference to the old row.
|
||||
if (mode == 'edit') {
|
||||
$edit_row.remove();
|
||||
}
|
||||
// Insert the new row at the correct location in the list of routines
|
||||
/**
|
||||
* @var text Contains the name of a routine from the list
|
||||
* that is used in comparisons to find the correct
|
||||
* location where to insert a new row.
|
||||
*/
|
||||
var text = '';
|
||||
/**
|
||||
* @var inserted Whether a new has been inserted
|
||||
* in the list of routines or not.
|
||||
*/
|
||||
var inserted = false;
|
||||
$('table.data').find('tr').each(function() {
|
||||
text = $(this).children('td').eq(0).find('strong').text().toUpperCase();
|
||||
if (text != '' && text > data.name) {
|
||||
$(this).before(data.new_row);
|
||||
inserted = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (! inserted) {
|
||||
$('table.data').append(data.new_row);
|
||||
}
|
||||
// Fade-in the new row
|
||||
$('.ajaxInsert').show('slow').removeClass('ajaxInsert');
|
||||
// Now we have inserted the row at the correct position, but surely
|
||||
// at least some row classes are wrong now. So we will itirate
|
||||
// throught all rows and assign correct classes to them.
|
||||
/**
|
||||
* @var ct Count of processed rows.
|
||||
*/
|
||||
var ct = 0;
|
||||
$('table.data').find('tr').has('td').each(function() {
|
||||
rowclass = (ct % 2 == 0) ? 'even' : 'odd';
|
||||
$(this).removeClass().addClass(rowclass);
|
||||
ct++;
|
||||
});
|
||||
// If this is the first routine being added, remove the
|
||||
// "No routines" message and show the list of routines.
|
||||
if ($('table.data').find('tr').has('td').length > 0 && $('#nothing2display').is(':visible')) {
|
||||
$('#nothing2display').hide("slow", function () {
|
||||
$('table.data').show("slow");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
} // end of function that handles the submission of the Editor
|
||||
button_options[PMA_messages['strClose']] = function() {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
$ajaxDialog = $('<div>'+data.message+'</div>').dialog({
|
||||
width: 700, // TODO: make a better decision about the size
|
||||
height: 550, // of the dialog based on the size of the viewport
|
||||
buttons: button_options,
|
||||
title: data.title,
|
||||
modal: true,
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$ajaxDialog.find('input[name=routine_name]').focus();
|
||||
/**
|
||||
* @var mode Used to remeber whether the editor is in
|
||||
* "Edit Routine" or "Add Routine" mode.
|
||||
*/
|
||||
var mode = 'add';
|
||||
if ($('input[name=routine_process_editroutine]').length > 0) {
|
||||
mode = 'edit';
|
||||
}
|
||||
// Cache the template for a parameter table row
|
||||
param_template = data.param_template;
|
||||
// Make adjustments in the dialog to make it AJAX compatible
|
||||
$('.routine_param_remove').show();
|
||||
$('input[name=routine_removeparameter]').remove();
|
||||
$('input[name=routine_addparameter]').css('width', '100%');
|
||||
// Enable/disable the 'options' dropdowns for parameters as necessary
|
||||
$('.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1');
|
||||
$('.routine_params_table').last().find('tr').has('td').each(function() {
|
||||
setOptionsForParameter(
|
||||
$(this).find('select[name^=routine_param_type]'),
|
||||
$(this).find('input[name^=routine_param_length]'),
|
||||
$(this).find('select[name^=routine_param_opts_text]'),
|
||||
$(this).find('select[name^=routine_param_opts_num]')
|
||||
);
|
||||
});
|
||||
// Enable/disable the 'options' dropdowns for function return value as necessary
|
||||
setOptionsForParameter(
|
||||
$('.rte_table').last().find('select[name=routine_returntype]'),
|
||||
$('.rte_table').last().find('input[name=routine_returnlength]'),
|
||||
$('.rte_table').last().find('select[name=routine_returnopts_text]'),
|
||||
$('.rte_table').last().find('select[name=routine_returnopts_num]')
|
||||
);
|
||||
// Attach syntax highlited editor to routine definition
|
||||
/**
|
||||
* @var $elm jQuery object containing the reference to
|
||||
* the "Routine Definition" textarea.
|
||||
*/
|
||||
var $elm = $('textarea[name=routine_definition]').last();
|
||||
/**
|
||||
* @var opts Options to pass to the codemirror editor.
|
||||
*/
|
||||
var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"};
|
||||
syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts);
|
||||
// Hack to prevent the syntax highlighter from expanding beyond dialog boundries
|
||||
$('.CodeMirror-scroll').find('div').first().css('width', '1px');
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}) // end $.get()
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Add parameter to routine" functionality.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('input[name=routine_addparameter]').live('click', function(event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $routine_params_table jQuery object containing the reference
|
||||
* to the routine parameters table.
|
||||
*/
|
||||
var $routine_params_table = $('.routine_params_table').last();
|
||||
/**
|
||||
* @var $new_param_row A string containing the HTML code for the
|
||||
* new row for the routine paramaters table.
|
||||
*/
|
||||
var new_param_row = param_template.replace(/%s/g, $routine_params_table.find('tr').length-1);
|
||||
$routine_params_table.append(new_param_row);
|
||||
if ($('.rte_table').find('select[name=routine_type]').val() == 'FUNCTION') {
|
||||
$('.routine_return_row').show();
|
||||
$('.routine_direction_cell').hide();
|
||||
}
|
||||
/**
|
||||
* @var $newrow jQuery object containing the reference to the newly
|
||||
* inserted row in the routine parameters table.
|
||||
*/
|
||||
var $newrow = $('.routine_params_table').last().find('tr').has('td').last();
|
||||
setOptionsForParameter(
|
||||
$newrow.find('select[name^=routine_param_type]'),
|
||||
$newrow.find('input[name^=routine_param_length]'),
|
||||
$newrow.find('select[name^=routine_param_opts_text]'),
|
||||
$newrow.find('select[name^=routine_param_opts_num]')
|
||||
);
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Remove parameter from routine" functionality.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('.routine_param_remove_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
$(this).parent().parent().remove();
|
||||
// After removing a parameter, the indices of the name attributes in
|
||||
// the input fields lose the correct order and need to be reordered.
|
||||
/**
|
||||
* @var index Counter used for reindexing the input
|
||||
* fields in the routine parameters table.
|
||||
*/
|
||||
var index = 0;
|
||||
$('.routine_params_table').last().find('tr').has('td').each(function() {
|
||||
$(this).find(':input').each(function() {
|
||||
/**
|
||||
* @var inputname The value of the name attribute of
|
||||
* the input field being reindexed.
|
||||
*/
|
||||
var inputname = $(this).attr('name');
|
||||
if (inputname.substr(0, 17) == 'routine_param_dir') {
|
||||
$(this).attr('name', inputname.substr(0, 17) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 18) == 'routine_param_name') {
|
||||
$(this).attr('name', inputname.substr(0, 18) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 18) == 'routine_param_type') {
|
||||
$(this).attr('name', inputname.substr(0, 18) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 20) == 'routine_param_length') {
|
||||
$(this).attr('name', inputname.substr(0, 20) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 23) == 'routine_param_opts_text') {
|
||||
$(this).attr('name', inputname.substr(0, 23) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 22) == 'routine_param_opts_num') {
|
||||
$(this).attr('name', inputname.substr(0, 22) + '[' + index + ']');
|
||||
}
|
||||
});
|
||||
index++;
|
||||
});
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change routine type" functionality.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('select[name=routine_type]').live('change', function() {
|
||||
$('.routine_return_row, .routine_direction_cell').toggle();
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change parameter type" functionality.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('select[name^=routine_param_type]').live('change', function() {
|
||||
/**
|
||||
* @var $row jQuery object containing the reference to
|
||||
* a row in the routine parameters table.
|
||||
*/
|
||||
var $row = $(this).parents('tr').first();
|
||||
setOptionsForParameter(
|
||||
$row.find('select[name^=routine_param_type]'),
|
||||
$row.find('input[name^=routine_param_length]'),
|
||||
$row.find('select[name^=routine_param_opts_text]'),
|
||||
$row.find('select[name^=routine_param_opts_num]')
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change the type of return
|
||||
* variable of function" functionality.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('select[name=routine_returntype]').live('change', function() {
|
||||
setOptionsForParameter(
|
||||
$('.rte_table').find('select[name=routine_returntype]'),
|
||||
$('.rte_table').find('input[name=routine_returnlength]'),
|
||||
$('.rte_table').find('select[name=routine_returnopts_text]'),
|
||||
$('.rte_table').find('select[name=routine_returnopts_num]')
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Execute routine functionality.
|
||||
*
|
||||
* @uses PMA_ajaxShowMessage()
|
||||
* @uses PMA_ajaxRemoveMessage()
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('.exec_routine_anchor').live('click', function(event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user.
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function(data) {
|
||||
if(data.success == true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
if (data.dialog) {
|
||||
button_options[PMA_messages['strGo']] = function() {
|
||||
/**
|
||||
* @var data Form data to be sent in the AJAX request.
|
||||
*/
|
||||
var data = $('.rte_form').last().serialize();
|
||||
$msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
$.post('db_routines.php', data, function (data) {
|
||||
if(data.success == true) {
|
||||
// Routine executed successfully
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
PMA_slidingMessage(data.message);
|
||||
$ajaxDialog.dialog('close');
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
button_options[PMA_messages['strClose']] = function() {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
$ajaxDialog = $('<div>'+data.message+'</div>').dialog({
|
||||
width: 650, // TODO: make a better decision about the size
|
||||
// of the dialog based on the size of the viewport
|
||||
buttons: button_options,
|
||||
title: data.title,
|
||||
modal: true,
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$ajaxDialog.find('input[name^=params]').first().focus();
|
||||
} else {
|
||||
// Routine executed successfully
|
||||
PMA_slidingMessage(data.message);
|
||||
}
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for input fields in the routines editor
|
||||
* and the routine execution dialog used to submit the Ajax request
|
||||
* when the ENTER key is pressed.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$('input[name^=routine], input[name^=params]').live('keydown', function(e) {
|
||||
if (e.which == 13) {
|
||||
e.preventDefault();
|
||||
if (typeof button_options[PMA_messages['strGo']] == 'function') {
|
||||
button_options[PMA_messages['strGo']].call();
|
||||
}
|
||||
}
|
||||
});
|
||||
}); // end of $(document).ready() for the Routine Functionalities
|
||||
@ -1,2 +0,0 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
233
js/functions.js
233
js/functions.js
@ -2389,7 +2389,7 @@ $(function() {
|
||||
* Get the row number from the classlist (for example, row_1)
|
||||
*/
|
||||
function PMA_getRowNumber(classlist) {
|
||||
return parseInt(classlist.split(/row_/)[1]);
|
||||
return parseInt(classlist.split(/\s+row_/)[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2425,6 +2425,136 @@ function PMA_init_slider() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* var toggleButton This is a function that creates a toggle
|
||||
* sliding button given a jQuery reference
|
||||
* to the correct DOM element
|
||||
*/
|
||||
var toggleButton = function ($obj) {
|
||||
// In rtl mode the toggle switch is flipped horizontally
|
||||
// so we need to take that into account
|
||||
if ($('.text_direction', $obj).text() == 'ltr') {
|
||||
var right = 'right';
|
||||
} else {
|
||||
var right = 'left';
|
||||
}
|
||||
/**
|
||||
* var h Height of the button, used to scale the
|
||||
* background image and position the layers
|
||||
*/
|
||||
var h = $obj.height();
|
||||
$('img', $obj).height(h);
|
||||
$('table', $obj).css('bottom', h-1);
|
||||
/**
|
||||
* var on Width of the "ON" part of the toggle switch
|
||||
* var off Width of the "OFF" part of the toggle switch
|
||||
*/
|
||||
var on = $('.toggleOn', $obj).width();
|
||||
var off = $('.toggleOff', $obj).width();
|
||||
// Make the "ON" and "OFF" parts of the switch the same size
|
||||
$('.toggleOn > div', $obj).width(Math.max(on, off));
|
||||
$('.toggleOff > div', $obj).width(Math.max(on, off));
|
||||
/**
|
||||
* var w Width of the central part of the switch
|
||||
*/
|
||||
var w = parseInt(($('img', $obj).height() / 16) * 22, 10);
|
||||
// Resize the central part of the switch on the top
|
||||
// layer to match the background
|
||||
$('table td:nth-child(2) > div', $obj).width(w);
|
||||
/**
|
||||
* var imgw Width of the background image
|
||||
* var tblw Width of the foreground layer
|
||||
* var offset By how many pixels to move the background
|
||||
* image, so that it matches the top layer
|
||||
*/
|
||||
var imgw = $('img', $obj).width();
|
||||
var tblw = $('table', $obj).width();
|
||||
var offset = parseInt(((imgw - tblw) / 2), 10);
|
||||
// Move the background to match the layout of the top layer
|
||||
$obj.find('img').css(right, offset);
|
||||
/**
|
||||
* var offw Outer width of the "ON" part of the toggle switch
|
||||
* var btnw Outer width of the central part of the switch
|
||||
*/
|
||||
var offw = $('.toggleOff', $obj).outerWidth();
|
||||
var btnw = $('table td:nth-child(2)', $obj).outerWidth();
|
||||
// Resize the main div so that exactly one side of
|
||||
// the switch plus the central part fit into it.
|
||||
$obj.width(offw + btnw + 2);
|
||||
/**
|
||||
* var move How many pixels to move the
|
||||
* switch by when toggling
|
||||
*/
|
||||
var move = $('.toggleOff', $obj).outerWidth();
|
||||
// If the switch is initialized to the
|
||||
// OFF state we need to move it now.
|
||||
if ($('.container', $obj).hasClass('off')) {
|
||||
if (right == 'right') {
|
||||
$('table, img', $obj).animate({'left': '-=' + move + 'px'}, 0);
|
||||
} else {
|
||||
$('table, img', $obj).animate({'left': '+=' + move + 'px'}, 0);
|
||||
}
|
||||
}
|
||||
// Attach an 'onclick' event to the switch
|
||||
$('.container', $obj).click(function () {
|
||||
if ($(this).hasClass('isActive')) {
|
||||
return false;
|
||||
} else {
|
||||
$(this).addClass('isActive');
|
||||
}
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
var $container = $(this);
|
||||
var callback = $('.callback', this).text();
|
||||
// Perform the actual toggle
|
||||
if ($(this).hasClass('on')) {
|
||||
if (right == 'right') {
|
||||
var operator = '-=';
|
||||
} else {
|
||||
var operator = '+=';
|
||||
}
|
||||
var url = $(this).find('.toggleOff > span').text();
|
||||
var removeClass = 'on';
|
||||
var addClass = 'off';
|
||||
} else {
|
||||
if (right == 'right') {
|
||||
var operator = '+=';
|
||||
} else {
|
||||
var operator = '-=';
|
||||
}
|
||||
var url = $(this).find('.toggleOn > span').text();
|
||||
var removeClass = 'off';
|
||||
var addClass = 'on';
|
||||
}
|
||||
$.post(url, {'ajax_request': true}, function(data) {
|
||||
if(data.success == true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
$container
|
||||
.removeClass(removeClass)
|
||||
.addClass(addClass)
|
||||
.animate({'left': operator + move + 'px'}, function () {
|
||||
$container.removeClass('isActive');
|
||||
});
|
||||
eval(callback);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
$container.removeClass('isActive');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise all toggle buttons
|
||||
*/
|
||||
$(window).load(function () {
|
||||
$('.toggleAjax').each(function () {
|
||||
$(this)
|
||||
.show()
|
||||
.find('.toggleButton')
|
||||
toggleButton($(this));
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Vertical pointer
|
||||
*/
|
||||
@ -2528,44 +2658,6 @@ $(document).ready(function() {
|
||||
|
||||
}) // end of $(document).ready()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for Export of Routines, Triggers and Events.
|
||||
*
|
||||
* @uses PMA_ajaxShowMessage()
|
||||
* @uses PMA_ajaxRemoveMessage()
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
$('.export_routine_anchor, .export_trigger_anchor, .export_event_anchor').live('click', function(event) {
|
||||
event.preventDefault();
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function(data) {
|
||||
if(data.success == true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
/**
|
||||
* @var button_options Object containing options for jQueryUI dialog buttons
|
||||
*/
|
||||
var button_options = {};
|
||||
button_options[PMA_messages['strClose']] = function() {$(this).dialog("close").remove();}
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
var $ajaxDialog = $('<div>'+data.message+'</div>').dialog({
|
||||
width: 500,
|
||||
buttons: button_options,
|
||||
title: data.title
|
||||
});
|
||||
// Attach syntax highlited editor to export dialog
|
||||
var elm = $ajaxDialog.find('textarea');
|
||||
CodeMirror.fromTextArea(elm[0], {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"});
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}) // end $.get()
|
||||
}); // end $.live()
|
||||
}); // end of $(document).ready() for Export of Routines, Triggers and Events.
|
||||
|
||||
/**
|
||||
* Creates a message inside an object with a sliding effect
|
||||
*
|
||||
@ -2643,69 +2735,6 @@ function PMA_slidingMessage(msg, $obj) {
|
||||
return true;
|
||||
} // end PMA_slidingMessage()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for Drop functionality of Routines, Triggers and Events.
|
||||
*
|
||||
* @uses $.PMA_confirm()
|
||||
* @uses PMA_ajaxShowMessage()
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
$('.drop_routine_anchor, .drop_trigger_anchor, .drop_event_anchor').live('click', function(event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $curr_row Object containing reference to the current row
|
||||
*/
|
||||
var $curr_row = $(this).parents('tr');
|
||||
/**
|
||||
* @var question String containing the question to be asked for confirmation
|
||||
*/
|
||||
var question = $('<div></div>').text($curr_row.children('td').children('.drop_sql').html());
|
||||
$(this).PMA_confirm(question, $(this).attr('href'), function(url) {
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user.
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
|
||||
$.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) {
|
||||
if(data.success == true) {
|
||||
/**
|
||||
* @var $table Object containing reference to the main list of elements.
|
||||
*/
|
||||
var $table = $curr_row.parent();
|
||||
if ($table.find('tr').length == 2) {
|
||||
$table.hide("slow", function () {
|
||||
$(this).find('tr.even, tr.odd').remove();
|
||||
$('#nothing2display').show("slow");
|
||||
});
|
||||
} else {
|
||||
$curr_row.hide("slow", function () {
|
||||
$(this).remove();
|
||||
// Now we have removed the row from the list, but maybe
|
||||
// some row classes are wrong now. So we will itirate
|
||||
// throught all rows and assign correct classes to them.
|
||||
/**
|
||||
* @var ct Count of processed rows.
|
||||
*/
|
||||
var ct = 0;
|
||||
$table.find('tr').has('td').each(function() {
|
||||
rowclass = (ct % 2 == 0) ? 'even' : 'odd';
|
||||
$(this).removeClass().addClass(rowclass);
|
||||
ct++;
|
||||
});
|
||||
});
|
||||
}
|
||||
// Show the query that we just executed
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
PMA_slidingMessage(data.sql_query);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error);
|
||||
}
|
||||
}) // end $.get()
|
||||
}) // end $.PMA_confirm()
|
||||
}); // end $.live()
|
||||
}); //end $(document).ready() for Drop functionality of Routines, Triggers and Events.
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for Drop Table.
|
||||
*
|
||||
|
||||
285
js/makegrid.js
285
js/makegrid.js
@ -6,7 +6,6 @@
|
||||
minColWidth: 15,
|
||||
|
||||
// variables, assigned with default value, changed later
|
||||
alignment: 'horizontal', // 3 possibilities: vertical, horizontal, horizontalflipped
|
||||
actionSpan: 5,
|
||||
colOrder: new Array(), // array of column order
|
||||
colVisib: new Array(), // array of column visibility
|
||||
@ -32,9 +31,7 @@
|
||||
n: n,
|
||||
obj: obj,
|
||||
objLeft: $(obj).position().left,
|
||||
objWidth: this.alignment != 'vertical' ?
|
||||
$(this.t).find('th.draggable:visible:eq(' + n + ') span').outerWidth() :
|
||||
$(this.t).find('tr:first td:eq(' + n + ') span').outerWidth()
|
||||
objWidth: $(this.t).find('th.draggable:visible:eq(' + n + ') span').outerWidth()
|
||||
};
|
||||
$('body').css('cursor', 'col-resize');
|
||||
$('body').noSelect();
|
||||
@ -44,27 +41,15 @@
|
||||
// prepare the cCpy and cPointer from the dragged column
|
||||
$(this.cCpy).text($(obj).text());
|
||||
var objPos = $(obj).position();
|
||||
if (this.alignment != 'vertical') {
|
||||
$(this.cCpy).css({
|
||||
top: objPos.top + 20,
|
||||
left: objPos.left,
|
||||
height: $(obj).height(),
|
||||
width: $(obj).width()
|
||||
});
|
||||
$(this.cPointer).css({
|
||||
top: objPos.top
|
||||
});
|
||||
} else { // vertical alignment
|
||||
$(this.cCpy).css({
|
||||
top: objPos.top,
|
||||
left: objPos.left + 30,
|
||||
height: $(obj).height(),
|
||||
width: $(obj).width()
|
||||
});
|
||||
$(this.cPointer).css({
|
||||
top: objPos.top
|
||||
});
|
||||
}
|
||||
$(this.cCpy).css({
|
||||
top: objPos.top + 20,
|
||||
left: objPos.left,
|
||||
height: $(obj).height(),
|
||||
width: $(obj).width()
|
||||
});
|
||||
$(this.cPointer).css({
|
||||
top: objPos.top
|
||||
});
|
||||
|
||||
// get the column index, zero-based
|
||||
var n = this.getHeaderIdx(obj);
|
||||
@ -90,17 +75,10 @@
|
||||
$(this.colRsz.obj).css('left', this.colRsz.objLeft + dx + 'px');
|
||||
} else if (this.colMov) {
|
||||
// dragged column animation
|
||||
if (this.alignment != 'vertical') {
|
||||
var dx = e.pageX - this.colMov.x0;
|
||||
$(this.cCpy)
|
||||
.css('left', this.colMov.objLeft + dx)
|
||||
.show();
|
||||
} else { // vertical alignment
|
||||
var dy = e.pageY - this.colMov.y0;
|
||||
$(this.cCpy)
|
||||
.css('top', this.colMov.objTop + dy)
|
||||
.show();
|
||||
}
|
||||
var dx = e.pageX - this.colMov.x0;
|
||||
$(this.cCpy)
|
||||
.css('left', this.colMov.objLeft + dx)
|
||||
.show();
|
||||
|
||||
// pointer animation
|
||||
var hoveredCol = this.getHoveredCol(e);
|
||||
@ -110,25 +88,14 @@
|
||||
if (newn != this.colMov.n) {
|
||||
// show the column pointer in the right place
|
||||
var colPos = $(hoveredCol).position();
|
||||
if (this.alignment != 'vertical') {
|
||||
var newleft = newn < this.colMov.n ?
|
||||
colPos.left :
|
||||
colPos.left + $(hoveredCol).outerWidth();
|
||||
$(this.cPointer)
|
||||
.css({
|
||||
left: newleft,
|
||||
visibility: 'visible'
|
||||
});
|
||||
} else { // vertical alignment
|
||||
var newtop = newn < this.colMov.n ?
|
||||
colPos.top :
|
||||
colPos.top + $(hoveredCol).outerHeight();
|
||||
$(this.cPointer)
|
||||
.css({
|
||||
top: newtop,
|
||||
visibility: 'visible'
|
||||
});
|
||||
}
|
||||
var newleft = newn < this.colMov.n ?
|
||||
colPos.left :
|
||||
colPos.left + $(hoveredCol).outerWidth();
|
||||
$(this.cPointer)
|
||||
.css({
|
||||
left: newleft,
|
||||
visibility: 'visible'
|
||||
});
|
||||
} else {
|
||||
// no movement to other column, hide the column pointer
|
||||
$(this.cPointer).css('visibility', 'hidden');
|
||||
@ -187,18 +154,11 @@
|
||||
* Resize column n to new width "nw"
|
||||
*/
|
||||
resize: function(n, nw) {
|
||||
if (this.alignment != 'vertical') {
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('th.draggable:visible:eq(' + n + ') span,' +
|
||||
'td:visible:eq(' + (g.actionSpan + n) + ') span')
|
||||
.css('width', nw);
|
||||
});
|
||||
} else { // vertical alignment
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('td:eq(' + n + ') span')
|
||||
.css('width', nw);
|
||||
});
|
||||
}
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('th.draggable:visible:eq(' + n + ') span,' +
|
||||
'td:visible:eq(' + (g.actionSpan + n) + ') span')
|
||||
.css('width', nw);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -206,9 +166,7 @@
|
||||
*/
|
||||
reposRsz: function() {
|
||||
$(this.cRsz).find('div').hide();
|
||||
$firstRowCols = this.alignment != 'vertical' ?
|
||||
$(this.t).find('tr:first th.draggable:visible') :
|
||||
$(this.t).find('tr:first td');
|
||||
$firstRowCols = $(this.t).find('tr:first th.draggable:visible');
|
||||
for (var n = 0; n < $firstRowCols.length; n++) {
|
||||
$this = $($firstRowCols[n]);
|
||||
$cb = $(g.cRsz).find('div:eq(' + n + ')'); // column border
|
||||
@ -222,40 +180,29 @@
|
||||
* Shift column from index oldn to newn.
|
||||
*/
|
||||
shiftCol: function(oldn, newn) {
|
||||
if (this.alignment != 'vertical') {
|
||||
$(this.t).find('tr').each(function() {
|
||||
if (newn < oldn) {
|
||||
$(this).find('th.draggable:eq(' + newn + '),' +
|
||||
'td:eq(' + (g.actionSpan + newn) + ')')
|
||||
.before($(this).find('th.draggable:eq(' + oldn + '),' +
|
||||
'td:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
} else {
|
||||
$(this).find('th.draggable:eq(' + newn + '),' +
|
||||
'td:eq(' + (g.actionSpan + newn) + ')')
|
||||
.after($(this).find('th.draggable:eq(' + oldn + '),' +
|
||||
'td:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
}
|
||||
});
|
||||
// reposition the column resize bars
|
||||
this.reposRsz();
|
||||
|
||||
} else { // vertical alignment
|
||||
// shift rows
|
||||
$(this.t).find('tr').each(function() {
|
||||
if (newn < oldn) {
|
||||
$(this.t).find('tr:eq(' + (g.actionSpan + newn) + ')')
|
||||
.before($(this.t).find('tr:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
$(this).find('th.draggable:eq(' + newn + '),' +
|
||||
'td:eq(' + (g.actionSpan + newn) + ')')
|
||||
.before($(this).find('th.draggable:eq(' + oldn + '),' +
|
||||
'td:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
} else {
|
||||
$(this.t).find('tr:eq(' + (g.actionSpan + newn) + ')')
|
||||
.after($(this.t).find('tr:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
$(this).find('th.draggable:eq(' + newn + '),' +
|
||||
'td:eq(' + (g.actionSpan + newn) + ')')
|
||||
.after($(this).find('th.draggable:eq(' + oldn + '),' +
|
||||
'td:eq(' + (g.actionSpan + oldn) + ')'));
|
||||
}
|
||||
}
|
||||
});
|
||||
// reposition the column resize bars
|
||||
this.reposRsz();
|
||||
|
||||
// adjust the column visibility list
|
||||
if (newn < oldn) {
|
||||
$(g.cList).find('tr:eq(' + newn + ')')
|
||||
.before($(g.cList).find('tr:eq(' + oldn + ')'));
|
||||
$(g.cList).find('.lDiv div:eq(' + newn + ')')
|
||||
.before($(g.cList).find('.lDiv div:eq(' + oldn + ')'));
|
||||
} else {
|
||||
$(g.cList).find('tr:eq(' + newn + ')')
|
||||
.after($(g.cList).find('tr:eq(' + oldn + ')'));
|
||||
$(g.cList).find('.lDiv div:eq(' + newn + ')')
|
||||
.after($(g.cList).find('.lDiv div:eq(' + oldn + ')'));
|
||||
}
|
||||
// adjust the colOrder
|
||||
var tmp = this.colOrder[oldn];
|
||||
@ -274,23 +221,13 @@
|
||||
getHoveredCol: function(e) {
|
||||
var hoveredCol;
|
||||
$headers = $(this.t).find('th.draggable:visible');
|
||||
if (this.alignment != 'vertical') {
|
||||
$headers.each(function() {
|
||||
var left = $(this).offset().left;
|
||||
var right = left + $(this).outerWidth();
|
||||
if (left <= e.pageX && e.pageX <= right) {
|
||||
hoveredCol = this;
|
||||
}
|
||||
});
|
||||
} else { // vertical alignment
|
||||
$headers.each(function() {
|
||||
var top = $(this).offset().top;
|
||||
var bottom = top + $(this).height();
|
||||
if (top <= e.pageY && e.pageY <= bottom) {
|
||||
hoveredCol = this;
|
||||
}
|
||||
});
|
||||
}
|
||||
$headers.each(function() {
|
||||
var left = $(this).offset().left;
|
||||
var right = left + $(this).outerWidth();
|
||||
if (left <= e.pageX && e.pageX <= right) {
|
||||
hoveredCol = this;
|
||||
}
|
||||
});
|
||||
return hoveredCol;
|
||||
},
|
||||
|
||||
@ -298,15 +235,7 @@
|
||||
* Get a zero-based index from a <th class="draggable"> tag in a table.
|
||||
*/
|
||||
getHeaderIdx: function(obj) {
|
||||
var n;
|
||||
if (this.alignment != 'vertical') {
|
||||
n = $(obj).parents('tr').find('th.draggable').index(obj);
|
||||
} else {
|
||||
var column_idx = $(obj).index();
|
||||
var $th_in_same_column = $(this.t).find('th.draggable:nth-child(' + (column_idx + 1) + ')');
|
||||
n = $th_in_same_column.index(obj);
|
||||
}
|
||||
return n;
|
||||
return $(obj).parents('tr').find('th.draggable').index(obj);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -453,36 +382,26 @@
|
||||
if (this.colVisib[n]) {
|
||||
// can hide if more than one column is visible
|
||||
if (this.visibleHeadersCount > 1) {
|
||||
if (this.alignment != 'vertical') {
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('th.draggable:eq(' + n + '),' +
|
||||
'td:eq(' + (g.actionSpan + n) + ')')
|
||||
.hide();
|
||||
});
|
||||
} else { // vertical alignment
|
||||
$(this.t).find('tr:eq(' + (g.actionSpan + n) + ')')
|
||||
.hide();
|
||||
}
|
||||
this.colVisib[n] = 0;
|
||||
$(this.cList).find('tr:eq(' + n + ') input').removeAttr('checked');
|
||||
} else {
|
||||
// cannot hide, force the checkbox to stay checked
|
||||
$(this.cList).find('tr:eq(' + n + ') input').attr('checked', 'checked');
|
||||
return false;
|
||||
}
|
||||
} else { // column n is not visible
|
||||
if (this.alignment != 'vertical') {
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('th.draggable:eq(' + n + '),' +
|
||||
'td:eq(' + (g.actionSpan + n) + ')')
|
||||
.show();
|
||||
.hide();
|
||||
});
|
||||
} else { // vertical alignment
|
||||
$(this.t).find('tr:eq(' + (g.actionSpan + n) + ')')
|
||||
.show();
|
||||
this.colVisib[n] = 0;
|
||||
$(this.cList).find('.lDiv div:eq(' + n + ') input').removeAttr('checked');
|
||||
} else {
|
||||
// cannot hide, force the checkbox to stay checked
|
||||
$(this.cList).find('.lDiv div:eq(' + n + ') input').attr('checked', 'checked');
|
||||
return false;
|
||||
}
|
||||
} else { // column n is not visible
|
||||
$(this.t).find('tr').each(function() {
|
||||
$(this).find('th.draggable:eq(' + n + '),' +
|
||||
'td:eq(' + (g.actionSpan + n) + ')')
|
||||
.show();
|
||||
});
|
||||
this.colVisib[n] = 1;
|
||||
$(this.cList).find('tr:eq(' + n + ') input').attr('checked', 'checked');
|
||||
$(this.cList).find('.lDiv div:eq(' + n + ') input').attr('checked', 'checked');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
@ -500,9 +419,7 @@
|
||||
this.sendColPrefs();
|
||||
|
||||
// check visible first row headers count
|
||||
this.visibleHeadersCount = this.alignment != 'vertical' ?
|
||||
$(this.t).find('tr:first th.draggable:visible').length :
|
||||
$(this.t).find('th.draggable:nth-child(1):visible').length;
|
||||
this.visibleHeadersCount = $(this.t).find('tr:first th.draggable:visible').length;
|
||||
this.refreshRestoreButton();
|
||||
},
|
||||
|
||||
@ -574,15 +491,12 @@
|
||||
g.cDrop = document.createElement('div'); // column drop-down arrows
|
||||
g.cList = document.createElement('div'); // column visibility list
|
||||
|
||||
// assign the table alignment
|
||||
g.alignment = $("#top_direction_dropdown").val();
|
||||
|
||||
// adjust g.cCpy
|
||||
g.cCpy.className = 'cCpy';
|
||||
$(g.cCpy).hide();
|
||||
|
||||
// adjust g.cPoint
|
||||
g.cPointer.className = g.alignment != 'vertical' ? 'cPointer' : 'cPointerVer';
|
||||
g.cPointer.className = 'cPointer';
|
||||
$(g.cPointer).css('visibility', 'hidden');
|
||||
|
||||
// adjust g.dHint
|
||||
@ -601,23 +515,14 @@
|
||||
g.t = t;
|
||||
|
||||
// get first row data columns
|
||||
var $firstRowCols = g.alignment != 'vertical' ?
|
||||
$(t).find('tr:first th.draggable') :
|
||||
$(t).find('tr:first td');
|
||||
|
||||
// get first row of data headers (first column of data headers, in vertical mode)
|
||||
var $firstRowHeaders = g.alignment != 'vertical' ?
|
||||
$(t).find('tr:first th.draggable') :
|
||||
$(t).find('th.draggable:nth-child(1)');
|
||||
var $firstRowCols = $(t).find('tr:first th.draggable');
|
||||
|
||||
// initialize g.visibleHeadersCount
|
||||
g.visibleHeadersCount = $firstRowHeaders.filter(':visible').length;
|
||||
g.visibleHeadersCount = $firstRowCols.filter(':visible').length;
|
||||
|
||||
// assign first column (actions) span
|
||||
if (! $(t).find('tr:first th:first').hasClass('draggable')) { // action header exist
|
||||
g.actionSpan = g.alignment != 'vertical' ?
|
||||
$(t).find('tr:first th:first').prop('colspan') :
|
||||
$(t).find('tr:first th:first').prop('rowspan');
|
||||
g.actionSpan = $(t).find('tr:first th:first').prop('colspan');
|
||||
} else {
|
||||
g.actionSpan = 0;
|
||||
}
|
||||
@ -642,7 +547,7 @@
|
||||
}
|
||||
} else {
|
||||
g.colOrder = new Array();
|
||||
for (var i = 0; i < $firstRowHeaders.length; i++) {
|
||||
for (var i = 0; i < $firstRowCols.length; i++) {
|
||||
g.colOrder.push(i);
|
||||
}
|
||||
}
|
||||
@ -656,12 +561,12 @@
|
||||
}
|
||||
} else {
|
||||
g.colVisib = new Array();
|
||||
for (var i = 0; i < $firstRowHeaders.length; i++) {
|
||||
for (var i = 0; i < $firstRowCols.length; i++) {
|
||||
g.colVisib.push(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ($firstRowHeaders.length > 1) {
|
||||
if ($firstRowCols.length > 1) {
|
||||
// create column drop-down arrow(s)
|
||||
$(t).find('th:not(.draggable)').each(function() {
|
||||
var cd = document.createElement('div'); // column drop-down arrow
|
||||
@ -682,16 +587,16 @@
|
||||
});
|
||||
|
||||
// add column visibility control
|
||||
g.cList.innerHTML = '<table cellpadding="0" cellspacing="0"><tbody></tbody></table>';
|
||||
var $tbody = $(g.cList).find('tbody');
|
||||
for (var i = 0; i < $firstRowHeaders.length; i++) {
|
||||
var currHeader = $firstRowHeaders[i];
|
||||
var tr = document.createElement('tr');
|
||||
$(tr).html('<td><input type="checkbox" ' + (g.colVisib[i] ? 'checked="checked" ' : '') + '/></td>' +
|
||||
'<td>' + $(currHeader).text() + '</td>');
|
||||
$tbody.append(tr);
|
||||
g.cList.innerHTML = '<div class="lDiv"></div>';
|
||||
var $listDiv = $(g.cList).find('div');
|
||||
for (var i = 0; i < $firstRowCols.length; i++) {
|
||||
var currHeader = $firstRowCols[i];
|
||||
var listElmt = document.createElement('div');
|
||||
$(listElmt).text($(currHeader).text())
|
||||
.prepend('<input type="checkbox" ' + (g.colVisib[i] ? 'checked="checked" ' : '') + '/>');
|
||||
$listDiv.append(listElmt);
|
||||
// add event on click
|
||||
$(tr).click(function() {
|
||||
$(listElmt).click(function() {
|
||||
if ( g.toggleCol($(this).index()) ) {
|
||||
g.afterToggleCol();
|
||||
}
|
||||
@ -706,7 +611,7 @@
|
||||
g.showAllColumns();
|
||||
});
|
||||
// prepend "show all column" button at top if the list is too long
|
||||
if ($firstRowHeaders.length > 10) {
|
||||
if ($firstRowCols.length > 10) {
|
||||
var clone = showAll.cloneNode(true);
|
||||
$(g.cList).prepend(clone);
|
||||
$(clone).click(function() {
|
||||
@ -749,15 +654,17 @@
|
||||
g.showHint(e);
|
||||
});
|
||||
}
|
||||
$(t).find('th:not(.draggable)')
|
||||
.mouseenter(function(e) {
|
||||
g.showColVisibHint = true;
|
||||
g.showHint(e);
|
||||
})
|
||||
.mouseleave(function(e) {
|
||||
g.showColVisibHint = false;
|
||||
g.showHint(e);
|
||||
});
|
||||
if ($firstRowCols.length > 1) {
|
||||
$(t).find('th:not(.draggable)')
|
||||
.mouseenter(function(e) {
|
||||
g.showColVisibHint = true;
|
||||
g.showHint(e);
|
||||
})
|
||||
.mouseleave(function(e) {
|
||||
g.showColVisibHint = false;
|
||||
g.showHint(e);
|
||||
});
|
||||
}
|
||||
$(t).find('th.draggable a')
|
||||
.attr('title', '') // hide default tooltip for sorting
|
||||
.mouseenter(function(e) {
|
||||
|
||||
@ -122,7 +122,6 @@ $js_messages['strDeleting'] = __('Deleting');
|
||||
|
||||
/* For db_routines.js */
|
||||
$js_messages['MissingReturn'] = __('The definition of a stored function must contain a RETURN statement!');
|
||||
$js_messages['strValueTooLong'] = __('Value too long in the form!');
|
||||
|
||||
/* For import.js */
|
||||
$js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, they will be combined into one');
|
||||
|
||||
380
js/rte/common.js
Normal file
380
js/rte/common.js
Normal file
@ -0,0 +1,380 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* @var RTE a JavaScript namespace containing the functionality
|
||||
* for Routines, Triggers and Events.
|
||||
*
|
||||
* This namespace is extended by the functionality required
|
||||
* to handle a specific item (a routine, trigger or event)
|
||||
* in the relevant javascript files in this folder.
|
||||
*/
|
||||
var RTE = {
|
||||
/**
|
||||
* @var $ajaxDialog jQuery object containing the reference to the
|
||||
* dialog that contains the editor.
|
||||
*/
|
||||
$ajaxDialog: null,
|
||||
/**
|
||||
* @var syntaxHiglighter Reference to the codemirror editor.
|
||||
*/
|
||||
syntaxHiglighter: null,
|
||||
/**
|
||||
* @var buttonOptions Object containing options for
|
||||
* the jQueryUI dialog buttons
|
||||
*/
|
||||
buttonOptions: {},
|
||||
/**
|
||||
* Validate editor form fields.
|
||||
*/
|
||||
validate: function () {
|
||||
/**
|
||||
* @var $elm a jQuery object containing the reference
|
||||
* to an element that is being validated.
|
||||
*/
|
||||
var $elm = null;
|
||||
// Common validation. At the very least the name
|
||||
// and the definition must be provided for an item
|
||||
$elm = $('.rte_table').last().find('input[name=item_name]');
|
||||
if ($elm.val() === '') {
|
||||
$elm.focus();
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
$elm = $('.rte_table').find('textarea[name=item_definition]');
|
||||
if ($elm.val() === '') {
|
||||
this.syntaxHiglighter.focus();
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
// The validation has so far passed, so now
|
||||
// we can validate item-specific fields.
|
||||
return RTE.validateCustom();
|
||||
}, // end validate()
|
||||
/**
|
||||
* Validate custom editor form fields.
|
||||
* This function can be overridden by
|
||||
* other files in this folder.
|
||||
*/
|
||||
validateCustom: function () {
|
||||
return true;
|
||||
}, // end validateCustom()
|
||||
/**
|
||||
* Execute some code after the ajax
|
||||
* dialog for the ditor is shown.
|
||||
* This function can be overridden by
|
||||
* other files in this folder.
|
||||
*/
|
||||
postDialogShow: function () {
|
||||
// Nothing by default
|
||||
} // end postDialogShow()
|
||||
}; // end RTE namespace
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Routines, Triggers and Events editor.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
/**
|
||||
* Attach Ajax event handlers for the Add/Edit functionality.
|
||||
*/
|
||||
$('.ajax_add_anchor, .ajax_edit_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $edit_row jQuery object containing the reference to
|
||||
* the row of the the item being edited
|
||||
* from the list of items .
|
||||
*/
|
||||
var $edit_row = null;
|
||||
if ($(this).hasClass('ajax_edit_anchor')) {
|
||||
// Remeber the row of the item being edited for later,
|
||||
// so that if the edit is successful, we can replace the
|
||||
// row with info about the modified item.
|
||||
$edit_row = $(this).parents('tr');
|
||||
}
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user.
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage();
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function (data) {
|
||||
if (data.success === true) {
|
||||
// We have successfully fetched the editor form
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
// Now define the function that is called when
|
||||
// the user presses the "Go" button
|
||||
RTE.buttonOptions[PMA_messages['strGo']] = function () {
|
||||
// Move the data from the codemirror editor back to the
|
||||
// textarea, where it can be used in the form submission.
|
||||
RTE.syntaxHiglighter.save();
|
||||
// Validate editor and submit request, if passed.
|
||||
if (RTE.validate()) {
|
||||
/**
|
||||
* @var data Form data to be sent in the AJAX request.
|
||||
*/
|
||||
var data = $('.rte_form').last().serialize();
|
||||
$msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
|
||||
$.post($('.rte_form').last().attr('action'), data, function (data) {
|
||||
if (data.success === true) {
|
||||
// Item created successfully
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
PMA_slidingMessage(data.message);
|
||||
RTE.$ajaxDialog.dialog('close');
|
||||
// If we are in 'edit' mode, we must remove the reference to the old row.
|
||||
if (mode === 'edit') {
|
||||
$edit_row.remove();
|
||||
}
|
||||
// Sometimes, like when moving a trigger from a table to
|
||||
// another one, the new row should not be inserted into the
|
||||
// list. In this case "data.insert" will be set to false.
|
||||
if (data.insert) {
|
||||
// Insert the new row at the correct location in the list of items
|
||||
/**
|
||||
* @var text Contains the name of an item from the list
|
||||
* that is used in comparisons to find the correct
|
||||
* location where to insert a new row.
|
||||
*/
|
||||
var text = '';
|
||||
/**
|
||||
* @var inserted Whether a new item has been inserted
|
||||
* in the list or not.
|
||||
*/
|
||||
var inserted = false;
|
||||
$('table.data').find('tr').each(function () {
|
||||
text = $(this)
|
||||
.children('td')
|
||||
.eq(0)
|
||||
.find('strong')
|
||||
.text()
|
||||
.toUpperCase();
|
||||
text = $.trim(text);
|
||||
if (text !== '' && text > data.name) {
|
||||
$(this).before(data.new_row);
|
||||
inserted = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (! inserted) {
|
||||
// If we didn't manage to insert the row yet,
|
||||
// it must belong at the end of the list,
|
||||
// so we insert it there.
|
||||
$('table.data').append(data.new_row);
|
||||
}
|
||||
// Fade-in the new row
|
||||
$('.ajaxInsert').show('slow').removeClass('ajaxInsert');
|
||||
} else if ($('table.data').find('tr').has('td').length === 0) {
|
||||
// If we are not supposed to insert the new row, we will now
|
||||
// check if the table is empty and needs to be hidden. This
|
||||
// will be the case if we were editing the only item in the
|
||||
// list, which we removed and will not be inserting something
|
||||
// else in its place.
|
||||
$('table.data').hide("slow", function () {
|
||||
$('#nothing2display').show("slow");
|
||||
});
|
||||
}
|
||||
// Now we have inserted the row at the correct position, but surely
|
||||
// at least some row classes are wrong now. So we will itirate
|
||||
// throught all rows and assign correct classes to them.
|
||||
/**
|
||||
* @var ct Count of processed rows.
|
||||
*/
|
||||
var ct = 0;
|
||||
/**
|
||||
* @var rowclass Class to be attached to the row
|
||||
* that is being processed
|
||||
*/
|
||||
var rowclass = '';
|
||||
$('table.data').find('tr').has('td').each(function () {
|
||||
rowclass = (ct % 2 === 0) ? 'even' : 'odd';
|
||||
$(this).removeClass().addClass(rowclass);
|
||||
ct++;
|
||||
});
|
||||
// If this is the first item being added, remove
|
||||
// the "No items" message and show the list.
|
||||
if ($('table.data').find('tr').has('td').length > 0
|
||||
&& $('#nothing2display').is(':visible')) {
|
||||
$('#nothing2display').hide("slow", function () {
|
||||
$('table.data').show("slow");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}); // end $.post()
|
||||
} // end "if (RTE.validate())"
|
||||
}; // end of function that handles the submission of the Editor
|
||||
RTE.buttonOptions[PMA_messages['strClose']] = function () {
|
||||
$(this).dialog("close");
|
||||
};
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
RTE.$ajaxDialog = $('<div>' + data.message + '</div>').dialog({
|
||||
width: 700,
|
||||
height: 555,
|
||||
buttons: RTE.buttonOptions,
|
||||
title: data.title,
|
||||
modal: true,
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
RTE.$ajaxDialog.find('input[name=item_name]').focus();
|
||||
RTE.$ajaxDialog.find('.datefield, .datetimefield').each(function () {
|
||||
PMA_addDatepicker($(this).css('width', '95%'));
|
||||
});
|
||||
/**
|
||||
* @var mode Used to remeber whether the editor is in
|
||||
* "Edit" or "Add" mode.
|
||||
*/
|
||||
var mode = 'add';
|
||||
if ($('input[name=editor_process_edit]').length > 0) {
|
||||
mode = 'edit';
|
||||
}
|
||||
// Attach syntax highlited editor to the definition
|
||||
/**
|
||||
* @var $elm jQuery object containing the reference to
|
||||
* the Definition textarea.
|
||||
*/
|
||||
var $elm = $('textarea[name=item_definition]').last();
|
||||
/**
|
||||
* @var opts Options to pass to the codemirror editor.
|
||||
*/
|
||||
var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"};
|
||||
RTE.syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts);
|
||||
// Hack to prevent the syntax highlighter from expanding beyond dialog boundries
|
||||
$('.CodeMirror-scroll').find('div').first().css('width', '1px');
|
||||
// Execute item-specific code
|
||||
RTE.postDialogShow(data);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}); // end $.get()
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for input fields in the editor
|
||||
* and the routine execution dialog used to submit the Ajax
|
||||
* request when the ENTER key is pressed.
|
||||
*/
|
||||
$('.rte_table').find('input[name^=item], input[name^=params]').live('keydown', function (e) {
|
||||
if (e.which === 13) { // 13 is the ENTER key
|
||||
e.preventDefault();
|
||||
if (typeof RTE.buttonOptions[PMA_messages['strGo']] === 'function') {
|
||||
RTE.buttonOptions[PMA_messages['strGo']].call();
|
||||
}
|
||||
}
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for Export of Routines, Triggers and Events.
|
||||
*/
|
||||
$('.ajax_export_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
var $msg = PMA_ajaxShowMessage();
|
||||
// Fire the ajax request straight away
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function (data) {
|
||||
if (data.success === true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
/**
|
||||
* @var button_options Object containing options for jQueryUI dialog buttons
|
||||
*/
|
||||
var button_options = {};
|
||||
button_options[PMA_messages['strClose']] = function () {
|
||||
$(this).dialog("close").remove();
|
||||
};
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
|
||||
width: 500,
|
||||
buttons: button_options,
|
||||
title: data.title
|
||||
});
|
||||
// Attach syntax highlited editor to export dialog
|
||||
/**
|
||||
* @var $elm jQuery object containing the reference
|
||||
* to the Export textarea.
|
||||
*/
|
||||
var $elm = $ajaxDialog.find('textarea');
|
||||
/**
|
||||
* @var opts Options to pass to the codemirror editor.
|
||||
*/
|
||||
var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"};
|
||||
CodeMirror.fromTextArea($elm[0], opts);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}); // end $.get()
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for Drop functionality of Routines, Triggers and Events.
|
||||
*/
|
||||
$('.ajax_drop_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $curr_row Object containing reference to the current row
|
||||
*/
|
||||
var $curr_row = $(this).parents('tr');
|
||||
/**
|
||||
* @var question String containing the question to be asked for confirmation
|
||||
*/
|
||||
var question = $('<div></div>').text($curr_row.children('td').children('.drop_sql').html());
|
||||
// We ask for confirmation first here, before submitting the ajax request
|
||||
$(this).PMA_confirm(question, $(this).attr('href'), function (url) {
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user.
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
|
||||
$.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function (data) {
|
||||
if (data.success === true) {
|
||||
/**
|
||||
* @var $table Object containing reference to the main list of elements.
|
||||
*/
|
||||
var $table = $curr_row.parent();
|
||||
// Check how many rows will be left after we remove
|
||||
// the one that the user has requested us to remove
|
||||
if ($table.find('tr').length === 2) {
|
||||
// If there are two rows left, it means that they are
|
||||
// the header of the table and the rows that we are
|
||||
// about to remove, so after the removal there will be
|
||||
// nothing to show in the table, so we hide it.
|
||||
$table.hide("slow", function () {
|
||||
$(this).find('tr.even, tr.odd').remove();
|
||||
$('#nothing2display').show("slow");
|
||||
});
|
||||
} else {
|
||||
$curr_row.hide("slow", function () {
|
||||
$(this).remove();
|
||||
// Now we have removed the row from the list, but maybe
|
||||
// some row classes are wrong now. So we will itirate
|
||||
// throught all rows and assign correct classes to them.
|
||||
/**
|
||||
* @var ct Count of processed rows.
|
||||
*/
|
||||
var ct = 0;
|
||||
/**
|
||||
* @var rowclass Class to be attached to the row
|
||||
* that is being processed
|
||||
*/
|
||||
var rowclass = '';
|
||||
$table.find('tr').has('td').each(function () {
|
||||
rowclass = (ct % 2 === 0) ? 'even' : 'odd';
|
||||
$(this).removeClass().addClass(rowclass);
|
||||
ct++;
|
||||
});
|
||||
});
|
||||
}
|
||||
// Get rid of the "Loading" message
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
// Show the query that we just executed
|
||||
PMA_slidingMessage(data.sql_query);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error);
|
||||
}
|
||||
}); // end $.get()
|
||||
}); // end $.PMA_confirm()
|
||||
}); // end $.live()
|
||||
}); // end of $(document).ready()
|
||||
43
js/rte/events.js
Normal file
43
js/rte/events.js
Normal file
@ -0,0 +1,43 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* Overriding the validateCustom() function defined in common.js
|
||||
*/
|
||||
RTE.validateCustom = function () {
|
||||
/**
|
||||
* @var $elm a jQuery object containing the reference
|
||||
* to an element that is being validated.
|
||||
*/
|
||||
var $elm = null;
|
||||
if ($('select[name=item_type]').find(':selected').val() === 'RECURRING') {
|
||||
// The interval field must not be empty for recurring events
|
||||
$elm = $('input[name=item_interval_value]');
|
||||
if ($elm.val() === '') {
|
||||
$elm.focus();
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The execute_at field must not be empty for "once off" events
|
||||
$elm = $('input[name=item_execute_at]');
|
||||
if ($elm.val() === '') {
|
||||
$elm.focus();
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}; // end RTE.validateCustom()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change event type"
|
||||
* functionality in the events editor, so that the correct
|
||||
* rows are shown in the editor when changing the event type
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
$('select[name=item_type]').live('change', function () {
|
||||
$('.recurring_event_row, .onetime_event_row').toggle();
|
||||
}); // end $.live()
|
||||
}); // end of $(document).ready()
|
||||
395
js/rte/routines.js
Normal file
395
js/rte/routines.js
Normal file
@ -0,0 +1,395 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* @var param_template This variable contains the template for one row
|
||||
* of the parameters table that is attached to the
|
||||
* dialog when a new parameter is added.
|
||||
*/
|
||||
RTE.param_template = '';
|
||||
|
||||
/**
|
||||
* Overriding the postDialogShow() function defined in common.js
|
||||
*
|
||||
* @param data JSON-encoded data from the ajax request
|
||||
*/
|
||||
RTE.postDialogShow = function (data) {
|
||||
// Cache the template for a parameter table row
|
||||
RTE.param_template = data.param_template;
|
||||
// Make adjustments in the dialog to make it AJAX compatible
|
||||
$('.routine_param_remove').show();
|
||||
$('input[name=routine_removeparameter]').remove();
|
||||
$('input[name=routine_addparameter]').css('width', '100%');
|
||||
// Enable/disable the 'options' dropdowns for parameters as necessary
|
||||
$('.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1');
|
||||
$('.routine_params_table').last().find('tr').has('td').each(function () {
|
||||
RTE.setOptionsForParameter(
|
||||
$(this).find('select[name^=item_param_type]'),
|
||||
$(this).find('input[name^=item_param_length]'),
|
||||
$(this).find('select[name^=item_param_opts_text]'),
|
||||
$(this).find('select[name^=item_param_opts_num]')
|
||||
);
|
||||
});
|
||||
// Enable/disable the 'options' dropdowns for
|
||||
// function return value as necessary
|
||||
RTE.setOptionsForParameter(
|
||||
$('.rte_table').last().find('select[name=item_returntype]'),
|
||||
$('.rte_table').last().find('input[name=item_returnlength]'),
|
||||
$('.rte_table').last().find('select[name=item_returnopts_text]'),
|
||||
$('.rte_table').last().find('select[name=item_returnopts_num]')
|
||||
);
|
||||
}; // end RTE.postDialogShow()
|
||||
|
||||
/**
|
||||
* Overriding the validateCustom() function defined in common.js
|
||||
*/
|
||||
RTE.validateCustom = function () {
|
||||
/**
|
||||
* @var isSuccess Stores the outcome of the validation
|
||||
*/
|
||||
var isSuccess = true;
|
||||
/**
|
||||
* @var inputname The value of the "name" attribute for
|
||||
* the field that is being processed
|
||||
*/
|
||||
var inputname = '';
|
||||
$('.routine_params_table').last().find('tr').each(function () {
|
||||
// Every parameter of a routine must have
|
||||
// a non-empty direction, name and type
|
||||
if (isSuccess) {
|
||||
$(this).find(':input').each(function () {
|
||||
inputname = $(this).attr('name');
|
||||
if (inputname.substr(0, 17) === 'item_param_dir' ||
|
||||
inputname.substr(0, 18) === 'item_param_name' ||
|
||||
inputname.substr(0, 18) === 'item_param_type') {
|
||||
if ($(this).val() === '') {
|
||||
$(this).focus();
|
||||
isSuccess = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (! isSuccess) {
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
$('.routine_params_table').last().find('tr').each(function () {
|
||||
// SET, ENUM, VARCHAR and VARBINARY fields must have length/values
|
||||
var $inputtyp = $(this).find('select[name^=item_param_type]');
|
||||
var $inputlen = $(this).find('input[name^=item_param_length]');
|
||||
if ($inputtyp.length && $inputlen.length) {
|
||||
if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR')
|
||||
&& $inputlen.val() === '') {
|
||||
$inputlen.focus();
|
||||
isSuccess = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (! isSuccess) {
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
|
||||
// The length/values of return variable for functions must
|
||||
// be set, if the type is SET, ENUM, VARCHAR or VARBINARY.
|
||||
var $returntyp = $('select[name=item_returntype]');
|
||||
var $returnlen = $('input[name=item_returnlength]');
|
||||
if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR')
|
||||
&& $returnlen.val() === '') {
|
||||
$returnlen.focus();
|
||||
alert(PMA_messages['strFormEmpty']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
|
||||
// A function must contain a RETURN statement in its definition
|
||||
if ($('.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) {
|
||||
RTE.syntaxHiglighter.focus();
|
||||
alert(PMA_messages['MissingReturn']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}; // end RTE.validateCustom()
|
||||
|
||||
/**
|
||||
* Enable/disable the "options" dropdown and "length" input for
|
||||
* parameters and the return variable in the routine editor
|
||||
* as necessary.
|
||||
*
|
||||
* @param $type a jQuery object containing the reference
|
||||
* to the "Type" dropdown box
|
||||
* @param $len a jQuery object containing the reference
|
||||
* to the "Length" input box
|
||||
* @param $text a jQuery object containing the reference
|
||||
* to the dropdown box with options for
|
||||
* parameters of text type
|
||||
* @param $num a jQuery object containing the reference
|
||||
* to the dropdown box with options for
|
||||
* parameters of numeric type
|
||||
*/
|
||||
RTE.setOptionsForParameter = function ($type, $len, $text, $num) {
|
||||
/**
|
||||
* @var $no_opts a jQuery object containing the reference
|
||||
* to an element to be displayed when no
|
||||
* options are available
|
||||
*/
|
||||
var $no_opts = $text.parent().parent().find('.no_opts');
|
||||
/**
|
||||
* @var $no_len a jQuery object containing the reference
|
||||
* to an element to be displayed when no
|
||||
* "length/values" field is available
|
||||
*/
|
||||
var $no_len = $len.parent().parent().find('.no_len');
|
||||
|
||||
// Process for parameter options
|
||||
switch ($type.val()) {
|
||||
case 'TINYINT':
|
||||
case 'SMALLINT':
|
||||
case 'MEDIUMINT':
|
||||
case 'INT':
|
||||
case 'BIGINT':
|
||||
case 'DECIMAL':
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
case 'REAL':
|
||||
$text.parent().hide();
|
||||
$num.parent().show();
|
||||
$no_opts.hide();
|
||||
break;
|
||||
case 'TINYTEXT':
|
||||
case 'TEXT':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGTEXT':
|
||||
case 'CHAR':
|
||||
case 'VARCHAR':
|
||||
case 'SET':
|
||||
case 'ENUM':
|
||||
$text.parent().show();
|
||||
$num.parent().hide();
|
||||
$no_opts.hide();
|
||||
break;
|
||||
default:
|
||||
$text.parent().hide();
|
||||
$num.parent().hide();
|
||||
$no_opts.show();
|
||||
break;
|
||||
}
|
||||
// Process for parameter length
|
||||
switch ($type.val()) {
|
||||
case 'DATE':
|
||||
case 'DATETIME':
|
||||
case 'TIME':
|
||||
case 'TINYBLOB':
|
||||
case 'TINYTEXT':
|
||||
case 'BLOB':
|
||||
case 'TEXT':
|
||||
case 'MEDIUMBLOB':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGBLOB':
|
||||
case 'LONGTEXT':
|
||||
$len.parent().hide();
|
||||
$no_len.show();
|
||||
break;
|
||||
default:
|
||||
$len.parent().show();
|
||||
$no_len.hide();
|
||||
break;
|
||||
}
|
||||
}; // end RTE.setOptionsForParameter()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Routines functionalities.
|
||||
*
|
||||
* @see $cfg['AjaxEnable']
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Add parameter to routine" functionality.
|
||||
*/
|
||||
$('input[name=routine_addparameter]').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $routine_params_table jQuery object containing the reference
|
||||
* to the routine parameters table.
|
||||
*/
|
||||
var $routine_params_table = $('.routine_params_table').last();
|
||||
/**
|
||||
* @var $new_param_row A string containing the HTML code for the
|
||||
* new row for the routine paramaters table.
|
||||
*/
|
||||
var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1);
|
||||
// Append the new row to the parameters table
|
||||
$routine_params_table.append(new_param_row);
|
||||
// Make sure that the row is correctly shown according to the type of routine
|
||||
if ($('.rte_table').find('select[name=item_type]').val() === 'FUNCTION') {
|
||||
$('.routine_return_row').show();
|
||||
$('.routine_direction_cell').hide();
|
||||
}
|
||||
/**
|
||||
* @var $newrow jQuery object containing the reference to the newly
|
||||
* inserted row in the routine parameters table.
|
||||
*/
|
||||
var $newrow = $('.routine_params_table').last().find('tr').has('td').last();
|
||||
// Enable/disable the 'options' dropdowns for parameters as necessary
|
||||
RTE.setOptionsForParameter(
|
||||
$newrow.find('select[name^=item_param_type]'),
|
||||
$newrow.find('input[name^=item_param_length]'),
|
||||
$newrow.find('select[name^=item_param_opts_text]'),
|
||||
$newrow.find('select[name^=item_param_opts_num]')
|
||||
);
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Remove parameter from routine" functionality.
|
||||
*/
|
||||
$('.routine_param_remove_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
$(this).parent().parent().remove();
|
||||
// After removing a parameter, the indices of the name attributes in
|
||||
// the input fields lose the correct order and need to be reordered.
|
||||
/**
|
||||
* @var index Counter used for reindexing the input
|
||||
* fields in the routine parameters table.
|
||||
*/
|
||||
var index = 0;
|
||||
$('.routine_params_table').last().find('tr').has('td').each(function () {
|
||||
$(this).find(':input').each(function () {
|
||||
/**
|
||||
* @var inputname The value of the name attribute of
|
||||
* the input field being reindexed.
|
||||
*/
|
||||
var inputname = $(this).attr('name');
|
||||
if (inputname.substr(0, 17) === 'item_param_dir') {
|
||||
$(this).attr('name', inputname.substr(0, 17) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 18) === 'item_param_name') {
|
||||
$(this).attr('name', inputname.substr(0, 18) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 18) === 'item_param_type') {
|
||||
$(this).attr('name', inputname.substr(0, 18) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 20) === 'item_param_length') {
|
||||
$(this).attr('name', inputname.substr(0, 20) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 23) === 'item_param_opts_text') {
|
||||
$(this).attr('name', inputname.substr(0, 23) + '[' + index + ']');
|
||||
} else if (inputname.substr(0, 22) === 'item_param_opts_num') {
|
||||
$(this).attr('name', inputname.substr(0, 22) + '[' + index + ']');
|
||||
}
|
||||
});
|
||||
index++;
|
||||
});
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change routine type"
|
||||
* functionality in the routines editor, so that the correct
|
||||
* fields are shown in the editor when changing the routine type
|
||||
*/
|
||||
$('select[name=item_type]').live('change', function () {
|
||||
$('.routine_return_row, .routine_direction_cell').toggle();
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change parameter type"
|
||||
* functionality in the routines editor, so that the correct
|
||||
* option/length fields, if any, are shown when changing
|
||||
* a parameter type
|
||||
*/
|
||||
$('select[name^=item_param_type]').live('change', function () {
|
||||
/**
|
||||
* @var $row jQuery object containing the reference to
|
||||
* a row in the routine parameters table
|
||||
*/
|
||||
var $row = $(this).parents('tr').first();
|
||||
RTE.setOptionsForParameter(
|
||||
$row.find('select[name^=item_param_type]'),
|
||||
$row.find('input[name^=item_param_length]'),
|
||||
$row.find('select[name^=item_param_opts_text]'),
|
||||
$row.find('select[name^=item_param_opts_num]')
|
||||
);
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the "Change the type of return
|
||||
* variable of function" functionality, so that the correct fields,
|
||||
* if any, are shown when changing the function return type type
|
||||
*/
|
||||
$('select[name=item_returntype]').live('change', function () {
|
||||
RTE.setOptionsForParameter(
|
||||
$('.rte_table').find('select[name=item_returntype]'),
|
||||
$('.rte_table').find('input[name=item_returnlength]'),
|
||||
$('.rte_table').find('select[name=item_returnopts_text]'),
|
||||
$('.rte_table').find('select[name=item_returnopts_num]')
|
||||
);
|
||||
}); // end $.live()
|
||||
|
||||
/**
|
||||
* Attach Ajax event handlers for the Execute routine functionality.
|
||||
*/
|
||||
$('.ajax_exec_anchor').live('click', function (event) {
|
||||
event.preventDefault();
|
||||
/**
|
||||
* @var $msg jQuery object containing the reference to
|
||||
* the AJAX message shown to the user
|
||||
*/
|
||||
var $msg = PMA_ajaxShowMessage();
|
||||
$.get($(this).attr('href'), {'ajax_request': true}, function (data) {
|
||||
if (data.success === true) {
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
// If 'data.dialog' is true we show a dialog with a form
|
||||
// to get the input parameters for routine, otherwise
|
||||
// we just show the results of the query
|
||||
if (data.dialog) {
|
||||
// Define the function that is called when
|
||||
// the user presses the "Go" button
|
||||
RTE.buttonOptions[PMA_messages['strGo']] = function () {
|
||||
/**
|
||||
* @var data Form data to be sent in the AJAX request.
|
||||
*/
|
||||
var data = $('.rte_form').last().serialize();
|
||||
$msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
|
||||
$.post('db_routines.php', data, function (data) {
|
||||
if (data.success === true) {
|
||||
// Routine executed successfully
|
||||
PMA_ajaxRemoveMessage($msg);
|
||||
PMA_slidingMessage(data.message);
|
||||
$ajaxDialog.dialog('close');
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
});
|
||||
};
|
||||
RTE.buttonOptions[PMA_messages['strClose']] = function () {
|
||||
$(this).dialog("close");
|
||||
};
|
||||
/**
|
||||
* Display the dialog to the user
|
||||
*/
|
||||
$ajaxDialog = $('<div>' + data.message + '</div>').dialog({
|
||||
width: 650,
|
||||
buttons: RTE.buttonOptions,
|
||||
title: data.title,
|
||||
modal: true,
|
||||
close: function () {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$ajaxDialog.find('input[name^=params]').first().focus();
|
||||
/**
|
||||
* Attach the datepickers to the relevant form fields
|
||||
*/
|
||||
$ajaxDialog.find('.datefield, .datetimefield').each(function () {
|
||||
PMA_addDatepicker($(this).css('width', '95%'));
|
||||
});
|
||||
} else {
|
||||
// Routine executed successfully
|
||||
PMA_slidingMessage(data.message);
|
||||
}
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
}
|
||||
}); // end $.get()
|
||||
}); // end $.live()
|
||||
}); // end of $(document).ready() for the Routine Functionalities
|
||||
8
js/rte/triggers.js
Normal file
8
js/rte/triggers.js
Normal file
@ -0,0 +1,8 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* So far it looks like triggers don't need
|
||||
* any special treatment as far as JavaScript
|
||||
* goes, but leaving this file here in case
|
||||
* the need for custom code will arise.
|
||||
*/
|
||||
245
js/sql.js
245
js/sql.js
@ -28,28 +28,18 @@ function PMA_urlencode(str) {
|
||||
* for inline editing
|
||||
*
|
||||
* @param $this_field jQuery object that points to the current field's tr
|
||||
* @param disp_mode string
|
||||
*/
|
||||
function getFieldName($this_field, disp_mode) {
|
||||
function getFieldName($this_field) {
|
||||
|
||||
if(disp_mode == 'vertical') {
|
||||
var field_name = $this_field.siblings('th').find('a').text();
|
||||
// happens when just one row (headings contain no a)
|
||||
if ("" == field_name) {
|
||||
field_name = $this_field.siblings('th').text();
|
||||
}
|
||||
}
|
||||
else {
|
||||
var this_field_index = $this_field.index();
|
||||
// ltr or rtl direction does not impact how the DOM was generated
|
||||
// check if the action column in the left exist
|
||||
var leftActionExist = !$('#table_results').find('th:first').hasClass('draggable');
|
||||
// 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4
|
||||
var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ') a').text();
|
||||
// happens when just one row (headings contain no a)
|
||||
if ("" == field_name) {
|
||||
field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ')').text();
|
||||
}
|
||||
var this_field_index = $this_field.index();
|
||||
// ltr or rtl direction does not impact how the DOM was generated
|
||||
// check if the action column in the left exist
|
||||
var leftActionExist = !$('#table_results').find('th:first').hasClass('draggable');
|
||||
// 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4
|
||||
var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ') a').text();
|
||||
// happens when just one row (headings contain no a)
|
||||
if ("" == field_name) {
|
||||
field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ')').text();
|
||||
}
|
||||
|
||||
field_name = $.trim(field_name);
|
||||
@ -63,49 +53,9 @@ function getFieldName($this_field, disp_mode) {
|
||||
*
|
||||
*/
|
||||
function appendInlineAnchor() {
|
||||
// TODO: remove two lines below if vertical display mode has been completely removed
|
||||
var disp_mode = $("#top_direction_dropdown").val();
|
||||
|
||||
if (disp_mode == 'vertical') {
|
||||
// there can be one or two tr containing this class, depending
|
||||
// on the RowActionLinks cfg parameter
|
||||
$('#table_results tr')
|
||||
.find('.edit_row_anchor')
|
||||
.removeClass('edit_row_anchor')
|
||||
.parent().each(function() {
|
||||
var $this_tr = $(this);
|
||||
var $cloned_tr = $this_tr.clone();
|
||||
|
||||
var $img_object = $cloned_tr.find('img:first').attr('title', PMA_messages['strInlineEdit']);
|
||||
if ($img_object.length != 0) {
|
||||
var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
|
||||
$img_object.attr('src', img_src);
|
||||
}
|
||||
|
||||
$cloned_tr.find('td')
|
||||
.addClass('inline_edit_anchor')
|
||||
.find('a').attr('href', '#');
|
||||
var $edit_span = $cloned_tr.find('span:contains("' + PMA_messages['strEdit'] + '")');
|
||||
var $span = $cloned_tr.find('a').find('span');
|
||||
if ($edit_span.length > 0) {
|
||||
$span.text(' ' + PMA_messages['strInlineEdit']);
|
||||
$span.prepend($img_object);
|
||||
} else {
|
||||
$span.text('');
|
||||
$span.append($img_object);
|
||||
}
|
||||
|
||||
$cloned_tr.insertAfter($this_tr);
|
||||
});
|
||||
|
||||
$('#resultsForm').find('tbody').find('th').each(function() {
|
||||
var $this_th = $(this);
|
||||
if ($this_th.attr('rowspan') == 4) {
|
||||
$this_th.attr('rowspan', '5');
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// horizontal mode
|
||||
if (disp_mode != 'vertical') {
|
||||
$('.edit_row_anchor').each(function() {
|
||||
|
||||
var $this_td = $(this);
|
||||
@ -194,23 +144,6 @@ $(document).ready(function() {
|
||||
.toggle($(this).attr('value').length > 0);
|
||||
}).trigger('keyup');
|
||||
|
||||
/**
|
||||
* current value of the direction in which the table is displayed
|
||||
* @type String
|
||||
* @fieldOf jQuery
|
||||
* @name disp_mode
|
||||
*/
|
||||
var disp_mode = $("#top_direction_dropdown").val();
|
||||
|
||||
/**
|
||||
* Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
|
||||
* @memberOf jQuery
|
||||
* @name direction_dropdown_change
|
||||
*/
|
||||
$("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) {
|
||||
disp_mode = $(this).val();
|
||||
})
|
||||
|
||||
/**
|
||||
* Attach the {@link appendInlineAnchor} function to a custom event, which
|
||||
* will be triggered manually everytime the table of results is reloaded
|
||||
@ -536,95 +469,39 @@ $(document).ready(function() {
|
||||
// Add hide icon and/or text.
|
||||
$edit_td.children('span.nowrap').append($('<br /><br />')).append($hide_a);
|
||||
|
||||
if (disp_mode != 'vertical') {
|
||||
$('#table_results tbody tr td span a#hide').click(function() {
|
||||
var $this_hide = $(this).parents('td');
|
||||
$('#table_results tbody tr td span a#hide').click(function() {
|
||||
var $this_hide = $(this).parents('td');
|
||||
|
||||
var $this_span = $this_hide.find('span');
|
||||
$this_span.find('a, br').remove();
|
||||
$this_span.append($data_a.clone());
|
||||
var $this_span = $this_hide.find('span');
|
||||
$this_span.find('a, br').remove();
|
||||
$this_span.append($data_a.clone());
|
||||
|
||||
$this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
|
||||
$this_hide.parent().removeClass("hover noclick");
|
||||
$this_hide.siblings().removeClass("hover");
|
||||
$this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
|
||||
$this_hide.parent().removeClass("hover noclick");
|
||||
$this_hide.siblings().removeClass("hover");
|
||||
|
||||
var $input_siblings = $this_hide.parent('tr').find('.inline_edit');
|
||||
var txt = '';
|
||||
$input_siblings.each(function() {
|
||||
var $this_hide_siblings = $(this);
|
||||
txt = $this_hide_siblings.data('original_data');
|
||||
if($this_hide_siblings.children('span').children().length != 0) {
|
||||
$this_hide_siblings.children('span').empty();
|
||||
$this_hide_siblings.children('span').append(txt);
|
||||
}
|
||||
});
|
||||
$(this).prev().prev().remove();
|
||||
$(this).prev().remove();
|
||||
$(this).remove();
|
||||
|
||||
// refresh the grid
|
||||
$("#sqlqueryresults").trigger('refreshgrid');
|
||||
});
|
||||
} else {
|
||||
var $input_siblings = $this_hide.parent('tr').find('.inline_edit');
|
||||
var txt = '';
|
||||
var rows = $edit_td.parent().siblings().length;
|
||||
|
||||
$('#table_results tbody tr td span a#hide').click(function() {
|
||||
var $hide_a = $(this);
|
||||
var $this_hide = $(this).parents('td');
|
||||
var pos = $this_hide.index();
|
||||
|
||||
var $this_span = $hide_a.parent();
|
||||
$this_span.find('a, br').remove();
|
||||
$this_span.append($data_a.clone());
|
||||
|
||||
var $this_row = $this_span.parents('tr');
|
||||
// changing inline_edit_active to inline_edit_anchor
|
||||
$this_hide.removeClass("inline_edit_active").addClass("inline_edit_anchor");
|
||||
|
||||
// removing marked and hover classes.
|
||||
$this_row.parent('tbody').find('tr').find("td:eq(" + pos + ")").removeClass("marked hover");
|
||||
|
||||
for( var i = 0; i <= rows + 2; i++){
|
||||
if( $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").hasClass("inline_edit") == false) {
|
||||
continue;
|
||||
}
|
||||
$this_row_siblings = $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")");
|
||||
txt = $this_row_siblings.data('original_data');
|
||||
$this_row_siblings.children('span').empty();
|
||||
$this_row_siblings.children('span').append(txt);
|
||||
$input_siblings.each(function() {
|
||||
var $this_hide_siblings = $(this);
|
||||
txt = $this_hide_siblings.data('original_data');
|
||||
if($this_hide_siblings.children('span').children().length != 0) {
|
||||
$this_hide_siblings.children('span').empty();
|
||||
$this_hide_siblings.children('span').append(txt);
|
||||
}
|
||||
$(this).prev().remove();
|
||||
$(this).prev().remove();
|
||||
$(this).remove();
|
||||
|
||||
// refresh the grid
|
||||
$("#sqlqueryresults").trigger('refreshgrid');
|
||||
});
|
||||
}
|
||||
$(this).prev().prev().remove();
|
||||
$(this).prev().remove();
|
||||
$(this).remove();
|
||||
|
||||
// refresh the grid
|
||||
$("#sqlqueryresults").trigger('refreshgrid');
|
||||
});
|
||||
|
||||
// Initialize some variables
|
||||
if(disp_mode == 'vertical') {
|
||||
/**
|
||||
* @var this_row_index Index of the current <td> in the parent <tr>
|
||||
* Current <td> is the inline edit anchor.
|
||||
*/
|
||||
var this_row_index = $edit_td.index();
|
||||
/**
|
||||
* @var $input_siblings Object referring to all inline editable events from same row
|
||||
*/
|
||||
var $input_siblings = $edit_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')');
|
||||
/**
|
||||
* @var where_clause String containing the WHERE clause to select this row
|
||||
*/
|
||||
var where_clause = $edit_td.parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
|
||||
}
|
||||
// horizontal mode
|
||||
else {
|
||||
var this_row_index = $edit_td.parent().index();
|
||||
var $input_siblings = $edit_td.parent('tr').find('.inline_edit');
|
||||
var where_clause = $edit_td.parent('tr').find('.where_clause').val();
|
||||
}
|
||||
var this_row_index = $edit_td.parent().index();
|
||||
var $input_siblings = $edit_td.parent('tr').find('.inline_edit');
|
||||
var where_clause = $edit_td.parent('tr').find('.where_clause').val();
|
||||
|
||||
$input_siblings.each(function() {
|
||||
/** @lends jQuery */
|
||||
@ -648,7 +525,7 @@ $(document).ready(function() {
|
||||
* @var field_name String containing the name of this field.
|
||||
* @see getFieldName()
|
||||
*/
|
||||
var field_name = getFieldName($this_field, disp_mode);
|
||||
var field_name = getFieldName($this_field);
|
||||
/**
|
||||
* @var relation_curr_value String current value of the field (for fields that are foreign keyed).
|
||||
*/
|
||||
@ -859,24 +736,8 @@ $(document).ready(function() {
|
||||
var $test_element = ''; // to test the presence of a element
|
||||
|
||||
// Initialize variables
|
||||
if(disp_mode == 'vertical') {
|
||||
/**
|
||||
* @var this_td_index Index of the current <td> in the parent <tr>
|
||||
* Current <td> is the inline edit anchor.
|
||||
*/
|
||||
var this_td_index = $this_td.index();
|
||||
/**
|
||||
* @var $input_siblings Object referring to all inline editable events from same row
|
||||
*/
|
||||
var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')');
|
||||
/**
|
||||
* @var where_clause String containing the WHERE clause to select this row
|
||||
*/
|
||||
var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val();
|
||||
} else {
|
||||
var $input_siblings = $this_td.parent('tr').find('.inline_edit');
|
||||
var where_clause = $this_td.parent('tr').find('.where_clause').val();
|
||||
}
|
||||
var $input_siblings = $this_td.parent('tr').find('.inline_edit');
|
||||
var where_clause = $this_td.parent('tr').find('.where_clause').val();
|
||||
|
||||
/**
|
||||
* @var nonunique Boolean, whether this row is unique or not
|
||||
@ -927,7 +788,7 @@ $(document).ready(function() {
|
||||
* @var field_name String containing the name of this field.
|
||||
* @see getFieldName()
|
||||
*/
|
||||
var field_name = getFieldName($this_field, disp_mode);
|
||||
var field_name = getFieldName($this_field);
|
||||
|
||||
/**
|
||||
* @var this_field_params Array temporary storage for the name/value of current field
|
||||
@ -1027,7 +888,6 @@ $(document).ready(function() {
|
||||
*/
|
||||
var post_params = {'ajax_request' : true,
|
||||
'sql_query' : sql_query,
|
||||
'disp_direction' : disp_mode,
|
||||
'token' : window.parent.token,
|
||||
'db' : window.parent.db,
|
||||
'table' : window.parent.table,
|
||||
@ -1044,19 +904,14 @@ $(document).ready(function() {
|
||||
$.post('tbl_replace.php', post_params, function(data) {
|
||||
if(data.success == true) {
|
||||
PMA_ajaxShowMessage(data.message);
|
||||
if(disp_mode == 'vertical') {
|
||||
$this_td.parents('tbody').find('tr').find('.where_clause:nth(' + this_td_index + ')').attr('value', new_clause);
|
||||
}
|
||||
else {
|
||||
$this_td.parent('tr').find('.where_clause').attr('value', new_clause);
|
||||
}
|
||||
$this_td.parent('tr').find('.where_clause').attr('value', new_clause);
|
||||
// remove possible previous feedback message
|
||||
$('#result_query').remove();
|
||||
if (typeof data.sql_query != 'undefined') {
|
||||
// display feedback
|
||||
$('#sqlqueryresults').prepend(data.sql_query);
|
||||
}
|
||||
PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode);
|
||||
PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data);
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error);
|
||||
};
|
||||
@ -1064,7 +919,7 @@ $(document).ready(function() {
|
||||
} else {
|
||||
// no posting was done but still need to display the row
|
||||
// in its previous format
|
||||
PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '', disp_mode);
|
||||
PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '');
|
||||
}
|
||||
}) // End After editing, clicking again should post data
|
||||
|
||||
@ -1229,7 +1084,7 @@ $(document).ready(function() {
|
||||
* (when called in the situation where no posting was done, the data
|
||||
* parameter is empty)
|
||||
*/
|
||||
function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode) {
|
||||
function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data) {
|
||||
|
||||
// deleting the hide button. remove <br><br><a> tags
|
||||
$del_hide.find('a, br').remove();
|
||||
@ -1241,11 +1096,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings,
|
||||
|
||||
// removing hover, marked and noclick classes
|
||||
$this_td.parent('tr').removeClass('noclick');
|
||||
if(disp_mode != 'vertical') {
|
||||
$this_td.parent('tr').removeClass('hover').find('td').removeClass('hover');
|
||||
} else {
|
||||
$this_td.parents('tbody').find('tr').find('td:eq(' + $this_td.index() + ')').removeClass('marked hover');
|
||||
}
|
||||
$this_td.parent('tr').removeClass('hover').find('td').removeClass('hover');
|
||||
|
||||
$input_siblings.each(function() {
|
||||
// Inline edit post has been successful.
|
||||
@ -1265,7 +1116,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings,
|
||||
var new_html = $this_sibling.find('textarea').val();
|
||||
|
||||
if($this_sibling.is('.transformed')) {
|
||||
var field_name = getFieldName($this_sibling, disp_mode);
|
||||
var field_name = getFieldName($this_sibling);
|
||||
if (typeof data.transformations != 'undefined') {
|
||||
$.each(data.transformations, function(key, value) {
|
||||
if(key == field_name) {
|
||||
@ -1294,7 +1145,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings,
|
||||
}
|
||||
|
||||
if($this_sibling.is('.relation')) {
|
||||
var field_name = getFieldName($this_sibling, disp_mode);
|
||||
var field_name = getFieldName($this_sibling);
|
||||
if (typeof data.relations != 'undefined') {
|
||||
$.each(data.relations, function(key, value) {
|
||||
if(key == field_name) {
|
||||
|
||||
@ -363,6 +363,7 @@ $goto_whitelist = array(
|
||||
'db_create.php',
|
||||
'db_datadict.php',
|
||||
'db_sql.php',
|
||||
'db_events.php',
|
||||
'db_export.php',
|
||||
'db_importdocsql.php',
|
||||
'db_qbe.php',
|
||||
|
||||
@ -140,10 +140,10 @@ function PMA_displayMaximumUploadSize($max_upload_size)
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function PMA_generateHiddenMaxFileSize($max_size)
|
||||
{
|
||||
return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
|
||||
}
|
||||
function PMA_generateHiddenMaxFileSize($max_size)
|
||||
{
|
||||
return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add slashes before "'" and "\" characters so a value containing them can
|
||||
@ -377,7 +377,7 @@ function PMA_showMySQLDocu($chapter, $link, $big_icon = false, $anchor = '', $ju
|
||||
$mysql = '5.1';
|
||||
/* l10n: Language to use for MySQL 5.1 documentation, please use only languages which do exist in official documentation. */
|
||||
$lang = _pgettext('MySQL 5.1 documentation language', 'en');
|
||||
} elseif (PMA_MYSQL_INT_VERSION >= 50000) {
|
||||
} else {
|
||||
$mysql = '5.0';
|
||||
/* l10n: Language to use for MySQL 5.0 documentation, please use only languages which do exist in official documentation. */
|
||||
$lang = _pgettext('MySQL 5.0 documentation language', 'en');
|
||||
@ -707,7 +707,7 @@ function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count =
|
||||
$group_name_full = '';
|
||||
$parts_cnt = count($parts) - 1;
|
||||
while ($i < $parts_cnt
|
||||
&& $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
|
||||
&& $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
|
||||
$group_name = $parts[$i] . $sep;
|
||||
$group_name_full .= $group_name;
|
||||
|
||||
@ -739,7 +739,7 @@ function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count =
|
||||
|
||||
|
||||
if ($GLOBALS['cfg']['ShowTooltipAliasTB']
|
||||
&& $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
|
||||
&& $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
|
||||
// switch tooltip and name
|
||||
$table['Comment'] = $table['Name'];
|
||||
$table['disp_name'] = $table['Comment'];
|
||||
@ -807,8 +807,6 @@ function PMA_backquote($a_name, $do_it = true)
|
||||
*/
|
||||
function PMA_whichCrlf()
|
||||
{
|
||||
$the_crlf = "\n";
|
||||
|
||||
// The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php"
|
||||
// Win case
|
||||
if (PMA_USR_OS == 'Win') {
|
||||
@ -825,15 +823,12 @@ function PMA_whichCrlf()
|
||||
/**
|
||||
* Reloads navigation if needed.
|
||||
*
|
||||
* @param $jsonly prints out pure JavaScript
|
||||
* @global array configuration
|
||||
* @param bool $jsonly prints out pure JavaScript
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function PMA_reloadNavigation($jsonly=false)
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
// Reloads the navigation frame via JavaScript if required
|
||||
if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
|
||||
// one of the reasons for a reload is when a table is dropped
|
||||
@ -869,7 +864,7 @@ if (!$jsonly)
|
||||
* @param string $sql_query the query to display
|
||||
* @param string $type the type (level) of the message
|
||||
* @param boolean $is_view is this a message after a VIEW operation?
|
||||
* @global array the configuration array
|
||||
* @return string
|
||||
* @access public
|
||||
*/
|
||||
function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view = false)
|
||||
@ -1218,6 +1213,7 @@ function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view
|
||||
ob_end_clean();
|
||||
return $buffer_contents;
|
||||
}
|
||||
return null;
|
||||
} // end of the 'PMA_showMessage()' function
|
||||
|
||||
/**
|
||||
@ -1225,7 +1221,6 @@ function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view
|
||||
*
|
||||
* @access public
|
||||
* @return boolean whether profiling is supported
|
||||
*
|
||||
*/
|
||||
function PMA_profilingSupported()
|
||||
{
|
||||
@ -1250,7 +1245,6 @@ function PMA_profilingSupported()
|
||||
*
|
||||
* @param string $sql_query
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
function PMA_profilingCheckbox($sql_query)
|
||||
{
|
||||
@ -1350,8 +1344,6 @@ function PMA_localizeNumber($value)
|
||||
* @return string the formatted value and its unit
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @version 1.1.0 - 2005-10-27
|
||||
*/
|
||||
function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_down = false, $noTrailingZero = true)
|
||||
{
|
||||
@ -1769,7 +1761,7 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
|
||||
}
|
||||
} // end if... else...
|
||||
|
||||
return $ret;
|
||||
return $ret;
|
||||
} // end of the 'PMA_linkOrButton()' function
|
||||
|
||||
|
||||
@ -1843,7 +1835,6 @@ function PMA_flipstring($string, $Separator = "<br />\n")
|
||||
return $format_string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function added to avoid path disclosures.
|
||||
* Called by each script that needs parameters, it displays
|
||||
@ -1930,9 +1921,8 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force
|
||||
$meta->orgname = $meta->name;
|
||||
|
||||
if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
|
||||
&& is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
|
||||
foreach ($GLOBALS['analyzed_sql'][0]['select_expr']
|
||||
as $select_expr) {
|
||||
&& is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
|
||||
foreach ($GLOBALS['analyzed_sql'][0]['select_expr'] as $select_expr) {
|
||||
// need (string) === (string)
|
||||
// '' !== 0 but '' == 0
|
||||
if ((string) $select_expr['alias'] === (string) $meta->name) {
|
||||
@ -1980,18 +1970,18 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force
|
||||
$condition .= '= ' . $row[$i] . ' AND';
|
||||
} elseif (($meta->type == 'blob' || $meta->type == 'string')
|
||||
// hexify only if this is a true not empty BLOB or a BINARY
|
||||
&& stristr($field_flags, 'BINARY')
|
||||
&& !empty($row[$i])) {
|
||||
// do not waste memory building a too big condition
|
||||
if (strlen($row[$i]) < 1000) {
|
||||
// use a CAST if possible, to avoid problems
|
||||
// if the field contains wildcard characters % or _
|
||||
$condition .= '= CAST(0x' . bin2hex($row[$i])
|
||||
. ' AS BINARY) AND';
|
||||
} else {
|
||||
// this blob won't be part of the final condition
|
||||
$condition = '';
|
||||
}
|
||||
&& stristr($field_flags, 'BINARY')
|
||||
&& !empty($row[$i])) {
|
||||
// do not waste memory building a too big condition
|
||||
if (strlen($row[$i]) < 1000) {
|
||||
// use a CAST if possible, to avoid problems
|
||||
// if the field contains wildcard characters % or _
|
||||
$condition .= '= CAST(0x' . bin2hex($row[$i])
|
||||
. ' AS BINARY) AND';
|
||||
} else {
|
||||
// this blob won't be part of the final condition
|
||||
$condition = '';
|
||||
}
|
||||
} elseif ($meta->type == 'bit') {
|
||||
$condition .= "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "' AND";
|
||||
} else {
|
||||
@ -2167,12 +2157,12 @@ function PMA_pageselector($rows, $pageNow = 1, $nbTotalPage = 1,
|
||||
* Generate navigation for a list
|
||||
*
|
||||
* @todo use $pos from $_url_params
|
||||
* @param integer number of elements in the list
|
||||
* @param integer current position in the list
|
||||
* @param array url parameters
|
||||
* @param string script name for form target
|
||||
* @param string target frame
|
||||
* @param integer maximum number of elements to display from the list
|
||||
* @param int $count number of elements in the list
|
||||
* @param int $pos current position in the list
|
||||
* @param array $_url_params url parameters
|
||||
* @param string $script script name for form target
|
||||
* @param string $frame target frame
|
||||
* @param int $max_count maximum number of elements to display from the list
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
@ -2354,10 +2344,11 @@ function PMA_display_html_radio($html_field_name, $choices, $checked_choice = ''
|
||||
* Generates and returns an HTML dropdown
|
||||
*
|
||||
* @param string $select_name
|
||||
* @param array $choices the choices values
|
||||
* @param string $active_choice the choice to select by default
|
||||
* @param string $id the id of the select element; can be different in case
|
||||
* the dropdown is present more than once on the page
|
||||
* @param array $choices choices values
|
||||
* @param string $active_choice the choice to select by default
|
||||
* @param string $id id of the select element; can be different in case
|
||||
* the dropdown is present more than once on the page
|
||||
* @return string
|
||||
* @todo support titles
|
||||
*/
|
||||
function PMA_generate_html_dropdown($select_name, $choices, $active_choice, $id)
|
||||
@ -2401,6 +2392,87 @@ function PMA_generate_slider_effect($id, $message)
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AJAX sliding toggle button (or and equivalent form when AJAX is disabled)
|
||||
*
|
||||
* @param string $action The URL for the request to be executed
|
||||
* @param string $select_name The name for the dropdown box
|
||||
* @param array $options An array of options (see rte_footer.lib.php)
|
||||
* @param string $callback A JS snippet to execute when the request is
|
||||
* successfully processed
|
||||
*
|
||||
* @return string HTML code for the toggle button
|
||||
*/
|
||||
function PMA_toggleButton($action, $select_name, $options, $callback)
|
||||
{
|
||||
// Do the logic first
|
||||
$link_on = "$action&$select_name=" . urlencode($options[1]['value']);
|
||||
$link_off = "$action&$select_name=" . urlencode($options[0]['value']);
|
||||
if ($options[1]['selected'] == true) {
|
||||
$state = 'on';
|
||||
} else if ($options[0]['selected'] == true) {
|
||||
$state = 'off';
|
||||
} else {
|
||||
$state = 'on';
|
||||
}
|
||||
$selected1 = '';
|
||||
$selected0 = '';
|
||||
if ($options[1]['selected'] == true) {
|
||||
$selected1 = " selected='selected'";
|
||||
} else if ($options[0]['selected'] == true) {
|
||||
$selected0 = " selected='selected'";
|
||||
}
|
||||
// Generate output
|
||||
$retval = "<!-- TOGGLE START -->\n";
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$retval .= "<noscript>\n";
|
||||
}
|
||||
$retval .= "<div class='wrapper'>\n";
|
||||
$retval .= " <form action='$action' method='post'>\n";
|
||||
$retval .= " <select name='$select_name'>\n";
|
||||
$retval .= " <option value='{$options[1]['value']}'$selected1>";
|
||||
$retval .= " {$options[1]['label']}\n";
|
||||
$retval .= " </option>\n";
|
||||
$retval .= " <option value='{$options[0]['value']}'$selected0>";
|
||||
$retval .= " {$options[0]['label']}\n";
|
||||
$retval .= " </option>\n";
|
||||
$retval .= " </select>\n";
|
||||
$retval .= " <input type='submit' value='" . __('Change') . "'/>\n";
|
||||
$retval .= " </form>\n";
|
||||
$retval .= "</div>\n";
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$retval .= "</noscript>\n";
|
||||
$retval .= "<div class='wrapper toggleAjax hide'>\n";
|
||||
$retval .= " <div class='toggleButton'>\n";
|
||||
$retval .= " <div title='" . __('Click to toggle') . "' class='container $state'>\n";
|
||||
$retval .= " <img src='{$GLOBALS['pmaThemeImage']}toggle-{$GLOBALS['text_dir']}.png'\n";
|
||||
$retval .= " alt='' />\n";
|
||||
$retval .= " <table cellspacing='0' cellpadding='0'><tr>\n";
|
||||
$retval .= " <tbody>\n";
|
||||
$retval .= " <td class='toggleOn'>\n";
|
||||
$retval .= " <span class='hide'>$link_on</span>\n";
|
||||
$retval .= " <div>";
|
||||
$retval .= str_replace(' ', ' ', $options[1]['label']) . "</div>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td><div> </div></td>\n";
|
||||
$retval .= " <td class='toggleOff'>\n";
|
||||
$retval .= " <span class='hide'>$link_off</span>\n";
|
||||
$retval .= " <div>";
|
||||
$retval .= str_replace(' ', ' ', $options[0]['label']) . "</div>\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= " </tbody>\n";
|
||||
$retval .= " </tr></table>\n";
|
||||
$retval .= " <span class='hide callback'>$callback</span>\n";
|
||||
$retval .= " <span class='hide text_direction'>{$GLOBALS['text_dir']}</span>\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= "</div>\n";
|
||||
}
|
||||
$retval .= "<!-- TOGGLE END -->";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_toggleButton()
|
||||
|
||||
/**
|
||||
* Clears cache content which needs to be refreshed on user change.
|
||||
*/
|
||||
@ -2411,8 +2483,8 @@ function PMA_clearUserCache() {
|
||||
/**
|
||||
* Verifies if something is cached in the session
|
||||
*
|
||||
* @param string $var
|
||||
* @param scalar $server
|
||||
* @param string $var
|
||||
* @param int|true $server
|
||||
* @return boolean
|
||||
*/
|
||||
function PMA_cacheExists($var, $server = 0)
|
||||
@ -2426,8 +2498,8 @@ function PMA_cacheExists($var, $server = 0)
|
||||
/**
|
||||
* Gets cached information from the session
|
||||
*
|
||||
* @param string $var
|
||||
* @param scalar $server
|
||||
* @param string $var
|
||||
* @param int|true $server
|
||||
* @return mixed
|
||||
*/
|
||||
function PMA_cacheGet($var, $server = 0)
|
||||
@ -2445,9 +2517,9 @@ function PMA_cacheGet($var, $server = 0)
|
||||
/**
|
||||
* Caches information in the session
|
||||
*
|
||||
* @param string $var
|
||||
* @param mixed $val
|
||||
* @param integer $server
|
||||
* @param string $var
|
||||
* @param mixed $val
|
||||
* @param int|true $server
|
||||
* @return mixed
|
||||
*/
|
||||
function PMA_cacheSet($var, $val = null, $server = 0)
|
||||
@ -2461,8 +2533,8 @@ function PMA_cacheSet($var, $val = null, $server = 0)
|
||||
/**
|
||||
* Removes cached information from the session
|
||||
*
|
||||
* @param string $var
|
||||
* @param scalar $server
|
||||
* @param string $var
|
||||
* @param int|true $server
|
||||
*/
|
||||
function PMA_cacheUnset($var, $server = 0)
|
||||
{
|
||||
@ -3077,6 +3149,7 @@ function PMA_getFunctionsForField($field, $insert_mode)
|
||||
* string, db name where to also check for privileges
|
||||
* @param mixed $tbl null, to only check global privileges
|
||||
* string, db name where to also check for privileges
|
||||
* @return bool
|
||||
*/
|
||||
function PMA_currentUserHasPrivilege($priv, $db = null, $tbl = null)
|
||||
{
|
||||
|
||||
@ -2315,7 +2315,7 @@ $cfg['ShowPropertyComments']= true;
|
||||
/**
|
||||
* shows table display direction.
|
||||
*/
|
||||
$cfg['ShowDisplayDir'] = false;
|
||||
$cfg['ShowDisplayDirection'] = false;
|
||||
|
||||
/**
|
||||
* repeat header names every X cells? (0 = deactivate)
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
/**
|
||||
* Messages for phpMyAdmin.
|
||||
*
|
||||
* This file is here for easy transition to Gettext. You should not add any
|
||||
* new messages here, use instead gettext directly in your template/PHP
|
||||
* file.
|
||||
* This file defines variables in a special format suited for the
|
||||
* configuration subsystem, with $strConfig as a prefix, _desc or _name
|
||||
* as a suffix, and the directive name in between.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
@ -450,8 +450,8 @@ $strConfigShowAll_name = __('Allow to display all the rows');
|
||||
$strConfigShowChgPassword_desc = __('Please note that enabling this has no effect with [kbd]config[/kbd] authentication mode because the password is hard coded in the configuration file; this does not limit the ability to execute the same command directly');
|
||||
$strConfigShowChgPassword_name = __('Show password change form');
|
||||
$strConfigShowCreateDb_name = __('Show create database form');
|
||||
$strConfigShowDisplayDir_desc = __('Defines whether or not type display direction option is shown when browsing a table');
|
||||
$strConfigShowDisplayDir_name = __('Show display direction');
|
||||
$strConfigShowDisplayDirection_desc = __('Defines whether or not type display direction option is shown when browsing a table');
|
||||
$strConfigShowDisplayDirection_name = __('Show display direction');
|
||||
$strConfigShowFieldTypesInDataEditView_desc = __('Defines whether or not type fields should be initially displayed in edit/insert mode');
|
||||
$strConfigShowFieldTypesInDataEditView_name = __('Show field types');
|
||||
$strConfigShowFunctionFields_desc = __('Display the function fields in edit/insert mode');
|
||||
|
||||
@ -198,7 +198,7 @@ $forms['Main_frame']['Browse'] = array(
|
||||
'Order',
|
||||
'BrowsePointerEnable',
|
||||
'BrowseMarkerEnable',
|
||||
'ShowDisplayDir',
|
||||
'ShowDisplayDirection',
|
||||
'RepeatCells',
|
||||
'LimitChars',
|
||||
'RowActionLinks',
|
||||
|
||||
@ -108,7 +108,7 @@ $forms['Main_frame']['Browse'] = array(
|
||||
'DisplayBinaryAsHex',
|
||||
'BrowsePointerEnable',
|
||||
'BrowseMarkerEnable',
|
||||
'ShowDisplayDir',
|
||||
'ShowDisplayDirection',
|
||||
'RepeatCells',
|
||||
'LimitChars',
|
||||
'RowActionLinks',
|
||||
|
||||
@ -1300,7 +1300,7 @@ function PMA_DBI_get_triggers($db, $table = '', $delimiter = '//')
|
||||
// Note: in http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html
|
||||
// their example uses WHERE TRIGGER_SCHEMA='dbname' so let's use this
|
||||
// instead of WHERE EVENT_OBJECT_SCHEMA='dbname'
|
||||
$query = "SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA= '" . PMA_sqlAddSlashes($db,true) . "';";
|
||||
$query = "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 TRIGGER_SCHEMA= '" . PMA_sqlAddSlashes($db,true) . "';";
|
||||
if (! empty($table)) {
|
||||
$query .= " AND EVENT_OBJECT_TABLE = '" . PMA_sqlAddSlashes($table, true) . "';";
|
||||
}
|
||||
@ -1319,12 +1319,15 @@ function PMA_DBI_get_triggers($db, $table = '', $delimiter = '//')
|
||||
$trigger['EVENT_MANIPULATION'] = $trigger['Event'];
|
||||
$trigger['EVENT_OBJECT_TABLE'] = $trigger['Table'];
|
||||
$trigger['ACTION_STATEMENT'] = $trigger['Statement'];
|
||||
$trigger['DEFINER'] = $trigger['Definer'];
|
||||
}
|
||||
$one_result = array();
|
||||
$one_result['name'] = $trigger['TRIGGER_NAME'];
|
||||
$one_result['table'] = $trigger['EVENT_OBJECT_TABLE'];
|
||||
$one_result['action_timing'] = $trigger['ACTION_TIMING'];
|
||||
$one_result['event_manipulation'] = $trigger['EVENT_MANIPULATION'];
|
||||
$one_result['definition'] = $trigger['ACTION_STATEMENT'];
|
||||
$one_result['definer'] = $trigger['DEFINER'];
|
||||
|
||||
// do not prepend the schema name; this way, importing the
|
||||
// definition into another schema will work
|
||||
@ -1335,6 +1338,14 @@ function PMA_DBI_get_triggers($db, $table = '', $delimiter = '//')
|
||||
$result[] = $one_result;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort results by name
|
||||
$name = array();
|
||||
foreach($result as $key => $value) {
|
||||
$name[] = $value['name'];
|
||||
}
|
||||
array_multisort($name, SORT_ASC, $result);
|
||||
|
||||
return($result);
|
||||
}
|
||||
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$events = PMA_DBI_fetch_result('SELECT EVENT_NAME, EVENT_TYPE FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \'' . PMA_sqlAddSlashes($db,true) . '\';');
|
||||
|
||||
$conditional_class_add = '';
|
||||
$conditional_class_drop = '';
|
||||
$conditional_class_export = '';
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$conditional_class_add = 'class="add_event_anchor"';
|
||||
$conditional_class_drop = 'class="drop_event_anchor"';
|
||||
$conditional_class_export = 'class="export_event_anchor"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the export for a event. This is for when JS is disabled.
|
||||
*/
|
||||
if (! empty($_GET['exportevent']) && ! empty($_GET['eventname'])) {
|
||||
$event_name = htmlspecialchars(PMA_backquote($_GET['eventname']));
|
||||
if ($create_event = PMA_DBI_get_definition($db, 'EVENT', $_GET['eventname'])) {
|
||||
$create_event = '<textarea cols="40" rows="15" style="width: 100%;">' . $create_event . '</textarea>';
|
||||
if (! empty($_REQUEST['ajax_request'])) {
|
||||
$extra_data = array('title' => sprintf(__('Export of event %s'), $event_name));
|
||||
PMA_ajaxResponse($create_event, true, $extra_data);
|
||||
} else {
|
||||
echo '<fieldset>' . "\n"
|
||||
. ' <legend>' . sprintf(__('Export of event "%s"'), $event_name) . '</legend>' . "\n"
|
||||
. $create_event
|
||||
. '</fieldset>';
|
||||
}
|
||||
} else {
|
||||
$response = __('Error in Processing Request') . ' : '
|
||||
. sprintf(__('No event with name %s found in database %s'),
|
||||
$event_name, htmlspecialchars(PMA_backquote($db)));
|
||||
$response = PMA_message::error($response);
|
||||
if (! empty($_REQUEST['ajax_request'])) {
|
||||
PMA_ajaxResponse($response, false);
|
||||
} else {
|
||||
$response->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of available events
|
||||
*/
|
||||
echo "\n\n<span id='js_query_display'></span>\n\n";
|
||||
echo '<fieldset>' . "\n";
|
||||
echo ' <legend>' . __('Events') . '</legend>' . "\n";
|
||||
if (! $events) {
|
||||
echo __('There are no events to display.');
|
||||
} else {
|
||||
echo '<div class="hide" id="nothing2display">' . __('There are no events to display.') . '</div>';
|
||||
echo '<table class="data">';
|
||||
echo sprintf('<tr>
|
||||
<th>%s</th>
|
||||
<th colspan="3">%s</th>
|
||||
<th>%s</th>
|
||||
</tr>',
|
||||
__('Name'),
|
||||
__('Action'),
|
||||
__('Type'));
|
||||
$ct=0;
|
||||
$delimiter = '//';
|
||||
foreach ($events as $event) {
|
||||
|
||||
// information_schema (at least in MySQL 5.1.22) does not return
|
||||
// the full CREATE EVENT statement in a way that could be useful for us
|
||||
// so we rely on PMA_DBI_get_definition() which uses SHOW CREATE EVENT
|
||||
|
||||
$create_event = PMA_DBI_get_definition($db, 'EVENT', $event['EVENT_NAME']);
|
||||
$definition = 'DROP EVENT IF EXISTS ' . PMA_backquote($event['EVENT_NAME'])
|
||||
. $delimiter . "\n" . $create_event . "\n";
|
||||
|
||||
$sqlDrop = 'DROP EVENT ' . PMA_backquote($event['EVENT_NAME']);
|
||||
echo sprintf('<tr class="%s">
|
||||
<td><span class="drop_sql" style="display:none;">%s</span><strong>%s</strong></td>
|
||||
<td>%s</td>
|
||||
<td><div class="create_sql" style="display: none;">%s</div>%s</td>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
</tr>',
|
||||
($ct%2 == 0) ? 'even' : 'odd',
|
||||
$sqlDrop,
|
||||
$event['EVENT_NAME'],
|
||||
! empty($definition) ? PMA_linkOrButton('db_sql.php?' . $url_query . '&sql_query=' . urlencode($definition) . '&show_query=1&db_query_force=1&delimiter=' . urlencode($delimiter), $titles['Edit']) : ' ',
|
||||
$create_event,
|
||||
'<a ' . $conditional_class_export . ' href="db_events.php?' . $url_query
|
||||
. '&exportevent=1'
|
||||
. '&eventname=' . urlencode($event['EVENT_NAME'])
|
||||
. '">' . $titles['Export'] . '</a>',
|
||||
'<a ' . $conditional_class_drop . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sqlDrop) . '" >' . $titles['Drop'] . '</a>',
|
||||
$event['EVENT_TYPE']);
|
||||
$ct++;
|
||||
}
|
||||
echo '</table>';
|
||||
}
|
||||
echo '</fieldset>' . "\n";
|
||||
|
||||
/**
|
||||
* If there has been a request to change the state
|
||||
* of the event scheduler, process it now.
|
||||
*/
|
||||
if (! empty($_GET['toggle_scheduler'])) {
|
||||
$new_scheduler_state = $_GET['toggle_scheduler'];
|
||||
if ($new_scheduler_state === 'ON' || $new_scheduler_state === 'OFF') {
|
||||
PMA_DBI_query("SET GLOBAL event_scheduler='$new_scheduler_state'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare to show the event scheduler fieldset, if necessary
|
||||
*/
|
||||
$tableStart = '';
|
||||
$schedulerFieldset = '';
|
||||
$es_state = PMA_DBI_fetch_value("SHOW GLOBAL VARIABLES LIKE 'event_scheduler'", 0, 1);
|
||||
if ($es_state === 'ON' || $es_state === 'OFF') {
|
||||
$es_change = ($es_state == 'ON') ? 'OFF' : 'ON';
|
||||
$tableStart = '<table style="width: 100%;"><tr><td style="width: 50%;">';
|
||||
$schedulerFieldset = '</td><td><fieldset style="margin: 1em 0;">' . "\n"
|
||||
. PMA_getIcon('b_events.png')
|
||||
. ($es_state === 'ON' ? __('The event scheduler is enabled') : __('The event scheduler is disabled')) . ':'
|
||||
. ' <a href="db_events.php?' . $url_query . '&toggle_scheduler=' . $es_change . '">'
|
||||
. ($es_change === 'ON' ? __('Turn it on') : __('Turn it off'))
|
||||
. '</a>' . "\n"
|
||||
. '</fieldset></td></tr></table>' . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the form for adding a new event
|
||||
*/
|
||||
echo $tableStart . '<fieldset style="margin: 1em 0;">' . "\n"
|
||||
. ' <a href="db_events.php?' . $url_query . '&addevent=1" ' . $conditional_class_add . '>' . "\n"
|
||||
. PMA_getIcon('b_event_add.png') . __('Add an event') . '</a>' . "\n"
|
||||
. '</fieldset>' . "\n";
|
||||
|
||||
/**
|
||||
* Display the state of the event scheduler
|
||||
* and offer an option to toggle it.
|
||||
*/
|
||||
echo $schedulerFieldset;
|
||||
|
||||
?>
|
||||
@ -121,16 +121,18 @@ if (! $db_is_information_schema) {
|
||||
if ($is_superuser) {
|
||||
$tabs[] =& $tab_privileges;
|
||||
}
|
||||
if (PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) {
|
||||
if (!PMA_DRIZZLE) {
|
||||
$tabs[] =& $tab_routines;
|
||||
}
|
||||
if (PMA_MYSQL_INT_VERSION >= 50106 && ! PMA_DRIZZLE) {
|
||||
// Temporarily hiding this unfinished feature
|
||||
// $tabs[] =& $tab_events;
|
||||
if (PMA_currentUserHasPrivilege('EVENT', $db)) {
|
||||
$tabs[] =& $tab_events;
|
||||
}
|
||||
}
|
||||
if (PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) {
|
||||
// Temporarily hiding this unfinished feature
|
||||
// $tabs[] =& $tab_triggers;
|
||||
if (!PMA_DRIZZLE) {
|
||||
if (PMA_currentUserHasPrivilege('TRIGGER', $db)) {
|
||||
$tabs[] =& $tab_triggers;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PMA_Tracker::isActive()) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -438,7 +438,7 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di
|
||||
<?php echo __('Number of rows') . ': ' . "\n"; ?>
|
||||
<input type="text" name="session_max_rows" size="3" value="<?php echo (($_SESSION['tmp_user_values']['max_rows'] != 'all') ? $_SESSION['tmp_user_values']['max_rows'] : $GLOBALS['cfg']['MaxRows']); ?>" class="textfield" onfocus="this.select()" />
|
||||
<?php
|
||||
if ($GLOBALS['cfg']['ShowDisplayDir']) {
|
||||
if ($GLOBALS['cfg']['ShowDisplayDirection']) {
|
||||
// Display mode (horizontal/vertical and repeat headers)
|
||||
echo __('Mode') . ': ' . "\n";
|
||||
$choices = array(
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$url_query .= '&goto=tbl_triggers.php';
|
||||
|
||||
$triggers = PMA_DBI_get_triggers($db, $table);
|
||||
|
||||
$conditional_class_add = '';
|
||||
$conditional_class_drop = '';
|
||||
$conditional_class_export = '';
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$conditional_class_add = 'class="add_trigger_anchor"';
|
||||
$conditional_class_drop = 'class="drop_trigger_anchor"';
|
||||
$conditional_class_export = 'class="export_trigger_anchor"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the export for a trigger. This is for when JS is disabled.
|
||||
*/
|
||||
if (! empty($_GET['exporttrigger']) && ! empty($_GET['triggername'])) {
|
||||
$success = false;
|
||||
foreach ($triggers as $trigger) {
|
||||
if ($trigger['name'] === $_GET['triggername']) {
|
||||
$success = true;
|
||||
$trigger_name = htmlspecialchars(PMA_backquote($_GET['triggername']));
|
||||
$create_trig = '<textarea cols="40" rows="15" style="width: 100%;">' . $trigger['create'] . '</textarea>';
|
||||
if (! empty($_REQUEST['ajax_request'])) {
|
||||
$extra_data = array('title' => sprintf(__('Export of trigger %s'), $trigger_name));
|
||||
PMA_ajaxResponse($create_trig, true, $extra_data);
|
||||
} else {
|
||||
echo '<fieldset>' . "\n"
|
||||
. ' <legend>' . sprintf(__('Export of trigger "%s"'), $trigger_name) . '</legend>' . "\n"
|
||||
. $create_trig
|
||||
. '</fieldset>';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! $success) {
|
||||
$response = __('Error in Processing Request') . ' : '
|
||||
. sprintf(__('No trigger with name %s found'), $event_name);
|
||||
$response = PMA_message::error($response);
|
||||
if (! empty($_REQUEST['ajax_request'])) {
|
||||
PMA_ajaxResponse($response, false);
|
||||
} else {
|
||||
$response->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of available triggers
|
||||
*/
|
||||
echo "\n\n<span id='js_query_display'></span>\n\n";
|
||||
echo '<fieldset>' . "\n";
|
||||
echo ' <legend>' . __('Triggers') . '</legend>' . "\n";
|
||||
if (! $triggers) {
|
||||
echo __('There are no triggers to display.');
|
||||
} else {
|
||||
echo '<div class="hide" id="nothing2display">' . __('There are no triggers to display.') . '</div>';
|
||||
echo '<table class="data">' . "\n";
|
||||
|
||||
// Print table header
|
||||
echo "<tr>\n<th>" . __('Name') . "</th>\n";
|
||||
if (empty($table)) {
|
||||
// if we don't have a table name, we will be showing the per-database list.
|
||||
// so we must specify which table each trigger belongs to
|
||||
echo "<th>" . __('Table') . "</th>\n";
|
||||
}
|
||||
echo "<th colspan='3'>" . __('Action') . "</th>\n";
|
||||
echo "<th>" . __('Time') . "</th>\n";
|
||||
echo "<th>" . __('Event') . "</th>\n";
|
||||
echo "</tr>";
|
||||
|
||||
$ct=0;
|
||||
$delimiter = '//';
|
||||
// Print table contents
|
||||
foreach ($triggers as $trigger) {
|
||||
$drop_and_create = $trigger['drop'] . $delimiter . "\n" . $trigger['create'] . "\n";
|
||||
$row = ($ct%2 == 0) ? 'even' : 'odd';
|
||||
$editlink = PMA_linkOrButton('tbl_sql.php?' . $url_query . '&sql_query='
|
||||
. urlencode($drop_and_create) . '&show_query=1&delimiter=' . urlencode($delimiter), $titles['Edit']);
|
||||
$exprlink = '<a ' . $conditional_class_export . ' href="db_triggers.php?' . $url_query
|
||||
. '&exporttrigger=1'
|
||||
. '&triggername=' . urlencode($trigger['name'])
|
||||
. '">' . $titles['Export'] . '</a>';
|
||||
$droplink = '<a ' . $conditional_class_drop . ' href="sql.php?' . $url_query . '&sql_query='
|
||||
. urlencode($trigger['drop']) . '" >' . $titles['Drop'] . '</a>';
|
||||
|
||||
echo "<tr class='noclick $row'>\n";
|
||||
echo "<td><span class='drop_sql' style='display:none;'>{$trigger['drop']}</span>";
|
||||
echo "<strong>{$trigger['name']}</strong></td>\n";
|
||||
if (empty($table)) {
|
||||
echo "<td><a href='tbl_triggers.php?db=$db&table={$trigger['table']}'>";
|
||||
echo $trigger['table'] . "</a></td>\n";
|
||||
}
|
||||
echo "<td>$editlink</td>\n";
|
||||
echo "<td><div class='create_sql' style='display: none;'>{$trigger['create']}</div>$exprlink</td>\n";
|
||||
echo "<td>$droplink</td>\n";
|
||||
echo "<td>{$trigger['action_timing']}</td>\n";
|
||||
echo "<td>{$trigger['event_manipulation']}</td>\n";
|
||||
echo "</tr>\n";
|
||||
$ct++;
|
||||
}
|
||||
echo '</table>';
|
||||
}
|
||||
echo '</fieldset>';
|
||||
|
||||
/**
|
||||
* Display the form for adding a new trigger
|
||||
*/
|
||||
echo '<fieldset>' . "\n"
|
||||
. ' <a href="tbl_triggers.php?' . $url_query . '&addtrigger=1" class="' . $conditional_class_add . '">' . "\n"
|
||||
. PMA_getIcon('b_trigger_add.png') . __('Add a trigger') . '</a>' . "\n"
|
||||
. '</fieldset>' . "\n";
|
||||
|
||||
?>
|
||||
@ -128,7 +128,7 @@ if (isset($plugin_list)) {
|
||||
$plugin_list['sql']['options'][] = array('type' => 'end_group');
|
||||
|
||||
/* begin Structure options */
|
||||
if (!$hide_structure) {
|
||||
if (!$hide_structure) {
|
||||
$plugin_list['sql']['options'][] = array(
|
||||
'type' => 'begin_group',
|
||||
'name' => 'structure',
|
||||
@ -144,7 +144,7 @@ if (isset($plugin_list)) {
|
||||
'name' => 'add_statements',
|
||||
'text' => __('Add statements:')
|
||||
));
|
||||
if ($plugin_param['export_type'] == 'table') {
|
||||
if ($plugin_param['export_type'] == 'table') {
|
||||
if (PMA_Table::isView($GLOBALS['db'], $GLOBALS['table'])) {
|
||||
$drop_clause = '<code>DROP VIEW</code>';
|
||||
} else {
|
||||
@ -313,7 +313,7 @@ function PMA_exportRoutines($db) {
|
||||
|
||||
if ($procedure_names || $function_names) {
|
||||
$text .= $crlf
|
||||
. 'DELIMITER ' . $delimiter . $crlf;
|
||||
. 'DELIMITER ' . $delimiter . $crlf;
|
||||
}
|
||||
|
||||
if ($procedure_names) {
|
||||
@ -415,9 +415,9 @@ function PMA_exportFooter()
|
||||
$charset_of_file = isset($GLOBALS['charset_of_file']) ? $GLOBALS['charset_of_file'] : '';
|
||||
if (!empty($GLOBALS['asfile']) && isset($mysql_charset_map[$charset_of_file])) {
|
||||
$foot .= $crlf
|
||||
. '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;' . $crlf
|
||||
. '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;' . $crlf
|
||||
. '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;' . $crlf;
|
||||
. '/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;' . $crlf
|
||||
. '/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;' . $crlf
|
||||
. '/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;' . $crlf;
|
||||
}
|
||||
|
||||
/* Restore timezone */
|
||||
@ -458,11 +458,11 @@ function PMA_exportHeader()
|
||||
$host_string .= ':' . $cfg['Server']['port'];
|
||||
}
|
||||
$head .= PMA_exportComment($host_string);
|
||||
$head .= PMA_exportComment(__('Generation Time')
|
||||
. ': ' . PMA_localisedDate())
|
||||
. PMA_exportComment(__('Server version') . ': ' . PMA_MYSQL_STR_VERSION)
|
||||
. PMA_exportComment(__('PHP Version') . ': ' . phpversion())
|
||||
. PMA_possibleCRLF();
|
||||
$head .= PMA_exportComment(__('Generation Time')
|
||||
. ': ' . PMA_localisedDate())
|
||||
. PMA_exportComment(__('Server version') . ': ' . PMA_MYSQL_STR_VERSION)
|
||||
. PMA_exportComment(__('PHP Version') . ': ' . phpversion())
|
||||
. PMA_possibleCRLF();
|
||||
|
||||
if (isset($GLOBALS['sql_header_comment']) && !empty($GLOBALS['sql_header_comment'])) {
|
||||
// '\n' is not a newline (like "\n" would be), it's the characters
|
||||
@ -476,17 +476,17 @@ function PMA_exportHeader()
|
||||
}
|
||||
|
||||
if (isset($GLOBALS['sql_disable_fk'])) {
|
||||
$head .= 'SET FOREIGN_KEY_CHECKS=0;' . $crlf;
|
||||
$head .= 'SET FOREIGN_KEY_CHECKS=0;' . $crlf;
|
||||
}
|
||||
|
||||
/* We want exported AUTO_INCREMENT fields to have still same value, do this only for recent MySQL exports */
|
||||
if (!isset($GLOBALS['sql_compatibility']) || $GLOBALS['sql_compatibility'] == 'NONE') {
|
||||
$head .= 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";' . $crlf;
|
||||
$head .= 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";' . $crlf;
|
||||
}
|
||||
|
||||
if (isset($GLOBALS['sql_use_transaction'])) {
|
||||
$head .= 'SET AUTOCOMMIT=0;' . $crlf
|
||||
. 'START TRANSACTION;' . $crlf;
|
||||
$head .= 'SET AUTOCOMMIT=0;' . $crlf
|
||||
. 'START TRANSACTION;' . $crlf;
|
||||
}
|
||||
|
||||
|
||||
@ -807,9 +807,9 @@ function PMA_getTableDef($db, $table, $crlf, $error_url, $show_dates = false, $a
|
||||
// comments for current table
|
||||
if (!isset($GLOBALS['no_constraints_comments'])) {
|
||||
$sql_constraints .= $crlf
|
||||
. PMA_exportComment()
|
||||
. PMA_exportComment(__('Constraints for table') . ' ' . PMA_backquote($table))
|
||||
. PMA_exportComment();
|
||||
. PMA_exportComment()
|
||||
. PMA_exportComment(__('Constraints for table') . ' ' . PMA_backquote($table))
|
||||
. PMA_exportComment();
|
||||
}
|
||||
|
||||
// let's do the work
|
||||
@ -964,8 +964,8 @@ function PMA_exportStructure($db, $table, $crlf, $error_url, $relation = false,
|
||||
|
||||
switch($export_mode) {
|
||||
case 'create_table':
|
||||
$dump .= PMA_exportComment(__('Table structure for table') . ' ' . $formatted_table_name)
|
||||
. PMA_exportComment();
|
||||
$dump .= PMA_exportComment(__('Table structure for table') . ' ' . $formatted_table_name);
|
||||
$dump .= PMA_exportComment();
|
||||
$dump .= PMA_getTableDef($db, $table, $crlf, $error_url, $dates);
|
||||
$dump .= PMA_getTableComments($db, $table, $crlf, $relation, $mime);
|
||||
break;
|
||||
@ -974,9 +974,9 @@ function PMA_exportStructure($db, $table, $crlf, $error_url, $relation = false,
|
||||
$triggers = PMA_DBI_get_triggers($db, $table);
|
||||
if ($triggers) {
|
||||
$dump .= PMA_possibleCRLF()
|
||||
. PMA_exportComment()
|
||||
. PMA_exportComment(__('Triggers') . ' ' . $formatted_table_name)
|
||||
. PMA_exportComment();
|
||||
. PMA_exportComment()
|
||||
. PMA_exportComment(__('Triggers') . ' ' . $formatted_table_name)
|
||||
. PMA_exportComment();
|
||||
$delimiter = '//';
|
||||
foreach ($triggers as $trigger) {
|
||||
$dump .= $trigger['drop'] . ';' . $crlf;
|
||||
@ -988,7 +988,7 @@ function PMA_exportStructure($db, $table, $crlf, $error_url, $relation = false,
|
||||
break;
|
||||
case 'create_view':
|
||||
$dump .= PMA_exportComment(__('Structure for view') . ' ' . $formatted_table_name)
|
||||
. PMA_exportComment();
|
||||
. PMA_exportComment();
|
||||
// delete the stand-in table previously created (if any)
|
||||
if ($export_type != 'table') {
|
||||
$dump .= 'DROP TABLE IF EXISTS ' . PMA_backquote($table) . ';' . $crlf;
|
||||
@ -997,7 +997,7 @@ function PMA_exportStructure($db, $table, $crlf, $error_url, $relation = false,
|
||||
break;
|
||||
case 'stand_in':
|
||||
$dump .= PMA_exportComment(__('Stand-in structure for view') . ' ' . $formatted_table_name)
|
||||
. PMA_exportComment();
|
||||
. PMA_exportComment();
|
||||
// export a stand-in definition to resolve view dependencies
|
||||
$dump .= PMA_getTableDefStandIn($db, $table, $crlf);
|
||||
} // end switch
|
||||
@ -1051,7 +1051,7 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
// are used, we did not get the true column name in case of aliases)
|
||||
$analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($sql_query));
|
||||
|
||||
$result = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
|
||||
$result = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
|
||||
// a possible error: the table has crashed
|
||||
$tmp_error = PMA_DBI_getError();
|
||||
if ($tmp_error) {
|
||||
@ -1059,11 +1059,11 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
}
|
||||
|
||||
if ($result != false) {
|
||||
$fields_cnt = PMA_DBI_num_fields($result);
|
||||
$fields_cnt = PMA_DBI_num_fields($result);
|
||||
|
||||
// Get field information
|
||||
$fields_meta = PMA_DBI_get_fields_meta($result);
|
||||
$field_flags = array();
|
||||
$fields_meta = PMA_DBI_get_fields_meta($result);
|
||||
$field_flags = array();
|
||||
for ($j = 0; $j < $fields_cnt; $j++) {
|
||||
$field_flags[$j] = PMA_DBI_field_flags($result, $j);
|
||||
}
|
||||
@ -1087,9 +1087,9 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
} else {
|
||||
// insert or replace
|
||||
if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] == 'REPLACE') {
|
||||
$sql_command = 'REPLACE';
|
||||
$sql_command = 'REPLACE';
|
||||
} else {
|
||||
$sql_command = 'INSERT';
|
||||
$sql_command = 'INSERT';
|
||||
}
|
||||
|
||||
// delayed inserts?
|
||||
@ -1116,10 +1116,10 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
}
|
||||
}
|
||||
|
||||
$search = array("\x00", "\x0a", "\x0d", "\x1a"); //\x08\\x09, not required
|
||||
$replace = array('\0', '\n', '\r', '\Z');
|
||||
$current_row = 0;
|
||||
$query_size = 0;
|
||||
$search = array("\x00", "\x0a", "\x0d", "\x1a"); //\x08\\x09, not required
|
||||
$replace = array('\0', '\n', '\r', '\Z');
|
||||
$current_row = 0;
|
||||
$query_size = 0;
|
||||
if (($GLOBALS['sql_insert_syntax'] == 'extended' || $GLOBALS['sql_insert_syntax'] == 'both') && (!isset($GLOBALS['sql_type']) || $GLOBALS['sql_type'] != 'UPDATE')) {
|
||||
$separator = ',';
|
||||
$schema_insert .= $crlf;
|
||||
@ -1142,7 +1142,7 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
for ($j = 0; $j < $fields_cnt; $j++) {
|
||||
// NULL
|
||||
if (!isset($row[$j]) || is_null($row[$j])) {
|
||||
$values[] = 'NULL';
|
||||
$values[] = 'NULL';
|
||||
// a number
|
||||
// timestamp is numeric on some MySQL 4.1, BLOBs are sometimes numeric
|
||||
} elseif ($fields_meta[$j]->numeric && $fields_meta[$j]->type != 'timestamp'
|
||||
@ -1212,7 +1212,7 @@ function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
|
||||
}
|
||||
// Other inserts case
|
||||
else {
|
||||
$insert_line = $schema_insert . '(' . implode(', ', $values) . ')';
|
||||
$insert_line = $schema_insert . '(' . implode(', ', $values) . ')';
|
||||
}
|
||||
}
|
||||
unset($values);
|
||||
|
||||
567
libraries/rte/rte_events.lib.php
Normal file
567
libraries/rte/rte_events.lib.php
Normal file
@ -0,0 +1,567 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Functions for event management.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is defined in: rte_routines.lib.php, rte_triggers.lib.php and
|
||||
* rte_events.lib.php. It is used to retreive some language strings that are
|
||||
* used in functionalities that are common to routines, triggers and events.
|
||||
*
|
||||
* @param string $index The index of the string to get
|
||||
*
|
||||
* @return string The requested string or an empty string, if not available
|
||||
*/
|
||||
function PMA_RTE_getWord($index)
|
||||
{
|
||||
$words = array(
|
||||
'add' => __('Add event'),
|
||||
'docu' => 'EVENTS',
|
||||
'export' => __('Export of event %s'),
|
||||
'human' => __('event'),
|
||||
'no_create' => __('You do not have the necessary privileges to create a new event'),
|
||||
'not_found' => __('No event with name %1$s found in database %2$s'),
|
||||
'nothing' => __('There are no events to display.'),
|
||||
'title' => __('Events'),
|
||||
);
|
||||
return isset($words[$index]) ? $words[$index] : '';
|
||||
} // end PMA_RTE_getWord()
|
||||
|
||||
/**
|
||||
* Main function for the events functionality
|
||||
*/
|
||||
function PMA_RTE_main()
|
||||
{
|
||||
global $db;
|
||||
|
||||
/**
|
||||
* Process all requests
|
||||
*/
|
||||
PMA_EVN_handleEditor();
|
||||
PMA_EVN_handleExport();
|
||||
/**
|
||||
* Display a list of available events
|
||||
*/
|
||||
$columns = "`EVENT_NAME`, `EVENT_TYPE`, `STATUS`";
|
||||
$where = "EVENT_SCHEMA='" . PMA_sqlAddSlashes($db) . "'";
|
||||
$query = "SELECT $columns FROM `INFORMATION_SCHEMA`.`EVENTS` "
|
||||
. "WHERE $where ORDER BY `EVENT_NAME` ASC;";
|
||||
$items = PMA_DBI_fetch_result($query);
|
||||
echo PMA_RTE_getList('event', $items);
|
||||
/**
|
||||
* Display a link for adding a new event, if
|
||||
* the user has the privileges and a link to
|
||||
* toggle the state of the event scheduler.
|
||||
*/
|
||||
echo PMA_EVN_getFooterLinks();
|
||||
} // end PMA_RTE_main()
|
||||
|
||||
/**
|
||||
* Handles editor requests for adding or editing an item
|
||||
*/
|
||||
function PMA_EVN_handleEditor()
|
||||
{
|
||||
global $_REQUEST, $_POST, $errors, $db, $table;
|
||||
|
||||
if (! empty($_REQUEST['editor_process_add'])
|
||||
|| ! empty($_REQUEST['editor_process_edit'])
|
||||
) {
|
||||
$sql_query = '';
|
||||
|
||||
$item_query = PMA_EVN_getQueryFromRequest();
|
||||
|
||||
if (! count($errors)) { // set by PMA_RTN_getQueryFromRequest()
|
||||
// Execute the created query
|
||||
if (! empty($_REQUEST['editor_process_edit'])) {
|
||||
// Backup the old trigger, in case something goes wrong
|
||||
$create_item = PMA_DBI_get_definition(
|
||||
$db,
|
||||
'EVENT',
|
||||
$_REQUEST['item_original_name']
|
||||
);
|
||||
$drop_item = "DROP EVENT " . PMA_backquote($_REQUEST['item_original_name']) . ";\n";
|
||||
$result = PMA_DBI_try_query($drop_item);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $drop_item) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$result = PMA_DBI_try_query($item_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $item_query) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
// We dropped the old item, but were unable to create the new one
|
||||
// Try to restore the backup query
|
||||
$result = PMA_DBI_try_query($create_item);
|
||||
if (! $result) {
|
||||
// OMG, this is really bad! We dropped the query, failed to create a new one
|
||||
// and now even the backup query does not execute!
|
||||
// This should not happen, but we better handle this just in case.
|
||||
$errors[] = __('Sorry, we failed to restore the dropped event.') . '<br />'
|
||||
. __('The backed up query was:') . "\"$create_item\"" . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
}
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Event %1$s has been modified.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['item_name']));
|
||||
$sql_query = $drop_item . $item_query;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 'Add a new item' mode
|
||||
$result = PMA_DBI_try_query($item_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $item_query) . '<br /><br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Event %1$s has been created.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['item_name']));
|
||||
$sql_query = $item_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors)) {
|
||||
$message = PMA_Message::error(__('<b>One or more errors have occured while processing your request:</b>'));
|
||||
$message->addString('<ul>');
|
||||
foreach ($errors as $num => $string) {
|
||||
$message->addString('<li>' . $string . '</li>');
|
||||
}
|
||||
$message->addString('</ul>');
|
||||
}
|
||||
|
||||
$output = PMA_showMessage($message, $sql_query);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array();
|
||||
if ($message->isSuccess()) {
|
||||
$columns = "`EVENT_NAME`, `EVENT_TYPE`, `STATUS`";
|
||||
$where = "EVENT_SCHEMA='" . PMA_sqlAddSlashes($db) . "' "
|
||||
. "AND EVENT_NAME='" . PMA_sqlAddSlashes($_REQUEST['item_name']) . "'";
|
||||
$query = "SELECT $columns FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE $where;";
|
||||
$event = PMA_DBI_fetch_single_row($query);
|
||||
$extra_data['name'] = htmlspecialchars(strtoupper($_REQUEST['item_name']));
|
||||
$extra_data['new_row'] = PMA_EVN_getRowForList($event);
|
||||
$extra_data['insert'] = ! empty($event);
|
||||
$response = $output;
|
||||
} else {
|
||||
$response = $message;
|
||||
}
|
||||
PMA_ajaxResponse($response, $message->isSuccess(), $extra_data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Display a form used to add/edit a trigger, if necessary
|
||||
*/
|
||||
if (count($errors) || ( empty($_REQUEST['editor_process_add']) && empty($_REQUEST['editor_process_edit'])
|
||||
&& (! empty($_REQUEST['add_item']) || ! empty($_REQUEST['edit_item'])
|
||||
|| ! empty($_REQUEST['item_changetype'])))
|
||||
) { // FIXME: this must be simpler than that
|
||||
$operation = '';
|
||||
if (! empty($_REQUEST['item_changetype'])) {
|
||||
$operation = 'change';
|
||||
}
|
||||
// Get the data for the form (if any)
|
||||
if (! empty($_REQUEST['add_item'])) {
|
||||
$title = __("Create event");
|
||||
$item = PMA_EVN_getDataFromRequest();
|
||||
$mode = 'add';
|
||||
} else if (! empty($_REQUEST['edit_item'])) {
|
||||
$title = __("Edit event");
|
||||
if (! empty($_REQUEST['item_name'])
|
||||
&& empty($_REQUEST['editor_process_edit'])
|
||||
&& empty($_REQUEST['item_changetype'])
|
||||
) {
|
||||
$item = PMA_EVN_getDataFromName($_REQUEST['item_name']);
|
||||
if ($item !== false) {
|
||||
$item['item_original_name'] = $item['item_name'];
|
||||
}
|
||||
} else {
|
||||
$item = PMA_EVN_getDataFromRequest();
|
||||
}
|
||||
$mode = 'edit';
|
||||
}
|
||||
if ($item !== false) {
|
||||
// Show form
|
||||
$editor = PMA_EVN_getEditorForm($mode, $operation, $item);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array('title' => $title);
|
||||
PMA_ajaxResponse($editor, true, $extra_data);
|
||||
} else {
|
||||
echo "\n\n<h2>$title</h2>\n\n$editor";
|
||||
unset($_POST);
|
||||
require './libraries/footer.inc.php';
|
||||
}
|
||||
// exit;
|
||||
} else {
|
||||
$message = __('Error in processing request') . ' : ';
|
||||
$message .= sprintf(
|
||||
PMA_RTE_getWord('not_found'),
|
||||
htmlspecialchars(PMA_backquote($_REQUEST['item_name'])),
|
||||
htmlspecialchars(PMA_backquote($db))
|
||||
);
|
||||
$message = PMA_message::error($message);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
PMA_ajaxResponse($message, false);
|
||||
} else {
|
||||
$message->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end PMA_EVN_handleEditor()
|
||||
|
||||
/**
|
||||
* This function will generate the values that are required to for the editor
|
||||
*
|
||||
* @return array Data necessary to create the editor.
|
||||
*/
|
||||
function PMA_EVN_getDataFromRequest()
|
||||
{
|
||||
$retval = array();
|
||||
$indices = array('item_name',
|
||||
'item_original_name',
|
||||
'item_status',
|
||||
'item_execute_at',
|
||||
'item_interval_value',
|
||||
'item_interval_field',
|
||||
'item_starts',
|
||||
'item_ends',
|
||||
'item_definition',
|
||||
'item_preserve',
|
||||
'item_comment',
|
||||
'item_definer');
|
||||
foreach ($indices as $key => $index) {
|
||||
$retval[$index] = isset($_REQUEST[$index]) ? $_REQUEST[$index] : '';
|
||||
}
|
||||
$retval['item_type'] = 'ONE TIME';
|
||||
$retval['item_type_toggle'] = 'RECURRING';
|
||||
if (isset($_REQUEST['item_type']) && $_REQUEST['item_type'] == 'RECURRING') {
|
||||
$retval['item_type'] = 'RECURRING';
|
||||
$retval['item_type_toggle'] = 'ONE TIME';
|
||||
}
|
||||
return $retval;
|
||||
} // end PMA_EVN_getDataFromRequest()
|
||||
|
||||
/**
|
||||
* This function will generate the values that are required to complete
|
||||
* the "Edit event" form given the name of a event.
|
||||
*
|
||||
* @param string $name The name of the event.
|
||||
*
|
||||
* @return array Data necessary to create the editor.
|
||||
*/
|
||||
function PMA_EVN_getDataFromName($name)
|
||||
{
|
||||
global $db;
|
||||
|
||||
$retval = array();
|
||||
$columns = "`EVENT_NAME`, `STATUS`, `EVENT_TYPE`, `EXECUTE_AT`, "
|
||||
. "`INTERVAL_VALUE`, `INTERVAL_FIELD`, `STARTS`, `ENDS`, "
|
||||
. "`EVENT_DEFINITION`, `ON_COMPLETION`, `DEFINER`, `EVENT_COMMENT`";
|
||||
$where = "EVENT_SCHEMA='" . PMA_sqlAddSlashes($db) . "' "
|
||||
. "AND EVENT_NAME='" . PMA_sqlAddSlashes($name) . "'";
|
||||
$query = "SELECT $columns FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE $where;";
|
||||
$item = PMA_DBI_fetch_single_row($query);
|
||||
if (! $item) {
|
||||
return false;
|
||||
}
|
||||
$retval['item_name'] = $item['EVENT_NAME'];
|
||||
$retval['item_status'] = $item['STATUS'];
|
||||
$retval['item_type'] = $item['EVENT_TYPE'];
|
||||
if ($retval['item_type'] == 'RECURRING') {
|
||||
$retval['item_type_toggle'] = 'ONE TIME';
|
||||
} else {
|
||||
$retval['item_type_toggle'] = 'RECURRING';
|
||||
}
|
||||
$retval['item_execute_at'] = $item['EXECUTE_AT'];
|
||||
$retval['item_interval_value'] = $item['INTERVAL_VALUE'];
|
||||
$retval['item_interval_field'] = $item['INTERVAL_FIELD'];
|
||||
$retval['item_starts'] = $item['STARTS'];
|
||||
$retval['item_ends'] = $item['ENDS'];
|
||||
$retval['item_preserve'] = '';
|
||||
if ($item['ON_COMPLETION'] == 'PRESERVE') {
|
||||
$retval['item_preserve'] = " checked='checked'";
|
||||
}
|
||||
$retval['item_definition'] = $item['EVENT_DEFINITION'];
|
||||
$retval['item_definer'] = $item['DEFINER'];
|
||||
$retval['item_comment'] = $item['EVENT_COMMENT'];
|
||||
|
||||
return $retval;
|
||||
} // end PMA_EVN_getDataFromName()
|
||||
|
||||
/**
|
||||
* Displays a form used to add/edit an event
|
||||
*
|
||||
* @param string $mode If the editor will be used edit an event
|
||||
* or add a new one: 'edit' or 'add'.
|
||||
* @param string $operation If the editor was previously invoked with
|
||||
* JS turned off, this will hold the name of
|
||||
* the current operation
|
||||
* @param array $item Data for the event returned by
|
||||
* PMA_EVN_getDataFromRequest() or
|
||||
* PMA_EVN_getDataFromName()
|
||||
*
|
||||
* @return string HTML code for the editor.
|
||||
*/
|
||||
function PMA_EVN_getEditorForm($mode, $operation, $item)
|
||||
{
|
||||
global $db, $table, $titles, $event_status, $event_type, $event_interval;
|
||||
|
||||
// Escape special characters
|
||||
$need_escape = array(
|
||||
'item_original_name',
|
||||
'item_name',
|
||||
'item_type',
|
||||
'item_execute_at',
|
||||
'item_interval_value',
|
||||
'item_starts',
|
||||
'item_ends',
|
||||
'item_definition',
|
||||
'item_definer',
|
||||
'item_comment'
|
||||
);
|
||||
foreach ($need_escape as $key => $index) {
|
||||
$item[$index] = htmlentities($item[$index], ENT_QUOTES);
|
||||
}
|
||||
$original_data = '';
|
||||
if ($mode == 'edit') {
|
||||
$original_data = "<input name='item_original_name' "
|
||||
. "type='hidden' value='{$item['item_original_name']}'/>\n";
|
||||
}
|
||||
// Handle some logic first
|
||||
if ($operation == 'change') {
|
||||
if ($item['item_type'] == 'RECURRING') {
|
||||
$item['item_type'] = 'ONE TIME';
|
||||
$item['item_type_toggle'] = 'RECURRING';
|
||||
} else {
|
||||
$item['item_type'] = 'RECURRING';
|
||||
$item['item_type_toggle'] = 'ONE TIME';
|
||||
}
|
||||
}
|
||||
if ($item['item_type'] == 'ONE TIME') {
|
||||
$isrecurring_class = ' hide';
|
||||
$isonetime_class = '';
|
||||
} else {
|
||||
$isrecurring_class = '';
|
||||
$isonetime_class = ' hide';
|
||||
}
|
||||
// Create the output
|
||||
$retval = "";
|
||||
$retval .= "<!-- START " . strtoupper($mode) . " EVENT FORM -->\n\n";
|
||||
$retval .= "<form class='rte_form' action='db_events.php' method='post'>\n";
|
||||
$retval .= "<input name='{$mode}_item' type='hidden' value='1' />\n";
|
||||
$retval .= $original_data;
|
||||
$retval .= PMA_generate_common_hidden_inputs($db, $table) . "\n";
|
||||
$retval .= "<fieldset>\n";
|
||||
$retval .= "<legend>" . __('Details') . "</legend>\n";
|
||||
$retval .= "<table class='rte_table' style='width: 100%'>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td style='width: 20%;'>" . __('Event name') . "</td>\n";
|
||||
$retval .= " <td><input type='text' name='item_name' \n";
|
||||
$retval .= " value='{$item['item_name']}'\n";
|
||||
$retval .= " maxlength='64' /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Status') . "</td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <select name='item_status'>\n";
|
||||
foreach ($event_status['display'] as $key => $value) {
|
||||
$selected = "";
|
||||
if (! empty($item['item_status']) && $item['item_status'] == $value) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= "<option$selected>$value</option>";
|
||||
}
|
||||
$retval .= " </select>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Event type') . "</td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$retval .= " <select name='item_type'>";
|
||||
foreach ($event_type as $key => $value) {
|
||||
$selected = "";
|
||||
if (! empty($item['item_type']) && $item['item_type'] == $value) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= "<option$selected>$value</option>";
|
||||
}
|
||||
$retval .= " </select>\n";
|
||||
} else {
|
||||
$retval .= " <input name='item_type' type='hidden' \n";
|
||||
$retval .= " value='{$item['item_type']}' />\n";
|
||||
$retval .= " <div style='width: 49%; float: left; text-align: center; font-weight: bold;'>\n";
|
||||
$retval .= " {$item['item_type']}\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= " <input style='width: 49%;' type='submit'\n";
|
||||
$retval .= " name='item_changetype'\n";
|
||||
$retval .= " value='";
|
||||
$retval .= sprintf(__('Change to %s'), $item['item_type_toggle']);
|
||||
$retval .= "' />\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr class='onetime_event_row $isonetime_class'>\n";
|
||||
$retval .= " <td>" . __('Execute at') . "</td>\n";
|
||||
$retval .= " <td class='nowrap'>\n";
|
||||
$retval .= " <input type='text' name='item_execute_at'\n";
|
||||
$retval .= " value='{$item['item_execute_at']}'\n";
|
||||
$retval .= " class='datetimefield' />\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr class='recurring_event_row $isrecurring_class'>\n";
|
||||
$retval .= " <td>" . __('Execute every') . "</td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <input style='width: 49%;' type='text'\n";
|
||||
$retval .= " name='item_interval_value'\n";
|
||||
$retval .= " value='{$item['item_interval_value']}' />\n";
|
||||
$retval .= " <select style='width: 49%;' name='item_interval_field'>";
|
||||
foreach ($event_interval as $key => $value) {
|
||||
$selected = "";
|
||||
if (! empty($item['item_interval_field'])
|
||||
&& $item['item_interval_field'] == $value
|
||||
) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= "<option$selected>$value</option>";
|
||||
}
|
||||
$retval .= " </select>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr class='recurring_event_row$isrecurring_class'>\n";
|
||||
$retval .= " <td>" . __('Start') . "</td>\n";
|
||||
$retval .= " <td class='nowrap'>\n";
|
||||
$retval .= " <input type='text'\n name='item_starts'\n";
|
||||
$retval .= " value='{$item['item_starts']}'\n";
|
||||
$retval .= " class='datetimefield' />\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr class='recurring_event_row$isrecurring_class'>\n";
|
||||
$retval .= " <td>" . __('End') . "</td>\n";
|
||||
$retval .= " <td class='nowrap'>\n";
|
||||
$retval .= " <input type='text' name='item_ends'\n";
|
||||
$retval .= " value='{$item['item_ends']}'\n";
|
||||
$retval .= " class='datetimefield' />\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Definition') . "</td>\n";
|
||||
$retval .= " <td><textarea name='item_definition' rows='15' cols='40'>";
|
||||
$retval .= $item['item_definition'];
|
||||
$retval .= "</textarea></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('On completion preserve') . "</td>\n";
|
||||
$retval .= " <td><input type='checkbox' name='item_preserve'{$item['item_preserve']} /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Definer') . "</td>\n";
|
||||
$retval .= " <td><input type='text' name='item_definer'\n";
|
||||
$retval .= " value='{$item['item_definer']}' /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Comment') . "</td>\n";
|
||||
$retval .= " <td><input type='text' name='item_comment' maxlength='64'\n";
|
||||
$retval .= " value='{$item['item_comment']}' /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "</table>\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$retval .= "<input type='hidden' name='editor_process_{$mode}'\n";
|
||||
$retval .= " value='true' />\n";
|
||||
$retval .= "<input type='hidden' name='ajax_request' value='true' />\n";
|
||||
} else {
|
||||
$retval .= "<fieldset class='tblFooters'>\n";
|
||||
$retval .= " <input type='submit' name='editor_process_{$mode}'\n";
|
||||
$retval .= " value='" . __('Go') . "' />\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
}
|
||||
$retval .= "</form>\n\n";
|
||||
$retval .= "<!-- END " . strtoupper($mode) . " EVENT FORM -->\n\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_EVN_getEditorForm()
|
||||
|
||||
/**
|
||||
* Composes the query necessary to create an event from an HTTP request.
|
||||
*
|
||||
* @return string The CREATE EVENT query.
|
||||
*/
|
||||
function PMA_EVN_getQueryFromRequest()
|
||||
{
|
||||
global $_REQUEST, $db, $errors, $event_status, $event_type, $event_interval;
|
||||
|
||||
$query = 'CREATE ';
|
||||
if (! empty($_REQUEST['item_definer'])) {
|
||||
if (strpos($_REQUEST['item_definer'], '@') !== false) {
|
||||
$arr = explode('@', $_REQUEST['item_definer']);
|
||||
$query .= 'DEFINER=' . PMA_backquote($arr[0]);
|
||||
$query .= '@' . PMA_backquote($arr[1]) . ' ';
|
||||
} else {
|
||||
$errors[] = __('The definer must be in the "username@hostname" format');
|
||||
}
|
||||
}
|
||||
$query .= 'EVENT ';
|
||||
if (! empty($_REQUEST['item_name'])) {
|
||||
$query .= PMA_backquote($_REQUEST['item_name']) . ' ';
|
||||
} else {
|
||||
$errors[] = __('You must provide an event name');
|
||||
}
|
||||
$query .= 'ON SCHEDULE ';
|
||||
if (! empty($_REQUEST['item_type']) && in_array($_REQUEST['item_type'], $event_type)) {
|
||||
if ($_REQUEST['item_type'] == 'RECURRING') {
|
||||
if (! empty($_REQUEST['item_interval_value'])
|
||||
&& !empty($_REQUEST['item_interval_field'])
|
||||
&& in_array($_REQUEST['item_interval_field'], $event_interval)
|
||||
) {
|
||||
$query .= 'EVERY ' . intval($_REQUEST['item_interval_value']) . ' ';
|
||||
$query .= $_REQUEST['item_interval_field'] . ' ';
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid interval value for the event.');
|
||||
}
|
||||
if (! empty($_REQUEST['item_starts'])) {
|
||||
$query .= "STARTS '" . PMA_sqlAddSlashes($_REQUEST['item_starts']) . "' ";
|
||||
}
|
||||
if (! empty($_REQUEST['item_ends'])) {
|
||||
$query .= "ENDS '" . PMA_sqlAddSlashes($_REQUEST['item_ends']) . "' ";
|
||||
}
|
||||
} else {
|
||||
if (! empty($_REQUEST['item_execute_at'])) {
|
||||
$query .= "AT '" . PMA_sqlAddSlashes($_REQUEST['item_execute_at']) . "' ";
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid execution time for the event.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid type for the event.');
|
||||
}
|
||||
$query .= 'ON COMPLETION ';
|
||||
if (empty($_REQUEST['item_preserve'])) {
|
||||
$query .= 'NOT ';
|
||||
}
|
||||
$query .= 'PRESERVE ';
|
||||
if (! empty($_REQUEST['item_status'])) {
|
||||
foreach ($event_status['display'] as $key => $value) {
|
||||
if ($value == $_REQUEST['item_status']) {
|
||||
$query .= $event_status['query'][$key] . ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$query .= 'DO ';
|
||||
if (! empty($_REQUEST['item_definition'])) {
|
||||
$query .= $_REQUEST['item_definition'];
|
||||
} else {
|
||||
$errors[] = __('You must provide an event definition.');
|
||||
}
|
||||
|
||||
return $query;
|
||||
} // end PMA_EVN_getQueryFromRequest()
|
||||
|
||||
?>
|
||||
107
libraries/rte/rte_export.lib.php
Normal file
107
libraries/rte/rte_export.lib.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Common functions for the export functionality for Routines, Triggers and Events.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called from one of the other functions in this file
|
||||
* and it completes the handling of the export functionality.
|
||||
*
|
||||
* @param string $item_name The name of the item that we are exporting
|
||||
* @param string $export_data The SQL query to create the requested item
|
||||
*/
|
||||
function PMA_RTE_handleExport($item_name, $export_data)
|
||||
{
|
||||
global $db, $table;
|
||||
|
||||
$item_name = htmlspecialchars(PMA_backquote($_GET['item_name']));
|
||||
if ($export_data !== false) {
|
||||
$export_data = '<textarea cols="40" rows="15" style="width: 100%;">'
|
||||
. htmlspecialchars(trim($export_data)) . '</textarea>';
|
||||
$title = sprintf(PMA_RTE_getWord('export'), $item_name);
|
||||
if ($GLOBALS['is_ajax_request'] == true) {
|
||||
$extra_data = array('title' => $title);
|
||||
PMA_ajaxResponse($export_data, true, $extra_data);
|
||||
} else {
|
||||
echo "<fieldset>\n"
|
||||
. "<legend>$title</legend>\n"
|
||||
. $export_data
|
||||
. "</fieldset>\n";
|
||||
}
|
||||
} else {
|
||||
$_db = htmlspecialchars(PMA_backquote($db));
|
||||
$response = __('Error in Processing Request') . ' : '
|
||||
. sprintf(PMA_RTE_getWord('not_found'), $item_name, $_db);
|
||||
$response = PMA_message::error($response);
|
||||
if ($GLOBALS['is_ajax_request'] == true) {
|
||||
PMA_ajaxResponse($response, false);
|
||||
} else {
|
||||
$response->display();
|
||||
}
|
||||
}
|
||||
} // end PMA_RTE_handleExport()
|
||||
|
||||
/**
|
||||
* If necessary, prepares event information and passes
|
||||
* it to PMA_RTE_handleExport() for the actual export.
|
||||
*/
|
||||
function PMA_EVN_handleExport()
|
||||
{
|
||||
global $_GET, $db;
|
||||
|
||||
if (! empty($_GET['export_item']) && ! empty($_GET['item_name'])) {
|
||||
$item_name = $_GET['item_name'];
|
||||
$export_data = PMA_DBI_get_definition($db, 'EVENT', $item_name);
|
||||
PMA_RTE_handleExport($item_name, $export_data);
|
||||
}
|
||||
} // end PMA_EVN_handleExport()
|
||||
|
||||
/**
|
||||
* If necessary, prepares routine information and passes
|
||||
* it to PMA_RTE_handleExport() for the actual export.
|
||||
*/
|
||||
function PMA_RTN_handleExport()
|
||||
{
|
||||
global $_GET, $db;
|
||||
|
||||
if (! empty($_GET['export_item']) && ! empty($_GET['item_name'])) {
|
||||
$item_name = $_GET['item_name'];
|
||||
$type = PMA_DBI_fetch_value(
|
||||
"SELECT ROUTINE_TYPE " .
|
||||
"FROM INFORMATION_SCHEMA.ROUTINES " .
|
||||
"WHERE ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' " .
|
||||
"AND SPECIFIC_NAME='" . PMA_sqlAddSlashes($item_name) . "';"
|
||||
);
|
||||
$export_data = PMA_DBI_get_definition($db, $type, $item_name);
|
||||
PMA_RTE_handleExport($item_name, $export_data);
|
||||
}
|
||||
} // end PMA_RTN_handleExport()
|
||||
|
||||
/**
|
||||
* If necessary, prepares trigger information and passes
|
||||
* it to PMA_RTE_handleExport() for the actual export.
|
||||
*/
|
||||
function PMA_TRI_handleExport()
|
||||
{
|
||||
global $_GET, $db, $table;
|
||||
|
||||
if (! empty($_GET['export_item']) && ! empty($_GET['item_name'])) {
|
||||
$item_name = $_GET['item_name'];
|
||||
$triggers = PMA_DBI_get_triggers($db, $table, '');
|
||||
$export_data = false;
|
||||
foreach ($triggers as $trigger) {
|
||||
if ($trigger['name'] === $item_name) {
|
||||
$export_data = $trigger['create'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
PMA_RTE_handleExport($item_name, $export_data);
|
||||
}
|
||||
} // end PMA_TRI_handleExport()
|
||||
?>
|
||||
127
libraries/rte/rte_footer.lib.php
Normal file
127
libraries/rte/rte_footer.lib.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Common functions for generating the footer for Routines, Triggers and Events.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fieldset for adding a new item, if the user has the privileges.
|
||||
*
|
||||
* @param string $docu String used to create a link to the MySQL docs
|
||||
* @param string $priv Privilege to check for adding a new item
|
||||
* @param string $name MySQL name of the item
|
||||
*
|
||||
* @return string An HTML snippet with the link to add a new item
|
||||
*/
|
||||
function PMA_RTE_getFooterLinks($docu, $priv, $name)
|
||||
{
|
||||
global $db, $url_query, $ajax_class;
|
||||
|
||||
$icon = 'b_' . strtolower($name) . '_add.png';
|
||||
$retval = "";
|
||||
$retval .= "<!-- ADD " . $name . " FORM START -->\n";
|
||||
$retval .= "<fieldset class='left'>\n";
|
||||
$retval .= " <legend>" . __('New'). "</legend>\n";
|
||||
$retval .= " <div class='wrap'>\n";
|
||||
if (PMA_currentUserHasPrivilege($priv, $db)) {
|
||||
$retval .= " <a {$ajax_class['add']} ";
|
||||
$retval .= "href='db_" . strtolower($name) . "s.php";
|
||||
$retval .= "?$url_query&add_item=1'>";
|
||||
$retval .= PMA_getIcon($icon);
|
||||
$retval .= PMA_RTE_getWord('add') . "</a>\n";
|
||||
} else {
|
||||
$retval .= " " . PMA_getIcon($icon);
|
||||
$retval .= PMA_RTE_getWord('no_create') . "\n";
|
||||
}
|
||||
$retval .= " " . PMA_showMySQLDocu('SQL-Syntax', $docu) . "\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
$retval .= "<!-- ADD " . $name . " FORM END -->\n\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_RTE_getFooterLinks()
|
||||
|
||||
/**
|
||||
* Creates a fieldset for adding a new routine, if the user has the privileges.
|
||||
*
|
||||
* @return string HTML code with containing the fotter fieldset
|
||||
*/
|
||||
function PMA_RTN_getFooterLinks()
|
||||
{
|
||||
return PMA_RTE_getFooterLinks('CREATE_PROCEDURE', 'CREATE ROUTINE', 'ROUTINE');
|
||||
}// end PMA_RTN_getFooterLinks()
|
||||
|
||||
/**
|
||||
* Creates a fieldset for adding a new trigger, if the user has the privileges.
|
||||
*
|
||||
* @return string HTML code with containing the fotter fieldset
|
||||
*/
|
||||
function PMA_TRI_getFooterLinks()
|
||||
{
|
||||
return PMA_RTE_getFooterLinks('CREATE_TRIGGER', 'TRIGGER', 'TRIGGER');
|
||||
} // end PMA_TRI_getFooterLinks()
|
||||
|
||||
/**
|
||||
* Creates a fieldset for adding a new event, if the user has the privileges.
|
||||
*
|
||||
* @return string HTML code with containing the fotter fieldset
|
||||
*/
|
||||
function PMA_EVN_getFooterLinks()
|
||||
{
|
||||
global $db, $url_query, $ajax_class;
|
||||
|
||||
/**
|
||||
* For events, we show the usual 'Add event' form and also
|
||||
* a form for toggling the state of the event scheduler
|
||||
*/
|
||||
// Init options for the event scheduler toggle functionality
|
||||
$es_state = PMA_DBI_fetch_value(
|
||||
"SHOW GLOBAL VARIABLES LIKE 'event_scheduler'",
|
||||
0,
|
||||
1
|
||||
);
|
||||
$es_state = strtolower($es_state);
|
||||
$options = array(
|
||||
0 => array(
|
||||
'label' => __('OFF'),
|
||||
'value' => "SET GLOBAL event_scheduler=\"OFF\"",
|
||||
'selected' => ($es_state != 'on')
|
||||
),
|
||||
1 => array(
|
||||
'label' => __('ON'),
|
||||
'value' => "SET GLOBAL event_scheduler=\"ON\"",
|
||||
'selected' => ($es_state == 'on')
|
||||
)
|
||||
);
|
||||
// Generate output
|
||||
$retval = "<!-- FOOTER LINKS START -->\n";
|
||||
$retval .= "<div class='doubleFieldset'>\n";
|
||||
// show the usual footer
|
||||
$retval .= PMA_RTE_getFooterLinks('CREATE_EVENT', 'EVENT', 'EVENT');
|
||||
$retval .= " <fieldset class='right'>\n";
|
||||
$retval .= " <legend>\n";
|
||||
$retval .= " " . __('Event scheduler status') . "\n";
|
||||
$retval .= " </legend>\n";
|
||||
$retval .= " <div class='wrap'>\n";
|
||||
// show the toggle button
|
||||
$retval .= PMA_toggleButton(
|
||||
"sql.php?$url_query&goto=db_events.php" . urlencode("?db=$db"),
|
||||
'sql_query',
|
||||
$options,
|
||||
'PMA_slidingMessage(data.sql_query);'
|
||||
);
|
||||
$retval .= " </div>\n";
|
||||
$retval .= " </fieldset>\n";
|
||||
$retval .= " <div style='clear: both;'></div>\n";
|
||||
$retval .= "</div>";
|
||||
$retval .= "<!-- FOOTER LINKS END -->\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_EVN_getFooterLinks()
|
||||
|
||||
?>
|
||||
338
libraries/rte/rte_list.lib.php
Normal file
338
libraries/rte/rte_list.lib.php
Normal file
@ -0,0 +1,338 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Common functions for generating lists of Routines, Triggers and Events.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of items containing the relevant
|
||||
* information and some action links.
|
||||
*
|
||||
* @param string $type One of ['routine'|'trigger'|'event']
|
||||
* @param array $items An array of items
|
||||
*
|
||||
* @return string HTML code of the list of items
|
||||
*/
|
||||
function PMA_RTE_getList($type, $items)
|
||||
{
|
||||
/**
|
||||
* Conditional classes switch the list on or off
|
||||
*/
|
||||
$class1 = 'hide';
|
||||
$class2 = '';
|
||||
if (! $items) {
|
||||
$class1 = '';
|
||||
$class2 = ' hide';
|
||||
}
|
||||
/**
|
||||
* Generate output
|
||||
*/
|
||||
$retval = "<!-- LIST OF " . PMA_RTE_getWord('docu') . " START -->\n";
|
||||
$retval .= "<fieldset>\n";
|
||||
$retval .= " <legend>\n";
|
||||
$retval .= " " . PMA_RTE_getWord('title') . "\n";
|
||||
$retval .= " " . PMA_showMySQLDocu('SQL-Syntax', PMA_RTE_getWord('docu')) . "\n";
|
||||
$retval .= " </legend>\n";
|
||||
$retval .= " <div class='$class1' id='nothing2display'>\n";
|
||||
$retval .= " " . PMA_RTE_getWord('nothing') . "\n";
|
||||
$retval .= " </div>\n";
|
||||
$retval .= " <table class='data$class2'>\n";
|
||||
$retval .= " <!-- TABLE HEADERS -->\n";
|
||||
$retval .= " <tr>\n";
|
||||
switch ($type) {
|
||||
case 'routine':
|
||||
$retval .= " <th>" . __('Name') . "</th>\n";
|
||||
$retval .= " <th colspan='4'>" . __('Action') . "</th>\n";
|
||||
$retval .= " <th>" . __('Type') . "</th>\n";
|
||||
$retval .= " <th>" . __('Returns') . "</th>\n";
|
||||
break;
|
||||
case 'trigger':
|
||||
$retval .= " <th>" . __('Name') . "</th>\n";
|
||||
$retval .= " <th>" . __('Table') . "</th>\n";
|
||||
$retval .= " <th colspan='3'>" . __('Action') . "</th>\n";
|
||||
$retval .= " <th>" . __('Time') . "</th>\n";
|
||||
$retval .= " <th>" . __('Event') . "</th>\n";
|
||||
break;
|
||||
case 'event':
|
||||
$retval .= " <th>" . __('Name') . "</th>\n";
|
||||
$retval .= " <th>" . __('Status') . "</th>\n";
|
||||
$retval .= " <th colspan='3'>" . __('Action') . "</th>\n";
|
||||
$retval .= " <th>" . __('Type') . "</th>\n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$retval .= " </tr>\n";
|
||||
$retval .= " <!-- TABLE DATA -->\n";
|
||||
$ct = 0;
|
||||
foreach ($items as $item) {
|
||||
$rowclass = ($ct % 2 == 0) ? 'even' : 'odd';
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$rowclass .= ' ajaxInsert hide';
|
||||
}
|
||||
// Get each row from the correct function
|
||||
switch ($type) {
|
||||
case 'routine':
|
||||
$retval .= PMA_RTN_getRowForList($item, $rowclass);
|
||||
break;
|
||||
case 'trigger':
|
||||
$retval .= PMA_TRI_getRowForList($item, $rowclass);
|
||||
break;
|
||||
case 'event':
|
||||
$retval .= PMA_EVN_getRowForList($item, $rowclass);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$ct++;
|
||||
}
|
||||
$retval .= " </table>\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
$retval .= "<!-- LIST OF " . PMA_RTE_getWord('docu') . " END -->\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_RTE_getList()
|
||||
|
||||
/**
|
||||
* Creates the contents for a row in the list of routines
|
||||
*
|
||||
* @param array $routine An array of routine data
|
||||
* @param string $rowclass Empty or one of ['even'|'odd']
|
||||
*
|
||||
* @return string HTML code of a row for the list of routines
|
||||
*/
|
||||
function PMA_RTN_getRowForList($routine, $rowclass = '')
|
||||
{
|
||||
global $ajax_class, $url_query, $db, $titles;
|
||||
|
||||
$sql_drop = sprintf('DROP %s IF EXISTS %s',
|
||||
$routine['ROUTINE_TYPE'],
|
||||
PMA_backquote($routine['SPECIFIC_NAME']));
|
||||
|
||||
|
||||
$retval = " <tr class='noclick $rowclass'>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <span class='drop_sql hide'>$sql_drop</span>\n";
|
||||
$retval .= " <strong>\n";
|
||||
$retval .= " " . htmlspecialchars($routine['SPECIFIC_NAME']) . "\n";
|
||||
$retval .= " </strong>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if ($routine['ROUTINE_DEFINITION'] !== null
|
||||
&& PMA_currentUserHasPrivilege('ALTER ROUTINE', $db)
|
||||
&& PMA_currentUserHasPrivilege('CREATE ROUTINE', $db)
|
||||
) {
|
||||
$retval .= ' <a ' . $ajax_class['edit']
|
||||
. ' href="db_routines.php?'
|
||||
. $url_query
|
||||
. '&edit_item=1'
|
||||
. '&item_name=' . urlencode($routine['SPECIFIC_NAME'])
|
||||
. '">' . $titles['Edit'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoEdit']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if ($routine['ROUTINE_DEFINITION'] !== null
|
||||
&& PMA_currentUserHasPrivilege('EXECUTE', $db)
|
||||
) {
|
||||
// Check if he routine has any input parameters. If it does,
|
||||
// we will show a dialog to get values for these parameters,
|
||||
// otherwise we can execute it directly.
|
||||
$routine_details = PMA_RTN_getDataFromName(
|
||||
$routine['SPECIFIC_NAME'],
|
||||
false
|
||||
);
|
||||
if ($routine !== false) {
|
||||
$execute_action = 'execute_routine';
|
||||
for ($i=0; $i<$routine_details['item_num_params']; $i++) {
|
||||
if ($routine_details['item_type'] == 'PROCEDURE'
|
||||
&& $routine_details['item_param_dir'][$i] == 'OUT'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
$execute_action = 'execute_dialog';
|
||||
break;
|
||||
}
|
||||
$retval .= ' <a ' . $ajax_class['exec']
|
||||
. ' href="db_routines.php?'
|
||||
. $url_query
|
||||
. '&' . $execute_action . '=1'
|
||||
. '&item_name=' . urlencode($routine['SPECIFIC_NAME'])
|
||||
. '">' . $titles['Execute'] . "</a>\n";
|
||||
}
|
||||
} else {
|
||||
$retval .= " {$titles['NoExecute']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= ' <a ' . $ajax_class['export']
|
||||
. ' href="db_routines.php?'
|
||||
. $url_query
|
||||
. '&export_item=1'
|
||||
. '&item_name=' . urlencode($routine['SPECIFIC_NAME'])
|
||||
. '">' . $titles['Export'] . "</a>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if (PMA_currentUserHasPrivilege('EVENT', $db)) {
|
||||
$retval .= ' <a ' . $ajax_class['drop']
|
||||
. ' href="sql.php?'
|
||||
. $url_query
|
||||
. '&sql_query=' . urlencode($sql_drop)
|
||||
. '&goto=db_events.php' . urlencode("?db={$db}")
|
||||
. '" >' . $titles['Drop'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoDrop']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " {$routine['ROUTINE_TYPE']}\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " " . htmlspecialchars($routine['DTD_IDENTIFIER']) . "\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " </tr>\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_RTN_getRowForList()
|
||||
|
||||
/**
|
||||
* Creates the contents for a row in the list of triggers
|
||||
*
|
||||
* @param array $trigger An array of routine data
|
||||
* @param string $rowclass Empty or one of ['even'|'odd']
|
||||
*
|
||||
* @return string HTML code of a cell for the list of triggers
|
||||
*/
|
||||
function PMA_TRI_getRowForList($trigger, $rowclass = '')
|
||||
{
|
||||
global $ajax_class, $url_query, $db, $table, $titles;
|
||||
|
||||
$retval = " <tr class='noclick $rowclass'>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <span class='drop_sql hide'>{$trigger['drop']}</span>\n";
|
||||
$retval .= " <strong>\n";
|
||||
$retval .= " " . htmlspecialchars($trigger['name']) . "\n";
|
||||
$retval .= " </strong>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <a href='db_triggers.php?db={$db}"
|
||||
. "&table={$trigger['table']}'>"
|
||||
. $trigger['table'] . "</a>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if (PMA_currentUserHasPrivilege('TRIGGER', $db, $table)) {
|
||||
$retval .= ' <a ' . $ajax_class['edit']
|
||||
. ' href="db_triggers.php?'
|
||||
. $url_query
|
||||
. '&edit_item=1'
|
||||
. '&item_name=' . urlencode($trigger['name'])
|
||||
. '">' . $titles['Edit'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoEdit']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= ' <a ' . $ajax_class['export']
|
||||
. ' href="db_triggers.php?'
|
||||
. $url_query
|
||||
. '&export_item=1'
|
||||
. '&item_name=' . urlencode($trigger['name'])
|
||||
. '">' . $titles['Export'] . "</a>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if (PMA_currentUserHasPrivilege('TRIGGER', $db)) {
|
||||
$retval .= ' <a ' . $ajax_class['drop']
|
||||
. ' href="sql.php?'
|
||||
. $url_query
|
||||
. '&sql_query=' . urlencode($trigger['drop'])
|
||||
. '&goto=db_triggers.php' . urlencode("?db={$db}")
|
||||
. '" >' . $titles['Drop'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoDrop']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " {$trigger['action_timing']}\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " {$trigger['event_manipulation']}\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " </tr>\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_TRI_getRowForList()
|
||||
|
||||
/**
|
||||
* Creates the contents for a row in the list of events
|
||||
*
|
||||
* @param array $event An array of routine data
|
||||
* @param string $rowclass Empty or one of ['even'|'odd']
|
||||
*
|
||||
* @return string HTML code of a cell for the list of events
|
||||
*/
|
||||
function PMA_EVN_getRowForList($event, $rowclass = '')
|
||||
{
|
||||
global $ajax_class, $url_query, $db, $titles;
|
||||
|
||||
$sql_drop = sprintf(
|
||||
'DROP EVENT IF EXISTS %s',
|
||||
PMA_backquote($event['EVENT_NAME'])
|
||||
);
|
||||
|
||||
$retval = " <tr class='noclick $rowclass'>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <span class='drop_sql hide'>$sql_drop</span>\n";
|
||||
$retval .= " <strong>\n";
|
||||
$retval .= " " . htmlspecialchars($event['EVENT_NAME']) . "\n";
|
||||
$retval .= " </strong>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " {$event['STATUS']}\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if (PMA_currentUserHasPrivilege('EVENT', $db)) {
|
||||
$retval .= ' <a ' . $ajax_class['edit']
|
||||
. ' href="db_events.php?'
|
||||
. $url_query
|
||||
. '&edit_item=1'
|
||||
. '&item_name=' . urlencode($event['EVENT_NAME'])
|
||||
. '">' . $titles['Edit'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoEdit']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= ' <a ' . $ajax_class['export']
|
||||
. ' href="db_events.php?'
|
||||
. $url_query
|
||||
. '&export_item=1'
|
||||
. '&item_name=' . urlencode($event['EVENT_NAME'])
|
||||
. '">' . $titles['Export'] . "</a>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
if (PMA_currentUserHasPrivilege('EVENT', $db)) {
|
||||
$retval .= ' <a ' . $ajax_class['drop']
|
||||
. ' href="sql.php?'
|
||||
. $url_query
|
||||
. '&sql_query=' . urlencode($sql_drop)
|
||||
. '&goto=db_events.php' . urlencode("?db={$db}")
|
||||
. '" >' . $titles['Drop'] . "</a>\n";
|
||||
} else {
|
||||
$retval .= " {$titles['NoDrop']}\n";
|
||||
}
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " {$event['EVENT_TYPE']}\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= " </tr>\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_EVN_getRowForList()
|
||||
|
||||
?>
|
||||
135
libraries/rte/rte_main.inc.php
Normal file
135
libraries/rte/rte_main.inc.php
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Common code for Routines, Triggers and Events.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include all other files that are common
|
||||
* to routines, triggers and events.
|
||||
*/
|
||||
require_once './libraries/rte/rte_export.lib.php';
|
||||
require_once './libraries/rte/rte_list.lib.php';
|
||||
require_once './libraries/rte/rte_footer.lib.php';
|
||||
|
||||
if ($GLOBALS['is_ajax_request'] != true) {
|
||||
/**
|
||||
* Displays the header and tabs
|
||||
*/
|
||||
if (! empty($table) && in_array($table, PMA_DBI_get_tables($db))) {
|
||||
require_once './libraries/tbl_common.php';
|
||||
require_once './libraries/tbl_links.inc.php';
|
||||
} else {
|
||||
$table = '';
|
||||
require_once './libraries/db_common.inc.php';
|
||||
require_once './libraries/db_info.inc.php';
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Since we did not include some libraries, we need
|
||||
* to manually select the required database and
|
||||
* create the missing $url_query variable
|
||||
*/
|
||||
if (strlen($db)) {
|
||||
PMA_DBI_select_db($db);
|
||||
if (! isset($url_query)) {
|
||||
$url_query = PMA_generate_common_url($db, $table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the conditional classes that will
|
||||
* be used to attach jQuery events to links
|
||||
*/
|
||||
$ajax_class = array('add' => '',
|
||||
'edit' => '',
|
||||
'exec' => '',
|
||||
'drop' => '',
|
||||
'export' => '');
|
||||
if ($GLOBALS['cfg']['AjaxEnable']) {
|
||||
$ajax_class = array('add' => 'class="ajax_add_anchor"',
|
||||
'edit' => 'class="ajax_edit_anchor"',
|
||||
'exec' => 'class="ajax_exec_anchor"',
|
||||
'drop' => 'class="ajax_drop_anchor"',
|
||||
'export' => 'class="ajax_export_anchor"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create labels for the list
|
||||
*/
|
||||
$titles = PMA_buildActionTitles();
|
||||
|
||||
/**
|
||||
* Keep a list of errors that occured while
|
||||
* processing an 'Add' or 'Edit' operation.
|
||||
*/
|
||||
$errors = array();
|
||||
|
||||
// Some definitions for triggers
|
||||
$action_timings = array('BEFORE',
|
||||
'AFTER');
|
||||
$event_manipulations = array('INSERT',
|
||||
'UPDATE',
|
||||
'DELETE');
|
||||
|
||||
// Some definitions for routines
|
||||
$param_directions = array('IN',
|
||||
'OUT',
|
||||
'INOUT');
|
||||
$param_opts_num = array('UNSIGNED',
|
||||
'ZEROFILL',
|
||||
'UNSIGNED ZEROFILL');
|
||||
$param_sqldataaccess = array('NO SQL',
|
||||
'CONTAINS SQL',
|
||||
'READS SQL DATA',
|
||||
'MODIFIES SQL DATA');
|
||||
|
||||
// Some definitions for events
|
||||
$event_status = array(
|
||||
'query' => array('ENABLE',
|
||||
'DISABLE',
|
||||
'DISABLE ON SLAVE'),
|
||||
'display' => array('ENABLED',
|
||||
'DISABLED',
|
||||
'SLAVESIDE_DISABLED')
|
||||
);
|
||||
$event_type = array('RECURRING',
|
||||
'ONE TIME');
|
||||
$event_interval = array('YEAR',
|
||||
'QUARTER',
|
||||
'MONTH',
|
||||
'DAY',
|
||||
'HOUR',
|
||||
'MINUTE',
|
||||
'WEEK',
|
||||
'SECOND',
|
||||
'YEAR_MONTH',
|
||||
'DAY_HOUR',
|
||||
'DAY_MINUTE',
|
||||
'DAY_SECOND',
|
||||
'HOUR_MINUTE',
|
||||
'HOUR_SECOND',
|
||||
'MINUTE_SECOND');
|
||||
/**
|
||||
* The below function is defined in rte_routines.lib.php,
|
||||
* rte_triggers.lib.php and rte_events.lib.php
|
||||
*
|
||||
* The appropriate function will now be called based on which one
|
||||
* of these files was included earlier in the top-level folder
|
||||
*/
|
||||
PMA_RTE_main();
|
||||
|
||||
/**
|
||||
* Display the footer, if necessary
|
||||
*/
|
||||
if ($GLOBALS['is_ajax_request'] != true) {
|
||||
require './libraries/footer.inc.php';
|
||||
}
|
||||
|
||||
?>
|
||||
1509
libraries/rte/rte_routines.lib.php
Normal file
1509
libraries/rte/rte_routines.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
435
libraries/rte/rte_triggers.lib.php
Normal file
435
libraries/rte/rte_triggers.lib.php
Normal file
@ -0,0 +1,435 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Functions for trigger management.
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is defined in: rte_routines.lib.php, rte_triggers.lib.php and
|
||||
* rte_events.lib.php. It is used to retreive some language strings that are
|
||||
* used in functionalities that are common to routines, triggers and events.
|
||||
*
|
||||
* @param string $index The index of the string to get
|
||||
*
|
||||
* @return string The requested string or an empty string, if not available
|
||||
*/
|
||||
function PMA_RTE_getWord($index)
|
||||
{
|
||||
$words = array(
|
||||
'add' => __('Add trigger'),
|
||||
'docu' => 'TRIGGERS',
|
||||
'export' => __('Export of trigger %s'),
|
||||
'human' => __('trigger'),
|
||||
'no_create' => __('You do not have the necessary privileges to create a new trigger'),
|
||||
'not_found' => __('No trigger with name %1$s found in database %2$s'),
|
||||
'nothing' => __('There are no triggers to display.'),
|
||||
'title' => __('Triggers'),
|
||||
);
|
||||
return isset($words[$index]) ? $words[$index] : '';
|
||||
} // end PMA_RTE_getWord()
|
||||
|
||||
/**
|
||||
* Main function for the triggers functionality
|
||||
*/
|
||||
function PMA_RTE_main()
|
||||
{
|
||||
global $db, $table;
|
||||
|
||||
/**
|
||||
* Process all requests
|
||||
*/
|
||||
PMA_TRI_handleEditor();
|
||||
PMA_TRI_handleExport();
|
||||
/**
|
||||
* Display a list of available triggers
|
||||
*/
|
||||
$items = PMA_DBI_get_triggers($db, $table);
|
||||
echo PMA_RTE_getList('trigger', $items);
|
||||
/**
|
||||
* Display a link for adding a new trigger,
|
||||
* if the user has the necessary privileges
|
||||
*/
|
||||
echo PMA_TRI_getFooterLinks();
|
||||
} // end PMA_RTE_main()
|
||||
|
||||
/**
|
||||
* Handles editor requests for adding or editing an item
|
||||
*/
|
||||
function PMA_TRI_handleEditor()
|
||||
{
|
||||
global $_REQUEST, $_POST, $errors, $db, $table;
|
||||
|
||||
if (! empty($_REQUEST['editor_process_add'])
|
||||
|| ! empty($_REQUEST['editor_process_edit'])
|
||||
) {
|
||||
$sql_query = '';
|
||||
|
||||
$item_query = PMA_TRI_getQueryFromRequest();
|
||||
|
||||
if (! count($errors)) { // set by PMA_RTN_getQueryFromRequest()
|
||||
// Execute the created query
|
||||
if (! empty($_REQUEST['editor_process_edit'])) {
|
||||
// Backup the old trigger, in case something goes wrong
|
||||
$trigger = PMA_TRI_getDataFromName($_REQUEST['item_original_name']);
|
||||
$create_item = $trigger['create'];
|
||||
$drop_item = $trigger['drop'] . ';';
|
||||
$result = PMA_DBI_try_query($drop_item);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $drop_item) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$result = PMA_DBI_try_query($item_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $item_query) . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
// We dropped the old item, but were unable to create the new one
|
||||
// Try to restore the backup query
|
||||
$result = PMA_DBI_try_query($create_item);
|
||||
if (! $result) {
|
||||
// OMG, this is really bad! We dropped the query, failed to create a new one
|
||||
// and now even the backup query does not execute!
|
||||
// This should not happen, but we better handle this just in case.
|
||||
$errors[] = __('Sorry, we failed to restore the dropped trigger.') . '<br />'
|
||||
. __('The backed up query was:') . "\"$create_item\"" . '<br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
}
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Trigger %1$s has been modified.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['item_name']));
|
||||
$sql_query = $drop_item . $item_query;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 'Add a new item' mode
|
||||
$result = PMA_DBI_try_query($item_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(__('The following query has failed: "%s"'), $item_query) . '<br /><br />'
|
||||
. __('MySQL said: ') . PMA_DBI_getError(null);
|
||||
} else {
|
||||
$message = PMA_Message::success(__('Trigger %1$s has been created.'));
|
||||
$message->addParam(PMA_backquote($_REQUEST['item_name']));
|
||||
$sql_query = $item_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors)) {
|
||||
$message = PMA_Message::error(__('<b>One or more errors have occured while processing your request:</b>'));
|
||||
$message->addString('<ul>');
|
||||
foreach ($errors as $num => $string) {
|
||||
$message->addString('<li>' . $string . '</li>');
|
||||
}
|
||||
$message->addString('</ul>');
|
||||
}
|
||||
|
||||
$output = PMA_showMessage($message, $sql_query);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array();
|
||||
if ($message->isSuccess()) {
|
||||
$items = PMA_DBI_get_triggers($db, $table, '');
|
||||
$trigger = false;
|
||||
foreach ($items as $key => $value) {
|
||||
if ($value['name'] == $_REQUEST['item_name']) {
|
||||
$trigger = $value;
|
||||
}
|
||||
}
|
||||
$extra_data['insert'] = false;
|
||||
if (empty($table) || ($trigger !== false && $table == $trigger['table'])) {
|
||||
$extra_data['insert'] = true;
|
||||
$extra_data['new_row'] = PMA_TRI_getRowForList($trigger);
|
||||
$extra_data['name'] = htmlspecialchars(
|
||||
strtoupper($_REQUEST['item_name'])
|
||||
);
|
||||
}
|
||||
$response = $output;
|
||||
} else {
|
||||
$response = $message;
|
||||
}
|
||||
PMA_ajaxResponse($response, $message->isSuccess(), $extra_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a form used to add/edit a trigger, if necessary
|
||||
*/
|
||||
if (count($errors) || ( empty($_REQUEST['editor_process_add']) && empty($_REQUEST['editor_process_edit'])
|
||||
&& (! empty($_REQUEST['add_item']) || ! empty($_REQUEST['edit_item']))) // FIXME: this must be simpler than that
|
||||
) {
|
||||
// Get the data for the form (if any)
|
||||
if (! empty($_REQUEST['add_item'])) {
|
||||
$title = __("Create trigger");
|
||||
$item = PMA_TRI_getDataFromRequest();
|
||||
$mode = 'add';
|
||||
} else if (! empty($_REQUEST['edit_item'])) {
|
||||
$title = __("Edit trigger");
|
||||
if (! empty($_REQUEST['item_name'])
|
||||
&& empty($_REQUEST['editor_process_edit'])
|
||||
) {
|
||||
$item = PMA_TRI_getDataFromName($_REQUEST['item_name']);
|
||||
if ($item !== false) {
|
||||
$item['item_original_name'] = $item['item_name'];
|
||||
}
|
||||
} else {
|
||||
$item = PMA_TRI_getDataFromRequest();
|
||||
}
|
||||
$mode = 'edit';
|
||||
}
|
||||
if ($item !== false) {
|
||||
// Show form
|
||||
$editor = PMA_TRI_getEditorForm($mode, $item);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$extra_data = array('title' => $title);
|
||||
PMA_ajaxResponse($editor, true, $extra_data);
|
||||
} else {
|
||||
echo "\n\n<h2>$title</h2>\n\n$editor";
|
||||
unset($_POST);
|
||||
require './libraries/footer.inc.php';
|
||||
}
|
||||
// exit;
|
||||
} else {
|
||||
$message = __('Error in processing request') . ' : ';
|
||||
$message .= sprintf(
|
||||
PMA_RTE_getWord('not_found'),
|
||||
htmlspecialchars(PMA_backquote($_REQUEST['item_name'])),
|
||||
htmlspecialchars(PMA_backquote($db))
|
||||
);
|
||||
$message = PMA_message::error($message);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
PMA_ajaxResponse($message, false);
|
||||
} else {
|
||||
$message->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end PMA_TRI_handleEditor()
|
||||
|
||||
/**
|
||||
* This function will generate the values that are required to for the editor
|
||||
*
|
||||
* @return array Data necessary to create the editor.
|
||||
*/
|
||||
function PMA_TRI_getDataFromRequest()
|
||||
{
|
||||
$retval = array();
|
||||
$indices = array('item_name',
|
||||
'item_table',
|
||||
'item_original_name',
|
||||
'item_action_timing',
|
||||
'item_event_manipulation',
|
||||
'item_definition',
|
||||
'item_definer');
|
||||
foreach ($indices as $key => $index) {
|
||||
$retval[$index] = isset($_REQUEST[$index]) ? $_REQUEST[$index] : '';
|
||||
}
|
||||
return $retval;
|
||||
} // end PMA_TRI_getDataFromRequest()
|
||||
|
||||
/**
|
||||
* This function will generate the values that are required to complete
|
||||
* the "Edit trigger" form given the name of a trigger.
|
||||
*
|
||||
* @param string $name The name of the trigger.
|
||||
*
|
||||
* @return array Data necessary to create the editor.
|
||||
*/
|
||||
function PMA_TRI_getDataFromName($name)
|
||||
{
|
||||
global $db, $table, $_REQUEST;
|
||||
|
||||
$temp = array();
|
||||
$items = PMA_DBI_get_triggers($db, $table, '');
|
||||
foreach ($items as $key => $value) {
|
||||
if ($value['name'] == $name) {
|
||||
$temp = $value;
|
||||
}
|
||||
}
|
||||
if (empty($temp)) {
|
||||
return false;
|
||||
} else {
|
||||
$retval = array();
|
||||
$retval['create'] = $temp['create'];
|
||||
$retval['drop'] = $temp['drop'];
|
||||
$retval['item_name'] = $temp['name'];
|
||||
$retval['item_table'] = $temp['table'];
|
||||
$retval['item_action_timing'] = $temp['action_timing'];
|
||||
$retval['item_event_manipulation'] = $temp['event_manipulation'];
|
||||
$retval['item_definition'] = $temp['definition'];
|
||||
$retval['item_definer'] = $temp['definer'];
|
||||
return $retval;
|
||||
}
|
||||
} // end PMA_TRI_getDataFromName()
|
||||
|
||||
/**
|
||||
* Displays a form used to add/edit a trigger
|
||||
*
|
||||
* @param string $mode If the editor will be used edit a trigger
|
||||
* or add a new one: 'edit' or 'add'.
|
||||
* @param array $item Data for the trigger returned by
|
||||
* PMA_TRI_getDataFromRequest() or
|
||||
* PMA_TRI_getDataFromName()
|
||||
*
|
||||
* @return string HTML code for the editor.
|
||||
*/
|
||||
function PMA_TRI_getEditorForm($mode, $item)
|
||||
{
|
||||
global $db, $table, $titles, $event_manipulations, $action_timings;
|
||||
|
||||
// Escape special characters
|
||||
$need_escape = array(
|
||||
'item_original_name',
|
||||
'item_name',
|
||||
'item_definition',
|
||||
'item_definer'
|
||||
);
|
||||
foreach ($need_escape as $key => $index) {
|
||||
$item[$index] = htmlentities($item[$index], ENT_QUOTES);
|
||||
}
|
||||
$original_data = '';
|
||||
if ($mode == 'edit') {
|
||||
$original_data = "<input name='item_original_name' "
|
||||
. "type='hidden' value='{$item['item_original_name']}'/>\n";
|
||||
}
|
||||
|
||||
// Create the output
|
||||
$retval = "";
|
||||
$retval .= "<!-- START " . strtoupper($mode) . " TRIGGER FORM -->\n\n";
|
||||
$retval .= "<form class='rte_form' action='db_triggers.php' method='post'>\n";
|
||||
$retval .= "<input name='{$mode}_item' type='hidden' value='1' />\n";
|
||||
$retval .= $original_data;
|
||||
$retval .= PMA_generate_common_hidden_inputs($db, $table) . "\n";
|
||||
$retval .= "<fieldset>\n";
|
||||
$retval .= "<legend>" . __('Details') . "</legend>\n";
|
||||
$retval .= "<table class='rte_table' style='width: 100%'>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td style='width: 20%;'>" . __('Trigger name') . "</td>\n";
|
||||
$retval .= " <td><input type='text' name='item_name' maxlength='64'\n";
|
||||
$retval .= " value='{$item['item_name']}' /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Table') . "</td>\n";
|
||||
$retval .= " <td>\n";
|
||||
$retval .= " <select name='item_table'>\n";
|
||||
foreach (PMA_DBI_get_tables($db) as $key => $value) {
|
||||
$selected = "";
|
||||
if ($value == $item['item_table']) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= " <option$selected>$value</option>\n";
|
||||
}
|
||||
$retval .= " </select>\n";
|
||||
$retval .= " </td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Time') . "</td>\n";
|
||||
$retval .= " <td><select name='item_timing'>\n";
|
||||
foreach ($action_timings as $key => $value) {
|
||||
$selected = "";
|
||||
if (! empty($item['item_action_timing'])
|
||||
&& $item['item_action_timing'] == $value
|
||||
) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= "<option$selected>$value</option>";
|
||||
}
|
||||
$retval .= " </select></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Event') . "</td>\n";
|
||||
$retval .= " <td><select name='item_event'>\n";
|
||||
foreach ($event_manipulations as $key => $value) {
|
||||
$selected = "";
|
||||
if (! empty($item['item_event_manipulation'])
|
||||
&& $item['item_event_manipulation'] == $value
|
||||
) {
|
||||
$selected = " selected='selected'";
|
||||
}
|
||||
$retval .= "<option$selected>$value</option>";
|
||||
}
|
||||
$retval .= " </select></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Definition') . "</td>\n";
|
||||
$retval .= " <td><textarea name='item_definition' rows='15' cols='40'>";
|
||||
$retval .= $item['item_definition'];
|
||||
$retval .= "</textarea></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "<tr>\n";
|
||||
$retval .= " <td>" . __('Definer') . "</td>\n";
|
||||
$retval .= " <td><input type='text' name='item_definer'\n";
|
||||
$retval .= " value='{$item['item_definer']}' /></td>\n";
|
||||
$retval .= "</tr>\n";
|
||||
$retval .= "</table>\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$retval .= "<input type='hidden' name='editor_process_{$mode}'\n";
|
||||
$retval .= " value='true' />\n";
|
||||
$retval .= "<input type='hidden' name='ajax_request' value='true' />\n";
|
||||
} else {
|
||||
$retval .= "<fieldset class='tblFooters'>\n";
|
||||
$retval .= " <input type='submit' name='editor_process_{$mode}'\n";
|
||||
$retval .= " value='" . __('Go') . "' />\n";
|
||||
$retval .= "</fieldset>\n";
|
||||
}
|
||||
$retval .= "</form>\n\n";
|
||||
$retval .= "<!-- END " . strtoupper($mode) . " TRIGGER FORM -->\n\n";
|
||||
|
||||
return $retval;
|
||||
} // end PMA_TRI_getEditorForm()
|
||||
|
||||
/**
|
||||
* Composes the query necessary to create a trigger from an HTTP request.
|
||||
*
|
||||
* @return string The CREATE TRIGGER query.
|
||||
*/
|
||||
function PMA_TRI_getQueryFromRequest()
|
||||
{
|
||||
global $_REQUEST, $db, $errors, $action_timings, $event_manipulations;
|
||||
|
||||
$query = 'CREATE ';
|
||||
if (! empty($_REQUEST['item_definer'])) {
|
||||
if (strpos($_REQUEST['item_definer'], '@') !== false) {
|
||||
$arr = explode('@', $_REQUEST['item_definer']);
|
||||
$query .= 'DEFINER=' . PMA_backquote($arr[0]);
|
||||
$query .= '@' . PMA_backquote($arr[1]) . ' ';
|
||||
} else {
|
||||
$errors[] = __('The definer must be in the "username@hostname" format');
|
||||
}
|
||||
}
|
||||
$query .= 'TRIGGER ';
|
||||
if (! empty($_REQUEST['item_name'])) {
|
||||
$query .= PMA_backquote($_REQUEST['item_name']) . ' ';
|
||||
} else {
|
||||
$errors[] = __('You must provide a trigger name');
|
||||
}
|
||||
if (! empty($_REQUEST['item_timing']) && in_array($_REQUEST['item_timing'], $action_timings)) {
|
||||
$query .= $_REQUEST['item_timing'] . ' ';
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid timing for the trigger');
|
||||
}
|
||||
if (! empty($_REQUEST['item_event']) && in_array($_REQUEST['item_event'], $event_manipulations)) {
|
||||
$query .= $_REQUEST['item_event'] . ' ';
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid event for the trigger');
|
||||
}
|
||||
$query .= 'ON ';
|
||||
if (! empty($_REQUEST['item_table']) && in_array($_REQUEST['item_table'], PMA_DBI_get_tables($db))) {
|
||||
$query .= PMA_backQuote($_REQUEST['item_table']);
|
||||
} else {
|
||||
$errors[] = __('You must provide a valid table name');
|
||||
}
|
||||
$query .= ' FOR EACH ROW ';
|
||||
if (! empty($_REQUEST['item_definition'])) {
|
||||
$query .= $_REQUEST['item_definition'];
|
||||
} else {
|
||||
$errors[] = __('You must provide a trigger definition.');
|
||||
}
|
||||
|
||||
return $query;
|
||||
} // end PMA_TRI_getQueryFromRequest()
|
||||
|
||||
?>
|
||||
@ -97,11 +97,12 @@ if(PMA_Tracker::isActive()) {
|
||||
$tabs['tracking']['text'] = __('Tracking');
|
||||
$tabs['tracking']['link'] = 'tbl_tracking.php';
|
||||
}
|
||||
if (! $db_is_information_schema && PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) {
|
||||
// Temporarily hiding this unfinished feature
|
||||
// $tabs['triggers']['link'] = 'tbl_triggers.php';
|
||||
// $tabs['triggers']['text'] = __('Triggers');
|
||||
// $tabs['triggers']['icon'] = 'b_triggers.png';
|
||||
if (!$db_is_information_schema && !PMA_DRIZZLE) {
|
||||
if (PMA_currentUserHasPrivilege('TRIGGER', $db, $table)) {
|
||||
$tabs['triggers']['link'] = 'tbl_triggers.php';
|
||||
$tabs['triggers']['text'] = __('Triggers');
|
||||
$tabs['triggers']['icon'] = 'b_triggers.png';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
1476
po/be@latin.po
1476
po/be@latin.po
File diff suppressed because it is too large
Load Diff
1442
po/en_GB.po
1442
po/en_GB.po
File diff suppressed because it is too large
Load Diff
1333
po/phpmyadmin.pot
1333
po/phpmyadmin.pot
File diff suppressed because it is too large
Load Diff
1505
po/pt_BR.po
1505
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1462
po/sr@latin.po
1462
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1500
po/uz@latin.po
1500
po/uz@latin.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user