Advanced Access Manager - Version 5.5

Version Description

  • Fixed the bug with EDIT BY OTHERS option
  • Fixed UI bug when managing access to AAM page itself
  • Fixed the bug reported by https://github.com/KenAer
  • Fixed the bug with creating new post when default access is denied to EDIT
  • Fixed the bug with editing page that is in draft state
  • Fixed multiple bugs with AAM export/import feature
  • Fixed the bug with blocked user being able to login again
  • Slightly improved extension installation feedback
  • Improved UI
  • Enhanced JWT token feature
  • Improved the way Backend Menu and Toolbar features work
  • Added multiple-roles support
  • Refactored Import/Export features
  • Removed Settings->Tools tab
Download this release

Release Info

Developer vasyl_m
Plugin Icon 128x128 Advanced Access Manager
Version 5.5
Comparing to
See all releases

Code changes from version 5.4.3.2 to 5.5

Files changed (45) hide show
  1. Application/Api/Rest/Resource/Post.php +3 -12
  2. Application/Backend/Feature/Extension/Manager.php +2 -3
  3. Application/Backend/Feature/Main/Capability.php +4 -1
  4. Application/Backend/Feature/Main/Menu.php +23 -21
  5. Application/Backend/Feature/Main/Post.php +5 -3
  6. Application/Backend/Feature/Main/Toolbar.php +1 -1
  7. Application/Backend/Feature/Settings/Core.php +5 -0
  8. Application/Backend/Feature/Settings/Tools.php +0 -93
  9. Application/Backend/Feature/Subject/Role.php +2 -1
  10. Application/Backend/Feature/Subject/User.php +2 -1
  11. Application/Backend/Filter.php +3 -23
  12. Application/Backend/Manager.php +111 -8
  13. Application/Backend/Subject.php +11 -4
  14. Application/Backend/View.php +45 -1
  15. Application/Backend/phtml/extensions.phtml +6 -2
  16. Application/Backend/phtml/index.phtml +48 -12
  17. Application/Backend/phtml/main/menu.phtml +1 -1
  18. Application/Backend/phtml/main/toolbar.phtml +0 -6
  19. Application/Backend/phtml/metabox/metabox-content.phtml +14 -12
  20. Application/Backend/phtml/partial/post-access-form.phtml +16 -7
  21. Application/Backend/phtml/settings/tools.phtml +0 -74
  22. Application/Backend/phtml/system/export.phtml +67 -0
  23. Application/Core/Exporter.php +43 -19
  24. Application/Core/Gateway.php +44 -0
  25. Application/Core/Importer.php +195 -46
  26. Application/Core/JwtAuth.php +5 -4
  27. Application/Core/Login.php +6 -28
  28. Application/Core/Media.php +1 -5
  29. Application/Core/Object.php +9 -0
  30. Application/Core/Object/Cache.php +20 -3
  31. Application/Core/Object/Menu.php +9 -0
  32. Application/Core/Object/Metabox.php +9 -0
  33. Application/Core/Object/Post.php +30 -3
  34. Application/Core/Object/Toolbar.php +9 -0
  35. Application/Core/Subject.php +47 -1
  36. Application/Core/Subject/User.php +14 -6
  37. Application/Extension/List.php +2 -2
  38. Application/Frontend/Authorization.php +1 -4
  39. Application/Frontend/Filter.php +2 -8
  40. Application/Shared/Manager.php +5 -25
  41. Application/Shortcode/Strategy/LoginRedirect.php +8 -1
  42. aam.php +1 -1
  43. media/css/aam.css +8 -0
  44. media/js/aam.js +339 -378
  45. readme.txt +18 -1
