diff --git a/ChangeLog b/ChangeLog index a9cffd1ff7..27aaed3c0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -85,6 +85,10 @@ phpMyAdmin - ChangeLog - issue #15566 Support RTL mode on the Designer - issue #16810 Fixed SQL query shown twice on drop column success - issue #16404 Fixed JS password generation fails after a new user creation failure +- issue #16837 Fixed PHP error on execute query "create table event(...)" +- issue Fixed a PHP warning that was occuring on wrong chmod on config files +- issue Fixed a JS error on dismiss notification modal +- issue #16793 Upgrade CodeMirror to 5.61.0 to fix a JS error on scroll in SQL query box 5.1.0 (2021-02-24) - issue #15350 Change Media (MIME) type references to Media type diff --git a/js/src/functions.js b/js/src/functions.js index 14155dfba7..3246319c80 100644 --- a/js/src/functions.js +++ b/js/src/functions.js @@ -2421,7 +2421,7 @@ $(function () { }, 250); }); - $(document).on('mouseup', 'span.ajax_notification.dismissable', function () { + $(document).on('mouseup', 'span.ajax_notification.dismissable', function (event) { if (holdStarter && event.which === 1) { clearTimeout(holdStarter); Functions.ajaxRemoveMessage($(this)); diff --git a/js/src/server/status/monitor.js b/js/src/server/status/monitor.js index 89143ed1b2..a490b6a5e2 100644 --- a/js/src/server/status/monitor.js +++ b/js/src/server/status/monitor.js @@ -1103,7 +1103,7 @@ AJAX.registerOnload('server/status/monitor.js', function () { initGrid(); } - /* Calculactes the dynamic chart size that depends on the column width */ + /* Calculates the dynamic chart size that depends on the column width */ function calculateChartSize () { var panelWidth; if ($('body').height() > $(window).height()) { // has vertical scroll bar diff --git a/js/vendor/codemirror/addon/hint/show-hint.js b/js/vendor/codemirror/addon/hint/show-hint.js index bfe7d3a353..8f236562b7 100644 --- a/js/vendor/codemirror/addon/hint/show-hint.js +++ b/js/vendor/codemirror/addon/hint/show-hint.js @@ -293,6 +293,7 @@ } } var overlapX = box.right - winW; + if (scrolls) overlapX += cm.display.nativeBarWidth; if (overlapX > 0) { if (box.right - box.left > winW) { hints.style.width = (winW - 5) + "px"; @@ -321,6 +322,7 @@ cm.on("scroll", this.onScroll = function() { var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); + if (!startScroll) startScroll = cm.getScrollInfo(); var newTop = top + startScroll.top - curScroll.top; var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop); if (!below) point += hints.offsetHeight; diff --git a/js/vendor/codemirror/addon/runmode/runmode.js b/js/vendor/codemirror/addon/runmode/runmode.js index 2cae68635d..f5d58e2428 100644 --- a/js/vendor/codemirror/addon/runmode/runmode.js +++ b/js/vendor/codemirror/addon/runmode/runmode.js @@ -67,7 +67,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) { if (!stream.string && mode.blankLine) mode.blankLine(state); while (!stream.eol()) { var style = mode.token(stream, state); - callback(stream.current(), style, i, stream.start, state); + callback(stream.current(), style, i, stream.start, state, mode); stream.start = stream.pos; } } diff --git a/js/vendor/codemirror/lib/codemirror.js b/js/vendor/codemirror/lib/codemirror.js index 055963b048..be9290f0f9 100644 --- a/js/vendor/codemirror/lib/codemirror.js +++ b/js/vendor/codemirror/lib/codemirror.js @@ -2186,6 +2186,7 @@ if (cm.options.lineNumbers || markers) { var wrap$1 = ensureLineWrapped(lineView); var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); + gutterWrap.setAttribute("aria-hidden", "true"); cm.display.input.setUneditable(gutterWrap); wrap$1.insertBefore(gutterWrap, lineView.text); if (lineView.line.gutterClass) @@ -4235,6 +4236,8 @@ function updateGutterSpace(display) { var width = display.gutters.offsetWidth; display.sizer.style.marginLeft = width + "px"; + // Send an event to consumers responding to changes in gutter width. + signalLater(display, "gutterChanged", display); } function setDocumentHeight(cm, measure) { @@ -6684,10 +6687,9 @@ // Very basic readline/emacs-style bindings, which are standard on Mac. keyMap.emacsy = { "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", - "Ctrl-O": "openLine" + "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", + "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", + "Ctrl-T": "transposeChars", "Ctrl-O": "openLine" }; keyMap.macDefault = { "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", @@ -8833,7 +8835,7 @@ var kludge = hiddenTextarea(), te = kludge.firstChild; cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); te.value = lastCopied.text.join("\n"); - var hadFocus = document.activeElement; + var hadFocus = activeElt(); selectInput(te); setTimeout(function () { cm.display.lineSpace.removeChild(kludge); @@ -8856,7 +8858,7 @@ ContentEditableInput.prototype.prepareSelection = function () { var result = prepareSelection(this.cm, false); - result.focus = document.activeElement == this.div; + result.focus = activeElt() == this.div; return result }; @@ -8952,7 +8954,7 @@ ContentEditableInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor") { - if (!this.selectionInEditor() || document.activeElement != this.div) + if (!this.selectionInEditor() || activeElt() != this.div) { this.showSelection(this.prepareSelection(), true); } this.div.focus(); } @@ -9794,7 +9796,7 @@ addLegacyProps(CodeMirror); - CodeMirror.version = "5.60.0"; + CodeMirror.version = "5.61.0"; return CodeMirror; diff --git a/js/vendor/codemirror/mode/javascript/javascript.js b/js/vendor/codemirror/mode/javascript/javascript.js index a42f23d07f..f9fb4ec1f7 100644 --- a/js/vendor/codemirror/mode/javascript/javascript.js +++ b/js/vendor/codemirror/mode/javascript/javascript.js @@ -16,6 +16,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var statementIndent = parserConfig.statementIndent; var jsonldMode = parserConfig.jsonld; var jsonMode = parserConfig.json || jsonldMode; + var trackScope = parserConfig.trackScope !== false var isTS = parserConfig.typescript; var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; @@ -231,6 +232,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } function inScope(state, varname) { + if (!trackScope) return false for (var v = state.localVars; v; v = v.next) if (v.name == varname) return true; for (var cx = state.context; cx; cx = cx.prev) { @@ -277,6 +279,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function register(varname) { var state = cx.state; cx.marked = "def"; + if (!trackScope) return if (state.context) { if (state.lexical.info == "var" && state.context && state.context.block) { // FIXME function decls are also not block scoped @@ -376,7 +379,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); } if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); + if (type == "for") return cont(pushlex("form"), pushblockcontext, forspec, statement, popcontext, poplex); if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword" return cont(pushlex("form", type == "class" ? type : value), className, poplex) @@ -883,7 +886,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { var c = state.cc[i]; if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; + else if (c != maybeelse && c != popcontext) break; } while ((lexical.type == "stat" || lexical.type == "form") && (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) && diff --git a/libraries/classes/Template.php b/libraries/classes/Template.php index 34d4bb6d22..cecf54e07f 100644 --- a/libraries/classes/Template.php +++ b/libraries/classes/Template.php @@ -29,6 +29,7 @@ use Twig\Loader\FilesystemLoader; use Twig\RuntimeLoader\ContainerRuntimeLoader; use Twig\TemplateWrapper; +use function is_array; use function sprintf; use function trigger_error; @@ -78,7 +79,7 @@ class Template $twig->addRuntimeLoader(new ContainerRuntimeLoader($containerBuilder)); - if ($cfg['environment'] === 'development') { + if (is_array($cfg) && $cfg['environment'] === 'development') { $twig->enableDebug(); $twig->addExtension(new DebugExtension()); // This will enable debug for the extension to print lines diff --git a/libraries/classes/Tracker.php b/libraries/classes/Tracker.php index 39b03cc3ed..bb604baa9a 100644 --- a/libraries/classes/Tracker.php +++ b/libraries/classes/Tracker.php @@ -537,7 +537,7 @@ class Tracker * * @static */ - public static function getVersion($dbname, $tablename, $statement = null) + public static function getVersion(string $dbname, string $tablename, ?string $statement = null) { global $dbi; @@ -747,13 +747,13 @@ class Tracker if ($options[6] === 'VIEW' || $options[6] === 'TABLE') { $result['identifier'] = 'CREATE ' . $options[6]; - $result['tablename'] = $statement->name->table; + $result['tablename'] = $statement->name !== null ? $statement->name->table : null; } elseif ($options[6] === 'DATABASE') { $result['identifier'] = 'CREATE DATABASE'; $result['tablename'] = ''; // In case of CREATE DATABASE, database field of the CreateStatement is the name of the database - $GLOBALS['db'] = $statement->name->database; + $GLOBALS['db'] = $statement->name !== null ? $statement->name->database : null; } elseif ( $options[6] === 'INDEX' || $options[6] === 'UNIQUE INDEX' @@ -880,6 +880,12 @@ class Tracker return; } + // The table name was not found, see issue: #16837 as an example + // Also checks if the value is not null + if (! isset($result['tablename'])) { + return; + } + $version = self::getVersion( $dbname, $result['tablename'], diff --git a/package.json b/package.json index 801618402d..7f473c85ff 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@popperjs/core": "^2.9.1", "autoprefixer": "^10.2.5", "bootstrap": "5.0.0-beta3", - "codemirror": "5.60.0", + "codemirror": "5.61.0", "jquery": "3.6.0", "jquery-debounce-throttle": "^1.0.6-rc.0", "jquery-migrate": "3.3.2", diff --git a/test/classes/TrackerTest.php b/test/classes/TrackerTest.php index f85c19dc65..b4854820b1 100644 --- a/test/classes/TrackerTest.php +++ b/test/classes/TrackerTest.php @@ -676,12 +676,12 @@ class TrackerTest extends AbstractTestCase /** * Test for Tracker::parseQuery * - * @param string $query Query to parse - * @param string $type Expected type - * @param string $identifier Expected identifier - * @param string $tablename Expected tablename - * @param string $db Expected dbname - * @param string $tablename_after_rename Expected name after rename + * @param string $query Query to parse + * @param string $type Expected type + * @param string $identifier Expected identifier + * @param string|null $tablename Expected tablename + * @param string|null $db Expected dbname + * @param string|null $tablename_after_rename Expected name after rename * * @dataProvider parseQueryData */ @@ -689,7 +689,7 @@ class TrackerTest extends AbstractTestCase string $query, string $type, string $identifier, - string $tablename, + ?string $tablename, ?string $db = null, ?string $tablename_after_rename = null ): void { @@ -734,6 +734,12 @@ class TrackerTest extends AbstractTestCase */ public function parseQueryData(): array { + // query + // type + // identifier + // table name + // db (optional) + // table name after rename (optional) $query = []; /** TODO: Should test fail when USE is in conjunction with * identifiers? $query[] = array( @@ -868,6 +874,22 @@ class TrackerTest extends AbstractTestCase 'TRUNCATE', 't1', ]; + $query[] = [ + 'create table event(' . "\n" + . 'eventID varchar(10) not null,' . "\n" + . 'b char(30),' . "\n" + . 'c varchar(20),' . "\n" + . 'd TIME,' . "\n" + . 'e Date,' . "\n" + . 'f int,' . "\n" + . 'g char(70),' . "\n" + . 'h char(90),' . "\n" + . 'primary key(eventID)' . "\n" + . ')' . "\n", + 'DDL', + 'CREATE TABLE', + null,// switch this to 'event' when sql-parse is fixed + ]; return $query; } diff --git a/yarn.lock b/yarn.lock index 743d9d5089..d1cbfac90d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2448,10 +2448,10 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -codemirror@5.60.0: - version "5.60.0" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.60.0.tgz#00a8cfd287d5d8737ceb73987f04aee2fe5860da" - integrity sha512-AEL7LhFOlxPlCL8IdTcJDblJm8yrAGib7I+DErJPdZd4l6imx8IMgKK3RblVgBQqz3TZJR4oknQ03bz+uNjBYA== +codemirror@5.61.0: + version "5.61.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.61.0.tgz#318e5b034a707207948b92ffc2862195e8fdb08e" + integrity sha512-D3wYH90tYY1BsKlUe0oNj2JAhQ9TepkD51auk3N7q+4uz7A/cgJ5JsWHreT0PqieW1QhOuqxQ2reCXV1YXzecg== collect-v8-coverage@^1.0.0: version "1.0.1"