Version Description
- Added capability suggestions and access preview to the "Extra capability" dropdown.
- The plugin now remembers the last selected menu item and re-selects it after you save changes.
- Fixed a layout issue where menus with very long titles would appear incorrectly in the menu editor.
- When you change the menu title, the window title will also be changed to match it. You can still edit the window title separately if necessary.
- Moved the "Icon URL" field up and moved "Window title" down.
Download this release
Release Info
| Developer | whiteshadow |
| Plugin | |
| Version | 1.7.2 |
| Comparing to | |
| See all releases | |
Code changes from version 1.7.1 to 1.7.2
- css/menu-editor.css +24 -0
- css/menu-editor.scss +40 -1
- includes/cap-suggestion-box.php +14 -0
- includes/capabilities/cap-power.csv +54 -0
- includes/editor-page.php +19 -7
- includes/menu-editor-core.php +80 -7
- js/actor-manager.js +92 -0
- js/actor-manager.ts +122 -0
- js/menu-editor.js +392 -71
- menu-editor.php +1 -1
- modules/access-editor/access-editor.js +4 -0
- readme.txt +8 -1
css/menu-editor.css
CHANGED
|
@@ -1336,6 +1336,30 @@ a#ws-ame-delete-color-preset:hover {
|
|
| 1336 |
#ws-ame-copy-permissions-dialog select {
|
| 1337 |
min-width: 280px; }
|
| 1338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1339 |
#ws_sidebar_pro_ad {
|
| 1340 |
min-width: 225px;
|
| 1341 |
margin-top: 5px;
|
| 1336 |
#ws-ame-copy-permissions-dialog select {
|
| 1337 |
min-width: 280px; }
|
| 1338 |
|
| 1339 |
+
/*********************************************
|
| 1340 |
+
Capability suggestions and preview
|
| 1341 |
+
**********************************************/
|
| 1342 |
+
#ws_capability_suggestions {
|
| 1343 |
+
padding: 4px;
|
| 1344 |
+
width: 350px;
|
| 1345 |
+
border: 1px solid #cdd5d5;
|
| 1346 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
| 1347 |
+
background: #fff;
|
| 1348 |
+
border-top-right-radius: 3px;
|
| 1349 |
+
border-bottom-right-radius: 3px; }
|
| 1350 |
+
#ws_capability_suggestions #ws_previewed_caps {
|
| 1351 |
+
margin-top: 0;
|
| 1352 |
+
margin-bottom: 6px; }
|
| 1353 |
+
#ws_capability_suggestions td, #ws_capability_suggestions th {
|
| 1354 |
+
padding-top: 3px;
|
| 1355 |
+
padding-bottom: 3px; }
|
| 1356 |
+
#ws_capability_suggestions tr.ws_preview_has_access .ws_ame_role_name {
|
| 1357 |
+
background-color: lightgreen; }
|
| 1358 |
+
#ws_capability_suggestions .ws_ame_suggested_capability {
|
| 1359 |
+
cursor: pointer; }
|
| 1360 |
+
#ws_capability_suggestions .ws_ame_suggested_capability:hover {
|
| 1361 |
+
background-color: #d0f2d0; }
|
| 1362 |
+
|
| 1363 |
#ws_sidebar_pro_ad {
|
| 1364 |
min-width: 225px;
|
| 1365 |
margin-top: 5px;
|
css/menu-editor.scss
CHANGED
|
@@ -692,10 +692,11 @@ select.ws_dropdown {
|
|
| 692 |
font-size: 12px;
|
| 693 |
}
|
| 694 |
|
|
|
|
| 695 |
select.ws_dropdown option {
|
| 696 |
font-family : "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
|
| 697 |
font-size: 12px;
|
| 698 |
-
padding:
|
| 699 |
}
|
| 700 |
|
| 701 |
select.ws_dropdown optgroup option {
|
|
@@ -1878,6 +1879,44 @@ $userSelectionPanelPadding: 10px;
|
|
| 1878 |
min-width: 280px;
|
| 1879 |
}
|
| 1880 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1881 |
|
| 1882 |
|
| 1883 |
#ws_sidebar_pro_ad {
|
| 692 |
font-size: 12px;
|
| 693 |
}
|
| 694 |
|
| 695 |
+
$dropdownOptionPaddingTop: 3px;
|
| 696 |
select.ws_dropdown option {
|
| 697 |
font-family : "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
|
| 698 |
font-size: 12px;
|
| 699 |
+
padding: $dropdownOptionPaddingTop;
|
| 700 |
}
|
| 701 |
|
| 702 |
select.ws_dropdown optgroup option {
|
| 1879 |
min-width: 280px;
|
| 1880 |
}
|
| 1881 |
|
| 1882 |
+
/*********************************************
|
| 1883 |
+
Capability suggestions and preview
|
| 1884 |
+
**********************************************/
|
| 1885 |
+
|
| 1886 |
+
#ws_capability_suggestions {
|
| 1887 |
+
padding: 4px;
|
| 1888 |
+
width: 350px;
|
| 1889 |
+
|
| 1890 |
+
border: 1px solid #cdd5d5;
|
| 1891 |
+
box-shadow: 0 1px 1px rgba(0,0,0,0.04);
|
| 1892 |
+
background: #fff;
|
| 1893 |
+
|
| 1894 |
+
border-top-right-radius: 3px;
|
| 1895 |
+
border-bottom-right-radius: 3px;
|
| 1896 |
+
|
| 1897 |
+
#ws_previewed_caps {
|
| 1898 |
+
margin-top: 0;
|
| 1899 |
+
margin-bottom: 6px;
|
| 1900 |
+
}
|
| 1901 |
+
|
| 1902 |
+
td, th {
|
| 1903 |
+
//For consistency, padding should match the capability dropdown.
|
| 1904 |
+
padding-top: $dropdownOptionPaddingTop;
|
| 1905 |
+
padding-bottom: $dropdownOptionPaddingTop;
|
| 1906 |
+
}
|
| 1907 |
+
|
| 1908 |
+
tr.ws_preview_has_access .ws_ame_role_name{
|
| 1909 |
+
background-color: lightgreen;
|
| 1910 |
+
}
|
| 1911 |
+
|
| 1912 |
+
.ws_ame_suggested_capability {
|
| 1913 |
+
cursor: pointer;
|
| 1914 |
+
|
| 1915 |
+
&:hover {
|
| 1916 |
+
background-color: #d0f2d0;
|
| 1917 |
+
}
|
| 1918 |
+
}
|
| 1919 |
+
}
|
| 1920 |
|
| 1921 |
|
| 1922 |
#ws_sidebar_pro_ad {
|
includes/cap-suggestion-box.php
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div id="ws_capability_suggestions" style="display: none;">
|
| 2 |
+
<p id="ws_previewed_caps"> </p>
|
| 3 |
+
<table class="widefat striped">
|
| 4 |
+
<thead>
|
| 5 |
+
<tr>
|
| 6 |
+
<th class="ws_ame_role_name">Role</th>
|
| 7 |
+
<th>Suggestion</th>
|
| 8 |
+
</tr>
|
| 9 |
+
</thead>
|
| 10 |
+
<tbody>
|
| 11 |
+
<tr><td colspan="2">This table will be populated by JavaScript</td></tr>
|
| 12 |
+
</tbody>
|
| 13 |
+
</table>
|
| 14 |
+
</div>
|
includes/capabilities/cap-power.csv
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Capability;Power;Super Admin;Administrator;Editor;Author;Contributor;Subscriber
|
| 2 |
+
manage_network;20;Y;;;;;
|
| 3 |
+
manage_sites;20;Y;;;;;
|
| 4 |
+
manage_network_users;20;Y;;;;;
|
| 5 |
+
manage_network_plugins;20;Y;;;;;
|
| 6 |
+
manage_network_themes;20;Y;;;;;
|
| 7 |
+
manage_network_options;20;Y;;;;;
|
| 8 |
+
install_plugins;10;Y;Y (single site);;;;
|
| 9 |
+
install_themes;10;Y;Y (single site);;;;
|
| 10 |
+
edit_plugins;10;Y;Y (single site);;;;
|
| 11 |
+
edit_themes;10;Y;Y (single site);;;;
|
| 12 |
+
delete_plugins;8;Y;Y (single site);;;;
|
| 13 |
+
delete_themes;8;Y;Y (single site);;;;
|
| 14 |
+
update_core;7;Y;Y (single site);;;;
|
| 15 |
+
update_plugins;7;Y;Y (single site);;;;
|
| 16 |
+
update_themes;7;Y;Y (single site);;;;
|
| 17 |
+
create_users;7;Y;Y (single site);;;;
|
| 18 |
+
delete_users;7;Y;Y (single site);;;;
|
| 19 |
+
edit_users;7;Y;Y (single site);;;;
|
| 20 |
+
activate_plugins;6;Y;Y (single site or enabled by network setting);;;;
|
| 21 |
+
edit_theme_options;5;Y;Y;;;;
|
| 22 |
+
export;5;Y;Y;;;;
|
| 23 |
+
import;5;Y;Y;;;;
|
| 24 |
+
list_users;5;Y;Y;;;;
|
| 25 |
+
manage_options;5;Y;Y;;;;
|
| 26 |
+
promote_users;5;Y;Y;;;;
|
| 27 |
+
remove_users;5;Y;Y;;;;
|
| 28 |
+
switch_themes;5;Y;Y;;;;
|
| 29 |
+
moderate_comments;4;Y;Y;Y;;;
|
| 30 |
+
manage_categories;4;Y;Y;Y;;;
|
| 31 |
+
manage_links;4;Y;Y;Y;;;
|
| 32 |
+
edit_others_posts;4;Y;Y;Y;;;
|
| 33 |
+
edit_pages;4;Y;Y;Y;;;
|
| 34 |
+
edit_others_pages;4;Y;Y;Y;;;
|
| 35 |
+
edit_published_pages;4;Y;Y;Y;;;
|
| 36 |
+
publish_pages;4;Y;Y;Y;;;
|
| 37 |
+
delete_pages;4;Y;Y;Y;;;
|
| 38 |
+
delete_others_pages;4;Y;Y;Y;;;
|
| 39 |
+
delete_published_pages;4;Y;Y;Y;;;
|
| 40 |
+
delete_others_posts;4;Y;Y;Y;;;
|
| 41 |
+
delete_private_posts;4;Y;Y;Y;;;
|
| 42 |
+
edit_private_posts;4;Y;Y;Y;;;
|
| 43 |
+
read_private_posts;4;Y;Y;Y;;;
|
| 44 |
+
delete_private_pages;4;Y;Y;Y;;;
|
| 45 |
+
edit_private_pages;4;Y;Y;Y;;;
|
| 46 |
+
read_private_pages;4;Y;Y;Y;;;
|
| 47 |
+
unfiltered_html;4,2;Y;Y;Y;;;
|
| 48 |
+
edit_published_posts;3;Y;Y;Y;Y;;
|
| 49 |
+
upload_files;3;Y;Y;Y;Y;;
|
| 50 |
+
publish_posts;3;Y;Y;Y;Y;;
|
| 51 |
+
delete_published_posts;3;Y;Y;Y;Y;;
|
| 52 |
+
edit_posts;2;Y;Y;Y;Y;Y;
|
| 53 |
+
delete_posts;2;Y;Y;Y;Y;Y;
|
| 54 |
+
read;1;Y;Y;Y;Y;Y;Y
|
includes/editor-page.php
CHANGED
|
@@ -236,6 +236,13 @@ function ame_output_sort_buttons($icons) {
|
|
| 236 |
<input type="hidden" name="data" id="ws_data" value="">
|
| 237 |
<input type="hidden" name="data_length" id="ws_data_length" value="">
|
| 238 |
<input type="hidden" name="selected_actor" id="ws_selected_actor" value="">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
<input type="button" id='ws_save_menu' class="button-primary ws_main_button" value="Save Changes" />
|
| 240 |
</form>
|
| 241 |
|
|
@@ -264,15 +271,16 @@ function ame_output_sort_buttons($icons) {
|
|
| 264 |
|
| 265 |
if ( $show_pro_benefits ):
|
| 266 |
$benefit_variations = array(
|
| 267 |
-
'
|
| 268 |
-
'
|
| 269 |
-
'
|
|
|
|
| 270 |
);
|
| 271 |
//Pseudo-randomly select one phrase based on the site URL.
|
| 272 |
-
$variation_index = hexdec( substr(md5(get_site_url()), -
|
| 273 |
$selected_variation = $benefit_variations[$variation_index];
|
| 274 |
|
| 275 |
-
$pro_version_link = 'http://adminmenueditor.com/upgrade-to-pro/?utm_source=Admin%2BMenu%2BEditor%2Bfree&utm_medium=text_link&utm_content=
|
| 276 |
?>
|
| 277 |
<div class="clear"></div>
|
| 278 |
|
|
@@ -281,9 +289,11 @@ function ame_output_sort_buttons($icons) {
|
|
| 281 |
<div class="ws_hint_content">
|
| 282 |
<strong>Upgrade to Pro:</strong>
|
| 283 |
<ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
<li><?php echo $selected_variation; ?></li>
|
| 285 |
-
<li>Drag items between menu levels.</li>
|
| 286 |
-
<li>Menu export & import.</li>
|
| 287 |
</ul>
|
| 288 |
<a href="<?php echo esc_attr($pro_version_link); ?>" target="_blank">Learn more</a>
|
| 289 |
|
|
|
@@ -551,6 +561,8 @@ function ame_output_sort_buttons($icons) {
|
|
| 551 |
</div>
|
| 552 |
</div>
|
| 553 |
|
|
|
|
|
|
|
| 554 |
<?php
|
| 555 |
if ( $is_pro_version ) {
|
| 556 |
include $extrasDirectory . '/page-dropdown.php';
|
| 236 |
<input type="hidden" name="data" id="ws_data" value="">
|
| 237 |
<input type="hidden" name="data_length" id="ws_data_length" value="">
|
| 238 |
<input type="hidden" name="selected_actor" id="ws_selected_actor" value="">
|
| 239 |
+
|
| 240 |
+
<input type="hidden" name="selected_menu_url" id="ws_selected_menu_url" value="">
|
| 241 |
+
<input type="hidden" name="selected_submenu_url" id="ws_selected_submenu_url" value="">
|
| 242 |
+
|
| 243 |
+
<input type="hidden" name="expand_menu" id="ws_expand_selected_menu" value="">
|
| 244 |
+
<input type="hidden" name="expand_submenu" id="ws_expand_selected_submenu" value="">
|
| 245 |
+
|
| 246 |
<input type="button" id='ws_save_menu' class="button-primary ws_main_button" value="Save Changes" />
|
| 247 |
</form>
|
| 248 |
|
| 271 |
|
| 272 |
if ( $show_pro_benefits ):
|
| 273 |
$benefit_variations = array(
|
| 274 |
+
'Drag items between menu levels.',
|
| 275 |
+
'More menu icons.',
|
| 276 |
+
'Make menus open in a new tab or an iframe.',
|
| 277 |
+
'Prevent users from deleting a specific user.',
|
| 278 |
);
|
| 279 |
//Pseudo-randomly select one phrase based on the site URL.
|
| 280 |
+
$variation_index = hexdec( substr(md5(get_site_url() . 'ab'), -2) ) % count($benefit_variations);
|
| 281 |
$selected_variation = $benefit_variations[$variation_index];
|
| 282 |
|
| 283 |
+
$pro_version_link = 'http://adminmenueditor.com/upgrade-to-pro/?utm_source=Admin%2BMenu%2BEditor%2Bfree&utm_medium=text_link&utm_content=sidebar_link_nv' . $variation_index . '&utm_campaign=Plugins';
|
| 284 |
?>
|
| 285 |
<div class="clear"></div>
|
| 286 |
|
| 289 |
<div class="ws_hint_content">
|
| 290 |
<strong>Upgrade to Pro:</strong>
|
| 291 |
<ul>
|
| 292 |
+
<li>Role-based menu permissions.</li>
|
| 293 |
+
<li>Hide items from specific users.</li>
|
| 294 |
+
<li>Menu import and export.</li>
|
| 295 |
+
<li>Change menu colors.</li>
|
| 296 |
<li><?php echo $selected_variation; ?></li>
|
|
|
|
|
|
|
| 297 |
</ul>
|
| 298 |
<a href="<?php echo esc_attr($pro_version_link); ?>" target="_blank">Learn more</a>
|
| 299 |
|
|
| 561 |
</div>
|
| 562 |
</div>
|
| 563 |
|
| 564 |
+
<?php include dirname(__FILE__) . '/cap-suggestion-box.php'; ?>
|
| 565 |
+
|
| 566 |
<?php
|
| 567 |
if ( $is_pro_version ) {
|
| 568 |
include $extrasDirectory . '/page-dropdown.php';
|
includes/menu-editor-core.php
CHANGED
|
@@ -754,6 +754,7 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
| 754 |
'roles' => $roles,
|
| 755 |
'users' => $users,
|
| 756 |
'isMultisite' => is_multisite(),
|
|
|
|
| 757 |
);
|
| 758 |
wp_localize_script('ame-actor-manager', 'wsAmeActorData', $actor_data);
|
| 759 |
|
|
@@ -821,6 +822,11 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
| 821 |
'getPagesNonce' => wp_create_nonce('ws_ame_get_pages'),
|
| 822 |
'getPageDetailsNonce' => wp_create_nonce('ws_ame_get_page_details'),
|
| 823 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 824 |
'isDemoMode' => defined('IS_DEMO_MODE'),
|
| 825 |
'isMasterMode' => defined('IS_MASTER_MODE'),
|
| 826 |
);
|
|
@@ -1083,15 +1089,34 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
| 1083 |
return $admin_title;
|
| 1084 |
}
|
| 1085 |
|
|
|
|
|
|
|
| 1086 |
//Check if the we have a custom title for this page.
|
| 1087 |
$default_title = isset($item['defaults']['page_title']) ? $item['defaults']['page_title'] : '';
|
| 1088 |
if ( !empty($item['page_title']) && $item['page_title'] != $default_title ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1089 |
if ( empty($title) ) {
|
| 1090 |
-
$admin_title = $
|
| 1091 |
} else {
|
| 1092 |
//Replace the first occurrence of the default title with the custom one.
|
| 1093 |
$title_pos = strpos($admin_title, $title);
|
| 1094 |
-
$admin_title = substr_replace($admin_title, $
|
| 1095 |
}
|
| 1096 |
}
|
| 1097 |
|
|
@@ -1918,11 +1943,19 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
| 1918 |
$this->set_custom_menu($menu);
|
| 1919 |
|
| 1920 |
//Redirect back to the editor and display the success message.
|
| 1921 |
-
//Also, automatically select the last selected actor (convenience feature).
|
| 1922 |
$query = array('message' => 1);
|
| 1923 |
-
|
| 1924 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1925 |
}
|
|
|
|
| 1926 |
wp_redirect( add_query_arg($query, $url) );
|
| 1927 |
die();
|
| 1928 |
} else {
|
|
@@ -3394,6 +3427,36 @@ class WPMenuEditor extends MenuEd_ShadowPluginFramework {
|
|
| 3394 |
return '';
|
| 3395 |
}
|
| 3396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3397 |
} //class
|
| 3398 |
|
| 3399 |
|
|
@@ -3493,13 +3556,23 @@ class ameMenuTemplateBuilder {
|
|
| 3493 |
|
| 3494 |
/**
|
| 3495 |
* Sanitize a menu title for display.
|
| 3496 |
-
* Removes HTML tags and update notification bubbles.
|
| 3497 |
*
|
| 3498 |
* @param string $title
|
| 3499 |
* @return string
|
| 3500 |
*/
|
| 3501 |
private function sanitizeMenuTitle($title) {
|
| 3502 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3503 |
}
|
| 3504 |
|
| 3505 |
public function getRelativeTemplateOrder() {
|
| 754 |
'roles' => $roles,
|
| 755 |
'users' => $users,
|
| 756 |
'isMultisite' => is_multisite(),
|
| 757 |
+
'capPower' => $this->load_cap_power(),
|
| 758 |
);
|
| 759 |
wp_localize_script('ame-actor-manager', 'wsAmeActorData', $actor_data);
|
| 760 |
|
| 822 |
'getPagesNonce' => wp_create_nonce('ws_ame_get_pages'),
|
| 823 |
'getPageDetailsNonce' => wp_create_nonce('ws_ame_get_page_details'),
|
| 824 |
|
| 825 |
+
'selectedMenu' => isset($this->get['selected_menu_url']) ? strval($this->get['selected_menu_url']) : null,
|
| 826 |
+
'selectedSubmenu' => isset($this->get['selected_submenu_url']) ? strval($this->get['selected_submenu_url']) : null,
|
| 827 |
+
'expandSelectedMenu' => isset($this->get['expand_menu']) && ($this->get['expand_menu'] === '1'),
|
| 828 |
+
'expandSelectedSubmenu' => isset($this->get['expand_submenu']) && ($this->get['expand_submenu'] === '1'),
|
| 829 |
+
|
| 830 |
'isDemoMode' => defined('IS_DEMO_MODE'),
|
| 831 |
'isMasterMode' => defined('IS_MASTER_MODE'),
|
| 832 |
);
|
| 1089 |
return $admin_title;
|
| 1090 |
}
|
| 1091 |
|
| 1092 |
+
$custom_title = null;
|
| 1093 |
+
|
| 1094 |
//Check if the we have a custom title for this page.
|
| 1095 |
$default_title = isset($item['defaults']['page_title']) ? $item['defaults']['page_title'] : '';
|
| 1096 |
if ( !empty($item['page_title']) && $item['page_title'] != $default_title ) {
|
| 1097 |
+
$custom_title = $item['page_title'];
|
| 1098 |
+
}
|
| 1099 |
+
|
| 1100 |
+
//Alternatively, use the custom menu title if the default page title is empty (as is usually
|
| 1101 |
+
//the case with core menus) or matches the default menu title (which is typical for plugins).
|
| 1102 |
+
//This saves the user a little bit of time, and, presumably, they'd want the titles to match.
|
| 1103 |
+
$default_menu_title = isset($item['defaults']['menu_title']) ? $item['defaults']['menu_title'] : '';
|
| 1104 |
+
if (
|
| 1105 |
+
!isset($custom_title)
|
| 1106 |
+
&& !empty($item['menu_title'])
|
| 1107 |
+
&& ($item['menu_title'] !== $default_menu_title)
|
| 1108 |
+
&& (($default_menu_title === $default_title) || ($default_title === ''))
|
| 1109 |
+
) {
|
| 1110 |
+
$custom_title = strip_tags($item['menu_title']);
|
| 1111 |
+
}
|
| 1112 |
+
|
| 1113 |
+
if ( isset($custom_title) ) {
|
| 1114 |
if ( empty($title) ) {
|
| 1115 |
+
$admin_title = $custom_title . $admin_title;
|
| 1116 |
} else {
|
| 1117 |
//Replace the first occurrence of the default title with the custom one.
|
| 1118 |
$title_pos = strpos($admin_title, $title);
|
| 1119 |
+
$admin_title = substr_replace($admin_title, $custom_title, $title_pos, strlen($title));
|
| 1120 |
}
|
| 1121 |
}
|
| 1122 |
|
| 1943 |
$this->set_custom_menu($menu);
|
| 1944 |
|
| 1945 |
//Redirect back to the editor and display the success message.
|
|
|
|
| 1946 |
$query = array('message' => 1);
|
| 1947 |
+
|
| 1948 |
+
//Also, automatically select the last selected actor and menu (convenience feature).
|
| 1949 |
+
$pass_through_params = array(
|
| 1950 |
+
'selected_actor', 'selected_menu_url', 'selected_submenu_url',
|
| 1951 |
+
'expand_menu', 'expand_submenu',
|
| 1952 |
+
);
|
| 1953 |
+
foreach($pass_through_params as $param) {
|
| 1954 |
+
if ( isset($post[$param]) && !empty($post[$param]) ) {
|
| 1955 |
+
$query[$param] = rawurlencode(strval($post[$param]));
|
| 1956 |
+
}
|
| 1957 |
}
|
| 1958 |
+
|
| 1959 |
wp_redirect( add_query_arg($query, $url) );
|
| 1960 |
die();
|
| 1961 |
} else {
|
| 3427 |
return '';
|
| 3428 |
}
|
| 3429 |
|
| 3430 |
+
/**
|
| 3431 |
+
* @return array
|
| 3432 |
+
*/
|
| 3433 |
+
private function load_cap_power() {
|
| 3434 |
+
$cap_power = array();
|
| 3435 |
+
|
| 3436 |
+
$power_filename = AME_ROOT_DIR . '/includes/capabilities/cap-power.csv';
|
| 3437 |
+
if ( is_file($power_filename) && is_readable($power_filename) ) {
|
| 3438 |
+
$csv = fopen($power_filename, 'r');
|
| 3439 |
+
$firstLineSkipped = false;
|
| 3440 |
+
|
| 3441 |
+
while ($csv && !feof($csv)) {
|
| 3442 |
+
$line = fgetcsv($csv, 1000, ';');
|
| 3443 |
+
if ( !$firstLineSkipped ) {
|
| 3444 |
+
$firstLineSkipped = true;
|
| 3445 |
+
continue;
|
| 3446 |
+
}
|
| 3447 |
+
|
| 3448 |
+
if ( count($line) >= 2 ) {
|
| 3449 |
+
$cap_power[strval($line[0])] = floatval(str_replace(',', '.', $line[1]));
|
| 3450 |
+
}
|
| 3451 |
+
}
|
| 3452 |
+
fclose($csv);
|
| 3453 |
+
|
| 3454 |
+
arsort($cap_power);
|
| 3455 |
+
}
|
| 3456 |
+
|
| 3457 |
+
return $cap_power;
|
| 3458 |
+
}
|
| 3459 |
+
|
| 3460 |
} //class
|
| 3461 |
|
| 3462 |
|
| 3556 |
|
| 3557 |
/**
|
| 3558 |
* Sanitize a menu title for display.
|
| 3559 |
+
* Removes HTML tags and update notification bubbles. Truncates long titles.
|
| 3560 |
*
|
| 3561 |
* @param string $title
|
| 3562 |
* @return string
|
| 3563 |
*/
|
| 3564 |
private function sanitizeMenuTitle($title) {
|
| 3565 |
+
$title = strip_tags( preg_replace('@<span[^>]*>.*</span>@i', '', $title) );
|
| 3566 |
+
|
| 3567 |
+
//Compact whitespace.
|
| 3568 |
+
$title = rtrim(preg_replace('@[\s\t\r\n]+@', ' ', $title));
|
| 3569 |
+
|
| 3570 |
+
$maxLength = 50;
|
| 3571 |
+
if ( strlen($title) > $maxLength ) {
|
| 3572 |
+
$title = rtrim(substr($title, 0, $maxLength)) . '...';
|
| 3573 |
+
}
|
| 3574 |
+
|
| 3575 |
+
return $title;
|
| 3576 |
}
|
| 3577 |
|
| 3578 |
public function getRelativeTemplateOrder() {
|
js/actor-manager.js
CHANGED
|
@@ -46,6 +46,9 @@ var AmeBaseActor = (function () {
|
|
| 46 |
}
|
| 47 |
return specificity;
|
| 48 |
};
|
|
|
|
|
|
|
|
|
|
| 49 |
return AmeBaseActor;
|
| 50 |
}());
|
| 51 |
var AmeRole = (function (_super) {
|
|
@@ -116,6 +119,7 @@ var AmeActorManager = (function () {
|
|
| 116 |
this.users = {};
|
| 117 |
this.grantedCapabilities = {};
|
| 118 |
this.isMultisite = false;
|
|
|
|
| 119 |
this.isMultisite = !!isMultisite;
|
| 120 |
AmeActorManager._.forEach(roles, function (roleDetails, id) {
|
| 121 |
var role = new AmeRole(id, roleDetails.name, roleDetails.capabilities);
|
|
@@ -341,10 +345,98 @@ var AmeActorManager = (function () {
|
|
| 341 |
return delta;
|
| 342 |
};
|
| 343 |
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
AmeActorManager._ = wsAmeLodash;
|
| 345 |
return AmeActorManager;
|
| 346 |
}());
|
| 347 |
if (typeof wsAmeActorData !== 'undefined') {
|
| 348 |
AmeActors = new AmeActorManager(wsAmeActorData.roles, wsAmeActorData.users, wsAmeActorData.isMultisite);
|
|
|
|
|
|
|
|
|
|
| 349 |
}
|
| 350 |
//# sourceMappingURL=actor-manager.js.map
|
| 46 |
}
|
| 47 |
return specificity;
|
| 48 |
};
|
| 49 |
+
AmeBaseActor.prototype.toString = function () {
|
| 50 |
+
return this.displayName + ' [' + this.id + ']';
|
| 51 |
+
};
|
| 52 |
return AmeBaseActor;
|
| 53 |
}());
|
| 54 |
var AmeRole = (function (_super) {
|
| 119 |
this.users = {};
|
| 120 |
this.grantedCapabilities = {};
|
| 121 |
this.isMultisite = false;
|
| 122 |
+
this.suggestedCapabilities = [];
|
| 123 |
this.isMultisite = !!isMultisite;
|
| 124 |
AmeActorManager._.forEach(roles, function (roleDetails, id) {
|
| 125 |
var role = new AmeRole(id, roleDetails.name, roleDetails.capabilities);
|
| 345 |
return delta;
|
| 346 |
};
|
| 347 |
;
|
| 348 |
+
AmeActorManager.prototype.generateCapabilitySuggestions = function (capPower) {
|
| 349 |
+
var _ = AmeActorManager._;
|
| 350 |
+
var capsByPower = _.memoize(function (role) {
|
| 351 |
+
var sortedCaps = _.reduce(role.capabilities, function (result, hasCap, capability) {
|
| 352 |
+
if (hasCap) {
|
| 353 |
+
result.push({
|
| 354 |
+
capability: capability,
|
| 355 |
+
power: _.get(capPower, [capability], 0)
|
| 356 |
+
});
|
| 357 |
+
}
|
| 358 |
+
return result;
|
| 359 |
+
}, []);
|
| 360 |
+
sortedCaps = _.sortBy(sortedCaps, function (item) { return -item.power; });
|
| 361 |
+
return sortedCaps;
|
| 362 |
+
});
|
| 363 |
+
var rolesByPower = _.values(this.getRoles()).sort(function (a, b) {
|
| 364 |
+
var aCaps = capsByPower(a), bCaps = capsByPower(b);
|
| 365 |
+
//Prioritise roles with the highest number of the most powerful capabilities.
|
| 366 |
+
for (var i = 0, limit = Math.min(aCaps.length, bCaps.length); i < limit; i++) {
|
| 367 |
+
var delta_1 = bCaps[i].power - aCaps[i].power;
|
| 368 |
+
if (delta_1 !== 0) {
|
| 369 |
+
return delta_1;
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
//Give a tie to the role that has more capabilities.
|
| 373 |
+
var delta = bCaps.length - aCaps.length;
|
| 374 |
+
if (delta !== 0) {
|
| 375 |
+
return delta;
|
| 376 |
+
}
|
| 377 |
+
//Failing that, just sort alphabetically.
|
| 378 |
+
if (a.displayName > b.displayName) {
|
| 379 |
+
return 1;
|
| 380 |
+
}
|
| 381 |
+
else if (a.displayName < b.displayName) {
|
| 382 |
+
return -1;
|
| 383 |
+
}
|
| 384 |
+
return 0;
|
| 385 |
+
});
|
| 386 |
+
var preferredCaps = [
|
| 387 |
+
'manage_network_options',
|
| 388 |
+
'install_plugins', 'edit_plugins', 'delete_users',
|
| 389 |
+
'manage_options', 'switch_themes',
|
| 390 |
+
'edit_others_pages', 'edit_others_posts', 'edit_pages',
|
| 391 |
+
'unfiltered_html',
|
| 392 |
+
'publish_posts', 'edit_posts',
|
| 393 |
+
'read'
|
| 394 |
+
];
|
| 395 |
+
var deprecatedCaps = _(_.range(0, 10)).map(function (level) { return 'level_' + level; }).value();
|
| 396 |
+
deprecatedCaps.push('edit_files');
|
| 397 |
+
var findDiscriminant = function (caps, includeRoles, excludeRoles) {
|
| 398 |
+
var getEnabledCaps = function (role) {
|
| 399 |
+
return _.keys(_.pick(role.capabilities, _.identity));
|
| 400 |
+
};
|
| 401 |
+
//Find caps that all of the includeRoles have and excludeRoles don't.
|
| 402 |
+
var includeCaps = _.intersection.apply(_, _.map(includeRoles, getEnabledCaps)), excludeCaps = _.union.apply(_, _.map(excludeRoles, getEnabledCaps)), possibleCaps = _.without.apply(_, [includeCaps].concat(excludeCaps).concat(deprecatedCaps));
|
| 403 |
+
var bestCaps = _.intersection(preferredCaps, possibleCaps);
|
| 404 |
+
if (bestCaps.length > 0) {
|
| 405 |
+
return bestCaps[0];
|
| 406 |
+
}
|
| 407 |
+
else if (possibleCaps.length > 0) {
|
| 408 |
+
return possibleCaps[0];
|
| 409 |
+
}
|
| 410 |
+
return null;
|
| 411 |
+
};
|
| 412 |
+
var suggestedCapabilities = [];
|
| 413 |
+
for (var i = 0; i < rolesByPower.length; i++) {
|
| 414 |
+
var role = rolesByPower[i];
|
| 415 |
+
var cap = findDiscriminant(preferredCaps, _.slice(rolesByPower, 0, i + 1), _.slice(rolesByPower, i + 1, rolesByPower.length));
|
| 416 |
+
suggestedCapabilities.push({ role: role, capability: cap });
|
| 417 |
+
}
|
| 418 |
+
var previousSuggestion = null;
|
| 419 |
+
for (var i = suggestedCapabilities.length - 1; i >= 0; i--) {
|
| 420 |
+
if (suggestedCapabilities[i].capability === null) {
|
| 421 |
+
suggestedCapabilities[i].capability =
|
| 422 |
+
previousSuggestion ? previousSuggestion : 'exist';
|
| 423 |
+
}
|
| 424 |
+
else {
|
| 425 |
+
previousSuggestion = suggestedCapabilities[i].capability;
|
| 426 |
+
}
|
| 427 |
+
}
|
| 428 |
+
this.suggestedCapabilities = suggestedCapabilities;
|
| 429 |
+
};
|
| 430 |
+
AmeActorManager.prototype.getSuggestedCapabilities = function () {
|
| 431 |
+
return this.suggestedCapabilities;
|
| 432 |
+
};
|
| 433 |
AmeActorManager._ = wsAmeLodash;
|
| 434 |
return AmeActorManager;
|
| 435 |
}());
|
| 436 |
if (typeof wsAmeActorData !== 'undefined') {
|
| 437 |
AmeActors = new AmeActorManager(wsAmeActorData.roles, wsAmeActorData.users, wsAmeActorData.isMultisite);
|
| 438 |
+
if (typeof wsAmeActorData['capPower'] !== 'undefined') {
|
| 439 |
+
AmeActors.generateCapabilitySuggestions(wsAmeActorData['capPower']);
|
| 440 |
+
}
|
| 441 |
}
|
| 442 |
//# sourceMappingURL=actor-manager.js.map
|
js/actor-manager.ts
CHANGED
|
@@ -58,6 +58,10 @@ abstract class AmeBaseActor {
|
|
| 58 |
}
|
| 59 |
return specificity;
|
| 60 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
}
|
| 62 |
|
| 63 |
class AmeRole extends AmeBaseActor {
|
|
@@ -162,6 +166,11 @@ interface AmeGrantedCapabilityMap {
|
|
| 162 |
}
|
| 163 |
}
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
class AmeActorManager {
|
| 166 |
private static _ = wsAmeLodash;
|
| 167 |
|
|
@@ -172,6 +181,8 @@ class AmeActorManager {
|
|
| 172 |
private isMultisite: boolean = false;
|
| 173 |
private superAdmin: AmeSuperAdmin;
|
| 174 |
|
|
|
|
|
|
|
| 175 |
constructor(roles, users, isMultisite: boolean = false) {
|
| 176 |
this.isMultisite = !!isMultisite;
|
| 177 |
|
|
@@ -450,6 +461,113 @@ class AmeActorManager {
|
|
| 450 |
}
|
| 451 |
return delta;
|
| 452 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
}
|
| 454 |
|
| 455 |
if (typeof wsAmeActorData !== 'undefined') {
|
|
@@ -458,4 +576,8 @@ if (typeof wsAmeActorData !== 'undefined') {
|
|
| 458 |
wsAmeActorData.users,
|
| 459 |
wsAmeActorData.isMultisite
|
| 460 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
}
|
| 58 |
}
|
| 59 |
return specificity;
|
| 60 |
}
|
| 61 |
+
|
| 62 |
+
toString(): string {
|
| 63 |
+
return this.displayName + ' [' + this.id + ']';
|
| 64 |
+
}
|
| 65 |
}
|
| 66 |
|
| 67 |
class AmeRole extends AmeBaseActor {
|
| 166 |
}
|
| 167 |
}
|
| 168 |
|
| 169 |
+
interface AmeCapabilitySuggestion {
|
| 170 |
+
role: AmeRole;
|
| 171 |
+
capability: string;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
class AmeActorManager {
|
| 175 |
private static _ = wsAmeLodash;
|
| 176 |
|
| 181 |
private isMultisite: boolean = false;
|
| 182 |
private superAdmin: AmeSuperAdmin;
|
| 183 |
|
| 184 |
+
private suggestedCapabilities: AmeCapabilitySuggestion[] = [];
|
| 185 |
+
|
| 186 |
constructor(roles, users, isMultisite: boolean = false) {
|
| 187 |
this.isMultisite = !!isMultisite;
|
| 188 |
|
| 461 |
}
|
| 462 |
return delta;
|
| 463 |
};
|
| 464 |
+
|
| 465 |
+
generateCapabilitySuggestions(capPower): void {
|
| 466 |
+
let _ = AmeActorManager._;
|
| 467 |
+
|
| 468 |
+
let capsByPower = _.memoize((role: AmeRole): {capability: string, power: number}[] => {
|
| 469 |
+
let sortedCaps = _.reduce(role.capabilities, (result, hasCap, capability) => {
|
| 470 |
+
if (hasCap) {
|
| 471 |
+
result.push({
|
| 472 |
+
capability: capability,
|
| 473 |
+
power: _.get(capPower, [capability], 0)
|
| 474 |
+
});
|
| 475 |
+
}
|
| 476 |
+
return result;
|
| 477 |
+
}, []);
|
| 478 |
+
|
| 479 |
+
sortedCaps = _.sortBy(sortedCaps, (item) => -item.power);
|
| 480 |
+
return sortedCaps;
|
| 481 |
+
});
|
| 482 |
+
|
| 483 |
+
let rolesByPower: AmeRole[] = _.values<AmeRole>(this.getRoles()).sort(function(a: AmeRole, b: AmeRole) {
|
| 484 |
+
let aCaps = capsByPower(a),
|
| 485 |
+
bCaps = capsByPower(b);
|
| 486 |
+
|
| 487 |
+
//Prioritise roles with the highest number of the most powerful capabilities.
|
| 488 |
+
for (var i = 0, limit = Math.min(aCaps.length, bCaps.length); i < limit; i++) {
|
| 489 |
+
let delta = bCaps[i].power - aCaps[i].power;
|
| 490 |
+
if (delta !== 0) {
|
| 491 |
+
return delta;
|
| 492 |
+
}
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
//Give a tie to the role that has more capabilities.
|
| 496 |
+
let delta = bCaps.length - aCaps.length;
|
| 497 |
+
if (delta !== 0) {
|
| 498 |
+
return delta;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
//Failing that, just sort alphabetically.
|
| 502 |
+
if (a.displayName > b.displayName) {
|
| 503 |
+
return 1;
|
| 504 |
+
} else if (a.displayName < b.displayName) {
|
| 505 |
+
return -1;
|
| 506 |
+
}
|
| 507 |
+
return 0;
|
| 508 |
+
});
|
| 509 |
+
|
| 510 |
+
let preferredCaps = [
|
| 511 |
+
'manage_network_options',
|
| 512 |
+
'install_plugins', 'edit_plugins', 'delete_users',
|
| 513 |
+
'manage_options', 'switch_themes',
|
| 514 |
+
'edit_others_pages', 'edit_others_posts', 'edit_pages',
|
| 515 |
+
'unfiltered_html',
|
| 516 |
+
'publish_posts', 'edit_posts',
|
| 517 |
+
'read'
|
| 518 |
+
];
|
| 519 |
+
|
| 520 |
+
let deprecatedCaps = _(_.range(0, 10)).map((level) => 'level_' + level).value();
|
| 521 |
+
deprecatedCaps.push('edit_files');
|
| 522 |
+
|
| 523 |
+
let findDiscriminant = (caps: string[], includeRoles: AmeRole[], excludeRoles): string => {
|
| 524 |
+
let getEnabledCaps = (role: AmeRole): string[] => {
|
| 525 |
+
return _.keys(_.pick(role.capabilities, _.identity));
|
| 526 |
+
};
|
| 527 |
+
|
| 528 |
+
//Find caps that all of the includeRoles have and excludeRoles don't.
|
| 529 |
+
let includeCaps = _.intersection.apply(_, _.map(includeRoles, getEnabledCaps)),
|
| 530 |
+
excludeCaps = _.union.apply(_, _.map(excludeRoles, getEnabledCaps)),
|
| 531 |
+
possibleCaps = _.without.apply(_, [includeCaps].concat(excludeCaps).concat(deprecatedCaps));
|
| 532 |
+
|
| 533 |
+
let bestCaps = _.intersection(preferredCaps, possibleCaps);
|
| 534 |
+
|
| 535 |
+
if (bestCaps.length > 0) {
|
| 536 |
+
return bestCaps[0];
|
| 537 |
+
} else if (possibleCaps.length > 0) {
|
| 538 |
+
return possibleCaps[0];
|
| 539 |
+
}
|
| 540 |
+
return null;
|
| 541 |
+
};
|
| 542 |
+
|
| 543 |
+
let suggestedCapabilities = [];
|
| 544 |
+
for (let i = 0; i < rolesByPower.length; i++) {
|
| 545 |
+
let role = rolesByPower[i];
|
| 546 |
+
|
| 547 |
+
let cap = findDiscriminant(
|
| 548 |
+
preferredCaps,
|
| 549 |
+
_.slice(rolesByPower, 0, i + 1),
|
| 550 |
+
_.slice(rolesByPower, i + 1, rolesByPower.length)
|
| 551 |
+
);
|
| 552 |
+
suggestedCapabilities.push({role: role, capability: cap});
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
let previousSuggestion = null;
|
| 556 |
+
for (let i = suggestedCapabilities.length - 1; i >= 0; i--) {
|
| 557 |
+
if (suggestedCapabilities[i].capability === null) {
|
| 558 |
+
suggestedCapabilities[i].capability =
|
| 559 |
+
previousSuggestion ? previousSuggestion : 'exist';
|
| 560 |
+
} else {
|
| 561 |
+
previousSuggestion = suggestedCapabilities[i].capability;
|
| 562 |
+
}
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
this.suggestedCapabilities = suggestedCapabilities;
|
| 566 |
+
}
|
| 567 |
+
|
| 568 |
+
public getSuggestedCapabilities(): AmeCapabilitySuggestion[] {
|
| 569 |
+
return this.suggestedCapabilities;
|
| 570 |
+
}
|
| 571 |
}
|
| 572 |
|
| 573 |
if (typeof wsAmeActorData !== 'undefined') {
|
| 576 |
wsAmeActorData.users,
|
| 577 |
wsAmeActorData.isMultisite
|
| 578 |
);
|
| 579 |
+
|
| 580 |
+
if (typeof wsAmeActorData['capPower'] !== 'undefined') {
|
| 581 |
+
AmeActors.generateCapabilitySuggestions(wsAmeActorData['capPower']);
|
| 582 |
+
}
|
| 583 |
}
|
js/menu-editor.js
CHANGED
|
@@ -43,6 +43,9 @@
|
|
| 43 |
* @property {object} wsEditorData.postTypes
|
| 44 |
* @property {object} wsEditorData.taxonomies
|
| 45 |
*
|
|
|
|
|
|
|
|
|
|
| 46 |
* @property {boolean} wsEditorData.isDemoMode
|
| 47 |
* @property {boolean} wsEditorData.isMasterMode
|
| 48 |
*/
|
|
@@ -398,7 +401,7 @@ function buildMenuItem(itemData, isTopLevel) {
|
|
| 398 |
itemData.separator ? '' : '<a class="ws_edit_link"> </a><div class="ws_flag_container"> </div>',
|
| 399 |
'<input type="checkbox" class="ws_actor_access_checkbox">',
|
| 400 |
'<span class="ws_item_title">',
|
| 401 |
-
|
| 402 |
' </span>',
|
| 403 |
|
| 404 |
'</div>',
|
|
@@ -459,6 +462,37 @@ function stripAllTags(input) {
|
|
| 459 |
return input.replace(commentsAndPhpTags, '').replace(tags, '');
|
| 460 |
}
|
| 461 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
//Editor field spec template.
|
| 463 |
var baseField = {
|
| 464 |
caption : '[No caption]',
|
|
@@ -484,7 +518,7 @@ var knownMenuFields = {
|
|
| 484 |
caption : 'Menu title',
|
| 485 |
display: function(menuItem, displayValue, input, containerNode) {
|
| 486 |
//Update the header as well.
|
| 487 |
-
containerNode.find('.ws_item_title').html(
|
| 488 |
return displayValue;
|
| 489 |
},
|
| 490 |
write: function(menuItem, value, input, containerNode) {
|
|
@@ -736,66 +770,6 @@ var knownMenuFields = {
|
|
| 736 |
}
|
| 737 |
}),
|
| 738 |
|
| 739 |
-
'page_title' : $.extend({}, baseField, {
|
| 740 |
-
caption: "Window title",
|
| 741 |
-
standardCaption : true,
|
| 742 |
-
advanced : true
|
| 743 |
-
}),
|
| 744 |
-
|
| 745 |
-
'open_in' : $.extend({}, baseField, {
|
| 746 |
-
caption: 'Open in',
|
| 747 |
-
advanced : true,
|
| 748 |
-
type : 'select',
|
| 749 |
-
options : [
|
| 750 |
-
['Same window or tab', 'same_window'],
|
| 751 |
-
['New window', 'new_window'],
|
| 752 |
-
['Frame', 'iframe']
|
| 753 |
-
],
|
| 754 |
-
defaultValue: 'same_window',
|
| 755 |
-
visible: false
|
| 756 |
-
}),
|
| 757 |
-
|
| 758 |
-
'iframe_height' : $.extend({}, baseField, {
|
| 759 |
-
caption: 'Frame height (pixels)',
|
| 760 |
-
advanced : true,
|
| 761 |
-
visible: function(menuItem) {
|
| 762 |
-
return wsEditorData.wsMenuEditorPro && (getFieldValue(menuItem, 'open_in') === 'iframe');
|
| 763 |
-
},
|
| 764 |
-
|
| 765 |
-
display: function(menuItem, displayValue, input) {
|
| 766 |
-
input.prop('placeholder', 'Auto');
|
| 767 |
-
if (displayValue === 0 || displayValue === '0') {
|
| 768 |
-
displayValue = '';
|
| 769 |
-
}
|
| 770 |
-
return displayValue;
|
| 771 |
-
},
|
| 772 |
-
|
| 773 |
-
write: function(menuItem, value) {
|
| 774 |
-
value = parseInt(value, 10);
|
| 775 |
-
if (isNaN(value) || (value < 0)) {
|
| 776 |
-
value = 0;
|
| 777 |
-
}
|
| 778 |
-
value = Math.round(value);
|
| 779 |
-
|
| 780 |
-
if (value > 10000) {
|
| 781 |
-
value = 10000;
|
| 782 |
-
}
|
| 783 |
-
|
| 784 |
-
if (value === 0) {
|
| 785 |
-
menuItem.iframe_height = null;
|
| 786 |
-
} else {
|
| 787 |
-
menuItem.iframe_height = value;
|
| 788 |
-
}
|
| 789 |
-
|
| 790 |
-
}
|
| 791 |
-
}),
|
| 792 |
-
|
| 793 |
-
'css_class' : $.extend({}, baseField, {
|
| 794 |
-
caption: 'CSS classes',
|
| 795 |
-
advanced : true,
|
| 796 |
-
onlyForTopMenus: true
|
| 797 |
-
}),
|
| 798 |
-
|
| 799 |
'icon_url' : $.extend({}, baseField, {
|
| 800 |
caption: 'Icon URL',
|
| 801 |
type : 'icon_selector',
|
|
@@ -856,6 +830,60 @@ var knownMenuFields = {
|
|
| 856 |
}
|
| 857 |
}),
|
| 858 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 859 |
'colors' : $.extend({}, baseField, {
|
| 860 |
caption: 'Color scheme',
|
| 861 |
defaultValue: 'Default',
|
|
@@ -894,6 +922,12 @@ var knownMenuFields = {
|
|
| 894 |
}
|
| 895 |
}),
|
| 896 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 897 |
'page_heading' : $.extend({}, baseField, {
|
| 898 |
caption: 'Page heading',
|
| 899 |
advanced : true,
|
|
@@ -1329,6 +1363,22 @@ function getDefaultValue(entry, fieldName, defaultValue, containerNode) {
|
|
| 1329 |
}
|
| 1330 |
}
|
| 1331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1332 |
if (typeof defaultValue === 'undefined') {
|
| 1333 |
defaultValue = null;
|
| 1334 |
}
|
|
@@ -1400,6 +1450,45 @@ AmeEditorApi.forEachMenuItem = function(callback, skipSeparators) {
|
|
| 1400 |
});
|
| 1401 |
};
|
| 1402 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1403 |
/***************************************************************************
|
| 1404 |
Parsing & encoding menu inputs
|
| 1405 |
***************************************************************************/
|
|
@@ -1891,11 +1980,16 @@ function ameOnDomReady() {
|
|
| 1891 |
submenuBox = $('#ws_submenu_box'),
|
| 1892 |
submenuDropZone = submenuBox.closest('.ws_main_container').find('.ws_dropzone');
|
| 1893 |
|
| 1894 |
-
//Highlight the clicked menu item and show it's submenu
|
| 1895 |
var currentVisibleSubmenu = null;
|
| 1896 |
-
|
| 1897 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1898 |
if (container.hasClass('ws_active')) {
|
|
|
|
| 1899 |
return;
|
| 1900 |
}
|
| 1901 |
|
|
@@ -1920,6 +2014,12 @@ function ameOnDomReady() {
|
|
| 1920 |
container.closest('.ws_main_container')
|
| 1921 |
.find('.ws_toolbar .ws_delete_menu_button')
|
| 1922 |
.toggleClass('ws_button_disabled', !canDeleteItem(container));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1923 |
}));
|
| 1924 |
|
| 1925 |
function updateSubmenuBoxHeight(selectedMenu) {
|
|
@@ -2277,7 +2377,9 @@ function ameOnDomReady() {
|
|
| 2277 |
|
| 2278 |
var capSelectorDropdown = $('#ws_cap_selector');
|
| 2279 |
var currentDropdownOwner = null; //The input element that the dropdown is currently associated with.
|
| 2280 |
-
var
|
|
|
|
|
|
|
| 2281 |
|
| 2282 |
//Show/hide the capability drop-down list when the trigger button is clicked
|
| 2283 |
$('#ws_trigger_capability_dropdown').on('mousedown click', onDropdownTriggerClicked);
|
|
@@ -2288,9 +2390,13 @@ function ameOnDomReady() {
|
|
| 2288 |
var inputBox = null;
|
| 2289 |
var button = $(this);
|
| 2290 |
|
|
|
|
|
|
|
|
|
|
| 2291 |
//Find the input associated with the button that was clicked.
|
| 2292 |
if ( button.attr('id') === 'ws_trigger_capability_dropdown' ) {
|
| 2293 |
inputBox = $('#ws_extra_capability');
|
|
|
|
| 2294 |
} else {
|
| 2295 |
inputBox = button.closest('.ws_edit_field').find('.ws_field_value').first();
|
| 2296 |
}
|
|
@@ -2333,7 +2439,17 @@ function ameOnDomReady() {
|
|
| 2333 |
width(inputBox.outerWidth());
|
| 2334 |
|
| 2335 |
currentDropdownOwner = inputBox;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2336 |
capSelectorDropdown.focus();
|
|
|
|
|
|
|
| 2337 |
}
|
| 2338 |
|
| 2339 |
//Also show it when the user presses the down arrow in the input field (doesn't work in Opera).
|
|
@@ -2343,26 +2459,34 @@ function ameOnDomReady() {
|
|
| 2343 |
}
|
| 2344 |
});
|
| 2345 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2346 |
//Event handlers for the drop-down lists themselves
|
| 2347 |
var dropdownNodes = $('.ws_dropdown');
|
| 2348 |
|
| 2349 |
// Hide capability drop-down when it loses focus.
|
| 2350 |
dropdownNodes.blur(function(){
|
| 2351 |
-
|
|
|
|
|
|
|
| 2352 |
});
|
| 2353 |
|
| 2354 |
dropdownNodes.keydown(function(event){
|
| 2355 |
|
| 2356 |
//Hide it when the user presses Esc
|
| 2357 |
if ( event.which === 27 ){
|
| 2358 |
-
|
| 2359 |
if (currentDropdownOwner) {
|
| 2360 |
currentDropdownOwner.focus();
|
| 2361 |
}
|
| 2362 |
|
| 2363 |
//Select an item & hide the list when the user presses Enter or Tab
|
| 2364 |
} else if ( (event.which === 13) || (event.which === 9) ){
|
| 2365 |
-
|
| 2366 |
|
| 2367 |
if (currentDropdownOwner) {
|
| 2368 |
if ( capSelectorDropdown.val() ){
|
|
@@ -2386,7 +2510,7 @@ function ameOnDomReady() {
|
|
| 2386 |
//Update the input & hide the list when an option is clicked
|
| 2387 |
dropdownNodes.click(function(){
|
| 2388 |
if (capSelectorDropdown.val()){
|
| 2389 |
-
|
| 2390 |
if (currentDropdownOwner) {
|
| 2391 |
currentDropdownOwner.val(capSelectorDropdown.val()).change().focus();
|
| 2392 |
}
|
|
@@ -2402,9 +2526,176 @@ function ameOnDomReady() {
|
|
| 2402 |
var option = event.target;
|
| 2403 |
if ( (typeof option.selected !== 'undefined') && !option.selected && option.value ){
|
| 2404 |
option.selected = true;
|
|
|
|
|
|
|
|
|
|
| 2405 |
}
|
| 2406 |
});
|
| 2407 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2408 |
/*************************************************************************
|
| 2409 |
Icon selector
|
| 2410 |
*************************************************************************/
|
|
@@ -2873,7 +3164,7 @@ function ameOnDomReady() {
|
|
| 2873 |
|
| 2874 |
//Add menu title to the dialog caption.
|
| 2875 |
var title = getFieldValue(menuItem, 'menu_title', null);
|
| 2876 |
-
setUpColorDialog(title ? ('Colors: ' + title
|
| 2877 |
|
| 2878 |
//Show the [global] preset only if the user has set it up.
|
| 2879 |
var globalPresetExists = colorPresets.hasOwnProperty('[global]');
|
|
@@ -3897,6 +4188,19 @@ function ameOnDomReady() {
|
|
| 3897 |
$('#ws_data').val(data);
|
| 3898 |
$('#ws_data_length').val(data.length);
|
| 3899 |
$('#ws_selected_actor').val(actorSelectorWidget.selectedActor === null ? '' : actorSelectorWidget.selectedActor);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3900 |
$('#ws_main_form').submit();
|
| 3901 |
});
|
| 3902 |
|
|
@@ -4309,6 +4613,23 @@ function ameOnDomReady() {
|
|
| 4309 |
//Finally, show the menu
|
| 4310 |
loadMenuConfiguration(customMenu);
|
| 4311 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4312 |
//... and make the UI visible now that it's fully rendered.
|
| 4313 |
menuEditorNode.css('visibility', 'visible');
|
| 4314 |
}
|
| 43 |
* @property {object} wsEditorData.postTypes
|
| 44 |
* @property {object} wsEditorData.taxonomies
|
| 45 |
*
|
| 46 |
+
* @property {string|null} wsEditorData.selectedMenu
|
| 47 |
+
* @property {string|null} wsEditorData.selectedSubmenu
|
| 48 |
+
*
|
| 49 |
* @property {boolean} wsEditorData.isDemoMode
|
| 50 |
* @property {boolean} wsEditorData.isMasterMode
|
| 51 |
*/
|
| 401 |
itemData.separator ? '' : '<a class="ws_edit_link"> </a><div class="ws_flag_container"> </div>',
|
| 402 |
'<input type="checkbox" class="ws_actor_access_checkbox">',
|
| 403 |
'<span class="ws_item_title">',
|
| 404 |
+
formatMenuTitle(menuTitle),
|
| 405 |
' </span>',
|
| 406 |
|
| 407 |
'</div>',
|
| 462 |
return input.replace(commentsAndPhpTags, '').replace(tags, '');
|
| 463 |
}
|
| 464 |
|
| 465 |
+
function truncateString(input, maxLength, padding) {
|
| 466 |
+
if (typeof padding === 'undefined') {
|
| 467 |
+
padding = '';
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
if (input.length > maxLength) {
|
| 471 |
+
input = input.substring(0, maxLength - 1) + padding;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
return input;
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
/**
|
| 478 |
+
* Format menu title for display in HTML.
|
| 479 |
+
* Strips tags and truncates long titles.
|
| 480 |
+
*
|
| 481 |
+
* @param {String} title
|
| 482 |
+
* @returns {String}
|
| 483 |
+
*/
|
| 484 |
+
function formatMenuTitle(title) {
|
| 485 |
+
title = stripAllTags(title);
|
| 486 |
+
|
| 487 |
+
//Compact whitespace.
|
| 488 |
+
title = title.replace(/[\s\t\r\n]+/g, ' ');
|
| 489 |
+
title = jsTrim(title);
|
| 490 |
+
|
| 491 |
+
//The max. length was chosen empirically.
|
| 492 |
+
title = truncateString(title, 34, '\u2026');
|
| 493 |
+
return title;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
//Editor field spec template.
|
| 497 |
var baseField = {
|
| 498 |
caption : '[No caption]',
|
| 518 |
caption : 'Menu title',
|
| 519 |
display: function(menuItem, displayValue, input, containerNode) {
|
| 520 |
//Update the header as well.
|
| 521 |
+
containerNode.find('.ws_item_title').html(formatMenuTitle(displayValue) + ' ');
|
| 522 |
return displayValue;
|
| 523 |
},
|
| 524 |
write: function(menuItem, value, input, containerNode) {
|
| 770 |
}
|
| 771 |
}),
|
| 772 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 773 |
'icon_url' : $.extend({}, baseField, {
|
| 774 |
caption: 'Icon URL',
|
| 775 |
type : 'icon_selector',
|
| 830 |
}
|
| 831 |
}),
|
| 832 |
|
| 833 |
+
'css_class' : $.extend({}, baseField, {
|
| 834 |
+
caption: 'CSS classes',
|
| 835 |
+
advanced : true,
|
| 836 |
+
onlyForTopMenus: true
|
| 837 |
+
}),
|
| 838 |
+
|
| 839 |
+
'open_in' : $.extend({}, baseField, {
|
| 840 |
+
caption: 'Open in',
|
| 841 |
+
advanced : true,
|
| 842 |
+
type : 'select',
|
| 843 |
+
options : [
|
| 844 |
+
['Same window or tab', 'same_window'],
|
| 845 |
+
['New window', 'new_window'],
|
| 846 |
+
['Frame', 'iframe']
|
| 847 |
+
],
|
| 848 |
+
defaultValue: 'same_window',
|
| 849 |
+
visible: false
|
| 850 |
+
}),
|
| 851 |
+
|
| 852 |
+
'iframe_height' : $.extend({}, baseField, {
|
| 853 |
+
caption: 'Frame height (pixels)',
|
| 854 |
+
advanced : true,
|
| 855 |
+
visible: function(menuItem) {
|
| 856 |
+
return wsEditorData.wsMenuEditorPro && (getFieldValue(menuItem, 'open_in') === 'iframe');
|
| 857 |
+
},
|
| 858 |
+
|
| 859 |
+
display: function(menuItem, displayValue, input) {
|
| 860 |
+
input.prop('placeholder', 'Auto');
|
| 861 |
+
if (displayValue === 0 || displayValue === '0') {
|
| 862 |
+
displayValue = '';
|
| 863 |
+
}
|
| 864 |
+
return displayValue;
|
| 865 |
+
},
|
| 866 |
+
|
| 867 |
+
write: function(menuItem, value) {
|
| 868 |
+
value = parseInt(value, 10);
|
| 869 |
+
if (isNaN(value) || (value < 0)) {
|
| 870 |
+
value = 0;
|
| 871 |
+
}
|
| 872 |
+
value = Math.round(value);
|
| 873 |
+
|
| 874 |
+
if (value > 10000) {
|
| 875 |
+
value = 10000;
|
| 876 |
+
}
|
| 877 |
+
|
| 878 |
+
if (value === 0) {
|
| 879 |
+
menuItem.iframe_height = null;
|
| 880 |
+
} else {
|
| 881 |
+
menuItem.iframe_height = value;
|
| 882 |
+
}
|
| 883 |
+
|
| 884 |
+
}
|
| 885 |
+
}),
|
| 886 |
+
|
| 887 |
'colors' : $.extend({}, baseField, {
|
| 888 |
caption: 'Color scheme',
|
| 889 |
defaultValue: 'Default',
|
| 922 |
}
|
| 923 |
}),
|
| 924 |
|
| 925 |
+
'page_title' : $.extend({}, baseField, {
|
| 926 |
+
caption: "Window title",
|
| 927 |
+
standardCaption : true,
|
| 928 |
+
advanced : true
|
| 929 |
+
}),
|
| 930 |
+
|
| 931 |
'page_heading' : $.extend({}, baseField, {
|
| 932 |
caption: 'Page heading',
|
| 933 |
advanced : true,
|
| 1363 |
}
|
| 1364 |
}
|
| 1365 |
|
| 1366 |
+
//Use the custom menu title as the page title if the default page title matches the default menu title.
|
| 1367 |
+
//Note that if the page title is an empty string (''), WP automatically uses the menu title. So we do the same.
|
| 1368 |
+
if ((fieldName === 'page_title') && (entry.template_id !== '')) {
|
| 1369 |
+
var defaultPageTitle = itemTemplates.getDefaultValue(entry.template_id, 'page_title'),
|
| 1370 |
+
defaultMenuTitle = itemTemplates.getDefaultValue(entry.template_id, 'menu_title'),
|
| 1371 |
+
customMenuTitle = entry['menu_title'];
|
| 1372 |
+
|
| 1373 |
+
if (
|
| 1374 |
+
(customMenuTitle !== null)
|
| 1375 |
+
&& (customMenuTitle !== '')
|
| 1376 |
+
&& ((defaultPageTitle === '') || (defaultMenuTitle === defaultPageTitle))
|
| 1377 |
+
) {
|
| 1378 |
+
return customMenuTitle;
|
| 1379 |
+
}
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
if (typeof defaultValue === 'undefined') {
|
| 1383 |
defaultValue = null;
|
| 1384 |
}
|
| 1450 |
});
|
| 1451 |
};
|
| 1452 |
|
| 1453 |
+
/**
|
| 1454 |
+
* Select the first menu item that has the specified URL.
|
| 1455 |
+
*
|
| 1456 |
+
* @param {string} boxSelector
|
| 1457 |
+
* @param {string} url
|
| 1458 |
+
* @param {boolean|null} [expandProperties]
|
| 1459 |
+
* @returns {JQuery}
|
| 1460 |
+
*/
|
| 1461 |
+
AmeEditorApi.selectMenuItemByUrl = function(boxSelector, url, expandProperties) {
|
| 1462 |
+
if (typeof expandProperties === 'undefined') {
|
| 1463 |
+
expandProperties = null;
|
| 1464 |
+
}
|
| 1465 |
+
|
| 1466 |
+
var box = $(boxSelector);
|
| 1467 |
+
if (box.is('#ws_submenu_box')) {
|
| 1468 |
+
box = box.find('.ws_submenu:visible').first();
|
| 1469 |
+
}
|
| 1470 |
+
|
| 1471 |
+
var containerNode =
|
| 1472 |
+
box.find('.ws_container')
|
| 1473 |
+
.filter(function() {
|
| 1474 |
+
var itemUrl = AmeEditorApi.getItemDisplayUrl($(this).data('menu_item'));
|
| 1475 |
+
return (itemUrl === url);
|
| 1476 |
+
})
|
| 1477 |
+
.first();
|
| 1478 |
+
|
| 1479 |
+
if (containerNode.length > 0) {
|
| 1480 |
+
AmeEditorApi.selectItem(containerNode);
|
| 1481 |
+
|
| 1482 |
+
if (expandProperties !== null) {
|
| 1483 |
+
var expandLink = containerNode.find('.ws_edit_link').first();
|
| 1484 |
+
if (expandLink.hasClass('ws_edit_link_expanded') !== expandProperties) {
|
| 1485 |
+
expandLink.click();
|
| 1486 |
+
}
|
| 1487 |
+
}
|
| 1488 |
+
}
|
| 1489 |
+
return containerNode;
|
| 1490 |
+
};
|
| 1491 |
+
|
| 1492 |
/***************************************************************************
|
| 1493 |
Parsing & encoding menu inputs
|
| 1494 |
***************************************************************************/
|
| 1980 |
submenuBox = $('#ws_submenu_box'),
|
| 1981 |
submenuDropZone = submenuBox.closest('.ws_main_container').find('.ws_dropzone');
|
| 1982 |
|
|
|
|
| 1983 |
var currentVisibleSubmenu = null;
|
| 1984 |
+
|
| 1985 |
+
/**
|
| 1986 |
+
* Select a menu item and show its submenu.
|
| 1987 |
+
*
|
| 1988 |
+
* @param {JQuery|HTMLElement} container Menu container node.
|
| 1989 |
+
*/
|
| 1990 |
+
function selectItem(container) {
|
| 1991 |
if (container.hasClass('ws_active')) {
|
| 1992 |
+
//The menu item is already selected.
|
| 1993 |
return;
|
| 1994 |
}
|
| 1995 |
|
| 2014 |
container.closest('.ws_main_container')
|
| 2015 |
.find('.ws_toolbar .ws_delete_menu_button')
|
| 2016 |
.toggleClass('ws_button_disabled', !canDeleteItem(container));
|
| 2017 |
+
}
|
| 2018 |
+
AmeEditorApi.selectItem = selectItem;
|
| 2019 |
+
|
| 2020 |
+
//Select the clicked menu item and show its submenu
|
| 2021 |
+
menuEditorNode.on('click', '.ws_container', (function () {
|
| 2022 |
+
selectItem($(this));
|
| 2023 |
}));
|
| 2024 |
|
| 2025 |
function updateSubmenuBoxHeight(selectedMenu) {
|
| 2377 |
|
| 2378 |
var capSelectorDropdown = $('#ws_cap_selector');
|
| 2379 |
var currentDropdownOwner = null; //The input element that the dropdown is currently associated with.
|
| 2380 |
+
var currentDropdownOwnerMenu = null; //The menu item that the above input belongs to.
|
| 2381 |
+
|
| 2382 |
+
var isDropdownBeingHidden = false, isSuggestionClick = false;
|
| 2383 |
|
| 2384 |
//Show/hide the capability drop-down list when the trigger button is clicked
|
| 2385 |
$('#ws_trigger_capability_dropdown').on('mousedown click', onDropdownTriggerClicked);
|
| 2390 |
var inputBox = null;
|
| 2391 |
var button = $(this);
|
| 2392 |
|
| 2393 |
+
var isInAccessEditor = false;
|
| 2394 |
+
isSuggestionClick = false;
|
| 2395 |
+
|
| 2396 |
//Find the input associated with the button that was clicked.
|
| 2397 |
if ( button.attr('id') === 'ws_trigger_capability_dropdown' ) {
|
| 2398 |
inputBox = $('#ws_extra_capability');
|
| 2399 |
+
isInAccessEditor = true;
|
| 2400 |
} else {
|
| 2401 |
inputBox = button.closest('.ws_edit_field').find('.ws_field_value').first();
|
| 2402 |
}
|
| 2439 |
width(inputBox.outerWidth());
|
| 2440 |
|
| 2441 |
currentDropdownOwner = inputBox;
|
| 2442 |
+
|
| 2443 |
+
currentDropdownOwnerMenu = null;
|
| 2444 |
+
if (isInAccessEditor) {
|
| 2445 |
+
currentDropdownOwnerMenu = AmeItemAccessEditor.getCurrentMenuItem();
|
| 2446 |
+
} else {
|
| 2447 |
+
currentDropdownOwnerMenu = currentDropdownOwner.closest('.ws_container').data('menu_item');
|
| 2448 |
+
}
|
| 2449 |
+
|
| 2450 |
capSelectorDropdown.focus();
|
| 2451 |
+
|
| 2452 |
+
capSuggestionFeature.show();
|
| 2453 |
}
|
| 2454 |
|
| 2455 |
//Also show it when the user presses the down arrow in the input field (doesn't work in Opera).
|
| 2459 |
}
|
| 2460 |
});
|
| 2461 |
|
| 2462 |
+
function hideCapSelector() {
|
| 2463 |
+
capSelectorDropdown.hide();
|
| 2464 |
+
capSuggestionFeature.hide();
|
| 2465 |
+
isSuggestionClick = false;
|
| 2466 |
+
}
|
| 2467 |
+
|
| 2468 |
//Event handlers for the drop-down lists themselves
|
| 2469 |
var dropdownNodes = $('.ws_dropdown');
|
| 2470 |
|
| 2471 |
// Hide capability drop-down when it loses focus.
|
| 2472 |
dropdownNodes.blur(function(){
|
| 2473 |
+
if (!isSuggestionClick) {
|
| 2474 |
+
hideCapSelector();
|
| 2475 |
+
}
|
| 2476 |
});
|
| 2477 |
|
| 2478 |
dropdownNodes.keydown(function(event){
|
| 2479 |
|
| 2480 |
//Hide it when the user presses Esc
|
| 2481 |
if ( event.which === 27 ){
|
| 2482 |
+
hideCapSelector();
|
| 2483 |
if (currentDropdownOwner) {
|
| 2484 |
currentDropdownOwner.focus();
|
| 2485 |
}
|
| 2486 |
|
| 2487 |
//Select an item & hide the list when the user presses Enter or Tab
|
| 2488 |
} else if ( (event.which === 13) || (event.which === 9) ){
|
| 2489 |
+
hideCapSelector();
|
| 2490 |
|
| 2491 |
if (currentDropdownOwner) {
|
| 2492 |
if ( capSelectorDropdown.val() ){
|
| 2510 |
//Update the input & hide the list when an option is clicked
|
| 2511 |
dropdownNodes.click(function(){
|
| 2512 |
if (capSelectorDropdown.val()){
|
| 2513 |
+
hideCapSelector();
|
| 2514 |
if (currentDropdownOwner) {
|
| 2515 |
currentDropdownOwner.val(capSelectorDropdown.val()).change().focus();
|
| 2516 |
}
|
| 2526 |
var option = event.target;
|
| 2527 |
if ( (typeof option.selected !== 'undefined') && !option.selected && option.value ){
|
| 2528 |
option.selected = true;
|
| 2529 |
+
|
| 2530 |
+
//Preview which roles have this capability and the required cap.
|
| 2531 |
+
capSuggestionFeature.previewAccessForItem(currentDropdownOwnerMenu, option.value);
|
| 2532 |
}
|
| 2533 |
});
|
| 2534 |
|
| 2535 |
+
/************************************************************************
|
| 2536 |
+
* Capability suggestions
|
| 2537 |
+
*************************************************************************/
|
| 2538 |
+
|
| 2539 |
+
var capSuggestionFeature = (function() {
|
| 2540 |
+
//This feature is not used in the Pro version because it has a different permission UI.
|
| 2541 |
+
if (wsEditorData.wsMenuEditorPro) {
|
| 2542 |
+
return {
|
| 2543 |
+
previewAccessForItem: function () {},
|
| 2544 |
+
show: function () {},
|
| 2545 |
+
hide: function () {}
|
| 2546 |
+
}
|
| 2547 |
+
}
|
| 2548 |
+
|
| 2549 |
+
var capabilitySuggestions = $('#ws_capability_suggestions'),
|
| 2550 |
+
suggestionBody = capabilitySuggestions.find('table tbody').first().empty(),
|
| 2551 |
+
suggestedCapabilities = AmeActors.getSuggestedCapabilities();
|
| 2552 |
+
|
| 2553 |
+
for (var i = 0; i < suggestedCapabilities.length; i++) {
|
| 2554 |
+
var role = suggestedCapabilities[i].role, capability = suggestedCapabilities[i].capability;
|
| 2555 |
+
$('<tr>')
|
| 2556 |
+
.data('role', role)
|
| 2557 |
+
.data('capability', capability)
|
| 2558 |
+
.append(
|
| 2559 |
+
$('<th>', {text: role.displayName, scope: 'row'}).addClass('ws_ame_role_name')
|
| 2560 |
+
)
|
| 2561 |
+
.append(
|
| 2562 |
+
$('<td>', {text: capability}).addClass('ws_ame_suggested_capability')
|
| 2563 |
+
)
|
| 2564 |
+
.appendTo(suggestionBody);
|
| 2565 |
+
}
|
| 2566 |
+
|
| 2567 |
+
var currentPreviewedCaps = null;
|
| 2568 |
+
|
| 2569 |
+
/**
|
| 2570 |
+
* Update the access preview.
|
| 2571 |
+
* @param {string|string[]|null} capabilities
|
| 2572 |
+
*/
|
| 2573 |
+
function previewAccess(capabilities) {
|
| 2574 |
+
if (typeof capabilities === 'string') {
|
| 2575 |
+
capabilities = [capabilities];
|
| 2576 |
+
}
|
| 2577 |
+
|
| 2578 |
+
if (_.isEqual(capabilities, currentPreviewedCaps)) {
|
| 2579 |
+
return;
|
| 2580 |
+
}
|
| 2581 |
+
currentPreviewedCaps = capabilities;
|
| 2582 |
+
capabilitySuggestions.find('#ws_previewed_caps').text(currentPreviewedCaps.join(' + '));
|
| 2583 |
+
|
| 2584 |
+
//Short-circuit the no-caps case.
|
| 2585 |
+
if (capabilities === null || capabilities.length === 0) {
|
| 2586 |
+
suggestionBody.find('tr').removeClass('ws_preview_has_access');
|
| 2587 |
+
return;
|
| 2588 |
+
}
|
| 2589 |
+
|
| 2590 |
+
suggestionBody.find('tr').each(function() {
|
| 2591 |
+
var $row = $(this),
|
| 2592 |
+
role = $row.data('role');
|
| 2593 |
+
|
| 2594 |
+
var hasCaps = true;
|
| 2595 |
+
for (var i = 0; i < capabilities.length; i++) {
|
| 2596 |
+
hasCaps = hasCaps && AmeActors.hasCap(role.id, capabilities[i]);
|
| 2597 |
+
}
|
| 2598 |
+
$row.toggleClass('ws_preview_has_access', hasCaps);
|
| 2599 |
+
});
|
| 2600 |
+
}
|
| 2601 |
+
|
| 2602 |
+
function previewAccessForItem(menuItem, selectedExtraCap) {
|
| 2603 |
+
var requiredCap = '', extraCap = '';
|
| 2604 |
+
|
| 2605 |
+
if (menuItem) {
|
| 2606 |
+
requiredCap = getFieldValue(menuItem, 'access_level', '');
|
| 2607 |
+
extraCap = getFieldValue(menuItem, 'extra_capability', '');
|
| 2608 |
+
}
|
| 2609 |
+
if (typeof selectedExtraCap !== 'undefined') {
|
| 2610 |
+
extraCap = selectedExtraCap;
|
| 2611 |
+
}
|
| 2612 |
+
|
| 2613 |
+
var caps = [];
|
| 2614 |
+
if (menuItem && (menuItem.template_id !== '') || (extraCap === '')) {
|
| 2615 |
+
caps.push(requiredCap);
|
| 2616 |
+
}
|
| 2617 |
+
if (extraCap !== '') {
|
| 2618 |
+
caps.push(extraCap);
|
| 2619 |
+
}
|
| 2620 |
+
|
| 2621 |
+
previewAccess(caps);
|
| 2622 |
+
}
|
| 2623 |
+
|
| 2624 |
+
suggestionBody.on('mouseenter', 'td.ws_ame_suggested_capability', function() {
|
| 2625 |
+
var row = $(this).closest('tr');
|
| 2626 |
+
previewAccessForItem(currentDropdownOwnerMenu, row.data('capability'));
|
| 2627 |
+
});
|
| 2628 |
+
|
| 2629 |
+
capSelectorDropdown.on('keydown keyup', function() {
|
| 2630 |
+
previewAccessForItem(currentDropdownOwnerMenu, capSelectorDropdown.val());
|
| 2631 |
+
});
|
| 2632 |
+
|
| 2633 |
+
suggestionBody.on('mousedown', 'td.ws_ame_suggested_capability', function() {
|
| 2634 |
+
//Don't immediately hide the list when the user tries to click a suggestion.
|
| 2635 |
+
//It would prevent the click from registering.
|
| 2636 |
+
isSuggestionClick = true;
|
| 2637 |
+
});
|
| 2638 |
+
|
| 2639 |
+
suggestionBody.on('click', 'td.ws_ame_suggested_capability', function() {
|
| 2640 |
+
var capability = $(this).closest('tr').data('capability');
|
| 2641 |
+
|
| 2642 |
+
//Change the input to the selected capability.
|
| 2643 |
+
if (currentDropdownOwner) {
|
| 2644 |
+
currentDropdownOwner.val(capability).change();
|
| 2645 |
+
}
|
| 2646 |
+
|
| 2647 |
+
hideCapSelector();
|
| 2648 |
+
});
|
| 2649 |
+
|
| 2650 |
+
//Workaround for pressing LMB on a suggestion, then moving the mouse outside the suggestion box and releasing the button.
|
| 2651 |
+
$(document).on('click', function(event) {
|
| 2652 |
+
if (
|
| 2653 |
+
isSuggestionClick
|
| 2654 |
+
&& capabilitySuggestions.is(':visible')
|
| 2655 |
+
&& ( $(event.target).closest(capabilitySuggestions).length < 1 )
|
| 2656 |
+
) {
|
| 2657 |
+
hideCapSelector();
|
| 2658 |
+
}
|
| 2659 |
+
});
|
| 2660 |
+
|
| 2661 |
+
return {
|
| 2662 |
+
previewAccessForItem: previewAccessForItem,
|
| 2663 |
+
show: function() {
|
| 2664 |
+
//Position the capability suggestion table next to the selector and match heights.
|
| 2665 |
+
capabilitySuggestions
|
| 2666 |
+
.css({
|
| 2667 |
+
position: 'absolute',
|
| 2668 |
+
zIndex: 1009
|
| 2669 |
+
})
|
| 2670 |
+
.show()
|
| 2671 |
+
.position({
|
| 2672 |
+
my: 'left top',
|
| 2673 |
+
at: 'right top',
|
| 2674 |
+
of: capSelectorDropdown,
|
| 2675 |
+
collision: 'none'
|
| 2676 |
+
});
|
| 2677 |
+
|
| 2678 |
+
var selectorHeight = capSelectorDropdown.height(),
|
| 2679 |
+
suggestionsHeight = capabilitySuggestions.height(),
|
| 2680 |
+
desiredHeight = Math.max(selectorHeight, suggestionsHeight);
|
| 2681 |
+
if (selectorHeight < desiredHeight) {
|
| 2682 |
+
capSelectorDropdown.height(desiredHeight);
|
| 2683 |
+
}
|
| 2684 |
+
if (suggestionsHeight < desiredHeight) {
|
| 2685 |
+
capabilitySuggestions.height(desiredHeight);
|
| 2686 |
+
}
|
| 2687 |
+
|
| 2688 |
+
if (currentDropdownOwnerMenu) {
|
| 2689 |
+
previewAccessForItem(currentDropdownOwnerMenu);
|
| 2690 |
+
}
|
| 2691 |
+
},
|
| 2692 |
+
hide: function() {
|
| 2693 |
+
capabilitySuggestions.hide();
|
| 2694 |
+
}
|
| 2695 |
+
};
|
| 2696 |
+
})();
|
| 2697 |
+
|
| 2698 |
+
|
| 2699 |
/*************************************************************************
|
| 2700 |
Icon selector
|
| 2701 |
*************************************************************************/
|
| 3164 |
|
| 3165 |
//Add menu title to the dialog caption.
|
| 3166 |
var title = getFieldValue(menuItem, 'menu_title', null);
|
| 3167 |
+
setUpColorDialog(title ? ('Colors: ' + formatMenuTitle(title)) : 'Colors');
|
| 3168 |
|
| 3169 |
//Show the [global] preset only if the user has set it up.
|
| 3170 |
var globalPresetExists = colorPresets.hasOwnProperty('[global]');
|
| 4188 |
$('#ws_data').val(data);
|
| 4189 |
$('#ws_data_length').val(data.length);
|
| 4190 |
$('#ws_selected_actor').val(actorSelectorWidget.selectedActor === null ? '' : actorSelectorWidget.selectedActor);
|
| 4191 |
+
|
| 4192 |
+
var selectedMenu = getSelectedMenu();
|
| 4193 |
+
if (selectedMenu.length > 0) {
|
| 4194 |
+
$('#ws_selected_menu_url').val(AmeEditorApi.getItemDisplayUrl(selectedMenu.data('menu_item')));
|
| 4195 |
+
$('#ws_expand_selected_menu').val(selectedMenu.find('.ws_editbox').is(':visible') ? '1' : '');
|
| 4196 |
+
|
| 4197 |
+
var selectedSubmenu = getSelectedSubmenuItem();
|
| 4198 |
+
if (selectedSubmenu.length > 0) {
|
| 4199 |
+
$('#ws_selected_submenu_url').val(AmeEditorApi.getItemDisplayUrl(selectedSubmenu.data('menu_item')));
|
| 4200 |
+
$('#ws_expand_selected_submenu').val(selectedSubmenu.find('.ws_editbox').is(':visible') ? '1' : '');
|
| 4201 |
+
}
|
| 4202 |
+
}
|
| 4203 |
+
|
| 4204 |
$('#ws_main_form').submit();
|
| 4205 |
});
|
| 4206 |
|
| 4613 |
//Finally, show the menu
|
| 4614 |
loadMenuConfiguration(customMenu);
|
| 4615 |
|
| 4616 |
+
//Select the previous selected menu, if any.
|
| 4617 |
+
if (wsEditorData.selectedMenu) {
|
| 4618 |
+
AmeEditorApi.selectMenuItemByUrl(
|
| 4619 |
+
'#ws_menu_box',
|
| 4620 |
+
wsEditorData.selectedMenu,
|
| 4621 |
+
_.get(wsEditorData, 'expandSelectedMenu') === '1'
|
| 4622 |
+
);
|
| 4623 |
+
|
| 4624 |
+
if (wsEditorData.selectedSubmenu) {
|
| 4625 |
+
AmeEditorApi.selectMenuItemByUrl(
|
| 4626 |
+
'#ws_submenu_box',
|
| 4627 |
+
wsEditorData.selectedSubmenu,
|
| 4628 |
+
_.get(wsEditorData, 'expandSelectedSubmenu') === '1'
|
| 4629 |
+
);
|
| 4630 |
+
}
|
| 4631 |
+
}
|
| 4632 |
+
|
| 4633 |
//... and make the UI visible now that it's fully rendered.
|
| 4634 |
menuEditorNode.css('visibility', 'visible');
|
| 4635 |
}
|
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.
|
| 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.7.2
|
| 7 |
Author: Janis Elsts
|
| 8 |
Author URI: http://w-shadow.com/blog/
|
| 9 |
*/
|
modules/access-editor/access-editor.js
CHANGED
|
@@ -488,6 +488,10 @@ window.AmeItemAccessEditor = (function ($) {
|
|
| 488 |
$('#ws_role_access_container').toggleClass('ws_has_extended_permissions', hasExtendedPermissions);
|
| 489 |
},
|
| 490 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
detectExtPermissions: detectExtPermissions
|
| 492 |
};
|
| 493 |
})(jQuery);
|
| 488 |
$('#ws_role_access_container').toggleClass('ws_has_extended_permissions', hasExtendedPermissions);
|
| 489 |
},
|
| 490 |
|
| 491 |
+
getCurrentMenuItem: function() {
|
| 492 |
+
return menuItem;
|
| 493 |
+
},
|
| 494 |
+
|
| 495 |
detectExtPermissions: detectExtPermissions
|
| 496 |
};
|
| 497 |
})(jQuery);
|
readme.txt
CHANGED
|
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
|
|
| 4 |
Tags: admin, dashboard, menu, security, wpmu
|
| 5 |
Requires at least: 4.1
|
| 6 |
Tested up to: 4.6
|
| 7 |
-
Stable tag: 1.7.
|
| 8 |
|
| 9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
| 10 |
|
|
@@ -63,6 +63,13 @@ Plugins installed in the `mu-plugins` directory are treated as "always on", so y
|
|
| 63 |
|
| 64 |
== Changelog ==
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
= 1.7.1 =
|
| 67 |
* Split the "required capability" field into two parts - a read-only field that shows the actual required capability, and an editable "extra capability" that you can use to restrict access to the menu.
|
| 68 |
* Added more detailed permission error messages. You can turn them off in the "Settings" tab by changing "Error verbosity level" to "Low".
|
| 4 |
Tags: admin, dashboard, menu, security, wpmu
|
| 5 |
Requires at least: 4.1
|
| 6 |
Tested up to: 4.6
|
| 7 |
+
Stable tag: 1.7.2
|
| 8 |
|
| 9 |
Lets you edit the WordPress admin menu. You can re-order, hide or rename menus, add custom menus and more.
|
| 10 |
|
| 63 |
|
| 64 |
== Changelog ==
|
| 65 |
|
| 66 |
+
= 1.7.2 =
|
| 67 |
+
* Added capability suggestions and access preview to the "Extra capability" dropdown.
|
| 68 |
+
* The plugin now remembers the last selected menu item and re-selects it after you save changes.
|
| 69 |
+
* Fixed a layout issue where menus with very long titles would appear incorrectly in the menu editor.
|
| 70 |
+
* When you change the menu title, the window title will also be changed to match it. You can still edit the window title separately if necessary.
|
| 71 |
+
* Moved the "Icon URL" field up and moved "Window title" down.
|
| 72 |
+
|
| 73 |
= 1.7.1 =
|
| 74 |
* Split the "required capability" field into two parts - a read-only field that shows the actual required capability, and an editable "extra capability" that you can use to restrict access to the menu.
|
| 75 |
* Added more detailed permission error messages. You can turn them off in the "Settings" tab by changing "Error verbosity level" to "Low".
|