Application/Api/Rest/Resource/Post.php CHANGED
@@ -179,10 +179,7 @@ class AAM_Api_Rest_Resource_Post {
179
  protected function checkReadAccess(AAM_Core_Object_Post $post) {
180
  $result = null;
181
 
182
- $read = $post->has('api.read');
183
- $others = $post->has('api.read_others');
184
-
185
- if ($read || ($others && (intval($post->post_author) !== get_current_user_id()))) {
186
  $result = new WP_Error(
187
  'rest_post_cannot_read',
188
  "User is unauthorized to read the post. Access denied.",
@@ -325,10 +322,7 @@ class AAM_Api_Rest_Resource_Post {
325
  protected function checkUpdate(AAM_Core_Object_Post $post) {
326
  $result = null;
327
 
328
- $edit = $post->has('api.edit');
329
- $others = $post->has('api.edit_others');
330
-
331
- if ($edit || ($others && (intval($post->post_author) !== get_current_user_id()))) {
332
  $result = new WP_Error(
333
  'rest_post_cannot_update',
334
  "User is unauthorized to update the post. Access denied.",
@@ -354,10 +348,7 @@ class AAM_Api_Rest_Resource_Post {
354
  protected function checkDelete(AAM_Core_Object_Post $post) {
355
  $result = null;
356
 
357
- $delete = $post->has('api.delete');
358
- $others = $post->has('api.delete_others');
359
-
360
- if ($delete || ($others && (intval($post->post_author) !== get_current_user_id()))) {
361
  $result = new WP_Error(
362
  'rest_post_cannot_delete',
363
  "User is unauthorized to delete the post. Access denied.",
179
  protected function checkReadAccess(AAM_Core_Object_Post $post) {
180
  $result = null;
181
 
182
+ if (!$post->allowed('api.read')) {
 
 
 
183
  $result = new WP_Error(
184
  'rest_post_cannot_read',
185
  "User is unauthorized to read the post. Access denied.",
322
  protected function checkUpdate(AAM_Core_Object_Post $post) {
323
  $result = null;
324
 
325
+ if (!$post->allowed('api.edit')) {
 
 
 
326
  $result = new WP_Error(
327
  'rest_post_cannot_update',
328
  "User is unauthorized to update the post. Access denied.",
348
  protected function checkDelete(AAM_Core_Object_Post $post) {
349
  $result = null;
350
 
351
+ if (!$post->allowed('api.delete')) {
 
 
 
352
  $result = new WP_Error(
353
  'rest_post_cannot_delete',
354
  "User is unauthorized to delete the post. Access denied.",
Application/Backend/Feature/Extension/Manager.php CHANGED
@@ -67,10 +67,9 @@ class AAM_Backend_Feature_Extension_Manager extends AAM_Backend_Feature_Abstract
67
  $package = AAM_Core_Server::download($license);
68
 
69
  if (is_wp_error($package)) {
70
- $manually = __('You may try to install extension manually.', AAM_KEY);
71
  $response = array(
72
  'status' => 'failure',
73
- 'error' => wp_strip_all_tags($package->get_error_message()) . ' ' . $manually
74
  );
75
  }elseif ($error = $repo->checkDirectory()) {
76
  $response = $this->installFailureResponse($error, $package);
@@ -78,7 +77,7 @@ class AAM_Backend_Feature_Extension_Manager extends AAM_Backend_Feature_Abstract
78
  } elseif (empty($package->content)) { //any unpredictable scenario
79
  $response = array(
80
  'status' => 'failure',
81
- 'error' => __('Download failure. Please try again or contact us.', AAM_KEY)
82
  );
83
  } else { //otherwise install the extension
84
  $result = $repo->add(base64_decode($package->content));
67
  $package = AAM_Core_Server::download($license);
68
 
69
  if (is_wp_error($package)) {
 
70
  $response = array(
71
  'status' => 'failure',
72
+ 'error' => wp_strip_all_tags($package->get_error_message())
73
  );
74
  }elseif ($error = $repo->checkDirectory()) {
75
  $response = $this->installFailureResponse($error, $package);
77
  } elseif (empty($package->content)) { //any unpredictable scenario
78
  $response = array(
79
  'status' => 'failure',
80
+ 'error' => __('Download failure. Try again or contact us.', AAM_KEY)
81
  );
82
  } else { //otherwise install the extension
83
  $result = $repo->add(base64_decode($package->content));
Application/Backend/Feature/Main/Capability.php CHANGED
@@ -52,7 +52,7 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
52
  'aam_manage_login_redirect', 'aam_manage_logout_redirect', 'aam_manager',
53
  'aam_manage_settings', 'aam_manage_extensions', 'aam_show_notifications',
54
  'aam_manage_404_redirect', 'aam_manage_ip_check', 'aam_manage_admin_toolbar',
55
- 'aam_manage_default', 'aam_manage_visitors', 'aam_list_roles',
56
  'aam_edit_roles', 'aam_delete_roles', 'aam_toggle_users', 'aam_switch_users',
57
  'aam_manage_configpress', 'aam_manage_api_routes'
58
  )
@@ -154,6 +154,9 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
154
  && ($subject->getUID() === AAM_Core_Subject_Role::UID)) {
155
  $actions[] = 'edit';
156
  $actions[] = 'delete';
 
 
 
157
  }
158
 
159
  return implode(',', $actions);
52
  'aam_manage_login_redirect', 'aam_manage_logout_redirect', 'aam_manager',
53
  'aam_manage_settings', 'aam_manage_extensions', 'aam_show_notifications',
54
  'aam_manage_404_redirect', 'aam_manage_ip_check', 'aam_manage_admin_toolbar',
55
+ 'aam_manage_default', 'aam_manage_visitors', 'aam_manage_roles', 'aam_manage_users',
56
  'aam_edit_roles', 'aam_delete_roles', 'aam_toggle_users', 'aam_switch_users',
57
  'aam_manage_configpress', 'aam_manage_api_routes'
58
  )
154
  && ($subject->getUID() === AAM_Core_Subject_Role::UID)) {
155
  $actions[] = 'edit';
156
  $actions[] = 'delete';
157
+ } else {
158
+ $actions[] = 'no-edit';
159
+ $actions[] = 'no-delete';
160
  }
161
 
162
  return implode(',', $actions);
Application/Backend/Feature/Main/Menu.php CHANGED
@@ -47,30 +47,32 @@ class AAM_Backend_Feature_Main_Menu extends AAM_Backend_Feature_Abstract {
47
  * @global array $menu
48
  */
49
  public function getMenu() {
50
- global $menu;
51
 
52
  $response = array();
53
 
54
  //let's create menu list with submenus
55
- foreach ($menu as $item) {
56
- if (preg_match('/^separator/', $item[2])) {
57
- continue; //skip separator
58
- }
59
-
60
- $submenu = $this->getSubmenu($item[2]);
61
-
62
- $allowed = AAM_Backend_Subject::getInstance()->hasCapability($item[1]);
63
-
64
- if ($allowed || count($submenu) > 0) {
65
- $response[] = array(
66
- //add menu- prefix to define that this is the top level menu
67
- //WordPress by default gives the same menu id to the first
68
- //submenu
69
- 'id' => 'menu-' . $item[2],
70
- 'name' => $this->filterMenuName($item[0]),
71
- 'submenu' => $submenu,
72
- 'capability' => $item[1]
73
- );
 
 
74
  }
75
  }
76
 
@@ -108,7 +110,7 @@ class AAM_Backend_Feature_Main_Menu extends AAM_Backend_Feature_Abstract {
108
  * @global array $submenu
109
  */
110
  protected function getSubmenu($menu) {
111
- global $submenu;
112
 
113
  $response = array();
114
  $subject = AAM_Backend_Subject::getInstance();
47
  * @global array $menu
48
  */
49
  public function getMenu() {
50
+ $menu = json_decode(base64_decode(AAM_Core_Request::post('menu')), 1);
51
 
52
  $response = array();
53
 
54
  //let's create menu list with submenus
55
+ if (!empty($menu)) {
56
+ foreach ($menu as $item) {
57
+ if (preg_match('/^separator/', $item[2])) {
58
+ continue; //skip separator
59
+ }
60
+
61
+ $submenu = $this->getSubmenu($item[2]);
62
+
63
+ $allowed = AAM_Backend_Subject::getInstance()->hasCapability($item[1]);
64
+
65
+ if ($allowed || count($submenu) > 0) {
66
+ $response[] = array(
67
+ //add menu- prefix to define that this is the top level menu
68
+ //WordPress by default gives the same menu id to the first
69
+ //submenu
70
+ 'id' => 'menu-' . $item[2],
71
+ 'name' => $this->filterMenuName($item[0]),
72
+ 'submenu' => $submenu,
73
+ 'capability' => $item[1]
74
+ );
75
+ }
76
  }
77
  }
78
 
110
  * @global array $submenu
111
  */
112
  protected function getSubmenu($menu) {
113
+ $submenu = json_decode(base64_decode(AAM_Core_Request::post('submenu')), 1);
114
 
115
  $response = array();
116
  $subject = AAM_Backend_Subject::getInstance();
Application/Backend/Feature/Main/Post.php CHANGED
@@ -156,7 +156,7 @@ class AAM_Backend_Feature_Main_Post extends AAM_Backend_Feature_Abstract {
156
  $link,
157
  'post',
158
  get_the_title($record),
159
- 'manage' . ($link ? ',edit' : ''),
160
  $parent,
161
  AAM_Backend_Subject::getInstance()->getObject('post', $record->ID)->isOverwritten()
162
  );
@@ -392,17 +392,19 @@ class AAM_Backend_Feature_Main_Post extends AAM_Backend_Feature_Abstract {
392
  $object = AAM_Backend_Subject::getInstance()->getObject($type, $id);
393
 
394
  //prepare the response object
 
395
  if (is_a($object, 'AAM_Core_Object')) {
396
  foreach($object->getOption() as $key => $value) {
397
- if (in_array($value, array(1, '1', 0, '0', false, "false", true, "true"), true)) {
398
  $access[$key] = !empty($value);
399
  } else {
400
  $access[$key] = $value;
401
  }
402
  }
403
  $metadata = array('overwritten' => $object->isOverwritten());
 
404
  }
405
-
406
  return wp_json_encode(array(
407
  'access' => $access,
408
  'meta' => $metadata,
156
  $link,
157
  'post',
158
  get_the_title($record),
159
+ 'manage' . ($link ? ',edit' : ',no-edit'),
160
  $parent,
161
  AAM_Backend_Subject::getInstance()->getObject('post', $record->ID)->isOverwritten()
162
  );
392
  $object = AAM_Backend_Subject::getInstance()->getObject($type, $id);
393
 
394
  //prepare the response object
395
+ $bValues = array(1, '1', 0, '0', false, "false", true, "true");
396
  if (is_a($object, 'AAM_Core_Object')) {
397
  foreach($object->getOption() as $key => $value) {
398
+ if (in_array($value, $bValues, true)) {
399
  $access[$key] = !empty($value);
400
  } else {
401
  $access[$key] = $value;
402
  }
403
  }
404
  $metadata = array('overwritten' => $object->isOverwritten());
405
+ $access = apply_filters('aam-get-post-access-filter', $access, $object);
406
  }
407
+
408
  return wp_json_encode(array(
409
  'access' => $access,
410
  'meta' => $metadata,
Application/Backend/Feature/Main/Toolbar.php CHANGED
@@ -47,7 +47,7 @@ class AAM_Backend_Feature_Main_Toolbar extends AAM_Backend_Feature_Abstract {
47
  * @global array $menu
48
  */
49
  public function getToolbar() {
50
- return AAM_Core_API::getOption('aam_toolbar_cache', array());
51
  }
52
 
53
  /**
47
  * @global array $menu
48
  */
49
  public function getToolbar() {
50
+ return json_decode(base64_decode(AAM_Core_Request::post('toolbar')));
51
  }
52
 
53
  /**
Application/Backend/Feature/Settings/Core.php CHANGED
@@ -83,6 +83,11 @@ class AAM_Backend_Feature_Settings_Core extends AAM_Backend_Feature_Abstract {
83
  'descr' => sprintf(AAM_Backend_View_Helper::preparePhrase('[Note!] PHP 5.4 or higher is required for this feature. Enable the ability to authenticate user with WordPress RESTful API and JWT token. For more information, check %sHow to authenticate WordPress user with JWT token%s article', 'b'), '<a href="https://aamplugin.com/help/how-to-authenticate-wordpress-user-with-jwt-token">', '</a>'),
84
  'value' => AAM_Core_Config::get('core.settings.jwtAuthentication', false)
85
  ),
 
 
 
 
 
86
  'core.settings.extensionSupport' => array(
87
  'title' => __('Support AAM Extensions', AAM_KEY),
88
  'descr' => __('AAM comes with the limited list of premium and free extensions that significantly enhance AAM behavior. You can disable support for AAM extension and any already installed extension will no longer be loaded during the website execution as well as website administrator will not be able to install new extensions.', AAM_KEY),
83
  'descr' => sprintf(AAM_Backend_View_Helper::preparePhrase('[Note!] PHP 5.4 or higher is required for this feature. Enable the ability to authenticate user with WordPress RESTful API and JWT token. For more information, check %sHow to authenticate WordPress user with JWT token%s article', 'b'), '<a href="https://aamplugin.com/help/how-to-authenticate-wordpress-user-with-jwt-token">', '</a>'),
84
  'value' => AAM_Core_Config::get('core.settings.jwtAuthentication', false)
85
  ),
86
+ 'core.settings.multiSubject' => array(
87
+ 'title' => __('Multiple Roles Support', AAM_KEY),
88
+ 'descr' => sprintf(__('Enable support for multiple roles per use. The final access settings or general settings will be computed based on the mergin preferences. For more information check %sWordPress access control for users with multiple roles%s article.', AAM_KEY), '<a href="https://aamplugin.com/help/wordpress-access-control-for-users-with-multiple-roles">', '</a>'),
89
+ 'value' => AAM_Core_Config::get('core.settings.multiSubject', false)
90
+ ),
91
  'core.settings.extensionSupport' => array(
92
  'title' => __('Support AAM Extensions', AAM_KEY),
93
  'descr' => __('AAM comes with the limited list of premium and free extensions that significantly enhance AAM behavior. You can disable support for AAM extension and any already installed extension will no longer be loaded during the website execution as well as website administrator will not be able to install new extensions.', AAM_KEY),
Application/Backend/Feature/Settings/Tools.php DELETED
@@ -1,93 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * ======================================================================
5
- * LICENSE: This file is subject to the terms and conditions defined in *
6
- * file 'license.txt', which is part of this source code package. *
7
- * ======================================================================
8
- */
9
-
10
- /**
11
- * Backend tools settings
12
- *
13
- * @package AAM
14
- * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15
- */
16
- class AAM_Backend_Feature_Settings_Tools extends AAM_Backend_Feature_Abstract {
17
-
18
- /**
19
- * @inheritdoc
20
- */
21
- public static function getTemplate() {
22
- return 'settings/tools.phtml';
23
- }
24
-
25
- /**
26
- *
27
- * @return type
28
- */
29
- public function export() {
30
- $exporter = new AAM_Core_Exporter(AAM_Core_Config::get(
31
- 'feature.export', array('system' => 'roles,utilities,configpress')
32
- ));
33
-
34
- return wp_json_encode(array(
35
- 'status' => 'success',
36
- 'content' => base64_encode(wp_json_encode($exporter->run()))
37
- ));
38
- }
39
-
40
- /**
41
- *
42
- * @return type
43
- */
44
- public function import() {
45
- $importer = new AAM_Core_Importer(filter_input(INPUT_POST, 'json'));
46
-
47
- return wp_json_encode($importer->run());
48
- }
49
-
50
- /**
51
- * Clear all AAM settings
52
- *
53
- * @global wpdb $wpdb
54
- *
55
- * @return string
56
- *
57
- * @access public
58
- */
59
- public function clear() {
60
- AAM_Core_API::clearSettings();
61
-
62
- return wp_json_encode(array('status' => 'success'));
63
- }
64
-
65
- /**
66
- *
67
- * @return type
68
- */
69
- public function clearCache() {
70
- AAM_Core_API::clearCache();
71
-
72
- return wp_json_encode(array('status' => 'success'));
73
- }
74
-
75
- /**
76
- * Register Contact/Hire feature
77
- *
78
- * @return void
79
- *
80
- * @access public
81
- */
82
- public static function register() {
83
- AAM_Backend_Feature::registerFeature((object) array(
84
- 'uid' => 'settings-tools',
85
- 'position' => 10,
86
- 'title' => __('Tools', AAM_KEY),
87
- 'capability' => 'aam_manage_settings',
88
- 'type' => 'settings',
89
- 'view' => __CLASS__
90
- ));
91
- }
92
-
93
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Application/Backend/Feature/Subject/Role.php CHANGED
@@ -25,7 +25,8 @@ class AAM_Backend_Feature_Subject_Role {
25
  * @access public
26
  */
27
  public function getTable() {
28
- if (current_user_can('aam_list_roles')) {
 
29
  //retrieve list of users
30
  $count = count_users();
31
  $stats = $count['avail_roles'];
25
  * @access public
26
  */
27
  public function getTable() {
28
+ // TODO: The aam_list_roles is legacy and can be removed in Oct 2021
29
+ if (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles')) {
30
  //retrieve list of users
31
  $count = count_users();
32
  $stats = $count['avail_roles'];
Application/Backend/Feature/Subject/User.php CHANGED
@@ -32,7 +32,8 @@ class AAM_Backend_Feature_Subject_User {
32
  'data' => array(),
33
  );
34
 
35
- if (current_user_can('list_users')) {
 
36
  //get total number of users
37
  $total = count_users();
38
  $result = $this->query();
32
  'data' => array(),
33
  );
34
 
35
+ // TODO: The list_users is legacy and can be removed in Oct 2021
36
+ if (current_user_can('aam_manage_users') || current_user_can('list_users')) {
37
  //get total number of users
38
  $total = count_users();
39
  $result = $this->query();
Application/Backend/Filter.php CHANGED
@@ -147,7 +147,7 @@ class AAM_Backend_Filter {
147
  $object = AAM::getUser()->getObject('post', $post->ID, $post);
148
 
149
  //filter edit menu
150
- if (!$this->isAllowed('backend.edit', $object)) {
151
  if (isset($actions['edit'])) {
152
  unset($actions['edit']);
153
  }
@@ -157,13 +157,13 @@ class AAM_Backend_Filter {
157
  }
158
 
159
  //filter delete menu
160
- if (!$this->isAllowed('backend.delete', $object)) {
161
  if (isset($actions['trash'])) { unset($actions['trash']); }
162
  if (isset($actions['delete'])) { unset($actions['delete']); }
163
  }
164
 
165
  //filter edit menu
166
- if (!$this->isAllowed('backend.publish', $object)) {
167
  if (isset($actions['inline hide-if-no-js'])) {
168
  unset($actions['inline hide-if-no-js']);
169
  }
@@ -172,26 +172,6 @@ class AAM_Backend_Filter {
172
  return $actions;
173
  }
174
 
175
- /**
176
- * Check if action is allowed
177
- *
178
- * This method will take in consideration also *_others action
179
- *
180
- * @param string $action
181
- * @param AAM_Core_Object_Post $object
182
- *
183
- * @return boolean
184
- *
185
- * @access protected
186
- */
187
- protected function isAllowed($action, $object) {
188
- $edit = $object->has($action);
189
- $others = $object->has("{$action}_others");
190
- $author = (intval($object->post_author) === get_current_user_id());
191
-
192
- return ($edit || ($others && !$author)) ? false : true;
193
- }
194
-
195
  /**
196
  * Override default category if defined
197
  *
147
  $object = AAM::getUser()->getObject('post', $post->ID, $post);
148
 
149
  //filter edit menu
150
+ if (!$object->allowed('backend.edit')) {
151
  if (isset($actions['edit'])) {
152
  unset($actions['edit']);
153
  }
157
  }
158
 
159
  //filter delete menu
160
+ if (!$object->allowed('backend.delete')) {
161
  if (isset($actions['trash'])) { unset($actions['trash']); }
162
  if (isset($actions['delete'])) { unset($actions['delete']); }
163
  }
164
 
165
  //filter edit menu
166
+ if (!$object->allowed('backend.publish')) {
167
  if (isset($actions['inline hide-if-no-js'])) {
168
  unset($actions['inline hide-if-no-js']);
169
  }
172
  return $actions;
173
  }
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  /**
176
  * Override default category if defined
177
  *
Application/Backend/Manager.php CHANGED
@@ -43,6 +43,7 @@ class AAM_Backend_Manager {
43
 
44
  //print required JS & CSS
45
  add_action('admin_print_scripts', array($this, 'printJavascript'));
 
46
  add_action('admin_print_styles', array($this, 'printStylesheet'));
47
 
48
  //map AAM UI specific capabilities
@@ -108,8 +109,8 @@ class AAM_Backend_Manager {
108
  add_action('admin_init', array($this, 'adminInit'));
109
 
110
  //admin toolbar
111
- if (filter_input(INPUT_GET, 'init') === 'toolbar') {
112
- add_action('wp_after_admin_bar_render', array($this, 'adminBar'));
113
  }
114
 
115
  //register login widget
@@ -132,6 +133,76 @@ class AAM_Backend_Manager {
132
  }
133
  }
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  /**
136
  *
137
  * @param type $caps
@@ -271,6 +342,12 @@ class AAM_Backend_Manager {
271
  echo AAM_Backend_View::getInstance()->renderAccessFrame();
272
  exit;
273
  }
 
 
 
 
 
 
274
  }
275
 
276
  /**
@@ -391,8 +468,9 @@ class AAM_Backend_Manager {
391
  *
392
  * @global type $wp_admin_bar
393
  */
394
- public function adminBar() {
395
  global $wp_admin_bar;
 
396
 
397
  $reflection = new ReflectionClass(get_class($wp_admin_bar));
398
 
@@ -401,7 +479,7 @@ class AAM_Backend_Manager {
401
 
402
  $nodes = $prop->getValue($wp_admin_bar);
403
 
404
- if (isset($nodes['root'])) {
405
  $cache = array();
406
  foreach($nodes['root']->children as $node) {
407
  $cache = array_merge($cache, $node->children);
@@ -413,9 +491,9 @@ class AAM_Backend_Manager {
413
  unset($cache[$i]);
414
  }
415
  }
416
-
417
- AAM_Core_API::updateOption('aam_toolbar_cache', array_values($cache));
418
  }
 
 
419
  }
420
 
421
  /**
@@ -533,7 +611,8 @@ class AAM_Backend_Manager {
533
  * @access public
534
  */
535
  public function userActions($actions, $user) {
536
- if ($this->renderExternalUIFeature('list_users')) {
 
537
  $url = admin_url('admin.php?page=aam&user=' . $user->ID);
538
 
539
  $actions['aam'] = '<a href="' . $url . '" target="_blank">';
@@ -575,6 +654,27 @@ class AAM_Backend_Manager {
575
  }
576
  }
577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  /**
579
  * Print plugin localization
580
  *
@@ -640,7 +740,7 @@ class AAM_Backend_Manager {
640
  * @access public
641
  */
642
  public function adminMenu() {
643
- if (AAM_Core_Console::count()) {
644
  $counter = '&nbsp;<span class="update-plugins">'
645
  . '<span class="plugin-count">' . AAM_Core_Console::count()
646
  . '</span></span>';
@@ -683,6 +783,9 @@ class AAM_Backend_Manager {
683
  public function renderContent() {
684
  check_ajax_referer('aam_ajax');
685
 
 
 
 
686
  if (AAM::getUser()->hasCapability('aam_manager')) {
687
  echo AAM_Backend_View::getInstance()->renderContent(
688
  AAM_Core_Request::post('uiType', 'main')
43
 
44
  //print required JS & CSS
45
  add_action('admin_print_scripts', array($this, 'printJavascript'));
46
+ add_action('admin_print_footer_scripts', array($this, 'printFooterJavascript'));
47
  add_action('admin_print_styles', array($this, 'printStylesheet'));
48
 
49
  //map AAM UI specific capabilities
109
  add_action('admin_init', array($this, 'adminInit'));
110
 
111
  //admin toolbar
112
+ if (AAM::isAAM()) {
113
+ add_action('wp_after_admin_bar_render', array($this, 'cacheAdminBar'));
114
  }
115
 
116
  //register login widget
133
  }
134
  }
135
 
136
+ /**
137
+ *
138
+ */
139
+ public function renderExportFields() {
140
+ ob_start();
141
+ require_once dirname(__FILE__) . '/phtml/system/export.phtml';
142
+ $content = ob_get_contents();
143
+ ob_end_clean();
144
+
145
+ echo $content;
146
+ }
147
+
148
+ /**
149
+ *
150
+ * @param type $args
151
+ * @return type
152
+ */
153
+ public function prepareExportArgs($args) {
154
+ if ($args['content'] === 'aam') {
155
+ $export = array();
156
+
157
+ foreach(AAM_Core_Request::get('export', array()) as $group => $settings) {
158
+ $export[$group] = implode(',', $settings);
159
+ }
160
+
161
+ $args['export'] = array_merge(
162
+ array('system' => 'roles,utilities,configpress'),
163
+ $export
164
+ );
165
+ }
166
+
167
+ return $args;
168
+ }
169
+
170
+ /**
171
+ *
172
+ * @param type $args
173
+ */
174
+ public function exportSettings($args) {
175
+ if ($args['content'] === 'aam') {
176
+ $filename = 'aam.export.' . date('Y-m-d') . '.json';
177
+ header('Content-Description: File Transfer');
178
+ header('Content-Disposition: attachment; filename=' . $filename);
179
+ header('Content-Type: application/json; charset=' . get_option('blog_charset'), true);
180
+ $exporter = new AAM_Core_Exporter($args['export']);
181
+ echo wp_json_encode($exporter->run());
182
+ die();
183
+ }
184
+ }
185
+
186
+ /**
187
+ *
188
+ */
189
+ protected function registerAAMImporter() {
190
+ register_importer(
191
+ 'aam',
192
+ 'AAM Access Settings',
193
+ 'Advanced Access Manager access settings and configurations',
194
+ array($this, 'renderImporer')
195
+ );
196
+ }
197
+
198
+ /**
199
+ *
200
+ */
201
+ public function renderImporer() {
202
+ $importer = new AAM_Core_Importer();
203
+ $importer->dispatch();
204
+ }
205
+
206
  /**
207
  *
208
  * @param type $caps
342
  echo AAM_Backend_View::getInstance()->renderAccessFrame();
343
  exit;
344
  }
345
+
346
+ // Import/Export feature
347
+ add_action('export_filters', array($this, 'renderExportFields'));
348
+ add_filter('export_args', array($this, 'prepareExportArgs'));
349
+ add_action('export_wp', array($this, 'exportSettings'));
350
+ $this->registerAAMImporter();
351
  }
352
 
353
  /**
468
  *
469
  * @global type $wp_admin_bar
470
  */
471
+ public function cacheAdminBar() {
472
  global $wp_admin_bar;
473
+ static $cache = null;
474
 
475
  $reflection = new ReflectionClass(get_class($wp_admin_bar));
476
 
479
 
480
  $nodes = $prop->getValue($wp_admin_bar);
481
 
482
+ if (isset($nodes['root']) && is_null($cache)) {
483
  $cache = array();
484
  foreach($nodes['root']->children as $node) {
485
  $cache = array_merge($cache, $node->children);
491
  unset($cache[$i]);
492
  }
493
  }
 
 
494
  }
495
+
496
+ return $cache;
497
  }
498
 
499
  /**
611
  * @access public
612
  */
613
  public function userActions($actions, $user) {
614
+ if ($this->renderExternalUIFeature('aam_manage_users')
615
+ || $this->renderExternalUIFeature('list_users')) {
616
  $url = admin_url('admin.php?page=aam&user=' . $user->ID);
617
 
618
  $actions['aam'] = '<a href="' . $url . '" target="_blank">';
654
  }
655
  }
656
 
657
+ /**
658
+ *
659
+ * @global type $menu
660
+ * @global type $submenu
661
+ */
662
+ public function printFooterJavascript() {
663
+ global $menu, $submenu;
664
+
665
+ if (AAM::isAAM()) {
666
+ $script = '<script type="text/javascript">';
667
+ $script .= 'var aamEnvData = ' . wp_json_encode(array(
668
+ 'menu' => base64_encode(json_encode($menu)),
669
+ 'submenu' => base64_encode(json_encode($submenu)),
670
+ 'toolbar' => base64_encode(json_encode($this->cacheAdminBar()))
671
+ )) ;
672
+ $script .= '</script>';
673
+
674
+ echo $script;
675
+ }
676
+ }
677
+
678
  /**
679
  * Print plugin localization
680
  *
740
  * @access public
741
  */
742
  public function adminMenu() {
743
+ if (AAM_Core_Console::count() && current_user_can('aam_show_notifications')) {
744
  $counter = '&nbsp;<span class="update-plugins">'
745
  . '<span class="plugin-count">' . AAM_Core_Console::count()
746
  . '</span></span>';
783
  public function renderContent() {
784
  check_ajax_referer('aam_ajax');
785
 
786
+ // flush any output buffer
787
+ ob_clean();
788
+
789
  if (AAM::getUser()->hasCapability('aam_manager')) {
790
  echo AAM_Backend_View::getInstance()->renderContent(
791
  AAM_Core_Request::post('uiType', 'main')
Application/Backend/Subject.php CHANGED
@@ -85,13 +85,20 @@ class AAM_Backend_Subject {
85
  * @access protected
86
  */
87
  protected function initDefaultSubject() {
88
- $user = intval(AAM_Core_Request::get('user'));
 
89
 
90
- if ($user && current_user_can('list_users')) {
91
- $this->initRequestedSubject(AAM_Core_Subject_User::UID, $user);
92
- } elseif (current_user_can('aam_list_roles')) {
93
  $roles = array_keys(get_editable_roles());
94
  $this->initRequestedSubject(AAM_Core_Subject_Role::UID, array_shift($roles));
 
 
 
 
 
 
 
95
  } elseif (current_user_can('aam_manage_visitors')) {
96
  $this->initRequestedSubject(AAM_Core_Subject_Visitor::UID, null);
97
  } elseif (current_user_can('aam_manage_default')) {
85
  * @access protected
86
  */
87
  protected function initDefaultSubject() {
88
+ // This cover the scenario when we directly go to user e.g. ?page=aam&user=38
89
+ $forceUser = AAM_Core_Request::get('user');
90
 
91
+ // TODO: The aam_list_roles is legacy and can be removed in Oct 2021
92
+ if (!$forceUser && (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles'))) {
 
93
  $roles = array_keys(get_editable_roles());
94
  $this->initRequestedSubject(AAM_Core_Subject_Role::UID, array_shift($roles));
95
+ // TODO: The list_users is legacy and can be removed in Oct 2021
96
+ } elseif (current_user_can('aam_manage_users') || current_user_can('list_users')) {
97
+ $this->initRequestedSubject(
98
+ AAM_Core_Subject_User::UID,
99
+ ($forceUser ? intval($forceUser) : get_current_user_id())
100
+ );
101
+ // TODO: The aam_list_roles is legacy and can be removed in Oct 2021
102
  } elseif (current_user_can('aam_manage_visitors')) {
103
  $this->initRequestedSubject(AAM_Core_Subject_Visitor::UID, null);
104
  } elseif (current_user_can('aam_manage_default')) {
Application/Backend/View.php CHANGED
@@ -48,12 +48,36 @@ class AAM_Backend_View {
48
  AAM_Backend_Feature_Settings_Core::register();
49
  AAM_Backend_Feature_Settings_Content::register();
50
  AAM_Backend_Feature_Settings_Security::register();
51
- AAM_Backend_Feature_Settings_Tools::register();
52
  AAM_Backend_Feature_Settings_ConfigPress::register();
53
 
54
  //feature registration hook
55
  do_action('aam-feature-registration-action');
56
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  /**
59
  * Run the Manager
@@ -242,6 +266,26 @@ class AAM_Backend_View {
242
  AAM_Core_API::updateOption(
243
  'aam-user-switch-' . $user->ID, get_current_user_id()
244
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  wp_clear_auth_cookie();
247
  wp_set_auth_cookie( $user->ID, true );
48
  AAM_Backend_Feature_Settings_Core::register();
49
  AAM_Backend_Feature_Settings_Content::register();
50
  AAM_Backend_Feature_Settings_Security::register();
 
51
  AAM_Backend_Feature_Settings_ConfigPress::register();
52
 
53
  //feature registration hook
54
  do_action('aam-feature-registration-action');
55
  }
56
+
57
+ /**
58
+ * Clear all AAM settings
59
+ *
60
+ * @global wpdb $wpdb
61
+ *
62
+ * @return string
63
+ *
64
+ * @access public
65
+ */
66
+ public function clearSettings() {
67
+ AAM_Core_API::clearSettings();
68
+
69
+ return wp_json_encode(array('status' => 'success'));
70
+ }
71
+
72
+ /**
73
+ *
74
+ * @return type
75
+ */
76
+ public function clearCache() {
77
+ AAM_Core_API::clearCache();
78
+
79
+ return wp_json_encode(array('status' => 'success'));
80
+ }
81
 
82
  /**
83
  * Run the Manager
266
  AAM_Core_API::updateOption(
267
  'aam-user-switch-' . $user->ID, get_current_user_id()
268
  );
269
+
270
+ // Making sure that user that we are switching too is not logged in
271
+ // already. Kinding by https://github.com/KenAer
272
+ $sessions = WP_Session_Tokens::get_instance($user->ID);
273
+ if (count($sessions->get_all()) > 1) {
274
+ $sessions->destroy_all();
275
+ }
276
+
277
+ // If there is jwt token in cookie, make sure it is deleted otherwise
278
+ // user technically will never be switched
279
+ if (AAM_Core_Request::cookie('aam-jwt')) {
280
+ setcookie(
281
+ 'aam-jwt',
282
+ '',
283
+ time() - YEAR_IN_SECONDS,
284
+ '/',
285
+ parse_url(get_bloginfo('url'), PHP_URL_HOST),
286
+ is_ssl()
287
+ );
288
+ }
289
 
290
  wp_clear_auth_cookie();
291
  wp_set_auth_cookie( $user->ID, true );
Application/Backend/phtml/extensions.phtml CHANGED
@@ -46,9 +46,13 @@
46
  </td>
47
  <td class="text-center">
48
  <?php if ($product['status'] == AAM_Extension_Repository::STATUS_INSTALLED) { ?>
49
- <a href="#" class="btn btn-sm btn-danger btn-block aam-deactivate-extension" data-product="<?php echo $product['id']; ?>"><i class="icon-attention-circled"></i> <?php echo __('Deactivate', AAM_KEY); ?></a><small><?php echo __('extension is active', AAM_KEY); ?></small>
 
 
 
 
50
  <?php } elseif ($product['status'] == AAM_Extension_Repository::STATUS_UPDATE) { ?>
51
- <a href="#" class="btn btn-sm btn-warning btn-block aam-update-extension" data-product="<?php echo $product['id']; ?>"><i class="icon-arrows-cw"></i> <?php echo __('Update', AAM_KEY); ?></a>
52
  <?php } elseif ($product['status'] == AAM_Extension_Repository::STATUS_INACTIVE) { ?>
53
  <a href="#" class="btn btn-sm btn-success btn-block aam-activate-extension" data-product="<?php echo $product['id']; ?>"><i class="icon-check"></i> <?php echo __('Activate', AAM_KEY); ?></a><small><?php echo __('extension is inactive', AAM_KEY); ?></small>
54
  <?php } else { ?>
46
  </td>
47
  <td class="text-center">
48
  <?php if ($product['status'] == AAM_Extension_Repository::STATUS_INSTALLED) { ?>
49
+ <?php if ($product['title'] === 'Complete Package') { ?>
50
+ <a href="#" class="btn btn-sm btn-success btn-block disabled"><i class="icon-check"></i> <?php echo __('Installed', AAM_KEY); ?></a>
51
+ <?php } else { ?>
52
+ <a href="#" class="btn btn-sm btn-danger btn-block aam-deactivate-extension" data-product="<?php echo $product['id']; ?>"><i class="icon-attention-circled"></i> <?php echo __('Deactivate', AAM_KEY); ?></a><small><?php echo __('extension is active', AAM_KEY); ?></small>
53
+ <?php } ?>
54
  <?php } elseif ($product['status'] == AAM_Extension_Repository::STATUS_UPDATE) { ?>
55
+ <a href="#" class="btn btn-sm btn-warning btn-block aam-update-extension<?php echo (empty($product['license']) ? ' disabled' : ''); ?>" data-product="<?php echo $product['id']; ?>"><i class="icon-arrows-cw"></i> <?php echo __('Update', AAM_KEY); ?></a><?php echo (empty($product['license']) ? '<small>' . __('license is missing', AAM_KEY) . '</small>' : ''); ?>
56
  <?php } elseif ($product['status'] == AAM_Extension_Repository::STATUS_INACTIVE) { ?>
57
  <a href="#" class="btn btn-sm btn-success btn-block aam-activate-extension" data-product="<?php echo $product['id']; ?>"><i class="icon-check"></i> <?php echo __('Activate', AAM_KEY); ?></a><small><?php echo __('extension is inactive', AAM_KEY); ?></small>
58
  <?php } else { ?>
Application/Backend/phtml/index.phtml CHANGED
@@ -71,6 +71,39 @@
71
  </div>
72
  </div>
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  <?php if (AAM_Extension_Repository::getInstance()->isWriteableDirectory() === false) { ?>
75
  <?php $relativePath = AAM_Extension_Repository::getInstance()->getBasedir(true); ?>
76
  <div class="metabox-holder extensions-metabox" id='extension-dir-warning' style="display:none;">
@@ -88,6 +121,7 @@
88
  </div>
89
  </div>
90
  </div>
 
91
  <div class="modal fade" id="extension-dir-issue-modal" tabindex="-1" role="dialog">
92
  <div class="modal-dialog" role="document">
93
  <div class="modal-content">
@@ -179,22 +213,24 @@
179
  <div class="inside" id="user-role-manager-inside">
180
  <div class="aam-postbox-inside">
181
  <ul class="nav nav-tabs" role="tablist">
182
- <?php if (current_user_can('aam_list_roles')) { ?>
183
- <li role="presentation" class="active text-center"><a href="#roles" aria-controls="roles" role="tab" data-toggle="tab"><i class="icon-users"></i><br/><?php echo __('Roles', AAM_KEY); ?></a></li>
 
184
  <?php } ?>
185
- <?php if (current_user_can('list_users')) { ?>
186
- <li role="presentation" class="text-center"><a href="#users" aria-controls="users" role="tab" data-toggle="tab"><i class="icon-user"></i><br/><?php echo __('Users', AAM_KEY); ?></a></li>
187
  <?php } ?>
188
  <?php if (current_user_can('aam_manage_visitors')) { ?>
189
- <li role="presentation" class="text-center"><a href="#visitor" aria-controls="visitor" role="tab" data-toggle="tab"><i class="icon-user-secret"></i><br/><?php echo __('Visitor', AAM_KEY); ?></a></li>
190
  <?php } ?>
191
  <?php if (current_user_can('aam_manage_default')) { ?>
192
- <li role="presentation" class="text-center"><a href="#default" aria-controls="default" role="tab" data-toggle="tab" class="text-danger"><i class="icon-asterisk"></i><br/><?php echo __('Default', AAM_KEY); ?></a></li>
193
  <?php } ?>
194
  </ul>
195
  <div class="tab-content">
196
- <?php if (current_user_can('aam_list_roles')) { ?>
197
- <div role="tabpanel" class="tab-pane active" id="roles">
 
198
  <table id="role-list" class="table table-striped table-bordered">
199
  <thead>
200
  <tr>
@@ -281,8 +317,8 @@
281
  </div>
282
  </div>
283
  <?php } ?>
284
- <?php if (current_user_can('list_users')) { ?>
285
- <div role="tabpanel" class="tab-pane" id="users">
286
  <table id="user-list" class="table table-striped table-bordered">
287
  <thead>
288
  <tr>
@@ -337,7 +373,7 @@
337
  </div>
338
  <?php } ?>
339
  <?php if (current_user_can('aam_manage_visitors')) { ?>
340
- <div role="tabpanel" class="tab-pane" id="visitor">
341
  <div class="visitor-message">
342
  <span class="aam-bordered"><?php echo __('Manage access to your website for visitors (any user that is not authenticated)', AAM_KEY); ?>.</span>
343
  <button class="btn btn-primary btn-block" id="manage-visitor"><i class="icon-cog"></i> <?php echo __('Manage Visitors', AAM_KEY); ?></button>
@@ -345,7 +381,7 @@
345
  </div>
346
  <?php } ?>
347
  <?php if (current_user_can('aam_manage_default')) { ?>
348
- <div role="tabpanel" class="tab-pane" id="default">
349
  <div class="visitor-message">
350
  <span class="aam-bordered"><?php echo __('Manage default access to your website resources for all users, roles and visitor. This includes Administrator role and your user', AAM_KEY); ?>.</span>
351
  <button class="btn btn-danger btn-block" id="manage-default"><i class="icon-cog"></i> <?php echo __('Manage Default Access', AAM_KEY); ?></button>
71
  </div>
72
  </div>
73
 
74
+ <div class="metabox-holder settings-metabox" style="display:none;">
75
+ <div class="postbox">
76
+ <div class="inside">
77
+ <div class="row">
78
+ <div class="col-xs-12 col-md-6">
79
+ <a href="#" class="btn btn-primary btn-block" id="clear-cache"><?php echo __('Clear AAM Cache', AAM_KEY); ?></a>
80
+ </div>
81
+ <div class="col-xs-12 col-md-6">
82
+ <a href="#clear-settings-modal" data-toggle="modal" class="btn btn-danger btn-block"><?php echo __('Reset AAM Settings', AAM_KEY); ?></a>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+
88
+ <div class="modal fade" id="clear-settings-modal" tabindex="-1" role="dialog">
89
+ <div class="modal-dialog modal-sm" role="document">
90
+ <div class="modal-content">
91
+ <div class="modal-header">
92
+ <button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">&times;</span></button>
93
+ <h4 class="modal-title"><?php echo __('Clear all settings', AAM_KEY); ?></h4>
94
+ </div>
95
+ <div class="modal-body">
96
+ <p class="text-center alert alert-danger text-larger"><?php echo __('All AAM settings will be removed.', AAM_KEY); ?></p>
97
+ </div>
98
+ <div class="modal-footer">
99
+ <button type="button" class="btn btn-danger" id="clear-settings"><?php echo __('Clear', AAM_KEY); ?></button>
100
+ <button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Cancel', AAM_KEY); ?></button>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
  <?php if (AAM_Extension_Repository::getInstance()->isWriteableDirectory() === false) { ?>
108
  <?php $relativePath = AAM_Extension_Repository::getInstance()->getBasedir(true); ?>
109
  <div class="metabox-holder extensions-metabox" id='extension-dir-warning' style="display:none;">
121
  </div>
122
  </div>
123
  </div>
124
+
125
  <div class="modal fade" id="extension-dir-issue-modal" tabindex="-1" role="dialog">
126
  <div class="modal-dialog" role="document">
127
  <div class="modal-content">
213
  <div class="inside" id="user-role-manager-inside">
214
  <div class="aam-postbox-inside">
215
  <ul class="nav nav-tabs" role="tablist">
216
+ <?php $active = 0; ?>
217
+ <?php if (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles')) { ?>
218
+ <li role="presentation" class="<?php echo (!$active++ ? 'active ' : ''); ?>text-center"><a href="#roles" aria-controls="roles" role="tab" data-toggle="tab"><i class="icon-users"></i><br/><?php echo __('Roles', AAM_KEY); ?></a></li>
219
  <?php } ?>
220
+ <?php if (current_user_can('aam_manage_users') || current_user_can('list_users')) { ?>
221
+ <li role="presentation" class="<?php echo (!$active++ ? 'active ' : ''); ?>text-center"><a href="#users" aria-controls="users" role="tab" data-toggle="tab"><i class="icon-user"></i><br/><?php echo __('Users', AAM_KEY); ?></a></li>
222
  <?php } ?>
223
  <?php if (current_user_can('aam_manage_visitors')) { ?>
224
+ <li role="presentation" class="<?php echo (!$active++ ? 'active ' : ''); ?>text-center"><a href="#visitor" aria-controls="visitor" role="tab" data-toggle="tab"><i class="icon-user-secret"></i><br/><?php echo __('Visitor', AAM_KEY); ?></a></li>
225
  <?php } ?>
226
  <?php if (current_user_can('aam_manage_default')) { ?>
227
+ <li role="presentation" class="<?php echo (!$active++ ? 'active ' : ''); ?>text-center"><a href="#default" aria-controls="default" role="tab" data-toggle="tab" class="text-danger"><i class="icon-asterisk"></i><br/><?php echo __('Default', AAM_KEY); ?></a></li>
228
  <?php } ?>
229
  </ul>
230
  <div class="tab-content">
231
+ <?php $active = 0; ?>
232
+ <?php if (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles')) { ?>
233
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="roles">
234
  <table id="role-list" class="table table-striped table-bordered">
235
  <thead>
236
  <tr>
317
  </div>
318
  </div>
319
  <?php } ?>
320
+ <?php if (current_user_can('aam_manage_users') || current_user_can('list_users')) { ?>
321
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="users">
322
  <table id="user-list" class="table table-striped table-bordered">
323
  <thead>
324
  <tr>
373
  </div>
374
  <?php } ?>
375
  <?php if (current_user_can('aam_manage_visitors')) { ?>
376
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="visitor">
377
  <div class="visitor-message">
378
  <span class="aam-bordered"><?php echo __('Manage access to your website for visitors (any user that is not authenticated)', AAM_KEY); ?>.</span>
379
  <button class="btn btn-primary btn-block" id="manage-visitor"><i class="icon-cog"></i> <?php echo __('Manage Visitors', AAM_KEY); ?></button>
381
  </div>
382
  <?php } ?>
383
  <?php if (current_user_can('aam_manage_default')) { ?>
384
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="default">
385
  <div class="visitor-message">
386
  <span class="aam-bordered"><?php echo __('Manage default access to your website resources for all users, roles and visitor. This includes Administrator role and your user', AAM_KEY); ?>.</span>
387
  <button class="btn btn-danger btn-block" id="manage-default"><i class="icon-cog"></i> <?php echo __('Manage Default Access', AAM_KEY); ?></button>
Application/Backend/phtml/main/menu.phtml CHANGED
@@ -15,7 +15,7 @@
15
  </div>
16
  </div>
17
  </div>
18
-
19
  <div class="panel-group" id="admin-menu" role="tablist" aria-multiselectable="true">
20
  <?php
21
  $first = false;
15
  </div>
16
  </div>
17
  </div>
18
+
19
  <div class="panel-group" id="admin-menu" role="tablist" aria-multiselectable="true">
20
  <?php
21
  $first = false;
Application/Backend/phtml/main/toolbar.phtml CHANGED
@@ -8,10 +8,6 @@
8
  </div>
9
  </div>
10
 
11
- <div class="aam-feature-top-actions text-right">
12
- <a href="#" class="btn btn-xs btn-primary" id="refresh-toolbar-list"><i class="icon-arrows-cw"></i> <?php echo __('Refresh', AAM_KEY); ?></a>
13
- </div>
14
-
15
  <div class="row">
16
  <div class="col-xs-12">
17
  <div class="aam-overwrite" id="aam-toolbar-overwrite" style="display: <?php echo ($this->isOverwritten() ? 'block' : 'none'); ?>">
@@ -27,8 +23,6 @@
27
  $toolbar = $this->getToolbar();
28
  $object = AAM_Backend_Subject::getInstance()->getObject('toolbar');
29
 
30
- //echo '<pre>'; print_r($toolbar); echo '</pre>';
31
-
32
  if (!empty($toolbar)) { ?>
33
  <?php foreach ($toolbar as $i => $branch) { ?>
34
  <div class="panel panel-default">
8
  </div>
9
  </div>
10
 
 
 
 
 
11
  <div class="row">
12
  <div class="col-xs-12">
13
  <div class="aam-overwrite" id="aam-toolbar-overwrite" style="display: <?php echo ($this->isOverwritten() ? 'block' : 'none'); ?>">
23
  $toolbar = $this->getToolbar();
24
  $object = AAM_Backend_Subject::getInstance()->getObject('toolbar');
25
 
 
 
26
  if (!empty($toolbar)) { ?>
27
  <?php foreach ($toolbar as $i => $branch) { ?>
28
  <div class="panel panel-default">
Application/Backend/phtml/metabox/metabox-content.phtml CHANGED
@@ -22,22 +22,24 @@
22
  <div class="panel panel-default" style="border-radius:0;">
23
  <div class="panel-body">
24
  <ul class="nav nav-tabs" role="tablist">
25
- <?php if (current_user_can('aam_list_roles')) { ?>
26
- <li role="presentation" class="active"><a href="#roles" aria-controls="roles" role="tab" data-toggle="tab"><i class="icon-users" data-toggle="tooltip" data-placement="top" title="Roles"></i></a></li>
 
27
  <?php } ?>
28
- <?php if (current_user_can('list_users')) { ?>
29
- <li role="presentation"><a href="#users" aria-controls="users" role="tab" data-toggle="tab"><i class="icon-user" data-toggle="tooltip" data-placement="top" title="Users"></i></a></li>
30
  <?php } ?>
31
  <?php if (current_user_can('aam_manage_visitors')) { ?>
32
- <li role="presentation"><a href="#visitor" aria-controls="visitor" role="tab" data-toggle="tab"><i class="icon-user-secret" data-toggle="tooltip" data-placement="top" title="Visitor"></i></a></li>
33
  <?php } ?>
34
  <?php if (current_user_can('aam_manage_default')) { ?>
35
- <li role="presentation"><a href="#default" aria-controls="default" role="tab" data-toggle="tab" class="text-danger"><i class="icon-asterisk" data-toggle="tooltip" data-placement="top" title="Default"></i></a></li>
36
  <?php } ?>
37
  </ul>
38
  <div class="tab-content">
39
- <?php if (current_user_can('aam_list_roles')) { ?>
40
- <div role="tabpanel" class="tab-pane active" id="roles">
 
41
  <table id="role-list" class="table table-striped table-bordered">
42
  <thead>
43
  <tr>
@@ -52,8 +54,8 @@
52
  </table>
53
  </div>
54
  <?php } ?>
55
- <?php if (current_user_can('list_users')) { ?>
56
- <div role="tabpanel" class="tab-pane" id="users">
57
  <table id="user-list" class="table table-striped table-bordered">
58
  <thead>
59
  <tr>
@@ -69,7 +71,7 @@
69
  </div>
70
  <?php } ?>
71
  <?php if (current_user_can('aam_manage_visitors')) { ?>
72
- <div role="tabpanel" class="tab-pane" id="visitor">
73
  <div class="visitor-message">
74
  <span class="aam-bordered"><?php echo sprintf(__('Manage access to %s for visitors (any user that is not authenticated)', AAM_KEY), '<b>' . ($object->type == 'post' ? $object->post->post_title : $object->term->name) . '</b>'); ?>.</span>
75
  <button class="btn btn-primary btn-block" id="manage-visitor"><i class="icon-cog"></i> <?php echo __('Manage Visitors', AAM_KEY); ?></button>
@@ -77,7 +79,7 @@
77
  </div>
78
  <?php } ?>
79
  <?php if (current_user_can('aam_manage_default')) { ?>
80
- <div role="tabpanel" class="tab-pane" id="default">
81
  <div class="visitor-message">
82
  <span class="aam-bordered"><?php echo sprintf(__('Manage default access to %s for all users, roles and visitor. This includes Administrator role and yourself', AAM_KEY), '<b>' . ($object->type == 'post' ? $object->post->post_title : $object->term->name) . '</b>'); ?>.</span>
83
  <?php if (defined('AAM_PLUS_PACKAGE')) { ?>
22
  <div class="panel panel-default" style="border-radius:0;">
23
  <div class="panel-body">
24
  <ul class="nav nav-tabs" role="tablist">
25
+ <?php $active = 0; ?>
26
+ <?php if (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles')) { ?>
27
+ <li role="presentation"<?php echo (!$active++ ? ' class="active"' : ''); ?>><a href="#roles" aria-controls="roles" role="tab" data-toggle="tab"><i class="icon-users" data-toggle="tooltip" data-placement="top" title="Roles"></i></a></li>
28
  <?php } ?>
29
+ <?php if (current_user_can('aam_manage_users')) { ?>
30
+ <li role="presentation"<?php echo (!$active++ ? ' class="active"' : ''); ?>><a href="#users" aria-controls="users" role="tab" data-toggle="tab"><i class="icon-user" data-toggle="tooltip" data-placement="top" title="Users"></i></a></li>
31
  <?php } ?>
32
  <?php if (current_user_can('aam_manage_visitors')) { ?>
33
+ <li role="presentation"<?php echo (!$active++ ? ' class="active"' : ''); ?>><a href="#visitor" aria-controls="visitor" role="tab" data-toggle="tab"><i class="icon-user-secret" data-toggle="tooltip" data-placement="top" title="Visitor"></i></a></li>
34
  <?php } ?>
35
  <?php if (current_user_can('aam_manage_default')) { ?>
36
+ <li role="presentation"<?php echo (!$active++ ? ' class="active"' : ''); ?>><a href="#default" aria-controls="default" role="tab" data-toggle="tab" class="text-danger"><i class="icon-asterisk" data-toggle="tooltip" data-placement="top" title="Default"></i></a></li>
37
  <?php } ?>
38
  </ul>
39
  <div class="tab-content">
40
+ <?php $active = 0; ?>
41
+ <?php if (current_user_can('aam_manage_roles') || current_user_can('aam_list_roles')) { ?>
42
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="roles">
43
  <table id="role-list" class="table table-striped table-bordered">
44
  <thead>
45
  <tr>
54
  </table>
55
  </div>
56
  <?php } ?>
57
+ <?php if (current_user_can('aam_manage_users') || current_user_can('list_users')) { ?>
58
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="users">
59
  <table id="user-list" class="table table-striped table-bordered">
60
  <thead>
61
  <tr>
71
  </div>
72
  <?php } ?>
73
  <?php if (current_user_can('aam_manage_visitors')) { ?>
74
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="visitor">
75
  <div class="visitor-message">
76
  <span class="aam-bordered"><?php echo sprintf(__('Manage access to %s for visitors (any user that is not authenticated)', AAM_KEY), '<b>' . ($object->type == 'post' ? $object->post->post_title : $object->term->name) . '</b>'); ?>.</span>
77
  <button class="btn btn-primary btn-block" id="manage-visitor"><i class="icon-cog"></i> <?php echo __('Manage Visitors', AAM_KEY); ?></button>
79
  </div>
80
  <?php } ?>
81
  <?php if (current_user_can('aam_manage_default')) { ?>
82
+ <div role="tabpanel" class="tab-pane<?php echo (!$active++ ? ' active' : ''); ?>" id="default">
83
  <div class="visitor-message">
84
  <span class="aam-bordered"><?php echo sprintf(__('Manage default access to %s for all users, roles and visitor. This includes Administrator role and yourself', AAM_KEY), '<b>' . ($object->type == 'post' ? $object->post->post_title : $object->term->name) . '</b>'); ?>.</span>
85
  <?php if (defined('AAM_PLUS_PACKAGE')) { ?>
Application/Backend/phtml/partial/post-access-form.phtml CHANGED
@@ -20,16 +20,20 @@
20
  <tbody>
21
  <?php foreach ($frontendOptions as $option => $data) { ?>
22
  <tr>
 
23
  <td width="90%">
24
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
25
  <?php if (!empty($data['sub'])) { ?>
26
- <small><?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b> <a href="#<?php echo $data['modal']; ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>"><?php echo __('change', AAM_KEY); ?></a></small>
 
 
 
27
  <?php } ?>
28
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
29
  </td>
30
  <td>
31
  <div class="aam-row-actions">
32
- <i class="aam-row-action text-muted icon-check-empty" data-property="frontend.<?php echo $option; ?>"></i>
33
  </div>
34
  </td>
35
  </tr>
@@ -56,16 +60,20 @@
56
  <tbody>
57
  <?php foreach ($backendOptions as $option => $data) { ?>
58
  <tr>
 
59
  <td width="90%">
60
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
61
  <?php if (!empty($data['sub'])) { ?>
62
- <small><?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b> <a href="#modal-<?php echo str_replace('.', '-', $data['option']); ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>"><?php echo __('change', AAM_KEY); ?></a></small>
 
 
 
63
  <?php } ?>
64
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
65
  </td>
66
  <td>
67
  <div class="aam-row-actions">
68
- <i class="aam-row-action text-muted icon-check-empty" data-property="backend.<?php echo $option; ?>"></i>
69
  </div>
70
  </td>
71
  </tr>
@@ -92,19 +100,20 @@
92
  <tbody>
93
  <?php foreach ($apiOptions as $option => $data) { ?>
94
  <tr>
 
95
  <td width="90%">
96
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
97
  <?php if (!empty($data['sub'])) { ?>
98
- <small>
99
  <?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b>
100
- <a href="#<?php echo $data['modal']; ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>"><?php echo __('change', AAM_KEY); ?></a>
101
  </small>
102
  <?php } ?>
103
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
104
  </td>
105
  <td>
106
  <div class="aam-row-actions">
107
- <i class="aam-row-action text-muted icon-check-empty" data-property="api.<?php echo $option; ?>"></i>
108
  </div>
109
  </td>
110
  </tr>
20
  <tbody>
21
  <?php foreach ($frontendOptions as $option => $data) { ?>
22
  <tr>
23
+ <?php $id = uniqid('aam'); ?>
24
  <td width="90%">
25
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
26
  <?php if (!empty($data['sub'])) { ?>
27
+ <small class="aam-small-highlighted">
28
+ <?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b>
29
+ <a href="#<?php echo $data['modal']; ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>" id="<?php echo $id; ?>"><?php echo __('change', AAM_KEY); ?></a>
30
+ </small>
31
  <?php } ?>
32
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
33
  </td>
34
  <td>
35
  <div class="aam-row-actions">
36
+ <i class="aam-row-action text-muted icon-check-empty" data-property="frontend.<?php echo $option; ?>" <?php echo (!empty($data['sub']) ? 'data-trigger="' . $id . '"' : ''); ?>></i>
37
  </div>
38
  </td>
39
  </tr>
60
  <tbody>
61
  <?php foreach ($backendOptions as $option => $data) { ?>
62
  <tr>
63
+ <?php $id = uniqid('aam'); ?>
64
  <td width="90%">
65
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
66
  <?php if (!empty($data['sub'])) { ?>
67
+ <small class="aam-small-highlighted">
68
+ <?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b>
69
+ <a href="#modal-<?php echo str_replace('.', '-', $data['option']); ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>" id="<?php echo $id; ?>"><?php echo __('change', AAM_KEY); ?></a>
70
+ </small>
71
  <?php } ?>
72
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
73
  </td>
74
  <td>
75
  <div class="aam-row-actions">
76
+ <i class="aam-row-action text-muted icon-check-empty" data-property="backend.<?php echo $option; ?>" <?php echo (!empty($data['sub']) ? 'data-trigger="' . $id . '"' : ''); ?>></i>
77
  </div>
78
  </td>
79
  </tr>
100
  <tbody>
101
  <?php foreach ($apiOptions as $option => $data) { ?>
102
  <tr>
103
+ <?php $id = uniqid('aam'); ?>
104
  <td width="90%">
105
  <strong class="aam-block aam-highlight text-uppercase"><?php echo $data['title']; ?></strong>
106
  <?php if (!empty($data['sub'])) { ?>
107
+ <small class="aam-small-highlighted">
108
  <?php echo $data['sub']; ?>: <b id="<?php echo $data['preview']; ?>" data-ref="<?php echo $data['option']; ?>" class="option-preview">...</b>
109
+ <a href="#<?php echo $data['modal']; ?>" data-toggle="modal" class="advanced-post-option" data-ref="<?php echo $data['option']; ?>" data-preview="#<?php echo $data['preview']; ?>" id="<?php echo $id; ?>"><?php echo __('change', AAM_KEY); ?></a>
110
  </small>
111
  <?php } ?>
112
  <p class="aam-hint" data-dynamic-post-label="<?php echo $data['descr']; ?>"></p>
113
  </td>
114
  <td>
115
  <div class="aam-row-actions">
116
+ <i class="aam-row-action text-muted icon-check-empty" data-property="api.<?php echo $option; ?>" <?php echo (!empty($data['sub']) ? 'data-trigger="' . $id . '"' : ''); ?>></i>
117
  </div>
118
  </td>
119
  </tr>
Application/Backend/phtml/settings/tools.phtml DELETED
@@ -1,74 +0,0 @@
1
- <?php if (defined('AAM_KEY')) { ?>
2
- <div class="aam-feature settings" id="settings-tools-content">
3
- <div role="tabpanel" class="tab-pane" id="utility-tools">
4
- <table class="table table-striped table-bordered">
5
- <tbody>
6
- <tr>
7
- <td>
8
- <span class='aam-setting-title'><?php echo __('Export AAM Settings', AAM_KEY); ?></span>
9
- <p class="aam-setting-description">
10
- <?php echo sprintf(__('Export selected AAM settings to the file. For more information about this feature check %sHow to export and import AAM settings%s article.', AAM_KEY), '<a href="https://aamplugin.com/help/how-to-export-and-import-aam-settings" target="_blank">', '</a>'); ?>
11
- </p>
12
- </td>
13
- <td>
14
- <a href="#" class="btn btn-success btn-block" id="export-aam">Export</a>
15
- </td>
16
- </tr>
17
- <tr>
18
- <td>
19
- <span class='aam-setting-title'><?php echo __('Import AAM Settings', AAM_KEY); ?></span>
20
- <p class="aam-setting-description">
21
- <?php echo __('Import AAM settings from the file.', AAM_KEY); ?>
22
- </p>
23
- </td>
24
- <td>
25
- <div class="hidden"><input type="file" id="aam-import-file" /></div>
26
- <a href="#" class="btn btn-warning btn-block" id="import-aam">Import</a>
27
- </td>
28
- </tr>
29
- <tr>
30
- <td>
31
- <span class='aam-setting-title'><?php echo __('Clear Cache', AAM_KEY); ?></span>
32
- <p class="aam-setting-description">
33
- <?php echo __('Clear all AAM cache.', AAM_KEY); ?>
34
- </p>
35
- </td>
36
- <td>
37
- <a href="#" class="btn btn-primary btn-block" id="clear-cache">Clear</a>
38
- </td>
39
- </tr>
40
- <tr>
41
- <td>
42
- <span class='aam-setting-title'><?php echo __('Clear All Settings', AAM_KEY); ?></span>
43
- <p class="aam-setting-description">
44
- <?php echo __('Remove all the settings related to AAM from the database.', AAM_KEY); ?>
45
- </p>
46
- </td>
47
- <td>
48
- <a href="#clear-settings-modal" data-toggle="modal" class="btn btn-danger btn-block">Clear</a>
49
- </td>
50
- </tr>
51
- </tbody>
52
- </table>
53
- </div>
54
-
55
- <div class="modal fade" id="clear-settings-modal" tabindex="-1" role="dialog">
56
- <div class="modal-dialog modal-sm" role="document">
57
- <div class="modal-content">
58
- <div class="modal-header">
59
- <button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">&times;</span></button>
60
- <h4 class="modal-title"><?php echo __('Clear all settings', AAM_KEY); ?></h4>
61
- </div>
62
- <div class="modal-body">
63
- <p class="text-center alert alert-danger text-larger"><?php echo __('All AAM settings will be removed.', AAM_KEY); ?></p>
64
- </div>
65
- <div class="modal-footer">
66
- <button type="button" class="btn btn-danger" id="clear-settings"><?php echo __('Clear', AAM_KEY); ?></button>
67
- <button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Cancel', AAM_KEY); ?></button>
68
- </div>
69
- </div>
70
- </div>
71
- </div>
72
- </div>
73
- <?php
74
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Application/Backend/phtml/system/export.phtml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <fieldset>
2
+ <p><label><input type="radio" name="content" value="aam" /> <?php _e('AAM Settings'); ?></label></p>
3
+ <ul id="aam-filters" class="export-filters">
4
+ <li>
5
+ <label><span class="label-responsive" style="font-weight: 500;"><?php _e('System Settings:'); ?></span></label><br/>
6
+ <ul style="margin: 5px 0 0 15px;">
7
+ <li><input type="checkbox" name="export[system][]" value="roles" /> Roles &amp; Capabilities</li>
8
+ <li><input type="checkbox" name="export[system][]" value="utilities" /> AAM Settings</li>
9
+ <li><input type="checkbox" name="export[system][]" value="configpress" /> ConfigPress</li>
10
+ </ul>
11
+ </li>
12
+ <li>
13
+ <label><span class="label-responsive" style="font-weight: 500;"><?php _e('Role Settings:'); ?></span></label><br/>
14
+ <ul style="margin: 5px 0 0 15px;">
15
+ <li><input type="checkbox" name="export[roles][]" value="menu" /> Backend Menu</li>
16
+ <li><input type="checkbox" name="export[roles][]" value="toolbar" /> Top Admin Toolbar</li>
17
+ <li><input type="checkbox" name="export[roles][]" value="metabox" /> Metaboxes &amp; Widgets</li>
18
+ <li><input type="checkbox" name="export[roles][]" value="post" /> Posts &amp; Terms</li>
19
+ <li><input type="checkbox" name="export[roles][]" value="redirect" /> Redirects</li>
20
+ <li><input type="checkbox" name="export[roles][]" value="route" /> API Routes</li>
21
+ </ul>
22
+ </li>
23
+ <li>
24
+ <label><span class="label-responsive" style="font-weight: 500;"><?php _e('User Settings:'); ?></span></label><br/>
25
+ <ul style="margin: 5px 0 0 15px;">
26
+ <li><input type="checkbox" name="export[users][]" value="menu" /> Backend Menu</li>
27
+ <li><input type="checkbox" name="export[users][]" value="toolbar" /> Top Admin Toolbar</li>
28
+ <li><input type="checkbox" name="export[users][]" value="metabox" /> Metaboxes &amp; Widgets</li>
29
+ <li><input type="checkbox" name="export[users][]" value="capability" /> Capabilities</li>
30
+ <li><input type="checkbox" name="export[users][]" value="post" /> Posts &amp; Terms</li>
31
+ <li><input type="checkbox" name="export[users][]" value="redirect" /> Redirects</li>
32
+ <li><input type="checkbox" name="export[users][]" value="route" /> API Routes</li>
33
+ </ul>
34
+ </li>
35
+ <li>
36
+ <label><span class="label-responsive" style="font-weight: 500;"><?php _e('Visitor Settings:'); ?></span></label><br/>
37
+ <ul style="margin: 5px 0 0 15px;">
38
+ <li><input type="checkbox" name="export[visitor][]" value="metabox" /> Frontend Widgets</li>
39
+ <li><input type="checkbox" name="export[visitor][]" value="post" /> Posts &amp; Terms</li>
40
+ <li><input type="checkbox" name="export[visitor][]" value="redirect" /> Redirects</li>
41
+ <li><input type="checkbox" name="export[visitor][]" value="route" /> API Routes</li>
42
+ </ul>
43
+ </li>
44
+ <li>
45
+ <label><span class="label-responsive" style="font-weight: 500;"><?php _e('Default Settings:'); ?></span></label><br/>
46
+ <ul style="margin: 5px 0 0 15px;">
47
+ <li><input type="checkbox" name="export[default][]" value="menu" /> Backend Menu</li>
48
+ <li><input type="checkbox" name="export[default][]" value="toolbar" /> Top Admin Toolbar</li>
49
+ <li><input type="checkbox" name="export[default][]" value="metabox" /> Metaboxes &amp; Widgets</li>
50
+ <li><input type="checkbox" name="export[default][]" value="post" /> Posts &amp; Terms</li>
51
+ <li><input type="checkbox" name="export[default][]" value="redirect" /> Redirects</li>
52
+ <li><input type="checkbox" name="export[default][]" value="route" /> API Routes</li>
53
+ </ul>
54
+ </li>
55
+ </ul>
56
+ </fieldset>
57
+ <script type="text/javascript">
58
+ jQuery(document).ready(function($){
59
+ var form = $('#export-filters');
60
+
61
+ form.find('input:radio').change(function() {
62
+ if ($(this).val() === 'aam') {
63
+ $('#aam-filters').slideDown();
64
+ }
65
+ });
66
+ });
67
+ </script>
Application/Core/Exporter.php CHANGED
@@ -69,7 +69,7 @@ class AAM_Core_Exporter {
69
  call_user_func(array($this, $method), explode(',', $features));
70
  } else {
71
  $this->output = apply_filters(
72
- 'aam-export-filter', $this->output, $backet, $this->config
73
  );
74
  }
75
  }
@@ -87,22 +87,22 @@ class AAM_Core_Exporter {
87
 
88
  foreach($features as $feature) {
89
  if ($feature === 'roles') {
90
- $this->add('_user_roles', base64_encode(json_encode(
 
91
  AAM_Core_API::getOption(
92
  $wpdb->get_blog_prefix($this->blog) . 'user_roles',
93
  array(),
94
  $this->blog
95
  )
96
- )));
97
- } elseif ($feature === 'utilities') {
98
  $this->add(
99
  AAM_Core_Config::OPTION,
100
- json_encode(AAM_Core_API::getOption(AAM_Core_Config::OPTION)
101
- ));
102
  } elseif ($feature === 'configpress') {
103
  $this->add(
104
- 'aam-configpress',
105
- base64_encode(AAM_Core_ConfigPress::getInstance()->read())
106
  );
107
  } else {
108
  do_action('aam-export-action', 'system', $feature, $this);
@@ -118,10 +118,14 @@ class AAM_Core_Exporter {
118
  foreach($features as $feature) {
119
  if ($feature === 'menu') {
120
  $this->pushData('options', '/^aam_menu_role/');
 
 
 
 
121
  } elseif ($feature === 'metabox') {
122
  $this->pushData('options', '/^aam_metabox_role/');
123
  } elseif ($feature === 'post') {
124
- $this->pushData('options', '/^aam_type_post_role/');
125
  $this->pushData('options', '/^aam_term_[\d]+\|.+_role/');
126
  $this->pushData('postmeta', '/^aam-post-access-role/');
127
  } elseif ($feature === 'redirect') {
@@ -142,11 +146,15 @@ class AAM_Core_Exporter {
142
  foreach($features as $feature) {
143
  if ($feature === 'menu') {
144
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_menu/');
 
 
 
 
145
  } elseif ($feature === 'metabox') {
146
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_metabox/');
147
  } elseif ($feature === 'post') {
148
- $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_type_post/');
149
- $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_term_[\d]+\|/');
150
  $this->pushData('postmeta', '/^aam-post-access-user/');
151
  } elseif ($feature === 'redirect') {
152
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_redirect/');
@@ -167,11 +175,13 @@ class AAM_Core_Exporter {
167
  if ($feature === 'metabox') {
168
  $this->pushData('options', '/^aam_visitor_metabox/');
169
  } elseif ($feature === 'post') {
170
- $this->pushData('options', '/^aam_visitor_type_post/');
171
- $this->pushData('options', '/^aam_visitor_term_/');
172
  $this->pushData('postmeta', '/^aam-post-access-visitor/');
173
  } elseif ($feature === 'redirect') {
174
  $this->pushData('options', '/^aam_visitor_redirect/');
 
 
175
  }
176
  }
177
  }
@@ -184,10 +194,14 @@ class AAM_Core_Exporter {
184
  foreach($features as $feature) {
185
  if ($feature === 'menu') {
186
  $this->pushData('options', '/^aam_menu_default/');
187
- } elseif ($feature == 'metabox') {
188
  $this->pushData('options', '/^aam_metabox_default/');
 
 
 
 
189
  } elseif ($feature === 'post') {
190
- $this->pushData('options', '/^aam_type_post_default/');
191
  $this->pushData('options', '/^aam_term_[\d]+\|.+_default/');
192
  $this->pushData('postmeta', '/^aam-post-access-default/');
193
  } elseif ($feature === 'redirect') {
@@ -220,7 +234,7 @@ class AAM_Core_Exporter {
220
  if (preg_match($regexp, $option->option_name)) {
221
  $this->add(
222
  $this->stripPrefix($option->option_name),
223
- $option->option_value,
224
  '_' . $group,
225
  $id
226
  );
@@ -229,7 +243,7 @@ class AAM_Core_Exporter {
229
  if (preg_match($regexp, $option->meta_key)) {
230
  $this->add(
231
  $this->stripPrefix($option->meta_key),
232
- $option->meta_value,
233
  '_' . $group,
234
  $id
235
  );
@@ -258,10 +272,12 @@ class AAM_Core_Exporter {
258
  * @param type $group
259
  */
260
  public function add($key, $value, $group = '_options', $id = null) {
 
 
261
  if (is_null($id)) {
262
- $this->output['dataset'][$group][$key] = $value;
263
  } else {
264
- $this->output['dataset'][$group][$id][$key] = $value;
265
  }
266
  }
267
 
@@ -274,6 +290,10 @@ class AAM_Core_Exporter {
274
  global $wpdb;
275
 
276
  if (empty($this->cache)) {
 
 
 
 
277
  $query = "SELECT option_name, option_value FROM {$wpdb->options} ";
278
  $query .= "WHERE option_name LIKE 'aam%'";
279
 
@@ -288,6 +308,10 @@ class AAM_Core_Exporter {
288
  $query .= "WHERE meta_key LIKE 'aam%'";
289
 
290
  $this->cache['postmeta'] = $wpdb->get_results($query);
 
 
 
 
291
  }
292
 
293
  return $this->cache;
69
  call_user_func(array($this, $method), explode(',', $features));
70
  } else {
71
  $this->output = apply_filters(
72
+ 'aam-export-filter', $this->output, $backet, $this->config
73
  );
74
  }
75
  }
87
 
88
  foreach($features as $feature) {
89
  if ($feature === 'roles') {
90
+ $this->add(
91
+ '_user_roles',
92
  AAM_Core_API::getOption(
93
  $wpdb->get_blog_prefix($this->blog) . 'user_roles',
94
  array(),
95
  $this->blog
96
  )
97
+ );
98
+ } elseif (in_array($feature, array('utilities', 'settings'), true)) {
99
  $this->add(
100
  AAM_Core_Config::OPTION,
101
+ AAM_Core_API::getOption(AAM_Core_Config::OPTION, '', 'site')
102
+ );
103
  } elseif ($feature === 'configpress') {
104
  $this->add(
105
+ 'aam-configpress', AAM_Core_ConfigPress::getInstance()->read()
 
106
  );
107
  } else {
108
  do_action('aam-export-action', 'system', $feature, $this);
118
  foreach($features as $feature) {
119
  if ($feature === 'menu') {
120
  $this->pushData('options', '/^aam_menu_role/');
121
+ } elseif ($feature === 'toolbar') {
122
+ $this->pushData('options', '/^aam_toolbar_role/');
123
+ } elseif ($feature === 'route') {
124
+ $this->pushData('options', '/^aam_route_role/');
125
  } elseif ($feature === 'metabox') {
126
  $this->pushData('options', '/^aam_metabox_role/');
127
  } elseif ($feature === 'post') {
128
+ $this->pushData('options', '/^aam_type_[\w_\-]+_role/');
129
  $this->pushData('options', '/^aam_term_[\d]+\|.+_role/');
130
  $this->pushData('postmeta', '/^aam-post-access-role/');
131
  } elseif ($feature === 'redirect') {
146
  foreach($features as $feature) {
147
  if ($feature === 'menu') {
148
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_menu/');
149
+ } elseif ($feature === 'toolbar') {
150
+ $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_toolbar/');
151
+ } elseif ($feature === 'route') {
152
+ $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_route/');
153
  } elseif ($feature === 'metabox') {
154
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_metabox/');
155
  } elseif ($feature === 'post') {
156
+ $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_type/');
157
+ $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_term/');
158
  $this->pushData('postmeta', '/^aam-post-access-user/');
159
  } elseif ($feature === 'redirect') {
160
  $this->pushData('usermeta', '/^' . $wpdb->prefix . 'aam_redirect/');
175
  if ($feature === 'metabox') {
176
  $this->pushData('options', '/^aam_visitor_metabox/');
177
  } elseif ($feature === 'post') {
178
+ $this->pushData('options', '/^aam_visitor_type/');
179
+ $this->pushData('options', '/^aam_visitor_term/');
180
  $this->pushData('postmeta', '/^aam-post-access-visitor/');
181
  } elseif ($feature === 'redirect') {
182
  $this->pushData('options', '/^aam_visitor_redirect/');
183
+ } elseif ($feature === 'route') {
184
+ $this->pushData('options', '/^aam_visitor_route/');
185
  }
186
  }
187
  }
194
  foreach($features as $feature) {
195
  if ($feature === 'menu') {
196
  $this->pushData('options', '/^aam_menu_default/');
197
+ } elseif ($feature === 'metabox') {
198
  $this->pushData('options', '/^aam_metabox_default/');
199
+ } elseif ($feature === 'route') {
200
+ $this->pushData('options', '/^aam_route_default/');
201
+ } elseif ($feature === 'toolbar') {
202
+ $this->pushData('options', '/^aam_toolbar_default/');
203
  } elseif ($feature === 'post') {
204
+ $this->pushData('options', '/^aam_type_[\w_\-]_default/');
205
  $this->pushData('options', '/^aam_term_[\d]+\|.+_default/');
206
  $this->pushData('postmeta', '/^aam-post-access-default/');
207
  } elseif ($feature === 'redirect') {
234
  if (preg_match($regexp, $option->option_name)) {
235
  $this->add(
236
  $this->stripPrefix($option->option_name),
237
+ maybe_unserialize($option->option_value),
238
  '_' . $group,
239
  $id
240
  );
243
  if (preg_match($regexp, $option->meta_key)) {
244
  $this->add(
245
  $this->stripPrefix($option->meta_key),
246
+ maybe_unserialize($option->meta_value),
247
  '_' . $group,
248
  $id
249
  );
272
  * @param type $group
273
  */
274
  public function add($key, $value, $group = '_options', $id = null) {
275
+ $compressed = base64_encode(json_encode($value));
276
+
277
  if (is_null($id)) {
278
+ $this->output['dataset'][$group][$key] = $compressed;
279
  } else {
280
+ $this->output['dataset'][$group][$id][$key] = $compressed;
281
  }
282
  }
283
 
290
  global $wpdb;
291
 
292
  if (empty($this->cache)) {
293
+ if (is_multisite()) {
294
+ switch_to_blog(get_main_site_id());
295
+ }
296
+
297
  $query = "SELECT option_name, option_value FROM {$wpdb->options} ";
298
  $query .= "WHERE option_name LIKE 'aam%'";
299
 
308
  $query .= "WHERE meta_key LIKE 'aam%'";
309
 
310
  $this->cache['postmeta'] = $wpdb->get_results($query);
311
+
312
+ if (is_multisite()) {
313
+ restore_current_blog();
314
+ }
315
  }
316
 
317
  return $this->cache;
Application/Core/Gateway.php CHANGED
@@ -106,6 +106,50 @@ final class AAM_Core_Gateway {
106
  return AAM_Core_API::capabilityExists($capability);
107
  }
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  /**
110
  * Get instance of the API gateway
111
  *
106
  return AAM_Core_API::capabilityExists($capability);
107
  }
108
 
109
+ /**
110
+ * Merge AAM settings
111
+ *
112
+ * @param array $set1
113
+ * @param array $set2
114
+ * @param string $objectType
115
+ *
116
+ * @return array
117
+ *
118
+ * @access public
119
+ */
120
+ public function mergeSettings($set1, $set2, $objectType, $preference = null) {
121
+ $combined = array($set1, $set2);
122
+ $merged = array();
123
+
124
+ if (is_null($preference)) {
125
+ $preference = $this->getConfig(
126
+ "core.settings.{$objectType}.merge.preference", 'deny'
127
+ );
128
+ }
129
+
130
+ // first get the complete list of unique keys
131
+ $keys = array_keys(call_user_func_array('array_merge', $combined));
132
+
133
+ foreach($keys as $key) {
134
+ foreach($combined as $options) {
135
+ // If merging preference is "deny" and at least one of the access
136
+ // settings is checked, then final merged array will have it set
137
+ // to checked
138
+ if ($preference === 'deny' && !empty($options[$key])) {
139
+ $merged[$key] = $options[$key];
140
+ break;
141
+ } elseif ($preference === 'allow' && empty($options[$key])) {
142
+ $merged[$key] = 0;
143
+ break;
144
+ } elseif (isset($options[$key])) {
145
+ $merged[$key] = $options[$key];
146
+ }
147
+ }
148
+ }
149
+
150
+ return $merged;
151
+ }
152
+
153
  /**
154
  * Get instance of the API gateway
155
  *
Application/Core/Importer.php CHANGED
@@ -14,7 +14,7 @@
14
  * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15
  */
16
  class AAM_Core_Importer {
17
-
18
  /**
19
  *
20
  * @var type
@@ -27,25 +27,190 @@ class AAM_Core_Importer {
27
  * @var [type]
28
  */
29
  protected $blog = null;
30
-
31
  /**
32
  *
33
  * @param type $input
34
  */
35
- public function __construct($input, $blog = null) {
36
- $this->input = json_decode($input);
37
- $this->blog = (is_null($blog) ? get_current_blog_id() : $blog);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  /**
41
  *
42
  * @return type
43
  */
44
  public function run() {
45
  $response = array('status' => 'success');
46
-
47
  if (version_compare($this->input->version, AAM_Core_API::version()) === 0) {
48
- foreach($this->input->dataset as $table => $data) {
49
  if ($table === '_options') {
50
  $this->insertOptions($data);
51
  } elseif ($table === '_postmeta') {
@@ -59,13 +224,13 @@ class AAM_Core_Importer {
59
  } else {
60
  $response = array(
61
  'status' => 'failure',
62
- 'reason' => __('Version of exported settings do not match current AAM version', AAM_KEY)
63
  );
64
  }
65
 
66
  return $response;
67
  }
68
-
69
  /**
70
  * Undocumented function
71
  *
@@ -75,15 +240,14 @@ class AAM_Core_Importer {
75
  protected function insertOptions($data) {
76
  global $wpdb;
77
 
78
- foreach($data as $key => $value) {
79
  AAM_Core_API::updateOption(
80
- preg_replace('/^_/', $wpdb->get_blog_prefix($this->blog), $key),
81
- $this->prepareValue($value),
82
- $this->blog
83
  );
84
  }
85
  }
86
-
87
  /**
88
  * Undocumented function
89
  *
@@ -92,18 +256,18 @@ class AAM_Core_Importer {
92
  */
93
  protected function insertUsermeta($data) {
94
  global $wpdb;
95
-
96
- foreach($data as $id => $set) {
97
- foreach($set as $key => $value) {
98
  update_user_meta(
99
- $id,
100
- preg_replace('/^_/', $wpdb->get_blog_prefix($this->blog), $key),
101
- $this->prepareValue($value)
102
  );
103
  }
104
  }
105
  }
106
-
107
  /**
108
  * Undocumented function
109
  *
@@ -112,18 +276,18 @@ class AAM_Core_Importer {
112
  */
113
  protected function insertPostmeta($data) {
114
  global $wpdb;
115
-
116
- foreach($data as $id => $set) {
117
- foreach($set as $key => $value) {
118
  update_post_meta(
119
- $id,
120
- preg_replace('/^_/', $wpdb->prefix, $key),
121
- $this->prepareValue($value)
122
  );
123
  }
124
  }
125
  }
126
-
127
  /**
128
  * Undocumented function
129
  *
@@ -131,22 +295,7 @@ class AAM_Core_Importer {
131
  * @return void
132
  */
133
  protected function prepareValue($value) {
134
- if (is_string($value)) {
135
- // #1. Check is string base64 encoded
136
- $decoded = base64_decode($value);
137
-
138
- if ($decoded !== false) {
139
- $value = $decoded;
140
- }
141
-
142
- // #2. Check if string is json
143
- $json = json_decode($value, true);
144
- if (json_last_error() == JSON_ERROR_NONE) {
145
- $value = $json;
146
- }
147
- }
148
-
149
- return $value;
150
  }
151
-
152
- }
14
  * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15
  */
16
  class AAM_Core_Importer {
17
+
18
  /**
19
  *
20
  * @var type
27
  * @var [type]
28
  */
29
  protected $blog = null;
30
+
31
  /**
32
  *
33
  * @param type $input
34
  */
35
+ public function __construct($input = null, $blog = null) {
36
+ if (!is_null($input)) {
37
+ $this->input = json_decode($input);
38
+ }
39
+
40
+ $this->setBlog(is_null($blog) ? get_current_blog_id() : $blog);
41
+ }
42
+
43
+ /**
44
+ *
45
+ * @param type $blog_id
46
+ * @return type
47
+ */
48
+ public function setBlog($blog_id) {
49
+ if ( is_numeric( $blog_id ) ) {
50
+ $blog_id = (int) $blog_id;
51
+ } else {
52
+ $blog = 'http://' . preg_replace( '#^https?://#', '', $blog_id );
53
+ if ( ( !$parsed = parse_url( $blog ) ) || empty( $parsed['host'] ) ) {
54
+ fwrite( STDERR, "Error: can not determine blog_id from $blog_id\n" );
55
+ exit();
56
+ }
57
+ if ( empty( $parsed['path'] ) ) {
58
+ $parsed['path'] = '/';
59
+ }
60
+ $blogs = get_sites( array( 'domain' => $parsed['host'], 'number' => 1, 'path' => $parsed['path'] ) );
61
+ if ( ! $blogs ) {
62
+ fwrite( STDERR, "Error: Could not find blog\n" );
63
+ exit();
64
+ }
65
+ $blog = array_shift( $blogs );
66
+ $blog_id = (int) $blog->blog_id;
67
+ }
68
+
69
+ if ( function_exists( 'is_multisite' ) ) {
70
+ if ( is_multisite() )
71
+ switch_to_blog( $blog_id );
72
+ }
73
+
74
+ return $blog_id;
75
+ }
76
+
77
+ /**
78
+ *
79
+ */
80
+ public function dispatch() {
81
+ $this->header();
82
+
83
+ switch(AAM_Core_Request::get('step', 0)) {
84
+ case 0:
85
+ $this->greet();
86
+ break;
87
+
88
+ case 1:
89
+ check_admin_referer('import-upload');
90
+
91
+ if ($this->handleUpload()) {
92
+ $this->renderConfirmationStep();
93
+ }
94
+ break;
95
+
96
+ case 2:
97
+ check_admin_referer( 'import-wordpress' );
98
+
99
+ $this->id = intval(AAM_Core_Request::post('import_id'));
100
+ $filepath = get_attached_file($this->id);
101
+ $this->import_start( $filepath );
102
+ $this->run();
103
+ $this->import_end();
104
+ break;
105
+ }
106
+
107
+ $this->footer();
108
+ }
109
+
110
+ // Display import page title
111
+ protected function header() {
112
+ echo '<div class="wrap">';
113
+ echo '<h2>' . __('Import AAM Settings', AAM_KEY) . '</h2>';
114
+ }
115
+
116
+ // Close div.wrap
117
+ protected function footer() {
118
+ echo '</div>';
119
+ }
120
+
121
+ /**
122
+ * Display introductory text and file upload form
123
+ */
124
+ protected function greet() {
125
+ echo '<div class="narrow">';
126
+ echo '<p>' . __('Howdy! Upload your AAM JSON file and we&#8217;ll import the access settings into this site.', AAM_KEY) . '</p>';
127
+ echo '<p>' . __('Choose a JSON (.json) file to upload, then click Upload file and import.', AAM_KEY) . '</p>';
128
+ wp_import_upload_form('admin.php?import=aam&amp;step=1');
129
+ echo '</div>';
130
+ }
131
+
132
+ /**
133
+ *
134
+ * @return boolean
135
+ */
136
+ protected function handleUpload() {
137
+ $result = true;
138
+ $file = wp_import_handle_upload();
139
+
140
+ if ( isset( $file['error'] ) ) {
141
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', AAM_KEY ) . '</strong><br />';
142
+ echo esc_html( $file['error'] ) . '</p>';
143
+ $result = false;
144
+ } else if ( ! file_exists( $file['file'] ) ) {
145
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', AAM_KEY ) . '</strong><br />';
146
+ printf( __( 'The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', AAM_KEY ), esc_html( $file['file'] ) );
147
+ echo '</p>';
148
+ $result = false;
149
+ } else {
150
+ $this->file = $file;
151
+ }
152
+
153
+ return $result;
154
  }
155
 
156
+ /**
157
+ *
158
+ */
159
+ protected function renderConfirmationStep() {
160
+ ?>
161
+ <form action="<?php echo admin_url('admin.php?import=aam&amp;step=2' ); ?>" method="post">
162
+ <?php wp_nonce_field('import-wordpress' ); ?>
163
+ <input type="hidden" name="import_id" value="<?php echo $this->file['id']; ?>" />
164
+
165
+ <p>Please confirm the AAM access settings import. Note! All imported access settings will override existing.</p>
166
+
167
+ <p class="submit"><input type="submit" class="button" value="<?php esc_attr_e( 'Submit', AAM_KEY ); ?>" /></p>
168
+ </form>
169
+ <?php
170
+ }
171
+
172
+ /**
173
+ * Parses the WXR file and prepares us for the task of processing parsed data
174
+ *
175
+ * @param string $file Path to the WXR file for importing
176
+ */
177
+ protected function import_start( $file ) {
178
+ if ( ! is_file($file) ) {
179
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', AAM_KEY ) . '</strong><br />';
180
+ echo __( 'The file does not exist, please try again.', AAM_KEY ) . '</p>';
181
+ $this->footer();
182
+ die();
183
+ }
184
+
185
+ $this->input = json_decode(file_get_contents($file));
186
+
187
+ if ( empty( $this->input ) ) {
188
+ echo '<p><strong>' . __( 'Sorry, there has been an error. File content is invalid', AAM_KEY ) . '</strong></p>';
189
+ $this->footer();
190
+ die();
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Performs post-import cleanup of files and the cache
196
+ */
197
+ function import_end() {
198
+ wp_import_cleanup( $this->id );
199
+
200
+ wp_cache_flush();
201
+
202
+ echo '<p>' . __( 'All done.', 'wordpress-importer' ) . ' <a href="' . admin_url() . '">' . __( 'Have fun!', 'wordpress-importer' ) . '</a>' . '</p>';
203
+ }
204
+
205
  /**
206
  *
207
  * @return type
208
  */
209
  public function run() {
210
  $response = array('status' => 'success');
211
+
212
  if (version_compare($this->input->version, AAM_Core_API::version()) === 0) {
213
+ foreach ($this->input->dataset as $table => $data) {
214
  if ($table === '_options') {
215
  $this->insertOptions($data);
216
  } elseif ($table === '_postmeta') {
224
  } else {
225
  $response = array(
226
  'status' => 'failure',
227
+ 'reason' => __('Version of exported settings do not match current AAM version', AAM_KEY)
228
  );
229
  }
230
 
231
  return $response;
232
  }
233
+
234
  /**
235
  * Undocumented function
236
  *
240
  protected function insertOptions($data) {
241
  global $wpdb;
242
 
243
+ foreach ($data as $key => $value) {
244
  AAM_Core_API::updateOption(
245
+ preg_replace('/^_/', $wpdb->get_blog_prefix(), $key),
246
+ $this->prepareValue($value)
 
247
  );
248
  }
249
  }
250
+
251
  /**
252
  * Undocumented function
253
  *
256
  */
257
  protected function insertUsermeta($data) {
258
  global $wpdb;
259
+
260
+ foreach ($data as $id => $set) {
261
+ foreach ($set as $key => $value) {
262
  update_user_meta(
263
+ $id,
264
+ preg_replace('/^_/', $wpdb->get_blog_prefix(), $key),
265
+ $this->prepareValue($value)
266
  );
267
  }
268
  }
269
  }
270
+
271
  /**
272
  * Undocumented function
273
  *
276
  */
277
  protected function insertPostmeta($data) {
278
  global $wpdb;
279
+
280
+ foreach ($data as $id => $set) {
281
+ foreach ($set as $key => $value) {
282
  update_post_meta(
283
+ $id,
284
+ preg_replace('/^_/', $wpdb->prefix, $key),
285
+ $this->prepareValue($value)
286
  );
287
  }
288
  }
289
  }
290
+
291
  /**
292
  * Undocumented function
293
  *
295
  * @return void
296
  */
297
  protected function prepareValue($value) {
298
+ return json_decode(base64_decode($value), true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
300
+
301
+ }
Application/Core/JwtAuth.php CHANGED
@@ -120,10 +120,10 @@ class AAM_Core_JwtAuth {
120
  * @access public
121
  * @throws Exception
122
  */
123
- public function generateJWT($userId) {
124
  $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
125
  $expire = AAM_Core_Config::get('authentication.jwt.expires', 86400);
126
- $container = AAM_Core_Config::get('authentication.jwt.container', 'header');
127
  $alg = AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256');
128
 
129
  if ($key) {
@@ -139,10 +139,11 @@ class AAM_Core_JwtAuth {
139
  setcookie(
140
  'aam-jwt',
141
  $token,
142
- time() + $expire, // 3 hours
143
  '/',
144
  parse_url(get_bloginfo('url'), PHP_URL_HOST),
145
- is_ssl()
 
146
  );
147
  }
148
  } else {
120
  * @access public
121
  * @throws Exception
122
  */
123
+ public function generateJWT($userId, $container = 'header') {
124
  $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
125
  $expire = AAM_Core_Config::get('authentication.jwt.expires', 86400);
126
+ $container = AAM_Core_Config::get('authentication.jwt.container', $container);
127
  $alg = AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256');
128
 
129
  if ($key) {
139
  setcookie(
140
  'aam-jwt',
141
  $token,
142
+ time() + $expire,
143
  '/',
144
  parse_url(get_bloginfo('url'), PHP_URL_HOST),
145
+ is_ssl(),
146
+ AAM_Core_Config::get('authentication.jwt.cookie.httpOnly', false)
147
  );
148
  }
149
  } else {
Application/Core/Login.php CHANGED
@@ -91,6 +91,10 @@ class AAM_Core_Login {
91
  }
92
  }
93
 
 
 
 
 
94
  if ($this->aamLogin === false) {
95
  $redirect = $this->getLoginRedirect($user);
96
 
@@ -133,7 +137,7 @@ class AAM_Core_Login {
133
  public function authenticateUser($user) {
134
  if (is_a($user, 'WP_User')) {
135
  // First check if user is blocked
136
- if ($user->user_status === 1) {
137
  $user = new WP_Error();
138
 
139
  $message = '[ERROR]: User is locked. Please contact your website ';
@@ -274,10 +278,8 @@ class AAM_Core_Login {
274
  'redirect' => AAM_Core_Request::post('redirect')
275
  );
276
 
277
- $log = sanitize_user(AAM_Core_Request::post('log'));
278
-
279
  try {
280
- $user = wp_signon($credentials, $this->checkUserSSL($log));
281
 
282
  if (is_wp_error($user)) {
283
  Throw new Exception($user->get_error_message());
@@ -291,7 +293,6 @@ class AAM_Core_Login {
291
  $response['status'] = 'success';
292
  $response['user'] = $user;
293
  } catch (Exception $ex) {
294
- $response['error'] = $user;
295
  $response['reason'] = $ex->getMessage();
296
  }
297
 
@@ -321,29 +322,6 @@ class AAM_Core_Login {
321
  return $normalized;
322
  }
323
 
324
- /**
325
- * Check user SSL status
326
- *
327
- * @param string $log
328
- *
329
- * @return boolean
330
- *
331
- * @access protected
332
- */
333
- protected function checkUserSSL($log) {
334
- $secure = false;
335
- $user = get_user_by((strpos($log, '@') ? 'email' : 'login'), $log);
336
-
337
- if ($user) {
338
- if (!force_ssl_admin() && get_user_option('use_ssl', $user->ID)) {
339
- $secure = true;
340
- force_ssl_admin(true);
341
- }
342
- }
343
-
344
- return $secure;
345
- }
346
-
347
  /**
348
  * Get single instance of itself
349
  *
91
  }
92
  }
93
 
94
+ if (AAM::api()->getConfig('core.settings.setJwtCookieAfterLogin', false)) {
95
+ AAM_Core_JwtAuth::getInstance()->generateJWT($user->ID, 'cookie');
96
+ }
97
+
98
  if ($this->aamLogin === false) {
99
  $redirect = $this->getLoginRedirect($user);
100
 
137
  public function authenticateUser($user) {
138
  if (is_a($user, 'WP_User')) {
139
  // First check if user is blocked
140
+ if (intval($user->user_status) === 1) {
141
  $user = new WP_Error();
142
 
143
  $message = '[ERROR]: User is locked. Please contact your website ';
278
  'redirect' => AAM_Core_Request::post('redirect')
279
  );
280
 
 
 
281
  try {
282
+ $user = wp_signon($credentials);
283
 
284
  if (is_wp_error($user)) {
285
  Throw new Exception($user->get_error_message());
293
  $response['status'] = 'success';
294
  $response['user'] = $user;
295
  } catch (Exception $ex) {
 
296
  $response['reason'] = $ex->getMessage();
297
  }
298
 
322
  return $normalized;
323
  }
324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  /**
326
  * Get single instance of itself
327
  *
Application/Core/Media.php CHANGED
@@ -87,11 +87,7 @@ class AAM_Core_Media {
87
  if (empty($media)) {
88
  $this->printMedia();
89
  } else {
90
- $read = $media->has('frontend.read');
91
- $others = $media->has('frontend.read_others');
92
- $author = (intval($media->post_author) === get_current_user_id());
93
-
94
- if ($read || ($others && !$author)) {
95
  $args = array(
96
  'hook' => 'media_read',
97
  'action' => "{$area}.read",
87
  if (empty($media)) {
88
  $this->printMedia();
89
  } else {
90
+ if (!$media->allowed('frontend.read')) {
 
 
 
 
91
  $args = array(
92
  'hook' => 'media_read',
93
  'action' => "{$area}.read",
Application/Core/Object.php CHANGED
@@ -117,6 +117,15 @@ abstract class AAM_Core_Object {
117
  return $this->_option;
118
  }
119
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  * Update single option item
122
  *
117
  return $this->_option;
118
  }
119
 
120
+ /**
121
+ *
122
+ * @param type $external
123
+ * @return type
124
+ */
125
+ public function mergeOption($external) {
126
+ return $external;
127
+ }
128
+
129
  /**
130
  * Update single option item
131
  *
Application/Core/Object/Cache.php CHANGED
@@ -23,6 +23,15 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
23
  * @access protected
24
  */
25
  protected $updated = false;
 
 
 
 
 
 
 
 
 
26
 
27
  /**
28
  * Constructor
@@ -36,8 +45,16 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
36
  public function __construct(AAM_Core_Subject $subject) {
37
  parent::__construct($subject);
38
 
39
- if (!AAM::isAAM()
40
- && (AAM_Core_Config::get('core.cache.status', 'enabled') === 'enabled')) {
 
 
 
 
 
 
 
 
41
  // Register shutdown hook
42
  add_action('shutdown', array($this, 'save'));
43
 
@@ -86,7 +103,7 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
86
  * @access public
87
  */
88
  public function save() {
89
- if ($this->updated) {
90
  $this->getSubject()->updateOption($this->getOption(), 'cache');
91
  }
92
 
23
  * @access protected
24
  */
25
  protected $updated = false;
26
+
27
+ /**
28
+ * Is cache enabled?
29
+ *
30
+ * @var boolean
31
+ *
32
+ * @access protected
33
+ */
34
+ protected $enabled = true;
35
 
36
  /**
37
  * Constructor
45
  public function __construct(AAM_Core_Subject $subject) {
46
  parent::__construct($subject);
47
 
48
+ // Determine if cache is enabled
49
+ $action = AAM_Core_Request::request('action');
50
+ $triggers = array('edit', 'editpost');
51
+ $status = AAM_Core_Config::get('core.cache.status', 'enabled');
52
+
53
+ if (!AAM::isAAM() || ($status !== 'enabled') || in_array($action, $triggers)) {
54
+ $this->enabled = false;
55
+ }
56
+
57
+ if ($this->enabled) {
58
  // Register shutdown hook
59
  add_action('shutdown', array($this, 'save'));
60
 
103
  * @access public
104
  */
105
  public function save() {
106
+ if ($this->enabled && $this->updated) {
107
  $this->getSubject()->updateOption($this->getOption(), 'cache');
108
  }
109
 
Application/Core/Object/Menu.php CHANGED
@@ -252,5 +252,14 @@ class AAM_Core_Object_Menu extends AAM_Core_Object {
252
  public function reset() {
253
  return $this->getSubject()->deleteOption('menu');
254
  }
 
 
 
 
 
 
 
 
 
255
 
256
  }
252
  public function reset() {
253
  return $this->getSubject()->deleteOption('menu');
254
  }
255
+
256
+ /**
257
+ *
258
+ * @param type $external
259
+ * @return type
260
+ */
261
+ public function mergeOption($external) {
262
+ return AAM::api()->mergeSettings($external, $this->getOption(), 'menu');
263
+ }
264
 
265
  }
Application/Core/Object/Metabox.php CHANGED
@@ -197,5 +197,14 @@ class AAM_Core_Object_Metabox extends AAM_Core_Object {
197
  public function deny($screen, $metabox) {
198
  return $this->save("{$screen}|{$metabox}", 1);
199
  }
 
 
 
 
 
 
 
 
 
200
 
201
  }
197
  public function deny($screen, $metabox) {
198
  return $this->save("{$screen}|{$metabox}", 1);
199
  }
200
+
201
+ /**
202
+ *
203
+ * @param type $external
204
+ * @return type
205
+ */
206
+ public function mergeOption($external) {
207
+ return AAM::api()->mergeSettings($external, $this->getOption(), 'metabox');
208
+ }
209
 
210
  }
Application/Core/Object/Post.php CHANGED
@@ -44,8 +44,7 @@ class AAM_Core_Object_Post extends AAM_Core_Object {
44
  $this->setPost(get_post($post));
45
  }
46
 
47
- // Do not initialize settings for posts that are about to be created
48
- if ($this->getPost() && ($this->getPost()->post_status !== 'auto-draft')) {
49
  $this->read();
50
  }
51
  }
@@ -193,7 +192,7 @@ class AAM_Core_Object_Post extends AAM_Core_Object {
193
  // set meta for revision, so let's bypass this constrain.
194
  if ($this->getPost()->post_type === 'revision') {
195
  $result = delete_metadata(
196
- 'post', $this->getPost()->ID, $this->getOptionName()
197
  );
198
  } else {
199
  $result = delete_post_meta($this->getPost()->ID, $this->getOptionName());
@@ -247,6 +246,25 @@ class AAM_Core_Object_Post extends AAM_Core_Object {
247
  return (array_key_exists($property, $option) && !empty($option[$property]));
248
  }
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  /**
251
  * Update property
252
  *
@@ -334,6 +352,15 @@ class AAM_Core_Object_Post extends AAM_Core_Object {
334
  return true;
335
  }
336
 
 
 
 
 
 
 
 
 
 
337
  /**
338
  * Get Post
339
  *
44
  $this->setPost(get_post($post));
45
  }
46
 
47
+ if ($this->getPost()) {
 
48
  $this->read();
49
  }
50
  }
192
  // set meta for revision, so let's bypass this constrain.
193
  if ($this->getPost()->post_type === 'revision') {
194
  $result = delete_metadata(
195
+ 'post', $this->getPost()->ID, $this->getOptionName()
196
  );
197
  } else {
198
  $result = delete_post_meta($this->getPost()->ID, $this->getOptionName());
246
  return (array_key_exists($property, $option) && !empty($option[$property]));
247
  }
248
 
249
+ /**
250
+ * Check if subject can do certain action
251
+ *
252
+ * The difference between `can` and `allowed` is that can is more in-depth way
253
+ * to take in consideration relationships between properties.
254
+ *
255
+ * @return boolean
256
+ *
257
+ * @access public
258
+ */
259
+ public function allowed() {
260
+ return apply_filters(
261
+ 'aam-post-action-allowed-filter',
262
+ !call_user_func_array(array($this, 'has'), func_get_args()),
263
+ func_get_arg(0),
264
+ $this
265
+ );
266
+ }
267
+
268
  /**
269
  * Update property
270
  *
352
  return true;
353
  }
354
 
355
+ /**
356
+ *
357
+ * @param type $external
358
+ * @return type
359
+ */
360
+ public function mergeOption($external) {
361
+ return AAM::api()->mergeSettings($external, $this->getOption(), 'post');
362
+ }
363
+
364
  /**
365
  * Get Post
366
  *
Application/Core/Object/Toolbar.php CHANGED
@@ -112,5 +112,14 @@ class AAM_Core_Object_Toolbar extends AAM_Core_Object {
112
  public function reset() {
113
  return $this->getSubject()->deleteOption('toolbar');
114
  }
 
 
 
 
 
 
 
 
 
115
 
116
  }
112
  public function reset() {
113
  return $this->getSubject()->deleteOption('toolbar');
114
  }
115
+
116
+ /**
117
+ *
118
+ * @param type $external
119
+ * @return type
120
+ */
121
+ public function mergeOption($external) {
122
+ return AAM::api()->mergeSettings($external, $this->getOption(), 'toolbar');
123
+ }
124
 
125
  }
Application/Core/Subject.php CHANGED
@@ -36,6 +36,17 @@ abstract class AAM_Core_Subject {
36
  * @access private
37
  */
38
  private $_subject;
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  /**
41
  * List of Objects to be access controlled for current subject
@@ -185,6 +196,30 @@ abstract class AAM_Core_Subject {
185
  public function setSubject($subject) {
186
  $this->_subject = $subject;
187
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
 
189
  /**
190
  * Get Individual Object
@@ -305,7 +340,9 @@ abstract class AAM_Core_Subject {
305
  /**
306
  *
307
  */
308
- abstract public function getOptionName($object, $id);
 
 
309
 
310
  /**
311
  * Read object from parent subject
@@ -322,6 +359,15 @@ abstract class AAM_Core_Subject {
322
 
323
  if (is_a($subject, 'AAM_Core_Subject')){
324
  $option = $subject->getObject($object, $id, $param)->getOption();
 
 
 
 
 
 
 
 
 
325
  } else {
326
  $option = null;
327
  }
36
  * @access private
37
  */
38
  private $_subject;
39
+
40
+ /**
41
+ * Covering the scenario of multi-subjects
42
+ *
43
+ * For example this is quite typical for the multi-roles
44
+ *
45
+ * @var array
46
+ *
47
+ * @access private
48
+ */
49
+ private $_siblings = array();
50
 
51
  /**
52
  * List of Objects to be access controlled for current subject
196
  public function setSubject($subject) {
197
  $this->_subject = $subject;
198
  }
199
+
200
+ /**
201
+ *
202
+ * @param type $siblings
203
+ */
204
+ public function setSiblings($siblings) {
205
+ $this->_siblings = $siblings;
206
+ }
207
+
208
+ /**
209
+ *
210
+ * @return type
211
+ */
212
+ public function hasSiblings() {
213
+ return count($this->_siblings) ? true : false;
214
+ }
215
+
216
+ /**
217
+ *
218
+ * @return type
219
+ */
220
+ public function getSiblings() {
221
+ return $this->_siblings;
222
+ }
223
 
224
  /**
225
  * Get Individual Object
340
  /**
341
  *
342
  */
343
+ public function getOptionName($object, $id) {
344
+ return '';
345
+ }
346
 
347
  /**
348
  * Read object from parent subject
359
 
360
  if (is_a($subject, 'AAM_Core_Subject')){
361
  $option = $subject->getObject($object, $id, $param)->getOption();
362
+ $multi = AAM::api()->getConfig('core.settings.multiSubject', false);
363
+
364
+ if ($multi && $subject->hasSiblings()) {
365
+ foreach($subject->getSiblings() as $sibling) {
366
+ $option = $sibling->getObject($object, $id, $param)->mergeOption(
367
+ $option
368
+ );
369
+ }
370
+ }
371
  } else {
372
  $option = null;
373
  }
Application/Core/Subject/User.php CHANGED
@@ -332,12 +332,20 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
332
  if (is_null($this->parent)) {
333
  //try to get this option from the User's Role
334
  $roles = $this->getSubject()->roles;
335
- //first user role is counted only. AAM does not support multi-roles
336
- $parent = array_shift($roles);
337
-
338
- //in case of multisite & current user does not belong to the site
339
- if ($parent) {
340
- $this->parent = new AAM_Core_Subject_Role($parent);
 
 
 
 
 
 
 
 
341
  } else {
342
  $this->parent = null;
343
  }
332
  if (is_null($this->parent)) {
333
  //try to get this option from the User's Role
334
  $roles = $this->getSubject()->roles;
335
+ $base = array_shift($roles);
336
+
337
+ if ($base) {
338
+ $this->parent = new AAM_Core_Subject_Role($base);
339
+
340
+ // if user has more than one role that set subject as multi
341
+ if (AAM::api()->getConfig('core.settings.multiSubject', false)
342
+ && count($roles)) {
343
+ $siblings = array();
344
+ foreach($roles as $role) {
345
+ $siblings[] = new AAM_Core_Subject_Role($role);
346
+ }
347
+ $this->parent->setSiblings($siblings);
348
+ }
349
  } else {
350
  $this->parent = null;
351
  }
Application/Extension/List.php CHANGED
@@ -22,7 +22,7 @@ class AAM_Extension_List {
22
  'description' => 'Get the complete list of all premium AAM extensions in one package and all future premium extensions already included for now additional cost.',
23
  'url' => 'https://aamplugin.com/complete-package',
24
  'version' => (defined('AAM_COMPLETE_PACKAGE') ? constant('AAM_COMPLETE_PACKAGE') : null),
25
- 'latest' => '3.8.6'
26
  ),
27
  'AAM_PLUS_PACKAGE' => array(
28
  'title' => 'Plus Package',
@@ -31,7 +31,7 @@ class AAM_Extension_List {
31
  'description' => 'Manage access to your WordPress website posts, pages, media, custom post types, categories and hierarchical taxonomies for any role, individual user, visitors or even define default access for everybody; and do this separately for frontend, backend or API levels. As the bonus, define more granular access to how comments can be managed on the backend by other users.',
32
  'url' => 'https://aamplugin.com/extension/plus-package',
33
  'version' => (defined('AAM_PLUS_PACKAGE') ? constant('AAM_PLUS_PACKAGE') : null),
34
- 'latest' => '3.8'
35
  ),
36
  'AAM_IP_CHECK' => array(
37
  'title' => 'IP Check',
22
  'description' => 'Get the complete list of all premium AAM extensions in one package and all future premium extensions already included for now additional cost.',
23
  'url' => 'https://aamplugin.com/complete-package',
24
  'version' => (defined('AAM_COMPLETE_PACKAGE') ? constant('AAM_COMPLETE_PACKAGE') : null),
25
+ 'latest' => '3.8.8'
26
  ),
27
  'AAM_PLUS_PACKAGE' => array(
28
  'title' => 'Plus Package',
31
  'description' => 'Manage access to your WordPress website posts, pages, media, custom post types, categories and hierarchical taxonomies for any role, individual user, visitors or even define default access for everybody; and do this separately for frontend, backend or API levels. As the bonus, define more granular access to how comments can be managed on the backend by other users.',
32
  'url' => 'https://aamplugin.com/extension/plus-package',
33
  'version' => (defined('AAM_PLUS_PACKAGE') ? constant('AAM_PLUS_PACKAGE') : null),
34
+ 'latest' => '3.8.2'
35
  ),
36
  'AAM_IP_CHECK' => array(
37
  'title' => 'IP Check',
Application/Frontend/Authorization.php CHANGED
@@ -95,10 +95,7 @@ class AAM_Frontend_Authorization {
95
  * @access protected
96
  */
97
  protected function checkReadAccess(AAM_Core_Object_Post $post) {
98
- $read = $post->has('frontend.read');
99
- $others = $post->has('frontend.read_others');
100
-
101
- if ($read || ($others && (intval($post->post_author) !== get_current_user_id()))) {
102
  $this->deny('post_read', 'frontend.read', $post->getPost());
103
  }
104
  }
95
  * @access protected
96
  */
97
  protected function checkReadAccess(AAM_Core_Object_Post $post) {
98
+ if (!$post->allowed('frontend.read')) {
 
 
 
99
  $this->deny('post_read', 'frontend.read', $post->getPost());
100
  }
101
  }
Application/Frontend/Filter.php CHANGED
@@ -125,10 +125,7 @@ class AAM_Frontend_Filter {
125
  foreach ($pages as $i => $page) {
126
  if (in_array($page->type, array('post_type', 'custom'), true)) {
127
  $object = AAM::getUser()->getObject('post', $page->object_id);
128
- $others = $object->get('frontend.list_others');
129
- $list = $object->get('frontend.list');
130
-
131
- if (($others && (intval($object->post_author) !== get_current_user_id())) || $list) {
132
  unset($pages[$i]);
133
  }
134
  }
@@ -158,10 +155,7 @@ class AAM_Frontend_Filter {
158
 
159
  // TODO: refactor this to AAM API standalone
160
  $object = AAM::getUser()->getObject('post', $post->ID);
161
- $list = $object->get($area. '.list');
162
- $others = $object->get($area. '.list_others');
163
-
164
- if ($list || ($others && (intval($post->post_author) !== get_current_user_id()))) {
165
  unset($pages[$i]);
166
  }
167
  }
125
  foreach ($pages as $i => $page) {
126
  if (in_array($page->type, array('post_type', 'custom'), true)) {
127
  $object = AAM::getUser()->getObject('post', $page->object_id);
128
+ if (!$object->allowed('frontend.list')) {
 
 
 
129
  unset($pages[$i]);
130
  }
131
  }
155
 
156
  // TODO: refactor this to AAM API standalone
157
  $object = AAM::getUser()->getObject('post', $post->ID);
158
+ if (!$object->allowed($area. '.list')) {
 
 
 
159
  unset($pages[$i]);
160
  }
161
  }
Application/Shared/Manager.php CHANGED
@@ -505,7 +505,7 @@ class AAM_Shared_Manager {
505
  $draft = $object->post_status === 'auto-draft';
506
  $area = AAM_Core_Api_Area::get();
507
 
508
- if (!$draft && !$this->isActionAllowed($area . '.edit', $object)) {
509
  $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
510
  }
511
 
@@ -527,7 +527,7 @@ class AAM_Shared_Manager {
527
  $object = AAM::getUser()->getObject('post', $id);
528
  $area = AAM_Core_Api_Area::get();
529
 
530
- if (!$this->isActionAllowed($area . '.delete', $object)) {
531
  $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
532
  }
533
 
@@ -551,35 +551,15 @@ class AAM_Shared_Manager {
551
  if (is_a($post, 'WP_Post')) {
552
  $object = AAM::getUser()->getObject('post', $post->ID);
553
  $area = AAM_Core_Api_Area::get();
554
-
555
- if (!$this->isActionAllowed($area . '.publish', $object)) {
556
- $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
557
  }
558
  }
559
 
560
  return $allcaps;
561
  }
562
 
563
- /**
564
- * Check if action is allowed
565
- *
566
- * This method will take in consideration also *_others action
567
- *
568
- * @param string $action
569
- * @param AAM_Core_Object_Post $object
570
- *
571
- * @return boolean
572
- *
573
- * @access protected
574
- */
575
- protected function isActionAllowed($action, $object) {
576
- $edit = $object->has($action);
577
- $others = $object->has("{$action}_others");
578
- $author = (intval($object->post_author) === get_current_user_id());
579
-
580
- return ($edit || ($others && !$author)) ? false : true;
581
- }
582
-
583
  /**
584
  * Restrict user capabilities
585
  *
505
  $draft = $object->post_status === 'auto-draft';
506
  $area = AAM_Core_Api_Area::get();
507
 
508
+ if (!$draft && !$object->allowed($area . '.edit')) {
509
  $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
510
  }
511
 
527
  $object = AAM::getUser()->getObject('post', $id);
528
  $area = AAM_Core_Api_Area::get();
529
 
530
+ if (!$object->allowed($area . '.delete')) {
531
  $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
532
  }
533
 
551
  if (is_a($post, 'WP_Post')) {
552
  $object = AAM::getUser()->getObject('post', $post->ID);
553
  $area = AAM_Core_Api_Area::get();
554
+
555
+ if (!$object->allowed($area . '.publish')) {
556
+ $allcaps = $this->restrictCapabilities($allcaps, $metacaps);
557
  }
558
  }
559
 
560
  return $allcaps;
561
  }
562
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  /**
564
  * Restrict user capabilities
565
  *
Application/Shortcode/Strategy/LoginRedirect.php CHANGED
@@ -33,6 +33,7 @@ class AAM_Shortcode_Strategy_LoginRedirect implements AAM_Shortcode_Strategy_Int
33
  * Expecting attributes in $args are:
34
  * "class" => CSS class for login button
35
  * "callback" => callback function that returns the login button
 
36
  *
37
  * @param type $args
38
  * @param type $content
@@ -59,8 +60,14 @@ class AAM_Shortcode_Strategy_LoginRedirect implements AAM_Shortcode_Strategy_Int
59
  wp_login_url($redirect)
60
  );
61
 
 
 
 
 
 
 
62
  $button = '<a href="' . $url . '" ';
63
- $button .= 'class="' . $class . '">' . $this->content . '</a>';
64
  }
65
 
66
  return $button;
33
  * Expecting attributes in $args are:
34
  * "class" => CSS class for login button
35
  * "callback" => callback function that returns the login button
36
+ * "label" => if stand-alone shortcode then defined text label will be used
37
  *
38
  * @param type $args
39
  * @param type $content
60
  wp_login_url($redirect)
61
  );
62
 
63
+ if (empty($this->content)) {
64
+ $label = (!empty($this->args['label']) ? $this->args['label'] : __('Login to continue', AAM_KEY));
65
+ } else {
66
+ $label = $this->content;
67
+ }
68
+
69
  $button = '<a href="' . $url . '" ';
70
+ $button .= 'class="' . $class . '">' . $label . '</a>';
71
  }
72
 
73
  return $button;
aam.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  Plugin Name: Advanced Access Manager
5
  Description: All you need to manage access to your WordPress website
6
- Version: 5.4.3.2
7
  Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  Author URI: https://vasyltech.com
9
 
3
  /**
4
  Plugin Name: Advanced Access Manager
5
  Description: All you need to manage access to your WordPress website
6
+ Version: 5.5
7
  Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  Author URI: https://vasyltech.com
9
 
media/css/aam.css CHANGED
@@ -557,6 +557,14 @@ input[type=radio]:checked + label:before {
557
  display: inline;
558
  }
559
 
 
 
 
 
 
 
 
 
560
  .aam-switch-user {
561
  float:right;
562
  font-size:1em !important;
557
  display: inline;
558
  }
559
 
560
+ .aam-small-highlighted {
561
+ font-size: 85%;
562
+ border-bottom: 1px solid #999999;
563
+ padding: 0px 20px 2px 0;
564
+ margin-bottom: 10px;
565
+ display: inline-block;
566
+ }
567
+
568
  .aam-switch-user {
569
  float:right;
570
  font-size:1em !important;
media/js/aam.js CHANGED
@@ -185,7 +185,9 @@
185
  },
186
  createdRow: function (row, data) {
187
  if (isCurrent(data[0])) {
188
- $('td:eq(0)', row).html('<strong class="aam-highlight">' + data[2] + '</strong>');
 
 
189
  } else {
190
  $('td:eq(0)', row).html('<span>' + data[2] + '</span>');
191
  }
@@ -532,8 +534,6 @@
532
  highlight.replaceWith($('<span/>').text(highlight.text()));
533
  }
534
  });
535
- //show post & pages access control groups that belong to backend
536
- $('.aam-backend-post-access').show();
537
  });
538
 
539
  //in case interface needed to be reloaded
@@ -888,7 +888,7 @@
888
  case 'no-switch':
889
  if (!getAAM().isUI()) {
890
  $(container).append($('<i/>', {
891
- 'class': 'aam-row-action icon-switch text-muted'
892
  }));
893
  }
894
  break;
@@ -1029,8 +1029,6 @@
1029
  highlight.replaceWith('<span>' + highlight.text() + '</span>');
1030
  }
1031
  });
1032
- //show post & pages access control groups that belong to backend
1033
- $('.aam-backend-post-access').show();
1034
  });
1035
 
1036
  //in case interface needed to be reloaded
@@ -1073,8 +1071,6 @@
1073
  );
1074
  });
1075
  }
1076
- //hide post & pages access control groups that belong to backend
1077
- $('.aam-backend-post-access').hide();
1078
  });
1079
  });
1080
 
@@ -1134,24 +1130,28 @@
1134
  * @returns {undefined}
1135
  */
1136
  function save(items, status, successCallback) {
1137
- $.ajax(getLocal().ajaxurl, {
1138
- type: 'POST',
1139
- dataType: 'json',
1140
- data: {
1141
- action: 'aam',
1142
- sub_action: 'Main_Menu.save',
1143
- subject: getAAM().getSubject().type,
1144
- subjectId: getAAM().getSubject().id,
1145
- _ajax_nonce: getLocal().nonce,
1146
- items: items,
1147
- status: status
1148
- },
1149
- success: function(response) {
1150
- successCallback(response);
1151
- },
1152
- error: function () {
1153
- getAAM().notification('danger', getAAM().__('Application Error'));
1154
- }
 
 
 
 
1155
  });
1156
  }
1157
 
@@ -1257,50 +1257,28 @@
1257
  * @returns {undefined}
1258
  */
1259
  function save(items, status, successCallback) {
1260
- $.ajax(getLocal().ajaxurl, {
1261
- type: 'POST',
1262
- dataType: 'json',
1263
- data: {
1264
- action: 'aam',
1265
- sub_action: 'Main_Toolbar.save',
1266
- subject: getAAM().getSubject().type,
1267
- subjectId: getAAM().getSubject().id,
1268
- _ajax_nonce: getLocal().nonce,
1269
- items: items,
1270
- status: status
1271
- },
1272
- success: function(response) {
1273
- successCallback(response);
1274
- },
1275
- error: function () {
1276
- getAAM().notification('danger', getAAM().__('Application Error'));
1277
- }
1278
- });
1279
- }
1280
-
1281
- /**
1282
- *
1283
- * @returns {undefined}
1284
- */
1285
- function getContent() {
1286
- $.ajax(getLocal().ajaxurl, {
1287
- type: 'POST',
1288
- dataType: 'html',
1289
- data: {
1290
- action: 'aam',
1291
- sub_action: 'Main_Toolbar.getContent',
1292
- _ajax_nonce: getLocal().nonce,
1293
- subject: getAAM().getSubject().type,
1294
- subjectId: getAAM().getSubject().id
1295
- },
1296
- success: function (response) {
1297
- $('#toolbar-content').replaceWith(response);
1298
- $('#toolbar-content').addClass('active');
1299
- initialize();
1300
- },
1301
- error: function () {
1302
- getAAM().notification('danger', getAAM().__('Application error'));
1303
- }
1304
  });
1305
  }
1306
 
@@ -1355,27 +1333,6 @@
1355
  });
1356
  });
1357
 
1358
- //init refresh list button
1359
- $('#refresh-toolbar-list').bind('click', function () {
1360
- var url = getLocal().url.site;
1361
- url += (url.indexOf('?') === -1 ? '?' : '&') + 'init=toolbar';
1362
-
1363
- $.ajax(url, {
1364
- type: 'GET',
1365
- beforeSend: function () {
1366
- $('i', '#refresh-toolbar-list').attr(
1367
- 'class', 'icon-spin4 animate-spin'
1368
- );
1369
- },
1370
- complete: function () {
1371
- getContent();
1372
- $('i', '#refresh-toolbar-list').attr(
1373
- 'class', 'icon-arrows-cw'
1374
- );
1375
- }
1376
- });
1377
- });
1378
-
1379
  //reset button
1380
  $('#toolbar-reset').bind('click', function () {
1381
  getAAM().reset('toolbar', $(this));
@@ -1598,7 +1555,8 @@
1598
  } else {
1599
  if (granted) {
1600
  getAAM().notification(
1601
- 'danger', getAAM().__('WordPress core does not allow to grant this capability')
 
1602
  );
1603
  $(btn).attr('class', 'aam-row-action text-muted icon-check-empty');
1604
  } else {
@@ -1672,6 +1630,12 @@
1672
  $('#edit-capability-modal').modal('show');
1673
  }));
1674
  break;
 
 
 
 
 
 
1675
 
1676
  case 'delete':
1677
  $(container).append($('<i/>', {
@@ -1686,6 +1650,12 @@
1686
  $('#delete-capability-modal').modal('show');
1687
  }));
1688
  break;
 
 
 
 
 
 
1689
 
1690
  default:
1691
  getAAM().triggerHook('decorate-capability-row', {
@@ -1889,36 +1859,40 @@
1889
  * @param {*} successCallback
1890
  */
1891
  function save(param, value, object, object_id, successCallback) {
1892
- $.ajax(getLocal().ajaxurl, {
1893
- type: 'POST',
1894
- dataType: 'json',
1895
- data: {
1896
- action: 'aam',
1897
- sub_action: 'Main_Post.save',
1898
- _ajax_nonce: getLocal().nonce,
1899
- subject: getAAM().getSubject().type,
1900
- subjectId: getAAM().getSubject().id,
1901
- param: param,
1902
- value: value,
1903
- object: object,
1904
- objectId: object_id
1905
- },
1906
- success: function (response) {
1907
- if (response.status === 'failure') {
1908
- getAAM().notification('danger', response.error);
1909
- } else {
1910
- $('#post-overwritten').removeClass('hidden');
1911
- //add some specific attributes to reset button
1912
- $('#post-reset').attr({
1913
- 'data-type': object,
1914
- 'data-id': object_id
1915
- });
 
 
 
 
 
 
 
 
1916
  }
1917
- successCallback(response);
1918
- },
1919
- error: function () {
1920
- getAAM().notification('danger', getAAM().__('Application error'));
1921
- }
1922
  });
1923
  }
1924
 
@@ -1968,11 +1942,12 @@
1968
  $(this).unbind('click').bind('click', function () {
1969
  var _this = $(this);
1970
  var checked = !_this.hasClass('icon-check');
 
1971
 
1972
  _this.attr('class', 'aam-row-action icon-spin4 animate-spin');
1973
  save(
1974
  _this.data('property'),
1975
- (checked ? 1 : 0),
1976
  object,
1977
  id,
1978
  function(response) {
@@ -1989,8 +1964,29 @@
1989
  }
1990
  }
1991
  );
 
 
 
 
1992
  });
1993
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1994
 
1995
  $.ajax(getLocal().ajaxurl, {
1996
  type: 'POST',
@@ -2253,6 +2249,12 @@
2253
  'title': getAAM().__('Edit')
2254
  }));
2255
  break;
 
 
 
 
 
 
2256
 
2257
  default:
2258
  getAAM().triggerHook('post-action', {
@@ -2331,23 +2333,6 @@
2331
  );
2332
  }
2333
 
2334
- $('.advanced-post-option').each(function() {
2335
- $(this).bind('click', function() {
2336
- var container = $(this).attr('href');
2337
- var option = objectAccess.access[$(this).data('ref')];
2338
- var field = $($('.extended-post-access-btn', container).data('field'));
2339
-
2340
- //add attributes to the .extended-post-access-btn
2341
- $('.extended-post-access-btn', container).attr({
2342
- 'data-ref': $(this).data('ref'),
2343
- 'data-preview': $(this).data('preview')
2344
- });
2345
-
2346
- //set field value
2347
- field.val(option);
2348
- });
2349
- });
2350
-
2351
  $('.extended-post-access-btn').each(function() {
2352
  $(this).bind('click', function() {
2353
  var _this = $(this);
@@ -2668,21 +2653,25 @@
2668
  * @returns {undefined}
2669
  */
2670
  function save(param, value) {
2671
- $.ajax(getLocal().ajaxurl, {
2672
- type: 'POST',
2673
- dataType: 'json',
2674
- data: {
2675
- action: 'aam',
2676
- sub_action: 'Main_404Redirect.save',
2677
- _ajax_nonce: getLocal().nonce,
2678
- subject: getAAM().getSubject().type,
2679
- subjectId: getAAM().getSubject().id,
2680
- param: param,
2681
- value: value
2682
- },
2683
- error: function () {
2684
- getAAM().notification('danger', getAAM().__('Application error'));
2685
- }
 
 
 
 
2686
  });
2687
  }
2688
 
@@ -2738,37 +2727,43 @@
2738
  * @param {type} btn
2739
  * @returns {undefined}
2740
  */
2741
- function save(type, route, method, value, btn) {
2742
- //show indicator
2743
- $(btn).attr('class', 'aam-row-action icon-spin4 animate-spin');
2744
 
2745
- $.ajax(getLocal().ajaxurl, {
2746
- type: 'POST',
2747
- dataType: 'json',
2748
- data: {
2749
- action: 'aam',
2750
- sub_action: 'Main_Route.save',
2751
- _ajax_nonce: getLocal().nonce,
2752
- subject: getAAM().getSubject().type,
2753
- subjectId: getAAM().getSubject().id,
2754
- type: type,
2755
- route: route,
2756
- method: method,
2757
- value: value
2758
- },
2759
- success: function (response) {
2760
- if (response.status === 'failure') {
2761
- getAAM().notification('danger', response.error);
 
 
 
 
 
 
 
 
 
 
 
2762
  updateBtn(btn, value ? 0 : 1);
2763
- } else {
2764
- $('#aam-route-overwrite').removeClass('hidden');
2765
- updateBtn(btn, value);
2766
  }
2767
- },
2768
- error: function () {
2769
- updateBtn(btn, value ? 0 : 1);
2770
- getAAM().notification('danger', getAAM().__('Application error'));
2771
- }
2772
  });
2773
  }
2774
 
@@ -2843,7 +2838,7 @@
2843
  $(container).append($('<i/>', {
2844
  'class': 'aam-row-action text-muted icon-check-empty'
2845
  }).bind('click', function () {
2846
- save(data[0], data[2], data[1], 1, this);
2847
  }));
2848
  break;
2849
 
@@ -2851,7 +2846,7 @@
2851
  $(container).append($('<i/>', {
2852
  'class': 'aam-row-action text-danger icon-check'
2853
  }).bind('click', function () {
2854
- save(data[0], data[2], data[1], 0, this);
2855
  }));
2856
  break;
2857
 
@@ -2925,26 +2920,32 @@
2925
  * @returns {undefined}
2926
  */
2927
  function updateStatus(data) {
2928
- $.ajax(getLocal().ajaxurl, {
2929
- type: 'POST',
2930
- dataType: 'json',
2931
- data: data,
2932
- success: function (response) {
2933
- if (response.status === 'success') {
 
 
 
 
 
 
 
 
 
 
 
 
2934
  getAAM().notification(
2935
- 'success',
2936
- getAAM().__('Extension status was updated successfully')
2937
  );
2938
- } else {
2939
- getAAM().notification('danger', getAAM().__(response.error));
 
2940
  }
2941
- },
2942
- error: function () {
2943
- getAAM().notification('danger', getAAM().__('Application error'));
2944
- },
2945
- complete: function () {
2946
- getAAM().fetchContent('extensions');
2947
- }
2948
  });
2949
  }
2950
 
@@ -3129,23 +3130,26 @@
3129
  *
3130
  * @param {type} param
3131
  * @param {type} value
3132
- * @param {type} reload
3133
  * @returns {undefined}
3134
  */
3135
  function save(param, value) {
3136
- $.ajax(getLocal().ajaxurl, {
3137
- type: 'POST',
3138
- dataType: 'json',
3139
- data: {
3140
- action: 'aam',
3141
- sub_action: 'Settings_Manager.save',
3142
- _ajax_nonce: getLocal().nonce,
3143
- param: param,
3144
- value: value
3145
- },
3146
- error: function () {
3147
- getAAM().notification('danger', getAAM().__('Application Error'));
3148
- }
 
 
 
 
3149
  });
3150
  }
3151
 
@@ -3174,7 +3178,7 @@
3174
  dataType: 'json',
3175
  data: {
3176
  action: 'aam',
3177
- sub_action: 'Settings_Tools.clear',
3178
  _ajax_nonce: getLocal().nonce
3179
  },
3180
  beforeSend: function() {
@@ -3208,7 +3212,7 @@
3208
  dataType: 'json',
3209
  data: {
3210
  action: 'aam',
3211
- sub_action: 'Settings_Tools.clearCache',
3212
  _ajax_nonce: getLocal().nonce
3213
  },
3214
  beforeSend: function() {
@@ -3234,103 +3238,6 @@
3234
  }
3235
  });
3236
  });
3237
-
3238
- $('#export-aam').bind('click', function () {
3239
- $.ajax(getLocal().ajaxurl, {
3240
- type: 'POST',
3241
- dataType: 'json',
3242
- data: {
3243
- action: 'aam',
3244
- sub_action: 'Settings_Tools.export',
3245
- _ajax_nonce: getLocal().nonce
3246
- },
3247
- beforeSend: function () {
3248
- $('#export-aam').prop('disabled', true);
3249
- $('#export-aam').attr('data-lable', $('#export-aam').text());
3250
- $('#export-aam').text(getAAM().__('Wait...'));
3251
- },
3252
- success: function(response) {
3253
- if (response.status === 'success') {
3254
- download(
3255
- 'data:text/plain;base64,' + response.content,
3256
- 'aam-export.json',
3257
- 'text/plain'
3258
- );
3259
- }
3260
- },
3261
- error: function () {
3262
- getAAM().notification('danger', getAAM().__('Application Error'));
3263
- },
3264
- complete: function () {
3265
- $('#export-aam').prop('disabled', false);
3266
- $('#export-aam').text($('#export-aam').attr('data-lable'));
3267
- }
3268
- });
3269
- });
3270
-
3271
- $('#import-aam').bind('click', function () {
3272
- if (typeof FileReader !== 'undefined') {
3273
- $('#aam-import-file').trigger('click');
3274
- } else {
3275
- getAAM().notification('danger', 'Your browser does not support FileReader functionality');
3276
- }
3277
- });
3278
-
3279
- $('#aam-import-file').bind('change', function () {
3280
- var file = $(this)[0].files[0];
3281
- var json = null;
3282
-
3283
- var reader = new FileReader();
3284
- reader.onload = function(e) {
3285
- json = reader.result;
3286
-
3287
- try {
3288
- //validate the content
3289
- var loaded = JSON.parse(json);
3290
- if (loaded.plugin && loaded.plugin === 'advanced-access-manager') {
3291
- $.ajax(getLocal().ajaxurl, {
3292
- type: 'POST',
3293
- dataType: 'json',
3294
- data: {
3295
- action: 'aam',
3296
- sub_action: 'Settings_Tools.import',
3297
- _ajax_nonce: getLocal().nonce,
3298
- json: json
3299
- },
3300
- beforeSend: function () {
3301
- $('#import-aam').prop('disabled', true);
3302
- $('#import-aam').attr('data-lable', $('#import-aam').text());
3303
- $('#import-aam').text(getAAM().__('Wait...'));
3304
- },
3305
- success: function(response) {
3306
- if (response.status === 'success') {
3307
- getAAM().notification(
3308
- 'success',
3309
- 'All settings were imported successfully'
3310
- );
3311
- location.reload();
3312
- } else {
3313
- getAAM().notification('danger', response.reason);
3314
- }
3315
- },
3316
- error: function () {
3317
- getAAM().notification('danger', getAAM().__('Application Error'));
3318
- },
3319
- complete: function () {
3320
- $('#import-aam').prop('disabled', false);
3321
- $('#import-aam').text($('#import-aam').attr('data-lable'));
3322
- }
3323
- });
3324
- } else {
3325
- throw 'Invalid format';
3326
- }
3327
- } catch (e) {
3328
- getAAM().notification('danger', 'Invalid file format');
3329
- }
3330
- };
3331
- reader.readAsText(file);
3332
-
3333
- });
3334
  }
3335
  }
3336
 
@@ -3390,8 +3297,45 @@
3390
  * Content filters
3391
  */
3392
  this.filters = {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3393
  }
3394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3395
  /**
3396
  *
3397
  * @returns {undefined}
@@ -3428,18 +3372,26 @@
3428
  var object = window.location.search.match(/&oid\=([^&]*)/);
3429
  var type = window.location.search.match(/&otype\=([^&]*)/);
3430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3431
  $.ajax(getLocal().url.site, {
3432
  type: 'POST',
3433
  dataType: 'html',
3434
- data: {
3435
- action: 'aamc',
3436
- _ajax_nonce: getLocal().nonce,
3437
- uiType: view,
3438
- subject: this.getSubject().type,
3439
- subjectId: this.getSubject().id,
3440
- oid: object ? object[1] : null,
3441
- otype: type ? type[1] : null
3442
- },
3443
  beforeSend: function () {
3444
  if ($('#aam-initial-load').length === 0) {
3445
  $('#aam-content').html(
@@ -3656,14 +3608,14 @@
3656
  return (getLocal().translation[label] ? getLocal().translation[label] : label);
3657
  };
3658
 
3659
- /**
3660
- *
3661
- * @param {type} type
3662
- * @param {type} id
3663
- * @param {type} name
3664
- * @param {type} level
3665
- * @returns {undefined}
3666
- */
3667
  AAM.prototype.setSubject = function (type, id, name, level) {
3668
  this.subject = {
3669
  type: type,
@@ -3730,65 +3682,74 @@
3730
  * @param {type} value
3731
  * @param {type} object
3732
  * @param {type} object_id
3733
- * @param {type} successCallback
3734
  * @returns {undefined}
3735
  */
3736
- AAM.prototype.save = function(param, value, object, object_id, successCallback) {
3737
- $.ajax(getLocal().ajaxurl, {
3738
- type: 'POST',
3739
- dataType: 'json',
3740
- data: {
3741
- action: 'aam',
3742
- sub_action: 'save',
3743
- _ajax_nonce: getLocal().nonce,
3744
- subject: this.getSubject().type,
3745
- subjectId: this.getSubject().id,
3746
- param: param,
3747
- value: value,
3748
- object: object,
3749
- objectId: object_id
3750
- },
3751
- success: function (response) {
3752
- if (typeof successCallback === 'function') {
3753
- successCallback(response);
 
 
 
 
 
 
 
3754
  }
3755
- },
3756
- error: function () {
3757
- getAAM().notification('danger', getAAM().__('Application error'));
3758
- }
3759
  });
3760
  };
3761
 
3762
  /**
3763
  *
3764
  * @param {type} object
 
3765
  * @returns {undefined}
3766
  */
3767
  AAM.prototype.reset = function(object, btn) {
3768
- $.ajax(getLocal().ajaxurl, {
3769
- type: 'POST',
3770
- data: {
3771
- action: 'aam',
3772
- sub_action: 'reset',
3773
- _ajax_nonce: getLocal().nonce,
3774
- subject: this.getSubject().type,
3775
- subjectId: this.getSubject().id,
3776
- object: object
3777
- },
3778
- beforeSend: function() {
3779
- var label = btn.text();
3780
- btn.attr('data-original-label', label);
3781
- btn.text(getAAM().__('Resetting...'));
3782
- },
3783
- success: function () {
3784
- getAAM().fetchContent('main');
3785
- },
3786
- error: function () {
3787
- getAAM().notification('danger', getAAM().__('Application error'));
3788
- },
3789
- complete: function() {
3790
- btn.text(btn.attr('data-original-label'));
3791
- }
 
 
 
 
3792
  });
3793
  };
3794
 
185
  },
186
  createdRow: function (row, data) {
187
  if (isCurrent(data[0])) {
188
+ $('td:eq(0)', row).html(
189
+ '<strong class="aam-highlight">' + data[2] + '</strong>'
190
+ );
191
  } else {
192
  $('td:eq(0)', row).html('<span>' + data[2] + '</span>');
193
  }
534
  highlight.replaceWith($('<span/>').text(highlight.text()));
535
  }
536
  });
 
 
537
  });
538
 
539
  //in case interface needed to be reloaded
888
  case 'no-switch':
889
  if (!getAAM().isUI()) {
890
  $(container).append($('<i/>', {
891
+ 'class': 'aam-row-action icon-exchange text-muted'
892
  }));
893
  }
894
  break;
1029
  highlight.replaceWith('<span>' + highlight.text() + '</span>');
1030
  }
1031
  });
 
 
1032
  });
1033
 
1034
  //in case interface needed to be reloaded
1071
  );
1072
  });
1073
  }
 
 
1074
  });
1075
  });
1076
 
1130
  * @returns {undefined}
1131
  */
1132
  function save(items, status, successCallback) {
1133
+ getAAM().queueRequest(function() {
1134
+ $.ajax(getLocal().ajaxurl, {
1135
+ type: 'POST',
1136
+ dataType: 'json',
1137
+ data: {
1138
+ action: 'aam',
1139
+ sub_action: 'Main_Menu.save',
1140
+ subject: getAAM().getSubject().type,
1141
+ subjectId: getAAM().getSubject().id,
1142
+ _ajax_nonce: getLocal().nonce,
1143
+ items: items,
1144
+ status: status
1145
+ },
1146
+ success: function(response) {
1147
+ successCallback(response);
1148
+ },
1149
+ error: function () {
1150
+ getAAM().notification(
1151
+ 'danger', getAAM().__('Application Error')
1152
+ );
1153
+ }
1154
+ });
1155
  });
1156
  }
1157
 
1257
  * @returns {undefined}
1258
  */
1259
  function save(items, status, successCallback) {
1260
+ getAAM().queueRequest(function() {
1261
+ $.ajax(getLocal().ajaxurl, {
1262
+ type: 'POST',
1263
+ dataType: 'json',
1264
+ data: {
1265
+ action: 'aam',
1266
+ sub_action: 'Main_Toolbar.save',
1267
+ subject: getAAM().getSubject().type,
1268
+ subjectId: getAAM().getSubject().id,
1269
+ _ajax_nonce: getLocal().nonce,
1270
+ items: items,
1271
+ status: status
1272
+ },
1273
+ success: function(response) {
1274
+ successCallback(response);
1275
+ },
1276
+ error: function () {
1277
+ getAAM().notification(
1278
+ 'danger', getAAM().__('Application Error')
1279
+ );
1280
+ }
1281
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1282
  });
1283
  }
1284
 
1333
  });
1334
  });
1335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1336
  //reset button
1337
  $('#toolbar-reset').bind('click', function () {
1338
  getAAM().reset('toolbar', $(this));
1555
  } else {
1556
  if (granted) {
1557
  getAAM().notification(
1558
+ 'danger',
1559
+ getAAM().__('WordPress core does not allow to grant this capability')
1560
  );
1561
  $(btn).attr('class', 'aam-row-action text-muted icon-check-empty');
1562
  } else {
1630
  $('#edit-capability-modal').modal('show');
1631
  }));
1632
  break;
1633
+
1634
+ case 'no-edit':
1635
+ $(container).append($('<i/>', {
1636
+ 'class': 'aam-row-action icon-pencil text-muted'
1637
+ }));
1638
+ break;
1639
 
1640
  case 'delete':
1641
  $(container).append($('<i/>', {
1650
  $('#delete-capability-modal').modal('show');
1651
  }));
1652
  break;
1653
+
1654
+ case 'no-delete':
1655
+ $(container).append($('<i/>', {
1656
+ 'class': 'aam-row-action icon-trash-empty text-muted'
1657
+ }));
1658
+ break;
1659
 
1660
  default:
1661
  getAAM().triggerHook('decorate-capability-row', {
1859
  * @param {*} successCallback
1860
  */
1861
  function save(param, value, object, object_id, successCallback) {
1862
+ getAAM().queueRequest(function() {
1863
+ $.ajax(getLocal().ajaxurl, {
1864
+ type: 'POST',
1865
+ dataType: 'json',
1866
+ data: {
1867
+ action: 'aam',
1868
+ sub_action: 'Main_Post.save',
1869
+ _ajax_nonce: getLocal().nonce,
1870
+ subject: getAAM().getSubject().type,
1871
+ subjectId: getAAM().getSubject().id,
1872
+ param: param,
1873
+ value: value,
1874
+ object: object,
1875
+ objectId: object_id
1876
+ },
1877
+ success: function (response) {
1878
+ if (response.status === 'failure') {
1879
+ getAAM().notification('danger', response.error);
1880
+ } else {
1881
+ $('#post-overwritten').removeClass('hidden');
1882
+ //add some specific attributes to reset button
1883
+ $('#post-reset').attr({
1884
+ 'data-type': object,
1885
+ 'data-id': object_id
1886
+ });
1887
+ }
1888
+ successCallback(response);
1889
+ },
1890
+ error: function () {
1891
+ getAAM().notification(
1892
+ 'danger', getAAM().__('Application error')
1893
+ );
1894
  }
1895
+ });
 
 
 
 
1896
  });
1897
  }
1898
 
1942
  $(this).unbind('click').bind('click', function () {
1943
  var _this = $(this);
1944
  var checked = !_this.hasClass('icon-check');
1945
+ var value = (checked ? 1 : 0);
1946
 
1947
  _this.attr('class', 'aam-row-action icon-spin4 animate-spin');
1948
  save(
1949
  _this.data('property'),
1950
+ value,
1951
  object,
1952
  id,
1953
  function(response) {
1964
  }
1965
  }
1966
  );
1967
+
1968
+ if ($(this).data('trigger') && value) {
1969
+ $('#' + $(this).data('trigger')).trigger('click');
1970
+ }
1971
  });
1972
  });
1973
+
1974
+ $('.advanced-post-option').each(function() {
1975
+ $(this).bind('click', function() {
1976
+ var container = $(this).attr('href');
1977
+ var option = objectAccess.access[$(this).data('ref')];
1978
+ var field = $($('.extended-post-access-btn', container).data('field'));
1979
+
1980
+ //add attributes to the .extended-post-access-btn
1981
+ $('.extended-post-access-btn', container).attr({
1982
+ 'data-ref': $(this).attr('data-ref'),
1983
+ 'data-preview': $(this).attr('data-preview')
1984
+ });
1985
+
1986
+ //set field value
1987
+ field.val(option);
1988
+ });
1989
+ });
1990
 
1991
  $.ajax(getLocal().ajaxurl, {
1992
  type: 'POST',
2249
  'title': getAAM().__('Edit')
2250
  }));
2251
  break;
2252
+
2253
+ case 'no-edit' :
2254
+ $(container).append($('<i/>', {
2255
+ 'class': 'aam-row-action text-muted icon-pencil'
2256
+ }));
2257
+ break;
2258
 
2259
  default:
2260
  getAAM().triggerHook('post-action', {
2333
  );
2334
  }
2335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2336
  $('.extended-post-access-btn').each(function() {
2337
  $(this).bind('click', function() {
2338
  var _this = $(this);
2653
  * @returns {undefined}
2654
  */
2655
  function save(param, value) {
2656
+ getAAM().queueRequest(function() {
2657
+ $.ajax(getLocal().ajaxurl, {
2658
+ type: 'POST',
2659
+ dataType: 'json',
2660
+ data: {
2661
+ action: 'aam',
2662
+ sub_action: 'Main_404Redirect.save',
2663
+ _ajax_nonce: getLocal().nonce,
2664
+ subject: getAAM().getSubject().type,
2665
+ subjectId: getAAM().getSubject().id,
2666
+ param: param,
2667
+ value: value
2668
+ },
2669
+ error: function () {
2670
+ getAAM().notification(
2671
+ 'danger', getAAM().__('Application error')
2672
+ );
2673
+ }
2674
+ });
2675
  });
2676
  }
2677
 
2727
  * @param {type} btn
2728
  * @returns {undefined}
2729
  */
2730
+ function save(type, route, method, btn) {
2731
+ var value = $(btn).hasClass('icon-check-empty') ? 1 : 0;
 
2732
 
2733
+ getAAM().queueRequest(function() {
2734
+ //show indicator
2735
+ $(btn).attr('class', 'aam-row-action icon-spin4 animate-spin');
2736
+
2737
+ $.ajax(getLocal().ajaxurl, {
2738
+ type: 'POST',
2739
+ dataType: 'json',
2740
+ data: {
2741
+ action: 'aam',
2742
+ sub_action: 'Main_Route.save',
2743
+ _ajax_nonce: getLocal().nonce,
2744
+ subject: getAAM().getSubject().type,
2745
+ subjectId: getAAM().getSubject().id,
2746
+ type: type,
2747
+ route: route,
2748
+ method: method,
2749
+ value: value
2750
+ },
2751
+ success: function (response) {
2752
+ if (response.status === 'failure') {
2753
+ getAAM().notification('danger', response.error);
2754
+ updateBtn(btn, value ? 0 : 1);
2755
+ } else {
2756
+ $('#aam-route-overwrite').removeClass('hidden');
2757
+ updateBtn(btn, value);
2758
+ }
2759
+ },
2760
+ error: function () {
2761
  updateBtn(btn, value ? 0 : 1);
2762
+ getAAM().notification(
2763
+ 'danger', getAAM().__('Application error')
2764
+ );
2765
  }
2766
+ });
 
 
 
 
2767
  });
2768
  }
2769
 
2838
  $(container).append($('<i/>', {
2839
  'class': 'aam-row-action text-muted icon-check-empty'
2840
  }).bind('click', function () {
2841
+ save(data[0], data[2], data[1], this);
2842
  }));
2843
  break;
2844
 
2846
  $(container).append($('<i/>', {
2847
  'class': 'aam-row-action text-danger icon-check'
2848
  }).bind('click', function () {
2849
+ save(data[0], data[2], data[1], this);
2850
  }));
2851
  break;
2852
 
2920
  * @returns {undefined}
2921
  */
2922
  function updateStatus(data) {
2923
+ getAAM().queueRequest(function() {
2924
+ $.ajax(getLocal().ajaxurl, {
2925
+ type: 'POST',
2926
+ dataType: 'json',
2927
+ data: data,
2928
+ success: function (response) {
2929
+ if (response.status === 'success') {
2930
+ getAAM().notification(
2931
+ 'success',
2932
+ getAAM().__('Extension status was updated successfully')
2933
+ );
2934
+ } else {
2935
+ getAAM().notification(
2936
+ 'danger', getAAM().__(response.error)
2937
+ );
2938
+ }
2939
+ },
2940
+ error: function () {
2941
  getAAM().notification(
2942
+ 'danger', getAAM().__('Application error')
 
2943
  );
2944
+ },
2945
+ complete: function () {
2946
+ getAAM().fetchContent('extensions');
2947
  }
2948
+ });
 
 
 
 
 
 
2949
  });
2950
  }
2951
 
3130
  *
3131
  * @param {type} param
3132
  * @param {type} value
 
3133
  * @returns {undefined}
3134
  */
3135
  function save(param, value) {
3136
+ getAAM().queueRequest(function() {
3137
+ $.ajax(getLocal().ajaxurl, {
3138
+ type: 'POST',
3139
+ dataType: 'json',
3140
+ data: {
3141
+ action: 'aam',
3142
+ sub_action: 'Settings_Manager.save',
3143
+ _ajax_nonce: getLocal().nonce,
3144
+ param: param,
3145
+ value: value
3146
+ },
3147
+ error: function () {
3148
+ getAAM().notification(
3149
+ 'danger', getAAM().__('Application Error')
3150
+ );
3151
+ }
3152
+ });
3153
  });
3154
  }
3155
 
3178
  dataType: 'json',
3179
  data: {
3180
  action: 'aam',
3181
+ sub_action: 'clearSettings',
3182
  _ajax_nonce: getLocal().nonce
3183
  },
3184
  beforeSend: function() {
3212
  dataType: 'json',
3213
  data: {
3214
  action: 'aam',
3215
+ sub_action: 'clearCache',
3216
  _ajax_nonce: getLocal().nonce
3217
  },
3218
  beforeSend: function() {
3238
  }
3239
  });
3240
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3241
  }
3242
  }
3243
 
3297
  * Content filters
3298
  */
3299
  this.filters = {};
3300
+
3301
+ /**
3302
+ * Request queue
3303
+ */
3304
+ this.queue = {
3305
+ requests: [],
3306
+ processing: false
3307
+ };
3308
+
3309
+ /**
3310
+ *
3311
+ * @type AAM
3312
+ */
3313
+ var _this = this;
3314
+
3315
+ $(document).ajaxComplete(function() {
3316
+ _this.queue.processing = false;
3317
+
3318
+ if (_this.queue.requests.length > 0) {
3319
+ _this.queue.processing = true;
3320
+ _this.queue.requests.shift().call(_this);
3321
+ }
3322
+ });
3323
  }
3324
 
3325
+ /**
3326
+ *
3327
+ * @param {type} request
3328
+ * @returns {undefined}
3329
+ */
3330
+ AAM.prototype.queueRequest = function(request) {
3331
+ this.queue.requests.push(request);
3332
+
3333
+ if (this.queue.processing === false) {
3334
+ this.queue.processing = true;
3335
+ this.queue.requests.shift().call(this);
3336
+ }
3337
+ };
3338
+
3339
  /**
3340
  *
3341
  * @returns {undefined}
3372
  var object = window.location.search.match(/&oid\=([^&]*)/);
3373
  var type = window.location.search.match(/&otype\=([^&]*)/);
3374
 
3375
+ var data = {
3376
+ action: 'aamc',
3377
+ _ajax_nonce: getLocal().nonce,
3378
+ uiType: view,
3379
+ subject: this.getSubject().type,
3380
+ subjectId: this.getSubject().id,
3381
+ oid: object ? object[1] : null,
3382
+ otype: type ? type[1] : null
3383
+ };
3384
+
3385
+ if (!getAAM().isUI() && (typeof aamEnvData !== 'undefined')) {
3386
+ data.menu = aamEnvData.menu;
3387
+ data.submenu = aamEnvData.submenu;
3388
+ data.toolbar = aamEnvData.toolbar;
3389
+ }
3390
+
3391
  $.ajax(getLocal().url.site, {
3392
  type: 'POST',
3393
  dataType: 'html',
3394
+ data: data,
 
 
 
 
 
 
 
 
3395
  beforeSend: function () {
3396
  if ($('#aam-initial-load').length === 0) {
3397
  $('#aam-content').html(
3608
  return (getLocal().translation[label] ? getLocal().translation[label] : label);
3609
  };
3610
 
3611
+ /**
3612
+ *
3613
+ * @param {type} type
3614
+ * @param {type} id
3615
+ * @param {type} name
3616
+ * @param {type} level
3617
+ * @returns {undefined}
3618
+ */
3619
  AAM.prototype.setSubject = function (type, id, name, level) {
3620
  this.subject = {
3621
  type: type,
3682
  * @param {type} value
3683
  * @param {type} object
3684
  * @param {type} object_id
3685
+ * @param {type} callback
3686
  * @returns {undefined}
3687
  */
3688
+ AAM.prototype.save = function(param, value, object, object_id, callback) {
3689
+ getAAM().queueRequest(function() {
3690
+ $.ajax(getLocal().ajaxurl, {
3691
+ type: 'POST',
3692
+ dataType: 'json',
3693
+ data: {
3694
+ action: 'aam',
3695
+ sub_action: 'save',
3696
+ _ajax_nonce: getLocal().nonce,
3697
+ subject: this.getSubject().type,
3698
+ subjectId: this.getSubject().id,
3699
+ param: param,
3700
+ value: value,
3701
+ object: object,
3702
+ objectId: object_id
3703
+ },
3704
+ success: function (response) {
3705
+ if (typeof callback === 'function') {
3706
+ callback(response);
3707
+ }
3708
+ },
3709
+ error: function () {
3710
+ getAAM().notification(
3711
+ 'danger', getAAM().__('Application error')
3712
+ );
3713
  }
3714
+ });
 
 
 
3715
  });
3716
  };
3717
 
3718
  /**
3719
  *
3720
  * @param {type} object
3721
+ * @param {type} btn
3722
  * @returns {undefined}
3723
  */
3724
  AAM.prototype.reset = function(object, btn) {
3725
+ getAAM().queueRequest(function() {
3726
+ $.ajax(getLocal().ajaxurl, {
3727
+ type: 'POST',
3728
+ data: {
3729
+ action: 'aam',
3730
+ sub_action: 'reset',
3731
+ _ajax_nonce: getLocal().nonce,
3732
+ subject: this.getSubject().type,
3733
+ subjectId: this.getSubject().id,
3734
+ object: object
3735
+ },
3736
+ beforeSend: function() {
3737
+ var label = btn.text();
3738
+ btn.attr('data-original-label', label);
3739
+ btn.text(getAAM().__('Resetting...'));
3740
+ },
3741
+ success: function () {
3742
+ getAAM().fetchContent('main');
3743
+ },
3744
+ error: function () {
3745
+ getAAM().notification(
3746
+ 'danger', getAAM().__('Application error')
3747
+ );
3748
+ },
3749
+ complete: function() {
3750
+ btn.text(btn.attr('data-original-label'));
3751
+ }
3752
+ });
3753
  });
3754
  };
3755
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: vasyltech,noelalvarez
3
  Tags: access control, membership, backend menu, user role, restricted content
4
  Requires at least: 4.0
5
  Tested up to: 4.9.7
6
- Stable tag: 5.4.3.2
7
 
8
  All you need to manage access to you WordPress websites on frontend, backend and API levels for any role, user or visitors.
9
 
@@ -53,6 +53,7 @@ https://www.youtube.com/watch?v=mj5Xa_Wc16Y
53
  * [paid] Manage access based on IP address or referred domain. Manage access to your website for all visitors based on referred host or IP address. Find out more from [How to manage access to WordPress website by IP address](https://aamplugin.com/help/how-to-manage-access-to-wordpress-website-by-ip-address) article;
54
  * [paid] Monetize access to you content. Start selling access to your website content with premium [E-Commerce](https://aamplugin.com/extension/ecommerce) extension. Find out more from [How to monetize access to the WordPress content](https://aamplugin.com/help/how-to-monetize-access-to-the-wordpress-content) article;
55
  * [free] Multisite support. Sync access settings across your network or even restrict none-members from accessing one of your sites. Find out more from [AAM and WordPress Multisite support](https://aamplugin.com/help/aam-and-wordpress-multisite-support);
 
56
  * [and even more...] Check our [help page](https://aamplugin.com/help) to learn more about AAM
57
 
58
  == Installation ==
@@ -76,6 +77,22 @@ https://www.youtube.com/watch?v=mj5Xa_Wc16Y
76
 
77
  == Changelog ==
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  = 5.4.3.2 =
80
  * Fixed bug that incorrectly checks post author property
81
  * Fixed bug that does not allow to assign roles that contain apostrophe
3
  Tags: access control, membership, backend menu, user role, restricted content
4
  Requires at least: 4.0
5
  Tested up to: 4.9.7
6
+ Stable tag: 5.5
7
 
8
  All you need to manage access to you WordPress websites on frontend, backend and API levels for any role, user or visitors.
9
 
53
  * [paid] Manage access based on IP address or referred domain. Manage access to your website for all visitors based on referred host or IP address. Find out more from [How to manage access to WordPress website by IP address](https://aamplugin.com/help/how-to-manage-access-to-wordpress-website-by-ip-address) article;
54
  * [paid] Monetize access to you content. Start selling access to your website content with premium [E-Commerce](https://aamplugin.com/extension/ecommerce) extension. Find out more from [How to monetize access to the WordPress content](https://aamplugin.com/help/how-to-monetize-access-to-the-wordpress-content) article;
55
  * [free] Multisite support. Sync access settings across your network or even restrict none-members from accessing one of your sites. Find out more from [AAM and WordPress Multisite support](https://aamplugin.com/help/aam-and-wordpress-multisite-support);
56
+ * [free] Multiple role support. Finally AAM supports multiple roles per user [WordPress access control for users with multiple roles](https://aamplugin.com/article/wordpress-access-control-for-users-with-multiple-roles)
57
  * [and even more...] Check our [help page](https://aamplugin.com/help) to learn more about AAM
58
 
59
  == Installation ==
77
 
78
  == Changelog ==
79
 
80
+ = 5.5 =
81
+ * Fixed the bug with EDIT BY OTHERS option
82
+ * Fixed UI bug when managing access to AAM page itself
83
+ * Fixed the bug reported by https://github.com/KenAer
84
+ * Fixed the bug with creating new post when default access is denied to EDIT
85
+ * Fixed the bug with editing page that is in draft state
86
+ * Fixed multiple bugs with AAM export/import feature
87
+ * Fixed the bug with blocked user being able to login again
88
+ * Slightly improved extension installation feedback
89
+ * Improved UI
90
+ * Enhanced JWT token feature
91
+ * Improved the way Backend Menu and Toolbar features work
92
+ * Added multiple-roles support
93
+ * Refactored Import/Export features
94
+ * Removed Settings->Tools tab
95
+
96
  = 5.4.3.2 =
97
  * Fixed bug that incorrectly checks post author property
98
  * Fixed bug that does not allow to assign roles that contain apostrophe