Version Description
- Added the ability to edit more plugin details like author name, site URL and version number. Note that this feature only changes how plugins are displayed. It doesn't actually modify plugin files.
- Fixed a PHP deprecation notice: "strpos(): Non-string needles will be interpreted as strings in the future". Hopefully this time it's been fixed for good.
- Fixed a couple of HTML validation errors.
- Fixed an inefficiency where the plugin would reinitialise the media frame every time the user tried to select an image from the media library.
- Added a partial workaround for situations where menu icons that were more than 32 pixels wide would be displayed incorrectly.
- Tested up to WP 5.1.1.
Download this release
Release Info
Developer | whiteshadow |
Plugin | Admin Menu Editor |
Version | 1.8.8 |
Comparing to | |
See all releases |
Code changes from version 1.8.7 to 1.8.8
- css/admin.css +1 -0
- includes/shadow_plugin_framework.php +9 -1
- js/actor-manager.js +1 -2
- js/menu-editor.js +18 -11
- menu-editor.php +1 -1
- modules/actor-selector/actor-selector.js +0 -1
- modules/plugin-visibility/plugin-visibility-template.php +25 -2
- modules/plugin-visibility/plugin-visibility.css +9 -2
- modules/plugin-visibility/plugin-visibility.js +33 -25
- modules/plugin-visibility/plugin-visibility.php +20 -12
- modules/plugin-visibility/plugin-visibility.scss +13 -2
- modules/plugin-visibility/plugin-visibility.ts +58 -42
- readme.txt +10 -2
css/admin.css
CHANGED
@@ -91,6 +91,7 @@ hr.ws-submenu-separator {
|
|
91 |
|
92 |
#adminmenu .ame-submenu-icon img {
|
93 |
padding-top: 2px;
|
|
|
94 |
|
95 |
opacity: 0.6;
|
96 |
filter: alpha(opacity=60);
|
91 |
|
92 |
#adminmenu .ame-submenu-icon img {
|
93 |
padding-top: 2px;
|
94 |
+
max-width: 32px;
|
95 |
|
96 |
opacity: 0.6;
|
97 |
filter: alpha(opacity=60);
|
includes/shadow_plugin_framework.php
CHANGED
@@ -318,10 +318,18 @@ class MenuEd_ShadowPluginFramework {
|
|
318 |
$normalizedFileName = realpath($filename);
|
319 |
|
320 |
//If realpath() fails, just normalize the syntax instead.
|
321 |
-
if ( empty($normalizedFileName) || empty($
|
322 |
$normalizedMuPluginDir = wp_normalize_path(WPMU_PLUGIN_DIR);
|
323 |
$normalizedFileName = wp_normalize_path($filename);
|
324 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
return (strpos( $normalizedFileName, $normalizedMuPluginDir ) !== false);
|
326 |
}
|
327 |
|
318 |
$normalizedFileName = realpath($filename);
|
319 |
|
320 |
//If realpath() fails, just normalize the syntax instead.
|
321 |
+
if ( empty($normalizedFileName) || empty($normalizedMuPluginDir) ) {
|
322 |
$normalizedMuPluginDir = wp_normalize_path(WPMU_PLUGIN_DIR);
|
323 |
$normalizedFileName = wp_normalize_path($filename);
|
324 |
}
|
325 |
+
//Yet another fallback if the above also fails.
|
326 |
+
if ( !is_string($normalizedMuPluginDir) || empty($normalizedMuPluginDir) ) {
|
327 |
+
if ( is_string(WPMU_PLUGIN_DIR) ) {
|
328 |
+
$normalizedMuPluginDir = WPMU_PLUGIN_DIR;
|
329 |
+
} else {
|
330 |
+
return false;
|
331 |
+
}
|
332 |
+
}
|
333 |
return (strpos( $normalizedFileName, $normalizedMuPluginDir ) !== false);
|
334 |
}
|
335 |
|
js/actor-manager.js
CHANGED
@@ -6,7 +6,7 @@ var __extends = (this && this.__extends) || (function () {
|
|
6 |
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
7 |
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
8 |
return extendStatics(d, b);
|
9 |
-
}
|
10 |
return function (d, b) {
|
11 |
extendStatics(d, b);
|
12 |
function __() { this.constructor = d; }
|
@@ -502,4 +502,3 @@ if (typeof wsAmeActorData !== 'undefined') {
|
|
502 |
AmeActors.generateCapabilitySuggestions(wsAmeActorData['capPower']);
|
503 |
}
|
504 |
}
|
505 |
-
//# sourceMappingURL=actor-manager.js.map
|
6 |
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
7 |
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
8 |
return extendStatics(d, b);
|
9 |
+
};
|
10 |
return function (d, b) {
|
11 |
extendStatics(d, b);
|
12 |
function __() { this.constructor = d; }
|
502 |
AmeActors.generateCapabilitySuggestions(wsAmeActorData['capPower']);
|
503 |
}
|
504 |
}
|
|
js/menu-editor.js
CHANGED
@@ -1074,7 +1074,7 @@ function buildEditboxField(entry, field_name, field_settings){
|
|
1074 |
case 'icon_selector':
|
1075 |
//noinspection HtmlUnknownTag
|
1076 |
inputBox = $(basicTextField)
|
1077 |
-
.add('<button class="button ws_select_icon" title="Select icon"><div class="icon16 icon-settings"></div><img src="" style="display:none;"></button>');
|
1078 |
break;
|
1079 |
|
1080 |
case 'color_scheme_editor':
|
@@ -1129,7 +1129,7 @@ function buildEditboxField(entry, field_name, field_settings){
|
|
1129 |
|
1130 |
editField
|
1131 |
.append(
|
1132 |
-
$('<img class="ws_reset_button" title="Reset to default value" src="">')
|
1133 |
.attr('src', wsEditorData.imagesUrl + '/transparent16.png')
|
1134 |
).data('field_name', field_name);
|
1135 |
|
@@ -2877,9 +2877,9 @@ function ameOnDomReady() {
|
|
2877 |
|
2878 |
//Alternatively, use the WordPress media uploader to select a custom icon.
|
2879 |
//This code is based on the header selection script in /wp-admin/js/custom-header.js.
|
|
|
2880 |
$('#ws_choose_icon_from_media').click(function(event) {
|
2881 |
event.preventDefault();
|
2882 |
-
var frame = null;
|
2883 |
|
2884 |
//This option is not usable on the demo site since the filesystem is usually read-only.
|
2885 |
if (wsEditorData.isDemoMode) {
|
@@ -2888,13 +2888,13 @@ function ameOnDomReady() {
|
|
2888 |
}
|
2889 |
|
2890 |
//If the media frame already exists, reopen it.
|
2891 |
-
if (
|
2892 |
-
|
2893 |
return;
|
2894 |
}
|
2895 |
|
2896 |
//Create a custom media frame.
|
2897 |
-
|
2898 |
//Set the title of the modal.
|
2899 |
title: 'Choose a Custom Icon (20x20)',
|
2900 |
|
@@ -2911,9 +2911,9 @@ function ameOnDomReady() {
|
|
2911 |
});
|
2912 |
|
2913 |
//When an image is selected, set it as the menu icon.
|
2914 |
-
|
2915 |
//Grab the selected attachment.
|
2916 |
-
var attachment =
|
2917 |
//TODO: Warn the user if the image exceeds 20x20 pixels.
|
2918 |
|
2919 |
//Set the menu icon to the attachment URL.
|
@@ -2935,11 +2935,11 @@ function ameOnDomReady() {
|
|
2935 |
});
|
2936 |
|
2937 |
//If the user closes the frame by via Esc or the "X" button, clear up state.
|
2938 |
-
|
2939 |
currentIconButton = null;
|
2940 |
});
|
2941 |
|
2942 |
-
|
2943 |
iconSelector.hide();
|
2944 |
});
|
2945 |
|
@@ -4321,6 +4321,13 @@ function ameOnDomReady() {
|
|
4321 |
}
|
4322 |
});
|
4323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4324 |
$('#ws_toggle_editor_layout').click(function () {
|
4325 |
var isCompactLayoutEnabled = menuEditorNode.toggleClass('ws_compact_layout').hasClass('ws_compact_layout');
|
4326 |
$.cookie('ame-compact-layout', isCompactLayoutEnabled ? '1' : '0', {expires: 90});
|
@@ -4938,7 +4945,7 @@ function ameOnDomReady() {
|
|
4938 |
},
|
4939 |
method: 'post',
|
4940 |
dataType: 'json',
|
4941 |
-
success: function(response
|
4942 |
if (!response) {
|
4943 |
alert('Error: Could not parse the server response.');
|
4944 |
testAccessButton.prop('disabled', false);
|
1074 |
case 'icon_selector':
|
1075 |
//noinspection HtmlUnknownTag
|
1076 |
inputBox = $(basicTextField)
|
1077 |
+
.add('<button class="button ws_select_icon" title="Select icon"><div class="icon16 icon-settings"></div><img src="" style="display:none;" alt="Icon"></button>');
|
1078 |
break;
|
1079 |
|
1080 |
case 'color_scheme_editor':
|
1129 |
|
1130 |
editField
|
1131 |
.append(
|
1132 |
+
$('<img class="ws_reset_button" title="Reset to default value" src="" alt="Reset">')
|
1133 |
.attr('src', wsEditorData.imagesUrl + '/transparent16.png')
|
1134 |
).data('field_name', field_name);
|
1135 |
|
2877 |
|
2878 |
//Alternatively, use the WordPress media uploader to select a custom icon.
|
2879 |
//This code is based on the header selection script in /wp-admin/js/custom-header.js.
|
2880 |
+
var mediaFrame = null;
|
2881 |
$('#ws_choose_icon_from_media').click(function(event) {
|
2882 |
event.preventDefault();
|
|
|
2883 |
|
2884 |
//This option is not usable on the demo site since the filesystem is usually read-only.
|
2885 |
if (wsEditorData.isDemoMode) {
|
2888 |
}
|
2889 |
|
2890 |
//If the media frame already exists, reopen it.
|
2891 |
+
if ( mediaFrame !== null ) {
|
2892 |
+
mediaFrame.open();
|
2893 |
return;
|
2894 |
}
|
2895 |
|
2896 |
//Create a custom media frame.
|
2897 |
+
mediaFrame = wp.media.frames.customAdminMenuIcon = wp.media({
|
2898 |
//Set the title of the modal.
|
2899 |
title: 'Choose a Custom Icon (20x20)',
|
2900 |
|
2911 |
});
|
2912 |
|
2913 |
//When an image is selected, set it as the menu icon.
|
2914 |
+
mediaFrame.on( 'select', function() {
|
2915 |
//Grab the selected attachment.
|
2916 |
+
var attachment = mediaFrame.state().get('selection').first();
|
2917 |
//TODO: Warn the user if the image exceeds 20x20 pixels.
|
2918 |
|
2919 |
//Set the menu icon to the attachment URL.
|
2935 |
});
|
2936 |
|
2937 |
//If the user closes the frame by via Esc or the "X" button, clear up state.
|
2938 |
+
mediaFrame.on('escape', function(){
|
2939 |
currentIconButton = null;
|
2940 |
});
|
2941 |
|
2942 |
+
mediaFrame.open();
|
2943 |
iconSelector.hide();
|
2944 |
});
|
2945 |
|
4321 |
}
|
4322 |
});
|
4323 |
|
4324 |
+
//Enable the "load default menu" and "undo changes" buttons only when "All" is selected.
|
4325 |
+
//Otherwise some users incorrectly assume these buttons only affect the currently selected role or user.
|
4326 |
+
actorSelectorWidget.onChange(function (newSelectedActor) {
|
4327 |
+
$('#ws_load_menu, #ws_reset_menu').prop('disabled', newSelectedActor !== null);
|
4328 |
+
});
|
4329 |
+
$('#ws_load_menu, #ws_reset_menu').prop('disabled', actorSelectorWidget.selectedActor !== null);
|
4330 |
+
|
4331 |
$('#ws_toggle_editor_layout').click(function () {
|
4332 |
var isCompactLayoutEnabled = menuEditorNode.toggleClass('ws_compact_layout').hasClass('ws_compact_layout');
|
4333 |
$.cookie('ame-compact-layout', isCompactLayoutEnabled ? '1' : '0', {expires: 90});
|
4945 |
},
|
4946 |
method: 'post',
|
4947 |
dataType: 'json',
|
4948 |
+
success: function(response) {
|
4949 |
if (!response) {
|
4950 |
alert('Error: Could not parse the server response.');
|
4951 |
testAccessButton.prop('disabled', false);
|
menu-editor.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Admin Menu Editor
|
4 |
Plugin URI: http://w-shadow.com/blog/2008/12/20/admin-menu-editor-for-wordpress/
|
5 |
Description: Lets you directly edit the WordPress admin menu. You can re-order, hide or rename existing menus, add custom menus and more.
|
6 |
-
Version: 1.8.
|
7 |
Author: Janis Elsts
|
8 |
Author URI: http://w-shadow.com/blog/
|
9 |
*/
|
3 |
Plugin Name: Admin Menu Editor
|
4 |
Plugin URI: http://w-shadow.com/blog/2008/12/20/admin-menu-editor-for-wordpress/
|
5 |
Description: Lets you directly edit the WordPress admin menu. You can re-order, hide or rename existing menus, add custom menus and more.
|
6 |
+
Version: 1.8.8
|
7 |
Author: Janis Elsts
|
8 |
Author URI: http://w-shadow.com/blog/
|
9 |
*/
|
modules/actor-selector/actor-selector.js
CHANGED
@@ -208,4 +208,3 @@ var AmeActorSelector = /** @class */ (function () {
|
|
208 |
AmeActorSelector._ = wsAmeLodash;
|
209 |
return AmeActorSelector;
|
210 |
}());
|
211 |
-
//# sourceMappingURL=actor-selector.js.map
|
208 |
AmeActorSelector._ = wsAmeLodash;
|
209 |
return AmeActorSelector;
|
210 |
}());
|
|
modules/plugin-visibility/plugin-visibility-template.php
CHANGED
@@ -75,10 +75,33 @@
|
|
75 |
<tr class="inline-edit-row" data-bind="if: isBeingEdited">
|
76 |
<td class="colspanchange" colspan="3">
|
77 |
<fieldset class="ame-pv-inline-edit-left">
|
|
|
|
|
|
|
78 |
<div class="inline-edit-col">
|
79 |
<label>
|
80 |
<span class="title">Name</span>
|
81 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
</label>
|
83 |
</div>
|
84 |
</fieldset>
|
@@ -88,7 +111,7 @@
|
|
88 |
<span class="title">Description</span>
|
89 |
<textarea name="plugin-description" cols="30" rows="5"
|
90 |
class="ame-pv-custom-description"
|
91 |
-
data-bind="value:
|
92 |
</label>
|
93 |
</div>
|
94 |
</fieldset>
|
75 |
<tr class="inline-edit-row" data-bind="if: isBeingEdited">
|
76 |
<td class="colspanchange" colspan="3">
|
77 |
<fieldset class="ame-pv-inline-edit-left">
|
78 |
+
<legend class="inline-edit-legend" data-bind="text: defaultProperties['name']">
|
79 |
+
Edit Plugin Properties
|
80 |
+
</legend>
|
81 |
<div class="inline-edit-col">
|
82 |
<label>
|
83 |
<span class="title">Name</span>
|
84 |
+
<span class="input-text-wrap">
|
85 |
+
<input type="text" data-bind="value: editableProperties['name']" class="ame-pv-custom-name">
|
86 |
+
</span>
|
87 |
+
</label>
|
88 |
+
<label>
|
89 |
+
<span class="title">Author</span>
|
90 |
+
<span class="input-text-wrap">
|
91 |
+
<input type="text" data-bind="value: editableProperties['author']" class="ame-pv-custom-author">
|
92 |
+
</span>
|
93 |
+
</label>
|
94 |
+
<label>
|
95 |
+
<span class="title">Site URL</span>
|
96 |
+
<span class="input-text-wrap">
|
97 |
+
<input type="text" data-bind="value: editableProperties['siteUrl']" class="ame-pv-custom-site-url">
|
98 |
+
</span>
|
99 |
+
</label>
|
100 |
+
<label>
|
101 |
+
<span class="title">Version</span>
|
102 |
+
<span class="input-text-wrap">
|
103 |
+
<input type="text" data-bind="value: editableProperties['version']" class="ame-pv-custom-version-number">
|
104 |
+
</span>
|
105 |
</label>
|
106 |
</div>
|
107 |
</fieldset>
|
111 |
<span class="title">Description</span>
|
112 |
<textarea name="plugin-description" cols="30" rows="5"
|
113 |
class="ame-pv-custom-description"
|
114 |
+
data-bind="value: editableProperties['description']"></textarea>
|
115 |
</label>
|
116 |
</div>
|
117 |
</fieldset>
|
modules/plugin-visibility/plugin-visibility.css
CHANGED
@@ -45,13 +45,15 @@
|
|
45 |
Inline editor
|
46 |
*/
|
47 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-edit-left {
|
48 |
-
width:
|
49 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-edit-right {
|
50 |
-
width:
|
51 |
#ame-plugin-visibility-editor .inline-edit-row span.title {
|
52 |
width: auto; }
|
53 |
#ame-plugin-visibility-editor .inline-edit-row input[type="text"] {
|
54 |
width: 100%; }
|
|
|
|
|
55 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-reset {
|
56 |
line-height: 28px;
|
57 |
margin-left: 1em; }
|
@@ -59,5 +61,10 @@
|
|
59 |
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); }
|
60 |
#ame-plugin-visibility-editor .inline-edit-row p.submit {
|
61 |
margin-bottom: 0.2em; }
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
/*# sourceMappingURL=plugin-visibility.css.map */
|
45 |
Inline editor
|
46 |
*/
|
47 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-edit-left {
|
48 |
+
width: 35%; }
|
49 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-edit-right {
|
50 |
+
width: 65%; }
|
51 |
#ame-plugin-visibility-editor .inline-edit-row span.title {
|
52 |
width: auto; }
|
53 |
#ame-plugin-visibility-editor .inline-edit-row input[type="text"] {
|
54 |
width: 100%; }
|
55 |
+
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-custom-description {
|
56 |
+
height: 9em; }
|
57 |
#ame-plugin-visibility-editor .inline-edit-row .ame-pv-inline-reset {
|
58 |
line-height: 28px;
|
59 |
margin-left: 1em; }
|
61 |
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1); }
|
62 |
#ame-plugin-visibility-editor .inline-edit-row p.submit {
|
63 |
margin-bottom: 0.2em; }
|
64 |
+
#ame-plugin-visibility-editor .inline-edit-row .inline-edit-legend {
|
65 |
+
margin: 0;
|
66 |
+
padding: 0.2em 0.5em 0;
|
67 |
+
line-height: 2.5;
|
68 |
+
font-weight: 600; }
|
69 |
|
70 |
/*# sourceMappingURL=plugin-visibility.css.map */
|
modules/plugin-visibility/plugin-visibility.js
CHANGED
@@ -137,10 +137,12 @@ var AmePluginVisibilityModule = /** @class */ (function () {
|
|
137 |
isVisibleByDefault: plugin.isVisibleByDefault(),
|
138 |
grantAccess: _.mapValues(plugin.grantAccess, function (allow) {
|
139 |
return allow();
|
140 |
-
})
|
141 |
-
customName: plugin.customName(),
|
142 |
-
customDescription: plugin.customDescription()
|
143 |
};
|
|
|
|
|
|
|
|
|
144 |
});
|
145 |
return result;
|
146 |
};
|
@@ -162,30 +164,33 @@ var AmePluginVisibilityModule = /** @class */ (function () {
|
|
162 |
var AmePlugin = /** @class */ (function () {
|
163 |
function AmePlugin(details, settings, module) {
|
164 |
var _this = this;
|
|
|
|
|
|
|
165 |
var _ = AmePluginVisibilityModule._;
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
170 |
this.name = ko.computed(function () {
|
171 |
-
var value = _this.
|
172 |
if (value === '') {
|
173 |
-
value = _this.
|
174 |
}
|
175 |
return AmePlugin.stripAllTags(value);
|
176 |
});
|
177 |
this.description = ko.computed(function () {
|
178 |
-
var value = _this.
|
179 |
if (value === '') {
|
180 |
-
value = _this.
|
181 |
}
|
182 |
return AmePlugin.stripAllTags(value);
|
183 |
});
|
184 |
this.fileName = details.fileName;
|
185 |
this.isActive = details.isActive;
|
186 |
this.isBeingEdited = ko.observable(false);
|
187 |
-
this.editableName = ko.observable(this.defaultName());
|
188 |
-
this.editableDescription = ko.observable(this.defaultDescription());
|
189 |
this.isVisibleByDefault = ko.observable(_.get(settings, 'isVisibleByDefault', true));
|
190 |
var emptyGrant = {};
|
191 |
this.grantAccess = _.mapValues(_.get(settings, 'grantAccess', emptyGrant), function (hasAccess) {
|
@@ -209,8 +214,10 @@ var AmePlugin = /** @class */ (function () {
|
|
209 |
};
|
210 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
211 |
AmePlugin.prototype.openInlineEditor = function () {
|
212 |
-
|
213 |
-
|
|
|
|
|
214 |
this.isBeingEdited(true);
|
215 |
};
|
216 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
@@ -219,20 +226,21 @@ var AmePlugin = /** @class */ (function () {
|
|
219 |
};
|
220 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
221 |
AmePlugin.prototype.confirmEdit = function () {
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
this.customDescription('');
|
229 |
}
|
230 |
this.isBeingEdited(false);
|
231 |
};
|
232 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
233 |
AmePlugin.prototype.resetNameAndDescription = function () {
|
234 |
-
|
235 |
-
|
|
|
|
|
236 |
this.isBeingEdited(false);
|
237 |
};
|
238 |
AmePlugin.stripAllTags = function (input) {
|
@@ -240,6 +248,7 @@ var AmePlugin = /** @class */ (function () {
|
|
240 |
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
241 |
return input.replace(commentsAndPhpTags, '').replace(tags, '');
|
242 |
};
|
|
|
243 |
return AmePlugin;
|
244 |
}());
|
245 |
jQuery(function ($) {
|
@@ -250,4 +259,3 @@ jQuery(function ($) {
|
|
250 |
AjawV1.getAction('ws_ame_dismiss_pv_usage_notice').request();
|
251 |
});
|
252 |
});
|
253 |
-
//# sourceMappingURL=plugin-visibility.js.map
|
137 |
isVisibleByDefault: plugin.isVisibleByDefault(),
|
138 |
grantAccess: _.mapValues(plugin.grantAccess, function (allow) {
|
139 |
return allow();
|
140 |
+
})
|
|
|
|
|
141 |
};
|
142 |
+
for (var i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
143 |
+
var key = AmePlugin.editablePropertyNames[i], upperKey = key.substring(0, 1).toUpperCase() + key.substring(1);
|
144 |
+
result.plugins[plugin.fileName]['custom' + upperKey] = plugin.customProperties[key]();
|
145 |
+
}
|
146 |
});
|
147 |
return result;
|
148 |
};
|
164 |
var AmePlugin = /** @class */ (function () {
|
165 |
function AmePlugin(details, settings, module) {
|
166 |
var _this = this;
|
167 |
+
this.defaultProperties = {};
|
168 |
+
this.customProperties = {};
|
169 |
+
this.editableProperties = {};
|
170 |
var _ = AmePluginVisibilityModule._;
|
171 |
+
for (var i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
172 |
+
var key = AmePlugin.editablePropertyNames[i], upperKey = key.substring(0, 1).toUpperCase() + key.substring(1);
|
173 |
+
this.defaultProperties[key] = ko.observable(_.get(details, key, ''));
|
174 |
+
this.customProperties[key] = ko.observable(_.get(settings, 'custom' + upperKey, ''));
|
175 |
+
this.editableProperties[key] = ko.observable(this.defaultProperties[key]());
|
176 |
+
}
|
177 |
this.name = ko.computed(function () {
|
178 |
+
var value = _this.customProperties['name']();
|
179 |
if (value === '') {
|
180 |
+
value = _this.defaultProperties['name']();
|
181 |
}
|
182 |
return AmePlugin.stripAllTags(value);
|
183 |
});
|
184 |
this.description = ko.computed(function () {
|
185 |
+
var value = _this.customProperties['description']();
|
186 |
if (value === '') {
|
187 |
+
value = _this.defaultProperties['description']();
|
188 |
}
|
189 |
return AmePlugin.stripAllTags(value);
|
190 |
});
|
191 |
this.fileName = details.fileName;
|
192 |
this.isActive = details.isActive;
|
193 |
this.isBeingEdited = ko.observable(false);
|
|
|
|
|
194 |
this.isVisibleByDefault = ko.observable(_.get(settings, 'isVisibleByDefault', true));
|
195 |
var emptyGrant = {};
|
196 |
this.grantAccess = _.mapValues(_.get(settings, 'grantAccess', emptyGrant), function (hasAccess) {
|
214 |
};
|
215 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
216 |
AmePlugin.prototype.openInlineEditor = function () {
|
217 |
+
for (var i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
218 |
+
var key = AmePlugin.editablePropertyNames[i], customValue = this.customProperties[key]();
|
219 |
+
this.editableProperties[key](customValue === '' ? this.defaultProperties[key]() : customValue);
|
220 |
+
}
|
221 |
this.isBeingEdited(true);
|
222 |
};
|
223 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
226 |
};
|
227 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
228 |
AmePlugin.prototype.confirmEdit = function () {
|
229 |
+
for (var i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
230 |
+
var key = AmePlugin.editablePropertyNames[i], customValue = this.editableProperties[key]();
|
231 |
+
if (customValue === this.defaultProperties[key]()) {
|
232 |
+
customValue = '';
|
233 |
+
}
|
234 |
+
this.customProperties[key](customValue);
|
|
|
235 |
}
|
236 |
this.isBeingEdited(false);
|
237 |
};
|
238 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
239 |
AmePlugin.prototype.resetNameAndDescription = function () {
|
240 |
+
for (var i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
241 |
+
var key = AmePlugin.editablePropertyNames[i];
|
242 |
+
this.customProperties[key]('');
|
243 |
+
}
|
244 |
this.isBeingEdited(false);
|
245 |
};
|
246 |
AmePlugin.stripAllTags = function (input) {
|
248 |
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
249 |
return input.replace(commentsAndPhpTags, '').replace(tags, '');
|
250 |
};
|
251 |
+
AmePlugin.editablePropertyNames = ['name', 'description', 'author', 'siteUrl', 'version'];
|
252 |
return AmePlugin;
|
253 |
}());
|
254 |
jQuery(function ($) {
|
259 |
AjawV1.getAction('ws_ame_dismiss_pv_usage_notice').request();
|
260 |
});
|
261 |
});
|
|
modules/plugin-visibility/plugin-visibility.php
CHANGED
@@ -162,6 +162,15 @@ class amePluginVisibility extends amePersistentModule {
|
|
162 |
return $plugins;
|
163 |
}
|
164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
$pluginFileNames = array_keys($plugins);
|
166 |
foreach($pluginFileNames as $fileName) {
|
167 |
//Remove all hidden plugins.
|
@@ -170,14 +179,12 @@ class amePluginVisibility extends amePersistentModule {
|
|
170 |
continue;
|
171 |
}
|
172 |
|
173 |
-
//Set custom names and
|
174 |
-
$
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
if ( $customDescription !== '' ) {
|
180 |
-
$plugins[$fileName]['Description'] = $customDescription;
|
181 |
}
|
182 |
}
|
183 |
|
@@ -324,12 +331,13 @@ class amePluginVisibility extends amePersistentModule {
|
|
324 |
|
325 |
$plugins[] = array(
|
326 |
'fileName' => $pluginFile,
|
327 |
-
'name' => $header['Name'],
|
328 |
-
'description' => isset($header['Description']) ? $header['Description'] : '',
|
329 |
'isActive' => $isActive || $isActiveForNetwork,
|
330 |
|
331 |
-
'
|
332 |
-
'
|
|
|
|
|
|
|
333 |
);
|
334 |
}
|
335 |
|
162 |
return $plugins;
|
163 |
}
|
164 |
|
165 |
+
$editableProperties = array(
|
166 |
+
'Name' => 'name',
|
167 |
+
'Description' => 'description',
|
168 |
+
'Author' => 'author',
|
169 |
+
'PluginURI' => 'siteUrl',
|
170 |
+
'AuthorURI' => 'siteUrl',
|
171 |
+
'Version' => 'version',
|
172 |
+
);
|
173 |
+
|
174 |
$pluginFileNames = array_keys($plugins);
|
175 |
foreach($pluginFileNames as $fileName) {
|
176 |
//Remove all hidden plugins.
|
179 |
continue;
|
180 |
}
|
181 |
|
182 |
+
//Set custom names, descriptions, and other properties.
|
183 |
+
foreach($editableProperties as $header => $property) {
|
184 |
+
$customValue = ameUtils::get($settings, array('plugins', $fileName, 'custom' . ucfirst($property)), '');
|
185 |
+
if ( $customValue !== '' ) {
|
186 |
+
$plugins[$fileName][$header] = $customValue;
|
187 |
+
}
|
|
|
|
|
188 |
}
|
189 |
}
|
190 |
|
331 |
|
332 |
$plugins[] = array(
|
333 |
'fileName' => $pluginFile,
|
|
|
|
|
334 |
'isActive' => $isActive || $isActiveForNetwork,
|
335 |
|
336 |
+
'name' => $header['Name'],
|
337 |
+
'description' => isset($header['Description']) ? $header['Description'] : '',
|
338 |
+
'author' => isset($header['Author']) ? $header['Author'] : '',
|
339 |
+
'siteUrl' => isset($header['PluginURI']) ? $header['PluginURI'] : '',
|
340 |
+
'version' => isset($header['Version']) ? $header['Version'] : '',
|
341 |
);
|
342 |
}
|
343 |
|
modules/plugin-visibility/plugin-visibility.scss
CHANGED
@@ -58,10 +58,10 @@
|
|
58 |
|
59 |
#ame-plugin-visibility-editor .inline-edit-row {
|
60 |
.ame-pv-inline-edit-left {
|
61 |
-
width:
|
62 |
}
|
63 |
.ame-pv-inline-edit-right {
|
64 |
-
width:
|
65 |
}
|
66 |
|
67 |
span.title {
|
@@ -71,6 +71,10 @@
|
|
71 |
width: 100%;
|
72 |
}
|
73 |
|
|
|
|
|
|
|
|
|
74 |
.ame-pv-inline-reset {
|
75 |
line-height: 28px;
|
76 |
margin-left: 1em;
|
@@ -83,4 +87,11 @@
|
|
83 |
p.submit {
|
84 |
margin-bottom: 0.2em;
|
85 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
58 |
|
59 |
#ame-plugin-visibility-editor .inline-edit-row {
|
60 |
.ame-pv-inline-edit-left {
|
61 |
+
width: 35%;
|
62 |
}
|
63 |
.ame-pv-inline-edit-right {
|
64 |
+
width: 65%;
|
65 |
}
|
66 |
|
67 |
span.title {
|
71 |
width: 100%;
|
72 |
}
|
73 |
|
74 |
+
.ame-pv-custom-description {
|
75 |
+
height: 9em;
|
76 |
+
}
|
77 |
+
|
78 |
.ame-pv-inline-reset {
|
79 |
line-height: 28px;
|
80 |
margin-left: 1em;
|
87 |
p.submit {
|
88 |
margin-bottom: 0.2em;
|
89 |
}
|
90 |
+
|
91 |
+
.inline-edit-legend {
|
92 |
+
margin: 0;
|
93 |
+
padding: 0.2em 0.5em 0;
|
94 |
+
line-height: 2.5;
|
95 |
+
font-weight: 600;
|
96 |
+
}
|
97 |
}
|
modules/plugin-visibility/plugin-visibility.ts
CHANGED
@@ -23,8 +23,11 @@ interface PluginVisibilitySettings {
|
|
23 |
[fileName : string] : {
|
24 |
isVisibleByDefault: boolean,
|
25 |
grantAccess: GrantAccessMap,
|
26 |
-
customName
|
27 |
-
customDescription
|
|
|
|
|
|
|
28 |
}
|
29 |
}
|
30 |
}
|
@@ -35,21 +38,22 @@ interface GrantAccessMap {
|
|
35 |
|
36 |
interface PvPluginInfo {
|
37 |
name: string,
|
38 |
-
fileName: string,
|
39 |
description: string,
|
40 |
-
|
|
|
|
|
41 |
|
42 |
-
|
43 |
-
|
44 |
}
|
45 |
|
46 |
class AmePluginVisibilityModule {
|
47 |
static _ = wsAmeLodash;
|
48 |
|
49 |
plugins: Array<AmePlugin>;
|
50 |
-
private canRoleManagePlugins: {[roleId: string] : boolean};
|
51 |
grantAccessByDefault: {[actorId: string] : KnockoutObservable<boolean>};
|
52 |
-
private isMultisite: boolean;
|
53 |
|
54 |
actorSelector: AmeActorSelector;
|
55 |
selectedActor: KnockoutComputed<string>;
|
@@ -61,7 +65,7 @@ class AmePluginVisibilityModule {
|
|
61 |
* Actors that don't lose access to a plugin when you uncheck it in the "All" view.
|
62 |
* This is a convenience feature that lets the user quickly hide a bunch of plugins from everyone else.
|
63 |
*/
|
64 |
-
private privilegedActors: Array<IAmeActor>;
|
65 |
|
66 |
constructor(scriptData: PluginVisibilityScriptData) {
|
67 |
const _ = AmePluginVisibilityModule._;
|
@@ -209,10 +213,14 @@ class AmePluginVisibilityModule {
|
|
209 |
isVisibleByDefault: plugin.isVisibleByDefault(),
|
210 |
grantAccess: _.mapValues(plugin.grantAccess, (allow): boolean => {
|
211 |
return allow();
|
212 |
-
})
|
213 |
-
customName: plugin.customName(),
|
214 |
-
customDescription: plugin.customDescription()
|
215 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
});
|
217 |
|
218 |
return result;
|
@@ -236,21 +244,23 @@ class AmePluginVisibilityModule {
|
|
236 |
}
|
237 |
}
|
238 |
|
|
|
|
|
|
|
|
|
239 |
class AmePlugin {
|
240 |
name: KnockoutComputed<string>;
|
241 |
fileName: string;
|
242 |
description: KnockoutComputed<string>;
|
243 |
isActive: boolean;
|
244 |
|
245 |
-
|
246 |
-
defaultDescription: KnockoutObservable<string>;
|
247 |
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
editableName: KnockoutObservable<string>;
|
252 |
-
editableDescription: KnockoutObservable<string>;
|
253 |
|
|
|
254 |
isChecked: KnockoutComputed<boolean>;
|
255 |
|
256 |
isVisibleByDefault: KnockoutObservable<boolean>;
|
@@ -259,22 +269,25 @@ class AmePlugin {
|
|
259 |
constructor(details: PvPluginInfo, settings: Object, module: AmePluginVisibilityModule) {
|
260 |
const _ = AmePluginVisibilityModule._;
|
261 |
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
|
|
|
|
|
|
266 |
|
267 |
this.name = ko.computed(() => {
|
268 |
-
let value = this.
|
269 |
if (value === '') {
|
270 |
-
value = this.
|
271 |
}
|
272 |
return AmePlugin.stripAllTags(value);
|
273 |
});
|
274 |
this.description = ko.computed(() => {
|
275 |
-
let value = this.
|
276 |
if (value === '') {
|
277 |
-
value = this.
|
278 |
}
|
279 |
return AmePlugin.stripAllTags(value);
|
280 |
});
|
@@ -283,12 +296,10 @@ class AmePlugin {
|
|
283 |
this.isActive = details.isActive;
|
284 |
|
285 |
this.isBeingEdited = ko.observable(false);
|
286 |
-
this.editableName = ko.observable(this.defaultName());
|
287 |
-
this.editableDescription = ko.observable(this.defaultDescription());
|
288 |
|
289 |
this.isVisibleByDefault = ko.observable(_.get(settings, 'isVisibleByDefault', true));
|
290 |
|
291 |
-
const emptyGrant: {[actorId
|
292 |
this.grantAccess = _.mapValues(_.get(settings, 'grantAccess', emptyGrant), (hasAccess) => {
|
293 |
return ko.observable<boolean>(hasAccess);
|
294 |
});
|
@@ -312,8 +323,12 @@ class AmePlugin {
|
|
312 |
|
313 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
314 |
openInlineEditor() {
|
315 |
-
|
316 |
-
|
|
|
|
|
|
|
|
|
317 |
this.isBeingEdited(true);
|
318 |
}
|
319 |
|
@@ -324,14 +339,13 @@ class AmePlugin {
|
|
324 |
|
325 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
326 |
confirmEdit() {
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
this.customDescription('');
|
335 |
}
|
336 |
|
337 |
this.isBeingEdited(false);
|
@@ -339,8 +353,10 @@ class AmePlugin {
|
|
339 |
|
340 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
341 |
resetNameAndDescription() {
|
342 |
-
|
343 |
-
|
|
|
|
|
344 |
this.isBeingEdited(false);
|
345 |
}
|
346 |
|
23 |
[fileName : string] : {
|
24 |
isVisibleByDefault: boolean,
|
25 |
grantAccess: GrantAccessMap,
|
26 |
+
customName?: string,
|
27 |
+
customDescription?: string;
|
28 |
+
customAuthor?: string;
|
29 |
+
customSiteUrl?: string;
|
30 |
+
customVersion?: string;
|
31 |
}
|
32 |
}
|
33 |
}
|
38 |
|
39 |
interface PvPluginInfo {
|
40 |
name: string,
|
|
|
41 |
description: string,
|
42 |
+
author: string,
|
43 |
+
version: string,
|
44 |
+
siteUrl: string,
|
45 |
|
46 |
+
fileName: string,
|
47 |
+
isActive: boolean;
|
48 |
}
|
49 |
|
50 |
class AmePluginVisibilityModule {
|
51 |
static _ = wsAmeLodash;
|
52 |
|
53 |
plugins: Array<AmePlugin>;
|
54 |
+
private readonly canRoleManagePlugins: {[roleId: string] : boolean};
|
55 |
grantAccessByDefault: {[actorId: string] : KnockoutObservable<boolean>};
|
56 |
+
private readonly isMultisite: boolean;
|
57 |
|
58 |
actorSelector: AmeActorSelector;
|
59 |
selectedActor: KnockoutComputed<string>;
|
65 |
* Actors that don't lose access to a plugin when you uncheck it in the "All" view.
|
66 |
* This is a convenience feature that lets the user quickly hide a bunch of plugins from everyone else.
|
67 |
*/
|
68 |
+
private readonly privilegedActors: Array<IAmeActor>;
|
69 |
|
70 |
constructor(scriptData: PluginVisibilityScriptData) {
|
71 |
const _ = AmePluginVisibilityModule._;
|
213 |
isVisibleByDefault: plugin.isVisibleByDefault(),
|
214 |
grantAccess: _.mapValues(plugin.grantAccess, (allow): boolean => {
|
215 |
return allow();
|
216 |
+
})
|
|
|
|
|
217 |
};
|
218 |
+
|
219 |
+
for (let i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
220 |
+
let key = AmePlugin.editablePropertyNames[i],
|
221 |
+
upperKey = key.substring(0, 1).toUpperCase() + key.substring(1);
|
222 |
+
result.plugins[plugin.fileName]['custom' + upperKey] = plugin.customProperties[key]();
|
223 |
+
}
|
224 |
});
|
225 |
|
226 |
return result;
|
244 |
}
|
245 |
}
|
246 |
|
247 |
+
interface AmeStringObservableMap {
|
248 |
+
[key: string]: KnockoutObservable<string>;
|
249 |
+
}
|
250 |
+
|
251 |
class AmePlugin {
|
252 |
name: KnockoutComputed<string>;
|
253 |
fileName: string;
|
254 |
description: KnockoutComputed<string>;
|
255 |
isActive: boolean;
|
256 |
|
257 |
+
static readonly editablePropertyNames = ['name', 'description', 'author', 'siteUrl', 'version'];
|
|
|
258 |
|
259 |
+
defaultProperties: AmeStringObservableMap = {};
|
260 |
+
customProperties: AmeStringObservableMap = {};
|
261 |
+
editableProperties: AmeStringObservableMap = {};
|
|
|
|
|
262 |
|
263 |
+
isBeingEdited: KnockoutObservable<boolean>;
|
264 |
isChecked: KnockoutComputed<boolean>;
|
265 |
|
266 |
isVisibleByDefault: KnockoutObservable<boolean>;
|
269 |
constructor(details: PvPluginInfo, settings: Object, module: AmePluginVisibilityModule) {
|
270 |
const _ = AmePluginVisibilityModule._;
|
271 |
|
272 |
+
for (let i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
273 |
+
let key = AmePlugin.editablePropertyNames[i],
|
274 |
+
upperKey = key.substring(0, 1).toUpperCase() + key.substring(1);
|
275 |
+
this.defaultProperties[key] = ko.observable(_.get(details, key, ''));
|
276 |
+
this.customProperties[key] = ko.observable(_.get(settings, 'custom' + upperKey, ''));
|
277 |
+
this.editableProperties[key] = ko.observable(this.defaultProperties[key]());
|
278 |
+
}
|
279 |
|
280 |
this.name = ko.computed(() => {
|
281 |
+
let value = this.customProperties['name']();
|
282 |
if (value === '') {
|
283 |
+
value = this.defaultProperties['name']();
|
284 |
}
|
285 |
return AmePlugin.stripAllTags(value);
|
286 |
});
|
287 |
this.description = ko.computed(() => {
|
288 |
+
let value = this.customProperties['description']();
|
289 |
if (value === '') {
|
290 |
+
value = this.defaultProperties['description']();
|
291 |
}
|
292 |
return AmePlugin.stripAllTags(value);
|
293 |
});
|
296 |
this.isActive = details.isActive;
|
297 |
|
298 |
this.isBeingEdited = ko.observable(false);
|
|
|
|
|
299 |
|
300 |
this.isVisibleByDefault = ko.observable(_.get(settings, 'isVisibleByDefault', true));
|
301 |
|
302 |
+
const emptyGrant: { [actorId: string]: boolean } = {};
|
303 |
this.grantAccess = _.mapValues(_.get(settings, 'grantAccess', emptyGrant), (hasAccess) => {
|
304 |
return ko.observable<boolean>(hasAccess);
|
305 |
});
|
323 |
|
324 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
325 |
openInlineEditor() {
|
326 |
+
for (let i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
327 |
+
let key = AmePlugin.editablePropertyNames[i],
|
328 |
+
customValue = this.customProperties[key]();
|
329 |
+
this.editableProperties[key](customValue === '' ? this.defaultProperties[key]() : customValue);
|
330 |
+
}
|
331 |
+
|
332 |
this.isBeingEdited(true);
|
333 |
}
|
334 |
|
339 |
|
340 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
341 |
confirmEdit() {
|
342 |
+
for (let i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
343 |
+
let key = AmePlugin.editablePropertyNames[i],
|
344 |
+
customValue = this.editableProperties[key]();
|
345 |
+
if (customValue === this.defaultProperties[key]()) {
|
346 |
+
customValue = '';
|
347 |
+
}
|
348 |
+
this.customProperties[key](customValue);
|
|
|
349 |
}
|
350 |
|
351 |
this.isBeingEdited(false);
|
353 |
|
354 |
//noinspection JSUnusedGlobalSymbols Used in KO template.
|
355 |
resetNameAndDescription() {
|
356 |
+
for (let i = 0; i < AmePlugin.editablePropertyNames.length; i++) {
|
357 |
+
let key = AmePlugin.editablePropertyNames[i];
|
358 |
+
this.customProperties[key]('');
|
359 |
+
}
|
360 |
this.isBeingEdited(false);
|
361 |
}
|
362 |
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: whiteshadow
|
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A6P9S6CE3SRSW
|
4 |
Tags: admin, dashboard, menu, security, wpmu
|
5 |
Requires at least: 4.1
|
6 |
-
Tested up to: 5.
|
7 |
-
Stable tag: 1.8.
|
8 |
|
9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
10 |
|
@@ -63,6 +63,14 @@ Plugins installed in the `mu-plugins` directory are treated as "always on", so y
|
|
63 |
|
64 |
== Changelog ==
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
= 1.8.7 =
|
67 |
* Fixed a bug introcuded in 1.8.6 that caused a PHP warning "strpos(): Empty needle".
|
68 |
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A6P9S6CE3SRSW
|
4 |
Tags: admin, dashboard, menu, security, wpmu
|
5 |
Requires at least: 4.1
|
6 |
+
Tested up to: 5.1
|
7 |
+
Stable tag: 1.8.8
|
8 |
|
9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
10 |
|
63 |
|
64 |
== Changelog ==
|
65 |
|
66 |
+
= 1.8.8 =
|
67 |
+
* Added the ability to edit more plugin details like author name, site URL and version number. Note that this feature only changes how plugins are displayed. It doesn't actually modify plugin files.
|
68 |
+
* Fixed a PHP deprecation notice: "strpos(): Non-string needles will be interpreted as strings in the future". Hopefully this time it's been fixed for good.
|
69 |
+
* Fixed a couple of HTML validation errors.
|
70 |
+
* Fixed an inefficiency where the plugin would reinitialise the media frame every time the user tried to select an image from the media library.
|
71 |
+
* Added a partial workaround for situations where menu icons that were more than 32 pixels wide would be displayed incorrectly.
|
72 |
+
* Tested up to WP 5.1.1.
|
73 |
+
|
74 |
= 1.8.7 =
|
75 |
* Fixed a bug introcuded in 1.8.6 that caused a PHP warning "strpos(): Empty needle".
|
76 |
|