Version Description
- Fixed Bug: Access policy was not applied to visitors
- Fixed Bug: Bug fixing that is related to unwanted PHP notices https://forum.aamplugin.com/d/456-notice-undefined-index-expire
- Fixed Bug: Failing to delete multiple Access URI rules without reloading the page
- Added New: Ability to generate Access Policy from user's or role's settings https://forum.aamplugin.com/d/446-announcement-about-upcoming-features/2
- Added New: More granular control over the HIDDEN access option https://forum.aamplugin.com/d/446-announcement-about-upcoming-features
- Added New: Export/Import AAM settings https://aamplugin.com/article/how-to-export-and-import-aam-settings
- Added New: Ability to send support request from the AAM UI
- Added New: Multisite Settings Sync service that allows to sync access settings changes across all sites
- Added New: New hook
aam_updated_access_settings
that is triggered when access settings are stored - Added New: New data type casting (*date) for Access Policy https://aamplugin.com/reference/policy#markers
- Added New: New POLICY_PARAM access policy token https://aamplugin.com/reference/policy#policy_param
- Added New: New WP_SITE access policy token https://aamplugin.com/reference/policy#wp_site
- Change: DATETIME access policy token returns time in UTC timezone
- Change: Enhanced security over AAM UI
- Change: Multiple internal simplifications and refactoring
Download this release
Release Info
Developer | vasyltech |
Plugin | Advanced Access Manager |
Version | 6.2.0 |
Comparing to | |
See all releases |
Code changes from version 6.1.1 to 6.2.0
- aam.php +2 -2
- application/Addon/Repository.php +13 -7
- application/Backend/Feature/Main/Policy.php +189 -21
- application/Backend/Feature/Main/Post.php +88 -6
- application/Backend/Feature/Settings/Manager.php +147 -3
- application/Backend/Manager.php +8 -3
- application/Backend/Subject.php +22 -7
- application/Backend/View/Localization.php +10 -4
- application/Backend/View/PostOptionList.php +10 -4
- application/Backend/tmpl/metabox/main-iframe.php +95 -4
- application/Backend/tmpl/metabox/policy-metabox.php +3 -2
- application/Backend/tmpl/page/addon-panel.php +3 -2
- application/Backend/tmpl/page/current-subject.php +13 -1
- application/Backend/tmpl/page/subject-panel.php +9 -2
- application/Backend/tmpl/partial/post-access-form.php +74 -13
- application/Backend/tmpl/service/policy.php +68 -1
- application/Core/AccessSettings.php +13 -5
- application/Core/Policy/Condition.php +23 -4
- application/Core/Policy/Generator.php +505 -0
- application/Core/Policy/Manager.php +24 -10
- application/Core/Policy/Token.php +75 -6
- application/Core/Policy/Validator.php +63 -25
- application/Migration/2019_06_30-base.php +13 -5
- application/Migration/2019_12_01-base.php +9 -5
- application/Migration/{2019_12_16-base.php → 2019_12_19-base.php} +4 -4
- application/Service/AccessPolicy.php +29 -5
- application/Service/Content.php +65 -15
- application/Service/Multisite.php +191 -0
- lang/advanced-access-manager-en_US.po +577 -333
- media/css/aam.css +39 -3
- media/font/fontello.eot +0 -0
- media/font/fontello.svg +6 -2
- media/font/fontello.ttf +0 -0
- media/font/fontello.woff +0 -0
- media/font/fontello.woff2 +0 -0
- media/js/aam.js +534 -102
- readme.txt +19 -2
aam.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
/**
|
4 |
* Plugin Name: Advanced Access Manager
|
5 |
* Description: Collection of features to manage your WordPress website authentication, authorization and monitoring
|
6 |
-
* Version: 6.
|
7 |
* Author: Vasyl Martyniuk <vasyl@vasyltech.com>
|
8 |
* Author URI: https://vasyltech.com
|
9 |
* Text Domain: advanced-access-manager
|
@@ -264,7 +264,7 @@ if (defined('ABSPATH')) {
|
|
264 |
//define few common constants
|
265 |
define('AAM_MEDIA', plugins_url('/media', __FILE__));
|
266 |
define('AAM_KEY', 'advanced-access-manager');
|
267 |
-
define('AAM_VERSION', '6.
|
268 |
define('AAM_BASEDIR', __DIR__);
|
269 |
|
270 |
//load vendor
|
3 |
/**
|
4 |
* Plugin Name: Advanced Access Manager
|
5 |
* Description: Collection of features to manage your WordPress website authentication, authorization and monitoring
|
6 |
+
* Version: 6.2.0
|
7 |
* Author: Vasyl Martyniuk <vasyl@vasyltech.com>
|
8 |
* Author URI: https://vasyltech.com
|
9 |
* Text Domain: advanced-access-manager
|
264 |
//define few common constants
|
265 |
define('AAM_MEDIA', plugins_url('/media', __FILE__));
|
266 |
define('AAM_KEY', 'advanced-access-manager');
|
267 |
+
define('AAM_VERSION', '6.2.0');
|
268 |
define('AAM_BASEDIR', __DIR__);
|
269 |
|
270 |
//load vendor
|
application/Addon/Repository.php
CHANGED
@@ -10,12 +10,13 @@
|
|
10 |
/**
|
11 |
* Addon repository
|
12 |
*
|
|
|
13 |
* @since 6.0.5 Refactored the license managements. Fixed couple bugs with license
|
14 |
* information displaying
|
15 |
* @since 6.0.0 Initial implementation of the class
|
16 |
*
|
17 |
* @package AAM
|
18 |
-
* @version 6.0
|
19 |
*/
|
20 |
class AAM_Addon_Repository
|
21 |
{
|
@@ -276,17 +277,19 @@ class AAM_Addon_Repository
|
|
276 |
*
|
277 |
* @return string|null
|
278 |
*
|
|
|
|
|
279 |
* @since 6.0.5 Fixed typo in the property name
|
280 |
* @since 6.0.0 Initial implementation of the method
|
281 |
*
|
282 |
* @access protected
|
283 |
-
* @version 6.0
|
284 |
*/
|
285 |
protected function getExpirationDate($plugin)
|
286 |
{
|
287 |
-
$
|
288 |
|
289 |
-
return (isset($
|
290 |
}
|
291 |
|
292 |
/**
|
@@ -296,14 +299,17 @@ class AAM_Addon_Repository
|
|
296 |
*
|
297 |
* @return string|null
|
298 |
*
|
|
|
|
|
|
|
299 |
* @access protected
|
300 |
-
* @version 6.
|
301 |
*/
|
302 |
protected function getPluginLicense($plugin)
|
303 |
{
|
304 |
-
$
|
305 |
|
306 |
-
return (isset($
|
307 |
}
|
308 |
|
309 |
}
|
10 |
/**
|
11 |
* Addon repository
|
12 |
*
|
13 |
+
* @since 6.2.0 Bug fixing that is related to unwanted PHP notices
|
14 |
* @since 6.0.5 Refactored the license managements. Fixed couple bugs with license
|
15 |
* information displaying
|
16 |
* @since 6.0.0 Initial implementation of the class
|
17 |
*
|
18 |
* @package AAM
|
19 |
+
* @version 6.2.0
|
20 |
*/
|
21 |
class AAM_Addon_Repository
|
22 |
{
|
277 |
*
|
278 |
* @return string|null
|
279 |
*
|
280 |
+
* @since 6.2.0 Fixed bug with PHP notice when `expire` is not defined
|
281 |
+
* @since 6.0.0 Initial implementation of the method
|
282 |
* @since 6.0.5 Fixed typo in the property name
|
283 |
* @since 6.0.0 Initial implementation of the method
|
284 |
*
|
285 |
* @access protected
|
286 |
+
* @version 6.2.0
|
287 |
*/
|
288 |
protected function getExpirationDate($plugin)
|
289 |
{
|
290 |
+
$r = $this->getRegistry();
|
291 |
|
292 |
+
return (isset($r[$plugin]['expire']) ? $r[$plugin]['expire'] : null);
|
293 |
}
|
294 |
|
295 |
/**
|
299 |
*
|
300 |
* @return string|null
|
301 |
*
|
302 |
+
* @since 6.2.0 Fixed bug with PHP notice when `license` is not defined
|
303 |
+
* @since 6.0.0 Initial implementation of the method
|
304 |
+
*
|
305 |
* @access protected
|
306 |
+
* @version 6.2.0
|
307 |
*/
|
308 |
protected function getPluginLicense($plugin)
|
309 |
{
|
310 |
+
$r = $this->getRegistry();
|
311 |
|
312 |
+
return (isset($r[$plugin]['license']) ? $r[$plugin]['license'] : null);
|
313 |
}
|
314 |
|
315 |
}
|
application/Backend/Feature/Main/Policy.php
CHANGED
@@ -10,11 +10,12 @@
|
|
10 |
/**
|
11 |
* Access Policy UI manager
|
12 |
*
|
|
|
13 |
* @since 6.1.0 Fixed bug with "Attach to Default" button
|
14 |
* @since 6.0.0 Initial implementation of the class
|
15 |
*
|
16 |
* @package AAM
|
17 |
-
* @version 6.
|
18 |
*/
|
19 |
class AAM_Backend_Feature_Main_Policy
|
20 |
extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAware
|
@@ -48,12 +49,13 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
48 |
*
|
49 |
* @return void
|
50 |
*
|
|
|
51 |
* @since 6.1.0 Fixed the bug where "Attach to Default" button was not showing at
|
52 |
* all
|
53 |
* @since 6.0.0 Initial implementation of the method
|
54 |
*
|
55 |
* @access public
|
56 |
-
* @version 6.
|
57 |
*/
|
58 |
public function __construct()
|
59 |
{
|
@@ -82,6 +84,19 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
82 |
|
83 |
return $content;
|
84 |
}, 10, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
}
|
86 |
|
87 |
/**
|
@@ -161,16 +176,15 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
161 |
*
|
162 |
* @return string
|
163 |
*
|
|
|
|
|
|
|
164 |
* @access public
|
165 |
-
* @version 6.
|
166 |
*/
|
167 |
public function getTable()
|
168 |
{
|
169 |
-
$list =
|
170 |
-
'post_type' => AAM_Service_AccessPolicy::POLICY_CPT,
|
171 |
-
'numberposts' => -1,
|
172 |
-
'post_status' => 'publish'
|
173 |
-
));
|
174 |
|
175 |
$response = array(
|
176 |
'recordsTotal' => count($list),
|
@@ -187,7 +201,8 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
187 |
$record->ID,
|
188 |
$this->preparePolicyTitle($record),
|
189 |
$this->preparePolicyActionList($record),
|
190 |
-
get_edit_post_link($record->ID, 'link')
|
|
|
191 |
);
|
192 |
}
|
193 |
}
|
@@ -202,15 +217,26 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
202 |
*
|
203 |
* @return string
|
204 |
*
|
|
|
|
|
|
|
205 |
* @access protected
|
206 |
-
* @version 6.
|
207 |
*/
|
208 |
protected function preparePolicyTitle($record)
|
209 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
if (!empty($record->post_title)) {
|
211 |
-
$title
|
212 |
} else {
|
213 |
-
$title
|
214 |
}
|
215 |
|
216 |
$title .= '<br/>';
|
@@ -229,8 +255,11 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
229 |
*
|
230 |
* @return string
|
231 |
*
|
|
|
|
|
|
|
232 |
* @access protected
|
233 |
-
* @version 6.
|
234 |
*/
|
235 |
protected function preparePolicyActionList($record)
|
236 |
{
|
@@ -241,7 +270,8 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
241 |
|
242 |
$actions = array(
|
243 |
$policy->has($record->ID) ? "detach" : "attach",
|
244 |
-
$post->isAllowedTo('edit') ? 'edit' : 'no-edit'
|
|
|
245 |
);
|
246 |
|
247 |
return implode(',', $actions);
|
@@ -252,8 +282,11 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
252 |
*
|
253 |
* @return string
|
254 |
*
|
|
|
|
|
|
|
255 |
* @access public
|
256 |
-
* @version 6.
|
257 |
*/
|
258 |
public function save()
|
259 |
{
|
@@ -262,19 +295,154 @@ extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAwar
|
|
262 |
$id = $this->getFromPost('id');
|
263 |
$effect = $this->getFromPost('effect', FILTER_VALIDATE_BOOLEAN);
|
264 |
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
} else {
|
270 |
-
$
|
271 |
}
|
272 |
|
273 |
return wp_json_encode(array(
|
274 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
));
|
276 |
}
|
277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
/**
|
279 |
* Get default Access Policy
|
280 |
*
|
10 |
/**
|
11 |
* Access Policy UI manager
|
12 |
*
|
13 |
+
* @since 6.2.0 Added ability to generate Access Policy
|
14 |
* @since 6.1.0 Fixed bug with "Attach to Default" button
|
15 |
* @since 6.0.0 Initial implementation of the class
|
16 |
*
|
17 |
* @package AAM
|
18 |
+
* @version 6.2.0
|
19 |
*/
|
20 |
class AAM_Backend_Feature_Main_Policy
|
21 |
extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAware
|
49 |
*
|
50 |
* @return void
|
51 |
*
|
52 |
+
* @since 6.2.0 Registering a new action to allow the Access Policy generation
|
53 |
* @since 6.1.0 Fixed the bug where "Attach to Default" button was not showing at
|
54 |
* all
|
55 |
* @since 6.0.0 Initial implementation of the method
|
56 |
*
|
57 |
* @access public
|
58 |
+
* @version 6.2.0
|
59 |
*/
|
60 |
public function __construct()
|
61 |
{
|
84 |
|
85 |
return $content;
|
86 |
}, 10, 2);
|
87 |
+
|
88 |
+
// Hook into Users/Roles Manager and add new action
|
89 |
+
if (current_user_can(AAM_Backend_Feature_Main_Policy::ACCESS_CAPABILITY)) {
|
90 |
+
add_filter('aam_top_subject_actions_filter', function($actions) {
|
91 |
+
$actions[] = array(
|
92 |
+
'icon' => 'icon-file-code',
|
93 |
+
'id' => 'generate-access-policy',
|
94 |
+
'tooltip' => __('Generate Access Policy', AAM_KEY)
|
95 |
+
);
|
96 |
+
|
97 |
+
return $actions;
|
98 |
+
});
|
99 |
+
}
|
100 |
}
|
101 |
|
102 |
/**
|
176 |
*
|
177 |
* @return string
|
178 |
*
|
179 |
+
* @since 6.2.0 Changed the way, all the policies are fetched
|
180 |
+
* @since 6.0.0 Initial implementation of the method
|
181 |
+
*
|
182 |
* @access public
|
183 |
+
* @version 6.2.0
|
184 |
*/
|
185 |
public function getTable()
|
186 |
{
|
187 |
+
$list = AAM::api()->getAccessPolicyManager()->fetchPolicies();
|
|
|
|
|
|
|
|
|
188 |
|
189 |
$response = array(
|
190 |
'recordsTotal' => count($list),
|
201 |
$record->ID,
|
202 |
$this->preparePolicyTitle($record),
|
203 |
$this->preparePolicyActionList($record),
|
204 |
+
get_edit_post_link($record->ID, 'link'),
|
205 |
+
(!empty($record->post_title) ? $record->post_title : $record->ID)
|
206 |
);
|
207 |
}
|
208 |
}
|
217 |
*
|
218 |
* @return string
|
219 |
*
|
220 |
+
* @since 6.2.0 Added new "icon-attention" if policy has error/warning
|
221 |
+
* @since 6.0.0 Initial implementation of the method
|
222 |
+
*
|
223 |
* @access protected
|
224 |
+
* @version 6.2.0
|
225 |
*/
|
226 |
protected function preparePolicyTitle($record)
|
227 |
{
|
228 |
+
$errors = (new AAM_Core_Policy_Validator($record->post_content))->validate();
|
229 |
+
|
230 |
+
if (!empty($errors)) {
|
231 |
+
$title = '<i class="icon-attention text-danger"></i> ';
|
232 |
+
} else {
|
233 |
+
$title = '';
|
234 |
+
}
|
235 |
+
|
236 |
if (!empty($record->post_title)) {
|
237 |
+
$title .= $record->post_title;
|
238 |
} else {
|
239 |
+
$title .= __('(no title)', AAM_KEY);
|
240 |
}
|
241 |
|
242 |
$title .= '<br/>';
|
255 |
*
|
256 |
* @return string
|
257 |
*
|
258 |
+
* @since 6.2.0 Added "delete" action
|
259 |
+
* @since 6.0.0 Initial implementation of the method
|
260 |
+
*
|
261 |
* @access protected
|
262 |
+
* @version 6.2.0
|
263 |
*/
|
264 |
protected function preparePolicyActionList($record)
|
265 |
{
|
270 |
|
271 |
$actions = array(
|
272 |
$policy->has($record->ID) ? "detach" : "attach",
|
273 |
+
$post->isAllowedTo('edit') ? 'edit' : 'no-edit',
|
274 |
+
$post->isAllowedTo('delete') ? 'delete' : 'no-delete'
|
275 |
);
|
276 |
|
277 |
return implode(',', $actions);
|
282 |
*
|
283 |
* @return string
|
284 |
*
|
285 |
+
* @since 6.2.0 Simplified implementation
|
286 |
+
* @since 6.0.0 Initial implementation of the method
|
287 |
+
*
|
288 |
* @access public
|
289 |
+
* @version 6.2.0
|
290 |
*/
|
291 |
public function save()
|
292 |
{
|
295 |
$id = $this->getFromPost('id');
|
296 |
$effect = $this->getFromPost('effect', FILTER_VALIDATE_BOOLEAN);
|
297 |
|
298 |
+
$object = $subject->getObject(self::OBJECT_TYPE, null, true);
|
299 |
+
$result = $object->updateOptionItem($id, $effect)->save();
|
300 |
+
|
301 |
+
return wp_json_encode(array(
|
302 |
+
'status' => ($result ? 'success' : 'failure')
|
303 |
+
));
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Delete policy
|
308 |
+
*
|
309 |
+
* @return string
|
310 |
+
*
|
311 |
+
* @access public
|
312 |
+
* @version 6.2.0
|
313 |
+
*/
|
314 |
+
public function delete()
|
315 |
+
{
|
316 |
+
$id = $this->getFromPost('id');
|
317 |
+
$result = wp_delete_post($id);
|
318 |
+
|
319 |
+
return wp_json_encode(array(
|
320 |
+
'status' => (is_a($result, 'WP_Post') ? 'success' : 'failure')
|
321 |
+
));
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Generate Access Policy from AAM settings
|
326 |
+
*
|
327 |
+
* @return string
|
328 |
+
*
|
329 |
+
* @access public
|
330 |
+
* @version 6.2.0
|
331 |
+
*/
|
332 |
+
public function generate()
|
333 |
+
{
|
334 |
+
$subject = AAM_Backend_Subject::getInstance()->getSubject();
|
335 |
+
$generator = new AAM_Core_Policy_Generator($subject);
|
336 |
+
|
337 |
+
// Prepare the policy name
|
338 |
+
if ($subject::UID === AAM_Core_Subject_User::UID) {
|
339 |
+
$title = sprintf('Policy for %s user', $subject->display_name);
|
340 |
+
} elseif ($subject::UID === AAM_Core_Subject_Role::UID) {
|
341 |
+
$title = sprintf('Policy for %s role', $subject->getId());
|
342 |
+
} elseif ($subject::UID === AAM_Core_Subject_Visitor::UID) {
|
343 |
+
$title = 'Policy for all visitors';
|
344 |
} else {
|
345 |
+
$title = 'Policy for everybody';
|
346 |
}
|
347 |
|
348 |
return wp_json_encode(array(
|
349 |
+
'title' => $title,
|
350 |
+
'policy' => base64_encode($generator->generate())
|
351 |
+
));
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Install access policy from the official hub
|
356 |
+
*
|
357 |
+
* @return string
|
358 |
+
*
|
359 |
+
* @access public
|
360 |
+
* @version 6.2.0
|
361 |
+
*/
|
362 |
+
public function install()
|
363 |
+
{
|
364 |
+
$metadata = json_decode($this->getFromPost('metadata'));
|
365 |
+
|
366 |
+
// Do some basic validation & normalization
|
367 |
+
$title = esc_js($metadata->title);
|
368 |
+
$excerpt = esc_js($metadata->description);
|
369 |
+
$assignee = $metadata->assignee;
|
370 |
+
$override = $metadata->override;
|
371 |
+
$policy = $this->getFromPost('aam-policy');
|
372 |
+
|
373 |
+
$id = wp_insert_post(array(
|
374 |
+
'post_type' => AAM_Service_AccessPolicy::POLICY_CPT,
|
375 |
+
'post_content' => $policy,
|
376 |
+
'post_title' => $title,
|
377 |
+
'post_excerpt' => $excerpt,
|
378 |
+
'post_status' => 'publish'
|
379 |
+
));
|
380 |
+
|
381 |
+
$errors = array();
|
382 |
+
|
383 |
+
if (!is_wp_error($id)) { // Assign & override
|
384 |
+
foreach($assignee as $s) {
|
385 |
+
$error = $this->applyToSubject($s, $id, true);
|
386 |
+
if ($error) {
|
387 |
+
$errors[] = $error;
|
388 |
+
}
|
389 |
+
}
|
390 |
+
|
391 |
+
foreach($override as $s) {
|
392 |
+
$error = $this->applyToSubject($s, $id, false);
|
393 |
+
if ($error) {
|
394 |
+
$errors[] = $error;
|
395 |
+
}
|
396 |
+
}
|
397 |
+
} else {
|
398 |
+
$errors[] = $id->get_error_message();
|
399 |
+
}
|
400 |
+
|
401 |
+
return wp_json_encode(array(
|
402 |
+
'status' => (empty($errors) ? 'success' : 'failure'),
|
403 |
+
'errors' => implode('; ', $errors)
|
404 |
));
|
405 |
}
|
406 |
|
407 |
+
/**
|
408 |
+
* Apply policy to provided subject
|
409 |
+
*
|
410 |
+
* @param string $s
|
411 |
+
* @param int $policyId
|
412 |
+
* @param boolean $effect
|
413 |
+
*
|
414 |
+
* @return string|null
|
415 |
+
*
|
416 |
+
* @access protected
|
417 |
+
* @version 6.2.0
|
418 |
+
*/
|
419 |
+
protected function applyToSubject($s, $policyId, $effect = true)
|
420 |
+
{
|
421 |
+
$error = null;
|
422 |
+
|
423 |
+
if ($s === 'visitor') {
|
424 |
+
$subject = AAM::api()->getVisitor();
|
425 |
+
} elseif ($s === 'default') {
|
426 |
+
$subject = AAM::api()->getDefault();
|
427 |
+
} elseif (strpos($s, 'role:') === 0) {
|
428 |
+
$subject = AAM::api()->getRole(substr($s, 5));
|
429 |
+
} elseif (strpos($s, 'user:') === 0) {
|
430 |
+
$uid = substr($s, 5);
|
431 |
+
$subject = AAM::api()->getUser(($uid === 'current') ? null : $uid);
|
432 |
+
} else {
|
433 |
+
$error = sprintf(__('Failed applying to %s', AAM_KEY), $s);
|
434 |
+
$subject = null;
|
435 |
+
}
|
436 |
+
|
437 |
+
if ($subject !== null) {
|
438 |
+
$subject->getObject(
|
439 |
+
AAM_Core_Object_Policy::OBJECT_TYPE, null, true
|
440 |
+
)->updateOptionItem($policyId, $effect)->save();
|
441 |
+
}
|
442 |
+
|
443 |
+
return $error;
|
444 |
+
}
|
445 |
+
|
446 |
/**
|
447 |
* Get default Access Policy
|
448 |
*
|
application/Backend/Feature/Main/Post.php
CHANGED
@@ -10,11 +10,12 @@
|
|
10 |
/**
|
11 |
* Backend posts & terms service UI
|
12 |
*
|
|
|
13 |
* @since 6.0.3 Allowed to manage access to ALL registered post types
|
14 |
* @since 6.0.0 Initial implementation of the class
|
15 |
*
|
16 |
* @package AAM
|
17 |
-
* @version 6.0
|
18 |
*/
|
19 |
class AAM_Backend_Feature_Main_Post
|
20 |
extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAware
|
@@ -44,6 +45,35 @@ class AAM_Backend_Feature_Main_Post
|
|
44 |
*/
|
45 |
const TEMPLATE = 'service/post.php';
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
/**
|
48 |
* Get posts & terms list
|
49 |
*
|
@@ -185,13 +215,19 @@ class AAM_Backend_Feature_Main_Post
|
|
185 |
*
|
186 |
* @return array
|
187 |
*
|
|
|
|
|
|
|
|
|
188 |
* @access protected
|
189 |
-
* @version 6.
|
190 |
*/
|
191 |
protected function getAccessOptionList()
|
192 |
{
|
193 |
$list = apply_filters(
|
194 |
-
'aam_post_access_options_filter',
|
|
|
|
|
195 |
);
|
196 |
|
197 |
return array_filter($list, function ($opt) {
|
@@ -226,12 +262,19 @@ class AAM_Backend_Feature_Main_Post
|
|
226 |
*
|
227 |
* @return string
|
228 |
*
|
|
|
|
|
|
|
229 |
* @access protected
|
230 |
-
* @version 6.
|
231 |
*/
|
232 |
protected function getPreviewValue($option, $value)
|
233 |
{
|
234 |
switch ($option) {
|
|
|
|
|
|
|
|
|
235 |
case 'teaser':
|
236 |
$preview = $this->prepareTeaserPreview($value);
|
237 |
break;
|
@@ -265,6 +308,42 @@ class AAM_Backend_Feature_Main_Post
|
|
265 |
return $preview;
|
266 |
}
|
267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
/**
|
269 |
* Prepare teaser message preview
|
270 |
*
|
@@ -450,8 +529,11 @@ class AAM_Backend_Feature_Main_Post
|
|
450 |
*
|
451 |
* @return mixed
|
452 |
*
|
|
|
|
|
|
|
453 |
* @access protected
|
454 |
-
* @version 6.
|
455 |
*/
|
456 |
protected function sanitizeOption($option, $value)
|
457 |
{
|
@@ -461,7 +543,7 @@ class AAM_Backend_Feature_Main_Post
|
|
461 |
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
462 |
}
|
463 |
|
464 |
-
return $value;
|
465 |
}
|
466 |
|
467 |
/**
|
10 |
/**
|
11 |
* Backend posts & terms service UI
|
12 |
*
|
13 |
+
* @since 6.2.0 Added more granular control over the HIDDEN access option
|
14 |
* @since 6.0.3 Allowed to manage access to ALL registered post types
|
15 |
* @since 6.0.0 Initial implementation of the class
|
16 |
*
|
17 |
* @package AAM
|
18 |
+
* @version 6.2.0
|
19 |
*/
|
20 |
class AAM_Backend_Feature_Main_Post
|
21 |
extends AAM_Backend_Feature_Abstract implements AAM_Backend_Feature_ISubjectAware
|
45 |
*/
|
46 |
const TEMPLATE = 'service/post.php';
|
47 |
|
48 |
+
/**
|
49 |
+
* Constructor
|
50 |
+
*
|
51 |
+
* @return void
|
52 |
+
*
|
53 |
+
* @access public
|
54 |
+
* @since 6.2.0
|
55 |
+
*/
|
56 |
+
public function __construct()
|
57 |
+
{
|
58 |
+
add_filter('aam_sanitize_post_value_filter', function($value, $option) {
|
59 |
+
if ($option === 'hidden') {
|
60 |
+
$value['frontend'] = isset($value['frontend']) && filter_var(
|
61 |
+
$value['frontend'], FILTER_VALIDATE_BOOLEAN
|
62 |
+
);
|
63 |
+
|
64 |
+
$value['backend'] = isset($value['backend']) && filter_var(
|
65 |
+
$value['backend'], FILTER_VALIDATE_BOOLEAN
|
66 |
+
);
|
67 |
+
|
68 |
+
$value['api'] = isset($value['api']) && filter_var(
|
69 |
+
$value['api'], FILTER_VALIDATE_BOOLEAN
|
70 |
+
);
|
71 |
+
}
|
72 |
+
|
73 |
+
return $value;
|
74 |
+
}, 10, 2);
|
75 |
+
}
|
76 |
+
|
77 |
/**
|
78 |
* Get posts & terms list
|
79 |
*
|
215 |
*
|
216 |
* @return array
|
217 |
*
|
218 |
+
* @since 6.2.0 Added additional argument "current subject" to the
|
219 |
+
* `aam_post_access_options_filter` filter
|
220 |
+
* @since 6.0.0 Initial implementation of the method
|
221 |
+
*
|
222 |
* @access protected
|
223 |
+
* @version 6.2.0
|
224 |
*/
|
225 |
protected function getAccessOptionList()
|
226 |
{
|
227 |
$list = apply_filters(
|
228 |
+
'aam_post_access_options_filter',
|
229 |
+
AAM_Backend_View_PostOptionList::get(),
|
230 |
+
$this->getSubject()
|
231 |
);
|
232 |
|
233 |
return array_filter($list, function ($opt) {
|
262 |
*
|
263 |
* @return string
|
264 |
*
|
265 |
+
* @since 6.2.0 Added HIDDEN preview value
|
266 |
+
* @since 6.0.0 Initial implementation of the method
|
267 |
+
*
|
268 |
* @access protected
|
269 |
+
* @version 6.2.0
|
270 |
*/
|
271 |
protected function getPreviewValue($option, $value)
|
272 |
{
|
273 |
switch ($option) {
|
274 |
+
case 'hidden':
|
275 |
+
$preview = $this->prepareHiddenPreview($value);
|
276 |
+
break;
|
277 |
+
|
278 |
case 'teaser':
|
279 |
$preview = $this->prepareTeaserPreview($value);
|
280 |
break;
|
308 |
return $preview;
|
309 |
}
|
310 |
|
311 |
+
/**
|
312 |
+
* Prepare preview value for the HIDDEN option
|
313 |
+
*
|
314 |
+
* @param array|boolean $hidden
|
315 |
+
*
|
316 |
+
* @return string
|
317 |
+
*
|
318 |
+
* @access protected
|
319 |
+
* @version 6.2.0
|
320 |
+
*/
|
321 |
+
protected function prepareHiddenPreview($hidden)
|
322 |
+
{
|
323 |
+
$preview = null;
|
324 |
+
|
325 |
+
if (is_array($hidden)) {
|
326 |
+
if ($hidden['enabled'] === true) {
|
327 |
+
$areas = array();
|
328 |
+
if (!empty($hidden['frontend'])) {
|
329 |
+
$areas[] = __('Frontend', AAM_KEY);
|
330 |
+
}
|
331 |
+
if (!empty($hidden['backend'])) {
|
332 |
+
$areas[] = __('Backend', AAM_KEY);
|
333 |
+
}
|
334 |
+
if (!empty($hidden['api'])) {
|
335 |
+
$areas[] = __('RESTful API', AAM_KEY);
|
336 |
+
}
|
337 |
+
|
338 |
+
$preview = implode(', ', $areas);
|
339 |
+
}
|
340 |
+
} elseif (!empty($hidden)) {
|
341 |
+
$preview = __('All Areas', AAM_KEY);
|
342 |
+
}
|
343 |
+
|
344 |
+
return $preview;
|
345 |
+
}
|
346 |
+
|
347 |
/**
|
348 |
* Prepare teaser message preview
|
349 |
*
|
529 |
*
|
530 |
* @return mixed
|
531 |
*
|
532 |
+
* @since 6.2.0 Added support for the new filter `aam_sanitize_post_value_filter`
|
533 |
+
* @since 6.0.0 Initial implementation of the method
|
534 |
+
*
|
535 |
* @access protected
|
536 |
+
* @version 6.2.0
|
537 |
*/
|
538 |
protected function sanitizeOption($option, $value)
|
539 |
{
|
543 |
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
544 |
}
|
545 |
|
546 |
+
return apply_filters('aam_sanitize_post_value_filter', $value, $option);
|
547 |
}
|
548 |
|
549 |
/**
|
application/Backend/Feature/Settings/Manager.php
CHANGED
@@ -5,15 +5,16 @@
|
|
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 |
-
* @version 6.0.0
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
* Backend Settings area abstract manager
|
14 |
*
|
|
|
|
|
|
|
15 |
* @package AAM
|
16 |
-
* @version 6.
|
17 |
*/
|
18 |
class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
|
19 |
{
|
@@ -60,6 +61,149 @@ class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
|
|
60 |
return wp_json_encode(array('status' => 'success'));
|
61 |
}
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
/**
|
64 |
* Register settings UI manager
|
65 |
*
|
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 Settings area abstract manager
|
12 |
*
|
13 |
+
* @since 6.2.0 Added Import/Export functionality
|
14 |
+
* @since 6.0.0 Initial implementation of the class
|
15 |
+
*
|
16 |
* @package AAM
|
17 |
+
* @version 6.2.0
|
18 |
*/
|
19 |
class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
|
20 |
{
|
61 |
return wp_json_encode(array('status' => 'success'));
|
62 |
}
|
63 |
|
64 |
+
/**
|
65 |
+
* Aggregate support request metadata
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*
|
69 |
+
* @access public
|
70 |
+
* @version 6.2.0
|
71 |
+
*/
|
72 |
+
public function getSupportMetadata()
|
73 |
+
{
|
74 |
+
global $wp_version;
|
75 |
+
|
76 |
+
return wp_json_encode(array(
|
77 |
+
'phpVersion' => PHP_VERSION,
|
78 |
+
'wpVersion' => $wp_version,
|
79 |
+
'aamVersion' => AAM_VERSION,
|
80 |
+
'settings' => AAM_Core_API::getOption(
|
81 |
+
AAM_Core_AccessSettings::DB_OPTION, array()
|
82 |
+
),
|
83 |
+
'config' => AAM_Core_API::getOption(
|
84 |
+
AAM_Core_Config::DB_OPTION, array()
|
85 |
+
),
|
86 |
+
'configpress' => AAM_Core_API::getOption(
|
87 |
+
AAM_Core_ConfigPress::DB_OPTION, array()
|
88 |
+
),
|
89 |
+
'roles' => AAM_Core_API::getOption(
|
90 |
+
AAM_Core_API::getRoles()->role_key, array()
|
91 |
+
),
|
92 |
+
'addons' => AAM_Addon_Repository::getInstance()->getRegistry(),
|
93 |
+
'plugins' => get_plugins()
|
94 |
+
));
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Export AAM settings as JSON
|
99 |
+
*
|
100 |
+
* @return string
|
101 |
+
*
|
102 |
+
* @access public
|
103 |
+
* @version 6.2.0
|
104 |
+
*/
|
105 |
+
public function exportSettings()
|
106 |
+
{
|
107 |
+
$data = array(
|
108 |
+
'version' => AAM_VERSION,
|
109 |
+
'plugin' => AAM_KEY,
|
110 |
+
'timestamp' => (new DateTime('now', new DateTimeZone('UTC')))->format('U'),
|
111 |
+
'dataset' => array()
|
112 |
+
);
|
113 |
+
|
114 |
+
$groups = AAM::api()->getConfig(
|
115 |
+
'core.export.groups', array('settings', 'config', 'roles')
|
116 |
+
);
|
117 |
+
|
118 |
+
if (is_string($groups)) {
|
119 |
+
$groups = array_map('trim', explode(',', $groups));
|
120 |
+
}
|
121 |
+
|
122 |
+
foreach($groups as $group) {
|
123 |
+
switch($group) {
|
124 |
+
case 'settings':
|
125 |
+
$data['dataset']['settings'] = AAM_Core_API::getOption(
|
126 |
+
AAM_Core_AccessSettings::DB_OPTION, array()
|
127 |
+
);
|
128 |
+
break;
|
129 |
+
|
130 |
+
case 'config':
|
131 |
+
$data['dataset']['config'] = AAM_Core_API::getOption(
|
132 |
+
AAM_Core_Config::DB_OPTION, array()
|
133 |
+
);
|
134 |
+
$data['dataset']['configpress'] = AAM_Core_API::getOption(
|
135 |
+
AAM_Core_ConfigPress::DB_OPTION, array()
|
136 |
+
);
|
137 |
+
break;
|
138 |
+
|
139 |
+
case 'roles':
|
140 |
+
$data['dataset']['roles'] = AAM_Core_API::getOption(
|
141 |
+
AAM_Core_API::getRoles()->role_key, array()
|
142 |
+
);
|
143 |
+
break;
|
144 |
+
|
145 |
+
default:
|
146 |
+
break;
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
return wp_json_encode(array(
|
151 |
+
'result' => base64_encode(wp_json_encode($data))
|
152 |
+
));
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Import AAM settings
|
157 |
+
*
|
158 |
+
* @return string
|
159 |
+
*
|
160 |
+
* @access public
|
161 |
+
* @version 6.2.0
|
162 |
+
*/
|
163 |
+
public function importSettings()
|
164 |
+
{
|
165 |
+
$error = __('Invalid data', AAM_KEY);
|
166 |
+
$data = json_decode($this->getFromPost('payload'), true);
|
167 |
+
|
168 |
+
if ($data) {
|
169 |
+
if (isset($data['dataset']) && is_array($data['dataset'])) {
|
170 |
+
foreach($data['dataset'] as $group => $settings) {
|
171 |
+
switch($group) {
|
172 |
+
case 'settings':
|
173 |
+
AAM_Core_API::updateOption(
|
174 |
+
AAM_Core_AccessSettings::DB_OPTION, $settings
|
175 |
+
);
|
176 |
+
break;
|
177 |
+
|
178 |
+
case 'config':
|
179 |
+
AAM_Core_API::updateOption(
|
180 |
+
AAM_Core_Config::DB_OPTION, $settings
|
181 |
+
);
|
182 |
+
break;
|
183 |
+
|
184 |
+
case 'roles':
|
185 |
+
AAM_Core_API::updateOption(
|
186 |
+
AAM_Core_API::getRoles()->role_key, $settings
|
187 |
+
);
|
188 |
+
break;
|
189 |
+
|
190 |
+
default:
|
191 |
+
break;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
$error = null;
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
if ($error !== null) {
|
199 |
+
$response = array('status' => 'failure', 'reason' => $error);
|
200 |
+
} else {
|
201 |
+
$response = array('status' => 'success');
|
202 |
+
}
|
203 |
+
|
204 |
+
return wp_json_encode($response);
|
205 |
+
}
|
206 |
+
|
207 |
/**
|
208 |
* Register settings UI manager
|
209 |
*
|
application/Backend/Manager.php
CHANGED
@@ -10,11 +10,12 @@
|
|
10 |
/**
|
11 |
* Backend manager
|
12 |
*
|
|
|
13 |
* @since 6.1.0 Fixed bug with HTML compression
|
14 |
* @since 6.0.0 Initial implementation of the class
|
15 |
*
|
16 |
* @package AAM
|
17 |
-
* @version 6.
|
18 |
*/
|
19 |
class AAM_Backend_Manager
|
20 |
{
|
@@ -124,8 +125,11 @@ class AAM_Backend_Manager
|
|
124 |
*
|
125 |
* @return void
|
126 |
*
|
|
|
|
|
|
|
127 |
* @access public
|
128 |
-
* @version 6.
|
129 |
*/
|
130 |
public function printFooterJavascript()
|
131 |
{
|
@@ -155,7 +159,8 @@ class AAM_Backend_Manager
|
|
155 |
'caps' => array(
|
156 |
'create_roles' => current_user_can('aam_create_roles'),
|
157 |
'create_users' => current_user_can('create_users')
|
158 |
-
)
|
|
|
159 |
));
|
160 |
|
161 |
echo '<script type="text/javascript">';
|
10 |
/**
|
11 |
* Backend manager
|
12 |
*
|
13 |
+
* @since 6.2.0 Added new property to the JS localization `blog_id`
|
14 |
* @since 6.1.0 Fixed bug with HTML compression
|
15 |
* @since 6.0.0 Initial implementation of the class
|
16 |
*
|
17 |
* @package AAM
|
18 |
+
* @version 6.2.0
|
19 |
*/
|
20 |
class AAM_Backend_Manager
|
21 |
{
|
125 |
*
|
126 |
* @return void
|
127 |
*
|
128 |
+
* @since 6.2.0 Added `blog_id` to the localized array of properties
|
129 |
+
* @since 6.0.0 Initial implementation of the method
|
130 |
+
*
|
131 |
* @access public
|
132 |
+
* @version 6.2.0
|
133 |
*/
|
134 |
public function printFooterJavascript()
|
135 |
{
|
159 |
'caps' => array(
|
160 |
'create_roles' => current_user_can('aam_create_roles'),
|
161 |
'create_users' => current_user_can('create_users')
|
162 |
+
),
|
163 |
+
'blog_id' => get_current_blog_id()
|
164 |
));
|
165 |
|
166 |
echo '<script type="text/javascript">';
|
application/Backend/Subject.php
CHANGED
@@ -13,11 +13,12 @@
|
|
13 |
* Currently managed subject. Based on the HTTP request data, define what subject
|
14 |
* is currently managed with AAM UI.
|
15 |
*
|
|
|
16 |
* @since 6.1.1 Improved safety by using a last role as default
|
17 |
* @since 6.0.0 Initial implementation of the class
|
18 |
*
|
19 |
* @package AAM
|
20 |
-
* @version 6.
|
21 |
*/
|
22 |
class AAM_Backend_Subject
|
23 |
{
|
@@ -40,12 +41,15 @@ class AAM_Backend_Subject
|
|
40 |
*
|
41 |
* @return void
|
42 |
*
|
|
|
|
|
|
|
43 |
* @access protected
|
44 |
-
* @version 6.
|
45 |
*/
|
46 |
protected function __construct()
|
47 |
{
|
48 |
-
$subject = $this->getFromPost('subject');
|
49 |
|
50 |
if ($subject) {
|
51 |
$this->initRequestedSubject($subject, $this->getFromPost('subjectId'));
|
@@ -129,18 +133,29 @@ class AAM_Backend_Subject
|
|
129 |
*
|
130 |
* @return AAM_Core_Subject
|
131 |
*
|
|
|
|
|
|
|
132 |
* @access protected
|
133 |
-
* @version 6.
|
134 |
*/
|
135 |
protected function initRequestedSubject($type, $id)
|
136 |
{
|
137 |
if ($type === AAM_Core_Subject_User::UID) {
|
138 |
$subject = AAM::api()->getUser(intval($id));
|
139 |
} elseif ($type === AAM_Core_Subject_Default::UID) {
|
140 |
-
$subject =
|
|
|
|
|
141 |
} else {
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
}
|
145 |
|
146 |
$this->setSubject($subject);
|
13 |
* Currently managed subject. Based on the HTTP request data, define what subject
|
14 |
* is currently managed with AAM UI.
|
15 |
*
|
16 |
+
* @since 6.2.0 Enhanced security & improved general functionality
|
17 |
* @since 6.1.1 Improved safety by using a last role as default
|
18 |
* @since 6.0.0 Initial implementation of the class
|
19 |
*
|
20 |
* @package AAM
|
21 |
+
* @version 6.2.0
|
22 |
*/
|
23 |
class AAM_Backend_Subject
|
24 |
{
|
41 |
*
|
42 |
* @return void
|
43 |
*
|
44 |
+
* @since 6.2.0 Enhanced security. Making sure that subject type is normalized
|
45 |
+
* @since 6.0.0 Initial implementation of the method
|
46 |
+
*
|
47 |
* @access protected
|
48 |
+
* @version 6.2.0
|
49 |
*/
|
50 |
protected function __construct()
|
51 |
{
|
52 |
+
$subject = strtolower($this->getFromPost('subject'));
|
53 |
|
54 |
if ($subject) {
|
55 |
$this->initRequestedSubject($subject, $this->getFromPost('subjectId'));
|
133 |
*
|
134 |
* @return AAM_Core_Subject
|
135 |
*
|
136 |
+
* @since 6.2.0 Refactored to use AAM API to retrieve subject
|
137 |
+
* @since 6.0.0 Initial implementation of the method
|
138 |
+
*
|
139 |
* @access protected
|
140 |
+
* @version 6.2.0
|
141 |
*/
|
142 |
protected function initRequestedSubject($type, $id)
|
143 |
{
|
144 |
if ($type === AAM_Core_Subject_User::UID) {
|
145 |
$subject = AAM::api()->getUser(intval($id));
|
146 |
} elseif ($type === AAM_Core_Subject_Default::UID) {
|
147 |
+
$subject = AAM::api()->getDefault();
|
148 |
+
} elseif ($type === AAM_Core_Subject_Visitor::UID) {
|
149 |
+
$subject = AAM::api()->getVisitor();
|
150 |
} else {
|
151 |
+
// Covering scenario when changing between sites and they have mismatched
|
152 |
+
// list of roles
|
153 |
+
if (AAM_Core_API::getRoles()->is_role($id)) {
|
154 |
+
$subject = AAM::api()->getRole($id);
|
155 |
+
} else {
|
156 |
+
$roles = array_keys(get_editable_roles());
|
157 |
+
$subject = AAM::api()->getRole(array_pop($roles));
|
158 |
+
}
|
159 |
}
|
160 |
|
161 |
$this->setSubject($subject);
|
application/Backend/View/Localization.php
CHANGED
@@ -5,15 +5,16 @@
|
|
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 |
-
* @version 6.0.0
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
* JS localization for AAM backend UI
|
14 |
*
|
|
|
|
|
|
|
15 |
* @package AAM
|
16 |
-
* @version 6.
|
17 |
*/
|
18 |
class AAM_Backend_View_Localization
|
19 |
{
|
@@ -23,8 +24,11 @@ class AAM_Backend_View_Localization
|
|
23 |
*
|
24 |
* @return array
|
25 |
*
|
|
|
|
|
|
|
26 |
* @access public
|
27 |
-
* @version 6.
|
28 |
*/
|
29 |
public static function get()
|
30 |
{
|
@@ -65,6 +69,8 @@ class AAM_Backend_View_Localization
|
|
65 |
'_TOTAL_ user(s)' => __('_TOTAL_ user(s)', AAM_KEY),
|
66 |
'Create New User' => __('Create New User', AAM_KEY),
|
67 |
'Role' => __('Role', AAM_KEY),
|
|
|
|
|
68 |
'All Users, Roles and Visitor' => __('All Users, Roles and Visitor', AAM_KEY),
|
69 |
'Failed to apply policy changes' => __('Failed to apply policy changes', AAM_KEY),
|
70 |
'Attach Policy To Visitors' => __('Attach Policy To Visitors', AAM_KEY),
|
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 |
* JS localization for AAM backend UI
|
12 |
*
|
13 |
+
* @since 6.2.0 Added couple new labels
|
14 |
+
* @since 6.0.0 Initial implementation of the class
|
15 |
+
*
|
16 |
* @package AAM
|
17 |
+
* @version 6.2.0
|
18 |
*/
|
19 |
class AAM_Backend_View_Localization
|
20 |
{
|
24 |
*
|
25 |
* @return array
|
26 |
*
|
27 |
+
* @since 6.2.0 Added couple new labels
|
28 |
+
* @since 6.0.0 Initial implementation of the method
|
29 |
+
*
|
30 |
* @access public
|
31 |
+
* @version 6.2.0
|
32 |
*/
|
33 |
public static function get()
|
34 |
{
|
69 |
'_TOTAL_ user(s)' => __('_TOTAL_ user(s)', AAM_KEY),
|
70 |
'Create New User' => __('Create New User', AAM_KEY),
|
71 |
'Role' => __('Role', AAM_KEY),
|
72 |
+
'Message has been sent' => __('Message has been sent', AAM_KEY),
|
73 |
+
'Download Exported Settings' => __('Download Exported Settings', AAM_KEY),
|
74 |
'All Users, Roles and Visitor' => __('All Users, Roles and Visitor', AAM_KEY),
|
75 |
'Failed to apply policy changes' => __('Failed to apply policy changes', AAM_KEY),
|
76 |
'Attach Policy To Visitors' => __('Attach Policy To Visitors', AAM_KEY),
|
application/Backend/View/PostOptionList.php
CHANGED
@@ -5,15 +5,16 @@
|
|
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 |
-
* @version 6.0.0
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
* Post & Term option list for the Post object
|
14 |
*
|
|
|
|
|
|
|
15 |
* @package AAM
|
16 |
-
* @version 6.
|
17 |
*/
|
18 |
class AAM_Backend_View_PostOptionList
|
19 |
{
|
@@ -23,14 +24,19 @@ class AAM_Backend_View_PostOptionList
|
|
23 |
*
|
24 |
* @return array
|
25 |
*
|
|
|
|
|
|
|
26 |
* @access public
|
27 |
-
* @version 6.
|
28 |
*/
|
29 |
public static function get()
|
30 |
{
|
31 |
return array(
|
32 |
'hidden' => array(
|
33 |
'title' => __('Hidden', AAM_KEY),
|
|
|
|
|
34 |
'description' => __('Completely hide the post however, still allow direct access with the valid URL.', AAM_KEY),
|
35 |
),
|
36 |
'restricted' => array(
|
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 |
* Post & Term option list for the Post object
|
12 |
*
|
13 |
+
* @since 6.2.0 Enhanced HIDDEN option with more granular access controls
|
14 |
+
* @since 6.0.0 Initial implementation of the class
|
15 |
+
*
|
16 |
* @package AAM
|
17 |
+
* @version 6.2.0
|
18 |
*/
|
19 |
class AAM_Backend_View_PostOptionList
|
20 |
{
|
24 |
*
|
25 |
* @return array
|
26 |
*
|
27 |
+
* @since 6.2.0 Enhanced HIDDEN option with more granular access controls
|
28 |
+
* @since 6.0.0 Initial implementation of the method
|
29 |
+
*
|
30 |
* @access public
|
31 |
+
* @version 6.2.0
|
32 |
*/
|
33 |
public static function get()
|
34 |
{
|
35 |
return array(
|
36 |
'hidden' => array(
|
37 |
'title' => __('Hidden', AAM_KEY),
|
38 |
+
'sub' => __('Hidden Areas', AAM_KEY),
|
39 |
+
'modal' => 'modal-hidden',
|
40 |
'description' => __('Completely hide the post however, still allow direct access with the valid URL.', AAM_KEY),
|
41 |
),
|
42 |
'restricted' => array(
|
application/Backend/tmpl/metabox/main-iframe.php
CHANGED
@@ -1,4 +1,11 @@
|
|
1 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
<?php if (defined('AAM_KEY')) { ?>
|
4 |
<?php echo static::loadTemplate(__DIR__ . '/iframe-header.php'); ?>
|
@@ -61,8 +68,8 @@
|
|
61 |
</a>
|
62 |
<?php } ?>
|
63 |
<?php if (current_user_can('aam_view_help_btn')) { ?>
|
64 |
-
<a href="
|
65 |
-
<i class="icon-
|
66 |
<span><?php echo __('Help', AAM_KEY); ?></span>
|
67 |
</a>
|
68 |
<?php } ?>
|
@@ -71,18 +78,102 @@
|
|
71 |
</div>
|
72 |
</div>
|
73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
<?php if (current_user_can('aam_manage_settings')) { ?>
|
75 |
<div class="metabox-holder settings-metabox" style="display:none;">
|
76 |
<div class="postbox">
|
77 |
<div class="inside">
|
78 |
<div class="row">
|
79 |
-
<div class="col-xs-12
|
|
|
|
|
|
|
|
|
|
|
80 |
<a href="#clear-settings-modal" data-toggle="modal" class="btn btn-danger btn-block"><?php echo __('Reset AAM Settings', AAM_KEY); ?></a>
|
81 |
</div>
|
82 |
</div>
|
83 |
</div>
|
84 |
</div>
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
<div class="modal fade" id="clear-settings-modal" tabindex="-1" role="dialog">
|
87 |
<div class="modal-dialog modal-sm" role="document">
|
88 |
<div class="modal-content">
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @since 6.2.0 Added support & import/export modals
|
4 |
+
* @since 6.0.0 Initial implementation of the template
|
5 |
+
*
|
6 |
+
* @version 6.2.0
|
7 |
+
* */
|
8 |
+
?>
|
9 |
|
10 |
<?php if (defined('AAM_KEY')) { ?>
|
11 |
<?php echo static::loadTemplate(__DIR__ . '/iframe-header.php'); ?>
|
68 |
</a>
|
69 |
<?php } ?>
|
70 |
<?php if (current_user_can('aam_view_help_btn')) { ?>
|
71 |
+
<a href="#modal-support" data-toggle="modal" title="Ask For Help">
|
72 |
+
<i class="icon-chat"></i>
|
73 |
<span><?php echo __('Help', AAM_KEY); ?></span>
|
74 |
</a>
|
75 |
<?php } ?>
|
78 |
</div>
|
79 |
</div>
|
80 |
|
81 |
+
<?php if (current_user_can('aam_view_help_btn')) { ?>
|
82 |
+
<div class="modal fade" id="modal-support" tabindex="-1" role="dialog">
|
83 |
+
<div class="modal-dialog" role="document">
|
84 |
+
<div class="modal-content">
|
85 |
+
<div class="modal-header">
|
86 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">×</span></button>
|
87 |
+
<h4 class="modal-title text-left"><?php echo __('Ask For Help', AAM_KEY); ?></h4>
|
88 |
+
</div>
|
89 |
+
<div class="modal-body">
|
90 |
+
<p class="alert alert-warning"><?php echo sprintf(__('Before submitting a support request, please get familiar with %show AAM support works%s so you can set the right expectations. Especially pay attention to how do we prioritize support.', AAM_KEY), '<a href="https://aamplugin.com/support" target="_blank">', '</a>'); ?></p>
|
91 |
+
|
92 |
+
<div class="form-group aam-outer-top-xxs">
|
93 |
+
<label><?php echo __('Name', AAM_KEY); ?></label>
|
94 |
+
<input type="text" class="form-control" placeholder="<?php echo __('How should we call you', AAM_KEY); ?>" id="support-name" />
|
95 |
+
</div>
|
96 |
+
|
97 |
+
<div class="form-group">
|
98 |
+
<label><?php echo __('Email', AAM_KEY); ?> <sup class="text-danger">*</sup></label>
|
99 |
+
<input type="email" class="form-control" placeholder="<?php echo __('Enter your email', AAM_KEY); ?>" id="support-email" />
|
100 |
+
<span class="hint text-muted"><?php echo __('The rest of the conversation will be conducted via provided email', AAM_KEY); ?></span>
|
101 |
+
</div>
|
102 |
+
|
103 |
+
<div class="form-group">
|
104 |
+
<label><?php echo __('Message', AAM_KEY); ?> <sup class="text-danger">*</sup></label>
|
105 |
+
<textarea class="form-control" placeholder="<?php echo __('Enter your message here...', AAM_KEY); ?>" rows="5" id="support-message"></textarea>
|
106 |
+
<span class="hint text-muted"><?php echo AAM_Backend_View_Helper::preparePhrase('Please be [kind], [specific] and [patient], and let us do the rest', 'strong', 'strong', 'strong'); ?></span>
|
107 |
+
</div>
|
108 |
+
|
109 |
+
<div class="checkbox">
|
110 |
+
<label>
|
111 |
+
<input type="checkbox" checked id="support-details" /> <?php echo sprintf(__('Attach system details (%slearn more here%s)', AAM_KEY), '<a href="https://forum.aamplugin.com/d/454-support-request-with-attached-system-details" target="_blank">', '</a>'); ?>
|
112 |
+
</label>
|
113 |
+
</div>
|
114 |
+
</div>
|
115 |
+
<div class="modal-footer">
|
116 |
+
<button type="button" class="btn btn-success" id="submit-support"><?php echo __('Request Support', AAM_KEY); ?></button>
|
117 |
+
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Close', AAM_KEY); ?></button>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
<?php } ?>
|
123 |
+
|
124 |
<?php if (current_user_can('aam_manage_settings')) { ?>
|
125 |
<div class="metabox-holder settings-metabox" style="display:none;">
|
126 |
<div class="postbox">
|
127 |
<div class="inside">
|
128 |
<div class="row">
|
129 |
+
<div class="col-xs-12">
|
130 |
+
<a href="#transfer-settings-modal" data-toggle="modal" class="btn btn-warning btn-block"><?php echo __('Export/Import AAM Settings', AAM_KEY); ?></a>
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
<div class="row aam-outer-top-xxs">
|
134 |
+
<div class="col-xs-12">
|
135 |
<a href="#clear-settings-modal" data-toggle="modal" class="btn btn-danger btn-block"><?php echo __('Reset AAM Settings', AAM_KEY); ?></a>
|
136 |
</div>
|
137 |
</div>
|
138 |
</div>
|
139 |
</div>
|
140 |
|
141 |
+
<div class="modal fade" id="transfer-settings-modal" tabindex="-1" role="dialog">
|
142 |
+
<div class="modal-dialog" role="document">
|
143 |
+
<div class="modal-content">
|
144 |
+
<div class="modal-body">
|
145 |
+
<p class="alert alert-danger" id="file-api-error"><?php echo __('Your browser does not support modern way to work with files. The Export/Import feature will not work properly. Consider to use the latest Chrome, Firefox or Safari browser instead.', AAM_KEY); ?></p>
|
146 |
+
|
147 |
+
<div id="import-export-container">
|
148 |
+
<ul class="nav nav-tabs" role="tablist">
|
149 |
+
<li role="presentation" class="active"><a href="#export-tab" aria-controls="export-tab" role="tab" data-toggle="tab"><?php echo __('Export', AAM_KEY); ?></a></li>
|
150 |
+
<li role="presentation"><a href="#import-tab" aria-controls="import-tab" role="tab" data-toggle="tab"><?php echo __('Import', AAM_KEY); ?></a></li>
|
151 |
+
</ul>
|
152 |
+
|
153 |
+
<div class="tab-content">
|
154 |
+
<div role="tabpanel" class="tab-pane active" id="export-tab">
|
155 |
+
<p class="alert alert-info"><?php echo __('Export AAM settings so they can be imported to a different location. To learn more about customizing exported data, refer to the "How Import/Export feature works" article.', AAM_KEY); ?></p>
|
156 |
+
<div class="form-group aam-bordered aam-outer-top-xxs text-center">
|
157 |
+
<a href="#" id="export-settings" class="btn btn-primary"><?php echo __('Download Exported Settings', AAM_KEY); ?></a>
|
158 |
+
</div>
|
159 |
+
</div>
|
160 |
+
|
161 |
+
<div role="tabpanel" class="tab-pane" id="import-tab">
|
162 |
+
<p class="alert alert-warning"><?php echo __('Select a *.json file with valid AAM settings. All the current AAM settings will be lost and replaced with imported settings.', AAM_KEY); ?></p>
|
163 |
+
<div class="form-group aam-bordered aam-outer-top-xxs">
|
164 |
+
<input type="file" id="aam-settings" name="aam-settings" />
|
165 |
+
</div>
|
166 |
+
</div>
|
167 |
+
</div>
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
<div class="modal-footer">
|
171 |
+
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Close', AAM_KEY); ?></button>
|
172 |
+
</div>
|
173 |
+
</div>
|
174 |
+
</div>
|
175 |
+
</div>
|
176 |
+
|
177 |
<div class="modal fade" id="clear-settings-modal" tabindex="-1" role="dialog">
|
178 |
<div class="modal-dialog modal-sm" role="document">
|
179 |
<div class="modal-content">
|
application/Backend/tmpl/metabox/policy-metabox.php
CHANGED
@@ -1,9 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
|
|
3 |
* @since 6.1.1 Removing the backslashes before displaying the policy
|
4 |
* @since 6.0.0 Initial implementation of the template
|
5 |
*
|
6 |
-
* @version 6.
|
7 |
*/
|
8 |
?>
|
9 |
<?php if (defined('AAM_KEY')) { ?>
|
@@ -44,7 +45,7 @@
|
|
44 |
|
45 |
$(document).ready(function() {
|
46 |
$('form[name="post"]').bind('submit', function(event) {
|
47 |
-
var json = editor.getValue();
|
48 |
|
49 |
$('#policy-parsing-error').addClass('hidden');
|
50 |
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @since 6.2.0 Escaping backslashes to avoid issue with JSON validation
|
4 |
* @since 6.1.1 Removing the backslashes before displaying the policy
|
5 |
* @since 6.0.0 Initial implementation of the template
|
6 |
*
|
7 |
+
* @version 6.2.0
|
8 |
*/
|
9 |
?>
|
10 |
<?php if (defined('AAM_KEY')) { ?>
|
45 |
|
46 |
$(document).ready(function() {
|
47 |
$('form[name="post"]').bind('submit', function(event) {
|
48 |
+
var json = editor.getValue().replace(/\\/g, '\\\\');
|
49 |
|
50 |
$('#policy-parsing-error').addClass('hidden');
|
51 |
|
application/Backend/tmpl/page/addon-panel.php
CHANGED
@@ -1,9 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
|
|
3 |
* @since 6.0.5 Fixed typo in the license expiration property. Enriched plugin' status display
|
4 |
* @since 6.0.0 Initial implementation of the template
|
5 |
*
|
6 |
-
* @version 6.0
|
7 |
* */
|
8 |
?>
|
9 |
|
@@ -46,7 +47,7 @@
|
|
46 |
<td width="80%">
|
47 |
<span class='aam-setting-title'><?php echo $product['title'], (!empty($product['tag']) ? '<sup><span class="badge sup">' . $product['tag'] . '</span></sup>' : ''), (!empty($product['version']) ? ' <small class="text-muted">' . $product['version'] . '</small>' : ''); ?></span>
|
48 |
<?php if (!empty($product['license'])) { ?>
|
49 |
-
<small class="aam-license-key"><b><?php echo __('License', AAM_KEY); ?>:</b> <a href="https://aamplugin.com/license/<?php echo $product['license']; ?>" target="_blank"><?php echo $product['license']; ?></a
|
50 |
<?php } elseif (!empty($product['version'])) { ?>
|
51 |
<small class="aam-license-key"><b><?php echo __('License', AAM_KEY); ?>:</b> <span class="text-danger"><?php echo __('unregistered version', AAM_KEY); ?></span></small>
|
52 |
<?php } ?>
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @since 6.2.0 Removed expiration date for license to avoid confusion
|
4 |
* @since 6.0.5 Fixed typo in the license expiration property. Enriched plugin' status display
|
5 |
* @since 6.0.0 Initial implementation of the template
|
6 |
*
|
7 |
+
* @version 6.2.0
|
8 |
* */
|
9 |
?>
|
10 |
|
47 |
<td width="80%">
|
48 |
<span class='aam-setting-title'><?php echo $product['title'], (!empty($product['tag']) ? '<sup><span class="badge sup">' . $product['tag'] . '</span></sup>' : ''), (!empty($product['version']) ? ' <small class="text-muted">' . $product['version'] . '</small>' : ''); ?></span>
|
49 |
<?php if (!empty($product['license'])) { ?>
|
50 |
+
<small class="aam-license-key"><b><?php echo __('License', AAM_KEY); ?>:</b> <a href="https://aamplugin.com/license/<?php echo $product['license']; ?>" target="_blank"><?php echo $product['license']; ?></a></small>
|
51 |
<?php } elseif (!empty($product['version'])) { ?>
|
52 |
<small class="aam-license-key"><b><?php echo __('License', AAM_KEY); ?>:</b> <span class="text-danger"><?php echo __('unregistered version', AAM_KEY); ?></span></small>
|
53 |
<?php } ?>
|
application/Backend/tmpl/page/current-subject.php
CHANGED
@@ -1,9 +1,21 @@
|
|
1 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
<?php if (defined('AAM_KEY')) { ?>
|
4 |
<div class="row" id="aam-subject-banner">
|
5 |
<div class="col-xs-12 col-md-8">
|
6 |
<div class="aam-current-subject"></div>
|
|
|
|
|
|
|
|
|
|
|
7 |
</div>
|
8 |
</div>
|
9 |
<?php }
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @since 6.2.0 Added `aam_top_subject_actions_filter` hook
|
4 |
+
* @since 6.0.0 Initial implementation of the template
|
5 |
+
*
|
6 |
+
* @version 6.2.0
|
7 |
+
* */
|
8 |
+
?>
|
9 |
|
10 |
<?php if (defined('AAM_KEY')) { ?>
|
11 |
<div class="row" id="aam-subject-banner">
|
12 |
<div class="col-xs-12 col-md-8">
|
13 |
<div class="aam-current-subject"></div>
|
14 |
+
<div class="subject-top-actions">
|
15 |
+
<?php foreach(apply_filters('aam_top_subject_actions_filter', array()) as $action) { ?>
|
16 |
+
<a href="#" id="<?php echo $action['id']; ?>" data-toggle="tooltip" title="<?php echo $action['tooltip']; ?>"><i class="<?php echo $action['icon']; ?>"></i></a>
|
17 |
+
<?php } ?>
|
18 |
+
</div>
|
19 |
</div>
|
20 |
</div>
|
21 |
<?php }
|
application/Backend/tmpl/page/subject-panel.php
CHANGED
@@ -1,4 +1,11 @@
|
|
1 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
<?php if (defined('AAM_KEY')) { ?>
|
4 |
<div class="metabox-holder main-metabox">
|
@@ -35,7 +42,7 @@
|
|
35 |
<tr>
|
36 |
<th>ID</th>
|
37 |
<th>Users</th>
|
38 |
-
<th width="
|
39 |
<th><?php echo __('Action', AAM_KEY); ?></th>
|
40 |
<th>Level</th>
|
41 |
</tr>
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @since 6.2.0 Changed the size of the "Role Name" column to 60%
|
4 |
+
* @since 6.0.0 Initial implementation of the template
|
5 |
+
*
|
6 |
+
* @version 6.2.0
|
7 |
+
* */
|
8 |
+
?>
|
9 |
|
10 |
<?php if (defined('AAM_KEY')) { ?>
|
11 |
<div class="metabox-holder main-metabox">
|
42 |
<tr>
|
43 |
<th>ID</th>
|
44 |
<th>Users</th>
|
45 |
+
<th width="60%"><?php echo __('Role', AAM_KEY); ?></th>
|
46 |
<th><?php echo __('Action', AAM_KEY); ?></th>
|
47 |
<th>Level</th>
|
48 |
</tr>
|
application/Backend/tmpl/partial/post-access-form.php
CHANGED
@@ -1,4 +1,11 @@
|
|
1 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
<?php if (defined('AAM_KEY')) { ?>
|
4 |
<div class="aam-overwrite<?php echo $params->object->isOverwritten() ? '' : ' hidden'; ?>" id="post-term-overwritten">
|
@@ -32,10 +39,10 @@
|
|
32 |
<?php } ?>
|
33 |
<p class="aam-hint">
|
34 |
<?php echo str_replace(
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
</p>
|
40 |
</td>
|
41 |
<td>
|
@@ -48,6 +55,60 @@
|
|
48 |
</tbody>
|
49 |
</table>
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
<div class="modal fade" id="modal-teaser" tabindex="-1" role="dialog">
|
52 |
<div class="modal-dialog" role="document">
|
53 |
<div class="modal-content">
|
@@ -133,14 +194,14 @@
|
|
133 |
<div class="form-group post-redirect-value" id="post-redirect-page-value-container" style="display: <?php echo ($type === 'page' ? 'block' : 'none'); ?>;">
|
134 |
<label><?php echo __('Existing Page', AAM_KEY); ?></label>
|
135 |
<?php
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
?>
|
145 |
</div>
|
146 |
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @since 6.2.0 Added "Hidden" modal for more granular access controls
|
4 |
+
* @since 6.0.0 Initial implementation of the template
|
5 |
+
*
|
6 |
+
* @version 6.2.0
|
7 |
+
* */
|
8 |
+
?>
|
9 |
|
10 |
<?php if (defined('AAM_KEY')) { ?>
|
11 |
<div class="aam-overwrite<?php echo $params->object->isOverwritten() ? '' : ' hidden'; ?>" id="post-term-overwritten">
|
39 |
<?php } ?>
|
40 |
<p class="aam-hint">
|
41 |
<?php echo str_replace(
|
42 |
+
array('{postType}'),
|
43 |
+
array(get_post_type_labels($params->postType)->singular_name),
|
44 |
+
$data['description']
|
45 |
+
); ?>
|
46 |
</p>
|
47 |
</td>
|
48 |
<td>
|
55 |
</tbody>
|
56 |
</table>
|
57 |
|
58 |
+
<div class="modal fade" id="modal-hidden" tabindex="-1" role="dialog">
|
59 |
+
<div class="modal-dialog" role="document">
|
60 |
+
<div class="modal-content">
|
61 |
+
<div class="modal-header">
|
62 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">×</span></button>
|
63 |
+
<h4 class="modal-title"><?php echo __('Hidden Areas', AAM_KEY); ?></h4>
|
64 |
+
</div>
|
65 |
+
<div class="modal-body">
|
66 |
+
<table class="table table-striped table-bordered">
|
67 |
+
<tbody>
|
68 |
+
<tr>
|
69 |
+
<td>
|
70 |
+
<span class='aam-setting-title'><?php echo __('Frontend', AAM_KEY); ?></span>
|
71 |
+
<p class="aam-setting-description">
|
72 |
+
<?php echo __('Hide post on the frontend site of the website'); ?>
|
73 |
+
</p>
|
74 |
+
</td>
|
75 |
+
<td class="text-center">
|
76 |
+
<input data-toggle="toggle" name="hidden.frontend" id="hidden-frontend" type="checkbox" <?php echo ($params->object->get('hidden.frontend') ? 'checked' : ''); ?> data-on="<?php echo __('Hidden', AAM_KEY); ?>" data-off="<?php echo __('Visible', AAM_KEY); ?>" data-size="small" data-onstyle="danger" data-offstyle="success" />
|
77 |
+
</td>
|
78 |
+
</tr>
|
79 |
+
<tr>
|
80 |
+
<td>
|
81 |
+
<span class='aam-setting-title'><?php echo __('Backend', AAM_KEY); ?></span>
|
82 |
+
<p class="aam-setting-description">
|
83 |
+
<?php echo __('Hide post on the backend site of the website'); ?>
|
84 |
+
</p>
|
85 |
+
</td>
|
86 |
+
<td class="text-center">
|
87 |
+
<input data-toggle="toggle" name="hidden.backend" id="hidden-backend" type="checkbox" <?php echo ($params->object->get('hidden.backend') ? 'checked' : ''); ?> data-on="<?php echo __('Hidden', AAM_KEY); ?>" data-off="<?php echo __('Visible', AAM_KEY); ?>" data-size="small" data-onstyle="danger" data-offstyle="success" />
|
88 |
+
</td>
|
89 |
+
</tr>
|
90 |
+
<tr>
|
91 |
+
<td>
|
92 |
+
<span class='aam-setting-title'><?php echo __('RESTful API', AAM_KEY); ?></span>
|
93 |
+
<p class="aam-setting-description">
|
94 |
+
<?php echo __('Hide post in the RESTful API response'); ?>
|
95 |
+
</p>
|
96 |
+
</td>
|
97 |
+
<td class="text-center">
|
98 |
+
<input data-toggle="toggle" name="hidden.api" id="hidden-api" type="checkbox" <?php echo ($params->object->get('hidden.api') ? 'checked' : ''); ?> data-on="<?php echo __('Hidden', AAM_KEY); ?>" data-off="<?php echo __('Visible', AAM_KEY); ?>" data-size="small" data-onstyle="danger" data-offstyle="success" />
|
99 |
+
</td>
|
100 |
+
</tr>
|
101 |
+
</tbody>
|
102 |
+
</table>
|
103 |
+
</div>
|
104 |
+
<div class="modal-footer">
|
105 |
+
<button type="button" class="btn btn-success btn-save" id="save-hidden-btn"><?php echo __('Save', AAM_KEY); ?></button>
|
106 |
+
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Close', AAM_KEY); ?></button>
|
107 |
+
</div>
|
108 |
+
</div>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
|
112 |
<div class="modal fade" id="modal-teaser" tabindex="-1" role="dialog">
|
113 |
<div class="modal-dialog" role="document">
|
114 |
<div class="modal-content">
|
194 |
<div class="form-group post-redirect-value" id="post-redirect-page-value-container" style="display: <?php echo ($type === 'page' ? 'block' : 'none'); ?>;">
|
195 |
<label><?php echo __('Existing Page', AAM_KEY); ?></label>
|
196 |
<?php
|
197 |
+
wp_dropdown_pages(array(
|
198 |
+
'depth' => 99,
|
199 |
+
'echo' => 1,
|
200 |
+
'selected' => ($type === 'page' ? $params->object->get('redirected.destination') : null),
|
201 |
+
'id' => 'post-redirect-page-value',
|
202 |
+
'class' => 'form-control',
|
203 |
+
'show_option_none' => __('-- Select Page --', AAM_KEY)
|
204 |
+
));
|
205 |
?>
|
206 |
</div>
|
207 |
|
application/Backend/tmpl/service/policy.php
CHANGED
@@ -1,3 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php if (defined('AAM_KEY')) { ?>
|
2 |
<div class="aam-feature" id="policy-content">
|
3 |
<?php if (defined('AAM_PLUS_PACKAGE') || !AAM_Backend_Subject::getInstance()->isDefault()) { ?>
|
@@ -27,12 +35,71 @@
|
|
27 |
<th width="80%"><?php echo __('Policy', AAM_KEY); ?></th>
|
28 |
<th><?php echo __('Actions', AAM_KEY); ?></th>
|
29 |
<th>Edit Link</th>
|
|
|
30 |
</tr>
|
31 |
</thead>
|
32 |
<tbody></tbody>
|
33 |
</table>
|
34 |
</div>
|
35 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
<?php } else { ?>
|
37 |
<div class="row">
|
38 |
<div class="col-xs-12">
|
@@ -43,4 +110,4 @@
|
|
43 |
</div>
|
44 |
<?php } ?>
|
45 |
</div>
|
46 |
-
<?php }
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @since 6.2.0 Enhanced the table with new functionality
|
4 |
+
* @since 6.0.0 Initial implementation of the template
|
5 |
+
*
|
6 |
+
* @version 6.2.0
|
7 |
+
* */
|
8 |
+
?>
|
9 |
<?php if (defined('AAM_KEY')) { ?>
|
10 |
<div class="aam-feature" id="policy-content">
|
11 |
<?php if (defined('AAM_PLUS_PACKAGE') || !AAM_Backend_Subject::getInstance()->isDefault()) { ?>
|
35 |
<th width="80%"><?php echo __('Policy', AAM_KEY); ?></th>
|
36 |
<th><?php echo __('Actions', AAM_KEY); ?></th>
|
37 |
<th>Edit Link</th>
|
38 |
+
<th>Just Title</th>
|
39 |
</tr>
|
40 |
</thead>
|
41 |
<tbody></tbody>
|
42 |
</table>
|
43 |
</div>
|
44 |
</div>
|
45 |
+
|
46 |
+
<div class="modal fade" id="delete-policy-modal" tabindex="-1" role="dialog">
|
47 |
+
<div class="modal-dialog" role="document">
|
48 |
+
<div class="modal-content">
|
49 |
+
<div class="modal-header">
|
50 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">×</span></button>
|
51 |
+
<h4 class="modal-title"><?php echo __('Delete Policy', AAM_KEY); ?></h4>
|
52 |
+
</div>
|
53 |
+
<div class="modal-body">
|
54 |
+
<p class="text-center aam-confirm-message alert alert-danger" data-message="<?php echo __('You are about to delete the %s policy. Please confirm.', AAM_KEY); ?>"></p>
|
55 |
+
</div>
|
56 |
+
<div class="modal-footer">
|
57 |
+
<button type="button" class="btn btn-danger" id="delete-policy-btn"><?php echo __('Delete Policy', AAM_KEY); ?></button>
|
58 |
+
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Close', AAM_KEY); ?></button>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
|
64 |
+
<div class="modal fade" id="modal-install-policy" tabindex="-1" role="dialog">
|
65 |
+
<div class="modal-dialog" role="document">
|
66 |
+
<div class="modal-content">
|
67 |
+
<div class="modal-header">
|
68 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">×</span></button>
|
69 |
+
<h4 class="modal-title text-left"><?php echo __('Install Access Policy', AAM_KEY); ?></h4>
|
70 |
+
</div>
|
71 |
+
<div class="modal-body">
|
72 |
+
<p class="alert alert-info"><?php echo sprintf(__('Install an access policy from the official %sAAM Access Policy Hub%s. Insert the policy ID and it will be automatically downloaded and applied to proper assignees.', AAM_KEY), '<a href="https://aamplugin.com/access-policy-hub" target="_blank">', '</a>'); ?></p>
|
73 |
+
|
74 |
+
<div class="input-group aam-outer-top-xs">
|
75 |
+
<input type="text" class="form-control" placeholder="<?php echo __('Insert Policy ID', AAM_KEY); ?>" id="policy-id" aria-describedby="basic-addon2" />
|
76 |
+
<span class="input-group-addon" id="basic-addon2"><?php echo __('Fetch', AAM_KEY); ?></span>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<table class="table table-striped table-bordered aam-ghost aam-outer-top-xxs" id="policy-details">
|
80 |
+
<tbody>
|
81 |
+
<tr>
|
82 |
+
<th width="30" class="text-muted"><?php echo __('Title', AAM_KEY); ?></th>
|
83 |
+
<td id="policy-title"></td>
|
84 |
+
</tr>
|
85 |
+
<tr>
|
86 |
+
<th width="30" class="text-muted"><?php echo __('Description', AAM_KEY); ?></th>
|
87 |
+
<td id="policy-description"></td>
|
88 |
+
</tr>
|
89 |
+
<tr>
|
90 |
+
<th width="30" class="text-muted"><?php echo __('Assignee(s)', AAM_KEY); ?></th>
|
91 |
+
<td id="policy-subjects"></td>
|
92 |
+
</tr>
|
93 |
+
</tbody>
|
94 |
+
</table>
|
95 |
+
</div>
|
96 |
+
<div class="modal-footer">
|
97 |
+
<button type="button" class="btn btn-success" disabled id="install-policy"><?php echo __('Install', AAM_KEY); ?></button>
|
98 |
+
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo __('Close', AAM_KEY); ?></button>
|
99 |
+
</div>
|
100 |
+
</div>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
<?php } else { ?>
|
104 |
<div class="row">
|
105 |
<div class="col-xs-12">
|
110 |
</div>
|
111 |
<?php } ?>
|
112 |
</div>
|
113 |
+
<?php }
|
application/Core/AccessSettings.php
CHANGED
@@ -5,15 +5,16 @@
|
|
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 |
-
* @version 6.0.0
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
* AAM Access Settings repository
|
14 |
*
|
|
|
|
|
|
|
15 |
* @package AAM
|
16 |
-
* @version 6.
|
17 |
*/
|
18 |
class AAM_Core_AccessSettings
|
19 |
{
|
@@ -137,12 +138,19 @@ class AAM_Core_AccessSettings
|
|
137 |
*
|
138 |
* @return boolean
|
139 |
*
|
|
|
|
|
|
|
140 |
* @access public
|
141 |
-
* @version 6.
|
142 |
*/
|
143 |
public function save()
|
144 |
{
|
145 |
-
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
/**
|
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 |
* AAM Access Settings repository
|
12 |
*
|
13 |
+
* @since 6.2.0 Added new hook `aam_updated_access_settings`
|
14 |
+
* @since 6.0.0 Initial implementation of the class
|
15 |
+
*
|
16 |
* @package AAM
|
17 |
+
* @version 6.2.0
|
18 |
*/
|
19 |
class AAM_Core_AccessSettings
|
20 |
{
|
138 |
*
|
139 |
* @return boolean
|
140 |
*
|
141 |
+
* @since 6.2.0 Added `aam_updated_access_settings` hook
|
142 |
+
* @since 6.0.0 Initial implementation of the method
|
143 |
+
*
|
144 |
* @access public
|
145 |
+
* @version 6.2.0
|
146 |
*/
|
147 |
public function save()
|
148 |
{
|
149 |
+
$result = AAM_Core_API::updateOption(self::DB_OPTION, $this->_settings);
|
150 |
+
|
151 |
+
do_action('aam_updated_access_settings', $this->_settings);
|
152 |
+
|
153 |
+
return $result;
|
154 |
}
|
155 |
|
156 |
/**
|
application/Core/Policy/Condition.php
CHANGED
@@ -10,11 +10,12 @@
|
|
10 |
/**
|
11 |
* AAM core policy condition evaluator
|
12 |
*
|
|
|
13 |
* @since 6.1.0 Improved type casting functionality
|
14 |
* @since 6.0.0 Initial implementation of the class
|
15 |
*
|
16 |
* @package AAM
|
17 |
-
* @version 6.
|
18 |
*/
|
19 |
class AAM_Core_Policy_Condition
|
20 |
{
|
@@ -383,11 +384,12 @@ class AAM_Core_Policy_Condition
|
|
383 |
*
|
384 |
* @return mixed Prepared part of the condition or false on failure
|
385 |
*
|
|
|
386 |
* @since 6.1.0 Improved type casing functionality
|
387 |
* @since 6.0.0 Initial implementation of the method
|
388 |
*
|
389 |
* @access protected
|
390 |
-
* @version 6.
|
391 |
*/
|
392 |
public function parseExpression($exp, $args)
|
393 |
{
|
@@ -396,7 +398,7 @@ class AAM_Core_Policy_Condition
|
|
396 |
$exp = AAM_Core_Policy_Token::evaluate($exp, $match[1], $args);
|
397 |
}
|
398 |
|
399 |
-
$types = 'string|ip|int|boolean|bool|array|null';
|
400 |
|
401 |
// Note! It make no sense to have multiple type casting for one expression
|
402 |
// due to the fact that they all would have to be concatenated as a string
|
@@ -424,12 +426,13 @@ class AAM_Core_Policy_Condition
|
|
424 |
*
|
425 |
* @return mixed
|
426 |
*
|
|
|
427 |
* @version 6.1.0 Renamed the method from `castValue` to `_typecast`. Added new
|
428 |
* filter `aam_token_typecast_filter`
|
429 |
* @version 6.0.0 Initial implementation of the method
|
430 |
*
|
431 |
* @access protected
|
432 |
-
* @version 6.
|
433 |
*/
|
434 |
private function _typecast($value, $type)
|
435 |
{
|
@@ -459,6 +462,22 @@ class AAM_Core_Policy_Condition
|
|
459 |
$value = ($value === '' ? null : $value);
|
460 |
break;
|
461 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
default:
|
463 |
$value = apply_filters('aam_token_typecast_filter', $value, $type);
|
464 |
break;
|
10 |
/**
|
11 |
* AAM core policy condition evaluator
|
12 |
*
|
13 |
+
* @since 6.2.0 Added support for the (*date) type casting
|
14 |
* @since 6.1.0 Improved type casting functionality
|
15 |
* @since 6.0.0 Initial implementation of the class
|
16 |
*
|
17 |
* @package AAM
|
18 |
+
* @version 6.2.0
|
19 |
*/
|
20 |
class AAM_Core_Policy_Condition
|
21 |
{
|
384 |
*
|
385 |
* @return mixed Prepared part of the condition or false on failure
|
386 |
*
|
387 |
+
* @since 6.2.0 Added support for new `date` type
|
388 |
* @since 6.1.0 Improved type casing functionality
|
389 |
* @since 6.0.0 Initial implementation of the method
|
390 |
*
|
391 |
* @access protected
|
392 |
+
* @version 6.2.0
|
393 |
*/
|
394 |
public function parseExpression($exp, $args)
|
395 |
{
|
398 |
$exp = AAM_Core_Policy_Token::evaluate($exp, $match[1], $args);
|
399 |
}
|
400 |
|
401 |
+
$types = 'string|ip|int|boolean|bool|array|null|date';
|
402 |
|
403 |
// Note! It make no sense to have multiple type casting for one expression
|
404 |
// due to the fact that they all would have to be concatenated as a string
|
426 |
*
|
427 |
* @return mixed
|
428 |
*
|
429 |
+
* @version 6.2.0 Added support for the `date` type
|
430 |
* @version 6.1.0 Renamed the method from `castValue` to `_typecast`. Added new
|
431 |
* filter `aam_token_typecast_filter`
|
432 |
* @version 6.0.0 Initial implementation of the method
|
433 |
*
|
434 |
* @access protected
|
435 |
+
* @version 6.2.0
|
436 |
*/
|
437 |
private function _typecast($value, $type)
|
438 |
{
|
462 |
$value = ($value === '' ? null : $value);
|
463 |
break;
|
464 |
|
465 |
+
case 'date':
|
466 |
+
try {
|
467 |
+
$value = new DateTime(
|
468 |
+
$value,
|
469 |
+
new DateTimeZone('UTC')
|
470 |
+
);
|
471 |
+
} catch(Exception $e) {
|
472 |
+
_doing_it_wrong(
|
473 |
+
__CLASS__ . '::' . __METHOD__,
|
474 |
+
'Cannot typecast value to DateTime',
|
475 |
+
AAM_VERSION
|
476 |
+
);
|
477 |
+
$value = null;
|
478 |
+
}
|
479 |
+
break;
|
480 |
+
|
481 |
default:
|
482 |
$value = apply_filters('aam_token_typecast_filter', $value, $type);
|
483 |
break;
|
application/Core/Policy/Generator.php
ADDED
@@ -0,0 +1,505 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|