Commit b9dbf07a authored by alain's avatar alain 🐙
Browse files

update plugins

parent fa69e04f
/***************************************
Tabs on the settings page
***************************************/
.wrap.ws-ame-too-many-tabs .ws-ame-nav-tab-list {
&.nav-tab-wrapper {
border-bottom-color: transparent;
}
.nav-tab {
border-bottom: 1px solid #c3c4c7;
margin-bottom: 10px;
margin-top: 0;
}
}
/* Spacing between the page heading and the tab list.
Normally, this is handled by .nav-tab styles, but WordPress changes the margins at smaller screen sizes
and the tabs end up without a left margin. Let's put that margin on the heading instead and remove it
from the first tab. */
#ws_ame_editor_heading {
margin-right: 0.305em;
}
.ws-ame-nav-tab-list {
a.nav-tab:first-of-type {
margin-left: 0;
}
}
/* When in "too many tabs" mode, there's too much space between the bottom of the tab list and the rest
of the page. I haven't found a good way to change the margins of just the last row, so here's a partial fix. */
.ws-ame-too-many-tabs #ws_actor_selector {
margin-top: 0;
}
\ No newline at end of file
......@@ -51,7 +51,8 @@ hr.ws-submenu-separator {
}
/* No colored bar/marker when hovering over a separator. */
#adminmenu li.ws-submenu-separator-wrap a:hover {
#adminmenu li.ws-submenu-separator-wrap a:hover,
#adminmenu li.ws-submenu-separator-wrap a:focus {
box-shadow: none;
}
......@@ -118,25 +119,3 @@ hr.ws-submenu-separator {
opacity: 1;
filter: alpha(opacity=100);
}
/*
* Third level menus.
*/
#adminmenu .ame-deep-submenu {
}
#adminmenu li.menu-top.opensub .ame-deep-submenu {
top: -1000em;
}
#adminmenu .wp-submenu li.opensub > ul.ame-deep-submenu {
top: -1px;
}
.folded #adminmenu li.opensub > ul.ame-deep-submenu,
.folded #adminmenu .wp-has-current-submenu.opensub > ul.ame-deep-submenu,
.no-js.folded #adminmenu .ame-has-deep-submenu:hover > ul.ame-deep-submenu {
top: 0;
left: 160px;
}
\ No newline at end of file
......@@ -740,7 +740,7 @@ a.ws_button.ws_button_disabled:hover {
width: 5px;
}
#ws_toggle_toolbar {
#ws_toggle_toolbar, .ws_toggle_toolbar_button {
margin-right: 0;
}
......@@ -1968,6 +1968,10 @@ $userSelectionPanelPadding: 10px;
vertical-align: bottom;
}
.ws_tooltip_trigger.ame-warning-tooltip {
color: orange;
}
.ws_wide_tooltip {
max-width: 450px;
}
......@@ -2256,4 +2260,6 @@ span.description {
padding: 8px;
}
@import "test-access-screen";
\ No newline at end of file
@import "test-access-screen";
@import "main-tabs";
\ No newline at end of file
......@@ -4,7 +4,7 @@ jQuery(function($) {
$submitButton = $importForm.find(':submit');
//Enable the "next" button when the user selects a file.
$importFile.change(function () {
$importFile.on('change', function () {
$submitButton.prop('disabled', !$importFile.val());
});
......
......@@ -178,6 +178,8 @@ class wsAmeImportExportFeature {
}
}
//todo: Consider adding some buffer space at the end to avoid truncation when other plugins add superfluous whitespace.
$data = $this->export_data();
$data['settings'] = array_intersect_key($data['settings'], $enabledOptions);
$json = json_encode($data);
......
......@@ -185,7 +185,7 @@ ko.bindingHandlers.ameColorPicker = {
if (newValue === '') {
//Programmatically click the "Clear" button. It's not elegant, but I haven't found
//a way to do this using the Iris API.
jQuery(element).closest('.wp-picker-input-wrap').find('.wp-picker-clear').click();
jQuery(element).closest('.wp-picker-input-wrap').find('.wp-picker-clear').trigger('click');
}
else {
jQuery(element).iris('color', newValue);
......
......@@ -231,7 +231,7 @@ ko.bindingHandlers.ameColorPicker = {
if (newValue === '') {
//Programmatically click the "Clear" button. It's not elegant, but I haven't found
//a way to do this using the Iris API.
jQuery(element).closest('.wp-picker-input-wrap').find('.wp-picker-clear').click();
jQuery(element).closest('.wp-picker-input-wrap').find('.wp-picker-clear').trigger('click');
} else {
jQuery(element).iris('color', newValue);
}
......
'use strict';
jQuery(function ($) {
const menuEditorNode = $('#ws_menu_editor');
$(document).on('filterMenuFields.adminMenuEditor', function (event, knownMenuFields, baseField) {
var scrollCheckboxField = $.extend({}, baseField, {
caption: 'Hide the frame scrollbar',
......@@ -48,79 +50,134 @@ jQuery(function ($) {
});
//The "Reset permissions" toolbar button.
$('#ws_reset_actor_permissions').on('click', function (event) {
event.preventDefault();
var selectedActor = AmeEditorApi.actorSelectorWidget.selectedActor;
if (selectedActor === null) {
alert(
'This button resets all permissions for the selected role. '
+ 'To use it, click a role and then click this button again.'
);
return;
}
var displayName = AmeEditorApi.actorSelectorWidget.selectedDisplayName;
if (!confirm('Reset all permissions for "' + displayName + '"?')) {
return;
}
//Reset CPT/taxonomy permissions and other directly granted capabilities.
var hadGrantedCaps = AmeCapabilityManager.resetActorCaps(selectedActor);
//Reset permissions and visibility for all menu items.
AmeEditorApi.forEachMenuItem(function (menuItem, containerNode) {
var wasModified = hadGrantedCaps;
//Reset the "hide without changing permissions" settings (aka "cosmetically hidden").
if (
menuItem.hidden_from_actor
&& $.isPlainObject(menuItem.hidden_from_actor)
&& menuItem.hidden_from_actor.hasOwnProperty(selectedActor)
) {
delete menuItem.hidden_from_actor[selectedActor];
wasModified = true;
menuEditorNode.on(
'adminMenuEditor:action-reset-permissions',
function (event) {
event.preventDefault();
var selectedActor = AmeEditorApi.actorSelectorWidget.selectedActor;
if (selectedActor === null) {
alert(
'This button resets all permissions for the selected role. '
+ 'To use it, click a role and then click this button again.'
);
return;
}
//Reset permissions.
if (
menuItem.grant_access
&& $.isPlainObject(menuItem.grant_access)
&& menuItem.grant_access.hasOwnProperty(selectedActor)
) {
delete menuItem.grant_access[selectedActor];
wasModified = true;
var displayName = AmeEditorApi.actorSelectorWidget.selectedDisplayName;
if (!confirm('Reset all permissions for "' + displayName + '"?')) {
return;
}
if (wasModified) {
AmeEditorApi.updateItemEditor(containerNode);
AmeEditorApi.updateParentAccessUi(containerNode);
}
});
});
//Reset CPT/taxonomy permissions and other directly granted capabilities.
var hadGrantedCaps = AmeCapabilityManager.resetActorCaps(selectedActor);
//Reset permissions and visibility for all menu items.
AmeEditorApi.forEachMenuItem(function (menuItem, containerNode) {
var wasModified = hadGrantedCaps;
//Reset the "hide without changing permissions" settings (aka "cosmetically hidden").
if (
menuItem.hidden_from_actor
&& $.isPlainObject(menuItem.hidden_from_actor)
&& menuItem.hidden_from_actor.hasOwnProperty(selectedActor)
) {
delete menuItem.hidden_from_actor[selectedActor];
wasModified = true;
}
//Reset permissions.
if (
menuItem.grant_access
&& $.isPlainObject(menuItem.grant_access)
&& menuItem.grant_access.hasOwnProperty(selectedActor)
) {
delete menuItem.grant_access[selectedActor];
wasModified = true;
}
if (wasModified) {
AmeEditorApi.updateItemEditor(containerNode);
AmeEditorApi.updateParentAccessUi(containerNode);
}
});
}
);
//"New heading" toolbar button.
let headingCount = 0;
$('#ws_new_heading').on('click', function (event) {
event.preventDefault();
headingCount++;
//The new menu starts out rather bare
const randomId = AmeEditorApi.randomMenuId('heading-');
let menu = $.extend(true, {}, wsEditorData.blankMenuItem, {
sub_type: 'heading',
menu_title: 'Heading ' + headingCount,
custom: true,
template_id: '',
css_class: 'menu-top ame-menu-heading-item',
file: randomId,
hookname: randomId,
access_level: 'read',
items: []
});
menuEditorNode.on(
'adminMenuEditor:action-new-heading',
/**
* @param event
* @param {JQuery|null} selectedItem
* @param {AmeEditorColumn} column
*/
function (event, selectedItem, column) {
headingCount++;
//The new menu starts out rather bare
const randomId = AmeEditorApi.randomMenuId('heading-');
let menu = $.extend(true, {}, wsEditorData.blankMenuItem, {
sub_type: 'heading',
menu_title: 'Heading ' + headingCount,
custom: true,
template_id: '',
css_class: 'menu-top ame-menu-heading-item',
file: randomId,
hookname: randomId,
access_level: 'read',
items: []
});
column.outputItem(menu, selectedItem);
$(document).trigger('adminMenuEditor:newHeadingCreated');
}
);
AmeEditorApi.insertMenu(menu);
//Three level menu confirmation dialog.
let $deepNestingDialog;
function initNestingDialog() {
if ($deepNestingDialog) {
return;
}
$(document).trigger('adminMenuEditor:newHeadingCreated');
});
$deepNestingDialog = $('#ws_ame_deep_nesting_dialog');
$deepNestingDialog.dialog({
autoOpen: false,
closeText: ' ',
draggable: false,
modal: true,
minHeight: 300,
minWidth: 400
});
}
menuEditorNode.on(
'adminMenuEditor:queryDeepNesting',
/**
* @param event
* @param {Array} queue
*/
function(event, queue) {
let isEnabled = $.Deferred();
queue.push(isEnabled);
initNestingDialog();
$deepNestingDialog.dialog('open');
$deepNestingDialog.find('#ame_allow_deep_nesting').one('click', function() {
isEnabled.resolve();
$deepNestingDialog.dialog('close');
return false;
});
$deepNestingDialog.find('#ame_reject_deep_nesting').one('click', function() {
isEnabled.reject();
$deepNestingDialog.dialog('close');
return false;
});
}
);
});
\ No newline at end of file
......@@ -214,6 +214,11 @@ class ameMenuHeadingStyler {
['&.ame-collapsible-heading a'],
['cursor' => 'pointer']
),
//Remove the colored bar from item unless the heading is clickable.
$this->makeCssRule(
['&:not(.ame-collapsible-heading) a'],
['box-shadow' => 'none']
),
];
//Some rules might be empty if we have no custom settings for their properties,
......
......@@ -374,7 +374,6 @@ class ameWidgetCollection {
'Cannot decompress dashboard widget data. This site may be missing the Zlib extension.'
);
}
/** @noinspection PhpComposerExtensionStubsInspection */
$data = gzuncompress($data);
}
......
......@@ -24,7 +24,7 @@ class ameWidgetEditor extends ameModule implements ameExportableModule {
return;
}
add_action('wp_dashboard_setup', array($this, 'setupDashboard'), 200);
add_action('wp_dashboard_setup', array($this, 'setupDashboard'), 20000);
add_action('admin_menu_editor-header', array($this, 'handleFormSubmission'), 10, 2);
......@@ -107,7 +107,7 @@ class ameWidgetEditor extends ameModule implements ameExportableModule {
plugins_url('dashboard-widget-editor.js', __FILE__),
array(
'ame-lodash', 'ame-dashboard-widget', 'knockout', 'ame-actor-selector',
'ame-jquery-form', 'jquery-ui-dialog', 'jquery-json', 'ame-ko-extensions',
'ame-jquery-form', 'jquery-ui-dialog', 'ame-ko-extensions',
)
);
......
......@@ -125,7 +125,7 @@ var AmeDashboardWidgetEditor = /** @class */ (function () {
AmeDashboardWidgetEditor.prototype.saveChanges = function () {
var settings = this.getCurrentSettings();
//Set the hidden form fields.
this.widgetData(jQuery.toJSON(settings));
this.widgetData(JSON.stringify(settings));
this.widgetDataLength(this.widgetData().length);
//Submit the form.
return true;
......@@ -158,7 +158,7 @@ var AmeDashboardWidgetEditor = /** @class */ (function () {
var _this = this;
//Temporarily disable the export button to prevent accidental repeated clicks.
this.isExportButtonEnabled(false);
this.widgetData(jQuery.toJSON(this.getCurrentSettings()));
this.widgetData(JSON.stringify(this.getCurrentSettings()));
//Re-enable the export button after a few seconds.
window.setTimeout(function () {
_this.isExportButtonEnabled(true);
......@@ -246,7 +246,7 @@ var AmeDashboardWidgetEditor = /** @class */ (function () {
handleUnexpectedImportError(xhr, errorMessage);
}
});
this.importDialog.find('#ame-cancel-widget-import').click(function () {
this.importDialog.find('#ame-cancel-widget-import').on('click', function () {
_this.importDialog.dialog('close');
});
};
......
......@@ -190,7 +190,7 @@ class AmeDashboardWidgetEditor {
let settings = this.getCurrentSettings();
//Set the hidden form fields.
this.widgetData(jQuery.toJSON(settings));
this.widgetData(JSON.stringify(settings));
this.widgetDataLength(this.widgetData().length);
//Submit the form.
......@@ -229,7 +229,7 @@ class AmeDashboardWidgetEditor {
//Temporarily disable the export button to prevent accidental repeated clicks.
this.isExportButtonEnabled(false);
this.widgetData(jQuery.toJSON(this.getCurrentSettings()));
this.widgetData(JSON.stringify(this.getCurrentSettings()));
//Re-enable the export button after a few seconds.
window.setTimeout(() => {
......@@ -334,7 +334,7 @@ class AmeDashboardWidgetEditor {
}
});
this.importDialog.find('#ame-cancel-widget-import').click(() => {
this.importDialog.find('#ame-cancel-widget-import').on('click', () => {
this.importDialog.dialog('close');
});
}
......
......@@ -10,6 +10,8 @@ var __extends = (this && this.__extends) || (function () {
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
......
......@@ -62,6 +62,13 @@ class ameMetaBoxCollection {
continue;
}
//Skip boxes that have an invalid ID. The ID must be a string.
//This is a workaround for plugins that set the ID to null or another unsupported value.
//Example: "Amazon Simple Affiliate (ASA2)", version 1.15.3.
if (!is_string($metaBox['id'])) {
continue;
}
$properties = array_merge(
array(
'context' => $context,
......
......@@ -20,6 +20,8 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
private $shouldRefreshMetaBoxes = false;
private $hiddenBoxCache = array();
private $areSettingsCorrupted = false;
public function __construct($menuEditor) {
parent::__construct($menuEditor);
......@@ -84,7 +86,7 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
global $wp_meta_boxes;
$currentScreen = get_current_screen();
if ( empty($currentScreen) ) {
if ( empty($currentScreen) || $this->areSettingsCorrupted ) {
return;
}
......@@ -143,7 +145,7 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
* @return array
*/
public function filterDefaultHiddenBoxes($hidden, $screen) {
if ( empty($screen) || !($screen instanceof WP_Screen) ) {
if ( empty($screen) || !($screen instanceof WP_Screen) || $this->areSettingsCorrupted ) {
return $hidden;
}
if ( isset($this->hiddenBoxCache[$screen->id]) ) {
......@@ -207,7 +209,11 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
* @param WP_Screen $screen
*/
public function processPostTypeFeatures($screen = null) {
if ( !isset($screen, $screen->post_type, $screen->id) || empty($screen->post_type) ) {
if (
!isset($screen, $screen->post_type, $screen->id)
|| empty($screen->post_type)
|| $this->areSettingsCorrupted
) {
return;
}
//Scan only the "Add Item" and "Edit Item" screens.
......@@ -256,17 +262,40 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
return $this->settings;
}
/** @noinspection PhpRedundantOptionalArgumentInspection The default value could change, so make it explicit. */
$json = $this->getScopedOption(self::OPTION_NAME, null);
if ( empty($json) ) {
$this->settings = new ameMetaBoxSettings();
} else {
$this->settings = ameMetaBoxSettings::fromJSON($json);
try {
$this->settings = ameMetaBoxSettings::fromJSON($json);
} catch (ameInvalidJsonException $ex) {
$this->areSettingsCorrupted = true;
$this->settings = new ameMetaBoxSettings();
if ( is_admin() && is_user_logged_in() && !did_action('all_admin_notices') ) {
add_action('all_admin_notices', array($this, 'showSettingsCorruptionError'));
}
}
}
return $this->settings;
}
public function showSettingsCorruptionError() {
if ( !$this->userCanEditMetaBoxes() ) {
return;
}
printf(
'<div class="notice notice-error"><p>%s</p></div>',
'<strong>Admin Menu Editor Pro error: Cannot load meta box settings. The data might be corrupted.</strong><br> '
. sprintf(
'If you have recently migrated this site to a new server, try restoring the <code>%s</code> option from backup.',
esc_html(self::OPTION_NAME)
)
);
}
public function exportSettings() {
$this->loadSettings();
if ( $this->settings->isEmpty() ) {
......@@ -332,7 +361,7 @@ class ameMetaBoxEditor extends ameModule implements ameExportableModule {
'post_status' => null,
'post_parent' => 'any',
));
if ( $attachments && !empty($attachments) ) {
if ( !empty($attachments) ) {
$firstAttachment = reset($attachments);