Version Description
- Added a special target page option: "< None >". It makes the selected menu item unclickable. This could be useful for creating menu headers and so on.
- Added a new menu editor colour scheme that's similar to the default WordPress admin colour scheme. Click the "Settings" button next to the menu editor page title to switch colour schemes.
- Fixed strange boxes showing up in the icon selector in Internet Explorer.
- Fixed duplicate top level menus mysteriously disappearing. Now the plugin will properly warn the user that all top level menus must have unique URLs.
- Fixed an obscure bug where changing the "Target page" from the default setting to "Custom" and back would occasionally make some menu properties suddenly show up as modified for no apparent reason.
- Fixed incorrect submenu item height and margins in WP 4.0-beta.
- Fixed a minor layout bug where items with no title would be smaller than other items.
- Fixed combo-box dropdown button height for WP 3.9.x.
- Added a workaround for a bug in WordPress Mu Domain Mapping 0.5.4.3.
- Added a workaround for the very unusual situation where the "user_has_cap" filter is called without a capability.
- Fixed duplicates of bbPress menu items showing up.
- Changed the default custom menu icon to the generic "cogwheel" icon from Dashicons.
- Other small UI changes.
- Raised minimum requirements to WordPress 3.8 or later. This is mainly due to the increased reliance on Dashicons as menu icons.
Download this release
Release Info
Developer | whiteshadow |
Plugin | Admin Menu Editor |
Version | 1.4 |
Comparing to | |
See all releases |
Code changes from version 1.3.2 to 1.4
- css/admin.css +59 -0
- css/menu-editor.css +108 -16
- css/{style-wp-gray.css → style-wp-grey.css} +68 -34
- includes/editor-page.php +32 -5
- includes/menu-editor-core.php +195 -37
- includes/menu-item.php +9 -4
- includes/menu.php +22 -0
- includes/settings-page.php +56 -0
- js/admin-helpers.js +12 -1
- js/menu-editor.js +270 -59
- js/menu-highlight-fix.js +9 -2
- menu-editor.php +1 -1
- readme.txt +28 -12
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
css/admin.css
CHANGED
@@ -38,7 +38,66 @@ hr.ws-submenu-separator {
|
|
38 |
}
|
39 |
*/
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
/* No pointer/hand on separators. */
|
42 |
#adminmenu li.ws-submenu-separator-wrap a {
|
43 |
cursor: default;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
}
|
38 |
}
|
39 |
*/
|
40 |
|
41 |
+
/* Override .wp-menu-separator styles as they don't work too well in submenus. */
|
42 |
+
#adminmenu .wp-submenu li.ws-submenu-separator-wrap {
|
43 |
+
margin: 0 0 0 0;
|
44 |
+
padding: 0;
|
45 |
+
height: inherit;
|
46 |
+
}
|
47 |
+
|
48 |
/* No pointer/hand on separators. */
|
49 |
#adminmenu li.ws-submenu-separator-wrap a {
|
50 |
cursor: default;
|
51 |
+
}
|
52 |
+
|
53 |
+
/* No extra margin in submenus with icons. The selector uses the URL prefix because we can't control the link class.
|
54 |
+
* li.ws-submenu-separator-wrap would also work, but it's added via JS so there's an undesirable delay (FOUC).
|
55 |
+
*/
|
56 |
+
#adminmenu .ame-has-submenu-icons ul.wp-submenu li a[href^="#submenu-separator-"] {
|
57 |
+
margin-left: 0;
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
/*
|
62 |
+
* Submenu icons.
|
63 |
+
*/
|
64 |
+
.ame-submenu-icon {
|
65 |
+
display: inline-block;
|
66 |
+
padding-right: 8px;
|
67 |
+
min-width: 20px;
|
68 |
+
|
69 |
+
/*
|
70 |
+
Dashicons are 20x20 by default and some of them look pretty bad at smaller sizes. Submenu item titles are 16px high
|
71 |
+
by default. So lets hack some negative margins to make a 20px icon fit in 16px. With the current admin UI styles
|
72 |
+
it looks okay - submenu items are ~28px high when including padding/margins, so there's no visual overlap.
|
73 |
+
*/
|
74 |
+
height: 20px;
|
75 |
+
margin-top: -2px;
|
76 |
+
margin-bottom: -2px;
|
77 |
+
|
78 |
+
vertical-align: top;
|
79 |
+
|
80 |
+
margin-left: -28px;
|
81 |
+
float: left;
|
82 |
+
|
83 |
+
/* Center image-based icons. Doesn't matter for dashicons. */
|
84 |
+
text-align: center;
|
85 |
+
}
|
86 |
+
|
87 |
+
#adminmenu .ame-has-submenu-icons ul.wp-submenu li a {
|
88 |
+
/* Push all submenus to the right to ensure that items with and without icons line up nicely. */
|
89 |
+
margin-left: 24px;
|
90 |
+
}
|
91 |
+
|
92 |
+
#adminmenu .ame-submenu-icon img {
|
93 |
+
padding-top: 2px;
|
94 |
+
|
95 |
+
opacity: 0.6;
|
96 |
+
filter: alpha(opacity=60);
|
97 |
+
}
|
98 |
+
|
99 |
+
#adminmenu .wp-submenu li:hover .ame-submenu-icon img,
|
100 |
+
#adminmenu .wp-submenu li.current .ame-submenu-icon img {
|
101 |
+
opacity: 1;
|
102 |
+
filter: alpha(opacity=100);
|
103 |
}
|
css/menu-editor.css
CHANGED
@@ -9,8 +9,10 @@
|
|
9 |
width: 310px;
|
10 |
float: left;
|
11 |
display:block;
|
|
|
12 |
border: 1px solid #cdd5d5;
|
13 |
-
|
|
|
14 |
border-radius: 3px;
|
15 |
-moz-border-radius: 3px;
|
16 |
-webkit-border-radius: 3px;
|
@@ -42,7 +44,7 @@
|
|
42 |
}
|
43 |
|
44 |
.ws_dropzone_hover {
|
45 |
-
border: 1px
|
46 |
background: yellow;
|
47 |
height: 30px;
|
48 |
}
|
@@ -286,18 +288,22 @@
|
|
286 |
margin-top: 0;
|
287 |
}
|
288 |
|
|
|
|
|
|
|
|
|
289 |
/* Dropdown button for combo-box fields */
|
290 |
#ws_menu_editor .ws_dropdown_button,
|
291 |
#ws_menu_access_editor .ws_dropdown_button
|
292 |
{
|
|
|
293 |
width: 20px;
|
294 |
-
height:
|
295 |
|
296 |
margin: 1px 1px 1px 0;
|
297 |
padding: 0;
|
298 |
|
299 |
text-align: center;
|
300 |
-
vertical-align: middle;
|
301 |
font-size: 9px !important;
|
302 |
|
303 |
border-color: #dfdfdf;
|
@@ -320,8 +326,7 @@
|
|
320 |
|
321 |
#ws_menu_access_editor .ws_dropdown_button {
|
322 |
display: inline-block;
|
323 |
-
height:
|
324 |
-
margin-bottom: 2px;
|
325 |
}
|
326 |
|
327 |
#ws_menu_editor .ws_dropdown_button {
|
@@ -351,6 +356,8 @@ to accommodate the drop-down button.
|
|
351 |
|
352 |
#ws_menu_access_editor input.ws_has_dropdown {
|
353 |
width: 90%;
|
|
|
|
|
354 |
}
|
355 |
|
356 |
#ws_menu_editor .ws_has_dropdown input.ws_field_value {
|
@@ -419,6 +426,19 @@ to accommodate the drop-down button.
|
|
419 |
background-image: url('../images/icon-extension-grey.png');
|
420 |
}
|
421 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
422 |
/* These classes could be used to apply different styles to items depending on their flags */
|
423 |
.ws_custom { }
|
424 |
.ws_hidden { }
|
@@ -557,6 +577,12 @@ select.ws_dropdown optgroup option {
|
|
557 |
margin: 0;
|
558 |
}
|
559 |
|
|
|
|
|
|
|
|
|
|
|
|
|
560 |
#ws_icon_selector .ws_icon_option img {
|
561 |
display: inline-block;
|
562 |
margin: 0;
|
@@ -715,18 +741,18 @@ select.ws_dropdown optgroup option {
|
|
715 |
}
|
716 |
|
717 |
.ui-front {
|
718 |
-
z-index:
|
719 |
}
|
720 |
|
721 |
.ui-dialog {
|
722 |
background: white;
|
723 |
border: 1px solid #c0c0c0;
|
|
|
|
|
724 |
|
725 |
-
padding: 2px;
|
726 |
-
|
727 |
-
border-radius: 5px;
|
728 |
-moz-border-radius: 5px;
|
729 |
-
|
|
|
730 |
}
|
731 |
|
732 |
.ui-dialog-titlebar {
|
@@ -738,10 +764,17 @@ select.ws_dropdown optgroup option {
|
|
738 |
background-color: #86A7E3;
|
739 |
font-size: 1.0em;
|
740 |
line-height: 22px;
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
745 |
}
|
746 |
|
747 |
.ui-dialog-title {
|
@@ -772,7 +805,7 @@ select.ws_dropdown optgroup option {
|
|
772 |
}
|
773 |
|
774 |
.ui-dialog-content {
|
775 |
-
padding:
|
776 |
font-size: 1.1em;
|
777 |
}
|
778 |
|
@@ -802,6 +835,24 @@ select.ws_dropdown optgroup option {
|
|
802 |
margin-top: 0;
|
803 |
}
|
804 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
805 |
#import_file_selector {
|
806 |
display: block;
|
807 |
width: 286px;
|
@@ -935,6 +986,18 @@ select.ws_dropdown optgroup option {
|
|
935 |
display: none;
|
936 |
}
|
937 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
938 |
/************************************
|
939 |
Tooltips and hints
|
940 |
*************************************/
|
@@ -1001,4 +1064,33 @@ select.ws_dropdown optgroup option {
|
|
1001 |
right: 20px;
|
1002 |
bottom: 40px;
|
1003 |
z-index: 100;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1004 |
}
|
9 |
width: 310px;
|
10 |
float: left;
|
11 |
display:block;
|
12 |
+
|
13 |
border: 1px solid #cdd5d5;
|
14 |
+
background-color: #FFFFFF;
|
15 |
+
|
16 |
border-radius: 3px;
|
17 |
-moz-border-radius: 3px;
|
18 |
-webkit-border-radius: 3px;
|
44 |
}
|
45 |
|
46 |
.ws_dropzone_hover {
|
47 |
+
border: 1px dashed silver;
|
48 |
background: yellow;
|
49 |
height: 30px;
|
50 |
}
|
288 |
margin-top: 0;
|
289 |
}
|
290 |
|
291 |
+
#ws_menu_editor input[type="text"].ws_field_value {
|
292 |
+
min-height: 25px;
|
293 |
+
}
|
294 |
+
|
295 |
/* Dropdown button for combo-box fields */
|
296 |
#ws_menu_editor .ws_dropdown_button,
|
297 |
#ws_menu_access_editor .ws_dropdown_button
|
298 |
{
|
299 |
+
box-sizing: border-box;
|
300 |
width: 20px;
|
301 |
+
height: 25px;
|
302 |
|
303 |
margin: 1px 1px 1px 0;
|
304 |
padding: 0;
|
305 |
|
306 |
text-align: center;
|
|
|
307 |
font-size: 9px !important;
|
308 |
|
309 |
border-color: #dfdfdf;
|
326 |
|
327 |
#ws_menu_access_editor .ws_dropdown_button {
|
328 |
display: inline-block;
|
329 |
+
height: 27px;
|
|
|
330 |
}
|
331 |
|
332 |
#ws_menu_editor .ws_dropdown_button {
|
356 |
|
357 |
#ws_menu_access_editor input.ws_has_dropdown {
|
358 |
width: 90%;
|
359 |
+
box-sizing: border-box;
|
360 |
+
height: 27px;
|
361 |
}
|
362 |
|
363 |
#ws_menu_editor .ws_has_dropdown input.ws_field_value {
|
426 |
background-image: url('../images/icon-extension-grey.png');
|
427 |
}
|
428 |
|
429 |
+
/* items with custom permissions for the selected actor */
|
430 |
+
.ws_custom_actor_permissions_flag {
|
431 |
+
font: 16px/1 'dashicons';
|
432 |
+
}
|
433 |
+
.ws_custom_actor_permissions_flag::before {
|
434 |
+
/*content: "\f160";*/ /* padlock */
|
435 |
+
content: "\f110"; /* human silhouette */
|
436 |
+
color: black;
|
437 |
+
|
438 |
+
filter: alpha(opacity=25); /*IE 5-7*/
|
439 |
+
opacity: 0.25;
|
440 |
+
}
|
441 |
+
|
442 |
/* These classes could be used to apply different styles to items depending on their flags */
|
443 |
.ws_custom { }
|
444 |
.ws_hidden { }
|
577 |
margin: 0;
|
578 |
}
|
579 |
|
580 |
+
#ws_icon_selector .ws_icon_option .ws_icon_image.dashicons {
|
581 |
+
width: 20px;
|
582 |
+
height: 20px;
|
583 |
+
padding: 5px;
|
584 |
+
}
|
585 |
+
|
586 |
#ws_icon_selector .ws_icon_option img {
|
587 |
display: inline-block;
|
588 |
margin: 0;
|
741 |
}
|
742 |
|
743 |
.ui-front {
|
744 |
+
z-index: 10000;
|
745 |
}
|
746 |
|
747 |
.ui-dialog {
|
748 |
background: white;
|
749 |
border: 1px solid #c0c0c0;
|
750 |
+
|
751 |
+
padding: 0;
|
752 |
|
|
|
|
|
|
|
753 |
-moz-border-radius: 5px;
|
754 |
+
-webkit-border-radius: 5px;
|
755 |
+
border-radius: 5px;
|
756 |
}
|
757 |
|
758 |
.ui-dialog-titlebar {
|
764 |
background-color: #86A7E3;
|
765 |
font-size: 1.0em;
|
766 |
line-height: 22px;
|
767 |
+
|
768 |
+
-webkit-border-top-left-radius: 4px;
|
769 |
+
-webkit-border-top-right-radius: 4px;
|
770 |
+
|
771 |
+
-moz-border-radius-topleft: 4px;
|
772 |
+
-moz-border-radius-topright: 4px;
|
773 |
+
|
774 |
+
border-top-left-radius: 4px;
|
775 |
+
border-top-right-radius: 4px;
|
776 |
+
|
777 |
+
border-bottom: 1px solid #809fd9;
|
778 |
}
|
779 |
|
780 |
.ui-dialog-title {
|
805 |
}
|
806 |
|
807 |
.ui-dialog-content {
|
808 |
+
padding: 8px 8px 8px 8px;
|
809 |
font-size: 1.1em;
|
810 |
}
|
811 |
|
835 |
margin-top: 0;
|
836 |
}
|
837 |
|
838 |
+
.ws_dialog_buttons.ame-vertical-button-list {
|
839 |
+
text-align: left;
|
840 |
+
}
|
841 |
+
|
842 |
+
.ws_dialog_buttons.ame-vertical-button-list .button-primary {
|
843 |
+
float: none;
|
844 |
+
}
|
845 |
+
|
846 |
+
.ws_dialog_buttons.ame-vertical-button-list .button {
|
847 |
+
width: 100%;
|
848 |
+
text-align: left;
|
849 |
+
margin-bottom: 10px;
|
850 |
+
}
|
851 |
+
|
852 |
+
.ws_dialog_buttons.ame-vertical-button-list .button:last-child {
|
853 |
+
margin-bottom: 0;
|
854 |
+
}
|
855 |
+
|
856 |
#import_file_selector {
|
857 |
display: block;
|
858 |
width: 286px;
|
986 |
display: none;
|
987 |
}
|
988 |
|
989 |
+
|
990 |
+
/************************************
|
991 |
+
Menu deletion error
|
992 |
+
*************************************/
|
993 |
+
|
994 |
+
#ws-ame-menu-deletion-error {
|
995 |
+
max-width: 400px;
|
996 |
+
}
|
997 |
+
|
998 |
+
|
999 |
+
|
1000 |
+
|
1001 |
/************************************
|
1002 |
Tooltips and hints
|
1003 |
*************************************/
|
1064 |
right: 20px;
|
1065 |
bottom: 40px;
|
1066 |
z-index: 100;
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
|
1070 |
+
.test-wrap {
|
1071 |
+
background-color: #444444;
|
1072 |
+
padding: 30px;
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
.test-container {
|
1076 |
+
width: 400px;
|
1077 |
+
height: 200px;
|
1078 |
+
background-color: white;
|
1079 |
+
|
1080 |
+
border: 1px solid black;
|
1081 |
+
border-radius: 10px;
|
1082 |
+
|
1083 |
+
overflow: hidden;
|
1084 |
+
}
|
1085 |
+
|
1086 |
+
.test-header {
|
1087 |
+
background-color: #67d6ff;
|
1088 |
+
padding: 6px;
|
1089 |
+
|
1090 |
+
border-top-left-radius: 8px;
|
1091 |
+
border-top-right-radius: 8px;
|
1092 |
+
}
|
1093 |
+
|
1094 |
+
.test-content {
|
1095 |
+
padding: 8px;
|
1096 |
}
|
css/{style-wp-gray.css → style-wp-grey.css}
RENAMED
@@ -10,8 +10,8 @@
|
|
10 |
-webkit-box-shadow: inset 0 1px 0 #fff;
|
11 |
box-shadow: inset 0 1px 0 #fff;
|
12 |
|
13 |
-
|
14 |
-
border-radius:
|
15 |
}
|
16 |
|
17 |
/**
|
@@ -19,31 +19,19 @@
|
|
19 |
*/
|
20 |
|
21 |
.ws_item_head {
|
22 |
-
padding:
|
23 |
-
border-top-left-radius: 3px;
|
24 |
-
border-top-right-radius: 3px;
|
25 |
|
26 |
background-color: #d9d9d9;
|
27 |
-
background-image: -o-linear-gradient(top, #efefef, #d9d9d9);
|
28 |
-
background-image: -o-linear-gradient(top, #e9e9e9, #d9d9d9);
|
29 |
background-image: -ms-linear-gradient(top, #e9e9e9, #d9d9d9);
|
30 |
background-image: -moz-linear-gradient(top, #e9e9e9, #d9d9d9);
|
31 |
background-image: -webkit-gradient(linear, left top, left bottom, from(#e9e9e9), to(#d9d9d9));
|
32 |
background-image: -webkit-linear-gradient(top, #e9e9e9, #d9d9d9);
|
33 |
-
background-image: linear-gradient(
|
34 |
-
/*background-color: #c7c7c7;*/
|
35 |
}
|
36 |
|
37 |
.ws_item_title {
|
38 |
-
padding: 6px 5px;
|
39 |
-
|
40 |
-
/*font-weight: bold;*/
|
41 |
color: #222;
|
42 |
-
text-shadow: #FFFFFF
|
43 |
-
}
|
44 |
-
|
45 |
-
.ws_flag_container {
|
46 |
-
padding-top: 6px;
|
47 |
}
|
48 |
|
49 |
/**
|
@@ -51,10 +39,7 @@
|
|
51 |
*/
|
52 |
|
53 |
.ws_edit_link {
|
54 |
-
|
55 |
-
height: 30px;
|
56 |
-
|
57 |
-
background: transparent url(../images/arrows.png) no-repeat center 5px;
|
58 |
overflow: hidden;
|
59 |
text-indent:-999em;
|
60 |
}
|
@@ -64,7 +49,7 @@ a.ws_edit_link:hover {
|
|
64 |
}
|
65 |
|
66 |
.ws_edit_link:active {
|
67 |
-
background:
|
68 |
}
|
69 |
|
70 |
.ws_edit_link_expanded {
|
@@ -92,19 +77,19 @@ a.ws_edit_link:hover {
|
|
92 |
}
|
93 |
|
94 |
.ws_menu_separator .ws_item_head {
|
95 |
-
height:
|
96 |
-
border-radius: 3px;
|
97 |
background: #F9F9F9 url("../images/menu-arrows.png") no-repeat 4px 8px;
|
98 |
}
|
99 |
|
100 |
-
.ws_menu_separator .ws_item_title {
|
101 |
-
display: none;
|
102 |
-
}
|
103 |
-
|
104 |
.ws_menu_separator.ws_active .ws_item_head {
|
105 |
background: #999 url("../images/menu-arrows.png") no-repeat 4px 8px;
|
106 |
}
|
107 |
|
|
|
|
|
|
|
|
|
|
|
108 |
/**
|
109 |
* Active item
|
110 |
*/
|
@@ -125,6 +110,33 @@ a.ws_edit_link:hover {
|
|
125 |
border-bottom-color: #6d6d6d;
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
/**
|
129 |
* Dropping menus on other menus.
|
130 |
*/
|
@@ -190,22 +202,44 @@ a.ws_button:hover {
|
|
190 |
.ui-dialog {
|
191 |
background: white;
|
192 |
border: 1px solid #c0c0c0;
|
|
|
|
|
193 |
}
|
194 |
|
195 |
.ui-dialog-titlebar {
|
196 |
-
background-color: #
|
|
|
197 |
}
|
198 |
|
199 |
.ui-dialog-title {
|
200 |
-
color:
|
201 |
}
|
202 |
|
203 |
.ui-dialog-titlebar-close {
|
204 |
-
background:
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
}
|
207 |
|
208 |
.ui-dialog-titlebar-close:hover {
|
209 |
-
|
210 |
-
|
211 |
}
|
10 |
-webkit-box-shadow: inset 0 1px 0 #fff;
|
11 |
box-shadow: inset 0 1px 0 #fff;
|
12 |
|
13 |
+
/*-webkit-border-radius: 2px;
|
14 |
+
border-radius: 2px;*/
|
15 |
}
|
16 |
|
17 |
/**
|
19 |
*/
|
20 |
|
21 |
.ws_item_head {
|
22 |
+
padding: 3px;
|
|
|
|
|
23 |
|
24 |
background-color: #d9d9d9;
|
|
|
|
|
25 |
background-image: -ms-linear-gradient(top, #e9e9e9, #d9d9d9);
|
26 |
background-image: -moz-linear-gradient(top, #e9e9e9, #d9d9d9);
|
27 |
background-image: -webkit-gradient(linear, left top, left bottom, from(#e9e9e9), to(#d9d9d9));
|
28 |
background-image: -webkit-linear-gradient(top, #e9e9e9, #d9d9d9);
|
29 |
+
background-image: linear-gradient(to bottom, #e9e9e9, #d9d9d9);
|
|
|
30 |
}
|
31 |
|
32 |
.ws_item_title {
|
|
|
|
|
|
|
33 |
color: #222;
|
34 |
+
text-shadow: #FFFFFF 0 1px 0;
|
|
|
|
|
|
|
|
|
35 |
}
|
36 |
|
37 |
/**
|
39 |
*/
|
40 |
|
41 |
.ws_edit_link {
|
42 |
+
background: transparent url(../images/arrows.png) no-repeat center 3px;
|
|
|
|
|
|
|
43 |
overflow: hidden;
|
44 |
text-indent:-999em;
|
45 |
}
|
49 |
}
|
50 |
|
51 |
.ws_edit_link:active {
|
52 |
+
background-image: url(../images/arrows-dark.png);
|
53 |
}
|
54 |
|
55 |
.ws_edit_link_expanded {
|
77 |
}
|
78 |
|
79 |
.ws_menu_separator .ws_item_head {
|
80 |
+
min-height: 22px;
|
|
|
81 |
background: #F9F9F9 url("../images/menu-arrows.png") no-repeat 4px 8px;
|
82 |
}
|
83 |
|
|
|
|
|
|
|
|
|
84 |
.ws_menu_separator.ws_active .ws_item_head {
|
85 |
background: #999 url("../images/menu-arrows.png") no-repeat 4px 8px;
|
86 |
}
|
87 |
|
88 |
+
/* Offset the separator image in actor view to prevent it from overlapping the checkbox. */
|
89 |
+
.ws_is_actor_view .ws_menu_separator .ws_item_head {
|
90 |
+
background-position: 25px 8px;
|
91 |
+
}
|
92 |
+
|
93 |
/**
|
94 |
* Active item
|
95 |
*/
|
110 |
border-bottom-color: #6d6d6d;
|
111 |
}
|
112 |
|
113 |
+
/**
|
114 |
+
* Hidden items.
|
115 |
+
*/
|
116 |
+
.ws_is_actor_view .ws_container.ws_is_hidden_for_actor .ws_item_head {
|
117 |
+
background: #F9F9F9 linear-gradient(to top, #F3F3F3, #FFFFFF);
|
118 |
+
}
|
119 |
+
|
120 |
+
/* selected hidden items */
|
121 |
+
.ws_is_actor_view .ws_is_hidden_for_actor.ws_active .ws_item_head {
|
122 |
+
background: #dedede linear-gradient(to top, #8f8f8f, #a2a2a2);
|
123 |
+
}
|
124 |
+
.ws_is_actor_view .ws_is_hidden_for_actor.ws_active .ws_item_title {
|
125 |
+
color: #fff;
|
126 |
+
text-shadow: none;
|
127 |
+
}
|
128 |
+
|
129 |
+
/* hidden separators */
|
130 |
+
.ws_is_actor_view .ws_menu_separator.ws_is_hidden_for_actor .ws_item_head {
|
131 |
+
/* Override gradient with the separator image. */
|
132 |
+
background: url("../images/menu-arrows.png") no-repeat 25px 8px;
|
133 |
+
}
|
134 |
+
/* selected hidden separators */
|
135 |
+
.ws_menu_separator.ws_is_hidden_for_actor.ws_active .ws_item_head {
|
136 |
+
background: #aaa url("../images/menu-arrows.png") no-repeat 25px 8px;
|
137 |
+
}
|
138 |
+
|
139 |
+
|
140 |
/**
|
141 |
* Dropping menus on other menus.
|
142 |
*/
|
202 |
.ui-dialog {
|
203 |
background: white;
|
204 |
border: 1px solid #c0c0c0;
|
205 |
+
|
206 |
+
border-radius: 0;
|
207 |
}
|
208 |
|
209 |
.ui-dialog-titlebar {
|
210 |
+
background-color: #fcfcfc;;
|
211 |
+
border-bottom-color: #dfdfdf;
|
212 |
}
|
213 |
|
214 |
.ui-dialog-title {
|
215 |
+
color: #444444;
|
216 |
}
|
217 |
|
218 |
.ui-dialog-titlebar-close {
|
219 |
+
background-color: transparent;
|
220 |
+
border-style: none;
|
221 |
+
|
222 |
+
color: #666;
|
223 |
+
cursor: pointer;
|
224 |
+
padding: 0;
|
225 |
+
position: absolute;
|
226 |
+
top: 0;
|
227 |
+
right: 0;
|
228 |
+
width: 36px;
|
229 |
+
height: 30px;
|
230 |
+
text-align: center;
|
231 |
+
}
|
232 |
+
|
233 |
+
.ui-dialog-titlebar-close::before {
|
234 |
+
font: normal 20px/30px 'dashicons';
|
235 |
+
content: '\f158';
|
236 |
+
|
237 |
+
vertical-align: top;
|
238 |
+
width: 36px;
|
239 |
+
height: 30px;
|
240 |
}
|
241 |
|
242 |
.ui-dialog-titlebar-close:hover {
|
243 |
+
background: transparent none;
|
244 |
+
color: #2ea2cc;
|
245 |
}
|
includes/editor-page.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
/**
|
3 |
* @var array $editor_data Various pieces of data passed by the plugin.
|
4 |
*/
|
|
|
5 |
$images_url = $editor_data['images_url'];
|
6 |
|
7 |
$icons = array(
|
@@ -126,13 +127,15 @@ if ( apply_filters('admin_menu_editor_is_pro', false) ) {
|
|
126 |
<a id='ws_toggle_all_menus' class='ws_button' href='javascript:void(0)'
|
127 |
title='Toggle all menus for the selected role'><img src='<?php echo $icons['toggle-all']; ?>' alt="Toggle all" /></a>
|
128 |
<?php endif; ?>
|
|
|
|
|
129 |
</div>
|
130 |
</div>
|
131 |
|
132 |
<div id='ws_menu_box' class="ws_box">
|
133 |
</div>
|
134 |
|
135 |
-
<?php do_action('
|
136 |
</div>
|
137 |
|
138 |
<div class='ws_main_container'>
|
@@ -163,13 +166,15 @@ if ( apply_filters('admin_menu_editor_is_pro', false) ) {
|
|
163 |
<a id='ws_sort_descending' class='ws_button' href='javascript:void(0)' title='Sort descending'>
|
164 |
<img src='<?php echo $images_url; ?>/sort_descending.png' alt="Sort descending" />
|
165 |
</a>
|
|
|
|
|
166 |
</div>
|
167 |
</div>
|
168 |
|
169 |
<div id='ws_submenu_box' class="ws_box">
|
170 |
</div>
|
171 |
|
172 |
-
<?php do_action('
|
173 |
</div>
|
174 |
|
175 |
<div class="ws_basic_container">
|
@@ -188,7 +193,7 @@ if ( apply_filters('admin_menu_editor_is_pro', false) ) {
|
|
188 |
<input type="button" id='ws_load_menu' value="Load default menu" class="button ws_main_button" />
|
189 |
|
190 |
<?php
|
191 |
-
do_action('
|
192 |
?>
|
193 |
</div>
|
194 |
|
@@ -342,7 +347,7 @@ if ( apply_filters('admin_menu_editor_is_pro', false) ) {
|
|
342 |
function ws_ame_print_dashicon_option($icon, $isExtraIcon = false) {
|
343 |
printf(
|
344 |
'<div class="ws_icon_option%3$s" title="%1$s" data-icon-url="dashicons-%2$s">
|
345 |
-
<div class="ws_icon_image icon16 dashicons dashicons-%2$s"
|
346 |
</div>',
|
347 |
esc_attr(ucwords(str_replace('-', ' ', $icon))),
|
348 |
$icon,
|
@@ -441,6 +446,28 @@ if ( apply_filters('admin_menu_editor_is_pro', false) ) {
|
|
441 |
</label>
|
442 |
</div>
|
443 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
444 |
|
445 |
<script type='text/javascript'>
|
446 |
var defaultMenu = <?php echo $editor_data['default_menu_js']; ?>;
|
@@ -450,4 +477,4 @@ var customMenu = <?php echo $editor_data['custom_menu_js']; ?>;
|
|
450 |
<?php
|
451 |
|
452 |
//Let the Pro version script output it's extra HTML & scripts.
|
453 |
-
do_action('
|
2 |
/**
|
3 |
* @var array $editor_data Various pieces of data passed by the plugin.
|
4 |
*/
|
5 |
+
$current_user = wp_get_current_user();
|
6 |
$images_url = $editor_data['images_url'];
|
7 |
|
8 |
$icons = array(
|
127 |
<a id='ws_toggle_all_menus' class='ws_button' href='javascript:void(0)'
|
128 |
title='Toggle all menus for the selected role'><img src='<?php echo $icons['toggle-all']; ?>' alt="Toggle all" /></a>
|
129 |
<?php endif; ?>
|
130 |
+
|
131 |
+
<div class="clear"></div>
|
132 |
</div>
|
133 |
</div>
|
134 |
|
135 |
<div id='ws_menu_box' class="ws_box">
|
136 |
</div>
|
137 |
|
138 |
+
<?php do_action('admin_menu_editor-container', 'menu'); ?>
|
139 |
</div>
|
140 |
|
141 |
<div class='ws_main_container'>
|
166 |
<a id='ws_sort_descending' class='ws_button' href='javascript:void(0)' title='Sort descending'>
|
167 |
<img src='<?php echo $images_url; ?>/sort_descending.png' alt="Sort descending" />
|
168 |
</a>
|
169 |
+
|
170 |
+
<div class="clear"></div>
|
171 |
</div>
|
172 |
</div>
|
173 |
|
174 |
<div id='ws_submenu_box' class="ws_box">
|
175 |
</div>
|
176 |
|
177 |
+
<?php do_action('admin_menu_editor-container', 'submenu'); ?>
|
178 |
</div>
|
179 |
|
180 |
<div class="ws_basic_container">
|
193 |
<input type="button" id='ws_load_menu' value="Load default menu" class="button ws_main_button" />
|
194 |
|
195 |
<?php
|
196 |
+
do_action('admin_menu_editor-sidebar');
|
197 |
?>
|
198 |
</div>
|
199 |
|
347 |
function ws_ame_print_dashicon_option($icon, $isExtraIcon = false) {
|
348 |
printf(
|
349 |
'<div class="ws_icon_option%3$s" title="%1$s" data-icon-url="dashicons-%2$s">
|
350 |
+
<div class="ws_icon_image icon16 dashicons dashicons-%2$s"></div>
|
351 |
</div>',
|
352 |
esc_attr(ucwords(str_replace('-', ' ', $icon))),
|
353 |
$icon,
|
446 |
</label>
|
447 |
</div>
|
448 |
|
449 |
+
<!-- Confirmation dialog when trying to delete a non-custom item. -->
|
450 |
+
<div id="ws-ame-menu-deletion-error" title="Error" style="display: none;">
|
451 |
+
<div class="ws_dialog_panel">
|
452 |
+
Sorry, it's not possible to permanently delete
|
453 |
+
<span id="ws-ame-menu-type-desc">{a built-in menu item|an item added by another plugin}</span>.
|
454 |
+
Would you like to hide it instead?
|
455 |
+
</div>
|
456 |
+
|
457 |
+
<div class="ws_dialog_buttons ame-vertical-button-list">
|
458 |
+
<?php
|
459 |
+
submit_button('Hide it from all users', 'secondary', 'ws_hide_menu_from_everyone', false);
|
460 |
+
submit_button(
|
461 |
+
sprintf('Hide it from everyone except "%s"', $current_user->get('user_login')),
|
462 |
+
'secondary',
|
463 |
+
'ws_hide_menu_except_current_user',
|
464 |
+
false
|
465 |
+
);
|
466 |
+
submit_button('Cancel', 'secondary', 'ws_cancel_menu_deletion', false);
|
467 |
+
?>
|
468 |
+
</div>
|
469 |
+
</div>
|
470 |
+
|
471 |
|
472 |
<script type='text/javascript'>
|
473 |
var defaultMenu = <?php echo $editor_data['default_menu_js']; ?>;
|
477 |
<?php
|
478 |
|
479 |
//Let the Pro version script output it's extra HTML & scripts.
|
480 |
+
do_action('admin_menu_editor-footer');
|
includes/menu-editor-core.php
CHANGED
@@ -104,6 +104,12 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
104 |
'show_deprecated_hide_button' => null,
|
105 |
'dashboard_hiding_confirmation_enabled' => true,
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
//Enable/disable the admin notice that tells the user where the plugin settings menu is.
|
108 |
'show_plugin_menu_notice' => true,
|
109 |
);
|
@@ -234,13 +240,13 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
234 |
$page = add_options_page(
|
235 |
apply_filters('admin_menu_editor-self_page_title', 'Menu Editor'),
|
236 |
apply_filters('admin_menu_editor-self_menu_title', 'Menu Editor'),
|
237 |
-
apply_filters('
|
238 |
'menu_editor',
|
239 |
array(&$this, 'page_menu_editor')
|
240 |
);
|
241 |
//Output our JS & CSS on that page only
|
242 |
-
add_action("admin_print_scripts-$page", array(
|
243 |
-
add_action("admin_print_styles-$page", array(
|
244 |
|
245 |
//Compatibility fix for All In One Event Calendar; see the callback for details.
|
246 |
add_action("admin_print_scripts-$page", array($this, 'dequeue_ai1ec_scripts'));
|
@@ -258,10 +264,18 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
258 |
//Store the "original" menus for later use in the editor
|
259 |
$this->default_wp_menu = $menu;
|
260 |
$this->default_wp_submenu = $submenu;
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
262 |
//Generate item templates from the default menu.
|
263 |
$this->item_templates = $this->build_templates($this->default_wp_menu, $this->default_wp_submenu);
|
264 |
|
|
|
|
|
|
|
265 |
//Is there a custom menu to use?
|
266 |
$custom_menu = $this->load_custom_menu();
|
267 |
if ( $custom_menu !== null ){
|
@@ -527,6 +541,8 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
527 |
'adminAjaxUrl' => admin_url('admin-ajax.php'),
|
528 |
'hideAdvancedSettings' => (boolean)$this->options['hide_advanced_settings'],
|
529 |
'showExtraIcons' => $showExtraIcons,
|
|
|
|
|
530 |
'hideAdvancedSettingsNonce' => wp_create_nonce('ws_ame_save_screen_options'),
|
531 |
'dashiconsAvailable' => wp_style_is('dashicons', 'registered'),
|
532 |
'captionShowAdvanced' => 'Show advanced options',
|
@@ -542,6 +558,9 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
542 |
'defaults' => ameMenuItem::custom_item_defaults(),
|
543 |
),
|
544 |
|
|
|
|
|
|
|
545 |
'actors' => $actors,
|
546 |
'roles' => $roles,
|
547 |
'users' => $users,
|
@@ -609,8 +628,8 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
609 |
array('menu-editor-base-style')
|
610 |
);
|
611 |
wp_register_auto_versioned_style(
|
612 |
-
'menu-editor-colours-wp-
|
613 |
-
plugins_url('css/style-wp-
|
614 |
array('menu-editor-base-style')
|
615 |
);
|
616 |
|
@@ -625,7 +644,8 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
625 |
wp_enqueue_style('menu-editor-screen-meta');
|
626 |
}
|
627 |
|
628 |
-
|
|
|
629 |
wp_enqueue_style('wp-color-picker');
|
630 |
}
|
631 |
|
@@ -805,6 +825,52 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
805 |
return strip_tags( preg_replace('@<span[^>]*>.*</span>@i', '', $title) );
|
806 |
}
|
807 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
808 |
/**
|
809 |
* Merge a custom menu with the current default WordPress menu. Adds/replaces defaults,
|
810 |
* inserts new items and removes missing items.
|
@@ -877,25 +943,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
877 |
|
878 |
//Now we have some items marked as missing, and some items in lookup arrays
|
879 |
//that are not marked as used. Lets remove the missing items from the tree.
|
880 |
-
$
|
881 |
-
foreach($tree as $file => $topmenu) {
|
882 |
-
if ( $topmenu['missing'] ) {
|
883 |
-
continue;
|
884 |
-
}
|
885 |
-
$filteredSubmenu = array();
|
886 |
-
if (is_array($topmenu['items'])) {
|
887 |
-
foreach($topmenu['items'] as $index => $item) {
|
888 |
-
if ( !$item['missing'] ) {
|
889 |
-
$filteredSubmenu[$index] = $item;
|
890 |
-
}
|
891 |
-
}
|
892 |
-
|
893 |
-
}
|
894 |
-
$topmenu['items'] = $filteredSubmenu;
|
895 |
-
$filteredTree[$file] = $topmenu;
|
896 |
-
}
|
897 |
-
|
898 |
-
$tree = $filteredTree;
|
899 |
|
900 |
//Lets merge in the unused items.
|
901 |
foreach ($this->item_templates as $template_id => $template){
|
@@ -1035,6 +1083,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1035 |
|
1036 |
//Prepare the submenu of this menu
|
1037 |
$new_items = array();
|
|
|
1038 |
if( !empty($topmenu['items']) ){
|
1039 |
$items = $topmenu['items'];
|
1040 |
//Sort by position
|
@@ -1051,9 +1100,18 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1051 |
|
1052 |
//Make a note of the page's correct title so we can fix it later if necessary.
|
1053 |
$this->title_lookups[$item['file']] = !empty($item['page_title']) ? $item['page_title'] : $item['menu_title'];
|
|
|
|
|
|
|
1054 |
}
|
1055 |
}
|
1056 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1057 |
$topmenu['items'] = $new_items;
|
1058 |
$new_tree[] = $topmenu;
|
1059 |
}
|
@@ -1084,8 +1142,6 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1084 |
$this->reverse_item_lookup[$topmenu['url']] = $topmenu;
|
1085 |
}
|
1086 |
|
1087 |
-
$new_menu[] = $this->convert_to_wp_format($topmenu);
|
1088 |
-
|
1089 |
foreach($topmenu['items'] as $item) {
|
1090 |
$trueAccess = isset($this->page_access_lookup[$item['url']]) ? $this->page_access_lookup[$item['url']] : null;
|
1091 |
if ( ($trueAccess === 'do_not_allow') && ($item['access_level'] !== $trueAccess) ) {
|
@@ -1104,6 +1160,8 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1104 |
$this->reverse_item_lookup[$item['url']] = $item;
|
1105 |
$new_submenu[$topmenu['file']][] = $this->convert_to_wp_format($item);
|
1106 |
}
|
|
|
|
|
1107 |
}
|
1108 |
|
1109 |
$this->custom_wp_menu = $new_menu;
|
@@ -1164,12 +1222,28 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1164 |
}
|
1165 |
}
|
1166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1167 |
//Menus that have both a custom icon URL and a "menu-icon-*" class will get two overlapping icons.
|
1168 |
//Fix this by automatically removing the class. The user can set a custom class attr. to override.
|
|
|
|
|
1169 |
if (
|
1170 |
ameMenuItem::is_default($item, 'css_class')
|
1171 |
-
&&
|
1172 |
-
&&
|
1173 |
) {
|
1174 |
$new_classes = preg_replace('@\bmenu-icon-[^\s]+\b@', '', $item['defaults']['css_class']);
|
1175 |
if ( $new_classes !== $item['defaults']['css_class'] ) {
|
@@ -1193,6 +1267,20 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1193 |
$item['icon_url'] = 'none';
|
1194 |
}
|
1195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1196 |
//Used later to determine the current page based on URL.
|
1197 |
if ( empty($item['url']) ) {
|
1198 |
$original_parent = !empty($item['defaults']['parent']) ? $item['defaults']['parent'] : $parent;
|
@@ -1314,7 +1402,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1314 |
}
|
1315 |
|
1316 |
$action = isset($this->post['action']) ? $this->post['action'] : (isset($this->get['action']) ? $this->get['action'] : '');
|
1317 |
-
do_action('
|
1318 |
|
1319 |
if ( !empty($action) ) {
|
1320 |
$this->handle_form_submission($this->post, $action);
|
@@ -1365,7 +1453,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1365 |
//Also, automatically select the last selected actor (convenience feature).
|
1366 |
$query = array('message' => 1);
|
1367 |
if ( isset($post['selected_actor']) && !empty($post['selected_actor']) ) {
|
1368 |
-
$query['selected_actor'] = strval($post['selected_actor']);
|
1369 |
}
|
1370 |
wp_redirect( add_query_arg($query, $url) );
|
1371 |
die();
|
@@ -1429,6 +1517,24 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1429 |
$this->options['show_deprecated_hide_button'] = !empty($this->post['show_deprecated_hide_button']);
|
1430 |
}
|
1431 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1432 |
$this->save_options();
|
1433 |
wp_redirect(add_query_arg('updated', 1, $this->get_settings_page_url()));
|
1434 |
}
|
@@ -1617,11 +1723,14 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
1617 |
* @param array $args The capability passed to current_user_can, the current user's ID, and other args.
|
1618 |
* @return array Filtered version of $allcaps
|
1619 |
*/
|
1620 |
-
function hook_user_has_cap($allcaps, $required_caps, $args){
|
1621 |
//Be careful not to overwrite a super_admin cap added by other plugins
|
1622 |
//For example, Advanced Access Manager also adds this capability.
|
1623 |
-
if (
|
1624 |
-
$
|
|
|
|
|
|
|
1625 |
}
|
1626 |
return $allcaps;
|
1627 |
}
|
@@ -2033,7 +2142,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
2033 |
'ame-helper-style',
|
2034 |
plugins_url('css/admin.css', $this->plugin_file),
|
2035 |
array(),
|
2036 |
-
'
|
2037 |
);
|
2038 |
}
|
2039 |
|
@@ -2085,7 +2194,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
2085 |
* @return string
|
2086 |
*/
|
2087 |
private function get_formatted_security_log() {
|
2088 |
-
$log = '<div style="font: 12px/
|
2089 |
$log .= implode("<br>\n", $this->security_log);
|
2090 |
$log .= '</div>';
|
2091 |
return $log;
|
@@ -2183,6 +2292,55 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
2183 |
return $name;
|
2184 |
}
|
2185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2186 |
/**
|
2187 |
* Tell new users how to access the plugin settings page.
|
2188 |
*/
|
104 |
'show_deprecated_hide_button' => null,
|
105 |
'dashboard_hiding_confirmation_enabled' => true,
|
106 |
|
107 |
+
//When to show submenu icons.
|
108 |
+
'submenu_icons_enabled' => 'if_custom', //"never", "if_custom" or "always".
|
109 |
+
|
110 |
+
//Menu editor UI colour scheme. "Classic" is the old blue/yellow scheme, and "wp-grey" is more WP-like.
|
111 |
+
'ui_colour_scheme' => 'classic',
|
112 |
+
|
113 |
//Enable/disable the admin notice that tells the user where the plugin settings menu is.
|
114 |
'show_plugin_menu_notice' => true,
|
115 |
);
|
240 |
$page = add_options_page(
|
241 |
apply_filters('admin_menu_editor-self_page_title', 'Menu Editor'),
|
242 |
apply_filters('admin_menu_editor-self_menu_title', 'Menu Editor'),
|
243 |
+
apply_filters('admin_menu_editor-capability', 'manage_options'),
|
244 |
'menu_editor',
|
245 |
array(&$this, 'page_menu_editor')
|
246 |
);
|
247 |
//Output our JS & CSS on that page only
|
248 |
+
add_action("admin_print_scripts-$page", array($this, 'enqueue_scripts'));
|
249 |
+
add_action("admin_print_styles-$page", array($this, 'enqueue_styles'));
|
250 |
|
251 |
//Compatibility fix for All In One Event Calendar; see the callback for details.
|
252 |
add_action("admin_print_scripts-$page", array($this, 'dequeue_ai1ec_scripts'));
|
264 |
//Store the "original" menus for later use in the editor
|
265 |
$this->default_wp_menu = $menu;
|
266 |
$this->default_wp_submenu = $submenu;
|
267 |
+
|
268 |
+
//Compatibility fix for bbPress.
|
269 |
+
$this->apply_bbpress_compat_fix();
|
270 |
+
//Compatibility fix for WordPress Mu Domain Mapping.
|
271 |
+
$this->apply_wpmu_domain_mapping_fix();
|
272 |
+
|
273 |
//Generate item templates from the default menu.
|
274 |
$this->item_templates = $this->build_templates($this->default_wp_menu, $this->default_wp_submenu);
|
275 |
|
276 |
+
//Add extra templates that are not part of the normal menu.
|
277 |
+
$this->item_templates = $this->add_special_templates($this->item_templates);
|
278 |
+
|
279 |
//Is there a custom menu to use?
|
280 |
$custom_menu = $this->load_custom_menu();
|
281 |
if ( $custom_menu !== null ){
|
541 |
'adminAjaxUrl' => admin_url('admin-ajax.php'),
|
542 |
'hideAdvancedSettings' => (boolean)$this->options['hide_advanced_settings'],
|
543 |
'showExtraIcons' => $showExtraIcons,
|
544 |
+
'submenuIconsEnabled' => $this->options['submenu_icons_enabled'],
|
545 |
+
|
546 |
'hideAdvancedSettingsNonce' => wp_create_nonce('ws_ame_save_screen_options'),
|
547 |
'dashiconsAvailable' => wp_style_is('dashicons', 'registered'),
|
548 |
'captionShowAdvanced' => 'Show advanced options',
|
558 |
'defaults' => ameMenuItem::custom_item_defaults(),
|
559 |
),
|
560 |
|
561 |
+
'unclickableTemplateId' => ameMenuItem::unclickableTemplateId,
|
562 |
+
'unclickableTemplateClass' => ameMenuItem::unclickableTemplateClass,
|
563 |
+
|
564 |
'actors' => $actors,
|
565 |
'roles' => $roles,
|
566 |
'users' => $users,
|
628 |
array('menu-editor-base-style')
|
629 |
);
|
630 |
wp_register_auto_versioned_style(
|
631 |
+
'menu-editor-colours-wp-grey',
|
632 |
+
plugins_url('css/style-wp-grey.css', $this->plugin_file),
|
633 |
array('menu-editor-base-style')
|
634 |
);
|
635 |
|
644 |
wp_enqueue_style('menu-editor-screen-meta');
|
645 |
}
|
646 |
|
647 |
+
$scheme = $this->options['ui_colour_scheme'];
|
648 |
+
wp_enqueue_style('menu-editor-colours-' . $scheme);
|
649 |
wp_enqueue_style('wp-color-picker');
|
650 |
}
|
651 |
|
825 |
return strip_tags( preg_replace('@<span[^>]*>.*</span>@i', '', $title) );
|
826 |
}
|
827 |
|
828 |
+
/**
|
829 |
+
* Generate special menu templates and add them to the input template list.
|
830 |
+
*
|
831 |
+
* @param array $templates Template list.
|
832 |
+
* @return array Modified template list.
|
833 |
+
*/
|
834 |
+
private function add_special_templates($templates) {
|
835 |
+
//Add a special template for unclickable menu items. These can be used as headers and such.
|
836 |
+
$itemDefaults = ameMenuItem::custom_item_defaults();
|
837 |
+
$unclickableDefaults = array_merge(
|
838 |
+
$itemDefaults,
|
839 |
+
array(
|
840 |
+
'file' => '#' . ameMenuItem::unclickableTemplateClass,
|
841 |
+
'url' => '#' . ameMenuItem::unclickableTemplateClass,
|
842 |
+
'css_class' => $itemDefaults['css_class'] . ' ' . ameMenuItem::unclickableTemplateClass,
|
843 |
+
'menu_title' => 'Unclickable Menu',
|
844 |
+
)
|
845 |
+
);
|
846 |
+
$templates[ameMenuItem::unclickableTemplateId] = array(
|
847 |
+
'name' => '< None >',
|
848 |
+
'used' => true,
|
849 |
+
'defaults' => $unclickableDefaults,
|
850 |
+
);
|
851 |
+
|
852 |
+
if ( $this->is_pro_version() ) {
|
853 |
+
//The Pro version has a [wp-logout-url] shortcode. Lets make it easier o use
|
854 |
+
//by adding it to the "Target page" dropdown.
|
855 |
+
$logoutDefaults = array_merge(
|
856 |
+
ameMenuItem::basic_defaults(),
|
857 |
+
array(
|
858 |
+
'menu_title' => 'Logout',
|
859 |
+
'file' => '[wp-logout-url]',
|
860 |
+
'url' => '[wp-logout-url]',
|
861 |
+
'icon_url' => 'dashicons-migrate',
|
862 |
+
)
|
863 |
+
);
|
864 |
+
$templates['>logout'] = array(
|
865 |
+
'name' => 'Logout',
|
866 |
+
'used' => true,
|
867 |
+
'defaults' => $logoutDefaults,
|
868 |
+
);
|
869 |
+
}
|
870 |
+
|
871 |
+
return $templates;
|
872 |
+
}
|
873 |
+
|
874 |
/**
|
875 |
* Merge a custom menu with the current default WordPress menu. Adds/replaces defaults,
|
876 |
* inserts new items and removes missing items.
|
943 |
|
944 |
//Now we have some items marked as missing, and some items in lookup arrays
|
945 |
//that are not marked as used. Lets remove the missing items from the tree.
|
946 |
+
$tree = ameMenu::remove_missing_items($tree);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
947 |
|
948 |
//Lets merge in the unused items.
|
949 |
foreach ($this->item_templates as $template_id => $template){
|
1083 |
|
1084 |
//Prepare the submenu of this menu
|
1085 |
$new_items = array();
|
1086 |
+
$has_submenu_icons = false;
|
1087 |
if( !empty($topmenu['items']) ){
|
1088 |
$items = $topmenu['items'];
|
1089 |
//Sort by position
|
1100 |
|
1101 |
//Make a note of the page's correct title so we can fix it later if necessary.
|
1102 |
$this->title_lookups[$item['file']] = !empty($item['page_title']) ? $item['page_title'] : $item['menu_title'];
|
1103 |
+
|
1104 |
+
//Keep track of which menus have items with icons.
|
1105 |
+
$has_submenu_icons = $has_submenu_icons || !empty($item['has_submenu_icon']);
|
1106 |
}
|
1107 |
}
|
1108 |
|
1109 |
+
//The ame-has-submenu-icons class lets us change the appearance of all submenu items at once,
|
1110 |
+
//without having to add classes/styles to each item individually.
|
1111 |
+
if ( $has_submenu_icons && (strpos($topmenu['css_class'], 'ame-has-submenu-icons') === false) ) {
|
1112 |
+
$topmenu['css_class'] .= ' ame-has-submenu-icons';
|
1113 |
+
}
|
1114 |
+
|
1115 |
$topmenu['items'] = $new_items;
|
1116 |
$new_tree[] = $topmenu;
|
1117 |
}
|
1142 |
$this->reverse_item_lookup[$topmenu['url']] = $topmenu;
|
1143 |
}
|
1144 |
|
|
|
|
|
1145 |
foreach($topmenu['items'] as $item) {
|
1146 |
$trueAccess = isset($this->page_access_lookup[$item['url']]) ? $this->page_access_lookup[$item['url']] : null;
|
1147 |
if ( ($trueAccess === 'do_not_allow') && ($item['access_level'] !== $trueAccess) ) {
|
1160 |
$this->reverse_item_lookup[$item['url']] = $item;
|
1161 |
$new_submenu[$topmenu['file']][] = $this->convert_to_wp_format($item);
|
1162 |
}
|
1163 |
+
|
1164 |
+
$new_menu[] = $this->convert_to_wp_format($topmenu);
|
1165 |
}
|
1166 |
|
1167 |
$this->custom_wp_menu = $new_menu;
|
1222 |
}
|
1223 |
}
|
1224 |
|
1225 |
+
//Give each unclickable item a unique URL.
|
1226 |
+
if ( $item['template_id'] === ameMenuItem::unclickableTemplateId ) {
|
1227 |
+
static $unclickableCounter = 0;
|
1228 |
+
$unclickableCounter++;
|
1229 |
+
$unclickableUrl = '#' . ameMenuItem::unclickableTemplateClass . '-' . $unclickableCounter;
|
1230 |
+
$item['file'] = $item['url'] = $unclickableUrl;
|
1231 |
+
|
1232 |
+
//The item must have the special "unclickable" class even if the user overrides the class.
|
1233 |
+
$cssClass = ameMenuItem::get($item, 'css_class', '');
|
1234 |
+
if ( strpos($cssClass, ameMenuItem::unclickableTemplateClass) === false ) {
|
1235 |
+
$item['css_class'] = ameMenuItem::unclickableTemplateClass . ' ' . $cssClass;
|
1236 |
+
}
|
1237 |
+
}
|
1238 |
+
|
1239 |
//Menus that have both a custom icon URL and a "menu-icon-*" class will get two overlapping icons.
|
1240 |
//Fix this by automatically removing the class. The user can set a custom class attr. to override.
|
1241 |
+
$hasCustomIconUrl = !ameMenuItem::is_default($item, 'icon_url');
|
1242 |
+
$hasIcon = !in_array(ameMenuItem::get($item, 'icon_url'), array('', 'none', 'div'));
|
1243 |
if (
|
1244 |
ameMenuItem::is_default($item, 'css_class')
|
1245 |
+
&& $hasCustomIconUrl
|
1246 |
+
&& $hasIcon //Skip "no icon" settings.
|
1247 |
) {
|
1248 |
$new_classes = preg_replace('@\bmenu-icon-[^\s]+\b@', '', $item['defaults']['css_class']);
|
1249 |
if ( $new_classes !== $item['defaults']['css_class'] ) {
|
1267 |
$item['icon_url'] = 'none';
|
1268 |
}
|
1269 |
|
1270 |
+
//Submenus must not have the "menu-top" class(-es). In WP versions that support submenu CSS classes,
|
1271 |
+
//it can break menu display.
|
1272 |
+
if ( !empty($item['css_class']) && ($item_type === 'submenu') ) {
|
1273 |
+
$item['css_class'] = preg_replace('@\bmenu-top(?:-[\w\-]+)?\b@', '', $item['css_class']);
|
1274 |
+
} elseif ( ($item_type === 'menu') && (!$item['separator']) && (!preg_match('@\bmenu-top\b@', $item['css_class'])) ) {
|
1275 |
+
//Top-level menus should always have the "menu-top" class.
|
1276 |
+
$item['css_class'] = 'menu-top ' . $item['css_class'];
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
//Add submenu icons if necessary.
|
1280 |
+
if ( ($item_type === 'submenu') && $hasIcon ) {
|
1281 |
+
$item = apply_filters('admin_menu_editor-submenu_with_icon', $item, $hasCustomIconUrl);
|
1282 |
+
}
|
1283 |
+
|
1284 |
//Used later to determine the current page based on URL.
|
1285 |
if ( empty($item['url']) ) {
|
1286 |
$original_parent = !empty($item['defaults']['parent']) ? $item['defaults']['parent'] : $parent;
|
1402 |
}
|
1403 |
|
1404 |
$action = isset($this->post['action']) ? $this->post['action'] : (isset($this->get['action']) ? $this->get['action'] : '');
|
1405 |
+
do_action('admin_menu_editor-header', $action);
|
1406 |
|
1407 |
if ( !empty($action) ) {
|
1408 |
$this->handle_form_submission($this->post, $action);
|
1453 |
//Also, automatically select the last selected actor (convenience feature).
|
1454 |
$query = array('message' => 1);
|
1455 |
if ( isset($post['selected_actor']) && !empty($post['selected_actor']) ) {
|
1456 |
+
$query['selected_actor'] = rawurlencode(strval($post['selected_actor']));
|
1457 |
}
|
1458 |
wp_redirect( add_query_arg($query, $url) );
|
1459 |
die();
|
1517 |
$this->options['show_deprecated_hide_button'] = !empty($this->post['show_deprecated_hide_button']);
|
1518 |
}
|
1519 |
|
1520 |
+
//Menu editor colour scheme.
|
1521 |
+
if ( !empty($this->post['ui_colour_scheme']) ) {
|
1522 |
+
$valid_colour_schemes = array('classic', 'wp-grey');
|
1523 |
+
$scheme = strval($this->post['ui_colour_scheme']);
|
1524 |
+
if ( in_array($scheme, $valid_colour_schemes) ) {
|
1525 |
+
$this->options['ui_colour_scheme'] = $scheme;
|
1526 |
+
}
|
1527 |
+
}
|
1528 |
+
|
1529 |
+
//Enable submenu icons.
|
1530 |
+
if ( !empty($this->post['submenu_icons_enabled']) ) {
|
1531 |
+
$submenu_icons_enabled = strval($this->post['submenu_icons_enabled']);
|
1532 |
+
$valid_icon_settings = array('never', 'if_custom', 'always');
|
1533 |
+
if ( in_array($submenu_icons_enabled, $valid_icon_settings, true) ) {
|
1534 |
+
$this->options['submenu_icons_enabled'] = $submenu_icons_enabled;
|
1535 |
+
}
|
1536 |
+
}
|
1537 |
+
|
1538 |
$this->save_options();
|
1539 |
wp_redirect(add_query_arg('updated', 1, $this->get_settings_page_url()));
|
1540 |
}
|
1723 |
* @param array $args The capability passed to current_user_can, the current user's ID, and other args.
|
1724 |
* @return array Filtered version of $allcaps
|
1725 |
*/
|
1726 |
+
function hook_user_has_cap($allcaps, /** @noinspection PhpUnusedParameterInspection */ $required_caps, $args){
|
1727 |
//Be careful not to overwrite a super_admin cap added by other plugins
|
1728 |
//For example, Advanced Access Manager also adds this capability.
|
1729 |
+
if ( is_array($allcaps) && !isset($allcaps['super_admin']) ){
|
1730 |
+
$user_id = intval($args[1]);
|
1731 |
+
if ( $user_id != 0 ) {
|
1732 |
+
$allcaps['super_admin'] = is_multisite() && is_super_admin($user_id);
|
1733 |
+
}
|
1734 |
}
|
1735 |
return $allcaps;
|
1736 |
}
|
2142 |
'ame-helper-style',
|
2143 |
plugins_url('css/admin.css', $this->plugin_file),
|
2144 |
array(),
|
2145 |
+
'20140630-3'
|
2146 |
);
|
2147 |
}
|
2148 |
|
2194 |
* @return string
|
2195 |
*/
|
2196 |
private function get_formatted_security_log() {
|
2197 |
+
$log = '<div style="font: 12px/17px Consolas, monospace; margin-bottom: 1em;">';
|
2198 |
$log .= implode("<br>\n", $this->security_log);
|
2199 |
$log .= '</div>';
|
2200 |
return $log;
|
2292 |
return $name;
|
2293 |
}
|
2294 |
|
2295 |
+
/**
|
2296 |
+
* Compatibility fix for bbPress 2.5.3.
|
2297 |
+
*
|
2298 |
+
* bbPress creates a bunch of "hidden" menu items in the admin_menu action only to remove them
|
2299 |
+
* later in an admin_head hook. This results in apparently duplicated menus showing up when AME is
|
2300 |
+
* active because AME processes the items before they get removed.
|
2301 |
+
*
|
2302 |
+
* This method works around the issue by explicitly removing those bbPress menus.
|
2303 |
+
*
|
2304 |
+
* @uses $this->default_wp_submenu
|
2305 |
+
*/
|
2306 |
+
private function apply_bbpress_compat_fix() {
|
2307 |
+
if ( !isset($this->default_wp_submenu, $this->default_wp_submenu['index.php']) ) {
|
2308 |
+
return;
|
2309 |
+
}
|
2310 |
+
|
2311 |
+
//Note to self: This would be easier if we could rely on anonymous function support being available.
|
2312 |
+
//Then we could just array_filter() the submenu with a closure as the callback.
|
2313 |
+
$items_to_remove = array('bbp-about' => null, 'bbp-credits' => null);
|
2314 |
+
foreach($this->default_wp_submenu['index.php'] as $index => $menu) {
|
2315 |
+
if ( array_key_exists($menu[2], $items_to_remove) ) {
|
2316 |
+
$items_to_remove[$menu[2]] = $index;
|
2317 |
+
}
|
2318 |
+
}
|
2319 |
+
|
2320 |
+
foreach($items_to_remove as $index) {
|
2321 |
+
if ( isset($index, $this->default_wp_submenu['index.php'][$index]) ) {
|
2322 |
+
unset($this->default_wp_submenu['index.php'][$index]);
|
2323 |
+
}
|
2324 |
+
}
|
2325 |
+
}
|
2326 |
+
|
2327 |
+
/**
|
2328 |
+
* Compatibility fix for WordPress Mu Domain Mapping 0.5.4.3.
|
2329 |
+
*
|
2330 |
+
* The aforementioned domain mapping plugin has a bug that makes the plugins_url() function
|
2331 |
+
* return incorrect URLs for plugins installed in /mu-plugins. Fixed by removing the offending
|
2332 |
+
* filter callback.
|
2333 |
+
*
|
2334 |
+
* Note that this won't break domain mapping. Domain Mapping adds two 'plugins_url' filters.
|
2335 |
+
* The buggy one is completely redundant and can be removed with no ill effects.
|
2336 |
+
*/
|
2337 |
+
private function apply_wpmu_domain_mapping_fix() {
|
2338 |
+
$priority = has_filter('plugins_url', 'domain_mapping_plugins_uri');
|
2339 |
+
if ( ($priority !== false) && (has_filter('plugins_url', 'domain_mapping_post_content') !== false) ) {
|
2340 |
+
remove_filter('plugins_url', 'domain_mapping_plugins_uri', $priority);
|
2341 |
+
}
|
2342 |
+
}
|
2343 |
+
|
2344 |
/**
|
2345 |
* Tell new users how to access the plugin settings page.
|
2346 |
*/
|
includes/menu-item.php
CHANGED
@@ -8,6 +8,9 @@
|
|
8 |
* currently registered hooks and the presence of specific files in admin/plugin folders.
|
9 |
*/
|
10 |
abstract class ameMenuItem {
|
|
|
|
|
|
|
11 |
/**
|
12 |
* @var array A partial list of files in /wp-admin/. Correct as of WP 3.8-RC1, 2013.12.04.
|
13 |
* When trying to determine if a menu links to one of the default WP admin pages, it's faster
|
@@ -34,14 +37,15 @@ abstract class ameMenuItem {
|
|
34 |
*/
|
35 |
public static function fromWpItem($item, $position = 0, $parent = '') {
|
36 |
static $separator_count = 0;
|
|
|
37 |
$item = array(
|
38 |
'menu_title' => $item[0],
|
39 |
'access_level' => $item[1], //= required capability
|
40 |
'file' => $item[2],
|
41 |
'page_title' => (isset($item[3]) ? $item[3] : ''),
|
42 |
-
'css_class' => (isset($item[4]) ? $item[4] :
|
43 |
'hookname' => (isset($item[5]) ? $item[5] : ''), //Used as the ID attr. of the generated HTML tag.
|
44 |
-
'icon_url' => (isset($item[6]) ? $item[6] : '
|
45 |
'position' => $position,
|
46 |
'parent' => $parent,
|
47 |
);
|
@@ -94,7 +98,7 @@ abstract class ameMenuItem {
|
|
94 |
//Fields that apply only to top level menus.
|
95 |
'css_class' => 'menu-top',
|
96 |
'hookname' => '',
|
97 |
-
'icon_url' => '
|
98 |
'separator' => false,
|
99 |
'colors' => false,
|
100 |
|
@@ -137,10 +141,11 @@ abstract class ameMenuItem {
|
|
137 |
return array(
|
138 |
'menu_title' => 'Custom Menu',
|
139 |
'access_level' => 'read',
|
|
|
140 |
'page_title' => '',
|
141 |
'css_class' => 'menu-top',
|
142 |
'hookname' => '',
|
143 |
-
'icon_url' => '
|
144 |
'open_in' => 'same_window',
|
145 |
'is_plugin_page' => false,
|
146 |
'page_heading' => '',
|
8 |
* currently registered hooks and the presence of specific files in admin/plugin folders.
|
9 |
*/
|
10 |
abstract class ameMenuItem {
|
11 |
+
const unclickableTemplateId = '>special:none';
|
12 |
+
const unclickableTemplateClass = 'ame-unclickable-menu-item';
|
13 |
+
|
14 |
/**
|
15 |
* @var array A partial list of files in /wp-admin/. Correct as of WP 3.8-RC1, 2013.12.04.
|
16 |
* When trying to determine if a menu links to one of the default WP admin pages, it's faster
|
37 |
*/
|
38 |
public static function fromWpItem($item, $position = 0, $parent = '') {
|
39 |
static $separator_count = 0;
|
40 |
+
$default_css_class = empty($parent) ? 'menu-top' : '';
|
41 |
$item = array(
|
42 |
'menu_title' => $item[0],
|
43 |
'access_level' => $item[1], //= required capability
|
44 |
'file' => $item[2],
|
45 |
'page_title' => (isset($item[3]) ? $item[3] : ''),
|
46 |
+
'css_class' => (isset($item[4]) ? $item[4] : $default_css_class),
|
47 |
'hookname' => (isset($item[5]) ? $item[5] : ''), //Used as the ID attr. of the generated HTML tag.
|
48 |
+
'icon_url' => (isset($item[6]) ? $item[6] : 'dashicons-admin-generic'),
|
49 |
'position' => $position,
|
50 |
'parent' => $parent,
|
51 |
);
|
98 |
//Fields that apply only to top level menus.
|
99 |
'css_class' => 'menu-top',
|
100 |
'hookname' => '',
|
101 |
+
'icon_url' => 'dashicons-admin-generic',
|
102 |
'separator' => false,
|
103 |
'colors' => false,
|
104 |
|
141 |
return array(
|
142 |
'menu_title' => 'Custom Menu',
|
143 |
'access_level' => 'read',
|
144 |
+
'extra_capability' => '',
|
145 |
'page_title' => '',
|
146 |
'css_class' => 'menu-top',
|
147 |
'hookname' => '',
|
148 |
+
'icon_url' => 'dashicons-admin-generic',
|
149 |
'open_in' => 'same_window',
|
150 |
'is_plugin_page' => false,
|
151 |
'page_heading' => '',
|
includes/menu.php
CHANGED
@@ -198,6 +198,28 @@ abstract class ameMenu {
|
|
198 |
|
199 |
return false;
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
202 |
|
203 |
|
198 |
|
199 |
return false;
|
200 |
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Recursively filter a list of menu items and remove items flagged as missing.
|
204 |
+
*
|
205 |
+
* @param array $items An array of menu items to filter.
|
206 |
+
* @return array
|
207 |
+
*/
|
208 |
+
public static function remove_missing_items($items) {
|
209 |
+
$items = array_filter($items, array(__CLASS__, 'is_not_missing'));
|
210 |
+
|
211 |
+
foreach($items as &$item) {
|
212 |
+
if ( !empty($item['items']) ) {
|
213 |
+
$item['items'] = self::remove_missing_items($item['items']);
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
return $items;
|
218 |
+
}
|
219 |
+
|
220 |
+
protected static function is_not_missing($item) {
|
221 |
+
return empty($item['missing']);
|
222 |
+
}
|
223 |
}
|
224 |
|
225 |
|
includes/settings-page.php
CHANGED
@@ -148,6 +148,62 @@ $isProVersion = apply_filters('admin_menu_editor_is_pro', false);
|
|
148 |
</td>
|
149 |
</tr>
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
<tr>
|
152 |
<th scope="row">Debugging</th>
|
153 |
<td>
|
148 |
</td>
|
149 |
</tr>
|
150 |
|
151 |
+
<tr>
|
152 |
+
<th scope="row">Editor colour scheme</th>
|
153 |
+
<td>
|
154 |
+
<fieldset>
|
155 |
+
<p>
|
156 |
+
<label>
|
157 |
+
<input type="radio" name="ui_colour_scheme" value="classic"
|
158 |
+
<?php checked('classic', $settings['ui_colour_scheme']); ?>>
|
159 |
+
Blue and yellow
|
160 |
+
</label>
|
161 |
+
</p>
|
162 |
+
|
163 |
+
<p>
|
164 |
+
<label>
|
165 |
+
<input type="radio" name="ui_colour_scheme" value="wp-grey"
|
166 |
+
<?php checked('wp-grey', $settings['ui_colour_scheme']); ?>>
|
167 |
+
Grey
|
168 |
+
</label>
|
169 |
+
</p>
|
170 |
+
</fieldset>
|
171 |
+
</td>
|
172 |
+
</tr>
|
173 |
+
|
174 |
+
<?php if ($isProVersion): ?>
|
175 |
+
<tr>
|
176 |
+
<th scope="row">Show submenu icons</th>
|
177 |
+
<td>
|
178 |
+
<fieldset id="ame-submenu-icons-settings">
|
179 |
+
<p>
|
180 |
+
<label>
|
181 |
+
<input type="radio" name="submenu_icons_enabled" value="always"
|
182 |
+
<?php checked('always', $settings['submenu_icons_enabled']); ?>>
|
183 |
+
Always
|
184 |
+
</label>
|
185 |
+
</p>
|
186 |
+
|
187 |
+
<p>
|
188 |
+
<label>
|
189 |
+
<input type="radio" name="submenu_icons_enabled" value="if_custom"
|
190 |
+
<?php checked('if_custom', $settings['submenu_icons_enabled']); ?>>
|
191 |
+
Only when manually selected
|
192 |
+
</label>
|
193 |
+
</p>
|
194 |
+
|
195 |
+
<p>
|
196 |
+
<label>
|
197 |
+
<input type="radio" name="submenu_icons_enabled" value="never"
|
198 |
+
<?php checked('never', $settings['submenu_icons_enabled']); ?>>
|
199 |
+
Never
|
200 |
+
</label>
|
201 |
+
</p>
|
202 |
+
</fieldset>
|
203 |
+
</td>
|
204 |
+
</tr>
|
205 |
+
<?php endif; ?>
|
206 |
+
|
207 |
<tr>
|
208 |
<th scope="row">Debugging</th>
|
209 |
<td>
|
js/admin-helpers.js
CHANGED
@@ -14,14 +14,25 @@
|
|
14 |
}
|
15 |
|
16 |
jQuery(function($) {
|
|
|
|
|
17 |
//Menu separators shouldn't be clickable and should have a custom class.
|
18 |
-
|
19 |
.find('.ws-submenu-separator')
|
20 |
.closest('a').click(function() {
|
21 |
return false;
|
22 |
})
|
23 |
.closest('li').addClass('ws-submenu-separator-wrap');
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
//Replace the original page heading with the custom heading.
|
26 |
if ( customPageHeading ) {
|
27 |
function replaceAdminPageHeading(newText) {
|
14 |
}
|
15 |
|
16 |
jQuery(function($) {
|
17 |
+
var adminMenu = $('#adminmenu');
|
18 |
+
|
19 |
//Menu separators shouldn't be clickable and should have a custom class.
|
20 |
+
adminMenu
|
21 |
.find('.ws-submenu-separator')
|
22 |
.closest('a').click(function() {
|
23 |
return false;
|
24 |
})
|
25 |
.closest('li').addClass('ws-submenu-separator-wrap');
|
26 |
|
27 |
+
//Menus with the target "< None >" also shouldn't be clickable.
|
28 |
+
adminMenu
|
29 |
+
.find(
|
30 |
+
'a.menu-top.ame-unclickable-menu-item, ul.wp-submenu > li > a[href^="#ame-unclickable-menu-item"]'
|
31 |
+
)
|
32 |
+
.click(function() {
|
33 |
+
return false;
|
34 |
+
});
|
35 |
+
|
36 |
//Replace the original page heading with the custom heading.
|
37 |
if ( customPageHeading ) {
|
38 |
function replaceAdminPageHeading(newText) {
|
js/menu-editor.js
CHANGED
@@ -355,12 +355,17 @@ function buildMenuItem(itemData, isTopLevel) {
|
|
355 |
//the editors themselves are created later, when the user tries to access them
|
356 |
//for the first time).
|
357 |
var contents = [];
|
|
|
|
|
|
|
|
|
|
|
358 |
contents.push(
|
359 |
'<div class="ws_item_head">',
|
360 |
itemData.separator ? '' : '<a class="ws_edit_link"> </a><div class="ws_flag_container"> </div>',
|
361 |
'<input type="checkbox" class="ws_actor_access_checkbox">',
|
362 |
'<span class="ws_item_title">',
|
363 |
-
|
364 |
' </span>',
|
365 |
|
366 |
'</div>',
|
@@ -434,7 +439,11 @@ var knownMenuFields = {
|
|
434 |
caption : 'Menu title',
|
435 |
display: function(menuItem, displayValue, input, containerNode) {
|
436 |
//Update the header as well.
|
437 |
-
|
|
|
|
|
|
|
|
|
438 |
return displayValue;
|
439 |
},
|
440 |
write: function(menuItem, value, input, containerNode) {
|
@@ -448,17 +457,49 @@ var knownMenuFields = {
|
|
448 |
type : 'select',
|
449 |
options : (function(){
|
450 |
//Generate name => id mappings for all item templates + the special "Custom" template.
|
451 |
-
var itemTemplateIds =
|
452 |
-
itemTemplateIds[wsEditorData.customItemTemplate.name
|
|
|
453 |
for (var template_id in wsEditorData.itemTemplates) {
|
454 |
if (wsEditorData.itemTemplates.hasOwnProperty(template_id)) {
|
455 |
-
itemTemplateIds[wsEditorData.itemTemplates[template_id].name
|
456 |
}
|
457 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
return itemTemplateIds;
|
459 |
})(),
|
460 |
|
461 |
write: function(menuItem, value, input, containerNode) {
|
|
|
|
|
462 |
menuItem.template_id = value;
|
463 |
menuItem.defaults = itemTemplates.getDefaults(menuItem.template_id);
|
464 |
menuItem.custom = (menuItem.template_id == '');
|
@@ -479,7 +520,10 @@ var knownMenuFields = {
|
|
479 |
var hasDefaultValue = itemTemplates.hasDefaultValue(menuItem.template_id, fieldName);
|
480 |
|
481 |
if (isSetToDefault && !hasDefaultValue) {
|
482 |
-
|
|
|
|
|
|
|
483 |
}
|
484 |
});
|
485 |
}
|
@@ -592,11 +636,11 @@ var knownMenuFields = {
|
|
592 |
caption: 'Open in',
|
593 |
advanced : true,
|
594 |
type : 'select',
|
595 |
-
options :
|
596 |
-
'Same window or tab'
|
597 |
-
'New window'
|
598 |
-
'Frame'
|
599 |
-
|
600 |
defaultValue: 'same_window',
|
601 |
visible: false
|
602 |
}),
|
@@ -614,20 +658,29 @@ var knownMenuFields = {
|
|
614 |
defaultValue: 'div',
|
615 |
onlyForTopMenus: true,
|
616 |
|
617 |
-
display: function(menuItem, displayValue, input) {
|
618 |
//Display the current icon in the selector.
|
619 |
var cssClass = getFieldValue(menuItem, 'css_class', '');
|
620 |
var iconUrl = getFieldValue(menuItem, 'icon_url', '');
|
621 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
622 |
var selectButton = input.closest('.ws_edit_field').find('.ws_select_icon');
|
623 |
var cssIcon = selectButton.find('.icon16');
|
624 |
var imageIcon = selectButton.find('img');
|
625 |
|
626 |
var matches = cssClass.match(/\b(ame-)?menu-icon-([^\s]+)\b/);
|
627 |
-
var dashiconMatches = iconUrl && iconUrl.match(
|
628 |
|
629 |
-
//Icon URL
|
630 |
if ( iconUrl && iconUrl !== 'none' && iconUrl !== 'div' && !dashiconMatches ) {
|
|
|
631 |
cssIcon.hide();
|
632 |
imageIcon.prop('src', iconUrl).show();
|
633 |
} else if ( dashiconMatches ) {
|
@@ -760,12 +813,12 @@ function buildEditboxField(entry, field_name, field_settings){
|
|
760 |
case 'select':
|
761 |
inputBox = $('<select class="ws_field_value">');
|
762 |
var option = null;
|
763 |
-
for( var
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
option = $('<option>')
|
768 |
-
.val(
|
769 |
.text(optionTitle);
|
770 |
option.appendTo(inputBox);
|
771 |
}
|
@@ -840,6 +893,7 @@ function updateActorAccessUi(containerNode) {
|
|
840 |
if (selectedActor != null) {
|
841 |
var menuItem = containerNode.data('menu_item');
|
842 |
var hasAccess = actorCanAccessMenu(menuItem, selectedActor);
|
|
|
843 |
|
844 |
var checkbox = containerNode.find('.ws_actor_access_checkbox');
|
845 |
checkbox.prop('checked', hasAccess);
|
@@ -870,8 +924,11 @@ function updateActorAccessUi(containerNode) {
|
|
870 |
}
|
871 |
|
872 |
containerNode.toggleClass('ws_is_hidden_for_actor', !hasAccess);
|
|
|
|
|
873 |
} else {
|
874 |
-
containerNode.removeClass('ws_is_hidden_for_actor');
|
|
|
875 |
}
|
876 |
}
|
877 |
|
@@ -1001,15 +1058,36 @@ function encodeMenuAsJSON(tree){
|
|
1001 |
|
1002 |
function readMenuTreeState(){
|
1003 |
var tree = {};
|
1004 |
-
var
|
|
|
1005 |
|
1006 |
//Gather all menus and their items
|
1007 |
$('#ws_menu_box').find('.ws_menu').each(function() {
|
1008 |
-
var
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1009 |
|
1010 |
-
//Attach the current menu to the main struct
|
1011 |
-
var filename = (menu.file !== null)?menu.file:menu.defaults.file;
|
1012 |
tree[filename] = menu;
|
|
|
1013 |
});
|
1014 |
|
1015 |
return {
|
@@ -1108,8 +1186,9 @@ function readAllFields(container){
|
|
1108 |
|
1109 |
var item_flags = {
|
1110 |
'custom':'This is a custom menu item',
|
1111 |
-
'unused':'This item was automatically
|
1112 |
-
'hidden':'This item is hidden'
|
|
|
1113 |
};
|
1114 |
|
1115 |
function setMenuFlag(item, flag, state) {
|
@@ -1156,6 +1235,13 @@ function actorCanAccessMenu(menuItem, actor) {
|
|
1156 |
return actorHasAccess;
|
1157 |
}
|
1158 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1159 |
function setActorAccess(containerNode, actor, allowAccess) {
|
1160 |
var menuItem = containerNode.data('menu_item');
|
1161 |
|
@@ -1195,13 +1281,9 @@ function setSelectedActor(actor) {
|
|
1195 |
editorNode.toggleClass('ws_is_actor_view', (selectedActor != null));
|
1196 |
|
1197 |
//Update the menu item states to indicate whether they're accessible.
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
});
|
1202 |
-
} else {
|
1203 |
-
editorNode.find('.ws_is_hidden_for_actor').removeClass('ws_is_hidden_for_actor');
|
1204 |
-
}
|
1205 |
}
|
1206 |
|
1207 |
/**
|
@@ -1224,11 +1306,14 @@ function denyAccessForAllExcept(menuItem, actor) {
|
|
1224 |
|
1225 |
$.each(wsEditorData.actors, function(otherActor) {
|
1226 |
//If the input actor is more or equally specific...
|
1227 |
-
if (AmeCapabilityManager.compareActorSpecificity(actor, otherActor) >= 0) {
|
1228 |
menuItem.grant_access[otherActor] = false;
|
1229 |
}
|
1230 |
});
|
1231 |
-
|
|
|
|
|
|
|
1232 |
return menuItem;
|
1233 |
}
|
1234 |
|
@@ -1248,6 +1333,10 @@ $(document).ready(function(){
|
|
1248 |
knownMenuFields['page_heading'].visible = true;
|
1249 |
knownMenuFields['colors'].visible = true;
|
1250 |
knownMenuFields['extra_capability'].visible = false; //Superseded by the "access_level" field.
|
|
|
|
|
|
|
|
|
1251 |
$('.ws_hide_if_pro').hide();
|
1252 |
}
|
1253 |
|
@@ -2086,18 +2175,121 @@ $(document).ready(function(){
|
|
2086 |
});
|
2087 |
});
|
2088 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2089 |
//Delete menu
|
2090 |
$('#ws_delete_menu').click(function () {
|
2091 |
//Get the selected menu
|
2092 |
var selection = getSelectedMenu();
|
2093 |
if (!selection.length) return;
|
2094 |
|
2095 |
-
|
2096 |
-
//Delete the submenu first
|
2097 |
-
$('#' + selection.data('submenu_id')).remove();
|
2098 |
-
//Delete the menu
|
2099 |
-
selection.remove();
|
2100 |
-
}
|
2101 |
});
|
2102 |
|
2103 |
//Copy menu
|
@@ -2137,7 +2329,7 @@ $(document).ready(function(){
|
|
2137 |
menu.css_class = 'menu-top';
|
2138 |
}
|
2139 |
if (getFieldValue(menu, 'icon_url', '') == '') {
|
2140 |
-
menu.icon_url = '
|
2141 |
}
|
2142 |
if (getFieldValue(menu, 'hookname', '') == '') {
|
2143 |
menu.hookname = randomMenuId();
|
@@ -2258,16 +2450,10 @@ $(document).ready(function(){
|
|
2258 |
|
2259 |
//Delete item
|
2260 |
$('#ws_delete_item').click(function () {
|
2261 |
-
//Get the selected menu
|
2262 |
var selection = getSelectedSubmenuItem();
|
2263 |
if (!selection.length) return;
|
2264 |
|
2265 |
-
|
2266 |
-
var submenu = selection.parent();
|
2267 |
-
//Delete the item
|
2268 |
-
selection.remove();
|
2269 |
-
updateParentAccessUi(submenu);
|
2270 |
-
}
|
2271 |
});
|
2272 |
|
2273 |
//Copy item
|
@@ -2420,7 +2606,23 @@ $(document).ready(function(){
|
|
2420 |
|
2421 |
//Save Changes - encode the current menu as JSON and save
|
2422 |
$('#ws_save_menu').click(function () {
|
2423 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2424 |
|
2425 |
function findItemByTemplateId(items, templateId) {
|
2426 |
var foundItem = null;
|
@@ -2457,8 +2659,6 @@ $(document).ready(function(){
|
|
2457 |
}
|
2458 |
}
|
2459 |
|
2460 |
-
console.log(tree);
|
2461 |
-
//return;
|
2462 |
var data = encodeMenuAsJSON(tree);
|
2463 |
$('#ws_data').val(data);
|
2464 |
$('#ws_data_length').val(data.length);
|
@@ -2490,16 +2690,27 @@ $(document).ready(function(){
|
|
2490 |
|
2491 |
$('#ws_export_menu').click(function(){
|
2492 |
var button = $(this);
|
2493 |
-
button.
|
2494 |
button.val('Exporting...');
|
2495 |
|
2496 |
$('#export_complete_notice, #download_menu_button').hide();
|
2497 |
$('#export_progress_notice').show();
|
2498 |
-
$('#export_dialog')
|
2499 |
-
|
2500 |
-
|
2501 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2502 |
|
|
|
2503 |
$.post(
|
2504 |
wsEditorData.adminAjaxUrl,
|
2505 |
{
|
@@ -2509,10 +2720,10 @@ $(document).ready(function(){
|
|
2509 |
},
|
2510 |
function(data){
|
2511 |
button.val('Export');
|
2512 |
-
button.
|
2513 |
|
2514 |
if ( typeof data['error'] != 'undefined' ){
|
2515 |
-
|
2516 |
alert(data.error);
|
2517 |
}
|
2518 |
|
355 |
//the editors themselves are created later, when the user tries to access them
|
356 |
//for the first time).
|
357 |
var contents = [];
|
358 |
+
var menuTitle = ((itemData.menu_title != null) ? itemData.menu_title : itemData.defaults.menu_title);
|
359 |
+
if (menuTitle === '') {
|
360 |
+
menuTitle = ' ';
|
361 |
+
}
|
362 |
+
|
363 |
contents.push(
|
364 |
'<div class="ws_item_head">',
|
365 |
itemData.separator ? '' : '<a class="ws_edit_link"> </a><div class="ws_flag_container"> </div>',
|
366 |
'<input type="checkbox" class="ws_actor_access_checkbox">',
|
367 |
'<span class="ws_item_title">',
|
368 |
+
menuTitle,
|
369 |
' </span>',
|
370 |
|
371 |
'</div>',
|
439 |
caption : 'Menu title',
|
440 |
display: function(menuItem, displayValue, input, containerNode) {
|
441 |
//Update the header as well.
|
442 |
+
var itemTitle = displayValue;
|
443 |
+
if (itemTitle === '') {
|
444 |
+
itemTitle = ' ';
|
445 |
+
}
|
446 |
+
containerNode.find('.ws_item_title').html(itemTitle);
|
447 |
return displayValue;
|
448 |
},
|
449 |
write: function(menuItem, value, input, containerNode) {
|
457 |
type : 'select',
|
458 |
options : (function(){
|
459 |
//Generate name => id mappings for all item templates + the special "Custom" template.
|
460 |
+
var itemTemplateIds = [];
|
461 |
+
itemTemplateIds.push([wsEditorData.customItemTemplate.name, '']);
|
462 |
+
|
463 |
for (var template_id in wsEditorData.itemTemplates) {
|
464 |
if (wsEditorData.itemTemplates.hasOwnProperty(template_id)) {
|
465 |
+
itemTemplateIds.push([wsEditorData.itemTemplates[template_id].name, template_id]);
|
466 |
}
|
467 |
}
|
468 |
+
|
469 |
+
itemTemplateIds.sort(function(a, b) {
|
470 |
+
if (a[1] === b[1]) {
|
471 |
+
return 0;
|
472 |
+
}
|
473 |
+
|
474 |
+
//The "Custom" item is always first.
|
475 |
+
if (a[1] === '') {
|
476 |
+
return -1;
|
477 |
+
} else if (b[1] === '') {
|
478 |
+
return 1;
|
479 |
+
}
|
480 |
+
|
481 |
+
//Top-level items go before submenus.
|
482 |
+
var aIsTop = (a[1].charAt(0) === '>') ? 1 : 0;
|
483 |
+
var bIsTop = (b[1].charAt(0) === '>') ? 1 : 0;
|
484 |
+
if (aIsTop !== bIsTop) {
|
485 |
+
return bIsTop - aIsTop;
|
486 |
+
}
|
487 |
+
|
488 |
+
//Everything else is sorted by name, in alphabetical order.
|
489 |
+
if (a[0] > b[0]) {
|
490 |
+
return 1;
|
491 |
+
} else if (a[0] < b[0]) {
|
492 |
+
return -1;
|
493 |
+
}
|
494 |
+
return 0;
|
495 |
+
});
|
496 |
+
|
497 |
return itemTemplateIds;
|
498 |
})(),
|
499 |
|
500 |
write: function(menuItem, value, input, containerNode) {
|
501 |
+
var oldTemplateId = menuItem.template_id;
|
502 |
+
|
503 |
menuItem.template_id = value;
|
504 |
menuItem.defaults = itemTemplates.getDefaults(menuItem.template_id);
|
505 |
menuItem.custom = (menuItem.template_id == '');
|
520 |
var hasDefaultValue = itemTemplates.hasDefaultValue(menuItem.template_id, fieldName);
|
521 |
|
522 |
if (isSetToDefault && !hasDefaultValue) {
|
523 |
+
var oldDefaultValue = itemTemplates.getDefaultValue(oldTemplateId, fieldName);
|
524 |
+
if (oldDefaultValue !== null) {
|
525 |
+
menuItem[fieldName] = oldDefaultValue;
|
526 |
+
}
|
527 |
}
|
528 |
});
|
529 |
}
|
636 |
caption: 'Open in',
|
637 |
advanced : true,
|
638 |
type : 'select',
|
639 |
+
options : [
|
640 |
+
['Same window or tab', 'same_window'],
|
641 |
+
['New window', 'new_window'],
|
642 |
+
['Frame', 'iframe']
|
643 |
+
],
|
644 |
defaultValue: 'same_window',
|
645 |
visible: false
|
646 |
}),
|
658 |
defaultValue: 'div',
|
659 |
onlyForTopMenus: true,
|
660 |
|
661 |
+
display: function(menuItem, displayValue, input, containerNode) {
|
662 |
//Display the current icon in the selector.
|
663 |
var cssClass = getFieldValue(menuItem, 'css_class', '');
|
664 |
var iconUrl = getFieldValue(menuItem, 'icon_url', '');
|
665 |
|
666 |
+
//When submenu icon visibility is set to "only if manually selected",
|
667 |
+
//don't show the default submenu icons.
|
668 |
+
var isDefault = (typeof menuItem['icon_url'] === 'undefined') || (menuItem['icon_url'] === null);
|
669 |
+
if (isDefault && (wsEditorData.submenuIconsEnabled === 'if_custom') && containerNode.hasClass('ws_item')) {
|
670 |
+
iconUrl = 'none';
|
671 |
+
cssClass = '';
|
672 |
+
}
|
673 |
+
|
674 |
var selectButton = input.closest('.ws_edit_field').find('.ws_select_icon');
|
675 |
var cssIcon = selectButton.find('.icon16');
|
676 |
var imageIcon = selectButton.find('img');
|
677 |
|
678 |
var matches = cssClass.match(/\b(ame-)?menu-icon-([^\s]+)\b/);
|
679 |
+
var dashiconMatches = iconUrl && iconUrl.match(/^\s*(dashicons-[a-z0-9\-]+)/);
|
680 |
|
681 |
+
//Icon URL takes precedence over icon class.
|
682 |
if ( iconUrl && iconUrl !== 'none' && iconUrl !== 'div' && !dashiconMatches ) {
|
683 |
+
//Regular image icon.
|
684 |
cssIcon.hide();
|
685 |
imageIcon.prop('src', iconUrl).show();
|
686 |
} else if ( dashiconMatches ) {
|
813 |
case 'select':
|
814 |
inputBox = $('<select class="ws_field_value">');
|
815 |
var option = null;
|
816 |
+
for( var index = 0; index < field_settings.options.length; index++ ){
|
817 |
+
var optionTitle = field_settings.options[index][0];
|
818 |
+
var optionValue = field_settings.options[index][1];
|
819 |
+
|
820 |
option = $('<option>')
|
821 |
+
.val(optionValue)
|
822 |
.text(optionTitle);
|
823 |
option.appendTo(inputBox);
|
824 |
}
|
893 |
if (selectedActor != null) {
|
894 |
var menuItem = containerNode.data('menu_item');
|
895 |
var hasAccess = actorCanAccessMenu(menuItem, selectedActor);
|
896 |
+
var hasCustomPermissions = actorHasCustomPermissions(menuItem, selectedActor);
|
897 |
|
898 |
var checkbox = containerNode.find('.ws_actor_access_checkbox');
|
899 |
checkbox.prop('checked', hasAccess);
|
924 |
}
|
925 |
|
926 |
containerNode.toggleClass('ws_is_hidden_for_actor', !hasAccess);
|
927 |
+
containerNode.toggleClass('ws_has_custom_permissions_for_actor', hasCustomPermissions);
|
928 |
+
setMenuFlag(containerNode, 'custom_actor_permissions', hasCustomPermissions)
|
929 |
} else {
|
930 |
+
containerNode.removeClass('ws_is_hidden_for_actor ws_has_custom_permissions_for_actor');
|
931 |
+
setMenuFlag(containerNode, 'custom_actor_permissions', false);
|
932 |
}
|
933 |
}
|
934 |
|
1058 |
|
1059 |
function readMenuTreeState(){
|
1060 |
var tree = {};
|
1061 |
+
var menuPosition = 0;
|
1062 |
+
var itemsByFilename = {};
|
1063 |
|
1064 |
//Gather all menus and their items
|
1065 |
$('#ws_menu_box').find('.ws_menu').each(function() {
|
1066 |
+
var containerNode = this;
|
1067 |
+
var menu = readItemState(containerNode, menuPosition++);
|
1068 |
+
|
1069 |
+
//Attach the current menu to the main structure.
|
1070 |
+
var filename = (menu.file !== null) ? menu.file : menu.defaults.file;
|
1071 |
+
|
1072 |
+
//Give unclickable items unique keys.
|
1073 |
+
if (menu.template_id === wsEditorData.unclickableTemplateId) {
|
1074 |
+
ws_paste_count++;
|
1075 |
+
filename = '#' + wsEditorData.unclickableTemplateClass + '-' + ws_paste_count;
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
//Prevent the user from saving top level items with duplicate URLs.
|
1079 |
+
//WordPress indexes the submenu array by parent URL and AME uses a {url : menu_data} hashtable internally.
|
1080 |
+
//Duplicate URLs would cause problems for both.
|
1081 |
+
if (itemsByFilename.hasOwnProperty(filename)) {
|
1082 |
+
throw {
|
1083 |
+
code: 'duplicate_top_level_url',
|
1084 |
+
message: 'Error: Found a duplicate URL! All top level menus must have unique URLs.',
|
1085 |
+
duplicates: [itemsByFilename[filename], containerNode]
|
1086 |
+
}
|
1087 |
+
}
|
1088 |
|
|
|
|
|
1089 |
tree[filename] = menu;
|
1090 |
+
itemsByFilename[filename] = containerNode;
|
1091 |
});
|
1092 |
|
1093 |
return {
|
1186 |
|
1187 |
var item_flags = {
|
1188 |
'custom':'This is a custom menu item',
|
1189 |
+
'unused':'This item was automatically recreated. You cannot delete a non-custom item, but you could hide it.',
|
1190 |
+
'hidden':'This item is hidden from ALL roles and users',
|
1191 |
+
'custom_actor_permissions' : "The selected role has custom permissions for this item."
|
1192 |
};
|
1193 |
|
1194 |
function setMenuFlag(item, flag, state) {
|
1235 |
return actorHasAccess;
|
1236 |
}
|
1237 |
|
1238 |
+
function actorHasCustomPermissions(menuItem, actor) {
|
1239 |
+
if (menuItem.grant_access && menuItem.grant_access.hasOwnProperty && menuItem.grant_access.hasOwnProperty(actor)) {
|
1240 |
+
return (menuItem.grant_access[actor] !== null);
|
1241 |
+
}
|
1242 |
+
return false;
|
1243 |
+
}
|
1244 |
+
|
1245 |
function setActorAccess(containerNode, actor, allowAccess) {
|
1246 |
var menuItem = containerNode.data('menu_item');
|
1247 |
|
1281 |
editorNode.toggleClass('ws_is_actor_view', (selectedActor != null));
|
1282 |
|
1283 |
//Update the menu item states to indicate whether they're accessible.
|
1284 |
+
editorNode.find('.ws_container').each(function() {
|
1285 |
+
updateActorAccessUi($(this));
|
1286 |
+
});
|
|
|
|
|
|
|
|
|
1287 |
}
|
1288 |
|
1289 |
/**
|
1306 |
|
1307 |
$.each(wsEditorData.actors, function(otherActor) {
|
1308 |
//If the input actor is more or equally specific...
|
1309 |
+
if ((actor === null) || (AmeCapabilityManager.compareActorSpecificity(actor, otherActor) >= 0)) {
|
1310 |
menuItem.grant_access[otherActor] = false;
|
1311 |
}
|
1312 |
});
|
1313 |
+
|
1314 |
+
if (actor !== null) {
|
1315 |
+
menuItem.grant_access[actor] = true;
|
1316 |
+
}
|
1317 |
return menuItem;
|
1318 |
}
|
1319 |
|
1333 |
knownMenuFields['page_heading'].visible = true;
|
1334 |
knownMenuFields['colors'].visible = true;
|
1335 |
knownMenuFields['extra_capability'].visible = false; //Superseded by the "access_level" field.
|
1336 |
+
|
1337 |
+
//The Pro version supports submenu icons, but they can be disabled by the user.
|
1338 |
+
knownMenuFields['icon_url'].onlyForTopMenus = (wsEditorData.submenuIconsEnabled == 'never');
|
1339 |
+
|
1340 |
$('.ws_hide_if_pro').hide();
|
1341 |
}
|
1342 |
|
2175 |
});
|
2176 |
});
|
2177 |
|
2178 |
+
//Delete error dialog. It shows up when the user tries to delete one of the default menus.
|
2179 |
+
var menuDeletionDialog = $('#ws-ame-menu-deletion-error').dialog({
|
2180 |
+
autoOpen: false,
|
2181 |
+
modal: true,
|
2182 |
+
closeText: ' ',
|
2183 |
+
title: 'Error',
|
2184 |
+
draggable: false
|
2185 |
+
});
|
2186 |
+
var menuDeletionCallback = function(hide) {
|
2187 |
+
menuDeletionDialog.dialog('close');
|
2188 |
+
var selection = menuDeletionDialog.data('selected_menu');
|
2189 |
+
|
2190 |
+
function hideRecursively(containerNode, exceptActor) {
|
2191 |
+
denyAccessForAllExcept(containerNode.data('menu_item'), exceptActor);
|
2192 |
+
|
2193 |
+
var subMenuId = containerNode.data('submenu_id');
|
2194 |
+
if (subMenuId && containerNode.hasClass('ws_menu')) {
|
2195 |
+
$('.ws_item', '#' + subMenuId).each(function() {
|
2196 |
+
var node = $(this);
|
2197 |
+
denyAccessForAllExcept(node.data('menu_item'), exceptActor);
|
2198 |
+
updateItemEditor(node);
|
2199 |
+
});
|
2200 |
+
}
|
2201 |
+
|
2202 |
+
updateItemEditor(containerNode);
|
2203 |
+
updateParentAccessUi(containerNode);
|
2204 |
+
}
|
2205 |
+
|
2206 |
+
if (hide === 'all') {
|
2207 |
+
hideRecursively(selection, null);
|
2208 |
+
} else if (hide === 'except_current_user') {
|
2209 |
+
hideRecursively(selection, 'user:' + wsEditorData.currentUserLogin);
|
2210 |
+
}
|
2211 |
+
};
|
2212 |
+
|
2213 |
+
//Callbacks for each of the dialog buttons.
|
2214 |
+
$('#ws_cancel_menu_deletion').click(function() {
|
2215 |
+
menuDeletionCallback(false);
|
2216 |
+
});
|
2217 |
+
$('#ws_hide_menu_from_everyone').click(function() {
|
2218 |
+
menuDeletionCallback('all');
|
2219 |
+
});
|
2220 |
+
$('#ws_hide_menu_except_current_user').click(function() {
|
2221 |
+
menuDeletionCallback('except_current_user');
|
2222 |
+
});
|
2223 |
+
|
2224 |
+
/**
|
2225 |
+
* Attempt to delete a menu item. Will check if the item can actually be deleted and ask the user for confirmation.
|
2226 |
+
* UI callback.
|
2227 |
+
*
|
2228 |
+
* @param selection The selected menu item (DOM node).
|
2229 |
+
*/
|
2230 |
+
function tryDeleteItem(selection) {
|
2231 |
+
var menuItem = selection.data('menu_item');
|
2232 |
+
var isDefaultItem =
|
2233 |
+
( menuItem.template_id !== '')
|
2234 |
+
&& ( menuItem.template_id !== wsEditorData.unclickableTemplateId)
|
2235 |
+
&& (!menuItem.separator);
|
2236 |
+
|
2237 |
+
var otherCopiesExist = false;
|
2238 |
+
var shouldDelete = false;
|
2239 |
+
|
2240 |
+
if (isDefaultItem) {
|
2241 |
+
//Check if there are any other menus with the same template ID.
|
2242 |
+
$('#ws_menu_editor').find('.ws_container').each(function() {
|
2243 |
+
var otherItem = $(this).data('menu_item');
|
2244 |
+
if ((menuItem != otherItem) && (menuItem.template_id == otherItem.template_id)) {
|
2245 |
+
otherCopiesExist = true;
|
2246 |
+
return false;
|
2247 |
+
}
|
2248 |
+
return true;
|
2249 |
+
});
|
2250 |
+
}
|
2251 |
+
|
2252 |
+
if (!isDefaultItem || otherCopiesExist || !wsEditorData.wsMenuEditorPro) {
|
2253 |
+
//Custom and duplicate items can be deleted normally. The free version doesn't get the dialog
|
2254 |
+
//because it doesn't have role-specific permissions.
|
2255 |
+
shouldDelete = confirm('Delete this menu?');
|
2256 |
+
} else {
|
2257 |
+
//Non-custom items can not be deleted, but they can be hidden. Ask the user if they want to do that.
|
2258 |
+
menuDeletionDialog.find('#ws-ame-menu-type-desc').text(
|
2259 |
+
menuItem.defaults.is_plugin_page ? 'an item added by another plugin' : 'a built-in menu item'
|
2260 |
+
);
|
2261 |
+
menuDeletionDialog.data('selected_menu', selection);
|
2262 |
+
menuDeletionDialog.dialog('open');
|
2263 |
+
|
2264 |
+
//Select "Cancel" as the default button.
|
2265 |
+
menuDeletionDialog.find('#ws_cancel_menu_deletion').focus();
|
2266 |
+
}
|
2267 |
+
|
2268 |
+
if (shouldDelete) {
|
2269 |
+
//Delete this menu's submenu first, if any.
|
2270 |
+
var submenuId = selection.data('submenu_id');
|
2271 |
+
if (submenuId) {
|
2272 |
+
$('#' + submenuId).remove();
|
2273 |
+
}
|
2274 |
+
var parentSubmenu = selection.closest('.ws_submenu');
|
2275 |
+
|
2276 |
+
//Delete the menu.
|
2277 |
+
selection.remove();
|
2278 |
+
|
2279 |
+
if (parentSubmenu) {
|
2280 |
+
//Refresh permissions UI for this menu's parent (if any).
|
2281 |
+
updateParentAccessUi(parentSubmenu);
|
2282 |
+
}
|
2283 |
+
}
|
2284 |
+
}
|
2285 |
+
|
2286 |
//Delete menu
|
2287 |
$('#ws_delete_menu').click(function () {
|
2288 |
//Get the selected menu
|
2289 |
var selection = getSelectedMenu();
|
2290 |
if (!selection.length) return;
|
2291 |
|
2292 |
+
tryDeleteItem(selection);
|
|
|
|
|
|
|
|
|
|
|
2293 |
});
|
2294 |
|
2295 |
//Copy menu
|
2329 |
menu.css_class = 'menu-top';
|
2330 |
}
|
2331 |
if (getFieldValue(menu, 'icon_url', '') == '') {
|
2332 |
+
menu.icon_url = 'dashicons-admin-generic';
|
2333 |
}
|
2334 |
if (getFieldValue(menu, 'hookname', '') == '') {
|
2335 |
menu.hookname = randomMenuId();
|
2450 |
|
2451 |
//Delete item
|
2452 |
$('#ws_delete_item').click(function () {
|
|
|
2453 |
var selection = getSelectedSubmenuItem();
|
2454 |
if (!selection.length) return;
|
2455 |
|
2456 |
+
tryDeleteItem(selection);
|
|
|
|
|
|
|
|
|
|
|
2457 |
});
|
2458 |
|
2459 |
//Copy item
|
2606 |
|
2607 |
//Save Changes - encode the current menu as JSON and save
|
2608 |
$('#ws_save_menu').click(function () {
|
2609 |
+
try {
|
2610 |
+
var tree = readMenuTreeState();
|
2611 |
+
} catch (error) {
|
2612 |
+
//Right now the only known error condition is duplicate top level URLs.
|
2613 |
+
if (error.hasOwnProperty('code') && (error.code === 'duplicate_top_level_url')) {
|
2614 |
+
var message = 'Error: Duplicate menu URLs. The following top level menus have the same URL:\n\n' ;
|
2615 |
+
for (var i = 0; i < error.duplicates.length; i++) {
|
2616 |
+
var containerNode = $(error.duplicates[i]);
|
2617 |
+
message += (i + 1) + '. ' + containerNode.find('.ws_item_title').first().text() + '\n';
|
2618 |
+
}
|
2619 |
+
message += '\nPlease change the URLs to be unique or delete the duplicates.';
|
2620 |
+
alert(message);
|
2621 |
+
} else {
|
2622 |
+
alert(error.message);
|
2623 |
+
}
|
2624 |
+
return;
|
2625 |
+
}
|
2626 |
|
2627 |
function findItemByTemplateId(items, templateId) {
|
2628 |
var foundItem = null;
|
2659 |
}
|
2660 |
}
|
2661 |
|
|
|
|
|
2662 |
var data = encodeMenuAsJSON(tree);
|
2663 |
$('#ws_data').val(data);
|
2664 |
$('#ws_data_length').val(data.length);
|
2690 |
|
2691 |
$('#ws_export_menu').click(function(){
|
2692 |
var button = $(this);
|
2693 |
+
button.prop('disabled', true);
|
2694 |
button.val('Exporting...');
|
2695 |
|
2696 |
$('#export_complete_notice, #download_menu_button').hide();
|
2697 |
$('#export_progress_notice').show();
|
2698 |
+
var exportDialog = $('#export_dialog');
|
2699 |
+
exportDialog.dialog('open');
|
2700 |
+
|
2701 |
+
//Encode the menu.
|
2702 |
+
try {
|
2703 |
+
var exportData = encodeMenuAsJSON();
|
2704 |
+
} catch (error) {
|
2705 |
+
exportDialog.dialog('close');
|
2706 |
+
alert(error.message);
|
2707 |
+
|
2708 |
+
button.val('Export');
|
2709 |
+
button.prop('disabled', false);
|
2710 |
+
return;
|
2711 |
+
}
|
2712 |
|
2713 |
+
//Store the menu for download.
|
2714 |
$.post(
|
2715 |
wsEditorData.adminAjaxUrl,
|
2716 |
{
|
2720 |
},
|
2721 |
function(data){
|
2722 |
button.val('Export');
|
2723 |
+
button.prop('disabled', false);
|
2724 |
|
2725 |
if ( typeof data['error'] != 'undefined' ){
|
2726 |
+
exportDialog.dialog('close');
|
2727 |
alert(data.error);
|
2728 |
}
|
2729 |
|
js/menu-highlight-fix.js
CHANGED
@@ -51,6 +51,14 @@ jQuery(function($) {
|
|
51 |
currentUri.path = currentUri.path + 'index.php';
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
var adminMenu = $('#adminmenu');
|
55 |
adminMenu.find('li > a').each(function(index, link) {
|
56 |
var $link = $(link);
|
@@ -63,8 +71,7 @@ jQuery(function($) {
|
|
63 |
|
64 |
var uri = parseUri(link.href);
|
65 |
|
66 |
-
//
|
67 |
-
//WordPress assumes it is "post". Here we make this explicit.
|
68 |
if ( (uri.file === 'edit.php') || (uri.file === 'post-new.php') ) {
|
69 |
if ( !uri.queryKey.hasOwnProperty('post_type') ) {
|
70 |
uri.queryKey['post_type'] = 'post';
|
51 |
currentUri.path = currentUri.path + 'index.php';
|
52 |
}
|
53 |
|
54 |
+
//Special case: if post_type is not specified for edit.php and post-new.php,
|
55 |
+
//WordPress assumes it is "post". Here we make this explicit.
|
56 |
+
if ( (currentUri.file === 'edit.php') || (currentUri.file === 'post-new.php') ) {
|
57 |
+
if ( !currentUri.queryKey.hasOwnProperty('post_type') ) {
|
58 |
+
currentUri.queryKey['post_type'] = 'post';
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
var adminMenu = $('#adminmenu');
|
63 |
adminMenu.find('li > a').each(function(index, link) {
|
64 |
var $link = $(link);
|
71 |
|
72 |
var uri = parseUri(link.href);
|
73 |
|
74 |
+
//Same as above - use "post" as the default post type.
|
|
|
75 |
if ( (uri.file === 'edit.php') || (uri.file === 'post-new.php') ) {
|
76 |
if ( !uri.queryKey.hasOwnProperty('post_type') ) {
|
77 |
uri.queryKey['post_type'] = 'post';
|
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.
|
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.4
|
7 |
Author: Janis Elsts
|
8 |
Author URI: http://w-shadow.com/blog/
|
9 |
*/
|
readme.txt
CHANGED
@@ -2,30 +2,31 @@
|
|
2 |
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: 3.
|
6 |
-
Tested up to: 4.0-
|
7 |
-
Stable tag: 1.
|
8 |
|
9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
10 |
|
11 |
== Description ==
|
12 |
-
Admin Menu Editor lets you manually edit the Dashboard menu. You can reorder the menus, show/hide specific items, change
|
13 |
|
14 |
**Features**
|
15 |
|
16 |
-
*
|
17 |
-
*
|
18 |
-
*
|
19 |
* Move a menu item to a different submenu.
|
20 |
* Create custom menus that point to any part of the Dashboard or an external URL.
|
|
|
21 |
|
22 |
The [Pro version](http://w-shadow.com/AdminMenuEditor/) lets you set per-role menu permissions, hide a menu from everyone except a specific user, export your admin menu, drag items between menu levels, make menus open in a new window and more. [Try online demo](http://amedemo.com/wpdemo/demo.php).
|
23 |
|
24 |
**Notes**
|
25 |
|
26 |
-
* If you delete any of the default menus they will reappear after saving. This is by design. To get rid of a menu for good, either hide it or
|
27 |
-
* In the free version,
|
28 |
-
* In case of emergency, you can reset the menu configuration back to the default by going to http://example.com/wp-admin/?reset\_admin\_menu=1
|
29 |
|
30 |
== Installation ==
|
31 |
|
@@ -40,7 +41,7 @@ That's it. You can access the the menu editor by going to *Settings -> Menu Edit
|
|
40 |
|
41 |
**WP MultiSite installation**
|
42 |
|
43 |
-
If you have WordPress set up in
|
44 |
|
45 |
1. Download the admin-menu-editor.zip file to your computer.
|
46 |
1. Unzip the file.
|
@@ -53,7 +54,6 @@ Plugins installed in the `mu-plugins` directory are treated as "always on", so y
|
|
53 |
*Notes*
|
54 |
* Instead of installing Admin Menu Editor in `mu-plugins`, you can also install it normally and then activate it globally via "Network Activate". However, this will make the plugin visible to normal users when it is inactive (e.g. during upgrades).
|
55 |
* When Admin Menu Editor is installed in `mu-plugins` or activated via "Network Activate", only the "super admin" user can access the menu editor page. Other users will see the customized Dashboard menu, but be unable to edit it.
|
56 |
-
* It is currently not possible to install Admin Menu Editor as both a normal and global plugin on the same site.
|
57 |
|
58 |
== Screenshots ==
|
59 |
|
@@ -63,6 +63,22 @@ Plugins installed in the `mu-plugins` directory are treated as "always on", so y
|
|
63 |
|
64 |
== Changelog ==
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
= 1.3.2 =
|
67 |
* Added a large number of menu icons based on the Dashicons icon font.
|
68 |
* Fixed default menu icons not showing up in WP 3.9.
|
2 |
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: 3.8
|
6 |
+
Tested up to: 4.0-beta2
|
7 |
+
Stable tag: 1.4
|
8 |
|
9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
10 |
|
11 |
== Description ==
|
12 |
+
Admin Menu Editor lets you manually edit the Dashboard menu. You can reorder the menus, show/hide specific items, change premissions, and more.
|
13 |
|
14 |
**Features**
|
15 |
|
16 |
+
* Change menu titles, URLs, icons, CSS classes and so on.
|
17 |
+
* Organize menu items via drag & drop.
|
18 |
+
* Change menu permissions by setting the required capability or role.
|
19 |
* Move a menu item to a different submenu.
|
20 |
* Create custom menus that point to any part of the Dashboard or an external URL.
|
21 |
+
* Hide/show any menu or menu item. A hidden menu is invisible to all users, including administrators.
|
22 |
|
23 |
The [Pro version](http://w-shadow.com/AdminMenuEditor/) lets you set per-role menu permissions, hide a menu from everyone except a specific user, export your admin menu, drag items between menu levels, make menus open in a new window and more. [Try online demo](http://amedemo.com/wpdemo/demo.php).
|
24 |
|
25 |
**Notes**
|
26 |
|
27 |
+
* If you delete any of the default menus they will reappear after saving. This is by design. To get rid of a menu for good, either hide it or change it's access permissions.
|
28 |
+
* In the free version, it's not possible to give a role access to a menu item that it couldn't see before. You can only restrict menu access further.
|
29 |
+
* In case of emergency, you can reset the menu configuration back to the default by going to http://example.com/wp-admin/?reset\_admin\_menu=1 (replace example.com with your site URL). You must be logged in as an Administrator to do this.
|
30 |
|
31 |
== Installation ==
|
32 |
|
41 |
|
42 |
**WP MultiSite installation**
|
43 |
|
44 |
+
If you have WordPress set up in Multisite ("Network") mode, you can also install Admin Menu Editor as a global plugin. This will enable you to edit the Dashboard menu for all sites and users at once.
|
45 |
|
46 |
1. Download the admin-menu-editor.zip file to your computer.
|
47 |
1. Unzip the file.
|
54 |
*Notes*
|
55 |
* Instead of installing Admin Menu Editor in `mu-plugins`, you can also install it normally and then activate it globally via "Network Activate". However, this will make the plugin visible to normal users when it is inactive (e.g. during upgrades).
|
56 |
* When Admin Menu Editor is installed in `mu-plugins` or activated via "Network Activate", only the "super admin" user can access the menu editor page. Other users will see the customized Dashboard menu, but be unable to edit it.
|
|
|
57 |
|
58 |
== Screenshots ==
|
59 |
|
63 |
|
64 |
== Changelog ==
|
65 |
|
66 |
+
= 1.4 =
|
67 |
+
* Added a special target page option: "< None >". It makes the selected menu item unclickable. This could be useful for creating menu headers and so on.
|
68 |
+
* Added a new menu editor colour scheme that's similar to the default WordPress admin colour scheme. Click the "Settings" button next to the menu editor page title to switch colour schemes.
|
69 |
+
* Fixed strange boxes showing up in the icon selector in Internet Explorer.
|
70 |
+
* Fixed duplicate top level menus mysteriously disappearing. Now the plugin will properly warn the user that all top level menus must have unique URLs.
|
71 |
+
* Fixed an obscure bug where changing the "Target page" from the default setting to "Custom" and back would occasionally make some menu properties suddenly show up as modified for no apparent reason.
|
72 |
+
* Fixed incorrect submenu item height and margins in WP 4.0-beta.
|
73 |
+
* Fixed a minor layout bug where items with no title would be smaller than other items.
|
74 |
+
* Fixed combo-box dropdown button height for WP 3.9.x.
|
75 |
+
* Added a workaround for a bug in WordPress Mu Domain Mapping 0.5.4.3.
|
76 |
+
* Added a workaround for the very unusual situation where the "user_has_cap" filter is called without a capability.
|
77 |
+
* Fixed duplicates of bbPress menu items showing up.
|
78 |
+
* Changed the default custom menu icon to the generic "cogwheel" icon from Dashicons.
|
79 |
+
* Other small UI changes.
|
80 |
+
* Raised minimum requirements to WordPress 3.8 or later. This is mainly due to the increased reliance on Dashicons as menu icons.
|
81 |
+
|
82 |
= 1.3.2 =
|
83 |
* Added a large number of menu icons based on the Dashicons icon font.
|
84 |
* Fixed default menu icons not showing up in WP 3.9.
|
screenshot-1.png
CHANGED
Binary file
|
screenshot-2.png
CHANGED
Binary file
|