Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Cheng <c4150221@gmail.com>2014-06-16 18:18:44 +0400
committerEdward Cheng <c4150221@gmail.com>2014-06-25 17:22:33 +0400
commitfb14e92d62a1d9990bfd4d779702688e873ce60f (patch)
treed7118c327f7a11eadab401183d88a68d37e423a5
parentf0d794613d1dc23f5bb1cddecfb65f8da96f96cb (diff)
PMA console, history and bookmarks.
Modified: resizer of navigation bar: whole-time-bind events removed. Signed-off-by: Edward Cheng <c4150221@gmail.com>
-rw-r--r--browse_foreigners.php2
-rw-r--r--import.php15
-rw-r--r--js/ajax.js4
-rw-r--r--js/console.js724
-rw-r--r--js/messages.php2
-rw-r--r--js/navigation.js38
-rw-r--r--js/sql.js3
-rw-r--r--libraries/Console.class.php265
-rw-r--r--libraries/Header.class.php16
-rw-r--r--libraries/bookmark.lib.php102
-rw-r--r--libraries/plugins/auth/AuthenticationConfig.class.php2
-rw-r--r--libraries/plugins/auth/AuthenticationCookie.class.php2
-rw-r--r--libraries/plugins/auth/AuthenticationHttp.class.php2
-rw-r--r--libraries/relation.lib.php14
-rw-r--r--querywindow.php2
-rw-r--r--test/classes/PMA_Header_test.php1
-rw-r--r--test/classes/plugin/auth/PMA_AuthenticationCookie_test.php4
-rw-r--r--test/classes/plugin/auth/PMA_AuthenticationHttp_test.php4
-rw-r--r--themes.php2
-rw-r--r--themes/original/css/common.css.php248
-rwxr-xr-xthemes/original/img/console.pngbin0 -> 1208 bytes
-rw-r--r--themes/pmahomme/css/common.css.php249
-rwxr-xr-xthemes/pmahomme/img/console.pngbin0 -> 1208 bytes
-rw-r--r--transformation_overview.php2
24 files changed, 1638 insertions, 65 deletions
diff --git a/browse_foreigners.php b/browse_foreigners.php
index daeaf47efe..444d01f5d0 100644
--- a/browse_foreigners.php
+++ b/browse_foreigners.php
@@ -29,7 +29,7 @@ PMA_Util::checkParameters(array('db', 'table', 'field'));
$response = PMA_Response::getInstance();
$response->getFooter()->setMinimal();
$header = $response->getHeader();
-$header->disableMenu();
+$header->disableMenuAndConsole();
$header->setBodyId('body_browse_foreigners');
/**
diff --git a/import.php b/import.php
index c77059acaf..89bb710ed5 100644
--- a/import.php
+++ b/import.php
@@ -12,6 +12,7 @@
require_once 'libraries/common.inc.php';
require_once 'libraries/sql.lib.php';
require_once 'libraries/bookmark.lib.php';
+require_once 'libraries/Console.class.php';
//require_once 'libraries/display_import_functions.lib.php';
if (isset($_REQUEST['show_as_php'])) {
@@ -27,6 +28,13 @@ if (isset($_REQUEST['simulate_dml'])) {
exit;
}
+// If it's a refresh console bookmarks request
+if(isset($_GET['console_bookmark_refresh'])) {
+ $response = PMA_Response::getInstance();
+ $response->addJSON('console_message_bookmark', PMA_Console::getBookmarkContent());
+ exit;
+}
+
/**
* Sets globals from $_POST
*/
@@ -124,7 +132,6 @@ if (! empty($sql_query)) {
// If we didn't get any parameters, either user called this directly, or
// upload limit has been reached, let's assume the second possibility.
-;
if ($_POST == array() && $_GET == array()) {
$message = PMA_Message::error(
__('You probably tried to upload a file that is too large. Please refer to %sdocumentation%s for a workaround for this limit.')
@@ -140,6 +147,12 @@ if ($_POST == array() && $_GET == array()) {
exit; // the footer is displayed automatically
}
+// Add console message id to response output
+if(isset($_POST['console_message_id'])) {
+ $response = PMA_Response::getInstance();
+ $response->addJSON('console_message_id', $_POST['console_message_id']);
+}
+
/**
* Sets globals from $_POST patterns, for import plugins
* We only need to load the selected plugin
diff --git a/js/ajax.js b/js/ajax.js
index e81eb8419c..7831448979 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -347,6 +347,7 @@ var AJAX = {
.not('#pma_header')
.not('#pma_footer')
.not('#pma_demo')
+ .not('#pma_console_container')
.remove();
// Replace #page_content with new content
if (data.message && data.message.length > 0) {
@@ -459,6 +460,9 @@ var AJAX = {
$('#'+data.fieldWithError).addClass("error");
}
}
+ if(PMA_console && PMA_console.isEnabled) {
+ PMA_console.ajaxCallback(data);
+ }
},
/**
* This object is in charge of downloading scripts,
diff --git a/js/console.js b/js/console.js
new file mode 100644
index 0000000000..02e0309f0c
--- /dev/null
+++ b/js/console.js
@@ -0,0 +1,724 @@
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Used in or for console
+ *
+ * @package phpMyAdmin-Console
+ */
+
+/**
+ * Executed on page load
+ */
+$(function () {
+ PMA_console.initialize();
+});
+
+
+/**
+ * Console object
+ */
+var PMA_console = {
+ /**
+ * @var object, jQuery object, selector is '#pma_console>.content'
+ * @access private
+ */
+ $consoleContent: null,
+ /**
+ * @var object, jQuery object, selector is '#pma_console .content',
+ * used for resizer
+ * @access private
+ */
+ $consoleAllContents: null,
+ /**
+ * @var object, jQuery object, selector is '#pma_console .toolbar'
+ * @access private
+ */
+ $consoleToolbar: null,
+ /**
+ * @var object, jQuery object, selector is '#pma_console .template'
+ * @access private
+ */
+ $consoleTemplates: null,
+ /**
+ * @var object, jQuery object, form for submit
+ * @access private
+ */
+ $requestForm: null,
+ /**
+ * @var object, contain console config
+ * @access private
+ */
+ config: null,
+ /**
+ * @var bool, if console element exist, it'll be true
+ * @access public
+ */
+ isEnabled: false,
+ /**
+ * @var bool, make sure console events bind only once
+ * @access private
+ */
+ isInitialized: false,
+ /**
+ * Used for console initialize, reinit is ok, just some variable assignment
+ *
+ * @return void
+ */
+ initialize: function() {
+
+ if($('#pma_console').length === 0) {
+ return;
+ }
+
+ PMA_console.isEnabled = true;
+
+ // Cookie var checks and init
+ if(! $.cookie('pma_console_height')) {
+ $.cookie('pma_console_height', 92);
+ }
+ if(! $.cookie('pma_console_mode')) {
+ $.cookie('pma_console_mode', 'info');
+ }
+
+ // Vars init
+ PMA_console.$consoleToolbar = $('#pma_console>.toolbar');
+ PMA_console.$consoleContent = $('#pma_console>.content');
+ PMA_console.$consoleAllContents = $('#pma_console .content');
+ PMA_console.$consoleTemplates = $('#pma_console>.templates');
+
+ // Generate a from for post
+ PMA_console.$requestForm = $('<form method="post" action="import.php">'
+ + '<input name="is_js_confirmed" value="0">'
+ + '<textarea name="sql_query"></textarea>'
+ + '<input name="console_message_id" value="0">'
+ + '<input name="db" value="">'
+ + '<input name="table" value="">'
+ + '<input name="token" value="'
+ + PMA_commonParams.get('token') + '">'
+ + '</form>');
+ PMA_console.$requestForm.bind('submit', AJAX.requestHandler);
+
+ // Event binds shouldn't run again
+ if(PMA_console.isInitialized === false) {
+
+ // Load config first
+ var tempConfig = JSON.parse($.cookie('pma_console_config'));
+ if(tempConfig) {
+ if(tempConfig.alwaysExpand === true) {
+ $('#pma_console_options input[name=always_expand]').attr('checked', true);
+ }
+ if(tempConfig.startHistory === true) {
+ $('#pma_console_options input[name=start_history]').attr('checked', true);
+ }
+ if(tempConfig.currentQuery === true) {
+ $('#pma_console_options input[name=current_query]').attr('checked', true);
+ }
+ } else {
+ $('#pma_console_options input[name=current_query]').attr('checked', true);
+ }
+
+ PMA_console.updateConfig();
+
+ PMA_consoleResizer.initialize();
+ PMA_consoleInput.initialize();
+ PMA_consoleMessages.initialize();
+ PMA_consoleBookmarks.initialize();
+
+ PMA_console.$consoleToolbar.children('.console_switch').click(PMA_console.toggle);
+ $(document).keydown(function(event) {
+ // 27 keycode is ESC
+ if(event.keyCode === 27)
+ PMA_console.toggle();
+ });
+
+ $('#pma_console .toolbar').children().mousedown(function(event) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ });
+
+ $('#pma_console .button.clear').click(function() {
+ PMA_consoleMessages.clear();
+ });
+
+ $('#pma_console .button.history').click(function() {
+ PMA_consoleMessages.showHistory();
+ });
+
+ $('#pma_console .button.options').click(function() {
+ PMA_console.showCard('#pma_console_options');
+ });
+
+ $('#pma_console .mid_layer').click(function() {
+ PMA_console.hideCard($(this).parent().children('.card'));
+ });
+ $('#pma_bookmarks .switch_button').click(function() {
+ PMA_console.hideCard($(this).closest('.card'));
+ });
+
+ $('#pma_console_options input[type=checkbox]').change(function() {
+ PMA_console.updateConfig();
+ });
+
+ $('#pma_console_options .button.default').click(function() {
+ $('#pma_console_options input[name=always_expand]').prop('checked', false);
+ $('#pma_console_options input[name=start_history]').prop('checked', false);
+ $('#pma_console_options input[name=current_query]').prop('checked', true);
+ PMA_console.updateConfig();
+ });
+
+ PMA_console.isInitialized = true;
+ }
+
+ // Change console mode from cookie
+ switch($.cookie('pma_console_mode')) {
+ case 'collapse':
+ PMA_console.collapse();
+ break;
+ default:
+ $.cookie('pma_console_mode', 'info');
+ case 'info':
+ PMA_console.info();
+ break;
+ case 'show':
+ PMA_console.show(true);
+ PMA_console.scrollBottom();
+ break;
+ }
+ },
+ /**
+ * Excute query and show results in console
+ *
+ * @return void
+ */
+ execute: function(queryString, target) {
+ if(typeof(queryString) != 'string' || ! /[a-z]|[A-Z]/.test(queryString)){
+ return;
+ }
+ PMA_console.$requestForm.children('textarea').val(queryString);
+ if(target && target.db) {
+ PMA_console.$requestForm.children('[name=db]').attr('value', target.db);
+ if(target.table) {
+ PMA_console.$requestForm.children('[name=table]').attr('value', target.table);
+ } else {
+ PMA_console.$requestForm.children('[name=table]').attr('value', '');
+ }
+ } else {
+ PMA_console.$requestForm.children('[name=db]').attr('value',
+ (PMA_commonParams.get('db').length > 0 ? PMA_commonParams.get('db') : ''));
+ }
+ if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0])) {
+ return;
+ }
+ PMA_console.$requestForm.children('[name=console_message_id]')
+ .attr('value', PMA_consoleMessages.appendQuery({sql_query: queryString}));
+ PMA_console.$requestForm.trigger('submit');
+ PMA_consoleInput.clear();
+ },
+ ajaxCallback: function(data) {
+ if(data.console_message_id) {
+ PMA_consoleMessages.updateQuery(data.console_message_id, data.success,
+ (data._reloadQuerywindow ? data._reloadQuerywindow : false));
+ } else if(data._reloadQuerywindow) {
+ if(data._reloadQuerywindow.sql_query.length > 0) {
+ PMA_consoleMessages.appendQuery(data._reloadQuerywindow, 'successed');
+ }
+ }
+ },
+ /**
+ * Change console to collapse mode
+ *
+ * @return void
+ */
+ collapse: function() {
+ $.cookie('pma_console_mode', 'collapse');
+ var pmaConsoleHeight = $.cookie('pma_console_height');
+
+ if(pmaConsoleHeight < 32) {
+ $.cookie('pma_console_height', 92);
+ }
+ PMA_console.$consoleToolbar.addClass('collapsed');
+ PMA_console.$consoleAllContents.height(pmaConsoleHeight);
+ PMA_console.$consoleContent.stop();
+ PMA_console.$consoleContent.animate({'margin-bottom': -1 * PMA_console.$consoleContent.outerHeight() + 'px'},
+ 'fast', 'easeOutQuart', function() {
+ PMA_console.$consoleContent.css({display:'none'});
+ $(window).trigger('resize');
+ });
+ PMA_console.hideCard();
+ },
+ /**
+ * Show console
+ *
+ * @param bool inputFocus If true, focus the input line after show()
+ * @return void
+ */
+ show: function(inputFocus) {
+ $.cookie('pma_console_mode', 'show');
+
+ var pmaConsoleHeight = $.cookie('pma_console_height');
+
+ if(pmaConsoleHeight < 32) {
+ $.cookie('pma_console_height', 32);
+ PMA_console.collapse();
+ return;
+ }
+ PMA_console.$consoleContent.css({display:'block'});
+ if(PMA_console.$consoleToolbar.hasClass('collapsed'))
+ PMA_console.$consoleToolbar.removeClass('collapsed');
+ PMA_console.$consoleAllContents.height(pmaConsoleHeight);
+ PMA_console.$consoleContent.stop();
+ PMA_console.$consoleContent.animate({'margin-bottom': 0},
+ 'fast', 'easeOutQuart', function() {
+ $(window).trigger('resize');
+ });
+ if(inputFocus) {
+ PMA_consoleInput.focus();
+ }
+ },
+ /**
+ * Change console to SQL information mode
+ * this mode shows current SQL query
+ * This mode is the default mode
+ *
+ * @return void
+ */
+ info: function() {
+ // Under construction
+ PMA_console.collapse();
+ },
+ /**
+ * Toggle console mode between collsapse/show
+ * Used for toggle buttons and shortcuts
+ *
+ * @return void
+ */
+ toggle: function() {
+ switch($.cookie('pma_console_mode')) {
+ case 'collapse':
+ case 'info':
+ PMA_console.show(true);
+ break;
+ case 'show':
+ PMA_console.collapse();
+ break;
+ default:
+ PMA_consoleInitialize();
+ }
+ },
+ /**
+ * Scroll console to bottom
+ *
+ * @return void
+ */
+ scrollBottom: function() {
+ PMA_console.$consoleContent.scrollTop(PMA_console.$consoleContent.prop("scrollHeight"));
+ },
+ /**
+ * Show card
+ *
+ * @param string cardSelector Selector, select string will be "#pma_console " + cardSelector
+ * this param also can be JQuery object, if you need.
+ *
+ * @return void
+ */
+ showCard: function(cardSelector) {
+ var $card = null;
+ if(typeof(cardSelector) !== 'string') {
+ if (cardSelector.length > 0) {
+ $card = cardSelector;
+ } else {
+ return;
+ }
+ } else {
+ $card = $("#pma_console " + cardSelector);
+ }
+ if($card.length === 0) {
+ return;
+ }
+ $card.parent().children('.mid_layer').show().fadeTo(0, 0.15);
+ $card.addClass('show');
+ PMA_consoleInput.blur();
+ if($card.parents('.card').length > 0) {
+ PMA_console.showCard($card.parents('.card'));
+ }
+ },
+ /**
+ * Scroll console to bottom
+ *
+ * @param object $targetCard Target card JQuery object, if it's empty, function will hide all cards
+ * @return void
+ */
+ hideCard: function($targetCard) {
+ if(! $targetCard) {
+ $('#pma_console .mid_layer').fadeOut(140);
+ $('#pma_console .card').removeClass('show');
+ } else if($targetCard.length > 0) {
+ $targetCard.parent().find('.mid_layer').fadeOut(140);
+ $targetCard.find('.card').removeClass('show');
+ $targetCard.removeClass('show');
+ }
+ },
+ /**
+ * Used for update console config
+ *
+ * @return void
+ */
+ updateConfig: function() {
+ PMA_console.config = {
+ alwaysExpand: $('#pma_console_options input[name=always_expand]').prop('checked'),
+ startHistory: $('#pma_console_options input[name=start_history]').prop('checked'),
+ currentQuery: $('#pma_console_options input[name=current_query]').prop('checked')
+ };
+ $.cookie('pma_console_config', JSON.stringify(PMA_console.config));
+ }
+};
+
+/**
+ * Resizer object
+ * Careful: this object UI logics highly related with functions under PMA_console
+ * Resizing min-height is 32, if small than it, console will collapse
+ */
+var PMA_consoleResizer = {
+ _posY: 0,
+ _height: 0,
+ _resultHeight: 0,
+ /**
+ * Mousedown event handler for bind to resizer
+ *
+ * @return void
+ */
+ _mousedown: function(event) {
+ if($.cookie('pma_console_mode') !== 'show')
+ return;
+ PMA_consoleResizer._posY = event.pageY;
+ PMA_consoleResizer._height = PMA_console.$consoleContent.height();
+ $(document).mousemove(PMA_consoleResizer._mousemove);
+ $(document).mouseup(PMA_consoleResizer._mouseup);
+ // Disable text selection while resizing
+ $(document).bind('selectstart', function(){ return false; });
+ },
+ /**
+ * Mousemove event handler for bind to resizer
+ *
+ * @return void
+ */
+ _mousemove: function(event) {
+ PMA_consoleResizer._resultHeight = PMA_consoleResizer._height + (PMA_consoleResizer._posY -event.pageY);
+ // Content min-height is 32, if adjusting height small than it we'll move it out of the page
+ if(PMA_consoleResizer._resultHeight <= 32) {
+ PMA_console.$consoleAllContents.height(32);
+ PMA_console.$consoleContent.css('margin-bottom', PMA_consoleResizer._resultHeight - 32);
+ }
+ else {
+ // Logic below makes viewable area always at bottom when adjusting height and content already at bottom
+ if(PMA_console.$consoleContent.scrollTop() + PMA_console.$consoleContent.innerHeight() + 16
+ >= PMA_console.$consoleContent.prop('scrollHeight')) {
+ PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight);
+ PMA_console.scrollBottom();
+ } else {
+ PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight);
+ }
+ }
+ },
+ /**
+ * Mouseup event handler for bind to resizer
+ *
+ * @return void
+ */
+ _mouseup: function() {
+ $.cookie('pma_console_height', PMA_consoleResizer._resultHeight);
+ PMA_console.show();
+ $(document).unbind('mousemove');
+ $(document).unbind('mouseup');
+ $(document).unbind('selectstart');
+ },
+ /**
+ * Used for console resizer initialize
+ *
+ * @return void
+ */
+ initialize: function() {
+ $('#pma_console .toolbar').unbind('mousedown');
+ $('#pma_console .toolbar').mousedown(PMA_consoleResizer._mousedown);
+ }
+};
+
+
+/**
+ * Console input object
+ */
+var PMA_consoleInput = {
+ /**
+ * @var CodeMirror object
+ * @access private
+ */
+ _cm: null,
+ /**
+ * Used for console input initialize
+ *
+ * @return void
+ */
+ initialize: function() {
+ // _cm object can't be reinitialize
+ if(PMA_consoleInput._cm !== null) {
+ return;
+ }
+ PMA_consoleInput._cm = CodeMirror($('#query_input')[0], {
+ theme: 'pma',
+ mode: 'text/x-sql',
+ lineWrapping: true
+ });
+ $('#pma_console .CodeMirror.cm-s-pma').keydown(PMA_consoleInput._keydown);
+ },
+ /**
+ * Mousedown event handler for bind to input
+ * Shortcut is ESC key
+ *
+ * @return void
+ */
+ _keydown: function(event) {
+ if(event.ctrlKey && event.keyCode === 13) {
+ PMA_consoleInput.execute();
+ }
+ },
+ /**
+ * Used for send text to PMA_console.execute()
+ *
+ * @return void
+ */
+ execute: function() {
+ PMA_console.execute(PMA_consoleInput._cm.getValue());
+ },
+ /**
+ * Used for clear the input
+ *
+ * @param bool clearHistory if true, clear type history
+ * @return void
+ */
+ clear: function(clearHistory) {
+ PMA_consoleInput._cm.setValue('');
+ if(clearHistory){
+ PMA_consoleInput._cm.clearHistory();
+ }
+ },
+ /**
+ * Used for set focus to input
+ *
+ * @return void
+ */
+ focus: function() {
+ PMA_consoleInput._cm.focus();
+ },
+ /**
+ * Used for blur input
+ *
+ * @return void
+ */
+ blur: function() {
+ PMA_consoleInput._cm.getInputField().blur();
+ },
+ /**
+ * Used for set text in input
+ *
+ * @return void
+ */
+ setText: function(text) {
+ PMA_consoleInput._cm.setValue(text);
+ }
+
+};
+
+
+/**
+ * Console messages, and message items management object
+ */
+var PMA_consoleMessages = {
+ /**
+ * Used for clear the messages
+ *
+ * @return void
+ */
+ clear: function() {
+ $('#pma_console .content .console_message_container .message:not(.welcome)').addClass('hide');
+ $('#pma_console .content .console_message_container .message.failed').remove();
+ },
+ /**
+ * Used for show history messages
+ *
+ * @return void
+ */
+ showHistory: function() {
+ $('#pma_console .content .console_message_container .message.hide').removeClass('hide');
+ },
+ /**
+ * Used for log new message
+ *
+ * @param string msgString Message to show
+ * @param string msgType Message type
+ * @return object, {message_id, $message}
+ */
+ append: function(msgString, msgType) {
+ if(typeof(msgString) !== 'string') {
+ return false;
+ }
+ // Generate an ID for each message, we can find them later
+ var msgId = Math.round(Math.random()*(899999999999)+100000000000);
+ var $newMessage =
+ $('<div class="message '
+ + (PMA_console.config.alwaysExpand ? 'expanded' : 'collapsed')
+ +'" msgid="' + msgId + '"><div class="action_content"></div></div>');
+ switch(msgType) {
+ case 'query':
+ $newMessage.append('<div class="query highlighted"></div>');
+ CodeMirror.runMode(msgString,
+ 'text/x-sql', $newMessage.children('.query')[0]);
+ $newMessage.children('.action_content')
+ .append(PMA_console.$consoleTemplates.children('.query_actions').html());
+ break;
+ default:
+ case 'normal':
+ $newMessage.append('<div>' + msgString + '</div>');
+ }
+ PMA_consoleMessages._msgEventBinds($newMessage);
+ $newMessage.find('span.text.query_time span').text(Date());
+ return {message_id: msgId,
+ $message: $newMessage.appendTo('#pma_console .content .console_message_container')};
+ },
+ /**
+ * Used for log new query
+ *
+ * @param string queryData Struct should be
+ * {sql_query: "Query string", db: "Target DB", table: "Target Table"}
+ * @param string state Message state
+ * @return object, {message_id: string message id, $message: JQuery object}
+ */
+ appendQuery: function(queryData, state) {
+ var targetMessage = PMA_consoleMessages.append(queryData.sql_query, 'query');
+ if(! targetMessage) {
+ return false;
+ }
+ if(queryData.db && queryData.table) {
+ targetMessage.$message.attr('targetdb', queryData.db);
+ targetMessage.$message.attr('targettable', queryData.table);
+ targetMessage.$message.find('.text.targetdb span').text(queryData.db);
+ }
+ switch(state) {
+ case 'failed':
+ targetMessage.$message.addClass('failed');
+ break;
+ case 'successed':
+ console.dir(targetMessage.$message);
+ targetMessage.$message.addClass('successed');
+ break;
+ default:
+ case 'pending':
+ targetMessage.$message.addClass('pending');
+ }
+ return targetMessage.message_id;
+ },
+ _msgEventBinds: function($targetMessage) {
+ // Leave unbinded elements, remove binded.
+ var $targetMessage = $targetMessage.filter(':not(.binded)');
+ if($targetMessage.length === 0) {
+ return;
+ }
+ $targetMessage.addClass('binded');
+
+ $targetMessage.find('.action.expand').click(function () {
+ $(this).closest('.message').removeClass('collapsed');
+ $(this).closest('.message').addClass('expanded');
+ });
+ $targetMessage.find('.action.collapse').click(function () {
+ $(this).closest('.message').addClass('collapsed');
+ $(this).closest('.message').removeClass('expanded');
+ });
+ $targetMessage.find('.action.reedit').click(function () {
+ PMA_consoleInput.setText($(this).parent().siblings('.query').text());
+ PMA_consoleInput.focus();
+ });
+ $targetMessage.find('.action.requery').click(function () {
+ var query = $(this).parent().siblings('.query').text();
+ var $message = $(this).closest('.message');
+ if(confirm(PMA_messages.strConsoleRequeryConfirm + '\n'
+ + (query.length<100 ? query : query.slice(0, 100) + '...'))) {
+ PMA_console.execute(query, {db: $message.attr('targetdb'), table: $message.attr('targettable')});
+ }
+ });
+ },
+ msgAppend: function(msgId, msgString, msgType) {
+ var $targetMessage = $('#pma_console .content .console_message_container .message[msgid=' + msgId +']');
+ if($targetMessage.length === 0 || isNaN(parseInt(msgId)) || typeof(msgString) !== 'string') {
+ return false;
+ }
+ $targetMessage.append('<div>' + msgString + '</div>');
+ },
+ updateQuery: function(msgId, isSuccessed, queryData) {
+ var $targetMessage = $('#pma_console .console_message_container .message[msgid=' + parseInt(msgId) +']');
+ if($targetMessage.length === 0 || isNaN(parseInt(msgId))) {
+ return false;
+ }
+ $targetMessage.removeClass('pending failed successed');
+ if(isSuccessed) {
+ $targetMessage.addClass('successed');
+ if(queryData) {
+ $targetMessage.children('.query').text('');
+ CodeMirror.runMode(queryData.sql_query, 'text/x-sql', $targetMessage.children('.query')[0]);
+ $targetMessage.attr('targetdb', queryData.db);
+ $targetMessage.attr('targettable', queryData.table);
+ $targetMessage.find('.text.targetdb span').text(queryData.db);
+ }
+ } else {
+ $targetMessage.addClass('failed');
+ }
+ },
+ /**
+ * Used for console messages initialize
+ *
+ * @return void
+ */
+ initialize: function() {
+ PMA_consoleMessages._msgEventBinds($('#pma_console .message:not(.binded)'));
+ $('#pma_console .message .query:not(.highlighted)').each(function(index, elem) {
+ CodeMirror.runMode(elem.innerHTML,
+ 'text/x-sql', elem);
+ $(this).addClass('highlighted');
+ });
+ if(PMA_console.config.startHistory) {
+ PMA_consoleMessages.showHistory();
+ }
+ }
+};
+
+
+/**
+ * Console bookmarks card, and bookmarks items management object
+ */
+var PMA_consoleBookmarks = {
+ /**
+ * Used for console bookmarks initialize
+ * message events are already binded by PMA_consoleMsg._msgEventBinds
+ *
+ * @return void
+ */
+ initialize: function() {
+ if($('#pma_bookmarks').length === 0) {
+ return;
+ }
+ $('#pma_console .button.bookmarks').click(function() {
+ PMA_console.showCard('#pma_bookmarks');
+ });
+ $('#pma_bookmarks .button.add').click(function() {
+ PMA_console.showCard('#pma_bookmarks .card.add');
+ });
+ $('#pma_console .button.refresh').click(function() {
+ $.get('import.php?console_bookmark_refresh=refresh&token=' + PMA_commonParams.get('token'),
+ {'ajax_request': true},
+ function(data) {
+ if(data.console_message_bookmark) {
+ $('#pma_bookmarks .content.bookmark').html(data.console_message_bookmark);
+ PMA_consoleMessages._msgEventBinds($('#pma_bookmarks .message:not(.binded)'));
+ }
+ });
+ });
+ }
+
+} \ No newline at end of file
diff --git a/js/messages.php b/js/messages.php
index 0f7a7097b7..e527fb65ef 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -468,6 +468,8 @@ $js_messages['phpErrorsBeingSubmitted'] = '<div class="error">'
. '" width="16" height="16" alt="ajax clock"/>'
. '</div>';
+$js_messages['strConsoleRequeryConfirm'] = __('Execute this query again?');
+
echo "var PMA_messages = new Array();\n";
foreach ($js_messages as $name => $js_message) {
PMA_printJsValue("PMA_messages['" . $name . "']", $js_message);
diff --git a/js/navigation.js b/js/navigation.js
index b7b037e61a..6b46f2222e 100644
--- a/js/navigation.js
+++ b/js/navigation.js
@@ -727,10 +727,6 @@ function PMA_navigationTreePagination($this) {
*/
var ResizeHandler = function () {
/**
- * Whether the user has initiated a resize operation
- */
- this.active = false;
- /**
* @var int panel_width Used by the collapser to know where to go
* back to when uncollapsing the panel
*/
@@ -752,7 +748,7 @@ var ResizeHandler = function () {
var $collapser = $('#pma_navigation_collapser');
$('#pma_navigation').width(pos);
$('body').css('margin-' + this.left, pos + 'px');
- $("#floating_menubar")
+ $("#floating_menubar, #pma_console")
.css('margin-' + this.left, (pos + resizer_width) + 'px');
$resizer.css(this.left, pos + 'px');
if (pos === 0) {
@@ -826,7 +822,11 @@ var ResizeHandler = function () {
*/
this.mousedown = function (event) {
event.preventDefault();
- event.data.resize_handler.active = true;
+ $(document)
+ .bind('mousemove', {'resize_handler': event.data.resize_handler},
+ $.throttle(event.data.resize_handler.mousemove, 4))
+ .bind('mouseup', {'resize_handler': event.data.resize_handler},
+ event.data.resize_handler.mouseup);
$('body').css('cursor', 'col-resize');
};
/**
@@ -837,12 +837,11 @@ var ResizeHandler = function () {
* @return void
*/
this.mouseup = function (event) {
- if (event.data.resize_handler.active) {
- event.data.resize_handler.active = false;
- $('body').css('cursor', '');
- $.cookie('pma_navi_width', event.data.resize_handler.getPos(event));
- $('#topmenu').menuResizer('resize');
- }
+ $('body').css('cursor', '');
+ $.cookie('pma_navi_width', event.data.resize_handler.getPos(event));
+ $('#topmenu').menuResizer('resize');
+ $(document)
+ .unbind('mousemove');
};
/**
* Event handler for updating the panel during a resize operation
@@ -852,11 +851,9 @@ var ResizeHandler = function () {
* @return void
*/
this.mousemove = function (event) {
- if (event.data && event.data.resize_handler && event.data.resize_handler.active) {
- event.preventDefault();
- var pos = event.data.resize_handler.getPos(event);
- event.data.resize_handler.setWidth(pos);
- }
+ event.preventDefault();
+ var pos = event.data.resize_handler.getPos(event);
+ event.data.resize_handler.setWidth(pos);
if($('#sticky_columns').length !== 0) {
handleStickyColumns();
}
@@ -870,7 +867,6 @@ var ResizeHandler = function () {
*/
this.collapse = function (event) {
event.preventDefault();
- event.data.active = false;
var panel_width = event.data.resize_handler.panel_width;
var width = $('#pma_navigation').width();
if (width === 0 && panel_width === 0) {
@@ -898,6 +894,9 @@ var ResizeHandler = function () {
'overflow-y': 'auto'
});
}
+ // Set content bottom space beacuse of console
+ $('body').css('margin-bottom',
+ $(window).height() + $(document).scrollTop() - $('#pma_console').offset().top + 'px');
};
/* Initialisation section begins here */
if ($.cookie('pma_navi_width')) {
@@ -909,9 +908,6 @@ var ResizeHandler = function () {
// Register the events for the resizer and the collapser
$('#pma_navigation_resizer')
.live('mousedown', {'resize_handler': this}, this.mousedown);
- $(document)
- .bind('mouseup', {'resize_handler': this}, this.mouseup)
- .bind('mousemove', {'resize_handler': this}, $.throttle(this.mousemove, 4));
var $collapser = $('#pma_navigation_collapser');
$collapser.live('click', {'resize_handler': this}, this.collapse);
// Add the correct arrow symbol to the collapser
diff --git a/js/sql.js b/js/sql.js
index 012a69f66b..3a431c098c 100644
--- a/js/sql.js
+++ b/js/sql.js
@@ -375,6 +375,9 @@ AJAX.registerOnload('sql.js', function () {
}
}
}
+ if(PMA_console && PMA_console.isEnabled) {
+ PMA_console.ajaxCallback(data);
+ }
} else if (data.success === false) {
// show an error message that stays on screen
$('#sqlqueryform').before(data.error);
diff --git a/libraries/Console.class.php b/libraries/Console.class.php
new file mode 100644
index 0000000000..fa9e538208
--- /dev/null
+++ b/libraries/Console.class.php
@@ -0,0 +1,265 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Used to render the console of PMA's pages
+ *
+ * @package PhpMyAdmin
+ */
+if (! defined('PHPMYADMIN')) {
+ exit;
+}
+
+require_once 'libraries/Scripts.class.php';
+require_once 'libraries/Util.class.php';
+require_once 'libraries/bookmark.lib.php';
+
+/**
+ * Class used to output the console
+ *
+ * @package PhpMyAdmin
+ */
+class PMA_Console
+{
+ /**
+ * PMA_Scripts instance
+ *
+ * @access private
+ * @var PMA_Scripts
+ */
+ private $_scripts;
+ /**
+ * Whether to display anything
+ *
+ * @access private
+ * @var bool
+ */
+ private $_isEnabled;
+
+ /**
+ * Creates a new class instance
+ */
+ public function __construct()
+ {
+ $this->_isEnabled = true;
+ $this->_scripts = new PMA_Scripts();
+ }
+
+ /**
+ * Whether we are servicing an ajax request.
+ * We can't simply use $GLOBALS['is_ajax_request']
+ * here since it may have not been initialised yet.
+ *
+ * @access private
+ * @var bool
+ */
+ private $_isAjax;
+
+ /**
+ * Set the ajax flag to indicate whether
+ * we are sevicing an ajax request
+ *
+ * @param bool $isAjax Whether we are sevicing an ajax request
+ *
+ * @return void
+ */
+ public function setAjax($isAjax)
+ {
+ $this->_isAjax = ($isAjax == true);
+ }
+
+ /**
+ * Disables the rendering of the footer
+ *
+ * @return void
+ */
+ public function disable()
+ {
+ $this->_isEnabled = false;
+ }
+
+ /**
+ * Renders the bookmark content
+ *
+ * @access public
+ * @return string
+ */
+ public static function getBookmarkContent()
+ {
+ $output = '';
+ $cfgBookmark = PMA_Bookmark_getParams();
+ if($cfgBookmark) {
+
+ $tpl_bookmark_actions =
+ '<span class="action collapse">' . __('Collapse') . '</span> '
+ . '<span class="action expand">' . __('Expand') . '</span> '
+ . '<span class="action requery">' . __('Requery') . '</span> '
+ . '<span class="action reedit">' . __('Reedit') . '</span> '
+ // . '<span class="action bookmark">' . __('Delete') . '</span> '
+ . '<span class="text targetdb">' . __('Database') . ': <span>%s</span></span>';
+
+ $bookmarks = PMA_Bookmark_getList();
+ $output .= '<div class="message welcome"><span>'
+ . (count($bookmarks) > 0 ? __('Total ') . count($bookmarks) . __(' bookmarks, ')
+ . '<span class="bookmark_label">' . __('private')
+ . '</span> and <span class="bookmark_label shared">' . __('shared')
+ . '</span>' . __(' bookmarks included.')
+ : __('No bookmarks'))
+ . '</span></div>';
+ foreach ($bookmarks as $key => $val) {
+ $output .= '<div class="message collapsed bookmark" bookmarkid="'
+ . $val['id'] . '" bookmarkdb="' . $val['db']
+ . '"><div class="action_content">'
+ . sprintf($tpl_bookmark_actions, $val['db'])
+ . '</div><span class="bookmark_label ' . ($val['shared'] ? 'shared' : '') . '">'
+ . $val['label']
+ . '</span> <span class="query">'
+ . $val['query']
+ . '</span></div>';
+ }
+ }
+ return $output;
+ }
+
+ /**
+ * Renders the console
+ *
+ * @access public
+ * @return string
+ */
+ public function getDisplay()
+ {
+ $output = '';
+ if((! $this->_isAjax) && $this->_isEnabled) {
+ $cfgBookmark = PMA_Bookmark_getParams();
+ $this->_scripts->addFile('codemirror/lib/codemirror.js');
+ $this->_scripts->addFile('codemirror/mode/sql/sql.js');
+ $this->_scripts->addFile('codemirror/addon/runmode/runmode.js');
+ $this->_scripts->addFile('console.js');
+ $output .= $this->_scripts->getDisplay();
+ $output .= '<div id="pma_console_container"><div id="pma_console">';
+
+ // The templates, use sprintf() to output them
+ // There're white space at the end of every <span>,
+ // for double-click selection
+ $tpl_query_actions =
+ '<span class="action collapse">' . __('Collapse') . '</span> '
+ . '<span class="action expand">' . __('Expand') . '</span> '
+ . '<span class="action requery">' . __('Requery') . '</span> '
+ . '<span class="action reedit">' . __('Reedit') . '</span> '
+ // . ($cfgBookmark ? '<span class="action bookmark">' . __('Bookmark') . '</span> ' : '')
+ . '<span class="text failed">' . __('Query failed') . '</span> '
+ . '<span class="text targetdb">' . __('Database') . ': <span>%s</span></span> '
+ . '<span class="text query_time">' . __('Queried time') . ': <span>%s</span></span> ';
+
+ // Console toolbar
+ $output .= '<div class="toolbar collapsed">';
+
+ $output .= '<div class="switch_button console_switch">';
+ $output .= PMA_Util::getImage('console.png', __('SQL Query Console'));
+ $output .= '<span>' . __('Console') . '</span></div>';
+
+ $output .= '<div class="button clear"><span>'
+ . __('Clear') . '</span></div>';
+
+ $output .= '<div class="button history"><span>'
+ . __('History') . '</span></div>';
+
+ $output .= '<div class="button options"><span>'
+ . __('Options') . '</span></div>';
+
+ if($cfgBookmark) {
+ $output .= '<div class="button bookmarks"><span>'
+ . __('Bookmarks') . '</span></div>';
+ }
+
+ $output .= '</div>'; // Toolbar end
+
+ // Console messages
+ $output .= '<div class="content">';
+ $output .= '<div class="console_message_container">'
+ . '<div class="message welcome"><span>'
+ . __('Press') . ' Ctrl+Enter ' . __('to Execute query')
+ . '</span></div>';
+
+ // History support
+ $_sql_history = PMA_getHistory($GLOBALS['cfg']['Server']['user']);
+ if($_sql_history) {
+ foreach (array_reverse($_sql_history) as $record) {
+ $output .= '<div class="message history collapsed hide" targetdb="'
+ . $record['db'] . '" targettable="' . $record['table']
+ . '""><div class="action_content">'
+ . sprintf($tpl_query_actions, $record['db'],
+ (isset($record['timevalue']) ? $record['timevalue'] : __('During current session')))
+ . '</div><span class="query">'
+ . $record['sqlquery']
+ . '</span></div>';
+ }
+ }
+
+ $output .= '</div>'; // .console_message_container
+ $output .= '<div class="query_input"><span id="query_input"></span></div>'
+ . '</div>'; // Messages end
+
+ // Dark the console while other cards cover it
+ $output .= '<div class="mid_layer"></div>';
+
+ // Bookmarks card:
+
+ if($cfgBookmark) {
+ $output .= '<div class="card" id="pma_bookmarks">';
+ $output .= '<div class="toolbar">'
+ . '<div class="switch_button"><span>' . __('Bookmarks')
+ . '</span></div>';
+
+ $output .= '<div class="button refresh"><span>'
+ . __('Refresh') . '</span></div>';
+
+ // $output .= '<div class="button add"><span>'
+ // . __('Add') . '</span></div>';
+
+ $output .= '</div><div class="content bookmark">';
+ $output .= $this->getBookmarkContent();
+ $output .= '</div>';
+ $output .= '<div class="mid_layer"></div>';
+ $output .= '<div class="card add">';
+ $output .= '<div class="toolbar">'
+ . '<div class="switch_button"><span>' . __('Add bookmark')
+ . '</span></div>';
+ $output .= '</div><div class="content add_bookmark">'
+ . '<label>'. __('Label') . ':<input type="text" name="label"></label> '
+ . '<label>'. __('Target database') . ':<input type="text" name="targetdb"></label> '
+ . '<label><input type="checkbox" name="shared">'. __('Share this bookmark') . '</label>';
+ $output .= '</div>';
+ $output .= '</div></div>'; // Bookmarks card
+ }
+
+ // Options card:
+ $output .= '<div class="card" id="pma_console_options">';
+ $output .= '<div class="toolbar">'
+ . '<div class="switch_button"><span>' . __('Options') . '</span></div>';
+
+ $output .= '<div class="button default"><span>'
+ . __('Set default') . '</span></div>';
+
+ $output .= '</div><div class="content">'
+ . '<label><input type="checkbox" name="always_expand">'
+ . __('Always expand queried messages') . '</label><br>'
+ . '<label><input type="checkbox" name="start_history">'
+ . __('Show query history at start') . '</label><br>'
+ . '<label><input type="checkbox" name="current_query">'
+ . __('Show current browsing query') . '</label><br>'
+ . '</div>';
+ $output .= '</div>'; // Options card
+
+ $output .= '<div class="templates">'
+ // Templates for console message actions
+ . '<div class="query_actions">'
+ . sprintf($tpl_query_actions, '', '')
+ . '</div>'
+ . '</div>';
+ $output .= '</div></div>'; // #console and #pma_console_container ends
+ }
+ return $output;
+ }
+
+}
diff --git a/libraries/Header.class.php b/libraries/Header.class.php
index af3f2d22b5..0097e7993d 100644
--- a/libraries/Header.class.php
+++ b/libraries/Header.class.php
@@ -12,6 +12,7 @@ if (! defined('PHPMYADMIN')) {
require_once 'libraries/Scripts.class.php';
require_once 'libraries/RecentFavoriteTable.class.php';
require_once 'libraries/Menu.class.php';
+require_once 'libraries/Console.class.php';
require_once 'libraries/navigation/Navigation.class.php';
require_once 'libraries/url_generating.lib.php';
@@ -31,6 +32,13 @@ class PMA_Header
*/
private $_scripts;
/**
+ * PMA_Console instance
+ *
+ * @access private
+ * @var PMA_Console
+ */
+ private $_console;
+ /**
* PMA_Menu instance
*
* @access private
@@ -113,6 +121,7 @@ class PMA_Header
$this->_isAjax = false;
$this->_bodyId = '';
$this->_title = '';
+ $this->_console = new PMA_Console();
$db = ! empty($GLOBALS['db']) ? $GLOBALS['db'] : '';
$table = ! empty($GLOBALS['table']) ? $GLOBALS['table'] : '';
$this->_menu = new PMA_Menu(
@@ -270,6 +279,7 @@ class PMA_Header
public function setAjax($isAjax)
{
$this->_isAjax = ($isAjax == true);
+ $this->_console->setAjax($isAjax);
}
/**
@@ -321,9 +331,10 @@ class PMA_Header
*
* @return void
*/
- public function disableMenu()
+ public function disableMenuAndConsole()
{
$this->_menuEnabled = false;
+ $this->_console->disable();
}
/**
@@ -343,7 +354,7 @@ class PMA_Header
*/
public function enablePrintView()
{
- $this->disableMenu();
+ $this->disableMenuAndConsole();
$this->setTitle(__('Print view') . ' - phpMyAdmin ' . PMA_VERSION);
$this->_isPrintView = true;
}
@@ -409,6 +420,7 @@ class PMA_Header
PMA_Util::getImage('s_top.png')
);
}
+ $retval .= $this->_console->getDisplay();
$retval .= '<div id="page_content">';
$retval .= $this->getMessage();
}
diff --git a/libraries/bookmark.lib.php b/libraries/bookmark.lib.php
index e5ae629ffc..fba3a798d0 100644
--- a/libraries/bookmark.lib.php
+++ b/libraries/bookmark.lib.php
@@ -45,13 +45,16 @@ function PMA_Bookmark_getParams()
*
* @param string $db the current database name
*
- * @return array the bookmarks list (key as index, label as value)
+ * @return array the bookmarks list (key as index, label as value),
+ * or if param is empty, function will give more information,
+ * array will be unindexed,
+ * each struct: [db, id, label, shared, query]
*
* @access public
*
* @global resource $controllink the controluser db connection handle
*/
-function PMA_Bookmark_getList($db)
+function PMA_Bookmark_getList($db = false)
{
global $controllink;
@@ -61,31 +64,80 @@ function PMA_Bookmark_getList($db)
return array();
}
- $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND user = \'' . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
- . ' ORDER BY label';
- $per_user = $GLOBALS['dbi']->fetchResult(
- $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
- );
-
- $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
- . '.' . PMA_Util::backquote($cfgBookmark['table'])
- . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
- . ' AND user = \'\''
- . ' ORDER BY label';
- $global = $GLOBALS['dbi']->fetchResult(
- $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
- );
-
- foreach ($global as $key => $val) {
- $global[$key] = $val . ' (' . __('shared') . ')';
- }
+ $ret = Array();
+ if($db !== false) {
+ $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
+ . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
+ . ' AND user = \'' . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
+ . ' ORDER BY label';
+ $per_user = $GLOBALS['dbi']->fetchResult(
+ $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ );
- $ret = $global + $per_user;
+ $query = 'SELECT label, id FROM ' . PMA_Util::backquote($cfgBookmark['db'])
+ . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE dbase = \'' . PMA_Util::sqlAddSlashes($db) . '\''
+ . ' AND user = \'\''
+ . ' ORDER BY label';
+ $global = $GLOBALS['dbi']->fetchResult(
+ $query, 'id', 'label', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ );
- asort($ret);
+ foreach ($global as $key => $val) {
+ $global[$key] = $val . ' (' . __('shared') . ')';
+ }
+
+ $ret = $global + $per_user;
+
+ asort($ret);
+ } else {
+ $query = 'SELECT label, id, query, dbase FROM ' . PMA_Util::backquote($cfgBookmark['db'])
+ . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE user = \'' . PMA_Util::sqlAddSlashes($cfgBookmark['user']) . '\''
+ . ' ORDER BY label';
+ $per_user = $GLOBALS['dbi']->fetchResult(
+ $query, Array('id', 'label', 'dbase'), 'query', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ );
+
+ $query = 'SELECT label, id, query, dbase FROM ' . PMA_Util::backquote($cfgBookmark['db'])
+ . '.' . PMA_Util::backquote($cfgBookmark['table'])
+ . ' WHERE user = \'\''
+ . ' ORDER BY label';
+ $global = $GLOBALS['dbi']->fetchResult(
+ $query, Array('id', 'label', 'dbase'), 'query', $controllink, PMA_DatabaseInterface::QUERY_STORE
+ );
+
+ $ret = Array();
+
+ foreach ($global as $id => $val) {
+ foreach ($val as $label => $val2) {
+ foreach ($val2 as $dbase => $query) {
+ $ret[] = Array(
+ 'db' => $dbase,
+ 'id' => $id,
+ 'label' => $label,
+ 'query' => $query,
+ 'shared' => true
+ );
+ }
+ }
+ }
+
+ foreach ($per_user as $id => $val) {
+ foreach ($val as $label => $val2) {
+ foreach ($val2 as $dbase => $query) {
+ $ret[] = Array(
+ 'db' => $dbase,
+ 'id' => $id,
+ 'label' => $label,
+ 'query' => $query,
+ 'shared' => false
+ );
+ }
+ }
+ }
+ }
return $ret;
} // end of the 'PMA_Bookmark_getList()' function
diff --git a/libraries/plugins/auth/AuthenticationConfig.class.php b/libraries/plugins/auth/AuthenticationConfig.class.php
index 53bbdc5671..857ea3e3f2 100644
--- a/libraries/plugins/auth/AuthenticationConfig.class.php
+++ b/libraries/plugins/auth/AuthenticationConfig.class.php
@@ -83,7 +83,7 @@ class AuthenticationConfig extends AuthenticationPlugin
$header = $response->getHeader();
$header->setBodyId('loginform');
$header->setTitle(__('Access denied!'));
- $header->disableMenu();
+ $header->disableMenuAndConsole();
echo '<br /><br />
<center>
<h1>';
diff --git a/libraries/plugins/auth/AuthenticationCookie.class.php b/libraries/plugins/auth/AuthenticationCookie.class.php
index 96771075a0..0fb4f6ff39 100644
--- a/libraries/plugins/auth/AuthenticationCookie.class.php
+++ b/libraries/plugins/auth/AuthenticationCookie.class.php
@@ -105,7 +105,7 @@ class AuthenticationCookie extends AuthenticationPlugin
$header = $response->getHeader();
$header->setBodyId('loginform');
$header->setTitle('phpMyAdmin');
- $header->disableMenu();
+ $header->disableMenuAndConsole();
$header->disableWarnings();
if (file_exists(CUSTOM_HEADER_FILE)) {
diff --git a/libraries/plugins/auth/AuthenticationHttp.class.php b/libraries/plugins/auth/AuthenticationHttp.class.php
index 16838472e6..0ac40f026c 100644
--- a/libraries/plugins/auth/AuthenticationHttp.class.php
+++ b/libraries/plugins/auth/AuthenticationHttp.class.php
@@ -67,7 +67,7 @@ class AuthenticationHttp extends AuthenticationPlugin
$response->getFooter()->setMinimal();
$header = $response->getHeader();
$header->setTitle(__('Access denied!'));
- $header->disableMenu();
+ $header->disableMenuAndConsole();
$header->setBodyId('loginform');
$response->addHTML('<h1>');
diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php
index 9461105e84..7d1c027820 100644
--- a/libraries/relation.lib.php
+++ b/libraries/relation.lib.php
@@ -949,22 +949,26 @@ function PMA_getHistory($username)
{
$cfgRelation = PMA_getRelationsParam();
+ if (! $cfgRelation['historywork']) {
+ return false;
+ }
+
/**
* if db-based history is disabled but there exists a session-based
* history, use it
*/
- if (! $GLOBALS['cfg']['QueryHistoryDB'] && isset($_SESSION['sql_history'])) {
+ if (! $GLOBALS['cfg']['QueryHistoryDB']) {
+ if(isset($_SESSION['sql_history'])) {
return array_reverse($_SESSION['sql_history']);
- }
-
- if (! $cfgRelation['historywork']) {
+ }
return false;
}
$hist_query = '
SELECT `db`,
`table`,
- `sqlquery`
+ `sqlquery`,
+ `timevalue`
FROM ' . PMA_Util::backquote($cfgRelation['db'])
. '.' . PMA_Util::backquote($cfgRelation['history']) . '
WHERE `username` = \'' . PMA_Util::sqlAddSlashes($username) . '\'
diff --git a/querywindow.php b/querywindow.php
index f14f600e66..6bc6600dbe 100644
--- a/querywindow.php
+++ b/querywindow.php
@@ -121,7 +121,7 @@ $sql_query = '';
$response = PMA_Response::getInstance();
$response->getFooter()->setMinimal();
$header = $response->getHeader();
-$header->disableMenu();
+$header->disableMenuAndConsole();
$header->setBodyId('bodyquerywindow');
$scripts = $header->getScripts();
$scripts->addFile('common.js');
diff --git a/test/classes/PMA_Header_test.php b/test/classes/PMA_Header_test.php
index 6befa89cee..cb7c8b63f9 100644
--- a/test/classes/PMA_Header_test.php
+++ b/test/classes/PMA_Header_test.php
@@ -56,6 +56,7 @@ class PMA_Header_Test extends PHPUnit_Framework_TestCase
$GLOBALS['PMA_Config']->enableBc();
$GLOBALS['cfg']['Server']['verbose'] = 'verbose host';
$GLOBALS['cfg']['Server']['pmadb'] = '';
+ $GLOBALS['cfg']['Server']['user'] = '';
}
/**
diff --git a/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php b/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php
index 6b9304c5ec..a327a07ef2 100644
--- a/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php
+++ b/test/classes/plugin/auth/PMA_AuthenticationCookie_test.php
@@ -137,7 +137,7 @@ class PMA_AuthenticationCookie_Test extends PHPUnit_Framework_TestCase
$mockHeader = $this->getMockBuilder('PMA_Header')
->disableOriginalConstructor()
->setMethods(
- array('setBodyId', 'setTitle', 'disableMenu', 'disableWarnings')
+ array('setBodyId', 'setTitle', 'disableMenuAndConsole', 'disableWarnings')
)
->getMock();
@@ -150,7 +150,7 @@ class PMA_AuthenticationCookie_Test extends PHPUnit_Framework_TestCase
->with('phpMyAdmin');
$mockHeader->expects($this->once())
- ->method('disableMenu')
+ ->method('disableMenuAndConsole')
->with();
$mockHeader->expects($this->once())
diff --git a/test/classes/plugin/auth/PMA_AuthenticationHttp_test.php b/test/classes/plugin/auth/PMA_AuthenticationHttp_test.php
index 3c53728b57..20c38f5c3d 100644
--- a/test/classes/plugin/auth/PMA_AuthenticationHttp_test.php
+++ b/test/classes/plugin/auth/PMA_AuthenticationHttp_test.php
@@ -101,7 +101,7 @@ class PMA_AuthenticationHttp_Test extends PHPUnit_Framework_TestCase
$mockHeader = $this->getMockBuilder('PMA_Header')
->disableOriginalConstructor()
->setMethods(
- array('setBodyId', 'setTitle', 'disableMenu', 'addHTML')
+ array('setBodyId', 'setTitle', 'disableMenuAndConsole', 'addHTML')
)
->getMock();
@@ -114,7 +114,7 @@ class PMA_AuthenticationHttp_Test extends PHPUnit_Framework_TestCase
->with('Access denied!');
$mockHeader->expects($this->once())
- ->method('disableMenu')
+ ->method('disableMenuAndConsole')
->with();
// set mocked headers and footers
diff --git a/themes.php b/themes.php
index aed65f97dd..f0d1be6f09 100644
--- a/themes.php
+++ b/themes.php
@@ -15,7 +15,7 @@ $response->getFooter()->setMinimal();
$header = $response->getHeader();
$header->setBodyId('bodythemes');
$header->setTitle('phpMyAdmin - ' . __('Theme'));
-$header->disableMenu();
+$header->disableMenuAndConsole();
$hash = '#pma_' . preg_replace('/([0-9]*)\.([0-9]*)\..*/', '\1_\2', PMA_VERSION);
$url = PMA_linkURL('http://www.phpmyadmin.net/home_page/themes.php') . $hash;
diff --git a/themes/original/css/common.css.php b/themes/original/css/common.css.php
index ae15cde699..b7ec2ce4ca 100644
--- a/themes/original/css/common.css.php
+++ b/themes/original/css/common.css.php
@@ -2706,3 +2706,251 @@ table.show_create td {
.small_font {
font-size: smaller;
}
+
+/* Console styles */
+#pma_console_container {
+ width: 100%;
+ position: fixed;
+ bottom: 0;
+ <?php echo $left; ?>: 0;
+ z-index: 100;
+}
+#pma_console {
+ position: relative;
+ margin-<?php echo $left; ?>: 240px;
+}
+#pma_console>.templates {
+ display: none;
+}
+#pma_console .mid_text,
+#pma_console .toolbar span {
+ vertical-align: middle;
+}
+#pma_console .toolbar {
+ position: relative;
+ background: #ccc;
+ border-top: solid 1px #aaa;
+ cursor: n-resize;
+}
+#pma_console .toolbar.collapsed:not(:hover) {
+ display: inline-block;
+ border-top-<?php echo $right; ?>-radius: 3px;
+ border-<?php echo $right; ?>: solid 1px #aaa;
+}
+#pma_console .toolbar.collapsed {
+ cursor: default;
+}
+#pma_console .toolbar.collapsed>.button {
+ display: none;
+}
+#pma_console .message span.text,
+#pma_console .message span.action,
+#pma_console .toolbar .button,
+#pma_console .switch_button {
+ padding: 0 3px;
+ display: inline-block;
+}
+#pma_console .message span.action,
+#pma_console .toolbar .button,
+#pma_console .switch_button {
+ cursor: pointer;
+}
+#pma_console .message span.action:hover,
+#pma_console .toolbar .button:hover,
+#pma_console .switch_button:hover {
+ background: #ddd;
+}
+#pma_console .toolbar .button {
+ margin-<?php echo $right; ?>: .4em;
+}
+#pma_console .toolbar .button {
+ float: <?php echo $right; ?>;
+}
+#pma_console .content {
+ overflow-x: hidden;
+ overflow-y: auto;
+ margin-bottom: -65px;
+ border-top: solid 1px #aaa;
+ background: #fff;
+ padding-top: .4em;
+}
+#pma_console .message,
+#pma_console .query_input {
+ position: relative;
+ font-family: Monaco, Consolas, monospace;
+ cursor: text;
+ margin: 0 10px .2em 1.4em;
+}
+#pma_console .message {
+ border-bottom: solid 1px #ccc;
+ padding-bottom: .2em;
+}
+#pma_console .message.expanded .action_content {
+ position: relative;
+}
+#pma_console .message:before,
+#pma_console .query_input:before {
+ left: -0.7em;
+ position: absolute;
+ content: ">";
+}
+#pma_console .query_input:before {
+ top: -2px;
+}
+#pma_console .message:hover:before {
+ color: #7cf;
+ font-weight: bold;
+}
+#pma_console .message.expanded:before {
+ content: "]";
+}
+#pma_console .message.welcome:before {
+ display: none;
+}
+#pma_console .message.failed:before,
+#pma_console .message.failed.expanded:before,
+#pma_console .message.failed:hover:before {
+ content: "=";
+ color: #944;
+}
+#pma_console .message.pending:before {
+ opacity: .3;
+}
+#pma_console .message.collapsed>.query {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+#pma_console .message.expanded>.query {
+ display: block;
+ white-space: pre;
+ word-wrap: break-word;
+}
+#pma_console .message .text.targetdb,
+#pma_console .message.collapsed .action.collapse,
+#pma_console .message.expanded .action.expand,
+#pma_console .message .action.requery,
+#pma_console .message .action.bookmark {
+ display: none;
+}
+#pma_console .message.history .text.targetdb,
+#pma_console .message.successed .text.targetdb,
+#pma_console .message.history .action.requery,
+#pma_console .message.history .action.bookmark,
+#pma_console .message.bookmark .action.requery,
+#pma_console .message.bookmark .action.bookmark,
+#pma_console .message.successed .action.requery,
+#pma_console .message.successed .action.bookmark {
+ display: inline-block;
+}
+#pma_console .message .action_content {
+ position: absolute;
+ bottom: 100%;
+ background: #ccc;
+ border: solid 1px #aaa;
+ border-top-<?php echo $left; ?>-radius: 3px;
+}
+html.ie8 #pma_console .message .action_content {
+ position: relative!important;
+}
+#pma_console .message.bookmark .text.targetdb,
+#pma_console .message .text.query_time {
+ margin: 0;
+ display: inline-block;
+}
+#pma_console .message.failed .text.query_time,
+#pma_console .message .text.failed {
+ display: none;
+}
+#pma_console .message.failed .text.failed {
+ display: inline-block;
+}
+#pma_console .message .text {
+ background: #fff;
+}
+#pma_console .message.collapsed:not(:hover) .action_content {
+ display: none;
+}
+#pma_console .message .bookmark_label {
+ padding: 0 4px;
+ top: 0;
+ background: #369;
+ color: #fff;
+ border-radius: 3px;
+}
+#pma_console .message .bookmark_label.shared {
+ background: #396;
+}
+#pma_console .message.expanded .bookmark_label {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+#pma_console .query_input {
+ position: relative;
+}
+#pma_console .mid_layer {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ top: 0;
+ /* For support IE8, this layer doesn't use filter:opacity or opacity,
+ js code will fade this layer opacity to 0.18(using animation) */
+ background: #666;
+ display: none;
+ cursor: pointer;
+ z-index: 200;
+}
+#pma_console .card {
+ position: absolute;
+ width: 94%;
+ height: 100%;
+ min-height: 48px;
+ <?php echo $left; ?>: 100%;
+ top: 0;
+ border-<?php echo $left; ?>: solid 1px #999;
+ z-index: 300;
+ transition: <?php echo $left; ?> 0.2s;
+ -ms-transition: <?php echo $left; ?> 0.2s;
+ -webkit-transition: <?php echo $left; ?> 0.2s;
+ -moz-transition: <?php echo $left; ?> 0.2s;
+}
+#pma_console .card.show {
+ <?php echo $left; ?>: 6%;
+ box-shadow: -2px 1px 4px -1px #999;
+}
+
+html.ie7 #pma_console .query_input {
+ display: none;
+}
+
+#pma_bookmarks .content.add_bookmark,
+#pma_console_options .content {
+ padding: 4px 6px;
+}
+#pma_bookmarks .content.add_bookmark input[type=text] {
+ margin: 0;
+ padding: 2px 4px;
+}
+
+/* Code mirror console style*/
+
+.cm-s-pma .CodeMirror-code pre,
+.cm-s-pma .CodeMirror-code {
+ font-family: Monaco, Consolas, monospace;
+}
+.cm-s-pma .CodeMirror-measure>pre,
+.cm-s-pma .CodeMirror-code>pre,
+.cm-s-pma .CodeMirror-lines {
+ padding: 0;
+}
+.cm-s-pma.CodeMirror {
+ resize: none;
+ height: auto;
+ width: 100%;
+ min-height: initial;
+ max-height: initial;
+}
+.cm-s-pma .CodeMirror-scroll {
+ padding-bottom: 2em;
+ cursor: text;
+}
diff --git a/themes/original/img/console.png b/themes/original/img/console.png
new file mode 100755
index 0000000000..94bae15eb5
--- /dev/null
+++ b/themes/original/img/console.png
Binary files differ
diff --git a/themes/pmahomme/css/common.css.php b/themes/pmahomme/css/common.css.php
index 8aab88e613..527e623429 100644
--- a/themes/pmahomme/css/common.css.php
+++ b/themes/pmahomme/css/common.css.php
@@ -2999,6 +2999,255 @@ table.show_create td {
position: fixed;
}
+
.small_font {
font-size: smaller;
}
+
+/* Console styles */
+#pma_console_container {
+ width: 100%;
+ position: fixed;
+ bottom: 0;
+ <?php echo $left; ?>: 0;
+ z-index: 100;
+}
+#pma_console {
+ position: relative;
+ margin-<?php echo $left; ?>: 240px;
+}
+#pma_console>.templates {
+ display: none;
+}
+#pma_console .mid_text,
+#pma_console .toolbar span {
+ vertical-align: middle;
+}
+#pma_console .toolbar {
+ position: relative;
+ background: #ccc;
+ border-top: solid 1px #aaa;
+ cursor: n-resize;
+}
+#pma_console .toolbar.collapsed:not(:hover) {
+ display: inline-block;
+ border-top-<?php echo $right; ?>-radius: 3px;
+ border-<?php echo $right; ?>: solid 1px #aaa;
+}
+#pma_console .toolbar.collapsed {
+ cursor: default;
+}
+#pma_console .toolbar.collapsed>.button {
+ display: none;
+}
+#pma_console .message span.text,
+#pma_console .message span.action,
+#pma_console .toolbar .button,
+#pma_console .switch_button {
+ padding: 0 3px;
+ display: inline-block;
+}
+#pma_console .message span.action,
+#pma_console .toolbar .button,
+#pma_console .switch_button {
+ cursor: pointer;
+}
+#pma_console .message span.action:hover,
+#pma_console .toolbar .button:hover,
+#pma_console .switch_button:hover {
+ background: #ddd;
+}
+#pma_console .toolbar .button {
+ margin-<?php echo $right; ?>: .4em;
+}
+#pma_console .toolbar .button {
+ float: <?php echo $right; ?>;
+}
+#pma_console .content {
+ overflow-x: hidden;
+ overflow-y: auto;
+ margin-bottom: -65px;
+ border-top: solid 1px #aaa;
+ background: #fff;
+ padding-top: .4em;
+}
+#pma_console .message,
+#pma_console .query_input {
+ position: relative;
+ font-family: Monaco, Consolas, monospace;
+ cursor: text;
+ margin: 0 10px .2em 1.4em;
+}
+#pma_console .message {
+ border-bottom: solid 1px #ccc;
+ padding-bottom: .2em;
+}
+#pma_console .message.expanded .action_content {
+ position: relative;
+}
+#pma_console .message:before,
+#pma_console .query_input:before {
+ left: -0.7em;
+ position: absolute;
+ content: ">";
+}
+#pma_console .query_input:before {
+ top: -2px;
+}
+#pma_console .message:hover:before {
+ color: #7cf;
+ font-weight: bold;
+}
+#pma_console .message.expanded:before {
+ content: "]";
+}
+#pma_console .message.welcome:before {
+ display: none;
+}
+#pma_console .message.failed:before,
+#pma_console .message.failed.expanded:before,
+#pma_console .message.failed:hover:before {
+ content: "=";
+ color: #944;
+}
+#pma_console .message.pending:before {
+ opacity: .3;
+}
+#pma_console .message.collapsed>.query {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+#pma_console .message.expanded>.query {
+ display: block;
+ white-space: pre;
+ word-wrap: break-word;
+}
+#pma_console .message .text.targetdb,
+#pma_console .message.collapsed .action.collapse,
+#pma_console .message.expanded .action.expand,
+#pma_console .message .action.requery,
+#pma_console .message .action.bookmark {
+ display: none;
+}
+#pma_console .message.history .text.targetdb,
+#pma_console .message.successed .text.targetdb,
+#pma_console .message.history .action.requery,
+#pma_console .message.history .action.bookmark,
+#pma_console .message.bookmark .action.requery,
+#pma_console .message.bookmark .action.bookmark,
+#pma_console .message.successed .action.requery,
+#pma_console .message.successed .action.bookmark {
+ display: inline-block;
+}
+#pma_console .message .action_content {
+ position: absolute;
+ bottom: 100%;
+ background: #ccc;
+ border: solid 1px #aaa;
+ border-top-<?php echo $left; ?>-radius: 3px;
+}
+html.ie8 #pma_console .message .action_content {
+ position: relative!important;
+}
+#pma_console .message.bookmark .text.targetdb,
+#pma_console .message .text.query_time {
+ margin: 0;
+ display: inline-block;
+}
+#pma_console .message.failed .text.query_time,
+#pma_console .message .text.failed {
+ display: none;
+}
+#pma_console .message.failed .text.failed {
+ display: inline-block;
+}
+#pma_console .message .text {
+ background: #fff;
+}
+#pma_console .message.collapsed:not(:hover) .action_content {
+ display: none;
+}
+#pma_console .message .bookmark_label {
+ padding: 0 4px;
+ top: 0;
+ background: #369;
+ color: #fff;
+ border-radius: 3px;
+}
+#pma_console .message .bookmark_label.shared {
+ background: #396;
+}
+#pma_console .message.expanded .bookmark_label {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+#pma_console .query_input {
+ position: relative;
+}
+#pma_console .mid_layer {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ top: 0;
+ /* For support IE8, this layer doesn't use filter:opacity or opacity,
+ js code will fade this layer opacity to 0.18(using animation) */
+ background: #666;
+ display: none;
+ cursor: pointer;
+ z-index: 200;
+}
+#pma_console .card {
+ position: absolute;
+ width: 94%;
+ height: 100%;
+ min-height: 48px;
+ <?php echo $left; ?>: 100%;
+ top: 0;
+ border-<?php echo $left; ?>: solid 1px #999;
+ z-index: 300;
+ transition: <?php echo $left; ?> 0.2s;
+ -ms-transition: <?php echo $left; ?> 0.2s;
+ -webkit-transition: <?php echo $left; ?> 0.2s;
+ -moz-transition: <?php echo $left; ?> 0.2s;
+}
+#pma_console .card.show {
+ <?php echo $left; ?>: 6%;
+ box-shadow: -2px 1px 4px -1px #999;
+}
+
+html.ie7 #pma_console .query_input {
+ display: none;
+}
+
+#pma_bookmarks .content.add_bookmark,
+#pma_console_options .content {
+ padding: 4px 6px;
+}
+#pma_bookmarks .content.add_bookmark input[type=text] {
+ margin: 0;
+ padding: 2px 4px;
+}
+
+/* Code mirror console style*/
+
+.cm-s-pma .CodeMirror-code pre,
+.cm-s-pma .CodeMirror-code {
+ font-family: Monaco, Consolas, monospace;
+}
+.cm-s-pma .CodeMirror-measure>pre,
+.cm-s-pma .CodeMirror-code>pre,
+.cm-s-pma .CodeMirror-lines {
+ padding: 0;
+}
+.cm-s-pma.CodeMirror {
+ resize: none;
+ height: auto;
+ width: 100%;
+ min-height: initial;
+ max-height: initial;
+}
+.cm-s-pma .CodeMirror-scroll {
+ padding-bottom: 2em;
+ cursor: text;
+}
diff --git a/themes/pmahomme/img/console.png b/themes/pmahomme/img/console.png
new file mode 100755
index 0000000000..94bae15eb5
--- /dev/null
+++ b/themes/pmahomme/img/console.png
Binary files differ
diff --git a/transformation_overview.php b/transformation_overview.php
index 119436e3c0..23a917c859 100644
--- a/transformation_overview.php
+++ b/transformation_overview.php
@@ -14,7 +14,7 @@ require_once './libraries/transformations.lib.php';
$response = PMA_Response::getInstance();
$header = $response->getHeader();
-$header->disableMenu();
+$header->disableMenuAndConsole();
$types = PMA_getAvailableMIMEtypes();
?>