From cf61fb1270d0efc4759723dd3467e117fa657eb2 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Thu, 30 Jun 2011 13:12:26 +0100 Subject: [PATCH] Prototype integration of Triggers editor. --- db_triggers.php | 1 + js/db_routines.js | 214 +++++++++-------- libraries/database_interface.lib.php | 13 +- libraries/rte/rte_events.lib.php | 4 +- libraries/rte/rte_footer.lib.php | 2 +- libraries/rte/rte_list.lib.php | 16 +- libraries/rte/rte_main.inc.php | 13 +- libraries/rte/rte_routines.lib.php | 122 +++++----- libraries/rte/rte_triggers.lib.php | 332 ++++++++++++++++++++++++++- 9 files changed, 543 insertions(+), 174 deletions(-) diff --git a/db_triggers.php b/db_triggers.php index ce5162bb97..cc7ce8c0ed 100644 --- a/db_triggers.php +++ b/db_triggers.php @@ -17,6 +17,7 @@ require_once './libraries/common.lib.php'; */ $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'db_triggers.js'; +$GLOBALS['js_include'][] = 'db_routines.js'; // FIXME /** * Include all other files diff --git a/js/db_routines.js b/js/db_routines.js index e4e17f6a8f..ffb03cf00d 100644 --- a/js/db_routines.js +++ b/js/db_routines.js @@ -1,14 +1,14 @@ /* vim: set expandtab sw=4 ts=4 sts=4: */ /** - * Validate routine editor form fields. + * Validate 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) { +function validateEditor(syntaxHiglighter) { /** * @var inputname Will contain the value of the name * attribute of input fields being checked. @@ -24,7 +24,8 @@ function validateRoutineEditor(syntaxHiglighter) { */ var isError = false; - $elm = $('.rte_table').last().find('input[name=routine_name]'); + // Common validation + $elm = $('.rte_table').last().find('input[name=item_name]'); if ($elm.val() == '') { $elm.focus(); isError = true; @@ -34,69 +35,73 @@ function validateRoutineEditor(syntaxHiglighter) { return false; } if (! isError) { - $elm = $('.rte_table').find('textarea[name=routine_definition]'); + $elm = $('.rte_table').find('textarea[name=item_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; + + // Validate routines editor + if (editor == 'routine') { + 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) { + // 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') { - // 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 && $('select[name=routine_type]').find(':selected').val() == 'FUNCTION') { + if ($('.rte_table').find('textarea[name=item_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) { + $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) { @@ -105,7 +110,7 @@ function validateRoutineEditor(syntaxHiglighter) { alert(PMA_messages['strFormEmpty']); return false; } -} // end validateRoutineEditor() +} // end validateEditor() /** * Enable/disable the "options" dropdown and "length" input for @@ -178,14 +183,21 @@ function setOptionsForParameter($type, $len, $text, $num) { } /** - * Attach Ajax event handlers for the Routines functionalities. + * What type item the editor is for. + * Can be one of [routine|trigger|event]. + * Loaded through AJAX with JSON data. + */ +var editor = null; + +/** + * Attach Ajax event handlers for the Routines, Triggers and Events functionalities. * * @see $cfg['AjaxEnable'] */ $(document).ready(function() { /** * @var $ajaxDialog jQuery object containing the reference to the - * dialog that contains the routine editor. + * dialog that contains the editor. */ var $ajaxDialog = null; /** @@ -204,7 +216,7 @@ $(document).ready(function() { var button_options = {}; /** - * Attach Ajax event handlers for the Add/Edit routine functionality. + * Attach Ajax event handlers for the Add/Edit functionality. * * @uses PMA_ajaxShowMessage() * @uses PMA_ajaxRemoveMessage() @@ -215,14 +227,14 @@ $(document).ready(function() { event.preventDefault(); /** * @var $edit_row jQuery object containing the reference to - * the row of the the routine being edited - * from the list of routines . + * 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 routine being edited for later, + // 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 routine. + // row with info about the modified item. $edit_row = $(this).parents('tr'); } /** @@ -232,19 +244,20 @@ $(document).ready(function() { var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); $.get($(this).attr('href'), {'ajax_request': true}, function(data) { if(data.success == true) { + editor = data.editor; PMA_ajaxRemoveMessage($msg); button_options[PMA_messages['strGo']] = function() { syntaxHiglighter.save(); // Validate editor and submit request, if passed. - if (validateRoutineEditor(syntaxHiglighter)) { + if (validateEditor(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) { + $.post($('.rte_form').last().attr('action'), data, function (data) { if(data.success == true) { - // Routine created successfully + // Item created successfully PMA_ajaxRemoveMessage($msg); PMA_slidingMessage(data.message); $ajaxDialog.dialog('close'); @@ -289,8 +302,8 @@ $(document).ready(function() { $(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 this is the first item being added, remove the + // "No items" message and show the list of items. if ($('table.data').find('tr').has('td').length > 0 && $('#nothing2display').is(':visible')) { $('#nothing2display').hide("slow", function () { $('table.data').show("slow"); @@ -310,7 +323,7 @@ $(document).ready(function() { */ $ajaxDialog = $('
'+data.message+'
').dialog({ width: 700, // TODO: make a better decision about the size - height: 550, // of the dialog based on the size of the viewport + height: 555, // of the dialog based on the size of the viewport buttons: button_options, title: data.title, modal: true, @@ -318,44 +331,47 @@ $(document).ready(function() { $(this).remove(); } }); - $ajaxDialog.find('input[name=routine_name]').focus(); + $ajaxDialog.find('input[name=item_name]').focus(); /** * @var mode Used to remeber whether the editor is in - * "Edit Routine" or "Add Routine" mode. + * "Edit" or "Add" mode. */ var mode = 'add'; - if ($('input[name=routine_process_editroutine]').length > 0) { + if ($('input[name=editor_process_edit]').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() { + // Routines-specific code + if (editor == 'routine') { + // 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( - $(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]') + $('.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]') ); - }); - // 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 $elm = $('textarea[name=item_definition]').last(); /** * @var opts Options to pass to the codemirror editor. */ @@ -551,13 +567,13 @@ $(document).ready(function() { }); /** - * 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. + * 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. * * @see $cfg['AjaxEnable'] */ - $('input[name^=routine], input[name^=params]').live('keydown', function(e) { + $('.rte_table').find('input[name^=item], input[name^=params]').live('keydown', function(e) { if (e.which == 13) { e.preventDefault(); if (typeof button_options[PMA_messages['strGo']] == 'function') { diff --git a/libraries/database_interface.lib.php b/libraries/database_interface.lib.php index 50ae58b736..8480d8e918 100644 --- a/libraries/database_interface.lib.php +++ b/libraries/database_interface.lib.php @@ -1373,7 +1373,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) . "';"; } @@ -1392,12 +1392,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 @@ -1408,6 +1411,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); } diff --git a/libraries/rte/rte_events.lib.php b/libraries/rte/rte_events.lib.php index 3782a5c0af..b7be281b48 100644 --- a/libraries/rte/rte_events.lib.php +++ b/libraries/rte/rte_events.lib.php @@ -23,8 +23,8 @@ function PMA_EVN_main() $items = PMA_DBI_fetch_result("SELECT $columns FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE $where;"); $cols = array(array('label' => __('Name'), 'colspan' => 1, 'field' => 'name'), array('label' => __('Action'), 'colspan' => 3, 'field' => 'edit'), - array( 'colspan' => 1, 'field' => 'export'), - array( 'colspan' => 1, 'field' => 'drop'), + array( 'field' => 'export'), + array( 'field' => 'drop'), array('label' => __('Type'), 'colspan' => 1, 'field' => 'type')); $header_arr = array('title' => __('Events'), 'docu' => 'EVENTS', diff --git a/libraries/rte/rte_footer.lib.php b/libraries/rte/rte_footer.lib.php index 9fa5bf8055..9f3c152423 100644 --- a/libraries/rte/rte_footer.lib.php +++ b/libraries/rte/rte_footer.lib.php @@ -28,7 +28,7 @@ function PMA_RTE_getFooterLinks($docu, $priv, $name) if (PMA_currentUserHasPrivilege($priv, $db)) { $retval .= " "; + $retval .= "?$url_query&add_item=1'>"; $retval .= PMA_getIcon('b_' . strtolower($name) . '_add.png'); $retval .= sprintf(__('Add %s'), $human_name) . "\n"; } else { diff --git a/libraries/rte/rte_list.lib.php b/libraries/rte/rte_list.lib.php index 4b68c80260..fffd2a447f 100644 --- a/libraries/rte/rte_list.lib.php +++ b/libraries/rte/rte_list.lib.php @@ -126,8 +126,8 @@ function PMA_RTN_getCellForList($field, $routine) && PMA_currentUserHasPrivilege('ALTER ROUTINE', $db) && PMA_currentUserHasPrivilege('CREATE ROUTINE', $db)) { $retval = '' . $titles['Edit'] . ''; } break; @@ -136,7 +136,7 @@ function PMA_RTN_getCellForList($field, $routine) // 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_getRoutineDataFromName($db, $routine['SPECIFIC_NAME'], false); + $routine_details = PMA_RTN_getRoutineDataFromName($routine['SPECIFIC_NAME'], false); if ($routine !== false) { $execute_action = 'execute_routine'; for ($i=0; $i<$routine_details['num_params']; $i++) { @@ -148,7 +148,7 @@ function PMA_RTN_getCellForList($field, $routine) } $retval = '' . $titles['Execute'] . ''; } } @@ -190,7 +190,7 @@ function PMA_RTN_getCellForList($field, $routine) */ function PMA_TRI_getCellForList($field, $trigger) { - global $ajax_class, $url_query, $db, $titles; + global $ajax_class, $url_query, $db, $table, $titles; switch ($field) { case 'name': @@ -203,6 +203,12 @@ function PMA_TRI_getCellForList($field, $trigger) break; case 'edit': $retval = $titles['NoEdit']; + if (PMA_currentUserHasPrivilege('TRIGGER', $db, $table)) { + $retval = '' . $titles['Edit'] . ''; + } break; case 'export': $retval = '' + $errors[] = sprintf(__('The following query has failed: "%s"'), $drop_routine) . '
' . __('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) . '
' + $errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '
' . __('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 @@ -378,13 +371,13 @@ function PMA_RTN_handleEditor() // 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.') . '
' + $errors[] = __('Sorry, we failed to restore the dropped routine.') . '
' . __('The backed up query was:') . "\"$create_routine\"" . '
' . __('MySQL said: ') . PMA_DBI_getError(null); } } else { $message = PMA_Message::success(__('Routine %1$s has been modified.')); - $message->addParam(PMA_backquote($_REQUEST['routine_name'])); + $message->addParam(PMA_backquote($_REQUEST['item_name'])); $sql_query = $drop_routine . $routine_query; } } @@ -393,20 +386,20 @@ function PMA_RTN_handleEditor() // '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) . '

