diff --git a/.gitignore b/.gitignore index dda2e0ecd9..6cc231a221 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ phpmyadmin.wpj .buildpath .cache .idea +.netbeans *.sw[op] # Locales /locale/ @@ -31,3 +32,8 @@ phpmyadmin.wpj /apidoc/ # Demo server revision-info.php +# PHPUnit +phpunit.xml +/test/bootstrap.php +# Jenkins +/build/ \ No newline at end of file diff --git a/ChangeLog b/ChangeLog index 4df55e5fd7..dc2f709b0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,6 +34,11 @@ phpMyAdmin - ChangeLog + Show/hide column in table Browse - bug #3353856 [AJAX] AJAX dialogs use wrong font-size - 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 ++ [interface] Improved server monitoring 3.4.4.0 (not yet released) - bug #3323060 [parser] SQL parser breaks AJAX requests if query has unclosed quotes @@ -43,6 +48,12 @@ phpMyAdmin - ChangeLog - bug #3353649 [interface] "Create an index on X columns" form not validated - bug #3350790 [interface] JS error in Table->Structure->Index->Edit - bug #3353811 [interface] Info message has "error" class +- bug #3357837 [interface] TABbing through a NULL field in the inline mode resets NULL +- remove version number in /setup +- bug #3367993 [usability] Missing "Generate Password" button +- bug #3363221 [display] Missing Server Parameter on inline sql query +- bug #3367986 [navi] Drop field -> lost active table +- remove misleading comment on the "Rename database" interface 3.4.3.1 (2011-07-02) - [security] Fixed possible session manipulation in swekey authentication, see PMASA-2011-5 diff --git a/Documentation.html b/Documentation.html index 0b3bd922c5..6a8d5dcd16 100644 --- a/Documentation.html +++ b/Documentation.html @@ -2143,7 +2143,7 @@ setfacl -d -m "g:www-data:rwx" tmp identify what they mean. -
$cfg['ShowDisplayDir'] boolean
+
$cfg['ShowDisplayDirection'] boolean
Defines whether or not type display direction option is shown when browsing a table. diff --git a/bs_disp_as_mime_type.php b/bs_disp_as_mime_type.php index 03a8c8b3ac..9ec0ec5b29 100644 --- a/bs_disp_as_mime_type.php +++ b/bs_disp_as_mime_type.php @@ -13,7 +13,7 @@ require_once './libraries/common.inc.php'; PMA_checkParameters(array('reference', 'c_type')); // Increase time limit, because fetching blob might take some time -set_time_limit(0); +@set_time_limit(0); $reference = $_REQUEST['reference']; /* diff --git a/build.xml b/build.xml new file mode 100644 index 0000000000..ad4dc40597 --- /dev/null +++ b/build.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/changelog.php b/changelog.php index 5c42e6797f..9892638193 100644 --- a/changelog.php +++ b/changelog.php @@ -75,7 +75,7 @@ $replaces = array( => 'bug #\\1', // all other 6+ digit numbers are treated as bugs - '/(? ' bug #\\1', // CVE/CAN entries diff --git a/chart_export.php b/chart_export.php index 87ab3a4615..e3a02f0e0b 100644 --- a/chart_export.php +++ b/chart_export.php @@ -7,17 +7,17 @@ */ -define('PMA_MINIMUM_COMMON',true); +define('PMA_MINIMUM_COMMON', true); require_once './libraries/common.inc.php'; if(isset($_REQUEST['filename']) && isset($_REQUEST['image'])) { $allowed = Array( 'image/png'=>'png', 'image/svg+xml'=>'svg'); - if(!isset($allowed[$_REQUEST['type']])) exit('Invalid export type'); + if(! isset($allowed[$_REQUEST['type']])) exit('Invalid export type'); - if(!preg_match("/(".implode("|",$allowed).")$/i",$_REQUEST['filename'])) - $_REQUEST['filename'].='.'.$allowed[$_REQUEST['type']]; + if(! preg_match("/(".implode("|",$allowed).")$/i", $_REQUEST['filename'])) + $_REQUEST['filename'] .= '.' . $allowed[$_REQUEST['type']]; header("Cache-Control: public"); header("Content-Description: File Transfer"); @@ -25,8 +25,8 @@ if(isset($_REQUEST['filename']) && isset($_REQUEST['image'])) { header("Content-Type: ".$_REQUEST['type']); header("Content-Transfer-Encoding: binary"); - if($allowed[$_REQUEST['type']]!='svg') - echo base64_decode(substr($_REQUEST['image'],strpos($_REQUEST['image'],',')+1)); + if($allowed[$_REQUEST['type']] != 'svg') + echo base64_decode(substr($_REQUEST['image'], strpos($_REQUEST['image'],',') + 1)); else echo $_REQUEST['image']; diff --git a/db_events.php b/db_events.php index 7d22f5d8c5..9991f83fff 100644 --- a/db_events.php +++ b/db_events.php @@ -1,40 +1,36 @@ diff --git a/db_operations.php b/db_operations.php index 190f9b649b..e2d1e2bba5 100644 --- a/db_operations.php +++ b/db_operations.php @@ -77,7 +77,7 @@ if (strlen($db) && (! empty($db_rename) || ! empty($db_copy))) { // the db name $procedure_names = PMA_DBI_get_procedures_or_functions($db, 'PROCEDURE'); if ($procedure_names) { - foreach($procedure_names as $procedure_name) { + foreach ($procedure_names as $procedure_name) { PMA_DBI_select_db($db); $tmp_query = PMA_DBI_get_definition($db, 'PROCEDURE', $procedure_name); // collect for later display @@ -89,7 +89,7 @@ if (strlen($db) && (! empty($db_rename) || ! empty($db_copy))) { $function_names = PMA_DBI_get_procedures_or_functions($db, 'FUNCTION'); if ($function_names) { - foreach($function_names as $function_name) { + foreach ($function_names as $function_name) { PMA_DBI_select_db($db); $tmp_query = PMA_DBI_get_definition($db, 'FUNCTION', $function_name); // collect for later display @@ -234,7 +234,7 @@ if (strlen($db) && (! empty($db_rename) || ! empty($db_copy))) { // the db name $event_names = PMA_DBI_fetch_result('SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \'' . PMA_sqlAddSlashes($db,true) . '\';'); if ($event_names) { - foreach($event_names as $event_name) { + foreach ($event_names as $event_name) { PMA_DBI_select_db($db); $tmp_query = PMA_DBI_get_definition($db, 'EVENT', $event_name); // collect for later display @@ -398,24 +398,12 @@ if ($db != 'mysql') { '; + echo ''; } echo __('Rename database to') . ':'; ?> - = XYYZZ) { - // echo 'RENAME DATABASE'; - //} else { - echo 'INSERT INTO ... SELECT'; - //} - echo ')'; ?>
@@ -434,8 +422,7 @@ if (($is_superuser || $GLOBALS['cfg']['AllowUserDropDatabase']) && ! $db_is_info
'; + echo ''; } echo __('Remove database'); ?> @@ -481,8 +468,7 @@ echo __('Remove database'); '; + echo ''; } echo __('Copy database to') . ':'; $drop_clause = 'DROP TABLE / DROP VIEW'; @@ -546,8 +532,7 @@ echo __('Remove database'); . '
' . "\n" . ' '; if ($cfg['PropertiesIconic']) { - echo ''; + echo ''; } echo ' ' . "\n" . ' ' . "\n" @@ -594,8 +579,7 @@ if ($cfgRelation['pdfwork'] && $num_tables > 0) { ?> */ echo ''; } // end if diff --git a/db_routines.php b/db_routines.php index 422ec767a6..745d1f9287 100644 --- a/db_routines.php +++ b/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,20 @@ 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'; +$GLOBALS['js_include'][] = 'codemirror/lib/codemirror.js'; +$GLOBALS['js_include'][] = 'codemirror/mode/mysql/mysql.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 .= '
'; - $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 = ''; - $output .= PMA_SQP_formatHtml(PMA_SQP_parse(implode($queries))); - $output .= ''; - // Display results - if ($result) { - $output .= "
"; - $output .= sprintf(__('Execution results of routine %s'), - PMA_backquote(htmlspecialchars($routine['name']))); - $output .= ""; - $output .= ""; - foreach (PMA_DBI_get_fields_meta($result) as $key => $field) { - $output .= ""; - } - $output .= ""; - // Stored routines can only ever return ONE ROW. - $data = PMA_DBI_fetch_single_row($result); - foreach ($data as $key => $value) { - if ($value === null) { - $value = 'NULL'; - } else { - $value = htmlspecialchars($value); - } - $output .= ""; - } - $output .= "
" . htmlspecialchars($field->name) . "
" . $value . "
"; - } 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) . '

