File Editors: Introduce sandboxed live editing of PHP files with rollbacks for both themes and plugins.
* Edits to active plugins which cause PHP fatal errors will no longer auto-deactivate the plugin. Supersedes #39766.
* Introduce sandboxed PHP file edits for active themes, preventing accidental whitescreening of a user's site when introducing a fatal error.
* After writing a change to a PHP file for an active theme or plugin, perform loopback requests on the file editor admin screens and the homepage to check for fatal errors. If a fatal error is encountered, roll back the edited file and display the error to the user to fix and try again.
* Introduce a secure way to scrape PHP fatal errors from a site via `wp_start_scraping_edited_file_errors()` and `wp_finalize_scraping_edited_file_errors()`.
* Moves file modifications from `theme-editor.php` and `plugin-editor.php` to common `wp_edit_theme_plugin_file()` function.
* Refactor themes and plugin editors to submit file changes via Ajax instead of doing full page refreshes when JS is available.
* Use `get` method for theme/plugin dropdowns.
* Improve styling of plugin editors, including width of plugin/theme dropdowns.
* Improve notices API for theme/plugin editor JS component.
* Strip common base directory from plugin file list. See #24048.
* Factor out functions to list editable file types in `wp_get_theme_file_editable_extensions()` and `wp_get_plugin_file_editable_extensions()`.
* Scroll to line in editor that has linting error when attempting to save. See #41886.
* Add checkbox to dismiss lint errors to proceed with saving. See #41887.
* Only style the Update File button as disabled instead of actually disabling it for accessibility reasons.
* Ensure that value from CodeMirror is used instead of `textarea` when CodeMirror is present.
* Add "Are you sure?" check when leaving editor when there are unsaved changes.
Supersedes [41560].
See #39766, #24048, #41886.
Props westonruter, Clorith, melchoyce, johnbillion, jjj, jdgrimes, azaozz.
Fixes #21622, #41887.
Built from https://develop.svn.wordpress.org/trunk@41721
git-svn-id: http://core.svn.wordpress.org/trunk@41555 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2017-10-04 02:20:45 +02:00
|
|
|
window.wp||(window.wp={}),wp.themePluginEditor=function(a){"use strict";var b={l10n:{lintError:{singular:"",plural:""},saveAlert:""},codeEditor:{},instance:null,noticeElements:{},dirty:!1,lintErrors:[]};return b.init=function(c,d){b.form=c,d&&a.extend(b,d),b.noticeTemplate=wp.template("wp-file-editor-notice"),b.noticesContainer=b.form.find(".editor-notices"),b.submitButton=b.form.find(":input[name=submit]"),b.spinner=b.form.find(".submit .spinner"),b.form.on("submit",b.submit),b.textarea=b.form.find("#newcontent"),b.textarea.on("change",b.onChange),!1!==b.codeEditor&&_.defer(function(){b.initCodeEditor()}),a(window).on("beforeunload",function(){if(b.dirty)return b.l10n.saveAlert})},b.onChange=function(){b.dirty=!0,b.removeNotice("file_saved")},b.submit=function(c){var d,e={};if(c.preventDefault(),a.each(b.form.serializeArray(),function(){e[this.name]=this.value}),b.instance&&(e.newcontent=b.instance.codemirror.getValue()),!b.isSaving){if(b.lintErrors.length)return void b.instance.codemirror.setCursor(b.lintErrors[0].from.line);b.isSaving=!0,b.textarea.prop("readonly",!0),b.instance&&b.instance.codemirror.setOption("readOnly",!0),b.spinner.addClass("is-active"),d=wp.ajax.post("edit-theme-plugin-file",e),b.lastSaveNoticeCode&&b.removeNotice(b.lastSaveNoticeCode),d.done(function(a){b.lastSaveNoticeCode="file_saved",b.addNotice({code:b.lastSaveNoticeCode,type:"success",message:a.message,dismissible:!0}),b.dirty=!1}),d.fail(function(c){var d=a.extend({code:"save_error"},c,{type:"error",dismissible:!0});b.lastSaveNoticeCode=d.code,b.addNotice(d)}),d.always(function(){b.spinner.removeClass("is-active"),b.isSaving=!1,b.textarea.prop("readonly",!1),b.instance&&b.instance.codemirror.setOption("readOnly",!1)})}},b.addNotice=function(c){var d;if(!c.code)throw new Error("Missing code.");return b.removeNotice(c.code),d=a(b.noticeTemplate(c)),d.hide(),d.find(".notice-dismiss").on("click",function(){b.removeNotice(c.code),c.onDismiss&&c.onDismiss(c)}),wp.a11y.speak(c.message),b.noticesContainer.append(d),d.slideDown("fast"),b.noticeElements[c.code]=d,d},b.removeNotice=function(c){return!!b.noticeElements[c]&&(b.noticeElements[c].slideUp("fast",function(){a(this).remove()}),delete b.noticeElements[c],!0)},b.initCodeEditor=function(){var c,d;c=a.extend({},b.codeEditor),c.onTabPrevious=function(){a("#templateside").find(":tabbable").last().focus()},c.onTabNext=function(){a("#template").find(":tabbable:not(.CodeMirror-code)").first().focus()},c.onChangeLintingErrors=function(a){b.lintErrors=a,0===a.length&&b.submitButton.toggleClass("disabled",!1)},c.onUpdateErrorNotice=function(a){var d,e;b.submitButton.toggleClass("disabled",a.length>0),0!==a.length?(d=1===a.length?b.l10n.lintError.singular.replace("%d","1"):b.l10n.lintError.plural.replace("%d",String(a.length)),e=b.addNotice({code:"lint_errors",type:"error",message:d,dismissible:!1}),e.find("input[type=checkbox]").on("click",function(){c.onChangeLintingErrors([]),b.removeNotice("lint_errors")})):b.removeNotice("lint_errors")},d=wp.codeEditor.initialize(a("#newcontent"),c),d.codemirror.on("change",b.onChange),a(d.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":"theme-plugin-editor-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),a("#theme-plugin-editor-label").on("click",function(){d.codemirror.focus()}),b.instance=d},b}(jQuery);
|