' + $errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '

' . __('MySQL said: ') . PMA_DBI_getError(null); } else { $message = PMA_Message::success(__('Routine %1$s has been created.')); - $message->addParam(PMA_backquote($_REQUEST['routine_name'])); + $message->addParam(PMA_backquote($_REQUEST['item_name'])); $sql_query = $routine_query; } } } - if (count($routine_errors)) { + if (count($errors)) { $message = PMA_Message::error(__('One or more errors have occured while processing your request:')); $message->addString(''); @@ -417,9 +410,9 @@ function PMA_RTN_handleEditor() $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']) . "'"; + $where = "ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' AND ROUTINE_NAME='" . PMA_sqlAddSlashes($_REQUEST['item_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['name'] = htmlspecialchars(strtoupper($_REQUEST['item_name'])); $extra_data['new_row'] = PMA_RTE_getRowForList('routine', $routine, 0); $response = $output; } else { @@ -432,8 +425,8 @@ function PMA_RTN_handleEditor() /** * 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']) + if (count($errors) || ( empty($_REQUEST['editor_process_add']) && empty($_REQUEST['editor_process_edit']) && + (! empty($_REQUEST['add_item']) || ! empty($_REQUEST['edit_item']) || ! 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 @@ -447,14 +440,14 @@ function PMA_RTN_handleEditor() $operation = 'change'; } // Get the data for the form (if any) - if (! empty($_REQUEST['addroutine'])) { + if (! empty($_REQUEST['add_item'])) { $title = __("Create routine"); $routine = PMA_RTN_getRoutineDataFromRequest(); $mode = 'add'; - } else if (! empty($_REQUEST['editroutine'])) { + } else if (! empty($_REQUEST['edit_item'])) { $title = __("Edit routine"); - if (! $operation && ! empty($_REQUEST['routine_name']) && empty($_REQUEST['routine_process_editroutine'])) { - $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name']); + if (! $operation && ! empty($_REQUEST['item_name']) && empty($_REQUEST['editor_process_edit'])) { + $routine = PMA_RTN_getRoutineDataFromName($_REQUEST['item_name']); if ($routine !== false) { $routine['original_name'] = $routine['name']; $routine['original_type'] = $routine['type']; @@ -466,10 +459,13 @@ function PMA_RTN_handleEditor() } if ($routine !== false) { // Show form - $editor = PMA_RTN_getEditorForm($mode, $operation, $routine, $routine_errors, $GLOBALS['is_ajax_request']); + $editor = PMA_RTN_getEditorForm($mode, $operation, $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']); + $extra_data = array('title' => $title, + 'editor' => 'routine', + 'param_template' => $template, + 'type' => $routine['type']); PMA_ajaxResponse($editor, true, $extra_data); } echo "\n\n

$title

\n\n$editor"; @@ -478,7 +474,7 @@ function PMA_RTN_handleEditor() } 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($_REQUEST['item_name'])), htmlspecialchars(PMA_backquote($db))); $message = PMA_message::error($message); if ($GLOBALS['is_ajax_request']) { @@ -504,8 +500,8 @@ function PMA_RTN_getRoutineDataFromRequest() $retval = array(); $retval['name'] = ''; - if (isset($_REQUEST['routine_name'])) { - $retval['name'] = $_REQUEST['routine_name']; + if (isset($_REQUEST['item_name'])) { + $retval['name'] = $_REQUEST['item_name']; } $retval['original_name'] = ''; if (isset($_REQUEST['routine_original_name'])) { @@ -617,8 +613,8 @@ function PMA_RTN_getRoutineDataFromRequest() $retval['returnopts_text'] = $_REQUEST['routine_returnopts_text']; } $retval['definition'] = ''; - if (isset($_REQUEST['routine_definition'])) { - $retval['definition'] = $_REQUEST['routine_definition']; + if (isset($_REQUEST['item_definition'])) { + $retval['definition'] = $_REQUEST['item_definition']; } $retval['isdeterministic'] = ''; if (isset($_REQUEST['routine_isdeterministic']) && strtolower($_REQUEST['routine_isdeterministic']) == 'on') { @@ -657,7 +653,7 @@ function PMA_RTN_getRoutineDataFromRequest() * */ function PMA_RTN_getQueryFromRequest() { - global $_REQUEST, $cfg, $routine_errors, $param_sqldataaccess; + global $_REQUEST, $cfg, $errors, $param_sqldataaccess; $query = 'CREATE '; if (! empty($_REQUEST['routine_definer']) && strpos($_REQUEST['routine_definer'], '@') !== false) { @@ -667,12 +663,12 @@ function PMA_RTN_getQueryFromRequest() { if ($_REQUEST['routine_type'] == 'FUNCTION' || $_REQUEST['routine_type'] == 'PROCEDURE') { $query .= $_REQUEST['routine_type'] . ' '; } else { - $routine_errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_type'])); + $errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_type'])); } - if (! empty($_REQUEST['routine_name'])) { - $query .= PMA_backquote($_REQUEST['routine_name']) . ' '; + if (! empty($_REQUEST['item_name'])) { + $query .= PMA_backquote($_REQUEST['item_name']) . ' '; } else { - $routine_errors[] = __('You must provide a routine name'); + $errors[] = __('You must provide a routine name'); } $params = ''; $warned_about_dir = false; @@ -691,7 +687,7 @@ function PMA_RTN_getQueryFromRequest() { $params .= PMA_backquote($_REQUEST['routine_param_name'][$i]) . " " . $_REQUEST['routine_param_type'][$i]; } else if (! $warned_about_dir) { $warned_about_dir = true; - $routine_errors[] = sprintf(__('Invalid direction "%s" given for parameter.'), + $errors[] = sprintf(__('Invalid direction "%s" given for parameter.'), htmlspecialchars($_REQUEST['routine_param_dir'][$i])); } if ($_REQUEST['routine_param_length'][$i] != '' @@ -702,7 +698,7 @@ function PMA_RTN_getQueryFromRequest() { && preg_match('@^(ENUM|SET|VARCHAR|VARBINARY)$@i', $_REQUEST['routine_param_type'][$i])) { if (! $warned_about_length) { $warned_about_length = true; - $routine_errors[] = __('You must provide length/values for routine ' + $errors[] = __('You must provide length/values for routine ' . 'parameters of type ENUM, SET, VARCHAR and VARBINARY.'); } } @@ -727,7 +723,7 @@ function PMA_RTN_getQueryFromRequest() { } } else if (! $warned_about_name) { $warned_about_name = true; - $routine_errors[] = __('You must provide a name and a type for each routine parameter.'); + $errors[] = __('You must provide a name and a type for each routine parameter.'); break; } } @@ -743,7 +739,7 @@ function PMA_RTN_getQueryFromRequest() { && preg_match('@^(ENUM|SET|VARCHAR|VARBINARY)$@i', $_REQUEST['routine_returntype'])) { if (! $warned_about_length) { $warned_about_length = true; - $routine_errors[] = __('You must provide length/values for routine ' + $errors[] = __('You must provide length/values for routine ' . 'parameters of type ENUM, SET, VARCHAR and VARBINARY.'); } } @@ -781,10 +777,10 @@ function PMA_RTN_getQueryFromRequest() { $query .= 'SQL SECURITY ' . $_REQUEST['routine_securitytype'] . ' '; } } - if (! empty($_REQUEST['routine_definition'])) { - $query .= $_REQUEST['routine_definition']; + if (! empty($_REQUEST['item_definition'])) { + $query .= $_REQUEST['item_definition']; } else { - $routine_errors[] = __('You must provide a routine definition.'); + $errors[] = __('You must provide a routine definition.'); } return $query; } // end PMA_RTN_getQueryFromRequest() @@ -967,7 +963,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine, $errors, $is_ajax) { $retval = ""; $retval .= "\n\n"; $retval .= "
\n"; - $retval .= "\n"; + $retval .= "\n"; $retval .= $original_routine; $retval .= PMA_generate_common_hidden_inputs($db) . "\n"; $retval .= "
\n"; @@ -975,7 +971,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine, $errors, $is_ajax) { $retval .= "\n"; $retval .= "\n"; $retval .= " \n"; - $retval .= " \n"; + $retval .= " \n"; $retval .= "\n"; $retval .= "\n"; $retval .= " \n"; @@ -1058,7 +1054,7 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine, $errors, $is_ajax) { $retval .= "\n"; $retval .= "\n"; $retval .= " \n"; - $retval .= " \n"; + $retval .= " \n"; $retval .= "\n"; $retval .= "\n"; $retval .= " \n"; @@ -1096,11 +1092,11 @@ function PMA_RTN_getEditorForm($mode, $operation, $routine, $errors, $is_ajax) { $retval .= "
" . __('Routine name') . "
" . __('Type') . "
" . __('Definition') . "
" . __('Is deterministic') . "
\n"; $retval .= "
\n"; if ($is_ajax) { - $retval .= "\n"; + $retval .= "\n"; $retval .= "\n"; } else { - $retval .= "
\n"; - $retval .= " \n"; $retval .= "
\n"; } @@ -1117,9 +1113,9 @@ function PMA_RTN_handleExecute() /** * Handle all user requests other than the default of listing routines */ - if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['routine_name'])) { + if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['item_name'])) { // Build the queries - $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name'], false); + $routine = PMA_RTN_getRoutineDataFromName($_REQUEST['item_name'], false); if ($routine !== false) { $queries = array(); $end_query = array(); @@ -1240,7 +1236,7 @@ function PMA_RTN_handleExecute() } 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($_REQUEST['item_name'])), htmlspecialchars(PMA_backquote($db))); $message = PMA_message::error($message); if ($GLOBALS['is_ajax_request']) { @@ -1250,18 +1246,18 @@ function PMA_RTN_handleExecute() unset($_POST); } } - } else if (! empty($_GET['execute_dialog']) && ! empty($_GET['routine_name'])) { + } else if (! empty($_GET['execute_dialog']) && ! empty($_GET['item_name'])) { /** * Display the execute form for a routine. */ - $routine = PMA_RTN_getRoutineDataFromName($db, $_GET['routine_name'], false); + $routine = PMA_RTN_getRoutineDataFromName($_GET['item_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)); + $extra_data['title'] .= PMA_backquote(htmlentities($_GET['item_name'], ENT_QUOTES)); PMA_ajaxResponse($form, true, $extra_data); } else { echo "\n\n

" . __("Execute routine") . "

\n\n"; @@ -1272,7 +1268,7 @@ function PMA_RTN_handleExecute() } 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($_REQUEST['item_name'])), htmlspecialchars(PMA_backquote($db))); $message = PMA_message::error($message); PMA_ajaxResponse($message, false); @@ -1304,7 +1300,7 @@ function PMA_RTN_getExecuteForm($routine, $is_ajax) $retval = ""; $retval .= "\n\n"; $retval .= "\n"; - $retval .= "\n"; + $retval .= "\n"; $retval .= PMA_generate_common_hidden_inputs($db) . "\n"; $retval .= "
\n"; if ($is_ajax != true) { diff --git a/libraries/rte/rte_triggers.lib.php b/libraries/rte/rte_triggers.lib.php index abb9c2c06d..f20d95d976 100644 --- a/libraries/rte/rte_triggers.lib.php +++ b/libraries/rte/rte_triggers.lib.php @@ -22,8 +22,8 @@ function PMA_TRI_main() $cols = array(array('label' => __('Name'), 'colspan' => 1, 'field' => 'name'), array('label' => __('Table'), 'colspan' => 1, 'field' => 'table'), array('label' => __('Action'), 'colspan' => 3, 'field' => 'edit'), - array( 'colspan' => 1, 'field' => 'export'), - array( 'colspan' => 1, 'field' => 'drop'), + array( 'field' => 'export'), + array( 'field' => 'drop'), array('label' => __('Time'), 'colspan' => 1, 'field' => 'time'), array('label' => __('Event'), 'colspan' => 1, 'field' => 'event')); $header_arr = array('title' => __('Triggers'), @@ -37,10 +37,12 @@ function PMA_TRI_main() /** * Process all requests */ + PMA_TRI_handleEditor(); PMA_TRI_handleExport(); /** * Display a list of available triggers */ + $items = PMA_DBI_get_triggers($db, $table); // refresh list echo PMA_RTE_getList('trigger', $items); /** * Display a link for adding a new trigger, @@ -49,4 +51,330 @@ function PMA_TRI_main() echo PMA_TRI_getFooterLinks(); } // end PMA_TRI_main() +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) . '
' + . __('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) . '
' + . __('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.') . '
' + . __('The backed up query was:') . "\"$create_item\"" . '
' + . __('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) . '