' - . __('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

" . __("Execute routine") . "

\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 = ''; - 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 '
' . "\n" - . ' ' . sprintf(__('Export of routine %s'), $routine_name) . '' . "\n" - . $create_proc . "\n" - . '
'; - } - } 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) . '
' - . __('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) . '
' - . __('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.') . '
' - . __('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'])); - $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) . '

' - . __('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(__('One or more errors have occured while processing your request:')); - $message->addString('
    '); - foreach ($routine_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()) { - $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

$title

\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. ' - . 'The execution of some stored routines may fail! ' - . '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'; -} +$_PMA_RTE = 'RTN'; +require_once './libraries/rte/rte_main.inc.php'; ?> diff --git a/db_sql.php b/db_sql.php index 26a6299d36..38074e9769 100644 --- a/db_sql.php +++ b/db_sql.php @@ -16,6 +16,8 @@ require_once './libraries/common.inc.php'; $GLOBALS['js_include'][] = 'functions.js'; $GLOBALS['js_include'][] = 'makegrid.js'; $GLOBALS['js_include'][] = 'sql.js'; +$GLOBALS['js_include'][] = 'codemirror/lib/codemirror.js'; +$GLOBALS['js_include'][] = 'codemirror/mode/mysql/mysql.js'; require './libraries/db_common.inc.php'; require_once './libraries/sql_query_form.lib.php'; diff --git a/db_structure.php b/db_structure.php index 0054585bb4..d1ffdc3b77 100644 --- a/db_structure.php +++ b/db_structure.php @@ -13,6 +13,7 @@ require_once './libraries/common.inc.php'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'db_structure.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; +$GLOBALS['js_include'][] = 'jquery/timepicker.js'; /** * Prepares the tables list if the user where not redirected to this script @@ -283,9 +284,9 @@ foreach ($tables as $keyname => $each_table) { $tracking_icon = ''; if (PMA_Tracker::isActive()) { if (PMA_Tracker::isTracked($GLOBALS["db"], $truename)) { - $tracking_icon = '' . __('Tracking is active.') . ''; + $tracking_icon = '' . __('Tracking is active.') . ''; } elseif (PMA_Tracker::getVersion($GLOBALS["db"], $truename) > 0) { - $tracking_icon = '' . __('Tracking is not active.') . ''; + $tracking_icon = '' . __('Tracking is not active.') . ''; } } @@ -340,7 +341,7 @@ foreach ($tables as $keyname => $each_table) { - ' : ''. $do ? ' REPLICATED' : ''; ?> + ' : ''. $do ? ' REPLICATED' : ''; ?> @@ -547,15 +548,13 @@ PMA_listNavigator($total_num_tables, $pos, $_url_params, 'db_structure.php', 'fr echo '

'; echo ''; if ($cfg['PropertiesIconic']) { - echo ''; + echo ''; } echo __('Print view') . ' '; echo ''; if ($cfg['PropertiesIconic']) { - echo ''; + echo ''; } echo __('Data Dictionary') . ''; echo '

'; diff --git a/db_tracking.php b/db_tracking.php index 3a9b6954b7..38a231d4e0 100644 --- a/db_tracking.php +++ b/db_tracking.php @@ -98,7 +98,7 @@ if (PMA_DBI_num_rows($all_tables_result) > 0) { $drop_image_or_text = ''; if (true == $GLOBALS['cfg']['PropertiesIconic']) { - $drop_image_or_text .= '' . __('Delete tracking data for this table') . ''; + $drop_image_or_text .= '' . __('Delete tracking data for this table') . ''; } if ('both' === $GLOBALS['cfg']['PropertiesIconic'] || false === $GLOBALS['cfg']['PropertiesIconic']) { $drop_image_or_text .= __('Drop'); @@ -198,7 +198,7 @@ if (isset($my_tables)) { $my_link = ''; if ($cfg['PropertiesIconic']) { - $my_link .= '' . __('Track table') . ' '; + $my_link .= '' . __('Track table') . ' '; } $my_link .= __('Track table') . ''; ?> diff --git a/db_triggers.php b/db_triggers.php index 416be77c15..4911f36b03 100644 --- a/db_triggers.php +++ b/db_triggers.php @@ -1,38 +1,35 @@ diff --git a/enum_editor.php b/enum_editor.php index ab86d737cb..5fe962fc10 100644 --- a/enum_editor.php +++ b/enum_editor.php @@ -32,7 +32,7 @@ require_once './libraries/header_meta_style.inc.php'; } // Display the values in text fields, excluding empty strings $field_counter = 0; - foreach($values as $value) { + foreach ($values as $value) { if(trim($value) != "") { $field_counter++; echo sprintf('', htmlspecialchars(str_replace(array("''", '\\\\', "\\'"), array("'", '\\', "'"), substr($value, 1, -1)))); diff --git a/export.php b/export.php index 9471ba0c15..f5a985ac75 100644 --- a/export.php +++ b/export.php @@ -125,8 +125,7 @@ $time_start = time(); * Output handler for all exports, if needed buffering, it stores data into * $dump_buffer, otherwise it prints thems out. * - * @param string the insert statement - * + * @param string $line the insert statement * @return bool Whether output suceeded */ function PMA_exportOutputHandler($line) @@ -401,7 +400,7 @@ if (!$save_on_server) { $_REQUEST['table_select'] = implode(",", $_REQUEST['table_select']); } - foreach($_REQUEST as $name => $value) { + foreach ($_REQUEST as $name => $value) { $back_button .= '&' . urlencode($name) . '=' . urlencode($value); } $back_button .= '&repopulate=1">Back ]

'; @@ -493,7 +492,7 @@ if ($export_type == 'server') { } } } - foreach($views as $view) { + foreach ($views as $view) { // no data export for a view if ($GLOBALS[$what . '_structure_or_data'] == 'structure' || $GLOBALS[$what . '_structure_or_data'] == 'structure_and_data') { if (!PMA_exportStructure($current_db, $view, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates, 'create_view', $export_type)) { @@ -512,7 +511,7 @@ if ($export_type == 'server') { } if (function_exists('PMA_exportRoutines') && strpos($GLOBALS['sql_structure_or_data'], 'structure') !== false && isset($GLOBALS['sql_procedure_function'])) { - PMA_exportRoutines($db); + PMA_exportRoutines($db); } $i = 0; diff --git a/import.php b/import.php index afc513ce3c..b9b7d150bc 100644 --- a/import.php +++ b/import.php @@ -264,7 +264,7 @@ if ($import_file != 'none' && !$error) { $file_to_unlink = $import_file_new; } - $size = filesize($import_file); + $size = filesize($import_file); } } diff --git a/js/common.js b/js/common.js index b3e996c022..b595108f83 100644 --- a/js/common.js +++ b/js/common.js @@ -14,78 +14,6 @@ var querywindow = ''; */ var query_to_load = ''; -/** - * attach a function to object event - * - * - * addEvent(window, 'load', PMA_initPage); - * - * @param object or id - * @param string event type (load, mouseover, focus, ...) - * @param function to be attached - */ -function addEvent(obj, type, fn) -{ - if (obj.attachEvent) { - obj['e' + type + fn] = fn; - obj[type + fn] = function() {obj['e' + type + fn](window.event);} - obj.attachEvent('on' + type, obj[type + fn]); - } else { - obj.addEventListener(type, fn, false); - } -} - -/** - * detach/remove a function from an object event - * - * @param object or id - * @param event type (load, mouseover, focus, ...) - * @param function naem of function to be attached - */ -function removeEvent(obj, type, fn) -{ - if (obj.detachEvent) { - obj.detachEvent('on' + type, obj[type + fn]); - obj[type + fn] = null; - } else { - obj.removeEventListener(type, fn, false); - } -} - -/** - * get DOM elements by html class - * - * @param string class_name - name of class - * @param node node - search only sub nodes of this node (optional) - * @param string tag - search only these tags (optional) - */ -function getElementsByClassName(class_name, node, tag) -{ - var classElements = new Array(); - - if (node == null) { - node = document; - } - if (tag == null) { - tag = '*'; - } - - var j = 0, teststr; - var els = node.getElementsByTagName(tag); - var elsLen = els.length; - - for (i = 0; i < elsLen; i++) { - if (els[i].className.indexOf(class_name) != -1) { - teststr = "," + els[i].className.split(" ").join(",") + ","; - if (teststr.indexOf("," + class_name + ",") != -1) { - classElements[j] = els[i]; - j++; - } - } - } - return classElements; -} - /** * sets current selected db * diff --git a/js/db_events.js b/js/db_events.js deleted file mode 100644 index 3a0ccd5650..0000000000 --- a/js/db_events.js +++ /dev/null @@ -1,2 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ - diff --git a/js/db_routines.js b/js/db_routines.js deleted file mode 100644 index ceb09626dd..0000000000 --- a/js/db_routines.js +++ /dev/null @@ -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 = $('
'+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 - 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 = $('
'+data.message+'
').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 diff --git a/js/db_search.js b/js/db_search.js index 0cb04b7f28..72b30463d4 100644 --- a/js/db_search.js +++ b/js/db_search.js @@ -87,7 +87,7 @@ $(document).ready(function() { }); /** Hide the table link in the initial search result */ - $("#table-info").prepend('').hide(); + $("#table-info").prepend('').hide(); /** Hide the browse and deleted results in the new search criteria */ $('#buttonGo').click(function(){ diff --git a/js/db_structure.js b/js/db_structure.js index ad55341b60..efc8f2ad2d 100644 --- a/js/db_structure.js +++ b/js/db_structure.js @@ -57,16 +57,19 @@ $(document).ready(function() { * @uses PMA_ajaxShowMessage() * @see $cfg['AjaxEnable'] */ - var currrent_insert_table; + var current_insert_table; $("td.insert_table a.ajax").live('click', function(event){ event.preventDefault(); - currrent_insert_table = $(this); - var url = $(this).attr("href"); - if (url.substring(0, 15) == "tbl_change.php?") { - url = url.substring(15); + current_insert_table = $(this); + var $url = $(this).attr("href"); + if ($url.substring(0, 15) == "tbl_change.php?") { + $url = $url.substring(15); } - var div = $('
'); + if ($("#insert_table_dialog").length > 0) { + $("#insert_table_dialog").remove(); + } + var $div = $('
'); var target = "tbl_change.php"; /** @@ -75,40 +78,47 @@ $(document).ready(function() { */ var button_options = {}; // in the following function we need to use $(this) - button_options[PMA_messages['strCancel']] = function() {$(this).parent().dialog('close').remove();} + button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} var button_options_error = {}; - button_options_error[PMA_messages['strOK']] = function() {$(this).parent().dialog('close').remove();} + button_options_error[PMA_messages['strOK']] = function() {$(this).dialog('close').remove();} var $msgbox = PMA_ajaxShowMessage(); - $.get( target , url+"&ajax_request=true" , function(data) { + $.get( target , $url+"&ajax_request=true" , function(data) { //in the case of an error, show the error message returned. if (data.success != undefined && data.success == false) { - div + $div .append(data.error) .dialog({ title: PMA_messages['strInsertTable'], height: 230, width: 900, + modal: true, open: PMA_verifyTypeOfAllColumns, buttons : button_options_error })// end dialog options } else { - div - .append(data) - .dialog({ - title: PMA_messages['strInsertTable'], - height: 600, - width: 900, - open: PMA_verifyTypeOfAllColumns, - buttons : button_options - }) + var $dialog = $div + .append(data) + .dialog({ + title: PMA_messages['strInsertTable'], + height: 600, + width: 900, + modal: true, + open: PMA_verifyTypeOfAllColumns, + buttons : button_options + });// end dialog options //Remove the top menu container from the dialog - .find("#topmenucontainer").hide() - ; // end dialog options + $dialog.find("#topmenucontainer").hide(); + //Adding the datetime pikers for the dialog + $dialog.find('.datefield, .datetimefield').each(function () { + PMA_addDatepicker($(this)); + }); $(".insertRowTable").addClass("ajax"); $("#buttonYes").addClass("ajax"); + $div = $("#insert_table_dialog"); + PMA_convertFootnotesToTooltips($div); } PMA_ajaxRemoveMessage($msgbox); }) // end $.get() @@ -134,7 +144,7 @@ $(document).ready(function() { $("#insert_table_dialog").dialog("close").remove(); } /**Update the row count at the tableForm*/ - currrent_insert_table.closest('tr').find('.value.tbl_rows').html(data.row_count); + current_insert_table.closest('tr').find('.value.tbl_rows').html(data.row_count); }) // end $.post() }) // end insert table button "Go" @@ -160,7 +170,7 @@ $(document).ready(function() { } if (selected_after_insert == "new_insert") { /**Trigger the insert dialog for new_insert option*/ - currrent_insert_table.trigger('click'); + current_insert_table.trigger('click'); } } else { @@ -170,7 +180,7 @@ $(document).ready(function() { $("#insert_table_dialog").dialog("close").remove(); } /**Update the row count at the tableForm*/ - currrent_insert_table.closest('tr').find('.value.tbl_rows').html(data.row_count); + current_insert_table.closest('tr').find('.value.tbl_rows').html(data.row_count); }) // end $.post() }); @@ -208,7 +218,7 @@ $(document).ready(function() { PMA_ajaxShowMessage(data.message); //Fetch inner span of this anchor //and replace the icon with its disabled version - var span = $this_anchor.html().replace(/b_empty.png/, 'bd_empty.png'); + var span = $this_anchor.html().replace(/ic_b_empty/, 'ic_bd_empty'); PMA_adjustTotals($this_anchor); //To disable further attempts to truncate the table, diff --git a/js/display_triggers.js b/js/display_triggers.js deleted file mode 100644 index 3a0ccd5650..0000000000 --- a/js/display_triggers.js +++ /dev/null @@ -1,2 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ - diff --git a/js/functions.js b/js/functions.js index 8d841cf524..0401f5d195 100644 --- a/js/functions.js +++ b/js/functions.js @@ -135,14 +135,13 @@ function displayPasswordGenerateButton() { * * @param object $this_element a jQuery object pointing to the element */ -function PMA_addDatepicker($this_element) { +function PMA_addDatepicker($this_element, options) { var showTimeOption = false; if ($this_element.is('.datetimefield')) { showTimeOption = true; } - - $this_element - .datepicker({ + + var defaultOptions = { showOn: 'button', buttonImage: themeCalendarImage, // defined in js/messages.php buttonImageOnly: true, @@ -157,9 +156,16 @@ function PMA_addDatepicker($this_element) { // Remember that we came from the datepicker; this is used // in tbl_change.js by verificationsAfterFieldChange() $this_element.data('comes_from', 'datepicker'); + + // Fix wrong timepicker z-index, doesn't work without timeout + setTimeout(function() { + $('#ui-timepicker-div').css('z-index',$('#ui-datepicker-div').css('z-index')) + },0); }, constrainInput: false - }); + }; + + $this_element.datepicker($.extend(defaultOptions, options)); } /** @@ -723,13 +729,13 @@ var last_shift_clicked_row = -1; * Row highlighting in horizontal mode (use "live" * so that it works also for pages reached via AJAX) */ -$(document).ready(function() { +/*$(document).ready(function() { $('tr.odd, tr.even').live('hover',function(event) { var $tr = $(this); $tr.toggleClass('hover',event.type=='mouseover'); $tr.children().toggleClass('hover',event.type=='mouseover'); }); -}) +})*/ /** * This array is used to remember mark status of rows in browse mode @@ -1217,6 +1223,7 @@ function changeMIMEType(db, table, reference, mime_type) */ $(document).ready(function(){ $(".inline_edit_sql").live('click', function(){ + var server = $(this).prev().find("input[name='server']").val(); var db = $(this).prev().find("input[name='db']").val(); var table = $(this).prev().find("input[name='table']").val(); var token = $(this).prev().find("input[name='token']").val(); @@ -1232,7 +1239,8 @@ $(document).ready(function(){ $(this).click(function(){ sql_query = $(this).prev().val(); window.location.replace("import.php" - + "?db=" + encodeURIComponent(db) + + "?server=" + encodeURIComponent(server) + + "&db=" + encodeURIComponent(db) + "&table=" + encodeURIComponent(table) + "&sql_query=" + encodeURIComponent(sql_query) + "&show_query=1" @@ -1459,20 +1467,26 @@ function PMA_createChart(passedSettings) { chart: { type: 'spline', marginRight: 10, + backgroundColor: 'transparent', events: { + /* Live charting support */ load: function() { var thisChart = this; var lastValue = null, curValue = null; var numLoadedPoints = 0, otherSum = 0; var diff; - // No realtime updates for graphs that are being exported, and disabled when no callback is set + + // No realtime updates for graphs that are being exported, and disabled when realtime is not set + // Also don't do live charting if we don't have the server time if(thisChart.options.chart.forExport == true || - ! passedSettings.realtime || - ! passedSettings.realtime.callback) return; + ! thisChart.options.realtime || + ! thisChart.options.realtime.callback || + ! server_time_diff) return; thisChart.options.realtime.timeoutCallBack = function() { - $.post(passedSettings.realtime.url, - { ajax_request: true, chart_data: 1, type: passedSettings.realtime.type }, + thisChart.options.realtime.postRequest = $.post( + thisChart.options.realtime.url, + thisChart.options.realtime.postData, function(data) { curValue = jQuery.parseJSON(data); @@ -1485,13 +1499,13 @@ function PMA_createChart(passedSettings) { false ); - passedSettings.realtime.callback(thisChart,curValue,lastValue,numLoadedPoints); + thisChart.options.realtime.callback(thisChart,curValue,lastValue,numLoadedPoints); lastValue = curValue; numLoadedPoints++; // Timeout has been cleared => don't start a new timeout - if(chart_activeTimeouts[container]==null) return; + if(chart_activeTimeouts[container] == null) return; chart_activeTimeouts[container] = setTimeout( thisChart.options.realtime.timeoutCallBack, @@ -1500,7 +1514,7 @@ function PMA_createChart(passedSettings) { }); } - chart_activeTimeouts[container] = setTimeout(thisChart.options.realtime.timeoutCallBack, 0); + chart_activeTimeouts[container] = setTimeout(thisChart.options.realtime.timeoutCallBack, 5); } } }, @@ -1542,15 +1556,20 @@ function PMA_createChart(passedSettings) { } /* Set/Get realtime chart default values */ - if(passedSettings.realtime) { + if(passedSettings.realtime) { if(!passedSettings.realtime.refreshRate) passedSettings.realtime.refreshRate = 5000; if(!passedSettings.realtime.numMaxPoints) passedSettings.realtime.numMaxPoints = 30; - settings.xAxis.min = new Date().getTime() - passedSettings.realtime.numMaxPoints * passedSettings.realtime.refreshRate; - settings.xAxis.max = new Date().getTime() + passedSettings.realtime.refreshRate / 4; + // Allow custom POST vars to be added + passedSettings.realtime.postData = $.extend(false,{ ajax_request: true, chart_data: 1, type: passedSettings.realtime.type },passedSettings.realtime.postData); + + if(server_time_diff) { + settings.xAxis.min = new Date().getTime() - server_time_diff - passedSettings.realtime.numMaxPoints * passedSettings.realtime.refreshRate; + settings.xAxis.max = new Date().getTime() - server_time_diff + passedSettings.realtime.refreshRate; + } } // Overwrite/Merge default settings with passedsettings @@ -1816,6 +1835,76 @@ $(document).ready(function() { }, 'top.frame_content'); //end $(document).ready for 'Create Table' +/** + * jQuery coding for 'Change Table'. Used on tbl_structure.php * + * Attach Ajax Event handlers for Change Table + */ +$(document).ready(function() { + /** + *Ajax action for submitting the column change form + **/ + $("#append_fields_form input[name=do_save_data]").live('click', function(event) { + event.preventDefault(); + /** + * @var the_form object referring to the export form + */ + var $form = $("#append_fields_form"); + + /* + * First validate the form; if there is a problem, avoid submitting it + * + * checkTableEditForm() needs a pure element and not a jQuery object, + * this is why we pass $form[0] as a parameter (the jQuery object + * is actually an array of DOM elements) + */ + if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) { + // OK, form passed validation step + if ($form.hasClass('ajax')) { + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize()+"&do_save_data=Save", function(data) { + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } else if ($(".error").length != 0) { + $(".error").remove(); + } + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + $("
").insertAfter("#topmenucontainer"); + $("#sqlqueryresults").html(data.sql_query); + $("#result_query .notice").remove(); + $("#result_query").prepend((data.message)); + if ($("#change_column_dialog").length > 0) { + $("#change_column_dialog").dialog("close").remove(); + } + /*Reload the field form*/ + $.post($("#fieldsForm").attr('action'), $("#fieldsForm").serialize()+"&ajax_request=true", function(form_data) { + $("#fieldsForm").remove(); + var $temp_div = $("
").append(form_data); + if ($("#sqlqueryresults").length != 0) { + $temp_div.find("#fieldsForm").insertAfter("#sqlqueryresults"); + } else { + $temp_div.find("#fieldsForm").insertAfter(".error"); + } + /*Call the function to display the more options in table*/ + displayMoreTableOpts(); + }); + } else { + var $temp_div = $("
").append(data); + var $error = $temp_div.find(".error code").addClass("error"); + PMA_ajaxShowMessage($error); + } + }) // end $.post() + } else { + // non-Ajax submit + $form.append(''); + $form.submit(); + } + } + }) // end change table button "do_save_data" + +}, 'top.frame_content'); //end $(document).ready for 'Change Table' + /** * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js * as it was also required on db_create.php @@ -2152,29 +2241,93 @@ function displayMoreTableOpts() { } }); } -} -$(document).ready(initTooltips); -/* Displays tooltips */ -function initTooltips() { +} +$(document).ready(function(){ + PMA_convertFootnotesToTooltips(); +}); + +/** + * Ensures indexes names are valid according to their type and, for a primary + * key, lock index name to 'PRIMARY' + * @param string form_id Variable which parses the form name as + * the input + * @return boolean false if there is no index form, true else + */ +function checkIndexName(form_id) +{ + if ($("#"+form_id).length == 0) { + return false; + } + + // Gets the elements pointers + var $the_idx_name = $("#input_index_name"); + var $the_idx_type = $("#select_index_type"); + + // Index is a primary key + if ($the_idx_type.find("option:selected").attr("value") == 'PRIMARY') { + $the_idx_name.attr("value", 'PRIMARY'); + $the_idx_name.attr("disabled", true); + } + + // Other cases + else { + if ($the_idx_name.attr("value") == 'PRIMARY') { + $the_idx_name.attr("value", ''); + } + $the_idx_name.attr("disabled", false); + } + + return true; +} // end of the 'checkIndexName()' function + +/** + * function to convert the footnotes to tooltips + * + * @param jquery-Object $div a div jquery object which specifies the + * domain for searching footnootes. If we + * ommit this parameter the function searches + * the footnotes in the whole body + **/ +function PMA_convertFootnotesToTooltips($div) { // Hide the footnotes from the footer (which are displayed for // JavaScript-disabled browsers) since the tooltip is sufficient - $(".footnotes").hide(); - $(".footnotes span").each(function() { + + if ($div == undefined || ! $div instanceof jQuery || $div.length == 0) { + $div = $("#serverinfo").parent(); + } + + $footnotes = $div.find(".footnotes"); + + $footnotes.hide(); + $footnotes.find('span').each(function() { $(this).children("sup").remove(); }); // The border and padding must be removed otherwise a thin yellow box remains visible - $(".footnotes").css("border", "none"); - $(".footnotes").css("padding", "0px"); + $footnotes.css("border", "none"); + $footnotes.css("padding", "0px"); // Replace the superscripts with the help icon - $("sup[class='footnotemarker']").hide(); - $("img[class='footnotemarker']").show(); + $div.find("sup.footnotemarker").hide(); + $div.find("img.footnotemarker").show(); - $("img[class='footnotemarker']").each(function() { - var span_id = $(this).attr("id"); - span_id = span_id.split("_")[1]; - var tooltip_text = $(".footnotes span[id='footnote_" + span_id + "']").html(); + $div.find("img.footnotemarker").each(function() { + var img_class = $(this).attr("class"); + /** img contains two classes, as example "footnotemarker footnote_1". + * We split it by second class and take it for the id of span + */ + img_class = img_class.split(" "); + for (i = 0; i < img_class.length; i++) { + if (img_class[i].split("_")[0] == "footnote") { + var span_id = img_class[i].split("_")[1]; + } + } + /** + * Now we get the #id of the span with span_id variable. As an example if we + * initially get the img class as "footnotemarker footnote_2", now we get + * #2 as the span_id. Using that we can find footnote_2 in footnotes. + * */ + var tooltip_text = $footnotes.find("span[id='footnote_" + span_id + "']").html(); $(this).qtip({ content: tooltip_text, show: { delay: 0 }, @@ -2257,7 +2410,7 @@ $(function() { }); var img = topmenu.find('li:first-child img'); if (img.length) { - img.clone().attr('src', img.attr('src').replace(/\/[^\/]+$/, '/b_more.png')).prependTo(link); + img.clone().attr('class', 'icon ic_b_more').prependTo(link); } var submenu = $('
  • ', {'class': 'submenu'}) .append(link) @@ -2319,6 +2472,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 */ @@ -2326,10 +2609,10 @@ $(document).ready(function() { $('.vpointer').live('hover', //handlerInOut function(e) { - var $this_td = $(this); - var row_num = PMA_getRowNumber($this_td.attr('class')); - // for all td of the same vertical row, toggle hover - $('.vpointer').filter('.row_' + row_num).toggleClass('hover'); + var $this_td = $(this); + var row_num = PMA_getRowNumber($this_td.attr('class')); + // for all td of the same vertical row, toggle hover + $('.vpointer').filter('.row_' + row_num).toggleClass('hover'); } ); }) // end of $(document).ready() for vertical pointer @@ -2339,11 +2622,35 @@ $(document).ready(function() { * Vertical marker */ $('.vmarker').live('click', function(e) { + // do not trigger when clicked on anchor + if ($(e.target).is('a, img, a *')) { + return; + } + var $this_td = $(this); var row_num = PMA_getRowNumber($this_td.attr('class')); - // for all td of the same vertical row, toggle the marked class - $('.vmarker').filter('.row_' + row_num).toggleClass('marked'); - }); + + // XXX: FF fires two click events for