' + . __('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(__('One or more errors have occured while processing your request:')); + $message->addString('
    '); + foreach ($errors as $num => $string) { + $message->addString('
  • ' . $string . '
  • '); + } + $message->addString('
'); + } + + $output = PMA_showMessage($message, $sql_query); + if ($GLOBALS['is_ajax_request']) { + $extra_data = array(); + if ($message->isSuccess()) { + $triggers = PMA_DBI_get_triggers($db, $table); + foreach ($triggers as $key => $value) { + if ($value['name'] == $_REQUEST['item_name']) { + $trigger = $value; + } + } + $extra_data['name'] = htmlspecialchars(strtoupper($_REQUEST['item_name'])); + $extra_data['new_row'] = PMA_RTE_getRowForList('trigger', $trigger, 0); + $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['original_name'] = $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, + 'editor' => 'trigger'); + PMA_ajaxResponse($editor, true, $extra_data); + } else { + echo "\n\n

$title

\n\n$editor"; + unset($_POST); + require './libraries/footer.inc.php'; + } + // exit; + } else { + $message = __('Error in processing request') . ' : ' + . sprintf(__('No trigger with name %1$s found in database %2$s'), + 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(); + } + } + } +} + +function PMA_TRI_getDataFromRequest() +{ + $retval = array(); + + $retval['name'] = ''; + if (isset($_REQUEST['item_name'])) { + $retval['name'] = $_REQUEST['item_name']; + } + $retval['table'] = ''; + if (isset($_REQUEST['item_table'])) { + $retval['table'] = $_REQUEST['item_table']; + } + $retval['original_name'] = ''; + if (isset($_REQUEST['item_original_name'])) { + $retval['original_name'] = $_REQUEST['item_original_name']; + } + $retval['action_timing'] = ''; + if (isset($_REQUEST['item_timing'])) { + $retval['action_timing'] = $_REQUEST['item_timing']; + } + $retval['event_manipulation'] = ''; + if (isset($_REQUEST['item_event'])) { + $retval['event_manipulation'] = $_REQUEST['item_event']; + } + $retval['definition'] = ''; + if (isset($_REQUEST['item_definition'])) { + $retval['definition'] = $_REQUEST['item_definition']; + } + $retval['definer'] = ''; + if (isset($_REQUEST['item_definer'])) { + $retval['definer'] = $_REQUEST['item_definer']; + } + + return $retval; +} + +function PMA_TRI_getDataFromName($name) +{ + global $db, $table, $_REQUEST; + + $retval = array(); + $items = PMA_DBI_get_triggers($db, $table, ''); + foreach ($items as $key => $value) { + if ($value['name'] == $name) { + $retval = $value; + } + } + if (empty($retval)) { + return false; + } else { + return $retval; + } +} + +function PMA_TRI_getEditorForm($mode, $item) +{ + global $db, $table, $titles, $event_manipulations, $action_timings; + + // Escape special characters + $need_escape = array( + 'original_name', + 'name', + 'definition', + 'definer' + ); + foreach($need_escape as $key => $index) { + $item[$index] = htmlentities($item[$index], ENT_QUOTES); + } + $original_data = ''; + if ($mode == 'edit') { + $original_data = "\n"; + } + + // Create the output + $retval = ""; + $retval .= "\n\n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= $original_data; + $retval .= PMA_generate_common_hidden_inputs($db, $table) . "\n"; + $retval .= "
\n"; + $retval .= "" . __('Details') . "\n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "\n"; + $retval .= "\n"; + $retval .= " \n"; + $retval .= "
" . __('Trigger name') . "
" . __('Table') . "\n"; + $retval .= " \n"; + $retval .= "
" . __('Time') . "
" . __('Event') . "
" . __('Definition') . "
" . __('Definer') . "\n"; + $retval .= "\n"; + } + $retval .= "\n\n"; + $retval .= "\n\n"; + + return $retval; +} + +function PMA_TRI_getQueryFromRequest() { + global $_REQUEST, $cfg, $db, $errors, $action_timings, $event_manipulations; + + $query = 'CREATE '; + if (! empty($_REQUEST['item_definer']) && strpos($_REQUEST['item_definer'], '@') !== false) { + $arr = explode('@', $_REQUEST['item_definer']); + $query .= 'DEFINER=' . PMA_backquote($arr[0]) . '@' . PMA_backquote($arr[1]) . ' '; + } + $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 { + $query .= 'BEFORE '; + } + if (! empty($_REQUEST['item_event']) && in_array($_REQUEST['item_event'], $event_manipulations)) { + $query .= $_REQUEST['item_event'] . ' '; + } else { + $query .= 'INSERT '; + } + $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; +} + ?>