Version Description
- Important: iThemes Security requires PHP 5.6 or greater and WordPress 5.2 or greater.
- New Feature: Save Time Securing WordPress With User Groups!
- New Feature: Simplified connection flow when setting up iThemes Sync.
- Enhancement: Add a warning if a WordPress Salt is set to an invalid value.
- Enhancement: Include child log items in the logs list table. These are helpful for debugging issues.
- Enhancement: Improve performance of the logs page on sites with large number of log items.
- Enhancement: Check tables exist after completing a DB upgrade.
- Tweak: When logging $_SERVER, only log a snapshot of available properties.
- Bug Fix: The "Mulisite Tweaks -> Hide Updates" setting prevented auto-updates from running with WP Cron.
- Bug Fix: Backup event was not added when the WP Cron Scheduler was reset manually.
- Bug Fix: Admin Notices Popover was not being hidden when clicking outside the Popover on WP 5.3.
- Bug Fix: New Password Requirements for already created accounts were not enforced until the second login.
- Bug Fix: Update admin notices styling to be compatible with WordPress 5.4.
- Bug Fix: Periodically clear expired opaque tokens.
- Bug Fix: Don't block registration page when "wp-signup.php" is the Hide Backend register slug.
- Bug Fix: Users with weak passwords would not be forced to change their password if the strong password requirement had been enabled after their password strength was checked.
- Bug Fix: Remove "get_magic_quotes()" call that existed for backwards compatibility with PHP versions 5.3 and earlier. This function call was causing a warning on PHP 7.4.
- Bug Fix: Warning when loading the settings page on PHP 7.4.
- Bug Fix: Warning when loading the debug page on PHP 7.4.
Download this release
Release Info
Developer | TimothyBlynJacobs |
Plugin | iThemes Security (formerly Better WP Security) |
Version | 7.7.0 |
Comparing to | |
See all releases |
Code changes from version 7.6.1 to 7.7.0
- better-wp-security.php +17 -3
- composer.json +34 -0
- core/Contracts/Runnable.php +12 -0
- core/Contracts/index.php +1 -0
- core/Exception/Exception.php +7 -0
- core/Exception/Invalid_Argument_Exception.php +7 -0
- core/Exception/Unsatisfied_Module_Dependencies_Exception.php +7 -0
- core/Exception/WP_Error.php +36 -0
- core/Exception/index.php +1 -0
- core/admin-pages/css/style.css +48 -7
- core/admin-pages/init.php +4 -2
- core/admin-pages/js/form-user-groups.js +103 -0
- core/admin-pages/js/lib/index.php +1 -0
- core/admin-pages/js/lib/jquery.multiselect.css +148 -0
- core/admin-pages/js/lib/jquery.multiselect.js +936 -0
- core/admin-pages/js/script.js +0 -1135
- core/admin-pages/js/util.js +40 -14
- core/admin-pages/logs-list-table.php +5 -48
- core/admin-pages/module-settings.php +8 -1
- core/admin-pages/page-debug.php +15 -8
- core/admin-pages/page-settings.php +37 -17
- core/composer.json +31 -0
- core/core.php +244 -56
- core/history.txt +38 -0
- core/img/bb-ad.jpg +0 -0
- core/lib.php +234 -19
- core/lib/class-itsec-lib-canonical-roles.php +68 -14
- core/lib/class-itsec-lib-directory.php +28 -8
- core/lib/class-itsec-lib-feature-flags.php +63 -7
- core/lib/class-itsec-lib-fingerprinting.php +11 -4
- core/lib/class-itsec-lib-login-interstitial.php +3 -1
- core/lib/class-itsec-lib-password-requirements.php +11 -3
- core/lib/class-itsec-lib-remote-messages.php +59 -21
- core/lib/class-itsec-lib-rest.php +85 -0
- core/lib/class-itsec-mutex.php +153 -0
- core/lib/class-itsec-scheduler.php +11 -0
- core/lib/form.php +50 -5
- core/lib/lock.php +0 -47
- core/lib/log-util.php +47 -16
- core/lib/log.php +2 -0
- core/lib/login-interstitial/class-itsec-login-interstitial-session.php +42 -1
- core/lib/mail-templates/small-code.html +1 -1
- core/lib/schema.php +59 -3
- core/lib/settings.php +20 -1
- core/lib/validator.php +167 -127
- core/modules.php +172 -53
- core/modules/404-detection/class-itsec-four-oh-four.php +1 -1
- core/modules/404-detection/labels.php +5 -0
- core/modules/admin-user/labels.php +5 -0
- core/modules/away-mode/labels.php +5 -0
- core/modules/backup/activate.php +2 -1
- core/modules/backup/labels.php +5 -0
- core/modules/backup/settings.php +2 -1
- core/modules/ban-users/labels.php +5 -0
- core/modules/ban-users/lists/user-agents.php +1543 -0
- core/modules/brute-force/class-itsec-brute-force.php +1 -1
- core/modules/brute-force/labels.php +5 -0
- core/modules/content-directory/labels.php +5 -0
- core/modules/core/entries/admin-notices/components/admin-bar/index.js +17 -4
- core/modules/core/entries/admin-notices/components/admin-bar/style.scss +2 -0
- core/modules/core/entries/admin-notices/components/panel/style.scss +2 -2
- core/modules/core/entries/admin-notices/components/toolbar/index.js +16 -3
- core/modules/core/entries/admin-notices/store/controls.js +1 -1
- core/modules/core/labels.php +5 -0
- core/modules/core/notices.php +73 -0
- core/modules/database-prefix/labels.php +5 -0
- core/modules/feature-flags/labels.php +5 -0
- core/modules/feature-flags/settings-page.php +19 -6
- core/modules/file-change/labels.php +5 -0
- core/modules/file-permissions/labels.php +5 -0
- core/modules/global/active.php +14 -0
- core/modules/global/labels.php +5 -0
- core/modules/global/settings-page.php +13 -0
- core/modules/global/settings.php +4 -1
- core/modules/global/validator.php +14 -0
- core/modules/hide-backend/class-itsec-hide-backend.php +25 -14
- core/modules/hide-backend/labels.php +5 -0
- core/modules/hide-backend/settings.php +1 -0
- core/modules/ipcheck/labels.php +5 -0
- core/modules/malware/labels.php +5 -0
- core/modules/malware/settings-page.php +27 -13
- core/modules/multisite-tweaks/class-itsec-multisite-tweaks.php +9 -9
- core/modules/multisite-tweaks/labels.php +5 -0
- core/modules/multisite-tweaks/settings-page.php +10 -11
- core/modules/notification-center/class-notification-center.php +8 -0
- core/modules/notification-center/labels.php +5 -0
- core/modules/notification-center/settings.php +2 -1
- core/modules/password-requirements/class-itsec-password-requirements.php +26 -4
- core/modules/password-requirements/labels.php +5 -0
- core/modules/password-requirements/settings.php +10 -1
- core/modules/password-requirements/validator.php +2 -1
- core/modules/privacy/labels.php +5 -0
- core/modules/salts/labels.php +5 -0
- core/modules/salts/settings-page.php +29 -10
- core/modules/salts/utilities.php +45 -25
- core/modules/security-check-pro/labels.php +5 -0
- core/modules/security-check-pro/utility.php +14 -6
- core/modules/security-check/labels.php +5 -0
- core/modules/security-check/scanner.php +3 -1
- core/modules/ssl/labels.php +5 -0
- core/modules/strong-passwords/active.php +3 -1
- core/modules/strong-passwords/class-itsec-strong-passwords.php +43 -30
- core/modules/strong-passwords/container.php +9 -0
- core/modules/strong-passwords/labels.php +5 -0
- core/modules/strong-passwords/setup.php +62 -85
- core/modules/sync-connect/active.php +6 -0
- core/modules/sync-connect/class-itsec-sync-connect-interstitial.php +136 -0
- core/modules/sync-connect/class-itsec-sync-connect.php +183 -0
- core/modules/sync-connect/css/connect.css +84 -0
- core/modules/sync-connect/css/index.php +1 -0
- core/modules/sync-connect/img/index.php +1 -0
- core/modules/sync-connect/img/sync-logo.svg +98 -0
- core/modules/sync-connect/includes/index.php +1 -0
- core/modules/sync-connect/includes/upgrader-skin.php +23 -0
- core/modules/sync-connect/index.php +1 -0
- core/modules/sync-connect/labels.php +5 -0
- core/modules/sync-connect/templates/connect-prompt.php +9 -0
- core/modules/sync-connect/templates/connect-unauthorized.php +11 -0
- core/modules/sync-connect/templates/fallback.php +11 -0
- core/modules/sync-connect/templates/index.php +1 -0
- core/modules/sync-connect/templates/or.php +3 -0
- core/modules/sync-connect/templates/prompt-link.php +9 -0
- core/modules/system-tweaks/labels.php +5 -0
- core/modules/user-groups/All_Users.php +17 -0
- core/modules/user-groups/Everybody_Else.php +38 -0
- core/modules/user-groups/Match/Default_Matcher.php +33 -0
- core/modules/user-groups/Match/Match_Target.php +66 -0
- core/modules/user-groups/Match/Matchable_Not_Found.php +9 -0
- core/modules/user-groups/Match/Matcher.php +16 -0
- core/modules/user-groups/Match/index.php +1 -0
- core/modules/user-groups/Matchable.php +29 -0
- core/modules/user-groups/Matchables_Source.php +77 -0
- core/modules/user-groups/Module/Module.php +95 -0
- core/modules/user-groups/Module/Settings.php +149 -0
- core/modules/user-groups/Module/Validator.php +19 -0
- core/modules/user-groups/Module/index.php +1 -0
- core/modules/user-groups/REST/Matchables.php +133 -0
- core/modules/user-groups/REST/REST.php +28 -0
- core/modules/user-groups/REST/Settings.php +355 -0
- core/modules/user-groups/REST/User_Groups.php +467 -0
- core/modules/user-groups/REST/index.php +1 -0
- core/modules/user-groups/Repository/DB_Repository.php +139 -0
- core/modules/user-groups/Repository/Decorator.php +35 -0
- core/modules/user-groups/Repository/Eager_Loading_Decorator.php +68 -0
- core/modules/user-groups/Repository/In_Memory_Repository.php +72 -0
- core/modules/user-groups/Repository/Object_Caching_Decorator.php +118 -0
- core/modules/user-groups/Repository/Repository.php +62 -0
- core/modules/user-groups/Repository/User_Group_Not_Found.php +9 -0
- core/modules/user-groups/Repository/index.php +1 -0
- core/modules/user-groups/Settings/Settings_Proxy.php +46 -0
- core/modules/user-groups/Settings/Settings_Registration.php +87 -0
- core/modules/user-groups/Settings/Settings_Registry.php +73 -0
- core/modules/user-groups/Settings/index.php +1 -0
- core/modules/user-groups/Upgrader.php +76 -0
- core/modules/user-groups/User_Group.php +436 -0
- core/modules/user-groups/container.php +90 -0
- core/modules/user-groups/entries/api.js +3 -0
- core/modules/user-groups/entries/index.php +1 -0
- core/modules/user-groups/entries/settings.js +37 -0
- core/modules/user-groups/entries/settings/app.js +26 -0
- core/modules/user-groups/entries/settings/components/edit-group-fields/index.js +17 -0
- core/modules/user-groups/entries/settings/components/edit-group-fields/index.php +1 -0
- core/modules/user-groups/entries/settings/components/edit-group-fields/style.scss +9 -0
- core/modules/user-groups/entries/settings/components/group-header/index.js +17 -0
- core/modules/user-groups/entries/settings/components/group-header/index.php +1 -0
- core/modules/user-groups/entries/settings/components/group-header/multi.js +22 -0
- core/modules/user-groups/entries/settings/components/group-header/new.js +29 -0
- core/modules/user-groups/entries/settings/components/group-header/single.js +58 -0
- core/modules/user-groups/entries/settings/components/group-header/style.scss +20 -0
- core/modules/user-groups/entries/settings/components/group-label/index.js +34 -0
- core/modules/user-groups/entries/settings/components/group-label/index.php +1 -0
- core/modules/user-groups/entries/settings/components/group-label/style.scss +3 -0
- core/modules/user-groups/entries/settings/components/group-nav/index.js +111 -0
- core/modules/user-groups/entries/settings/components/group-nav/index.php +1 -0
- core/modules/user-groups/entries/settings/components/group-nav/style.scss +46 -0
- core/modules/user-groups/entries/settings/components/index.js +16 -0
- core/modules/user-groups/entries/settings/components/index.php +1 -0
- core/modules/user-groups/entries/settings/components/layout/index.js +9 -0
- core/modules/user-groups/entries/settings/components/layout/index.php +1 -0
- core/modules/user-groups/entries/settings/components/manage-group/index.js +70 -0
- core/modules/user-groups/entries/settings/components/manage-group/index.php +1 -0
- core/modules/user-groups/entries/settings/components/manage-group/style.scss +51 -0
- core/modules/user-groups/entries/settings/components/manage-multiple-groups/index.js +39 -0
- core/modules/user-groups/entries/settings/components/manage-multiple-groups/index.php +1 -0
- core/modules/user-groups/entries/settings/components/panel-minimum-role/index.js +36 -0
- core/modules/user-groups/entries/settings/components/panel-minimum-role/index.php +1 -0
- core/modules/user-groups/entries/settings/components/panel-roles/index.js +114 -0
- core/modules/user-groups/entries/settings/components/panel-roles/index.php +1 -0
- core/modules/user-groups/entries/settings/components/panel-users/index.js +90 -0
- core/modules/user-groups/entries/settings/components/panel-users/index.php +1 -0
- core/modules/user-groups/entries/settings/components/panel-users/style.scss +11 -0
- core/modules/user-groups/entries/settings/components/settings-form/index.js +25 -0
- core/modules/user-groups/entries/settings/components/settings-form/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-body/index.js +30 -0
- core/modules/user-groups/entries/settings/components/tab-body/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-body/style.scss +15 -0
- core/modules/user-groups/entries/settings/components/tab-create-group/index.js +37 -0
- core/modules/user-groups/entries/settings/components/tab-create-group/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-edit-group/index.js +39 -0
- core/modules/user-groups/entries/settings/components/tab-edit-group/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-settings-bulk/field.js +33 -0
- core/modules/user-groups/entries/settings/components/tab-settings-bulk/index.js +47 -0
- core/modules/user-groups/entries/settings/components/tab-settings-bulk/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-settings/field.js +29 -0
- core/modules/user-groups/entries/settings/components/tab-settings/index.js +48 -0
- core/modules/user-groups/entries/settings/components/tab-settings/index.php +1 -0
- core/modules/user-groups/entries/settings/components/tab-settings/style.scss +15 -0
- core/modules/user-groups/entries/settings/index.php +1 -0
- core/modules/user-groups/entries/settings/store/actions.js +226 -0
- core/modules/user-groups/entries/settings/store/controls.js +135 -0
- core/modules/user-groups/entries/settings/store/index.js +23 -0
- core/modules/user-groups/entries/settings/store/index.php +1 -0
- core/modules/user-groups/entries/settings/store/reducers.js +116 -0
- core/modules/user-groups/entries/settings/store/resolvers.js +14 -0
- core/modules/user-groups/entries/settings/store/selectors.js +188 -0
- core/modules/user-groups/entries/settings/style.scss +0 -0
- core/modules/user-groups/entries/store/actions.js +404 -0
- core/modules/user-groups/entries/store/controls.js +83 -0
- core/modules/user-groups/entries/store/index.js +23 -0
- core/modules/user-groups/entries/store/index.php +1 -0
- core/modules/user-groups/entries/store/reducers.js +199 -0
- core/modules/user-groups/entries/store/resolvers.js +54 -0
- core/modules/user-groups/entries/store/selectors.js +204 -0
- core/modules/user-groups/index.php +1 -0
- core/modules/user-groups/labels.php +5 -0
- core/modules/user-groups/settings-page.php +43 -0
- core/modules/wordpress-tweaks/labels.php +5 -0
- core/package.json +17 -11
- core/packages/components/src/checkbox-control/index.js +44 -0
- core/packages/components/src/checkbox-control/index.php +1 -0
- core/packages/components/src/checkbox-control/style.scss +111 -0
- core/packages/components/src/checkbox-group-control/index.js +35 -0
- core/packages/components/src/checkbox-group-control/index.php +1 -0
- core/packages/components/src/hierarchical-checkbox-control/index.js +267 -0
- core/packages/components/src/hierarchical-checkbox-control/index.php +1 -0
- core/packages/components/src/hierarchical-checkbox-control/style.scss +20 -0
- core/packages/components/src/index.js +7 -0
- core/packages/components/src/module-settings-notice-list/index.js +95 -0
- core/packages/components/src/module-settings-notice-list/index.php +1 -0
- core/packages/components/src/module-settings-notice-list/notice.js +54 -0
- core/packages/components/src/module-settings-notice-list/style.scss +25 -0
- core/packages/components/src/notice-list/index.js +48 -0
- core/packages/components/src/notice-list/index.php +1 -0
- core/packages/components/src/tab-panel/controlled.js +98 -0
- core/packages/components/src/tab-panel/index.js +30 -0
- core/packages/components/src/tab-panel/index.php +1 -0
- core/packages/components/src/tab-panel/multi.js +277 -0
- core/packages/components/src/tab-panel/tab-button.js +16 -0
- core/packages/components/src/toggle-control/index.js +68 -0
- core/packages/components/src/toggle-control/index.php +1 -0
- core/packages/components/src/toggle-control/style.scss +3 -0
- core/packages/data/index.php +1 -0
- core/packages/data/src/actions.js +40 -0
- core/packages/data/src/controls.js +172 -0
- core/packages/data/src/index.js +21 -0
- core/packages/data/src/index.php +1 -0
- core/packages/data/src/reducers.js +34 -0
- core/packages/data/src/resolvers.js +24 -0
- core/packages/data/src/selectors.js +56 -0
- core/packages/hocs/src/index.js +1 -0
- core/packages/hocs/src/with-pressed-modifier-keys.js +78 -0
- core/packages/i18n/index.php +1 -0
- core/packages/i18n/src/index.js +26 -0
- core/packages/i18n/src/index.php +1 -0
- core/packages/preload/index.php +1 -0
- core/packages/preload/src/index.js +78 -0
- core/packages/preload/src/index.php +1 -0
- core/packages/style-guide/src/breakpoints.scss +42 -0
- core/packages/style-guide/src/mixins.scss +53 -0
- core/packages/utils/src/index.js +59 -2
- core/packages/utils/src/wp-error.js +16 -0
- core/packages/webpack/src/babel.js +1 -0
- core/packages/webpack/src/config/index.js +3 -0
- core/response.php +11 -0
- core/rest.php +103 -0
- core/setup.php +133 -6
- dist/8.min.js +1 -0
- dist/core/admin-notices-api.min.js +1 -1
- dist/core/admin-notices-dashboard-admin-bar.min.css +2 -2
- dist/core/admin-notices-dashboard-admin-bar.min.js +1 -1
- dist/core/admin-notices.min.css +1 -1
- dist/core/admin-notices.min.js +1 -1
- dist/manifest.php +110 -8
- dist/packages/index.php +1 -0
- dist/packages/preload.min.js +1 -0
- dist/user-groups/api.min.js +1 -0
- dist/user-groups/index.php +1 -0
- dist/user-groups/settings.min.css +37 -0
- dist/user-groups/settings.min.js +7 -0
- dist/vendors/index.php +1 -0
- dist/vendors/user-groups/api.min.js +1 -0
- dist/vendors/user-groups/index.php +1 -0
- history.txt +20 -2
- package.json +17 -11
- readme.txt +27 -6
- vendor-prod/autoload.php +7 -0
- vendor-prod/composer/ClassLoader.php +445 -0
- vendor-prod/composer/LICENSE +21 -0
- vendor-prod/composer/autoload_classmap.php +327 -0
- vendor-prod/composer/autoload_namespaces.php +10 -0
- vendor-prod/composer/autoload_psr4.php +11 -0
- vendor-prod/composer/autoload_real.php +52 -0
- vendor-prod/composer/autoload_static.php +372 -0
- vendor-prod/composer/index.php +1 -0
- vendor-prod/composer/installed.json +156 -0
- vendor-prod/index.php +1 -0
- vendor-prod/pimple/index.php +1 -0
- vendor-prod/pimple/pimple/CHANGELOG +59 -0
- vendor-prod/pimple/pimple/LICENSE +19 -0
- vendor-prod/pimple/pimple/README.rst +315 -0
better-wp-security.php
CHANGED
@@ -6,14 +6,15 @@
|
|
6 |
Â
* Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
|
7 |
Â
* Author: iThemes
|
8 |
Â
* Author URI: https://ithemes.com
|
9 |
-
* Version: 7.
|
10 |
Â
* Text Domain: better-wp-security
|
11 |
Â
* Network: True
|
12 |
Â
* License: GPLv2
|
13 |
-
* Requires PHP: 5.
|
Â
|
|
14 |
Â
*/
|
15 |
Â
|
16 |
-
if ( version_compare( phpversion(), '5.
|
17 |
Â
function itsec_free_minimum_php_version_notice() {
|
18 |
Â
echo '<div class="notice notice-error"><p>' . esc_html__( 'iThemes Security requires PHP 5.5 or higher.', 'better-wp-security' ) . '</p></div>';
|
19 |
Â
}
|
@@ -23,6 +24,16 @@ if ( version_compare( phpversion(), '5.5.0', '<' ) ) {
|
|
23 |
Â
return;
|
24 |
Â
}
|
25 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
26 |
Â
function itsec_load_textdomain() {
|
27 |
Â
|
28 |
Â
if ( function_exists( 'determine_locale' ) ) {
|
@@ -46,6 +57,9 @@ if ( isset( $itsec_dir ) || class_exists( 'ITSEC_Core' ) ) {
|
|
46 |
Â
return;
|
47 |
Â
}
|
48 |
Â
|
Â
|
|
Â
|
|
Â
|
|
49 |
Â
|
50 |
Â
$itsec_dir = dirname( __FILE__ );
|
51 |
Â
|
6 |
Â
* Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
|
7 |
Â
* Author: iThemes
|
8 |
Â
* Author URI: https://ithemes.com
|
9 |
+
* Version: 7.7.0
|
10 |
Â
* Text Domain: better-wp-security
|
11 |
Â
* Network: True
|
12 |
Â
* License: GPLv2
|
13 |
+
* Requires PHP: 5.6
|
14 |
+
* Requires at least: 5.2
|
15 |
Â
*/
|
16 |
Â
|
17 |
+
if ( version_compare( phpversion(), '5.6.0', '<' ) ) {
|
18 |
Â
function itsec_free_minimum_php_version_notice() {
|
19 |
Â
echo '<div class="notice notice-error"><p>' . esc_html__( 'iThemes Security requires PHP 5.5 or higher.', 'better-wp-security' ) . '</p></div>';
|
20 |
Â
}
|
24 |
Â
return;
|
25 |
Â
}
|
26 |
Â
|
27 |
+
if ( version_compare( $GLOBALS['wp_version'], '5.2.0', '<' ) ) {
|
28 |
+
function itsec_minimum_wp_version_notice() {
|
29 |
+
echo '<div class="notice notice-error"><p>' . esc_html__( 'iThemes Security Pro requires WordPress 5.2 or later.', 'better-wp-security' ) . '</p></div>';
|
30 |
+
}
|
31 |
+
|
32 |
+
add_action( 'admin_notices', 'itsec_minimum_wp_version_notice' );
|
33 |
+
|
34 |
+
return;
|
35 |
+
}
|
36 |
+
|
37 |
Â
function itsec_load_textdomain() {
|
38 |
Â
|
39 |
Â
if ( function_exists( 'determine_locale' ) ) {
|
57 |
Â
return;
|
58 |
Â
}
|
59 |
Â
|
60 |
+
if ( file_exists( __DIR__ . '/vendor-prod/autoload.php' ) ) {
|
61 |
+
require_once( __DIR__ . '/vendor-prod/autoload.php' );
|
62 |
+
}
|
63 |
Â
|
64 |
Â
$itsec_dir = dirname( __FILE__ );
|
65 |
Â
|
composer.json
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
{
|
2 |
+
"name": "ithemes/ithemes-security",
|
3 |
+
"description": "Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.",
|
4 |
+
"type": "wordpress-plugin",
|
5 |
+
"license": "GPL-2.0-or-later",
|
6 |
+
"authors": [
|
7 |
+
{
|
8 |
+
"name": "Timothy Jacobs",
|
9 |
+
"email": "timothy@ithemes.com"
|
10 |
+
},
|
11 |
+
{
|
12 |
+
"name": "Chris Jean",
|
13 |
+
"email": "chris@ithemes.com"
|
14 |
+
}
|
15 |
+
],
|
16 |
+
"minimum-stability": "stable",
|
17 |
+
"require": {
|
18 |
+
"php": "^5.4 | ^7.0",
|
19 |
+
"wikimedia/composer-merge-plugin": "^1.4"
|
20 |
+
},
|
21 |
+
"config": {
|
22 |
+
"platform": {
|
23 |
+
"php": "5.6.0"
|
24 |
+
}
|
25 |
+
},
|
26 |
+
"extra": {
|
27 |
+
"merge-plugin": {
|
28 |
+
"require": [
|
29 |
+
"core/composer.json"
|
30 |
+
],
|
31 |
+
"merge-dev": false
|
32 |
+
}
|
33 |
+
}
|
34 |
+
}
|
core/Contracts/Runnable.php
ADDED
@@ -0,0 +1,12 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\Contracts;
|
4 |
+
|
5 |
+
interface Runnable {
|
6 |
+
/**
|
7 |
+
* Run the class.
|
8 |
+
*
|
9 |
+
* @return void
|
10 |
+
*/
|
11 |
+
public function run();
|
12 |
+
}
|
core/Contracts/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/Exception/Exception.php
ADDED
@@ -0,0 +1,7 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\Exception;
|
4 |
+
|
5 |
+
interface Exception {
|
6 |
+
|
7 |
+
}
|
core/Exception/Invalid_Argument_Exception.php
ADDED
@@ -0,0 +1,7 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\Exception;
|
4 |
+
|
5 |
+
class Invalid_Argument_Exception extends \InvalidArgumentException implements Exception {
|
6 |
+
|
7 |
+
}
|
core/Exception/Unsatisfied_Module_Dependencies_Exception.php
ADDED
@@ -0,0 +1,7 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\Exception;
|
4 |
+
|
5 |
+
class Unsatisfied_Module_Dependencies_Exception extends \RuntimeException implements Exception {
|
6 |
+
|
7 |
+
}
|
core/Exception/WP_Error.php
ADDED
@@ -0,0 +1,36 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\Exception;
|
4 |
+
|
5 |
+
class WP_Error extends \Exception implements Exception {
|
6 |
+
|
7 |
+
/** @var \WP_Error */
|
8 |
+
private $error;
|
9 |
+
|
10 |
+
public function __construct( \WP_Error $error, \Exception $previous = null ) {
|
11 |
+
$this->error = $error;
|
12 |
+
parent::__construct( wp_sprintf( '%l', $error->get_error_messages() ), 0, $previous );
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Create a WP Error instance from an error code and message.
|
17 |
+
*
|
18 |
+
* @param string $code
|
19 |
+
* @param string $message
|
20 |
+
* @param array $data
|
21 |
+
*
|
22 |
+
* @return static
|
23 |
+
*/
|
24 |
+
public static function from_code( $code, $message, array $data = [] ) {
|
25 |
+
return new static( new \WP_Error( $code, $message, $data ) );
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Get the WP Error instance.
|
30 |
+
*
|
31 |
+
* @return \WP_Error
|
32 |
+
*/
|
33 |
+
public function get_error() {
|
34 |
+
return $this->error;
|
35 |
+
}
|
36 |
+
}
|
core/Exception/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/admin-pages/css/style.css
CHANGED
@@ -124,8 +124,7 @@
|
|
124 |
Â
box-shadow: 0 0 20px rgba(0,0,0,0.2);
|
125 |
Â
z-index: 510;
|
126 |
Â
}
|
127 |
-
.grid .itsec-modal-navigation
|
128 |
-
.grid .itsec-modal-content-footer {
|
129 |
Â
display: block;
|
130 |
Â
}
|
131 |
Â
.grid .itsec-list-content-footer,
|
@@ -261,7 +260,10 @@ body.itsec-modal-open {
|
|
261 |
Â
.itsec-modal-navigation button.itsec-close-modal::before {
|
262 |
Â
content: '\f335';
|
263 |
Â
}
|
264 |
-
.itsec-modal-content-footer {
|
Â
|
|
Â
|
|
Â
|
|
265 |
Â
position: absolute;
|
266 |
Â
bottom: 0;
|
267 |
Â
left: 0;
|
@@ -344,18 +346,17 @@ body.itsec-modal-open {
|
|
344 |
Â
box-sizing: border-box;
|
345 |
Â
}
|
346 |
Â
.itsec-module-cards {
|
347 |
-
|
348 |
-
|
Â
|
|
349 |
Â
}
|
350 |
Â
.itsec-module-cards:after {
|
351 |
Â
content: '';
|
352 |
-
display: inline-block;
|
353 |
Â
width: 100%;
|
354 |
Â
}
|
355 |
Â
.itsec-module-card,
|
356 |
Â
.itsec-module-card-filler {
|
357 |
Â
font-size: 16px;
|
358 |
-
display: inline-block;
|
359 |
Â
width: 100%;
|
360 |
Â
max-width: 32%;
|
361 |
Â
text-align: left;
|
@@ -449,6 +450,12 @@ body.itsec-modal-open {
|
|
449 |
Â
min-height: 14em;
|
450 |
Â
}
|
451 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
452 |
Â
@media ( max-width: 782px ) {
|
453 |
Â
#poststuff .list .itsec-module-card h2 {
|
454 |
Â
line-height: 2.6;
|
@@ -464,6 +471,10 @@ body.itsec-modal-open {
|
|
464 |
Â
}
|
465 |
Â
}
|
466 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
467 |
Â
/*
|
468 |
Â
* Success Error Messages
|
469 |
Â
*/
|
@@ -880,6 +891,36 @@ body.security_page_itsec-logs .itsec-module-settings-content-main .form-table .w
|
|
880 |
Â
padding: 15px 10px;
|
881 |
Â
}
|
882 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
883 |
Â
|
884 |
Â
/***************************************
|
885 |
Â
Tooltip
|
124 |
Â
box-shadow: 0 0 20px rgba(0,0,0,0.2);
|
125 |
Â
z-index: 510;
|
126 |
Â
}
|
127 |
+
.grid .itsec-modal-navigation {
|
Â
|
|
128 |
Â
display: block;
|
129 |
Â
}
|
130 |
Â
.grid .itsec-list-content-footer,
|
260 |
Â
.itsec-modal-navigation button.itsec-close-modal::before {
|
261 |
Â
content: '\f335';
|
262 |
Â
}
|
263 |
+
.grid .itsec-modal-content-footer {
|
264 |
+
display: flex;
|
265 |
+
align-items: center;
|
266 |
+
justify-content: space-between;
|
267 |
Â
position: absolute;
|
268 |
Â
bottom: 0;
|
269 |
Â
left: 0;
|
346 |
Â
box-sizing: border-box;
|
347 |
Â
}
|
348 |
Â
.itsec-module-cards {
|
349 |
+
display: flex;
|
350 |
+
flex-wrap: wrap;
|
351 |
+
justify-content: space-between;
|
352 |
Â
}
|
353 |
Â
.itsec-module-cards:after {
|
354 |
Â
content: '';
|
Â
|
|
355 |
Â
width: 100%;
|
356 |
Â
}
|
357 |
Â
.itsec-module-card,
|
358 |
Â
.itsec-module-card-filler {
|
359 |
Â
font-size: 16px;
|
Â
|
|
360 |
Â
width: 100%;
|
361 |
Â
max-width: 32%;
|
362 |
Â
text-align: left;
|
450 |
Â
min-height: 14em;
|
451 |
Â
}
|
452 |
Â
|
453 |
+
.list .itsec-list-content-footer {
|
454 |
+
display: flex;
|
455 |
+
align-items: center;
|
456 |
+
justify-content: space-between;
|
457 |
+
}
|
458 |
+
|
459 |
Â
@media ( max-width: 782px ) {
|
460 |
Â
#poststuff .list .itsec-module-card h2 {
|
461 |
Â
line-height: 2.6;
|
471 |
Â
}
|
472 |
Â
}
|
473 |
Â
|
474 |
+
.itsec-module-documentation {
|
475 |
+
font-size: 13px;
|
476 |
+
}
|
477 |
+
|
478 |
Â
/*
|
479 |
Â
* Success Error Messages
|
480 |
Â
*/
|
891 |
Â
padding: 15px 10px;
|
892 |
Â
}
|
893 |
Â
|
894 |
+
.itsec-settings-module-settings .form-table td {
|
895 |
+
position: relative;
|
896 |
+
}
|
897 |
+
|
898 |
+
.itsec-settings-module-settings .ms-options-wrap {
|
899 |
+
max-width: 455px;
|
900 |
+
}
|
901 |
+
|
902 |
+
.itsec-settings-module-settings .ms-options-wrap > .ms-options {
|
903 |
+
margin-left: 10px;
|
904 |
+
margin-right: 10px;
|
905 |
+
width: auto;
|
906 |
+
}
|
907 |
+
|
908 |
+
.itsec-settings-module-settings .ms-options-wrap > .ms-options > ul label {
|
909 |
+
padding: 4px;
|
910 |
+
}
|
911 |
+
|
912 |
+
.itsec-settings-module-settings .ms-options-wrap > .ms-options > ul input[type="checkbox"] {
|
913 |
+
position: initial;
|
914 |
+
}
|
915 |
+
|
916 |
+
.itsec-settings-module-settings .ms-options-wrap > button {
|
917 |
+
text-overflow: ellipsis;
|
918 |
+
overflow: hidden;
|
919 |
+
}
|
920 |
+
|
921 |
+
.itsec-settings-module-settings .ms-options-wrap > button > span {
|
922 |
+
display: inline;
|
923 |
+
}
|
924 |
Â
|
925 |
Â
/***************************************
|
926 |
Â
Tooltip
|
core/admin-pages/init.php
CHANGED
@@ -24,10 +24,12 @@ final class ITSEC_Admin_Page_Loader {
|
|
24 |
Â
}
|
25 |
Â
|
26 |
Â
public function add_scripts() {
|
27 |
-
|
Â
|
|
28 |
Â
}
|
29 |
Â
|
30 |
Â
public function add_styles() {
|
Â
|
|
31 |
Â
wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
|
32 |
Â
}
|
33 |
Â
|
@@ -63,7 +65,7 @@ final class ITSEC_Admin_Page_Loader {
|
|
63 |
Â
return $this->page_id;
|
64 |
Â
}
|
65 |
Â
|
66 |
-
if (
|
67 |
Â
if ( isset( $_REQUEST['action'] ) && preg_match( '/^itsec_(.+)_page$/', $_REQUEST['action'], $match ) ) {
|
68 |
Â
$this->page_id = $match[1];
|
69 |
Â
}
|
24 |
Â
}
|
25 |
Â
|
26 |
Â
public function add_scripts() {
|
27 |
+
wp_register_script( 'itsec-jquery-multi-select', plugin_dir_url( __FILE__ ) . '/js/lib/jquery.multiselect.js', array( 'jquery' ), '2.4.17' );
|
28 |
+
wp_register_script( 'itsec-form-user-groups', plugin_dir_url( __FILE__ ) . '/js/form-user-groups.js', array( 'itsec-jquery-multi-select', 'lodash' ), 1 );
|
29 |
Â
}
|
30 |
Â
|
31 |
Â
public function add_styles() {
|
32 |
+
wp_register_style( 'itsec-jquery-multi-select', plugin_dir_url( __FILE__ ) . '/js/lib/jquery.multiselect.css', array(), '2.4.17' );
|
33 |
Â
wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
|
34 |
Â
}
|
35 |
Â
|
65 |
Â
return $this->page_id;
|
66 |
Â
}
|
67 |
Â
|
68 |
+
if ( wp_doing_ajax() ) {
|
69 |
Â
if ( isset( $_REQUEST['action'] ) && preg_match( '/^itsec_(.+)_page$/', $_REQUEST['action'], $match ) ) {
|
70 |
Â
$this->page_id = $match[1];
|
71 |
Â
}
|
core/admin-pages/js/form-user-groups.js
ADDED
@@ -0,0 +1,103 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
( function( $, lodash, itsec, data ) {
|
2 |
+
function getValue( obj, path ) {
|
3 |
+
return path ? lodash.get( obj, path ) : obj;
|
4 |
+
}
|
5 |
+
|
6 |
+
function defaultCompare( a, b ) {
|
7 |
+
return a === b;
|
8 |
+
}
|
9 |
+
|
10 |
+
// Based on redux-watch licensed MIT: https://github.com/jprichardson/redux-watch
|
11 |
+
function watch( getState, objectPath, compare ) {
|
12 |
+
compare = compare || defaultCompare;
|
13 |
+
var currentValue = getValue( getState(), objectPath );
|
14 |
+
return function w( fn ) {
|
15 |
+
return function() {
|
16 |
+
var newValue = getValue( getState(), objectPath );
|
17 |
+
if ( !compare( currentValue, newValue ) ) {
|
18 |
+
var oldValue = currentValue;
|
19 |
+
currentValue = newValue;
|
20 |
+
fn( newValue, oldValue, objectPath );
|
21 |
+
}
|
22 |
+
};
|
23 |
+
};
|
24 |
+
}
|
25 |
+
|
26 |
+
$( function() {
|
27 |
+
$( '.itsec-form-input--type-user-groups' ).multiselect( {
|
28 |
+
selectAll: true,
|
29 |
+
} );
|
30 |
+
|
31 |
+
if ( itsec[ 'user-groups' ] && itsec[ 'user-groups' ][ 'api' ] && itsec[ 'user-groups' ][ 'api' ][ 'store' ] ) {
|
32 |
+
var store = itsec[ 'user-groups' ][ 'api' ][ 'store' ];
|
33 |
+
|
34 |
+
var watchMatchables = watch( data.select( 'ithemes-security/user-groups' ).getMatchables );
|
35 |
+
var watchSettings = watch( function() {
|
36 |
+
return store.getState().settings;
|
37 |
+
} );
|
38 |
+
|
39 |
+
store.subscribe( watchMatchables( function( currentValue, previousValue ) {
|
40 |
+
if ( !data.select( 'core/data' ).hasFinishedResolution( 'ithemes-security/user-groups', 'getMatchables' ) ) {
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
|
44 |
+
$( '.itsec-form-input--type-user-groups' ).each( function() {
|
45 |
+
var $el = $( this ),
|
46 |
+
checked = $el.val() || [];
|
47 |
+
|
48 |
+
var options = ( currentValue || [] )
|
49 |
+
.sort( function( groupA, groupB ) {
|
50 |
+
if ( groupA.type === groupB.type ) {
|
51 |
+
return 0;
|
52 |
+
}
|
53 |
+
|
54 |
+
if ( groupA.type === 'user-group' ) {
|
55 |
+
return -1;
|
56 |
+
}
|
57 |
+
|
58 |
+
if ( groupB.type === 'user-group' ) {
|
59 |
+
return 1;
|
60 |
+
}
|
61 |
+
|
62 |
+
return 0;
|
63 |
+
} )
|
64 |
+
.map( function( userGroup ) {
|
65 |
+
return {
|
66 |
+
name : userGroup.label,
|
67 |
+
value : userGroup.id,
|
68 |
+
checked: checked.includes( userGroup.id ),
|
69 |
+
};
|
70 |
+
} );
|
71 |
+
|
72 |
+
$el.multiselect( 'loadOptions', options );
|
73 |
+
} );
|
74 |
+
} ) );
|
75 |
+
|
76 |
+
store.subscribe( watchSettings( lodash.debounce( function( currentValue, previousValue ) {
|
77 |
+
const settings = data.select( 'ithemes-security/user-groups' ).getGroupsBySetting();
|
78 |
+
|
79 |
+
for ( var module in settings ) {
|
80 |
+
if ( !settings.hasOwnProperty( module ) ) {
|
81 |
+
continue;
|
82 |
+
}
|
83 |
+
|
84 |
+
for ( var setting in settings[ module ] ) {
|
85 |
+
if ( !settings[ module ].hasOwnProperty( setting ) ) {
|
86 |
+
continue;
|
87 |
+
}
|
88 |
+
|
89 |
+
var groupIds = settings[ module ][ setting ];
|
90 |
+
|
91 |
+
var $option = $( '.itsec-form-input--type-user-groups[data-module="' + module + '"][data-setting="' + setting + '"]' );
|
92 |
+
var current = $option.val();
|
93 |
+
|
94 |
+
if ( !lodash.isEqual( current, groupIds ) ) {
|
95 |
+
$option.val( groupIds );
|
96 |
+
$option.multiselect( 'reload' );
|
97 |
+
}
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}, 100 ) ) );
|
101 |
+
}
|
102 |
+
} );
|
103 |
+
} )( jQuery, lodash, window[ 'itsec' ], window[ 'wp' ][ 'data' ] );
|
core/admin-pages/js/lib/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/admin-pages/js/lib/jquery.multiselect.css
ADDED
@@ -0,0 +1,148 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.ms-options-wrap,
|
2 |
+
.ms-options-wrap * {
|
3 |
+
box-sizing: border-box;
|
4 |
+
}
|
5 |
+
|
6 |
+
.ms-options-wrap > button:focus,
|
7 |
+
.ms-options-wrap > button {
|
8 |
+
position: relative;
|
9 |
+
width: 100%;
|
10 |
+
text-align: left;
|
11 |
+
border: 1px solid #aaa;
|
12 |
+
background-color: #fff;
|
13 |
+
padding: 5px 20px 5px 5px;
|
14 |
+
margin-top: 1px;
|
15 |
+
font-size: 13px;
|
16 |
+
color: #aaa;
|
17 |
+
outline-offset: -2px;
|
18 |
+
white-space: nowrap;
|
19 |
+
}
|
20 |
+
|
21 |
+
.ms-options-wrap > button > span {
|
22 |
+
display: inline-block;
|
23 |
+
}
|
24 |
+
|
25 |
+
.ms-options-wrap > button[disabled] {
|
26 |
+
background-color: #e5e9ed;
|
27 |
+
color: #808080;
|
28 |
+
opacity: 0.6;
|
29 |
+
}
|
30 |
+
|
31 |
+
.ms-options-wrap > button:after {
|
32 |
+
content: ' ';
|
33 |
+
height: 0;
|
34 |
+
position: absolute;
|
35 |
+
top: 50%;
|
36 |
+
right: 5px;
|
37 |
+
width: 0;
|
38 |
+
border: 6px solid rgba(0, 0, 0, 0);
|
39 |
+
border-top-color: #999;
|
40 |
+
margin-top: -3px;
|
41 |
+
}
|
42 |
+
|
43 |
+
.ms-options-wrap.ms-has-selections > button {
|
44 |
+
color: #333;
|
45 |
+
}
|
46 |
+
|
47 |
+
.ms-options-wrap > .ms-options {
|
48 |
+
position: absolute;
|
49 |
+
left: 0;
|
50 |
+
width: 100%;
|
51 |
+
margin-top: 1px;
|
52 |
+
margin-bottom: 20px;
|
53 |
+
background: white;
|
54 |
+
z-index: 2000;
|
55 |
+
border: 1px solid #aaa;
|
56 |
+
overflow: auto;
|
57 |
+
visibility: hidden;
|
58 |
+
}
|
59 |
+
|
60 |
+
.ms-options-wrap.ms-active > .ms-options {
|
61 |
+
visibility: visible
|
62 |
+
}
|
63 |
+
|
64 |
+
.ms-options-wrap > .ms-options > .ms-search input {
|
65 |
+
width: 100%;
|
66 |
+
padding: 4px 5px;
|
67 |
+
border: none;
|
68 |
+
border-bottom: 1px groove;
|
69 |
+
outline: none;
|
70 |
+
}
|
71 |
+
|
72 |
+
.ms-options-wrap > .ms-options .ms-selectall {
|
73 |
+
display: inline-block;
|
74 |
+
font-size: .9em;
|
75 |
+
text-transform: lowercase;
|
76 |
+
text-decoration: none;
|
77 |
+
}
|
78 |
+
.ms-options-wrap > .ms-options .ms-selectall:hover {
|
79 |
+
text-decoration: underline;
|
80 |
+
}
|
81 |
+
|
82 |
+
.ms-options-wrap > .ms-options > .ms-selectall.global {
|
83 |
+
margin: 4px 5px;
|
84 |
+
}
|
85 |
+
|
86 |
+
.ms-options-wrap > .ms-options > ul,
|
87 |
+
.ms-options-wrap > .ms-options > ul > li.optgroup ul {
|
88 |
+
list-style-type: none;
|
89 |
+
padding: 0;
|
90 |
+
margin: 0;
|
91 |
+
}
|
92 |
+
|
93 |
+
.ms-options-wrap > .ms-options > ul li.ms-hidden {
|
94 |
+
display: none;
|
95 |
+
}
|
96 |
+
|
97 |
+
.ms-options-wrap > .ms-options > ul > li.optgroup {
|
98 |
+
padding: 5px;
|
99 |
+
}
|
100 |
+
.ms-options-wrap > .ms-options > ul > li.optgroup + li.optgroup {
|
101 |
+
border-top: 1px solid #aaa;
|
102 |
+
}
|
103 |
+
|
104 |
+
.ms-options-wrap > .ms-options > ul > li.optgroup .label {
|
105 |
+
display: block;
|
106 |
+
padding: 5px 0 0 0;
|
107 |
+
font-weight: bold;
|
108 |
+
}
|
109 |
+
|
110 |
+
.ms-options-wrap > .ms-options > ul label {
|
111 |
+
position: relative;
|
112 |
+
display: inline-block;
|
113 |
+
width: 100%;
|
114 |
+
padding: 4px 4px 4px 20px;
|
115 |
+
margin: 1px 0;
|
116 |
+
border: 1px dotted transparent;
|
117 |
+
}
|
118 |
+
.ms-options-wrap > .ms-options.checkbox-autofit > ul label,
|
119 |
+
.ms-options-wrap > .ms-options.hide-checkbox > ul label {
|
120 |
+
padding: 4px;
|
121 |
+
}
|
122 |
+
|
123 |
+
.ms-options-wrap > .ms-options > ul label.focused,
|
124 |
+
.ms-options-wrap > .ms-options > ul label:hover {
|
125 |
+
background-color: #efefef;
|
126 |
+
border-color: #999;
|
127 |
+
}
|
128 |
+
|
129 |
+
.ms-options-wrap > .ms-options > ul li.selected label {
|
130 |
+
background-color: #efefef;
|
131 |
+
border-color: transparent;
|
132 |
+
}
|
133 |
+
|
134 |
+
.ms-options-wrap > .ms-options > ul input[type="checkbox"] {
|
135 |
+
margin: 0 5px 0 0;
|
136 |
+
position: absolute;
|
137 |
+
left: 4px;
|
138 |
+
top: 7px;
|
139 |
+
}
|
140 |
+
|
141 |
+
.ms-options-wrap > .ms-options.hide-checkbox > ul input[type="checkbox"] {
|
142 |
+
position: absolute !important;
|
143 |
+
height: 1px;
|
144 |
+
width: 1px;
|
145 |
+
overflow: hidden;
|
146 |
+
clip: rect(1px 1px 1px 1px);
|
147 |
+
clip: rect(1px, 1px, 1px, 1px);
|
148 |
+
}
|
core/admin-pages/js/lib/jquery.multiselect.js
ADDED
@@ -0,0 +1,936 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Display a nice easy to use multiselect list
|
3 |
+
* @Version: 2.4.17
|
4 |
+
* @Author: Patrick Springstubbe
|
5 |
+
* @Contact: @JediNobleclem
|
6 |
+
* @Website: springstubbe.us
|
7 |
+
* @Source: https://github.com/nobleclem/jQuery-MultiSelect
|
8 |
+
*
|
9 |
+
* Usage:
|
10 |
+
* $('select[multiple]').multiselect();
|
11 |
+
* $('select[multiple]').multiselect({ texts: { placeholder: 'Select options' } });
|
12 |
+
* $('select[multiple]').multiselect('reload');
|
13 |
+
* $('select[multiple]').multiselect( 'loadOptions', [{
|
14 |
+
* name : 'Option Name 1',
|
15 |
+
* value : 'option-value-1',
|
16 |
+
* checked: false,
|
17 |
+
* attributes : {
|
18 |
+
* custom1: 'value1',
|
19 |
+
* custom2: 'value2'
|
20 |
+
* }
|
21 |
+
* },{
|
22 |
+
* name : 'Option Name 2',
|
23 |
+
* value : 'option-value-2',
|
24 |
+
* checked: false,
|
25 |
+
* attributes : {
|
26 |
+
* custom1: 'value1',
|
27 |
+
* custom2: 'value2'
|
28 |
+
* }
|
29 |
+
* }]);
|
30 |
+
*
|
31 |
+
**/
|
32 |
+
(function($){
|
33 |
+
var defaults = {
|
34 |
+
columns: 1, // how many columns should be use to show options
|
35 |
+
search : false, // include option search box
|
36 |
+
|
37 |
+
// search filter options
|
38 |
+
searchOptions : {
|
39 |
+
delay : 250, // time (in ms) between keystrokes until search happens
|
40 |
+
showOptGroups: false, // show option group titles if no options remaining
|
41 |
+
searchText : true, // search within the text
|
42 |
+
searchValue : false, // search within the value
|
43 |
+
onSearch : function( element ){} // fires on keyup before search on options happens
|
44 |
+
},
|
45 |
+
|
46 |
+
// plugin texts
|
47 |
+
texts: {
|
48 |
+
placeholder : 'Select options', // text to use in dummy input
|
49 |
+
search : 'Search', // search input placeholder text
|
50 |
+
selectedOptions: ' selected', // selected suffix text
|
51 |
+
selectAll : 'Select all', // select all text
|
52 |
+
unselectAll : 'Unselect all', // unselect all text
|
53 |
+
noneSelected : 'None Selected' // None selected text
|
54 |
+
},
|
55 |
+
|
56 |
+
// general options
|
57 |
+
selectAll : false, // add select all option
|
58 |
+
selectGroup : false, // select entire optgroup
|
59 |
+
minHeight : 200, // minimum height of option overlay
|
60 |
+
maxHeight : null, // maximum height of option overlay
|
61 |
+
maxWidth : null, // maximum width of option overlay (or selector)
|
62 |
+
maxPlaceholderWidth: null, // maximum width of placeholder button
|
63 |
+
maxPlaceholderOpts : 10, // maximum number of placeholder options to show until "# selected" shown instead
|
64 |
+
showCheckbox : true, // display the checkbox to the user
|
65 |
+
checkboxAutoFit : false, // auto calc checkbox padding
|
66 |
+
optionAttributes : [], // attributes to copy to the checkbox from the option element
|
67 |
+
|
68 |
+
// Callbacks
|
69 |
+
onLoad : function( element ){}, // fires at end of list initialization
|
70 |
+
onOptionClick : function( element, option ){}, // fires when an option is clicked
|
71 |
+
onControlClose: function( element ){}, // fires when the options list is closed
|
72 |
+
onSelectAll : function( element, selected ){}, // fires when (un)select all is clicked
|
73 |
+
onPlaceholder : function( element, placeholder, selectedOpts ){}, // fires when the placeholder txt is updated
|
74 |
+
};
|
75 |
+
|
76 |
+
var msCounter = 1; // counter for each select list
|
77 |
+
var msOptCounter = 1; // counter for each option on page
|
78 |
+
|
79 |
+
// FOR LEGACY BROWSERS (talking to you IE8)
|
80 |
+
if( typeof Array.prototype.map !== 'function' ) {
|
81 |
+
Array.prototype.map = function( callback, thisArg ) {
|
82 |
+
if( typeof thisArg === 'undefined' ) {
|
83 |
+
thisArg = this;
|
84 |
+
}
|
85 |
+
|
86 |
+
return $.isArray( thisArg ) ? $.map( thisArg, callback ) : [];
|
87 |
+
};
|
88 |
+
}
|
89 |
+
if( typeof String.prototype.trim !== 'function' ) {
|
90 |
+
String.prototype.trim = function() {
|
91 |
+
return this.replace(/^\s+|\s+$/g, '');
|
92 |
+
};
|
93 |
+
}
|
94 |
+
|
95 |
+
function MultiSelect( element, options )
|
96 |
+
{
|
97 |
+
this.element = element;
|
98 |
+
this.options = $.extend( true, {}, defaults, options );
|
99 |
+
this.updateSelectAll = true;
|
100 |
+
this.updatePlaceholder = true;
|
101 |
+
this.listNumber = msCounter;
|
102 |
+
|
103 |
+
msCounter = msCounter + 1; // increment counter
|
104 |
+
|
105 |
+
/* Make sure its a multiselect list */
|
106 |
+
if( !$(this.element).attr('multiple') ) {
|
107 |
+
throw new Error( '[jQuery-MultiSelect] Select list must be a multiselect list in order to use this plugin' );
|
108 |
+
}
|
109 |
+
|
110 |
+
/* Options validation checks */
|
111 |
+
if( this.options.search ){
|
112 |
+
if( !this.options.searchOptions.searchText && !this.options.searchOptions.searchValue ){
|
113 |
+
throw new Error( '[jQuery-MultiSelect] Either searchText or searchValue should be true.' );
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
/** BACKWARDS COMPATIBILITY **/
|
118 |
+
if( 'placeholder' in this.options ) {
|
119 |
+
this.options.texts.placeholder = this.options.placeholder;
|
120 |
+
delete this.options.placeholder;
|
121 |
+
}
|
122 |
+
if( 'default' in this.options.searchOptions ) {
|
123 |
+
this.options.texts.search = this.options.searchOptions['default'];
|
124 |
+
delete this.options.searchOptions['default'];
|
125 |
+
}
|
126 |
+
/** END BACKWARDS COMPATIBILITY **/
|
127 |
+
|
128 |
+
// load this instance
|
129 |
+
this.load();
|
130 |
+
}
|
131 |
+
|
132 |
+
MultiSelect.prototype = {
|
133 |
+
/* LOAD CUSTOM MULTISELECT DOM/ACTIONS */
|
134 |
+
load: function() {
|
135 |
+
var instance = this;
|
136 |
+
|
137 |
+
// make sure this is a select list and not loaded
|
138 |
+
if( (instance.element.nodeName != 'SELECT') || $(instance.element).hasClass('jqmsLoaded') ) {
|
139 |
+
return true;
|
140 |
+
}
|
141 |
+
|
142 |
+
// sanity check so we don't double load on a select element
|
143 |
+
$(instance.element).addClass('jqmsLoaded ms-list-'+ instance.listNumber ).data( 'plugin_multiselect-instance', instance );
|
144 |
+
|
145 |
+
// add option container
|
146 |
+
$(instance.element).after('<div id="ms-list-'+ instance.listNumber +'" class="ms-options-wrap"><button type="button"><span>None Selected</span></button><div class="ms-options"><ul></ul></div></div>');
|
147 |
+
|
148 |
+
var placeholder = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child');
|
149 |
+
var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
|
150 |
+
var optionsList = optionsWrap.find('> ul');
|
151 |
+
|
152 |
+
// don't show checkbox (add class for css to hide checkboxes)
|
153 |
+
if( !instance.options.showCheckbox ) {
|
154 |
+
optionsWrap.addClass('hide-checkbox');
|
155 |
+
}
|
156 |
+
else if( instance.options.checkboxAutoFit ) {
|
157 |
+
optionsWrap.addClass('checkbox-autofit');
|
158 |
+
}
|
159 |
+
|
160 |
+
// check if list is disabled
|
161 |
+
if( $(instance.element).prop( 'disabled' ) ) {
|
162 |
+
placeholder.prop( 'disabled', true );
|
163 |
+
}
|
164 |
+
|
165 |
+
// set placeholder maxWidth
|
166 |
+
if( instance.options.maxPlaceholderWidth ) {
|
167 |
+
placeholder.css( 'maxWidth', instance.options.maxPlaceholderWidth );
|
168 |
+
}
|
169 |
+
|
170 |
+
// override with user defined maxHeight
|
171 |
+
if( instance.options.maxHeight ) {
|
172 |
+
var maxHeight = instance.options.maxHeight;
|
173 |
+
}
|
174 |
+
else {
|
175 |
+
// cacl default maxHeight
|
176 |
+
var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20);
|
177 |
+
}
|
178 |
+
|
179 |
+
// maxHeight cannot be less than options.minHeight
|
180 |
+
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
|
181 |
+
|
182 |
+
optionsWrap.css({
|
183 |
+
maxWidth : instance.options.maxWidth,
|
184 |
+
minHeight: instance.options.minHeight,
|
185 |
+
maxHeight: maxHeight,
|
186 |
+
});
|
187 |
+
|
188 |
+
// isolate options scroll
|
189 |
+
// @source: https://github.com/nobleclem/jQuery-IsolatedScroll
|
190 |
+
optionsWrap.on( 'touchmove mousewheel DOMMouseScroll', function ( e ) {
|
191 |
+
if( ($(this).outerHeight() < $(this)[0].scrollHeight) ) {
|
192 |
+
var e0 = e.originalEvent,
|
193 |
+
delta = e0.wheelDelta || -e0.detail;
|
194 |
+
|
195 |
+
if( ($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight ) {
|
196 |
+
e.preventDefault();
|
197 |
+
this.scrollTop += ( delta < 0 ? 1 : -1 );
|
198 |
+
}
|
199 |
+
}
|
200 |
+
});
|
201 |
+
|
202 |
+
// hide options menus if click happens off of the list placeholder button
|
203 |
+
$(document).off('click.ms-hideopts').on('click.ms-hideopts', function( event ){
|
204 |
+
if( !$(event.target).closest('.ms-options-wrap').length ) {
|
205 |
+
$('.ms-options-wrap.ms-active > .ms-options').each(function(){
|
206 |
+
$(this).closest('.ms-options-wrap').removeClass('ms-active');
|
207 |
+
|
208 |
+
var listID = $(this).closest('.ms-options-wrap').attr('id');
|
209 |
+
|
210 |
+
var thisInst = $(this).parent().siblings('.'+ listID +'.jqmsLoaded').data('plugin_multiselect-instance');
|
211 |
+
|
212 |
+
// USER CALLBACK
|
213 |
+
if( typeof thisInst.options.onControlClose == 'function' ) {
|
214 |
+
thisInst.options.onControlClose( thisInst.element );
|
215 |
+
}
|
216 |
+
});
|
217 |
+
}
|
218 |
+
// hide open option lists if escape key pressed
|
219 |
+
}).on('keydown', function( event ){
|
220 |
+
if( (event.keyCode || event.which) == 27 ) { // esc key
|
221 |
+
$(this).trigger('click.ms-hideopts');
|
222 |
+
}
|
223 |
+
});
|
224 |
+
|
225 |
+
// handle pressing enter|space while tabbing through
|
226 |
+
placeholder.on('keydown', function( event ){
|
227 |
+
var code = (event.keyCode || event.which);
|
228 |
+
if( (code == 13) || (code == 32) ) { // enter OR space
|
229 |
+
placeholder.trigger( 'mousedown' );
|
230 |
+
}
|
231 |
+
});
|
232 |
+
|
233 |
+
// disable button action
|
234 |
+
placeholder.on( 'mousedown', function( event ){
|
235 |
+
// ignore if its not a left click
|
236 |
+
if( event.which && (event.which != 1) ) {
|
237 |
+
return true;
|
238 |
+
}
|
239 |
+
|
240 |
+
// hide other menus before showing this one
|
241 |
+
$('.ms-options-wrap.ms-active').each(function(){
|
242 |
+
if( $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded')[0] != optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded')[0] ) {
|
243 |
+
$(this).removeClass('ms-active');
|
244 |
+
|
245 |
+
var thisInst = $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded').data('plugin_multiselect-instance');
|
246 |
+
|
247 |
+
// USER CALLBACK
|
248 |
+
if( typeof thisInst.options.onControlClose == 'function' ) {
|
249 |
+
thisInst.options.onControlClose( thisInst.element );
|
250 |
+
}
|
251 |
+
}
|
252 |
+
});
|
253 |
+
|
254 |
+
// show/hide options
|
255 |
+
optionsWrap.closest('.ms-options-wrap').toggleClass('ms-active');
|
256 |
+
|
257 |
+
// recalculate height
|
258 |
+
if( optionsWrap.closest('.ms-options-wrap').hasClass('ms-active') ) {
|
259 |
+
optionsWrap.css( 'maxHeight', '' );
|
260 |
+
|
261 |
+
// override with user defined maxHeight
|
262 |
+
if( instance.options.maxHeight ) {
|
263 |
+
var maxHeight = instance.options.maxHeight;
|
264 |
+
}
|
265 |
+
else {
|
266 |
+
// cacl default maxHeight
|
267 |
+
var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20);
|
268 |
+
}
|
269 |
+
|
270 |
+
if( maxHeight ) {
|
271 |
+
// maxHeight cannot be less than options.minHeight
|
272 |
+
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
|
273 |
+
|
274 |
+
optionsWrap.css( 'maxHeight', maxHeight );
|
275 |
+
}
|
276 |
+
}
|
277 |
+
else if( typeof instance.options.onControlClose == 'function' ) {
|
278 |
+
instance.options.onControlClose( instance.element );
|
279 |
+
}
|
280 |
+
}).click(function( event ){ event.preventDefault(); });
|
281 |
+
|
282 |
+
// add placeholder copy
|
283 |
+
if( instance.options.texts.placeholder ) {
|
284 |
+
placeholder.find('span').text( instance.options.texts.placeholder );
|
285 |
+
}
|
286 |
+
|
287 |
+
// add search box
|
288 |
+
if( instance.options.search ) {
|
289 |
+
optionsList.before('<div class="ms-search"><input type="text" value="" placeholder="'+ instance.options.texts.search +'" /></div>');
|
290 |
+
|
291 |
+
var search = optionsWrap.find('.ms-search input');
|
292 |
+
search.on('keyup', function(){
|
293 |
+
// ignore keystrokes that don't make a difference
|
294 |
+
if( $(this).data('lastsearch') == $(this).val() ) {
|
295 |
+
return true;
|
296 |
+
}
|
297 |
+
|
298 |
+
// pause timeout
|
299 |
+
if( $(this).data('searchTimeout') ) {
|
300 |
+
clearTimeout( $(this).data('searchTimeout') );
|
301 |
+
}
|
302 |
+
|
303 |
+
var thisSearchElem = $(this);
|
304 |
+
|
305 |
+
$(this).data('searchTimeout', setTimeout(function(){
|
306 |
+
thisSearchElem.data('lastsearch', thisSearchElem.val() );
|
307 |
+
|
308 |
+
// USER CALLBACK
|
309 |
+
if( typeof instance.options.searchOptions.onSearch == 'function' ) {
|
310 |
+
instance.options.searchOptions.onSearch( instance.element );
|
311 |
+
}
|
312 |
+
|
313 |
+
// search non optgroup li's
|
314 |
+
var searchString = $.trim( search.val().toLowerCase() );
|
315 |
+
if( searchString ) {
|
316 |
+
optionsList.find('li[data-search-term*="'+ searchString +'"]:not(.optgroup)').removeClass('ms-hidden');
|
317 |
+
optionsList.find('li:not([data-search-term*="'+ searchString +'"], .optgroup)').addClass('ms-hidden');
|
318 |
+
}
|
319 |
+
else {
|
320 |
+
optionsList.find('.ms-hidden').removeClass('ms-hidden');
|
321 |
+
}
|
322 |
+
|
323 |
+
// show/hide optgroups based on if there are items visible within
|
324 |
+
if( !instance.options.searchOptions.showOptGroups ) {
|
325 |
+
optionsList.find('.optgroup').each(function(){
|
326 |
+
if( $(this).find('li:not(.ms-hidden)').length ) {
|
327 |
+
$(this).show();
|
328 |
+
}
|
329 |
+
else {
|
330 |
+
$(this).hide();
|
331 |
+
}
|
332 |
+
});
|
333 |
+
}
|
334 |
+
|
335 |
+
instance._updateSelectAllText();
|
336 |
+
}, instance.options.searchOptions.delay ));
|
337 |
+
});
|
338 |
+
}
|
339 |
+
|
340 |
+
// add global select all options
|
341 |
+
if( instance.options.selectAll ) {
|
342 |
+
optionsList.before('<a href="#" class="ms-selectall global">' + instance.options.texts.selectAll + '</a>');
|
343 |
+
}
|
344 |
+
|
345 |
+
// handle select all option
|
346 |
+
optionsWrap.on('click', '.ms-selectall', function( event ){
|
347 |
+
event.preventDefault();
|
348 |
+
|
349 |
+
instance.updateSelectAll = false;
|
350 |
+
instance.updatePlaceholder = false;
|
351 |
+
|
352 |
+
var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded');
|
353 |
+
|
354 |
+
if( $(this).hasClass('global') ) {
|
355 |
+
// check if any options are not selected if so then select them
|
356 |
+
if( optionsList.find('li:not(.optgroup, .selected, .ms-hidden)').length ) {
|
357 |
+
// get unselected vals, mark as selected, return val list
|
358 |
+
optionsList.find('li:not(.optgroup, .selected, .ms-hidden)').addClass('selected');
|
359 |
+
optionsList.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true );
|
360 |
+
}
|
361 |
+
// deselect everything
|
362 |
+
else {
|
363 |
+
optionsList.find('li:not(.optgroup, .ms-hidden).selected').removeClass('selected');
|
364 |
+
optionsList.find('li:not(.optgroup, .ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false );
|
365 |
+
}
|
366 |
+
}
|
367 |
+
else if( $(this).closest('li').hasClass('optgroup') ) {
|
368 |
+
var optgroup = $(this).closest('li.optgroup');
|
369 |
+
|
370 |
+
// check if any selected if so then select them
|
371 |
+
if( optgroup.find('li:not(.selected, .ms-hidden)').length ) {
|
372 |
+
optgroup.find('li:not(.selected, .ms-hidden)').addClass('selected');
|
373 |
+
optgroup.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true );
|
374 |
+
}
|
375 |
+
// deselect everything
|
376 |
+
else {
|
377 |
+
optgroup.find('li:not(.ms-hidden).selected').removeClass('selected');
|
378 |
+
optgroup.find('li:not(.ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false );
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
var vals = [];
|
383 |
+
optionsList.find('li.selected input[type="checkbox"]').each(function(){
|
384 |
+
vals.push( $(this).val() );
|
385 |
+
});
|
386 |
+
select.val( vals ).trigger('change');
|
387 |
+
|
388 |
+
instance.updateSelectAll = true;
|
389 |
+
instance.updatePlaceholder = true;
|
390 |
+
|
391 |
+
// USER CALLBACK
|
392 |
+
if( typeof instance.options.onSelectAll == 'function' ) {
|
393 |
+
instance.options.onSelectAll( instance.element, vals.length );
|
394 |
+
}
|
395 |
+
|
396 |
+
instance._updateSelectAllText();
|
397 |
+
instance._updatePlaceholderText();
|
398 |
+
});
|
399 |
+
|
400 |
+
// add options to wrapper
|
401 |
+
var options = [];
|
402 |
+
$(instance.element).children().each(function(){
|
403 |
+
if( this.nodeName == 'OPTGROUP' ) {
|
404 |
+
var groupOptions = [];
|
405 |
+
|
406 |
+
$(this).children('option').each(function(){
|
407 |
+
var thisOptionAtts = {};
|
408 |
+
for( var i = 0; i < instance.options.optionAttributes.length; i++ ) {
|
409 |
+
var thisOptAttr = instance.options.optionAttributes[ i ];
|
410 |
+
|
411 |
+
if( $(this).attr( thisOptAttr ) !== undefined ) {
|
412 |
+
thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr );
|
413 |
+
}
|
414 |
+
}
|
415 |
+
|
416 |
+
groupOptions.push({
|
417 |
+
name : $(this).text(),
|
418 |
+
value : $(this).val(),
|
419 |
+
checked: $(this).prop( 'selected' ),
|
420 |
+
attributes: thisOptionAtts
|
421 |
+
});
|
422 |
+
});
|
423 |
+
|
424 |
+
options.push({
|
425 |
+
label : $(this).attr('label'),
|
426 |
+
options: groupOptions
|
427 |
+
});
|
428 |
+
}
|
429 |
+
else if( this.nodeName == 'OPTION' ) {
|
430 |
+
var thisOptionAtts = {};
|
431 |
+
for( var i = 0; i < instance.options.optionAttributes.length; i++ ) {
|
432 |
+
var thisOptAttr = instance.options.optionAttributes[ i ];
|
433 |
+
|
434 |
+
if( $(this).attr( thisOptAttr ) !== undefined ) {
|
435 |
+
thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr );
|
436 |
+
}
|
437 |
+
}
|
438 |
+
|
439 |
+
options.push({
|
440 |
+
name : $(this).text(),
|
441 |
+
value : $(this).val(),
|
442 |
+
checked : $(this).prop( 'selected' ),
|
443 |
+
attributes: thisOptionAtts
|
444 |
+
});
|
445 |
+
}
|
446 |
+
else {
|
447 |
+
// bad option
|
448 |
+
return true;
|
449 |
+
}
|
450 |
+
});
|
451 |
+
instance.loadOptions( options, true, false );
|
452 |
+
|
453 |
+
// BIND SELECT ACTION
|
454 |
+
optionsWrap.on( 'click', 'input[type="checkbox"]', function(){
|
455 |
+
$(this).closest( 'li' ).toggleClass( 'selected' );
|
456 |
+
|
457 |
+
var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded');
|
458 |
+
|
459 |
+
// toggle clicked option
|
460 |
+
select.find('option[value="'+ instance._escapeSelector( $(this).val() ) +'"]').prop(
|
461 |
+
'selected', $(this).is(':checked')
|
462 |
+
).closest('select').trigger('change');
|
463 |
+
|
464 |
+
// USER CALLBACK
|
465 |
+
if( typeof instance.options.onOptionClick == 'function' ) {
|
466 |
+
instance.options.onOptionClick(instance.element, this);
|
467 |
+
}
|
468 |
+
|
469 |
+
instance._updateSelectAllText();
|
470 |
+
instance._updatePlaceholderText();
|
471 |
+
});
|
472 |
+
|
473 |
+
// BIND FOCUS EVENT
|
474 |
+
optionsWrap.on('focusin', 'input[type="checkbox"]', function(){
|
475 |
+
$(this).closest('label').addClass('focused');
|
476 |
+
}).on('focusout', 'input[type="checkbox"]', function(){
|
477 |
+
$(this).closest('label').removeClass('focused');
|
478 |
+
});
|
479 |
+
|
480 |
+
// USER CALLBACK
|
481 |
+
if( typeof instance.options.onLoad === 'function' ) {
|
482 |
+
instance.options.onLoad( instance.element );
|
483 |
+
}
|
484 |
+
|
485 |
+
// hide native select list
|
486 |
+
$(instance.element).hide();
|
487 |
+
},
|
488 |
+
|
489 |
+
/* LOAD SELECT OPTIONS */
|
490 |
+
loadOptions: function( options, overwrite, updateSelect ) {
|
491 |
+
overwrite = (typeof overwrite == 'boolean') ? overwrite : true;
|
492 |
+
updateSelect = (typeof updateSelect == 'boolean') ? updateSelect : true;
|
493 |
+
|
494 |
+
var instance = this;
|
495 |
+
var select = $(instance.element);
|
496 |
+
var optionsList = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options > ul');
|
497 |
+
var optionsWrap = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
|
498 |
+
|
499 |
+
if( overwrite ) {
|
500 |
+
optionsList.find('> li').remove();
|
501 |
+
|
502 |
+
if( updateSelect ) {
|
503 |
+
select.find('> *').remove();
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
var containers = [];
|
508 |
+
for( var key in options ) {
|
509 |
+
// Prevent prototype methods injected into options from being iterated over.
|
510 |
+
if( !options.hasOwnProperty( key ) ) {
|
511 |
+
continue;
|
512 |
+
}
|
513 |
+
|
514 |
+
var thisOption = options[ key ];
|
515 |
+
var container = $('<li/>');
|
516 |
+
var appendContainer = true;
|
517 |
+
|
518 |
+
// OPTION
|
519 |
+
if( thisOption.hasOwnProperty('value') ) {
|
520 |
+
if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) {
|
521 |
+
container.addClass('ms-reflow');
|
522 |
+
}
|
523 |
+
|
524 |
+
// add option to ms dropdown
|
525 |
+
instance._addOption( container, thisOption );
|
526 |
+
|
527 |
+
if( updateSelect ) {
|
528 |
+
var selOption = $('<option value="'+ thisOption.value +'">'+ thisOption.name +'</option>');
|
529 |
+
|
530 |
+
// add custom user attributes
|
531 |
+
if( thisOption.hasOwnProperty('attributes') && Object.keys( thisOption.attributes ).length ) {
|
532 |
+
selOption.attr( thisOption.attributes );
|
533 |
+
}
|
534 |
+
|
535 |
+
// mark option as selected
|
536 |
+
if( thisOption.checked ) {
|
537 |
+
selOption.prop( 'selected', true );
|
538 |
+
}
|
539 |
+
|
540 |
+
select.append( selOption );
|
541 |
+
}
|
542 |
+
}
|
543 |
+
// OPTGROUP
|
544 |
+
else if( thisOption.hasOwnProperty('options') ) {
|
545 |
+
var optGroup = $('<optgroup label="'+ thisOption.label +'"></optgroup>');
|
546 |
+
|
547 |
+
optionsList.find('> li.optgroup > span.label').each(function(){
|
548 |
+
if( $(this).text() == thisOption.label ) {
|
549 |
+
container = $(this).closest('.optgroup');
|
550 |
+
appendContainer = false;
|
551 |
+
}
|
552 |
+
});
|
553 |
+
|
554 |
+
// prepare to append optgroup to select element
|
555 |
+
if( updateSelect ) {
|
556 |
+
if( select.find('optgroup[label="'+ thisOption.label +'"]').length ) {
|
557 |
+
optGroup = select.find('optgroup[label="'+ thisOption.label +'"]');
|
558 |
+
}
|
559 |
+
else {
|
560 |
+
select.append( optGroup );
|
561 |
+
}
|
562 |
+
}
|
563 |
+
|
564 |
+
// setup container
|
565 |
+
if( appendContainer ) {
|
566 |
+
container.addClass('optgroup');
|
567 |
+
container.append('<span class="label">'+ thisOption.label +'</span>');
|
568 |
+
container.find('> .label').css({
|
569 |
+
clear: 'both'
|
570 |
+
});
|
571 |
+
|
572 |
+
// add select all link
|
573 |
+
if( instance.options.selectGroup ) {
|
574 |
+
container.append('<a href="#" class="ms-selectall">' + instance.options.texts.selectAll + '</a>');
|
575 |
+
}
|
576 |
+
|
577 |
+
container.append('<ul/>');
|
578 |
+
}
|
579 |
+
|
580 |
+
for( var gKey in thisOption.options ) {
|
581 |
+
// Prevent prototype methods injected into options from
|
582 |
+
// being iterated over.
|
583 |
+
if( !thisOption.options.hasOwnProperty( gKey ) ) {
|
584 |
+
continue;
|
585 |
+
}
|
586 |
+
|
587 |
+
var thisGOption = thisOption.options[ gKey ];
|
588 |
+
var gContainer = $('<li/>');
|
589 |
+
if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) {
|
590 |
+
gContainer.addClass('ms-reflow');
|
591 |
+
}
|
592 |
+
|
593 |
+
// no clue what this is we hit (skip)
|
594 |
+
if( !thisGOption.hasOwnProperty('value') ) {
|
595 |
+
continue;
|
596 |
+
}
|
597 |
+
|
598 |
+
instance._addOption( gContainer, thisGOption );
|
599 |
+
|
600 |
+
container.find('> ul').append( gContainer );
|
601 |
+
|
602 |
+
// add option to optgroup in select element
|
603 |
+
if( updateSelect ) {
|
604 |
+
var selOption = $('<option value="'+ thisGOption.value +'">'+ thisGOption.name +'</option>');
|
605 |
+
|
606 |
+
// add custom user attributes
|
607 |
+
if( thisGOption.hasOwnProperty('attributes') && Object.keys( thisGOption.attributes ).length ) {
|
608 |
+
selOption.attr( thisGOption.attributes );
|
609 |
+
}
|
610 |
+
|
611 |
+
// mark option as selected
|
612 |
+
if( thisGOption.checked ) {
|
613 |
+
selOption.prop( 'selected', true );
|
614 |
+
}
|
615 |
+
|
616 |
+
optGroup.append( selOption );
|
617 |
+
}
|
618 |
+
}
|
619 |
+
}
|
620 |
+
else {
|
621 |
+
// no clue what this is we hit (skip)
|
622 |
+
continue;
|
623 |
+
}
|
624 |
+
|
625 |
+
if( appendContainer ) {
|
626 |
+
containers.push( container );
|
627 |
+
}
|
628 |
+
}
|
629 |
+
optionsList.append( containers );
|
630 |
+
|
631 |
+
// pad out label for room for the checkbox
|
632 |
+
if( instance.options.checkboxAutoFit && instance.options.showCheckbox && !optionsWrap.hasClass('hide-checkbox') ) {
|
633 |
+
var chkbx = optionsList.find('.ms-reflow:eq(0) input[type="checkbox"]');
|
634 |
+
if( chkbx.length ) {
|
635 |
+
var checkboxWidth = chkbx.outerWidth();
|
636 |
+
checkboxWidth = checkboxWidth ? checkboxWidth : 15;
|
637 |
+
|
638 |
+
optionsList.find('.ms-reflow label').css(
|
639 |
+
'padding-left',
|
640 |
+
(parseInt( chkbx.closest('label').css('padding-left') ) * 2) + checkboxWidth
|
641 |
+
);
|
642 |
+
|
643 |
+
optionsList.find('.ms-reflow').removeClass('ms-reflow');
|
644 |
+
}
|
645 |
+
}
|
646 |
+
|
647 |
+
// update placeholder text
|
648 |
+
instance._updatePlaceholderText();
|
649 |
+
|
650 |
+
// RESET COLUMN STYLES
|
651 |
+
optionsWrap.find('ul').css({
|
652 |
+
'column-count' : '',
|
653 |
+
'column-gap' : '',
|
654 |
+
'-webkit-column-count': '',
|
655 |
+
'-webkit-column-gap' : '',
|
656 |
+
'-moz-column-count' : '',
|
657 |
+
'-moz-column-gap' : ''
|
658 |
+
});
|
659 |
+
|
660 |
+
// COLUMNIZE
|
661 |
+
if( select.find('optgroup').length ) {
|
662 |
+
// float non grouped options
|
663 |
+
optionsList.find('> li:not(.optgroup)').css({
|
664 |
+
'float': 'left',
|
665 |
+
width: (100 / instance.options.columns) +'%'
|
666 |
+
});
|
667 |
+
|
668 |
+
// add CSS3 column styles
|
669 |
+
optionsList.find('li.optgroup').css({
|
670 |
+
clear: 'both'
|
671 |
+
}).find('> ul').css({
|
672 |
+
'column-count' : instance.options.columns,
|
673 |
+
'column-gap' : 0,
|
674 |
+
'-webkit-column-count': instance.options.columns,
|
675 |
+
'-webkit-column-gap' : 0,
|
676 |
+
'-moz-column-count' : instance.options.columns,
|
677 |
+
'-moz-column-gap' : 0
|
678 |
+
});
|
679 |
+
|
680 |
+
// for crappy IE versions float grouped options
|
681 |
+
if( this._ieVersion() && (this._ieVersion() < 10) ) {
|
682 |
+
optionsList.find('li.optgroup > ul > li').css({
|
683 |
+
'float': 'left',
|
684 |
+
width: (100 / instance.options.columns) +'%'
|
685 |
+
});
|
686 |
+
}
|
687 |
+
}
|
688 |
+
else {
|
689 |
+
// add CSS3 column styles
|
690 |
+
optionsList.css({
|
691 |
+
'column-count' : instance.options.columns,
|
692 |
+
'column-gap' : 0,
|
693 |
+
'-webkit-column-count': instance.options.columns,
|
694 |
+
'-webkit-column-gap' : 0,
|
695 |
+
'-moz-column-count' : instance.options.columns,
|
696 |
+
'-moz-column-gap' : 0
|
697 |
+
});
|
698 |
+
|
699 |
+
// for crappy IE versions float grouped options
|
700 |
+
if( this._ieVersion() && (this._ieVersion() < 10) ) {
|
701 |
+
optionsList.find('> li').css({
|
702 |
+
'float': 'left',
|
703 |
+
width: (100 / instance.options.columns) +'%'
|
704 |
+
});
|
705 |
+
}
|
706 |
+
}
|
707 |
+
|
708 |
+
// update un/select all logic
|
709 |
+
instance._updateSelectAllText();
|
710 |
+
},
|
711 |
+
|
712 |
+
/* UPDATE MULTISELECT CONFIG OPTIONS */
|
713 |
+
settings: function( options ) {
|
714 |
+
this.options = $.extend( true, {}, this.options, options );
|
715 |
+
this.reload();
|
716 |
+
},
|
717 |
+
|
718 |
+
/* RESET THE DOM */
|
719 |
+
unload: function() {
|
720 |
+
$(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove();
|
721 |
+
$(this.element).show(function(){
|
722 |
+
$(this).css('display','').removeClass('jqmsLoaded');
|
723 |
+
});
|
724 |
+
},
|
725 |
+
|
726 |
+
/* RELOAD JQ MULTISELECT LIST */
|
727 |
+
reload: function() {
|
728 |
+
// remove existing options
|
729 |
+
$(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove();
|
730 |
+
$(this.element).removeClass('jqmsLoaded');
|
731 |
+
|
732 |
+
// load element
|
733 |
+
this.load();
|
734 |
+
},
|
735 |
+
|
736 |
+
// RESET BACK TO DEFAULT VALUES & RELOAD
|
737 |
+
reset: function() {
|
738 |
+
var defaultVals = [];
|
739 |
+
$(this.element).find('option').each(function(){
|
740 |
+
if( $(this).prop('defaultSelected') ) {
|
741 |
+
defaultVals.push( $(this).val() );
|
742 |
+
}
|
743 |
+
});
|
744 |
+
|
745 |
+
$(this.element).val( defaultVals );
|
746 |
+
|
747 |
+
this.reload();
|
748 |
+
},
|
749 |
+
|
750 |
+
disable: function( status ) {
|
751 |
+
status = (typeof status === 'boolean') ? status : true;
|
752 |
+
$(this.element).prop( 'disabled', status );
|
753 |
+
$(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').find('button:first-child')
|
754 |
+
.prop( 'disabled', status );
|
755 |
+
},
|
756 |
+
|
757 |
+
/** PRIVATE FUNCTIONS **/
|
758 |
+
// update the un/select all texts based on selected options and visibility
|
759 |
+
_updateSelectAllText: function(){
|
760 |
+
if( !this.updateSelectAll ) {
|
761 |
+
return;
|
762 |
+
}
|
763 |
+
|
764 |
+
var instance = this;
|
765 |
+
|
766 |
+
// select all not used at all so just do nothing
|
767 |
+
if( !instance.options.selectAll && !instance.options.selectGroup ) {
|
768 |
+
return;
|
769 |
+
}
|
770 |
+
|
771 |
+
var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
|
772 |
+
|
773 |
+
// update un/select all text
|
774 |
+
optionsWrap.find('.ms-selectall').each(function(){
|
775 |
+
var unselected = $(this).parent().find('li:not(.optgroup,.selected,.ms-hidden)');
|
776 |
+
|
777 |
+
$(this).text(
|
778 |
+
unselected.length ? instance.options.texts.selectAll : instance.options.texts.unselectAll
|
779 |
+
);
|
780 |
+
});
|
781 |
+
},
|
782 |
+
|
783 |
+
// update selected placeholder text
|
784 |
+
_updatePlaceholderText: function(){
|
785 |
+
if( !this.updatePlaceholder ) {
|
786 |
+
return;
|
787 |
+
}
|
788 |
+
|
789 |
+
var instance = this;
|
790 |
+
var select = $(instance.element);
|
791 |
+
var selectVals = select.val() ? select.val() : [];
|
792 |
+
var placeholder = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child');
|
793 |
+
var placeholderTxt = placeholder.find('span');
|
794 |
+
var optionsWrap = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
|
795 |
+
|
796 |
+
// if there are disabled options get those values as well
|
797 |
+
if( select.find('option:selected:disabled').length ) {
|
798 |
+
selectVals = [];
|
799 |
+
select.find('option:selected').each(function(){
|
800 |
+
selectVals.push( $(this).val() );
|
801 |
+
});
|
802 |
+
}
|
803 |
+
|
804 |
+
// get selected options
|
805 |
+
var selOpts = [];
|
806 |
+
for( var key in selectVals ) {
|
807 |
+
// Prevent prototype methods injected into options from being iterated over.
|
808 |
+
if( !selectVals.hasOwnProperty( key ) ) {
|
809 |
+
continue;
|
810 |
+
}
|
811 |
+
|
812 |
+
selOpts.push(
|
813 |
+
$.trim( select.find('option[value="'+ instance._escapeSelector( selectVals[ key ] ) +'"]').text() )
|
814 |
+
);
|
815 |
+
|
816 |
+
if( selOpts.length >= instance.options.maxPlaceholderOpts ) {
|
817 |
+
break;
|
818 |
+
}
|
819 |
+
}
|
820 |
+
|
821 |
+
// UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED
|
822 |
+
placeholderTxt.text( selOpts.join( ', ' ) );
|
823 |
+
|
824 |
+
if( selOpts.length ) {
|
825 |
+
optionsWrap.closest('.ms-options-wrap').addClass('ms-has-selections');
|
826 |
+
|
827 |
+
// USER CALLBACK
|
828 |
+
if( typeof instance.options.onPlaceholder == 'function' ) {
|
829 |
+
instance.options.onPlaceholder( instance.element, placeholderTxt, selOpts );
|
830 |
+
}
|
831 |
+
}
|
832 |
+
else {
|
833 |
+
optionsWrap.closest('.ms-options-wrap').removeClass('ms-has-selections');
|
834 |
+
}
|
835 |
+
|
836 |
+
// replace placeholder text
|
837 |
+
if( !selOpts.length ) {
|
838 |
+
placeholderTxt.text( instance.options.texts.placeholder );
|
839 |
+
}
|
840 |
+
// if copy is larger than button width use "# selected"
|
841 |
+
else if( (placeholderTxt.width() > placeholder.width()) || (selOpts.length != selectVals.length) ) {
|
842 |
+
placeholderTxt.text( selectVals.length + instance.options.texts.selectedOptions );
|
843 |
+
}
|
844 |
+
},
|
845 |
+
|
846 |
+
// Add option to the custom dom list
|
847 |
+
_addOption: function( container, option ) {
|
848 |
+
var instance = this;
|
849 |
+
var thisOption = $('<label/>', {
|
850 |
+
for : 'ms-opt-'+ msOptCounter,
|
851 |
+
text: option.name
|
852 |
+
});
|
853 |
+
|
854 |
+
var thisCheckbox = $('<input>', {
|
855 |
+
type : 'checkbox',
|
856 |
+
title: option.name,
|
857 |
+
id : 'ms-opt-'+ msOptCounter,
|
858 |
+
value: option.value
|
859 |
+
});
|
860 |
+
|
861 |
+
// add user defined attributes
|
862 |
+
if( option.hasOwnProperty('attributes') && Object.keys( option.attributes ).length ) {
|
863 |
+
thisCheckbox.attr( option.attributes );
|
864 |
+
}
|
865 |
+
|
866 |
+
if( option.checked ) {
|
867 |
+
container.addClass('default selected');
|
868 |
+
thisCheckbox.prop( 'checked', true );
|
869 |
+
}
|
870 |
+
|
871 |
+
thisOption.prepend( thisCheckbox );
|
872 |
+
|
873 |
+
var searchTerm = '';
|
874 |
+
if( instance.options.searchOptions.searchText ) {
|
875 |
+
searchTerm += ' ' + option.name.toLowerCase();
|
876 |
+
}
|
877 |
+
if( instance.options.searchOptions.searchValue ) {
|
878 |
+
searchTerm += ' ' + option.value.toLowerCase();
|
879 |
+
}
|
880 |
+
|
881 |
+
container.attr( 'data-search-term', $.trim( searchTerm ) ).prepend( thisOption );
|
882 |
+
|
883 |
+
msOptCounter = msOptCounter + 1;
|
884 |
+
},
|
885 |
+
|
886 |
+
// check ie version
|
887 |
+
_ieVersion: function() {
|
888 |
+
var myNav = navigator.userAgent.toLowerCase();
|
889 |
+
return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
|
890 |
+
},
|
891 |
+
|
892 |
+
// escape selector
|
893 |
+
_escapeSelector: function( string ) {
|
894 |
+
if( typeof $.escapeSelector == 'function' ) {
|
895 |
+
return $.escapeSelector( string );
|
896 |
+
}
|
897 |
+
else {
|
898 |
+
return string.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
899 |
+
}
|
900 |
+
}
|
901 |
+
};
|
902 |
+
|
903 |
+
// ENABLE JQUERY PLUGIN FUNCTION
|
904 |
+
$.fn.multiselect = function( options ){
|
905 |
+
if( !this.length ) {
|
906 |
+
return;
|
907 |
+
}
|
908 |
+
|
909 |
+
var args = arguments;
|
910 |
+
var ret;
|
911 |
+
|
912 |
+
// menuize each list
|
913 |
+
if( (options === undefined) || (typeof options === 'object') ) {
|
914 |
+
return this.each(function(){
|
915 |
+
if( !$.data( this, 'plugin_multiselect' ) ) {
|
916 |
+
$.data( this, 'plugin_multiselect', new MultiSelect( this, options ) );
|
917 |
+
}
|
918 |
+
});
|
919 |
+
} else if( (typeof options === 'string') && (options[0] !== '_') && (options !== 'init') ) {
|
920 |
+
this.each(function(){
|
921 |
+
var instance = $.data( this, 'plugin_multiselect' );
|
922 |
+
|
923 |
+
if( instance instanceof MultiSelect && typeof instance[ options ] === 'function' ) {
|
924 |
+
ret = instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) );
|
925 |
+
}
|
926 |
+
|
927 |
+
// special destruct handler
|
928 |
+
if( options === 'unload' ) {
|
929 |
+
$.data( this, 'plugin_multiselect', null );
|
930 |
+
}
|
931 |
+
});
|
932 |
+
|
933 |
+
return ret;
|
934 |
+
}
|
935 |
+
};
|
936 |
+
}(jQuery));
|
core/admin-pages/js/script.js
DELETED
@@ -1,1135 +0,0 @@
|
|
1 |
-
"use strict";
|
2 |
-
|
3 |
-
var itsecSettingsPage = {
|
4 |
-
|
5 |
-
events: jQuery( {} ),
|
6 |
-
|
7 |
-
init: function() {
|
8 |
-
jQuery( '.itsec-module-settings-container' ).hide();
|
9 |
-
|
10 |
-
this.bindEvents();
|
11 |
-
|
12 |
-
jQuery( '.itsec-settings-view-toggle .itsec-selected' ).removeClass( 'itsec-selected' ).trigger( 'click' );
|
13 |
-
jQuery( '.itsec-settings-toggle' ).trigger( 'change' );
|
14 |
-
|
15 |
-
this.initFilters();
|
16 |
-
this.initCurrentModule();
|
17 |
-
this.makeNoticesDismissible();
|
18 |
-
},
|
19 |
-
|
20 |
-
initFilters: function() {
|
21 |
-
var module_type = this.getUrlParameter( 'module_type' );
|
22 |
-
if ( false === module_type || 0 === jQuery( '#itsec-module-filter-' + module_type.replace( /[^\w-]/g, '' ) ).length ) {
|
23 |
-
module_type = 'recommended';
|
24 |
-
}
|
25 |
-
jQuery( '#itsec-module-filter-' + module_type.replace( /[^\w-]/g, '' ) + ' a' ).trigger( 'click' );
|
26 |
-
},
|
27 |
-
|
28 |
-
initCurrentModule: function() {
|
29 |
-
|
30 |
-
var module = this.getUrlParameter( 'module' );
|
31 |
-
if ( 'string' === typeof module ) {
|
32 |
-
jQuery( '#itsec-module-card-' + module.replace( /[^\w-]/g, '' ) + ' button.itsec-toggle-settings' ).trigger( 'click' );
|
33 |
-
}
|
34 |
-
},
|
35 |
-
|
36 |
-
bindEvents: function() {
|
37 |
-
|
38 |
-
if ( itsecSettingsPage.bindEvents.bound ) {
|
39 |
-
return;
|
40 |
-
}
|
41 |
-
|
42 |
-
jQuery(window).on("popstate", function(e, data) {
|
43 |
-
if ( null !== e.originalEvent.state && 'string' == typeof e.originalEvent.state.module && '' !== e.originalEvent.state.module.replace( /[^\w-]/g, '' ) ) {
|
44 |
-
jQuery( '#itsec-module-card-' + e.originalEvent.state.module.replace( /[^\w-]/g, '' ) + ' button.itsec-toggle-settings' ).trigger( 'itsec-popstate' );
|
45 |
-
} else {
|
46 |
-
itsecSettingsPage.closeGridSettingsModal( e );
|
47 |
-
}
|
48 |
-
|
49 |
-
if ( null !== e.originalEvent.state && 'string' == typeof e.originalEvent.state.module_type && '' !== e.originalEvent.state.module_type.replace( /[^\w-]/g, '' ) ) {
|
50 |
-
jQuery( '#itsec-module-filter-' + e.originalEvent.state.module_type.replace( /[^\w-]/g, '' ) + ' a' ).trigger( 'itsec-popstate' );
|
51 |
-
}
|
52 |
-
});
|
53 |
-
|
54 |
-
var $container = jQuery( '#wpcontent' );
|
55 |
-
|
56 |
-
$container.on( 'click', '.itsec-module-filter a', this.filterView );
|
57 |
-
$container.on( 'itsec-popstate', '.itsec-module-filter a', this.filterView );
|
58 |
-
$container.on( 'click', '.itsec-settings-view-toggle a', this.toggleView );
|
59 |
-
// $container.on( 'click', '.itsec-toggle-settings, .itsec-module-card-content h2', this.toggleSettings );
|
60 |
-
$container.on( 'click', 'a[data-module-link]', this.openModuleFromLink );
|
61 |
-
$container.on( 'click', '.list .itsec-module-card:not(.itsec-module-pro-upsell) .itsec-module-card-content, .itsec-toggle-settings, .itsec-module-settings-cancel', this.toggleSettings );
|
62 |
-
$container.on( 'itsec-popstate', '.list .itsec-module-card-content, .itsec-toggle-settings', this.toggleSettings );
|
63 |
-
$container.on( 'click', '.itsec-close-modal, .itsec-modal-background', this.closeGridSettingsModal );
|
64 |
-
$container.on( 'keyup', this.closeGridSettingsModal );
|
65 |
-
$container.on( 'click', '.itsec-toggle-activation', this.toggleModuleActivation );
|
66 |
-
$container.on( 'click', '.itsec-module-settings-save', this.saveSettings );
|
67 |
-
$container.on( 'click', '.itsec-reload-module', this.reloadModule );
|
68 |
-
$container.on( 'click', '.itsec-details-toggle-container a[href="#"]', this.toggleDetails );
|
69 |
-
|
70 |
-
$container.on( 'change', '#itsec-filter', this.logPageChangeFilter );
|
71 |
-
|
72 |
-
// For use by module content to show/hide settings sections based upon an input.
|
73 |
-
$container.on( 'change', '.itsec-settings-toggle', this.toggleModuleContent );
|
74 |
-
$container.on( 'click', '.itsec-copy-trigger', this.handleCopy );
|
75 |
-
|
76 |
-
itsecSettingsPage.bindEvents.bound = true;
|
77 |
-
},
|
78 |
-
|
79 |
-
toggleDetails: function( e ) {
|
80 |
-
e.preventDefault();
|
81 |
-
|
82 |
-
var $details = jQuery(this).parent().find( '.itsec-details-toggle-details' ).toggleClass( 'hide-if-js' );
|
83 |
-
|
84 |
-
if ( $details.hasClass( 'hide-if-js' ) ) {
|
85 |
-
jQuery(this).html( itsec_page.translations.show_information );
|
86 |
-
} else {
|
87 |
-
jQuery(this).html( itsec_page.translations.hide_description );
|
88 |
-
}
|
89 |
-
},
|
90 |
-
|
91 |
-
logPageChangeFilter: function( e ) {
|
92 |
-
var filter = jQuery( this ).val();
|
93 |
-
var url = itsec_page.logs_page_url + '&filter=' + filter;
|
94 |
-
window.location.href = url;
|
95 |
-
},
|
96 |
-
|
97 |
-
toggleModuleContent: function( e ) {
|
98 |
-
if ( 'checkbox' === jQuery(this).attr( 'type' ) ) {
|
99 |
-
var show = jQuery(this).prop( 'checked' );
|
100 |
-
} else {
|
101 |
-
var show = ( jQuery(this).val() ) ? true : false;
|
102 |
-
}
|
103 |
-
|
104 |
-
var $content = jQuery( '.' + jQuery(this).attr( 'id' ) + '-content' );
|
105 |
-
|
106 |
-
if ( show ) {
|
107 |
-
$content.show();
|
108 |
-
|
109 |
-
|
110 |
-
var $container = jQuery( '.itsec-module-cards-container' );
|
111 |
-
|
112 |
-
if ( $container.hasClass( 'grid' ) ) {
|
113 |
-
var $modal = jQuery(this).parents( '.itsec-module-settings-content-container' );
|
114 |
-
var scrollOffset = $modal.scrollTop() + jQuery(this).parent().position().top;
|
115 |
-
|
116 |
-
$modal.animate( {'scrollTop': scrollOffset}, 'slow' );
|
117 |
-
}
|
118 |
-
} else {
|
119 |
-
$content.hide();
|
120 |
-
}
|
121 |
-
},
|
122 |
-
|
123 |
-
handleCopy: function( e ) {
|
124 |
-
|
125 |
-
e.preventDefault();
|
126 |
-
|
127 |
-
var $trigger = jQuery( e.currentTarget );
|
128 |
-
var fromId = $trigger.data( 'copy-from' );
|
129 |
-
|
130 |
-
if ( ! fromId.length ) {
|
131 |
-
return;
|
132 |
-
}
|
133 |
-
|
134 |
-
var el = document.getElementById( fromId );
|
135 |
-
|
136 |
-
var removeSelect = itsecSettingsPage.selectText( el );
|
137 |
-
|
138 |
-
try {
|
139 |
-
|
140 |
-
document.execCommand( 'copy' );
|
141 |
-
removeSelect();
|
142 |
-
$trigger.text( itsec_page.translations.copied );
|
143 |
-
|
144 |
-
} catch ( e ) {
|
145 |
-
var $p = jQuery( '<p></p>' ).text( itsec_page.translations.copy_instruction ),
|
146 |
-
$notice = jQuery( '<div class="notice notice-alt notice-info"></div>' ).append( $p ),
|
147 |
-
$el = jQuery( el );
|
148 |
-
|
149 |
-
$trigger.after( $notice );
|
150 |
-
|
151 |
-
var removeNotice = function () {
|
152 |
-
$notice.fadeOut( function () {
|
153 |
-
$notice.remove();
|
154 |
-
} );
|
155 |
-
};
|
156 |
-
var copy = function () {
|
157 |
-
|
158 |
-
setTimeout( function () {
|
159 |
-
removeNotice();
|
160 |
-
removeSelect();
|
161 |
-
}, 100 );
|
162 |
-
|
163 |
-
$el.off( 'copy', copy );
|
164 |
-
|
165 |
-
return true;
|
166 |
-
};
|
167 |
-
|
168 |
-
$el.on( 'copy', copy );
|
169 |
-
|
170 |
-
setTimeout( removeNotice, 5000 );
|
171 |
-
}
|
172 |
-
},
|
173 |
-
|
174 |
-
// https://stackoverflow.com/a/987376
|
175 |
-
selectText: function( element ) {
|
176 |
-
var doc = document, text = element, range, selection;
|
177 |
-
|
178 |
-
if ( doc.body.createTextRange ) { // ie
|
179 |
-
range = document.body.createTextRange();
|
180 |
-
range.moveToElementText( text );
|
181 |
-
range.select();
|
182 |
-
} else if ( window.getSelection ) {
|
183 |
-
selection = window.getSelection();
|
184 |
-
range = document.createRange();
|
185 |
-
range.selectNodeContents( text );
|
186 |
-
selection.removeAllRanges();
|
187 |
-
selection.addRange( range );
|
188 |
-
}
|
189 |
-
|
190 |
-
return function() {
|
191 |
-
if ( selection ) {
|
192 |
-
selection.removeAllRanges();
|
193 |
-
} else {
|
194 |
-
range.collapse();
|
195 |
-
}
|
196 |
-
};
|
197 |
-
},
|
198 |
-
|
199 |
-
saveSettings: function( e ) {
|
200 |
-
e.preventDefault();
|
201 |
-
|
202 |
-
var $button = jQuery(this);
|
203 |
-
|
204 |
-
if ( $button.hasClass( 'itsec-module-settings-save' ) ) {
|
205 |
-
var module = $button.parents( '.itsec-module-card' ).attr( 'id' ).replace( 'itsec-module-card-', '' );
|
206 |
-
} else {
|
207 |
-
var module = '';
|
208 |
-
}
|
209 |
-
|
210 |
-
$button.prop( 'disabled', true );
|
211 |
-
|
212 |
-
var data = {
|
213 |
-
'--itsec-form-serialized-data': jQuery( '#itsec-module-settings-form' ).serialize()
|
214 |
-
};
|
215 |
-
|
216 |
-
itsecSettingsPage.sendAJAXRequest( module, 'save', data, itsecSettingsPage.saveSettingsCallback );
|
217 |
-
},
|
218 |
-
|
219 |
-
saveSettingsCallback: function( results ) {
|
220 |
-
if ( '' === results.module ) {
|
221 |
-
jQuery( '#itsec-save' ).prop( 'disabled', false );
|
222 |
-
} else {
|
223 |
-
jQuery( '#itsec-module-card-' + results.module + ' button.itsec-module-settings-save' ).prop( 'disabled', false );
|
224 |
-
}
|
225 |
-
|
226 |
-
var $container = jQuery( '.itsec-module-cards-container' );
|
227 |
-
|
228 |
-
if ( $container.hasClass( 'grid' ) ) {
|
229 |
-
var view = 'grid';
|
230 |
-
} else {
|
231 |
-
var view = 'list';
|
232 |
-
}
|
233 |
-
|
234 |
-
itsecSettingsPage.clearMessages();
|
235 |
-
|
236 |
-
if ( results.errors.length > 0 || results.warnings.length > 0 || ! results.closeModal ) {
|
237 |
-
itsecSettingsPage.showErrors( results.errors, results.module, 'open' );
|
238 |
-
itsecSettingsPage.showErrors( results.warnings, results.module, 'open', 'warning' );
|
239 |
-
itsecSettingsPage.showMessages( results.messages, results.module, 'open' );
|
240 |
-
itsecSettingsPage.showMessages( results.infos, results.module, 'open', 'info' );
|
241 |
-
|
242 |
-
if ( 'grid' === view ) {
|
243 |
-
$container.find( '.itsec-module-settings-content-container:visible' ).animate( {'scrollTop': 0}, 'fast' );
|
244 |
-
}
|
245 |
-
|
246 |
-
if ( 'list' === view ) {
|
247 |
-
jQuery(document).scrollTop( 0 );
|
248 |
-
}
|
249 |
-
} else {
|
250 |
-
itsecSettingsPage.showMessages( results.messages, results.module, 'closed' );
|
251 |
-
itsecSettingsPage.showMessages( results.infos, results.module, 'closed', 'info' );
|
252 |
-
|
253 |
-
if ( 'grid' === view ) {
|
254 |
-
$container.find( '.itsec-module-settings-content-container:visible' ).scrollTop( 0 );
|
255 |
-
itsecSettingsPage.closeGridSettingsModal();
|
256 |
-
}
|
257 |
-
}
|
258 |
-
},
|
259 |
-
|
260 |
-
clearMessages: function() {
|
261 |
-
jQuery( '#itsec-settings-messages-container, .itsec-module-messages-container' ).empty();
|
262 |
-
},
|
263 |
-
|
264 |
-
showErrors: function( errors, module, containerStatus, type ) {
|
265 |
-
jQuery.each( errors, function( index, error ) {
|
266 |
-
itsecSettingsPage.showError( error, module, containerStatus, type );
|
267 |
-
} );
|
268 |
-
},
|
269 |
-
|
270 |
-
showError: function( error, module, containerStatus, type ) {
|
271 |
-
|
272 |
-
type = type || 'error';
|
273 |
-
|
274 |
-
if ( jQuery( '.itsec-module-cards-container' ).hasClass( 'grid' ) ) {
|
275 |
-
var view = 'grid';
|
276 |
-
} else {
|
277 |
-
var view = 'list';
|
278 |
-
}
|
279 |
-
|
280 |
-
if ( 'closed' !== containerStatus && 'open' !== containerStatus ) {
|
281 |
-
containerStatus = 'closed';
|
282 |
-
}
|
283 |
-
|
284 |
-
if ( 'string' !== typeof module ) {
|
285 |
-
module = '';
|
286 |
-
}
|
287 |
-
|
288 |
-
|
289 |
-
if ( 'closed' === containerStatus || '' === module ) {
|
290 |
-
var container = jQuery( '#itsec-settings-messages-container' );
|
291 |
-
|
292 |
-
if ( '' === module ) {
|
293 |
-
container.addClass( 'no-module' );
|
294 |
-
}
|
295 |
-
} else {
|
296 |
-
var container = jQuery( '#itsec-module-card-' + module + ' .itsec-module-messages-container' );
|
297 |
-
}
|
298 |
-
|
299 |
-
var $notice = jQuery( '<div class="notice"><p><strong>' + error + '</strong></p></div>' );
|
300 |
-
$notice.addClass( 'notice-' + type );
|
301 |
-
|
302 |
-
if ( containerStatus === 'open' || module.length ) {
|
303 |
-
$notice.addClass( 'notice-alt' );
|
304 |
-
}
|
305 |
-
|
306 |
-
container.append( $notice ).addClass( 'visible' );
|
307 |
-
},
|
308 |
-
|
309 |
-
showMessages: function( messages, module, containerStatus, type ) {
|
310 |
-
jQuery.each( messages, function( index, message ) {
|
311 |
-
itsecSettingsPage.showMessage( message, module, containerStatus, type );
|
312 |
-
} );
|
313 |
-
},
|
314 |
-
|
315 |
-
showMessage: function( message, module, containerStatus, type ) {
|
316 |
-
|
317 |
-
type = type || 'success';
|
318 |
-
|
319 |
-
if ( jQuery( '.itsec-module-cards-container' ).hasClass( 'grid' ) ) {
|
320 |
-
var view = 'grid';
|
321 |
-
} else {
|
322 |
-
var view = 'list';
|
323 |
-
}
|
324 |
-
|
325 |
-
if ( 'closed' !== containerStatus && 'open' !== containerStatus ) {
|
326 |
-
containerStatus = 'closed';
|
327 |
-
}
|
328 |
-
|
329 |
-
if ( 'string' !== typeof module ) {
|
330 |
-
module = '';
|
331 |
-
}
|
332 |
-
|
333 |
-
|
334 |
-
if ( 'closed' === containerStatus || '' === module ) {
|
335 |
-
var container = jQuery( '#itsec-settings-messages-container' );
|
336 |
-
|
337 |
-
var dismiss = function () {
|
338 |
-
|
339 |
-
if ( container.is( ':hover' ) ) {
|
340 |
-
return setTimeout( dismiss, 2000 );
|
341 |
-
}
|
342 |
-
|
343 |
-
container.removeClass( 'visible' );
|
344 |
-
setTimeout( function () {
|
345 |
-
container.find( 'div' ).remove();
|
346 |
-
}, 500 );
|
347 |
-
};
|
348 |
-
|
349 |
-
setTimeout( dismiss, 4000 );
|
350 |
-
} else {
|
351 |
-
var container = jQuery( '#itsec-module-card-' + module + ' .itsec-module-messages-container' );
|
352 |
-
}
|
353 |
-
|
354 |
-
var $notice = jQuery( '<div class="notice fade"><p><strong>' + message + '</strong></p></div>' );
|
355 |
-
$notice.addClass( 'notice-' + type );
|
356 |
-
|
357 |
-
if ( containerStatus === 'open' || module.length ) {
|
358 |
-
$notice.addClass( 'notice-alt' );
|
359 |
-
}
|
360 |
-
|
361 |
-
container.append( $notice ).addClass( 'visible' );
|
362 |
-
},
|
363 |
-
|
364 |
-
filterView: function( e ) {
|
365 |
-
e.preventDefault();
|
366 |
-
|
367 |
-
var $activeLink = jQuery(this),
|
368 |
-
$oldLink = $activeLink.parents( '.itsec-feature-tabs' ).find( '.current' ),
|
369 |
-
type = $activeLink.parent().attr( 'id' ).substr( 20 );
|
370 |
-
|
371 |
-
$oldLink.removeClass( 'current' );
|
372 |
-
$activeLink.addClass( 'current' );
|
373 |
-
|
374 |
-
if ( 'all' === type ) {
|
375 |
-
jQuery( '.itsec-module-card' ).show();
|
376 |
-
} else {
|
377 |
-
jQuery( '.itsec-module-type-' + type ).show();
|
378 |
-
jQuery( '.itsec-module-card' ).not( '.itsec-module-type-' + type ).hide();
|
379 |
-
}
|
380 |
-
|
381 |
-
// We use this to avoid pushing a new state when we're trying to handle a popstate
|
382 |
-
if ( 'itsec-popstate' !== e.type ) {
|
383 |
-
var url = '?page=itsec&module_type=' + type;
|
384 |
-
var module = itsecSettingsPage.getUrlParameter( 'module' );
|
385 |
-
if ( 'string' === typeof module ) {
|
386 |
-
url += '&module=' + module;
|
387 |
-
}
|
388 |
-
|
389 |
-
window.history.pushState( {'module_type':type}, type, url );
|
390 |
-
}
|
391 |
-
},
|
392 |
-
|
393 |
-
toggleView: function( e ) {
|
394 |
-
e.preventDefault();
|
395 |
-
|
396 |
-
var $self = jQuery(this);
|
397 |
-
|
398 |
-
if ( $self.hasClass( 'itsec-selected' ) ) {
|
399 |
-
// Do nothing if already selected.
|
400 |
-
return;
|
401 |
-
}
|
402 |
-
|
403 |
-
var $view = $self.attr( 'class' ).replace( 'itsec-', '' );
|
404 |
-
|
405 |
-
$self.addClass( 'itsec-selected' ).siblings().removeClass( 'itsec-selected' );
|
406 |
-
jQuery( '.itsec-module-settings-container' ).hide();
|
407 |
-
|
408 |
-
jQuery( '.itsec-toggle-settings' ).each(function( index ) {
|
409 |
-
var $button = jQuery( this );
|
410 |
-
|
411 |
-
if ( $button.parents( '.itsec-module-card' ).hasClass( 'itsec-module-type-enabled' ) && ! $button.hasClass( 'information-only' ) ) {
|
412 |
-
$button.html( itsec_page.translations.show_settings );
|
413 |
-
} else if ( $button.hasClass( 'information-only' ) ) {
|
414 |
-
$button.html( itsec_page.translations.information_only );
|
415 |
-
} else {
|
416 |
-
$button.html( itsec_page.translations.show_description );
|
417 |
-
}
|
418 |
-
});
|
419 |
-
|
420 |
-
var $cardContainer = jQuery( '.itsec-module-cards-container' );
|
421 |
-
jQuery.post( ajaxurl, {
|
422 |
-
'action': 'itsec-set-user-setting',
|
423 |
-
'itsec-user-setting-nonce': $self.parent().data( 'nonce' ),
|
424 |
-
'setting': 'itsec-settings-view',
|
425 |
-
'value': $view
|
426 |
-
} );
|
427 |
-
|
428 |
-
$cardContainer.fadeOut( 100, function() {
|
429 |
-
$cardContainer.removeClass( 'grid list' ).addClass( $view );
|
430 |
-
} );
|
431 |
-
$cardContainer.fadeIn( 100 );
|
432 |
-
},
|
433 |
-
|
434 |
-
openModuleFromLink: function( e ) {
|
435 |
-
|
436 |
-
var $link = jQuery( this ), module = $link.data( 'module-link' ),
|
437 |
-
$module = jQuery( '.itsec-module-card[data-module-id="' + module + '"]' ),
|
438 |
-
highlight = $link.data( 'highlight-setting-id' );
|
439 |
-
|
440 |
-
if ( ! $module.length ) {
|
441 |
-
return; // safety check
|
442 |
-
}
|
443 |
-
|
444 |
-
e.preventDefault();
|
445 |
-
|
446 |
-
jQuery( '.itsec-module-settings-container:visible' ).hide();
|
447 |
-
|
448 |
-
var $listClassElement = $module.parents( '.itsec-module-cards-container' ),
|
449 |
-
$toggleButton = $module.find( '.itsec-toggle-settings' );
|
450 |
-
|
451 |
-
if ( highlight && highlight.length ) {
|
452 |
-
jQuery( 'label[for="' + highlight + '"]', $module ).parents( 'tr' ).addClass( 'itsec-highlighted-setting' );
|
453 |
-
}
|
454 |
-
|
455 |
-
if ( $listClassElement.hasClass( 'list' ) ) {
|
456 |
-
itsecSettingsPage.toggleListSettingsCard.call( $toggleButton, e );
|
457 |
-
} else if ( $listClassElement.hasClass( 'grid' ) ) {
|
458 |
-
itsecSettingsPage.showGridSettingsModal.call( $toggleButton, e );
|
459 |
-
}
|
460 |
-
|
461 |
-
var type = $module.hasClass( 'itsec-module-type-advanced' ) ? 'advanced' : 'recommended';
|
462 |
-
|
463 |
-
window.history.pushState( {module: module}, module, '?page=itsec&module=' + module + '&module_type=' + type );
|
464 |
-
|
465 |
-
var href = $link.attr( 'href' );
|
466 |
-
|
467 |
-
if ( href && href.length > 1 && href.charAt( 0 ) === '#' ) {
|
468 |
-
setTimeout( function () {
|
469 |
-
jQuery( '.itsec-module-settings-content-container', '#itsec-module-card-notification-center' ).scrollTo( jQuery( href ), 'swing', { offset: -30 } );
|
470 |
-
}, 350 );
|
471 |
-
}
|
472 |
-
},
|
473 |
-
|
474 |
-
toggleSettings: function( e ) {
|
475 |
-
e.stopPropagation();
|
476 |
-
|
477 |
-
var $listClassElement = jQuery(e.currentTarget).parents( '.itsec-module-cards-container' );
|
478 |
-
|
479 |
-
if ( $listClassElement.hasClass( 'list') ) {
|
480 |
-
itsecSettingsPage.toggleListSettingsCard.call( this, e );
|
481 |
-
} else if ( $listClassElement.hasClass( 'grid' ) ) {
|
482 |
-
itsecSettingsPage.showGridSettingsModal.call( this, e );
|
483 |
-
}
|
484 |
-
|
485 |
-
// We use this to avoid pushing a new state when we're trying to handle a popstate
|
486 |
-
if ( 'itsec-popstate' !== e.type ) {
|
487 |
-
var module_id = jQuery(this).closest('.itsec-module-card').data( 'module-id' );
|
488 |
-
|
489 |
-
var module_type = itsecSettingsPage.getUrlParameter( 'module_type' );
|
490 |
-
if ( false === module_type || 0 === jQuery( '#itsec-module-filter-' + module_type.replace( /[^\w-]/g, '' ) ).length ) {
|
491 |
-
module_type = 'recommended';
|
492 |
-
}
|
493 |
-
window.history.pushState( {'module':module_id}, module_id, '?page=itsec&module=' + module_id + '&module_type=' + module_type );
|
494 |
-
}
|
495 |
-
},
|
496 |
-
|
497 |
-
toggleListSettingsCard: function( e ) {
|
498 |
-
e.preventDefault();
|
499 |
-
|
500 |
-
var $container = jQuery(this);
|
501 |
-
|
502 |
-
if ( ! $container.hasClass( 'itsec-module-card-content' ) ) {
|
503 |
-
$container = $container.parents( '.itsec-module-card' ).find( '.itsec-module-card-content' );
|
504 |
-
}
|
505 |
-
|
506 |
-
var $settings = $container.siblings( '.itsec-module-settings-container' ),
|
507 |
-
isVisible = $settings.is( ':visible' );
|
508 |
-
$settings.stop().slideToggle( 300 );
|
509 |
-
|
510 |
-
if ( ! isVisible ) {
|
511 |
-
var $highlighted = jQuery( '.itsec-highlighted-setting', $settings );
|
512 |
-
|
513 |
-
if ( $highlighted.length ) {
|
514 |
-
setTimeout( function () {
|
515 |
-
jQuery.scrollTo( $highlighted.first(), 'swing', {
|
516 |
-
offset: { top: -30 },
|
517 |
-
onAfter: function() {
|
518 |
-
var $el = jQuery( 'input[type!="button"], textarea, select', $highlighted ).not( ':hidden' ).first();
|
519 |
-
itsecSettingsPage.focus( $el, $highlighted );
|
520 |
-
}
|
521 |
-
} );
|
522 |
-
}, 50 );
|
523 |
-
} else {
|
524 |
-
var $el = jQuery( 'input[type!="button"], textarea, select', $settings ).not( ':hidden' ).first();
|
525 |
-
itsecSettingsPage.focus( $el, $settings );
|
526 |
-
}
|
527 |
-
}
|
528 |
-
|
529 |
-
var $button = $container.find( '.itsec-toggle-settings' );
|
530 |
-
|
531 |
-
if ( $container.parent().hasClass( 'itsec-module-type-enabled' ) ) {
|
532 |
-
if ( $button.html() == itsec_page.translations.show_settings ) {
|
533 |
-
$button.html( itsec_page.translations.hide_settings );
|
534 |
-
} else {
|
535 |
-
$button.html( itsec_page.translations.show_settings );
|
536 |
-
}
|
537 |
-
} else {
|
538 |
-
if ( $button.hasClass( 'information-only' ) ) {
|
539 |
-
if ( $button.html() == itsec_page.translations.show_information ) {
|
540 |
-
$button.html( itsec_page.translations.hide_description );
|
541 |
-
} else {
|
542 |
-
$button.html( itsec_page.translations.show_information );
|
543 |
-
}
|
544 |
-
} else {
|
545 |
-
if ( $button.html() == itsec_page.translations.show_description ) {
|
546 |
-
$button.html( itsec_page.translations.hide_description );
|
547 |
-
} else {
|
548 |
-
$button.html( itsec_page.translations.show_description );
|
549 |
-
}
|
550 |
-
}
|
551 |
-
}
|
552 |
-
},
|
553 |
-
|
554 |
-
showGridSettingsModal: function( e ) {
|
555 |
-
e.preventDefault();
|
556 |
-
|
557 |
-
var $module = jQuery(this).parents( '.itsec-module-card' ),
|
558 |
-
$settingsContainer = $module.find( '.itsec-module-settings-container' ),
|
559 |
-
$modalBackground = jQuery( '.itsec-modal-background' );
|
560 |
-
|
561 |
-
$module.show();
|
562 |
-
|
563 |
-
$modalBackground.fadeIn();
|
564 |
-
$settingsContainer.fadeIn( 200 );
|
565 |
-
|
566 |
-
jQuery( 'body' ).addClass( 'itsec-modal-open' );
|
567 |
-
|
568 |
-
var $highlighted = jQuery( '.itsec-highlighted-setting', $module ).first();
|
569 |
-
|
570 |
-
if ( $highlighted.length ) {
|
571 |
-
jQuery( '.itsec-module-settings-content-container', $module ).scrollTo( $highlighted, 'swing', {
|
572 |
-
offset: { top: -20 },
|
573 |
-
onAfter: function() {
|
574 |
-
var $el = jQuery( 'input[type!="button"], textarea, select', $highlighted ).not( ':hidden' ).first();
|
575 |
-
itsecSettingsPage.focus( $el, $highlighted );
|
576 |
-
}
|
577 |
-
} );
|
578 |
-
} else {
|
579 |
-
var $el = jQuery( 'input[type!="button"], textarea, select', $settingsContainer ).not( ':hidden' ).first();
|
580 |
-
itsecSettingsPage.focus( $el, $settingsContainer );
|
581 |
-
}
|
582 |
-
},
|
583 |
-
|
584 |
-
focus: function( $el, $fallback ) {
|
585 |
-
if ( itsecSettingsPage.isElementVisible( $el ) && jQuery( window ).height() > 800 ) {
|
586 |
-
$el.focus();
|
587 |
-
} else {
|
588 |
-
$fallback.prop( 'tabindex', -1 ).focus();
|
589 |
-
}
|
590 |
-
},
|
591 |
-
|
592 |
-
isElementVisible: function( $el ) {
|
593 |
-
|
594 |
-
var $window = jQuery( window ), height = $window.height(), width = $window.width(), offset = $el.offset();
|
595 |
-
|
596 |
-
if ( ! $el || ! offset ) {
|
597 |
-
return false;
|
598 |
-
}
|
599 |
-
|
600 |
-
return offset.top < height && offset.left < width;
|
601 |
-
},
|
602 |
-
|
603 |
-
closeGridSettingsModal: function( e ) {
|
604 |
-
if ( 'undefined' !== typeof e ) {
|
605 |
-
e.preventDefault();
|
606 |
-
|
607 |
-
// For keyup events, only process esc
|
608 |
-
if ( 'keyup' === e.type && 27 !== e.which ) {
|
609 |
-
return;
|
610 |
-
}
|
611 |
-
}
|
612 |
-
|
613 |
-
jQuery( '.itsec-modal-background' ).fadeOut();
|
614 |
-
jQuery( '.itsec-module-settings-container' ).fadeOut( 200 );
|
615 |
-
jQuery( 'body' ).removeClass( 'itsec-modal-open' );
|
616 |
-
|
617 |
-
if ( 'undefined' === typeof e || 'popstate' !== e.type ) {
|
618 |
-
var module_type = itsecSettingsPage.getUrlParameter( 'module_type' );
|
619 |
-
if ( false === module_type || 0 === jQuery( '#itsec-module-filter-' + module_type.replace( /[^\w-]/g, '' ) ).length ) {
|
620 |
-
module_type = 'recommended';
|
621 |
-
}
|
622 |
-
window.history.pushState( {'module':'', 'module_type':module_type}, module_type, '?page=itsec&module_type=' + module_type );
|
623 |
-
}
|
624 |
-
|
625 |
-
if ( jQuery( '#search' ).val().length ) {
|
626 |
-
jQuery( '#search' ).focus();
|
627 |
-
}
|
628 |
-
},
|
629 |
-
|
630 |
-
toggleModuleActivation: function( e ) {
|
631 |
-
e.preventDefault();
|
632 |
-
e.stopPropagation();
|
633 |
-
|
634 |
-
var $button = jQuery(this),
|
635 |
-
$card = $button.parents( '.itsec-module-card' ),
|
636 |
-
$buttons = $card.find( '.itsec-toggle-activation' ),
|
637 |
-
module = $card.attr( 'id' ).replace( 'itsec-module-card-', '' );
|
638 |
-
|
639 |
-
$buttons.prop( 'disabled', true );
|
640 |
-
|
641 |
-
if ( $button.html() == itsec_page.translations.activate ) {
|
642 |
-
var method = 'activate';
|
643 |
-
} else {
|
644 |
-
var method = 'deactivate';
|
645 |
-
}
|
646 |
-
|
647 |
-
itsecSettingsPage.sendAJAXRequest( module, method, {}, itsecSettingsPage.toggleModuleActivationCallback );
|
648 |
-
},
|
649 |
-
|
650 |
-
setModuleToActive: function( module ) {
|
651 |
-
var args = {
|
652 |
-
'module': module,
|
653 |
-
'method': 'activate',
|
654 |
-
'errors': []
|
655 |
-
};
|
656 |
-
|
657 |
-
itsecSettingsPage.toggleModuleActivationCallback( args );
|
658 |
-
},
|
659 |
-
|
660 |
-
setModuleToInactive: function( module ) {
|
661 |
-
var args = {
|
662 |
-
'module': module,
|
663 |
-
'method': 'deactivate',
|
664 |
-
'errors': []
|
665 |
-
};
|
666 |
-
|
667 |
-
itsecSettingsPage.toggleModuleActivationCallback( args );
|
668 |
-
},
|
669 |
-
|
670 |
-
toggleModuleActivationCallback: function( results ) {
|
671 |
-
var module = results.module;
|
672 |
-
var method = results.method;
|
673 |
-
|
674 |
-
var $card = jQuery( '#itsec-module-card-' + module ),
|
675 |
-
$buttons = $card.find( '.itsec-toggle-activation' )
|
676 |
-
|
677 |
-
if ( results.errors.length > 0 ) {
|
678 |
-
$buttons
|
679 |
-
.html( itsec_page.translations.error )
|
680 |
-
.addClass( 'button-secondary' )
|
681 |
-
.removeClass( 'button-primary' );
|
682 |
-
|
683 |
-
setTimeout( function() {
|
684 |
-
itsecSettingsPage.isModuleActive( module );
|
685 |
-
}, 1000 );
|
686 |
-
|
687 |
-
return;
|
688 |
-
}
|
689 |
-
|
690 |
-
if ( 'activate' === method ) {
|
691 |
-
$buttons
|
692 |
-
.html( itsec_page.translations.deactivate )
|
693 |
-
.addClass( 'button-secondary' )
|
694 |
-
.removeClass( 'button-primary' )
|
695 |
-
.prop( 'disabled', false );
|
696 |
-
|
697 |
-
$card
|
698 |
-
.addClass( 'itsec-module-type-enabled' )
|
699 |
-
.removeClass( 'itsec-module-type-disabled' );
|
700 |
-
|
701 |
-
var newToggleSettingsLabel = itsec_page.translations.show_settings;
|
702 |
-
} else {
|
703 |
-
$buttons
|
704 |
-
.html( itsec_page.translations.activate )
|
705 |
-
.addClass( 'button-primary' )
|
706 |
-
.removeClass( 'button-secondary' )
|
707 |
-
.prop( 'disabled', false );
|
708 |
-
|
709 |
-
$card
|
710 |
-
.addClass( 'itsec-module-type-disabled' )
|
711 |
-
.removeClass( 'itsec-module-type-enabled' );
|
712 |
-
|
713 |
-
var newToggleSettingsLabel = itsec_page.translations.show_description;
|
714 |
-
}
|
715 |
-
|
716 |
-
$card.find( '.itsec-toggle-settings' ).html( newToggleSettingsLabel );
|
717 |
-
|
718 |
-
var enabledCount = jQuery( '.itsec-module-type-enabled' ).length,
|
719 |
-
disabledCount = jQuery( '.itsec-module-type-disabled' ).length;
|
720 |
-
|
721 |
-
jQuery( '#itsec-module-filter-enabled .count' ).html( '(' + enabledCount + ')' );
|
722 |
-
jQuery( '#itsec-module-filter-disabled .count' ).html( '(' + disabledCount + ')' );
|
723 |
-
|
724 |
-
|
725 |
-
itsecSettingsPage.showErrors( results.warnings, results.module, 'closed', 'warning' );
|
726 |
-
itsecSettingsPage.showMessages( results.messages, results.module, 'closed' );
|
727 |
-
itsecSettingsPage.showMessages( results.infos, results.module, 'closed', 'info' );
|
728 |
-
},
|
729 |
-
|
730 |
-
isModuleActive: function( module ) {
|
731 |
-
var data = {
|
732 |
-
'module': module,
|
733 |
-
'method': 'is_active'
|
734 |
-
};
|
735 |
-
|
736 |
-
itsecSettingsPage.sendAJAXRequest( module, 'is_active', {}, itsecSettingsPage.isModuleActiveCallback );
|
737 |
-
},
|
738 |
-
|
739 |
-
isModuleActiveCallback: function( results ) {
|
740 |
-
if ( true === results.response ) {
|
741 |
-
results.method = 'activate';
|
742 |
-
} else if ( false === results.response ) {
|
743 |
-
results.method = 'deactivate';
|
744 |
-
} else {
|
745 |
-
return;
|
746 |
-
}
|
747 |
-
|
748 |
-
itsecSettingsPage.toggleModuleActivationCallback( results );
|
749 |
-
},
|
750 |
-
|
751 |
-
reloadModule: function( module ) {
|
752 |
-
if ( module.preventDefault ) {
|
753 |
-
module.preventDefault();
|
754 |
-
|
755 |
-
module = jQuery(this).parents( '.itsec-module-card' ).attr( 'id' ).replace( 'itsec-module-card-', '' );
|
756 |
-
}
|
757 |
-
|
758 |
-
var method = 'get_refreshed_module_settings';
|
759 |
-
var data = {};
|
760 |
-
|
761 |
-
itsecSettingsPage.sendAJAXRequest( module, method, data, function( results ) {
|
762 |
-
if ( results.success && results.response ) {
|
763 |
-
var $card = jQuery( '#itsec-module-card-' + module );
|
764 |
-
var isHidden = $card.is( ':hidden' );
|
765 |
-
|
766 |
-
jQuery( '.itsec-module-settings-content-main', $card ).html( results.response );
|
767 |
-
|
768 |
-
if ( isHidden ) {
|
769 |
-
$card.hide();
|
770 |
-
} else {
|
771 |
-
jQuery( '.itsec-settings-toggle' ).trigger( 'change' );
|
772 |
-
}
|
773 |
-
} else if ( results.errors && results.errors.length > 0 ) {
|
774 |
-
itsecSettingsPage.showErrors( results.errors, results.module, 'open' );
|
775 |
-
} else if ( results.warnings && results.warnings.length > 0 ) {
|
776 |
-
itsecSettingsPage.showErrors( results.warnings, results.module, 'open', 'warning' );
|
777 |
-
}
|
778 |
-
|
779 |
-
itsecSettingsPage.events.trigger( 'moduleReloaded', module );
|
780 |
-
|
781 |
-
itsecSettingsPage.makeNoticesDismissible();
|
782 |
-
} );
|
783 |
-
},
|
784 |
-
|
785 |
-
reloadAllModules: function( _, initialResponse) {
|
786 |
-
itsecSettingsPage.sendAJAXRequest( '#', 'get_refreshed_module_form', null, function ( response ) {
|
787 |
-
|
788 |
-
if ( ! response.success || response.errors.length ) {
|
789 |
-
return;
|
790 |
-
}
|
791 |
-
|
792 |
-
var $open;
|
793 |
-
|
794 |
-
if ( jQuery( 'body' ).hasClass( 'itsec-modal-open' ) ) {
|
795 |
-
var $newModules = jQuery( response.response ), $cardsList = jQuery( '.itsec-module-cards' );
|
796 |
-
$open = jQuery( '.itsec-module-settings-container:visible' ).parents( '.itsec-module-card' );
|
797 |
-
|
798 |
-
jQuery( '.itsec-module-card', $newModules ).each( function () {
|
799 |
-
var $new = jQuery( this ), $current = jQuery( '#' + $new.attr( 'id' ), $cardsList );
|
800 |
-
|
801 |
-
if ( $new.attr( 'id' ).length && $new.attr( 'id' ) === $open.attr( 'id' ) ) {
|
802 |
-
jQuery( '.itsec-module-settings-content-main', $current ).html( jQuery( '.itsec-module-settings-content-main', $new ).html() );
|
803 |
-
} else {
|
804 |
-
jQuery( '.itsec-module-settings-container', $new ).hide();
|
805 |
-
$current.replaceWith( $new );
|
806 |
-
}
|
807 |
-
} );
|
808 |
-
|
809 |
-
} else {
|
810 |
-
jQuery( '.itsec-module-cards-container' ).html( response.response );
|
811 |
-
}
|
812 |
-
|
813 |
-
itsecSettingsPage.initFilters();
|
814 |
-
|
815 |
-
if ( ! $open ) {
|
816 |
-
jQuery( '.itsec-module-settings-container' ).hide();
|
817 |
-
}
|
818 |
-
|
819 |
-
if ( initialResponse ) {
|
820 |
-
itsecSettingsPage.showMessages( initialResponse.messages, initialResponse.module, $open ? 'open' : 'closed' );
|
821 |
-
itsecSettingsPage.showMessages( initialResponse.infos, initialResponse.module, $open ? 'open' : 'closed', 'info' );
|
822 |
-
itsecSettingsPage.showErrors( initialResponse.errors, initialResponse.module, $open ? 'open' : 'closed' );
|
823 |
-
itsecSettingsPage.showErrors( initialResponse.warnings, initialResponse.module, $open ? 'open' : 'closed', 'warning' );
|
824 |
-
}
|
825 |
-
|
826 |
-
itsecSettingsPage.makeNoticesDismissible();
|
827 |
-
itsecSettingsPage.events.trigger( 'modulesReloaded', initialResponse );
|
828 |
-
} );
|
829 |
-
},
|
830 |
-
|
831 |
-
reloadWidget: function( widget ) {
|
832 |
-
var method = 'get_refreshed_widget_settings';
|
833 |
-
var data = {};
|
834 |
-
|
835 |
-
itsecSettingsPage.sendAJAXRequest( module, method, data, function( results ) {
|
836 |
-
if ( results.success && results.response ) {
|
837 |
-
jQuery( '#itsec-sidebar-widget-' + module + ' .inside' ).html( results.response );
|
838 |
-
} else {
|
839 |
-
itsecSettingsPage.showErrors( results.errors, results.module, 'closed' );
|
840 |
-
itsecSettingsPage.showErrors( results.warnings, results.module, 'closed', 'warning' );
|
841 |
-
}
|
842 |
-
} );
|
843 |
-
},
|
844 |
-
|
845 |
-
sendAJAXRequest: function( module, method, data, callback ) {
|
846 |
-
var postData = {
|
847 |
-
'action': itsec_page.ajax_action,
|
848 |
-
'nonce': itsec_page.ajax_nonce,
|
849 |
-
'module': module,
|
850 |
-
'method': method,
|
851 |
-
'data': data,
|
852 |
-
};
|
853 |
-
|
854 |
-
jQuery.post( ajaxurl, postData )
|
855 |
-
.always(function( a, status, b ) {
|
856 |
-
itsecSettingsPage.processAjaxResponse( a, status, b, module, method, data, callback );
|
857 |
-
});
|
858 |
-
},
|
859 |
-
|
860 |
-
processAjaxResponse: function( a, status, b, module, method, data, callback ) {
|
861 |
-
var results = {
|
862 |
-
'module': module,
|
863 |
-
'method': method,
|
864 |
-
'data': data,
|
865 |
-
'status': status,
|
866 |
-
'jqxhr': null,
|
867 |
-
'success': false,
|
868 |
-
'response': null,
|
869 |
-
'errors': [],
|
870 |
-
'warnings': [],
|
871 |
-
'messages': [],
|
872 |
-
'infos': [],
|
873 |
-
'functionCalls': [],
|
874 |
-
'redirect': false,
|
875 |
-
'closeModal': true
|
876 |
-
};
|
877 |
-
|
878 |
-
|
879 |
-
if ( 'ITSEC_Response' === a.source && 'undefined' !== a.response ) {
|
880 |
-
// Successful response with a valid format.
|
881 |
-
results.jqxhr = b;
|
882 |
-
results.success = a.success;
|
883 |
-
results.response = a.response;
|
884 |
-
results.errors = a.errors;
|
885 |
-
results.warnings = a.warnings;
|
886 |
-
results.messages = a.messages;
|
887 |
-
results.infos = a.infos;
|
888 |
-
results.functionCalls = a.functionCalls;
|
889 |
-
results.redirect = a.redirect;
|
890 |
-
results.closeModal = a.closeModal;
|
891 |
-
} else if ( a.responseText ) {
|
892 |
-
// Failed response.
|
893 |
-
results.jqxhr = a;
|
894 |
-
var errorThrown = b;
|
895 |
-
|
896 |
-
if ( 'undefined' === typeof results.jqxhr.status ) {
|
897 |
-
results.jqxhr.status = -1;
|
898 |
-
}
|
899 |
-
|
900 |
-
if ( 'timeout' === status ) {
|
901 |
-
var error = itsec_page.translations.ajax_timeout;
|
902 |
-
} else if ( 'parsererror' === status ) {
|
903 |
-
var error = itsec_page.translations.ajax_parsererror;
|
904 |
-
} else if ( 403 == results.jqxhr.status ) {
|
905 |
-
var error = itsec_page.translations.ajax_forbidden;
|
906 |
-
} else if ( 404 == results.jqxhr.status ) {
|
907 |
-
var error = itsec_page.translations.ajax_not_found;
|
908 |
-
} else if ( 500 == results.jqxhr.status ) {
|
909 |
-
var error = itsec_page.translations.ajax_server_error;
|
910 |
-
} else {
|
911 |
-
var error = itsec_page.translations.ajax_unknown;
|
912 |
-
}
|
913 |
-
|
914 |
-
error = error.replace( '%1$s', status );
|
915 |
-
error = error.replace( '%2$s', errorThrown );
|
916 |
-
|
917 |
-
results.errors = [ error ];
|
918 |
-
} else {
|
919 |
-
// Successful response with an invalid format.
|
920 |
-
results.jqxhr = b;
|
921 |
-
|
922 |
-
results.response = a;
|
923 |
-
results.errors = [ itsec_page.translations.ajax_invalid ];
|
924 |
-
}
|
925 |
-
|
926 |
-
|
927 |
-
if ( results.redirect ) {
|
928 |
-
window.location = results.redirect;
|
929 |
-
}
|
930 |
-
|
931 |
-
|
932 |
-
if ( 'function' === typeof callback ) {
|
933 |
-
callback( results );
|
934 |
-
} else if ( 'function' === typeof console.log ) {
|
935 |
-
console.log( 'ERROR: Unable to handle settings AJAX request due to an invalid callback:', callback, {'data': postData, 'results': results} );
|
936 |
-
}
|
937 |
-
|
938 |
-
|
939 |
-
if ( results.functionCalls ) {
|
940 |
-
for ( var i = 0; i < results.functionCalls.length; i++ ) {
|
941 |
-
if ( 'object' === typeof results.functionCalls[i] && 'string' === typeof results.functionCalls[i][0] && 'function' === typeof itsecSettingsPage[results.functionCalls[i][0]] ) {
|
942 |
-
itsecSettingsPage[results.functionCalls[i][0]]( results.functionCalls[i][1], results );
|
943 |
-
} else if ( 'string' === typeof results.functionCalls[i] && 'function' === typeof window[results.functionCalls[i]] ) {
|
944 |
-
window[results.functionCalls[i]]();
|
945 |
-
} else if ( 'object' === typeof results.functionCalls[i] && 'string' === typeof results.functionCalls[i][0] && 'function' === typeof window[results.functionCalls[i][0]] ) {
|
946 |
-
window[results.functionCalls[i][0]]( results.functionCalls[i][1] );
|
947 |
-
} else if ( 'function' === typeof console.log ) {
|
948 |
-
console.log( 'ERROR: Unable to call missing function:', results.functionCalls[i] );
|
949 |
-
}
|
950 |
-
}
|
951 |
-
}
|
952 |
-
},
|
953 |
-
|
954 |
-
sendModuleAJAXRequest: function( module, data, callback ) {
|
955 |
-
itsecSettingsPage.sendAJAXRequest( module, 'handle_module_request', data, callback );
|
956 |
-
},
|
957 |
-
|
958 |
-
sendWidgetAJAXRequest: function( widget, data, callback ) {
|
959 |
-
itsecSettingsPage.sendAJAXRequest( widget, 'handle_widget_request', data, callback );
|
960 |
-
},
|
961 |
-
|
962 |
-
getUrlParameter: function( name ) {
|
963 |
-
var pageURL = decodeURIComponent( window.location.search.substring( 1 ) ),
|
964 |
-
URLParameters = pageURL.split( '&' ),
|
965 |
-
parameterName,
|
966 |
-
i;
|
967 |
-
|
968 |
-
// Loop through all parameters
|
969 |
-
for ( i = 0; i < URLParameters.length; i++ ) {
|
970 |
-
parameterName = URLParameters[i].split( '=' );
|
971 |
-
|
972 |
-
// If this is the parameter we're looking for
|
973 |
-
if ( parameterName[0] === name ) {
|
974 |
-
// Return the value or true if there is no value
|
975 |
-
return parameterName[1] === undefined ? true : parameterName[1];
|
976 |
-
}
|
977 |
-
}
|
978 |
-
// If the requested parameter doesn't exist, return false
|
979 |
-
return false;
|
980 |
-
},
|
981 |
-
|
982 |
-
// Make notices dismissible
|
983 |
-
makeNoticesDismissible: function() {
|
984 |
-
jQuery( '.notice.itsec-is-dismissible' ).each( function() {
|
985 |
-
var $el = jQuery( this ),
|
986 |
-
$button = jQuery( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
|
987 |
-
btnText = itsec_page.translations.dismiss || '';
|
988 |
-
|
989 |
-
// Don't rebind twice
|
990 |
-
if ( jQuery( '.notice-dismiss', $el ).length ) {
|
991 |
-
return;
|
992 |
-
}
|
993 |
-
|
994 |
-
// Ensure plain text
|
995 |
-
$button.find( '.screen-reader-text' ).text( btnText );
|
996 |
-
$button.on( 'click.wp-dismiss-notice', function( event ) {
|
997 |
-
event.preventDefault();
|
998 |
-
|
999 |
-
$el.trigger( 'itsec-dismiss-notice' );
|
1000 |
-
|
1001 |
-
$el.fadeTo( 100, 0, function() {
|
1002 |
-
$el.slideUp( 100, function() {
|
1003 |
-
$el.remove();
|
1004 |
-
});
|
1005 |
-
});
|
1006 |
-
});
|
1007 |
-
|
1008 |
-
$el.append( $button );
|
1009 |
-
});
|
1010 |
-
},
|
1011 |
-
|
1012 |
-
refreshPage: function() {
|
1013 |
-
location.reload( true );
|
1014 |
-
}
|
1015 |
-
};
|
1016 |
-
|
1017 |
-
jQuery(document).ready(function( $ ) {
|
1018 |
-
itsecSettingsPage.init();
|
1019 |
-
|
1020 |
-
if ( itsec_page.show_security_check ) {
|
1021 |
-
jQuery( '.itsec-settings-view-toggle a.itsec-grid' ).trigger( 'click' );
|
1022 |
-
jQuery( '#itsec-module-card-security-check .itsec-toggle-settings' ).trigger( 'click' );
|
1023 |
-
}
|
1024 |
-
|
1025 |
-
|
1026 |
-
jQuery( '.dialog' ).click( function ( event ) {
|
1027 |
-
event.preventDefault();
|
1028 |
-
|
1029 |
-
var target = jQuery( this ).attr( 'href' );
|
1030 |
-
var title = jQuery( this ).parents( '.inside' ).siblings( 'h3.hndle' ).children( 'span' ).text();
|
1031 |
-
|
1032 |
-
jQuery( '#' + target ).dialog( {
|
1033 |
-
dialogClass : 'wp-dialog itsec-dialog itsec-dialog-logs',
|
1034 |
-
modal : true,
|
1035 |
-
closeOnEscape: true,
|
1036 |
-
title : title,
|
1037 |
-
height : ( jQuery( window ).height() * 0.8 ),
|
1038 |
-
width : ( jQuery( window ).width() * 0.8 ),
|
1039 |
-
open : function ( event, ui ) {
|
1040 |
-
jQuery( '.ui-widget-overlay' ).bind( 'click', function () {
|
1041 |
-
jQuery( this ).siblings( '.ui-dialog' ).find( '.ui-dialog-content' ).dialog( 'close' );
|
1042 |
-
} );
|
1043 |
-
}
|
1044 |
-
} );
|
1045 |
-
|
1046 |
-
jQuery( '.ui-dialog :button' ).blur();
|
1047 |
-
} );
|
1048 |
-
|
1049 |
-
var regex = /[^\w]/ig;
|
1050 |
-
|
1051 |
-
var $search = $( '#search' ), $cardsContainer = $( '.itsec-module-cards' ),
|
1052 |
-
$cards = $( '.itsec-module-card', $cardsContainer ),
|
1053 |
-
$searchFilter = $( '#itsec-module-filter-search' ),
|
1054 |
-
$currentFilter = $( '.itsec-feature-tabs .current' ).parent();
|
1055 |
-
|
1056 |
-
itsecSettingsPage.events.on( 'modulesReloaded', function() {
|
1057 |
-
$cardsContainer = $( '.itsec-module-cards' );
|
1058 |
-
$cards = $( '.itsec-module-card', $cardsContainer );
|
1059 |
-
} );
|
1060 |
-
|
1061 |
-
$search.on( 'input', _.debounce( function () {
|
1062 |
-
var query = $search.val().trim().replace( regex, ' ' );
|
1063 |
-
|
1064 |
-
var $maybeCurrent = $( '.itsec-feature-tabs .current' ).parent();
|
1065 |
-
|
1066 |
-
if ( $maybeCurrent && $maybeCurrent.prop( 'id' ) !== 'itsec-module-filter-search' ) {
|
1067 |
-
$currentFilter = $maybeCurrent;
|
1068 |
-
}
|
1069 |
-
|
1070 |
-
$( '.itsec-highlighted-setting', $cards ).removeClass( 'itsec-highlighted-setting' );
|
1071 |
-
|
1072 |
-
if ( !query.length ) {
|
1073 |
-
$searchFilter.addClass( 'hide-if-js' );
|
1074 |
-
$( 'a', $searchFilter ).removeClass( 'current' );
|
1075 |
-
$( 'a', $currentFilter ).addClass( 'current' );
|
1076 |
-
|
1077 |
-
var type = $currentFilter.prop( 'id' ).substr( 20 );
|
1078 |
-
|
1079 |
-
if ( 'all' === type ) {
|
1080 |
-
$cards.show();
|
1081 |
-
} else {
|
1082 |
-
$( '.itsec-module-type-' + type ).show();
|
1083 |
-
$( '.itsec-module-card' ).not( '.itsec-module-type-' + type ).hide();
|
1084 |
-
}
|
1085 |
-
|
1086 |
-
return;
|
1087 |
-
}
|
1088 |
-
|
1089 |
-
var $titleMatches = $( ".itsec-module-card-content > h2:itsecContains('" + query + "')", $cards ),
|
1090 |
-
$titleMatchesCards = $titleMatches.parents( '.itsec-module-card' );
|
1091 |
-
|
1092 |
-
var $descriptionMatches = $( ".itsec-module-card-content > p:itsecContains('" + query + "')", $cards ),
|
1093 |
-
$descriptionMatchesCards = $descriptionMatches.parents( '.itsec-module-card' );
|
1094 |
-
|
1095 |
-
var $settingMatches = $( ".itsec-module-settings-container .form-table tr > th > label:itsecContains('" + query + "')", $cards ),
|
1096 |
-
$settingMatchesCards = $settingMatches.parents( '.itsec-module-card' );
|
1097 |
-
|
1098 |
-
|
1099 |
-
var $matches = $titleMatchesCards.add( $descriptionMatchesCards ).add( $settingMatchesCards );
|
1100 |
-
|
1101 |
-
$searchFilter.removeClass( 'hide-if-js' );
|
1102 |
-
$( 'a', $currentFilter ).removeClass( 'current' );
|
1103 |
-
$( 'a', $searchFilter ).addClass( 'current' );
|
1104 |
-
$( '.count', $searchFilter ).text( '(' + $matches.length + ')' );
|
1105 |
-
|
1106 |
-
$cards.hide();
|
1107 |
-
$matches.show();
|
1108 |
-
|
1109 |
-
$settingMatches.parents( 'tr' ).addClass( 'itsec-highlighted-setting' );
|
1110 |
-
|
1111 |
-
if ( $matches.length === 1 ) {
|
1112 |
-
$( '.itsec-toggle-settings', $matches.first() ).click();
|
1113 |
-
}
|
1114 |
-
}, 250 ) );
|
1115 |
-
|
1116 |
-
$.expr[":"].itsecContains = $.expr.createPseudo( function ( arg ) {
|
1117 |
-
return function ( elem ) {
|
1118 |
-
var candidate = $( elem ).text().toUpperCase().replace( regex, ' ' ), term = arg.toUpperCase();
|
1119 |
-
var index = candidate.indexOf( term );
|
1120 |
-
|
1121 |
-
if ( index === -1 ) {
|
1122 |
-
return false;
|
1123 |
-
}
|
1124 |
-
|
1125 |
-
if ( index === 0 ) {
|
1126 |
-
return true;
|
1127 |
-
}
|
1128 |
-
|
1129 |
-
var prior = candidate.charAt( index - 1 ), next = candidate.charAt( term.length + index );
|
1130 |
-
|
1131 |
-
// full word
|
1132 |
-
return prior === ' ' && ( next === ' ' || next === '' );
|
1133 |
-
};
|
1134 |
-
} );
|
1135 |
-
});
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
core/admin-pages/js/util.js
CHANGED
@@ -54,20 +54,21 @@ var itsecUtil = {
|
|
54 |
Â
|
55 |
Â
processAjaxResponse: function( a, status, b, module, method, data, callback ) {
|
56 |
Â
var results = {
|
57 |
-
'module':
|
58 |
-
'method':
|
59 |
-
'data':
|
60 |
-
'status':
|
61 |
-
'jqxhr':
|
62 |
-
'success':
|
63 |
-
'response':
|
64 |
-
'errors':
|
65 |
-
'warnings':
|
66 |
-
'messages':
|
67 |
-
'infos':
|
68 |
-
'functionCalls':
|
69 |
-
'
|
70 |
-
'
|
Â
|
|
71 |
Â
};
|
72 |
Â
|
73 |
Â
|
@@ -81,6 +82,7 @@ var itsecUtil = {
|
|
81 |
Â
results.messages = a.messages;
|
82 |
Â
results.infos = a.infos;
|
83 |
Â
results.functionCalls = a.functionCalls;
|
Â
|
|
84 |
Â
results.redirect = a.redirect;
|
85 |
Â
results.closeModal = a.closeModal;
|
86 |
Â
} else if ( a.responseText ) {
|
@@ -146,6 +148,30 @@ var itsecUtil = {
|
|
146 |
Â
}
|
147 |
Â
}
|
148 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
149 |
Â
},
|
150 |
Â
|
151 |
Â
getUrlParameter: function( name ) {
|
54 |
Â
|
55 |
Â
processAjaxResponse: function( a, status, b, module, method, data, callback ) {
|
56 |
Â
var results = {
|
57 |
+
'module': module,
|
58 |
+
'method': method,
|
59 |
+
'data': data,
|
60 |
+
'status': status,
|
61 |
+
'jqxhr': null,
|
62 |
+
'success': false,
|
63 |
+
'response': null,
|
64 |
+
'errors': [],
|
65 |
+
'warnings': [],
|
66 |
+
'messages': [],
|
67 |
+
'infos': [],
|
68 |
+
'functionCalls': [],
|
69 |
+
'storeDispatches': [],
|
70 |
+
'redirect': false,
|
71 |
+
'closeModal': true
|
72 |
Â
};
|
73 |
Â
|
74 |
Â
|
82 |
Â
results.messages = a.messages;
|
83 |
Â
results.infos = a.infos;
|
84 |
Â
results.functionCalls = a.functionCalls;
|
85 |
+
results.storeDispatches = a.storeDispatches;
|
86 |
Â
results.redirect = a.redirect;
|
87 |
Â
results.closeModal = a.closeModal;
|
88 |
Â
} else if ( a.responseText ) {
|
148 |
Â
}
|
149 |
Â
}
|
150 |
Â
}
|
151 |
+
|
152 |
+
itsecUtil.handleStoreDispatches( results.storeDispatches );
|
153 |
+
},
|
154 |
+
|
155 |
+
handleStoreDispatches: function( dispatches ) {
|
156 |
+
if ( !wp.data ) {
|
157 |
+
return;
|
158 |
+
}
|
159 |
+
|
160 |
+
for ( var i = 0; i < dispatches.length; i++ ) {
|
161 |
+
var dispatch = dispatches[ i ];
|
162 |
+
var key = dispatch.store,
|
163 |
+
action = dispatch.action,
|
164 |
+
args = dispatch.args;
|
165 |
+
|
166 |
+
var store = wp.data.dispatch( key );
|
167 |
+
|
168 |
+
if ( ! store ) {
|
169 |
+
console.warn( 'Unable to call store dispatch. The store does not exist.', dispatch );
|
170 |
+
continue;
|
171 |
+
}
|
172 |
+
|
173 |
+
store[ action ].apply( store, args );
|
174 |
+
}
|
175 |
Â
},
|
176 |
Â
|
177 |
Â
getUrlParameter: function( name ) {
|
core/admin-pages/logs-list-table.php
CHANGED
@@ -223,7 +223,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
223 |
Â
$filters = $this->get_raw_filters();
|
224 |
Â
|
225 |
Â
if ( 'process' === $filters['type'] ) {
|
226 |
-
$filters['type'] = 'process-start';
|
227 |
Â
}
|
228 |
Â
|
229 |
Â
if ( 'all' === $filters['type'] ) {
|
@@ -234,11 +234,13 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
234 |
Â
}
|
235 |
Â
if ( ! $options['show_process'] ) {
|
236 |
Â
$type_not[] = 'process-start';
|
Â
|
|
Â
|
|
237 |
Â
}
|
238 |
Â
|
239 |
Â
unset( $filters['type'] );
|
240 |
Â
} else if ( 'important' === $filters['type'] ) {
|
241 |
-
$type_not = array( 'action', 'notice', 'debug', 'process-start' );
|
242 |
Â
|
243 |
Â
unset( $filters['type'] );
|
244 |
Â
}
|
@@ -424,7 +426,7 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
424 |
Â
<label for="itsec-module-filter" class="screen-reader-text"><?php esc_html_e( 'Filter by Module', 'better-wp-security' ) ?></label>
|
425 |
Â
<select name="filters[]" id="itsec-module-filter">
|
426 |
Â
<option value=""><?php esc_html_e( 'All Modules', 'better-wp-security' ); ?></option>
|
427 |
-
<?php foreach (
|
428 |
Â
<option value="module|<?php echo esc_attr( $module ) ?>" <?php selected( $module, $current ); ?>>
|
429 |
Â
<?php echo $label; // Expected to be escaped by modules. ?>
|
430 |
Â
</option>
|
@@ -444,49 +446,4 @@ final class ITSEC_Logs_List_Table extends ITSEC_WP_List_Table {
|
|
444 |
Â
public function no_items() {
|
445 |
Â
esc_html_e( 'No events.', 'better-wp-security' );
|
446 |
Â
}
|
447 |
-
|
448 |
-
private function get_modules() {
|
449 |
-
$columns = implode(', ', array(
|
450 |
-
'id',
|
451 |
-
'parent_id',
|
452 |
-
'module',
|
453 |
-
'type',
|
454 |
-
'code',
|
455 |
-
'timestamp',
|
456 |
-
'init_timestamp',
|
457 |
-
'remote_ip',
|
458 |
-
'user_id',
|
459 |
-
'url',
|
460 |
-
'memory_current',
|
461 |
-
'memory_peak',
|
462 |
-
) );
|
463 |
-
|
464 |
-
global $wpdb;
|
465 |
-
|
466 |
-
$items = $wpdb->get_results( "SELECT {$columns} FROM {$wpdb->prefix}itsec_logs GROUP BY `module`", ARRAY_A );
|
467 |
-
|
468 |
-
if ( ! is_array( $items ) ) {
|
469 |
-
return array();
|
470 |
-
}
|
471 |
-
|
472 |
-
$modules = array();
|
473 |
-
|
474 |
-
foreach ( $items as $item ) {
|
475 |
-
if ( false === strpos( $item['code'], '::' ) ) {
|
476 |
-
$code = $item['code'];
|
477 |
-
$data = array();
|
478 |
-
} else {
|
479 |
-
list( $code, $data ) = explode( '::', $item['code'], 2 );
|
480 |
-
$data = explode( ',', $data );
|
481 |
-
}
|
482 |
-
|
483 |
-
$item['description'] = $item['code'];
|
484 |
-
$item['module_display'] = $item['module'];
|
485 |
-
$item = apply_filters( "itsec_logs_prepare_{$item['module']}_entry_for_list_display", $item, $code, $data );
|
486 |
-
|
487 |
-
$modules[ $item['module'] ] = $item['module_display'];
|
488 |
-
}
|
489 |
-
|
490 |
-
return $modules;
|
491 |
-
}
|
492 |
Â
}
|
223 |
Â
$filters = $this->get_raw_filters();
|
224 |
Â
|
225 |
Â
if ( 'process' === $filters['type'] ) {
|
226 |
+
$filters['type'] = [ 'process-start', 'process-update', 'process-stop' ];
|
227 |
Â
}
|
228 |
Â
|
229 |
Â
if ( 'all' === $filters['type'] ) {
|
234 |
Â
}
|
235 |
Â
if ( ! $options['show_process'] ) {
|
236 |
Â
$type_not[] = 'process-start';
|
237 |
+
$type_not[] = 'process-update';
|
238 |
+
$type_not[] = 'process-stop';
|
239 |
Â
}
|
240 |
Â
|
241 |
Â
unset( $filters['type'] );
|
242 |
Â
} else if ( 'important' === $filters['type'] ) {
|
243 |
+
$type_not = array( 'action', 'notice', 'debug', 'process-start', 'process-update', 'process-stop' );
|
244 |
Â
|
245 |
Â
unset( $filters['type'] );
|
246 |
Â
}
|
426 |
Â
<label for="itsec-module-filter" class="screen-reader-text"><?php esc_html_e( 'Filter by Module', 'better-wp-security' ) ?></label>
|
427 |
Â
<select name="filters[]" id="itsec-module-filter">
|
428 |
Â
<option value=""><?php esc_html_e( 'All Modules', 'better-wp-security' ); ?></option>
|
429 |
+
<?php foreach ( ITSEC_Log_Util::get_modules() as $module => $label ): ?>
|
430 |
Â
<option value="module|<?php echo esc_attr( $module ) ?>" <?php selected( $module, $current ); ?>>
|
431 |
Â
<?php echo $label; // Expected to be escaped by modules. ?>
|
432 |
Â
</option>
|
446 |
Â
public function no_items() {
|
447 |
Â
esc_html_e( 'No events.', 'better-wp-security' );
|
448 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
449 |
Â
}
|
core/admin-pages/module-settings.php
CHANGED
@@ -14,6 +14,7 @@
|
|
14 |
Â
* @property-read string $upsell_url
|
15 |
Â
* @property-read bool $information_only
|
16 |
Â
* @property-read string $status
|
Â
|
|
17 |
Â
*/
|
18 |
Â
class ITSEC_Module_Settings_Page {
|
19 |
Â
/**
|
@@ -113,6 +114,12 @@ class ITSEC_Module_Settings_Page {
|
|
113 |
Â
*/
|
114 |
Â
protected $status = '';
|
115 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
116 |
Â
|
117 |
Â
/**
|
118 |
Â
* Constructor.
|
@@ -139,7 +146,7 @@ class ITSEC_Module_Settings_Page {
|
|
139 |
Â
* @return mixed Property.
|
140 |
Â
*/
|
141 |
Â
public function __get( $name ) {
|
142 |
-
if ( in_array( $name, array( 'id', 'title', 'description', 'type', 'pro', 'can_save', 'redraw_on_save', 'upsell', 'upsell_url', 'information_only', 'status' ) ) ) {
|
143 |
Â
return $this->$name;
|
144 |
Â
}
|
145 |
Â
|
14 |
Â
* @property-read string $upsell_url
|
15 |
Â
* @property-read bool $information_only
|
16 |
Â
* @property-read string $status
|
17 |
+
* @property-read string $documentation
|
18 |
Â
*/
|
19 |
Â
class ITSEC_Module_Settings_Page {
|
20 |
Â
/**
|
114 |
Â
*/
|
115 |
Â
protected $status = '';
|
116 |
Â
|
117 |
+
/**
|
118 |
+
* Link to documentation for this module.
|
119 |
+
*
|
120 |
+
* @var string
|
121 |
+
*/
|
122 |
+
protected $documentation = '';
|
123 |
Â
|
124 |
Â
/**
|
125 |
Â
* Constructor.
|
146 |
Â
* @return mixed Property.
|
147 |
Â
*/
|
148 |
Â
public function __get( $name ) {
|
149 |
+
if ( in_array( $name, array( 'id', 'title', 'description', 'type', 'pro', 'can_save', 'redraw_on_save', 'upsell', 'upsell_url', 'information_only', 'status', 'documentation' ) ) ) {
|
150 |
Â
return $this->$name;
|
151 |
Â
}
|
152 |
Â
|
core/admin-pages/page-debug.php
CHANGED
@@ -80,8 +80,7 @@ final class ITSEC_Debug_Page {
|
|
80 |
Â
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-module-request-missing-data', __( 'The server did not receive a valid request. The required "data" argument for the module is missing. Please try again.', 'better-wp-security' ) ) );
|
81 |
Â
}
|
82 |
Â
} elseif ( 'reset_scheduler' === $method ) {
|
83 |
-
ITSEC_Core::get_scheduler()->
|
84 |
-
ITSEC_Core::get_scheduler()->register_events();
|
85 |
Â
ITSEC_Response::set_response( $this->get_events_table() );
|
86 |
Â
ITSEC_Response::set_success( true );
|
87 |
Â
ITSEC_Response::add_message( __( 'Scheduler reset.', 'better-wp-security' ) );
|
@@ -272,7 +271,7 @@ final class ITSEC_Debug_Page {
|
|
272 |
Â
$wp_config = array(
|
273 |
Â
'Version' => get_bloginfo( 'version' ),
|
274 |
Â
'Language' => defined( 'WPLANG' ) && WPLANG ? WPLANG : 'en_US',
|
275 |
-
'Permalink' => get_option( 'permalink_structure' )
|
276 |
Â
'Theme' => wp_get_theme()->Name . ' ' . wp_get_theme()->Version,
|
277 |
Â
'Show on Front' => get_option( 'show_on_front' )
|
278 |
Â
);
|
@@ -287,9 +286,9 @@ final class ITSEC_Debug_Page {
|
|
287 |
Â
|
288 |
Â
$wp_config['ABSPATH'] = ABSPATH;
|
289 |
Â
$wp_config['Table Prefix'] = 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'Too long' : 'Acceptable' );
|
290 |
-
$wp_config['WP_DEBUG'] = defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set';
|
291 |
-
$wp_config['WP_DEBUG_LOG'] = defined( 'WP_DEBUG_LOG' ) ? WP_DEBUG_LOG ? 'Enabled' : 'Disabled' : 'Not set';
|
292 |
-
$wp_config['SCRIPT_DEBUG'] = defined( 'SCRIPT_DEBUG' ) ? SCRIPT_DEBUG ? 'Enabled' : 'Disabled' : 'Not set';
|
293 |
Â
$wp_config['Object Cache'] = wp_using_ext_object_cache() ? 'Yes' : 'No';
|
294 |
Â
$wp_config['Memory Limit'] = WP_MEMORY_LIMIT;
|
295 |
Â
$info['WordPress Configuration'] = $wp_config;
|
@@ -312,6 +311,7 @@ final class ITSEC_Debug_Page {
|
|
312 |
Â
'ITSEC_DISABLE_AUTOMATIC_REMOTE_IP_DETECTION',
|
313 |
Â
'ITSEC_DISABLE_PASSWORD_STRENGTH',
|
314 |
Â
'ITSEC_DISABLE_INACTIVE_USER_CHECK',
|
Â
|
|
315 |
Â
);
|
316 |
Â
|
317 |
Â
ITSEC_Lib::load( 'feature-flags' );
|
@@ -328,8 +328,15 @@ final class ITSEC_Debug_Page {
|
|
328 |
Â
|
329 |
Â
foreach ( $defines as $define ) {
|
330 |
Â
if ( defined( $define ) ) {
|
331 |
-
$value
|
332 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
333 |
Â
}
|
334 |
Â
}
|
335 |
Â
|
80 |
Â
ITSEC_Response::add_error( new WP_Error( 'itsec-debug-page-module-request-missing-data', __( 'The server did not receive a valid request. The required "data" argument for the module is missing. Please try again.', 'better-wp-security' ) ) );
|
81 |
Â
}
|
82 |
Â
} elseif ( 'reset_scheduler' === $method ) {
|
83 |
+
ITSEC_Core::get_scheduler()->reset();
|
Â
|
|
84 |
Â
ITSEC_Response::set_response( $this->get_events_table() );
|
85 |
Â
ITSEC_Response::set_success( true );
|
86 |
Â
ITSEC_Response::add_message( __( 'Scheduler reset.', 'better-wp-security' ) );
|
271 |
Â
$wp_config = array(
|
272 |
Â
'Version' => get_bloginfo( 'version' ),
|
273 |
Â
'Language' => defined( 'WPLANG' ) && WPLANG ? WPLANG : 'en_US',
|
274 |
+
'Permalink' => get_option( 'permalink_structure' ) ?: 'Default',
|
275 |
Â
'Theme' => wp_get_theme()->Name . ' ' . wp_get_theme()->Version,
|
276 |
Â
'Show on Front' => get_option( 'show_on_front' )
|
277 |
Â
);
|
286 |
Â
|
287 |
Â
$wp_config['ABSPATH'] = ABSPATH;
|
288 |
Â
$wp_config['Table Prefix'] = 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'Too long' : 'Acceptable' );
|
289 |
+
$wp_config['WP_DEBUG'] = defined( 'WP_DEBUG' ) ? ( WP_DEBUG ? 'Enabled' : 'Disabled' ) : 'Not set';
|
290 |
+
$wp_config['WP_DEBUG_LOG'] = defined( 'WP_DEBUG_LOG' ) ? ( WP_DEBUG_LOG ? 'Enabled' : 'Disabled' ) : 'Not set';
|
291 |
+
$wp_config['SCRIPT_DEBUG'] = defined( 'SCRIPT_DEBUG' ) ? ( SCRIPT_DEBUG ? 'Enabled' : 'Disabled' ) : 'Not set';
|
292 |
Â
$wp_config['Object Cache'] = wp_using_ext_object_cache() ? 'Yes' : 'No';
|
293 |
Â
$wp_config['Memory Limit'] = WP_MEMORY_LIMIT;
|
294 |
Â
$info['WordPress Configuration'] = $wp_config;
|
311 |
Â
'ITSEC_DISABLE_AUTOMATIC_REMOTE_IP_DETECTION',
|
312 |
Â
'ITSEC_DISABLE_PASSWORD_STRENGTH',
|
313 |
Â
'ITSEC_DISABLE_INACTIVE_USER_CHECK',
|
314 |
+
'ITSEC_SHOW_FEATURE_FLAGS',
|
315 |
Â
);
|
316 |
Â
|
317 |
Â
ITSEC_Lib::load( 'feature-flags' );
|
328 |
Â
|
329 |
Â
foreach ( $defines as $define ) {
|
330 |
Â
if ( defined( $define ) ) {
|
331 |
+
$value = constant( $define );
|
332 |
+
|
333 |
+
if ( true === $value ) {
|
334 |
+
$value = 'Enabled';
|
335 |
+
} elseif ( false === $value ) {
|
336 |
+
$value = 'Disabled';
|
337 |
+
}
|
338 |
+
|
339 |
+
$info['iThemes Security'][ $define ] = $value;
|
340 |
Â
}
|
341 |
Â
}
|
342 |
Â
|
core/admin-pages/page-settings.php
CHANGED
@@ -169,9 +169,13 @@ final class ITSEC_Settings_Page {
|
|
169 |
Â
ITSEC_Modules::load_module_file( 'active.php', $module );
|
170 |
Â
}
|
171 |
Â
|
Â
|
|
Â
|
|
172 |
Â
ITSEC_Response::maybe_flag_new_notifications_available();
|
173 |
Â
} else if ( 'deactivate' === $method ) {
|
174 |
Â
ITSEC_Response::set_response( ITSEC_Modules::deactivate( $module ) );
|
Â
|
|
Â
|
|
175 |
Â
ITSEC_Response::maybe_flag_new_notifications_available();
|
176 |
Â
} else if ( 'is_active' === $method ) {
|
177 |
Â
ITSEC_Response::set_response( ITSEC_Modules::is_active( $module ) );
|
@@ -478,7 +482,7 @@ final class ITSEC_Settings_Page {
|
|
478 |
Â
<input type="search" placeholder="<?php esc_attr_e( 'Search Modules', 'better-wp-security' ); ?>" id="search" spellcheck="false" autocomplete="off" autofill="off" x-autocomplete="false">
|
479 |
Â
</div>
|
480 |
Â
<ul class="subsubsub itsec-feature-tabs hide-if-no-js">
|
481 |
-
<?php echo implode(
|
482 |
Â
<li class="itsec-module-filter hide-if-js" id="itsec-module-filter-search">| <a><?php esc_html_e( 'Search', 'better-wp-security' ); ?></a> <span class="count"></span></li>
|
483 |
Â
</ul>
|
484 |
Â
</div>
|
@@ -598,32 +602,48 @@ final class ITSEC_Settings_Page {
|
|
598 |
Â
<?php echo esc_html( $module->title ); ?>
|
599 |
Â
<?php do_action( 'itsec_module_settings_after_title', $id ); ?>
|
600 |
Â
</h3>
|
601 |
-
<div class="itsec-module-messages-container"></div>
|
602 |
Â
<div class="itsec-module-settings-content-main">
|
603 |
Â
<?php $this->get_module_settings( $id, $form, true ); ?>
|
604 |
Â
</div>
|
605 |
Â
</div>
|
606 |
Â
</div>
|
607 |
Â
<div class="itsec-list-content-footer hide-if-no-js">
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
612 |
Â
</div>
|
613 |
Â
<div class="itsec-modal-content-footer">
|
614 |
-
|
615 |
-
<?php if (
|
616 |
-
<button class="button button-
|
Â
|
|
Â
|
|
617 |
Â
<?php endif; ?>
|
618 |
-
|
619 |
-
<button class="button button-primary align-right itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
|
620 |
-
<?php endif; ?>
|
621 |
Â
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
627 |
Â
</div>
|
628 |
Â
</div>
|
629 |
Â
<?php endif; ?>
|
169 |
Â
ITSEC_Modules::load_module_file( 'active.php', $module );
|
170 |
Â
}
|
171 |
Â
|
172 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/user-groups', 'fetchGroupsSettings' );
|
173 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/core', 'fetchIndex', [ true ] );
|
174 |
Â
ITSEC_Response::maybe_flag_new_notifications_available();
|
175 |
Â
} else if ( 'deactivate' === $method ) {
|
176 |
Â
ITSEC_Response::set_response( ITSEC_Modules::deactivate( $module ) );
|
177 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/user-groups', 'fetchGroupsSettings' );
|
178 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/core', 'fetchIndex', [ true ] );
|
179 |
Â
ITSEC_Response::maybe_flag_new_notifications_available();
|
180 |
Â
} else if ( 'is_active' === $method ) {
|
181 |
Â
ITSEC_Response::set_response( ITSEC_Modules::is_active( $module ) );
|
482 |
Â
<input type="search" placeholder="<?php esc_attr_e( 'Search Modules', 'better-wp-security' ); ?>" id="search" spellcheck="false" autocomplete="off" autofill="off" x-autocomplete="false">
|
483 |
Â
</div>
|
484 |
Â
<ul class="subsubsub itsec-feature-tabs hide-if-no-js">
|
485 |
+
<?php echo implode( " |</li>\n", $feature_tabs ) . "</li>\n"; ?>
|
486 |
Â
<li class="itsec-module-filter hide-if-js" id="itsec-module-filter-search">| <a><?php esc_html_e( 'Search', 'better-wp-security' ); ?></a> <span class="count"></span></li>
|
487 |
Â
</ul>
|
488 |
Â
</div>
|
602 |
Â
<?php echo esc_html( $module->title ); ?>
|
603 |
Â
<?php do_action( 'itsec_module_settings_after_title', $id ); ?>
|
604 |
Â
</h3>
|
605 |
+
<div class="itsec-module-messages-container" id="itsec-module-messages-container-<?php echo esc_attr( $id ); ?>"></div>
|
606 |
Â
<div class="itsec-module-settings-content-main">
|
607 |
Â
<?php $this->get_module_settings( $id, $form, true ); ?>
|
608 |
Â
</div>
|
609 |
Â
</div>
|
610 |
Â
</div>
|
611 |
Â
<div class="itsec-list-content-footer hide-if-no-js">
|
612 |
+
<div class="itsec-module-footer-actions itsec-module-footer-actions--left">
|
613 |
+
<?php if ( $module->can_save ) : ?>
|
614 |
+
<button class="button button-primary itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
|
615 |
+
<?php endif; ?>
|
616 |
+
<button class="button button-secondary itsec-module-settings-cancel"><?php _e( 'Cancel', 'better-wp-security' ); ?></button>
|
617 |
+
</div>
|
618 |
+
|
619 |
+
<div class="itsec-module-footer-actions itsec-module-footer-actions--right">
|
620 |
+
<?php if ( $module->documentation ): ?>
|
621 |
+
<a href="<?php echo esc_url( $module->documentation ); ?>" class="itsec-module-documentation"><?php esc_html_e( 'Documentation', 'better-wp-security' ); ?></a>
|
622 |
+
<?php endif; ?>
|
623 |
+
</div>
|
624 |
Â
</div>
|
625 |
Â
<div class="itsec-modal-content-footer">
|
626 |
+
<div class="itsec-module-footer-actions itsec-module-footer-actions--left">
|
627 |
+
<?php if ( $module->can_save ) : ?>
|
628 |
+
<button class="button button-primary itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
|
629 |
+
<?php else : ?>
|
630 |
+
<button class="button button-primary itsec-close-modal"><?php echo $this->translations['close_settings']; ?></button>
|
631 |
Â
<?php endif; ?>
|
632 |
+
</div>
|
Â
|
|
Â
|
|
633 |
Â
|
634 |
+
<div class="itsec-module-footer-actions itsec-module-footer-actions--right">
|
635 |
+
<?php if ( $module->documentation ): ?>
|
636 |
+
<a href="<?php echo esc_url( $module->documentation ); ?>" class="itsec-module-documentation"><?php esc_html_e( 'Documentation', 'better-wp-security' ); ?></a>
|
637 |
+
<?php endif; ?>
|
638 |
+
|
639 |
+
<?php if ( $module->enabled || $module->always_active || $module->information_only ) : ?>
|
640 |
+
<?php if ( ! $module->always_active && ! $module->information_only ) : ?>
|
641 |
+
<button class="button button-secondary itsec-toggle-activation"><?php echo $this->translations['deactivate']; ?></button>
|
642 |
+
<?php endif; ?>
|
643 |
+
<?php else : ?>
|
644 |
+
<button class="button button-primary itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
|
645 |
+
<?php endif; ?>
|
646 |
+
</div>
|
647 |
Â
</div>
|
648 |
Â
</div>
|
649 |
Â
<?php endif; ?>
|
core/composer.json
ADDED
@@ -0,0 +1,31 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
{
|
2 |
+
"name": "ithemes/ithemes-security-core",
|
3 |
+
"description": "iThemes Security Core",
|
4 |
+
"type": "project",
|
5 |
+
"require": {
|
6 |
+
"pimple/pimple": "^3.2"
|
7 |
+
},
|
8 |
+
"license": "GPL-2.0-or-later",
|
9 |
+
"authors": [
|
10 |
+
{
|
11 |
+
"name": "Timothy Jacobs",
|
12 |
+
"email": "timothy@ithemes.com"
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"name": "Chris Jean",
|
16 |
+
"email": "chris@ithemes.com"
|
17 |
+
}
|
18 |
+
],
|
19 |
+
"minimum-stability": "stable",
|
20 |
+
"autoload": {
|
21 |
+
"classmap": [
|
22 |
+
"Exception/",
|
23 |
+
"Contracts/",
|
24 |
+
"modules/",
|
25 |
+
"lib"
|
26 |
+
],
|
27 |
+
"exclude-from-classmap": [
|
28 |
+
"lib/itsec-zxcvbn-php"
|
29 |
+
]
|
30 |
+
}
|
31 |
+
}
|
core/core.php
CHANGED
@@ -1,14 +1,16 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
/**
|
4 |
Â
* iThemes Security Core.
|
5 |
Â
*
|
6 |
Â
* Core class for iThemes Security sets up globals and other items and dispatches modules.
|
7 |
Â
*
|
8 |
-
* @package iThemes_Security
|
9 |
-
*
|
10 |
Â
* @since 4.0
|
11 |
Â
*
|
Â
|
|
Â
|
|
12 |
Â
* @global array $itsec_globals Global variables for use throughout iThemes Security.
|
13 |
Â
* @global object $itsec_lockout Class for handling lockouts.
|
14 |
Â
*
|
@@ -24,7 +26,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
24 |
Â
*
|
25 |
Â
* @access private
|
26 |
Â
*/
|
27 |
-
private $plugin_build =
|
28 |
Â
|
29 |
Â
/**
|
30 |
Â
* Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
|
@@ -37,6 +39,9 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
37 |
Â
private $notices_loaded = false;
|
38 |
Â
private $doing_data_upgrade = false;
|
39 |
Â
|
Â
|
|
Â
|
|
Â
|
|
40 |
Â
private
|
41 |
Â
$itsec_files,
|
42 |
Â
$itsec_notify,
|
@@ -51,7 +56,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
51 |
Â
$is_iwp_call,
|
52 |
Â
$wp_upload_dir,
|
53 |
Â
$login_interstitial,
|
54 |
-
$version
|
Â
|
|
55 |
Â
|
56 |
Â
|
57 |
Â
/**
|
@@ -59,7 +65,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
59 |
Â
*
|
60 |
Â
* @access private
|
61 |
Â
*/
|
62 |
-
private function __construct() {}
|
63 |
Â
|
64 |
Â
/**
|
65 |
Â
* Function to instantiate our class and make it a singleton
|
@@ -78,7 +84,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
78 |
Â
* Creates all plugin globals, registers activation and related hooks,
|
79 |
Â
* loads the text domain and loads all plugin modules
|
80 |
Â
*
|
81 |
-
* @since
|
82 |
Â
*
|
83 |
Â
* @access private
|
84 |
Â
*
|
@@ -89,10 +95,10 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
89 |
Â
public function init( $plugin_file, $plugin_name ) {
|
90 |
Â
global $itsec_globals, $itsec_lockout;
|
91 |
Â
|
92 |
-
$this->plugin_file
|
93 |
-
$this->plugin_dir
|
94 |
-
$this->plugin_name
|
95 |
-
$this->current_time
|
96 |
Â
$this->current_time_gmt = current_time( 'timestamp', true );
|
97 |
Â
|
98 |
Â
$itsec_globals = array(
|
@@ -110,6 +116,14 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
110 |
Â
require( $this->plugin_dir . 'core/modules.php' );
|
111 |
Â
require( $this->plugin_dir . 'core/lib.php' );
|
112 |
Â
require( $this->plugin_dir . 'core/lib/log.php' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
113 |
Â
|
114 |
Â
add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
|
115 |
Â
ITSEC_Modules::init_modules();
|
@@ -127,35 +141,125 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
127 |
Â
require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
|
128 |
Â
require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
|
129 |
Â
|
130 |
-
$this->itsec_files
|
131 |
Â
$this->itsec_notify = new ITSEC_Notify();
|
132 |
-
$itsec_lockout
|
133 |
-
$itsec_lockout->run();
|
134 |
Â
|
135 |
Â
// Handle upgrade if needed.
|
136 |
-
add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), -100, 0 );
|
Â
|
|
137 |
Â
|
138 |
-
|
139 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
140 |
Â
|
141 |
-
|
142 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
143 |
Â
}
|
144 |
Â
|
Â
|
|
Â
|
|
Â
|
|
145 |
Â
|
146 |
-
|
147 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
148 |
Â
|
149 |
-
|
Â
|
|
150 |
Â
|
151 |
-
|
152 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
153 |
Â
}
|
154 |
Â
|
155 |
Â
/**
|
156 |
Â
* Perform initialization that requires the plugins_loaded hook to be fired.
|
157 |
Â
*/
|
158 |
Â
public function continue_init() {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
159 |
Â
$this->setup_scheduler();
|
160 |
Â
ITSEC_Modules::run_active_modules();
|
161 |
Â
|
@@ -171,6 +275,23 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
171 |
Â
ITSEC_Lib_Remote_Messages::init();
|
172 |
Â
}
|
173 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
174 |
Â
private function setup_scheduler() {
|
175 |
Â
|
176 |
Â
if ( $this->scheduler ) {
|
@@ -194,6 +315,24 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
194 |
Â
self::get_scheduler()->run();
|
195 |
Â
}
|
196 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
197 |
Â
/**
|
198 |
Â
* Retrieve the global instance of the files utility.
|
199 |
Â
*
|
@@ -201,6 +340,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
201 |
Â
*/
|
202 |
Â
public static function get_itsec_files() {
|
203 |
Â
$self = self::get_instance();
|
Â
|
|
204 |
Â
return $self->itsec_files;
|
205 |
Â
}
|
206 |
Â
|
@@ -211,6 +351,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
211 |
Â
*/
|
212 |
Â
public static function get_itsec_notify() {
|
213 |
Â
$self = self::get_instance();
|
Â
|
|
214 |
Â
return $self->itsec_notify;
|
215 |
Â
}
|
216 |
Â
|
@@ -275,9 +416,19 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
275 |
Â
*/
|
276 |
Â
public static function get_sync_api() {
|
277 |
Â
$self = self::get_instance();
|
Â
|
|
278 |
Â
return $self->sync_api;
|
279 |
Â
}
|
280 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
281 |
Â
/**
|
282 |
Â
* Register ITSEC verbs with sync.
|
283 |
Â
*
|
@@ -298,6 +449,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
298 |
Â
public function register_events( $scheduler ) {
|
299 |
Â
$scheduler->schedule( ITSEC_Scheduler::S_DAILY, 'clear-locks' );
|
300 |
Â
$scheduler->schedule( ITSEC_Scheduler::S_DAILY, 'health-check' );
|
Â
|
|
301 |
Â
}
|
302 |
Â
|
303 |
Â
/**
|
@@ -306,9 +458,11 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
306 |
Â
public function register_modules() {
|
307 |
Â
$path = dirname( __FILE__ );
|
308 |
Â
|
Â
|
|
309 |
Â
ITSEC_Modules::register_module( 'security-check', "$path/modules/security-check", 'always-active' );
|
310 |
Â
ITSEC_Modules::register_module( 'global', "$path/modules/global", 'always-active' );
|
311 |
Â
ITSEC_Modules::register_module( 'notification-center', "$path/modules/notification-center", 'always-active' );
|
Â
|
|
312 |
Â
ITSEC_Modules::register_module( 'privacy', "$path/modules/privacy", 'always-active' );
|
313 |
Â
ITSEC_Modules::register_module( '404-detection', "$path/modules/404-detection" );
|
314 |
Â
ITSEC_Modules::register_module( 'admin-user', "$path/modules/admin-user", 'always-active' );
|
@@ -331,7 +485,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
331 |
Â
|
332 |
Â
ITSEC_Modules::register_module( 'network-brute-force', "$path/modules/ipcheck", 'default-active' );
|
333 |
Â
|
334 |
-
if ( ! defined( 'ITSEC_DISABLE_PASSWORD_REQUIREMENTS') || ! ITSEC_DISABLE_PASSWORD_REQUIREMENTS ) {
|
335 |
Â
ITSEC_Modules::register_module( 'password-requirements', "$path/modules/password-requirements/", 'always-active' );
|
336 |
Â
}
|
337 |
Â
|
@@ -342,8 +496,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
342 |
Â
ITSEC_Modules::register_module( 'wordpress-tweaks', "$path/modules/wordpress-tweaks", 'default-active' );
|
343 |
Â
ITSEC_Modules::register_module( 'file-writing', "$path/modules/file-writing", 'always-active' );
|
344 |
Â
ITSEC_Modules::register_module( 'malware', "$path/modules/malware", 'always-active' );
|
345 |
-
ITSEC_Modules::register_module( 'feature-flags', "$path/modules/feature-flags", 'always-active' );
|
346 |
Â
ITSEC_Modules::register_module( 'security-check-pro', "$path/modules/security-check-pro", self::is_pro() ? 'always-active' : 'default-inactive' );
|
Â
|
|
347 |
Â
|
348 |
Â
if ( ! ITSEC_Core::is_pro() ) {
|
349 |
Â
ITSEC_Modules::register_module( 'pro-module-upsells', "$path/modules/pro", 'always-active' );
|
@@ -405,22 +559,26 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
405 |
Â
* Dispatch a request to upgrade the data schema to another version.
|
406 |
Â
*
|
407 |
Â
* @param int|bool $build The version of the data storage format. Pass false to default to the current version.
|
Â
|
|
Â
|
|
408 |
Â
*/
|
409 |
Â
public function handle_upgrade( $build = false ) {
|
410 |
Â
|
411 |
-
if ( func_num_args() === 0 &&
|
412 |
-
return;
|
413 |
Â
}
|
414 |
Â
|
415 |
Â
$this->doing_data_upgrade = true;
|
416 |
Â
|
417 |
Â
require_once( self::get_core_dir() . '/setup.php' );
|
418 |
-
ITSEC_Setup::handle_upgrade( $build );
|
Â
|
|
Â
|
|
419 |
Â
}
|
420 |
Â
|
421 |
Â
public static function handle_activation() {
|
422 |
Â
require_once( self::get_core_dir() . '/setup.php' );
|
423 |
-
ITSEC_Setup::handle_activation();
|
424 |
Â
}
|
425 |
Â
|
426 |
Â
public static function handle_deactivation() {
|
@@ -436,8 +594,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
436 |
Â
/**
|
437 |
Â
* Register a notice to be displayed in the WordPress admin.
|
438 |
Â
*
|
439 |
-
* @param callable $callback
|
440 |
-
* @param bool
|
441 |
Â
*/
|
442 |
Â
public static function add_notice( $callback, $all_pages = false ) {
|
443 |
Â
_deprecated_function( __METHOD__, '6.0.0', 'ITSEC_Lib_Admin_Notices::register' );
|
@@ -464,42 +622,57 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
464 |
Â
}
|
465 |
Â
}
|
466 |
Â
|
467 |
-
/**
|
468 |
-
* Get the required capability to manage ITSEC.
|
469 |
-
*
|
470 |
-
* @return string
|
471 |
-
*/
|
472 |
-
public static function get_required_cap() {
|
473 |
-
return apply_filters( 'itsec_cap_required', is_multisite() ? 'manage_network_options' : 'manage_options' );
|
474 |
-
}
|
475 |
-
|
476 |
-
/**
|
477 |
-
* Does the current user have permission to manage ITSEC.
|
478 |
-
*
|
479 |
-
* @return bool
|
480 |
-
*/
|
481 |
-
public static function current_user_can_manage() {
|
482 |
-
return current_user_can( self::get_required_cap() );
|
483 |
-
}
|
484 |
-
|
485 |
Â
public static function get_plugin_file() {
|
486 |
Â
$self = self::get_instance();
|
Â
|
|
487 |
Â
return $self->plugin_file;
|
488 |
Â
}
|
489 |
Â
|
490 |
Â
public static function set_plugin_file( $plugin_file ) {
|
491 |
-
$self
|
492 |
Â
$self->plugin_file = $plugin_file;
|
493 |
-
$self->plugin_dir
|
494 |
Â
}
|
495 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
496 |
Â
public static function get_plugin_build() {
|
497 |
Â
$self = self::get_instance();
|
Â
|
|
498 |
Â
return $self->plugin_build;
|
499 |
Â
}
|
500 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
501 |
Â
public static function get_plugin_dir() {
|
502 |
Â
$self = self::get_instance();
|
Â
|
|
503 |
Â
return $self->plugin_dir;
|
504 |
Â
}
|
505 |
Â
|
@@ -509,6 +682,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
509 |
Â
|
510 |
Â
public static function get_plugin_name() {
|
511 |
Â
$self = self::get_instance();
|
Â
|
|
512 |
Â
return $self->plugin_name;
|
513 |
Â
}
|
514 |
Â
|
@@ -562,6 +736,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
562 |
Â
*/
|
563 |
Â
public static function get_current_time() {
|
564 |
Â
$self = self::get_instance();
|
Â
|
|
565 |
Â
return $self->current_time;
|
566 |
Â
}
|
567 |
Â
|
@@ -574,6 +749,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
574 |
Â
*/
|
575 |
Â
public static function get_current_time_gmt() {
|
576 |
Â
$self = self::get_instance();
|
Â
|
|
577 |
Â
return $self->current_time_gmt;
|
578 |
Â
}
|
579 |
Â
|
@@ -584,6 +760,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
584 |
Â
*/
|
585 |
Â
public static function get_time_offset() {
|
586 |
Â
$self = self::get_instance();
|
Â
|
|
587 |
Â
return $self->current_time - $self->current_time_gmt;
|
588 |
Â
}
|
589 |
Â
|
@@ -599,7 +776,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
599 |
Â
$filters = array();
|
600 |
Â
|
601 |
Â
if ( $module ) {
|
602 |
-
$filters[] = rawurlencode("module|{$module}");
|
603 |
Â
}
|
604 |
Â
|
605 |
Â
if ( $type ) {
|
@@ -634,8 +811,8 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
634 |
Â
*
|
635 |
Â
* @param bool $interactive
|
636 |
Â
*/
|
637 |
-
public static function set_interactive( $interactive ) {
|
638 |
-
$self
|
639 |
Â
$self->interactive = (bool) $interactive;
|
640 |
Â
}
|
641 |
Â
|
@@ -646,6 +823,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
646 |
Â
*/
|
647 |
Â
public static function is_interactive() {
|
648 |
Â
$self = self::get_instance();
|
Â
|
|
649 |
Â
return $self->interactive;
|
650 |
Â
}
|
651 |
Â
|
@@ -688,9 +866,9 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
688 |
Â
* This value is cached for both the lifetime of the request and possibly indefinitely when WordPress is
|
689 |
Â
* using an object cache.
|
690 |
Â
*
|
Â
|
|
691 |
Â
* @see wp_upload_dir
|
692 |
Â
*
|
693 |
-
* @return array
|
694 |
Â
*/
|
695 |
Â
public static function get_wp_upload_dir() {
|
696 |
Â
$self = self::get_instance();
|
@@ -739,7 +917,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
739 |
Â
/**
|
740 |
Â
* Retrieve and/or create a directory for ITSEC to store data.
|
741 |
Â
*
|
742 |
-
* @param string $dir
|
743 |
Â
* @param bool $public Whether to get the public version of the directory.
|
744 |
Â
*
|
745 |
Â
* @return string
|
@@ -824,11 +1002,13 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
824 |
Â
|
825 |
Â
if ( ! function_exists( 'rest_get_url_prefix' ) ) {
|
826 |
Â
$GLOBALS['__itsec_core_is_rest_api_request'] = false;
|
Â
|
|
827 |
Â
return false;
|
828 |
Â
}
|
829 |
Â
|
830 |
Â
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
831 |
Â
$GLOBALS['__itsec_core_is_rest_api_request'] = true;
|
Â
|
|
832 |
Â
return true;
|
833 |
Â
}
|
834 |
Â
|
@@ -924,5 +1104,13 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
|
|
924 |
Â
|
925 |
Â
return $self->version;
|
926 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
927 |
Â
}
|
928 |
Â
}
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
/**
|
6 |
Â
* iThemes Security Core.
|
7 |
Â
*
|
8 |
Â
* Core class for iThemes Security sets up globals and other items and dispatches modules.
|
9 |
Â
*
|
Â
|
|
Â
|
|
10 |
Â
* @since 4.0
|
11 |
Â
*
|
12 |
+
* @package iThemes_Security
|
13 |
+
*
|
14 |
Â
* @global array $itsec_globals Global variables for use throughout iThemes Security.
|
15 |
Â
* @global object $itsec_lockout Class for handling lockouts.
|
16 |
Â
*
|
26 |
Â
*
|
27 |
Â
* @access private
|
28 |
Â
*/
|
29 |
+
private $plugin_build = 4118;
|
30 |
Â
|
31 |
Â
/**
|
32 |
Â
* Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
|
39 |
Â
private $notices_loaded = false;
|
40 |
Â
private $doing_data_upgrade = false;
|
41 |
Â
|
42 |
+
/** @var true|WP_Error|null */
|
43 |
+
private $setup_error;
|
44 |
+
|
45 |
Â
private
|
46 |
Â
$itsec_files,
|
47 |
Â
$itsec_notify,
|
56 |
Â
$is_iwp_call,
|
57 |
Â
$wp_upload_dir,
|
58 |
Â
$login_interstitial,
|
59 |
+
$version,
|
60 |
+
$importing = false;
|
61 |
Â
|
62 |
Â
|
63 |
Â
/**
|
65 |
Â
*
|
66 |
Â
* @access private
|
67 |
Â
*/
|
68 |
+
private function __construct() { }
|
69 |
Â
|
70 |
Â
/**
|
71 |
Â
* Function to instantiate our class and make it a singleton
|
84 |
Â
* Creates all plugin globals, registers activation and related hooks,
|
85 |
Â
* loads the text domain and loads all plugin modules
|
86 |
Â
*
|
87 |
+
* @since 4.0
|
88 |
Â
*
|
89 |
Â
* @access private
|
90 |
Â
*
|
95 |
Â
public function init( $plugin_file, $plugin_name ) {
|
96 |
Â
global $itsec_globals, $itsec_lockout;
|
97 |
Â
|
98 |
+
$this->plugin_file = $plugin_file;
|
99 |
+
$this->plugin_dir = dirname( $plugin_file ) . '/';
|
100 |
+
$this->plugin_name = $plugin_name;
|
101 |
+
$this->current_time = current_time( 'timestamp' );
|
102 |
Â
$this->current_time_gmt = current_time( 'timestamp', true );
|
103 |
Â
|
104 |
Â
$itsec_globals = array(
|
116 |
Â
require( $this->plugin_dir . 'core/modules.php' );
|
117 |
Â
require( $this->plugin_dir . 'core/lib.php' );
|
118 |
Â
require( $this->plugin_dir . 'core/lib/log.php' );
|
119 |
+
require( $this->plugin_dir . 'core/lib/class-itsec-mutex.php' );
|
120 |
+
require( $this->plugin_dir . 'core/rest.php' );
|
121 |
+
|
122 |
+
$this->setup_tables();
|
123 |
+
|
124 |
+
add_filter( 'user_has_cap', [ $this, 'user_has_cap' ], 10, 4 );
|
125 |
+
|
126 |
+
( new ITSEC_REST() )->run();
|
127 |
Â
|
128 |
Â
add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
|
129 |
Â
ITSEC_Modules::init_modules();
|
141 |
Â
require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
|
142 |
Â
require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
|
143 |
Â
|
144 |
+
$this->itsec_files = ITSEC_Files::get_instance();
|
145 |
Â
$this->itsec_notify = new ITSEC_Notify();
|
146 |
+
$itsec_lockout = new ITSEC_Lockout();
|
Â
|
|
147 |
Â
|
148 |
Â
// Handle upgrade if needed.
|
149 |
+
add_action( 'plugins_loaded', array( $this, 'handle_upgrade' ), - 100, 0 );
|
150 |
+
add_action( 'plugins_loaded', array( $this, 'continue_init' ), - 90 );
|
151 |
Â
|
152 |
+
add_action( 'itsec_scheduler_register_events', array( $this, 'register_events' ) );
|
153 |
+
add_action( 'itsec_scheduled_clear-locks', array( 'ITSEC_Lib', 'delete_expired_locks' ) );
|
154 |
+
add_action( 'itsec_scheduled_clear-tokens', array( ITSEC_Lib_Opaque_Tokens::class, 'delete_expired_tokens' ) );
|
155 |
+
add_action( 'itsec_before_import', function () {
|
156 |
+
$this->importing = true;
|
157 |
+
} );
|
158 |
+
add_action( 'itsec_after_import', function () {
|
159 |
+
$this->importing = false;
|
160 |
+
} );
|
161 |
+
}
|
162 |
Â
|
163 |
+
/**
|
164 |
+
* Handle dynamically granting the 'itsec_manage' cap to users in the necessary group.
|
165 |
+
*
|
166 |
+
* @param array $has_caps
|
167 |
+
* @param array $requested_caps
|
168 |
+
* @param array $args
|
169 |
+
* @param WP_User $user
|
170 |
+
*
|
171 |
+
* @return array
|
172 |
+
*/
|
173 |
+
public function user_has_cap( $has_caps, $requested_caps, $args, $user ) {
|
174 |
+
if ( ! in_array( 'itsec_manage', $requested_caps, true ) ) {
|
175 |
+
return $has_caps;
|
176 |
Â
}
|
177 |
Â
|
178 |
+
if ( isset( $has_caps['itsec_manage'] ) ) {
|
179 |
+
return $has_caps;
|
180 |
+
}
|
181 |
Â
|
182 |
+
if (
|
183 |
+
is_wp_error( $this->setup_error ) ||
|
184 |
+
self::is_temp_disable_modules_set() ||
|
185 |
+
! ITSEC_Modules::get_container()->has( User_Groups\Matcher::class ) ||
|
186 |
+
! $this->has_valid_manage_groups()
|
187 |
+
) {
|
188 |
+
$has_caps['itsec_manage'] = $user->has_cap( is_multisite() ? 'manage_network_options' : 'manage_options' );
|
189 |
Â
|
190 |
+
return $has_caps;
|
191 |
+
}
|
192 |
Â
|
193 |
+
$group = ITSEC_Modules::get_setting( 'global', 'manage_group' );
|
194 |
+
$matcher = ITSEC_Modules::get_container()->get( User_Groups\Matcher::class );
|
195 |
+
|
196 |
+
if ( ! $matcher->matches( User_Groups\Match_Target::for_user( $user ), $group ) ) {
|
197 |
+
return $has_caps;
|
198 |
+
}
|
199 |
+
|
200 |
+
$has_caps['itsec_manage'] = true;
|
201 |
+
|
202 |
+
return $has_caps;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Check if there are valid "Manage groups" selected.
|
207 |
+
*
|
208 |
+
* @return bool
|
209 |
+
*/
|
210 |
+
private function has_valid_manage_groups() {
|
211 |
+
$source = ITSEC_Modules::get_container()->get( User_Groups\Matchables_Source::class );
|
212 |
+
$groups = ITSEC_Modules::get_setting( 'global', 'manage_group' );
|
213 |
+
|
214 |
+
foreach ( $groups as $group ) {
|
215 |
+
if ( $source->has( $group ) ) {
|
216 |
+
return true;
|
217 |
+
}
|
218 |
+
}
|
219 |
+
|
220 |
+
return false;
|
221 |
Â
}
|
222 |
Â
|
223 |
Â
/**
|
224 |
Â
* Perform initialization that requires the plugins_loaded hook to be fired.
|
225 |
Â
*/
|
226 |
Â
public function continue_init() {
|
227 |
+
global $itsec_lockout;
|
228 |
+
|
229 |
+
if ( is_wp_error( $this->setup_error ) ) {
|
230 |
+
if ( ! current_user_can( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) {
|
231 |
+
return;
|
232 |
+
}
|
233 |
+
|
234 |
+
add_action( 'admin_notices', function () {
|
235 |
+
echo '<div class="notice notice-error">';
|
236 |
+
echo '<p>';
|
237 |
+
esc_html_e( 'Cannot run iThemes Security. Error encountered during setup. Please try deactivating and reactivating iThemes Security. Contact support if the error persists.', 'better-wp-security' );
|
238 |
+
echo '</p>';
|
239 |
+
|
240 |
+
echo '<ol>';
|
241 |
+
foreach ( ITSEC_Lib::get_error_strings( $this->setup_error ) as $string ) {
|
242 |
+
echo '<li>' . $string . '</li>';
|
243 |
+
}
|
244 |
+
echo '</ol>';
|
245 |
+
echo '</div>';
|
246 |
+
} );
|
247 |
+
|
248 |
+
return;
|
249 |
+
}
|
250 |
+
|
251 |
+
$itsec_lockout->run();
|
252 |
+
|
253 |
+
if ( is_admin() ) {
|
254 |
+
require( $this->plugin_dir . 'core/admin-pages/init.php' );
|
255 |
+
|
256 |
+
add_filter( 'plugin_action_links', array( $this, 'add_action_link' ), 10, 2 );
|
257 |
+
add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 4 );
|
258 |
+
}
|
259 |
+
|
260 |
+
add_action( 'wp_login_failed', array( 'ITSEC_Lib', 'handle_wp_login_failed' ) );
|
261 |
+
add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
|
262 |
+
|
263 |
Â
$this->setup_scheduler();
|
264 |
Â
ITSEC_Modules::run_active_modules();
|
265 |
Â
|
275 |
Â
ITSEC_Lib_Remote_Messages::init();
|
276 |
Â
}
|
277 |
Â
|
278 |
+
/**
|
279 |
+
* Register our tables with {@see wpdb}.
|
280 |
+
*/
|
281 |
+
private function setup_tables() {
|
282 |
+
global $wpdb;
|
283 |
+
|
284 |
+
$wpdb->global_tables[] = 'itsec_logs';
|
285 |
+
$wpdb->global_tables[] = 'itsec_log';
|
286 |
+
$wpdb->global_tables[] = 'itsec_lockouts';
|
287 |
+
$wpdb->global_tables[] = 'itsec_temp';
|
288 |
+
$wpdb->global_tables[] = 'itsec_distributed_storage';
|
289 |
+
$wpdb->global_tables[] = 'itsec_geolocation_cache';
|
290 |
+
$wpdb->global_tables[] = 'itsec_fingerprints';
|
291 |
+
$wpdb->global_tables[] = 'itsec_user_groups';
|
292 |
+
$wpdb->global_tables[] = 'itsec_mutexes';
|
293 |
+
}
|
294 |
+
|
295 |
Â
private function setup_scheduler() {
|
296 |
Â
|
297 |
Â
if ( $this->scheduler ) {
|
315 |
Â
self::get_scheduler()->run();
|
316 |
Â
}
|
317 |
Â
|
318 |
+
/**
|
319 |
+
* Get the required capability to manage ITSEC.
|
320 |
+
*
|
321 |
+
* @return string
|
322 |
+
*/
|
323 |
+
public static function get_required_cap() {
|
324 |
+
return apply_filters( 'itsec_cap_required', 'itsec_manage' );
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Does the current user have permission to manage ITSEC.
|
329 |
+
*
|
330 |
+
* @return bool
|
331 |
+
*/
|
332 |
+
public static function current_user_can_manage() {
|
333 |
+
return current_user_can( self::get_required_cap() );
|
334 |
+
}
|
335 |
+
|
336 |
Â
/**
|
337 |
Â
* Retrieve the global instance of the files utility.
|
338 |
Â
*
|
340 |
Â
*/
|
341 |
Â
public static function get_itsec_files() {
|
342 |
Â
$self = self::get_instance();
|
343 |
+
|
344 |
Â
return $self->itsec_files;
|
345 |
Â
}
|
346 |
Â
|
351 |
Â
*/
|
352 |
Â
public static function get_itsec_notify() {
|
353 |
Â
$self = self::get_instance();
|
354 |
+
|
355 |
Â
return $self->itsec_notify;
|
356 |
Â
}
|
357 |
Â
|
416 |
Â
*/
|
417 |
Â
public static function get_sync_api() {
|
418 |
Â
$self = self::get_instance();
|
419 |
+
|
420 |
Â
return $self->sync_api;
|
421 |
Â
}
|
422 |
Â
|
423 |
+
/**
|
424 |
+
* Check if an import is in progress.
|
425 |
+
*
|
426 |
+
* @return bool
|
427 |
+
*/
|
428 |
+
public static function is_importing() {
|
429 |
+
return self::get_instance()->importing;
|
430 |
+
}
|
431 |
+
|
432 |
Â
/**
|
433 |
Â
* Register ITSEC verbs with sync.
|
434 |
Â
*
|
449 |
Â
public function register_events( $scheduler ) {
|
450 |
Â
$scheduler->schedule( ITSEC_Scheduler::S_DAILY, 'clear-locks' );
|
451 |
Â
$scheduler->schedule( ITSEC_Scheduler::S_DAILY, 'health-check' );
|
452 |
+
$scheduler->schedule( ITSEC_Scheduler::S_DAILY, 'clear-tokens' );
|
453 |
Â
}
|
454 |
Â
|
455 |
Â
/**
|
458 |
Â
public function register_modules() {
|
459 |
Â
$path = dirname( __FILE__ );
|
460 |
Â
|
461 |
+
ITSEC_Modules::register_module( 'feature-flags', "$path/modules/feature-flags", 'always-active' );
|
462 |
Â
ITSEC_Modules::register_module( 'security-check', "$path/modules/security-check", 'always-active' );
|
463 |
Â
ITSEC_Modules::register_module( 'global', "$path/modules/global", 'always-active' );
|
464 |
Â
ITSEC_Modules::register_module( 'notification-center', "$path/modules/notification-center", 'always-active' );
|
465 |
+
ITSEC_Modules::register_module( 'user-groups', "$path/modules/user-groups", 'always-active' );
|
466 |
Â
ITSEC_Modules::register_module( 'privacy', "$path/modules/privacy", 'always-active' );
|
467 |
Â
ITSEC_Modules::register_module( '404-detection', "$path/modules/404-detection" );
|
468 |
Â
ITSEC_Modules::register_module( 'admin-user', "$path/modules/admin-user", 'always-active' );
|
485 |
Â
|
486 |
Â
ITSEC_Modules::register_module( 'network-brute-force', "$path/modules/ipcheck", 'default-active' );
|
487 |
Â
|
488 |
+
if ( ! defined( 'ITSEC_DISABLE_PASSWORD_REQUIREMENTS' ) || ! ITSEC_DISABLE_PASSWORD_REQUIREMENTS ) {
|
489 |
Â
ITSEC_Modules::register_module( 'password-requirements', "$path/modules/password-requirements/", 'always-active' );
|
490 |
Â
}
|
491 |
Â
|
496 |
Â
ITSEC_Modules::register_module( 'wordpress-tweaks', "$path/modules/wordpress-tweaks", 'default-active' );
|
497 |
Â
ITSEC_Modules::register_module( 'file-writing', "$path/modules/file-writing", 'always-active' );
|
498 |
Â
ITSEC_Modules::register_module( 'malware', "$path/modules/malware", 'always-active' );
|
Â
|
|
499 |
Â
ITSEC_Modules::register_module( 'security-check-pro', "$path/modules/security-check-pro", self::is_pro() ? 'always-active' : 'default-inactive' );
|
500 |
+
ITSEC_Modules::register_module( 'sync-connect', "$path/modules/sync-connect", 'always-active' );
|
501 |
Â
|
502 |
Â
if ( ! ITSEC_Core::is_pro() ) {
|
503 |
Â
ITSEC_Modules::register_module( 'pro-module-upsells', "$path/modules/pro", 'always-active' );
|
559 |
Â
* Dispatch a request to upgrade the data schema to another version.
|
560 |
Â
*
|
561 |
Â
* @param int|bool $build The version of the data storage format. Pass false to default to the current version.
|
562 |
+
*
|
563 |
+
* @return true|WP_Error|null
|
564 |
Â
*/
|
565 |
Â
public function handle_upgrade( $build = false ) {
|
566 |
Â
|
567 |
+
if ( func_num_args() === 0 && self::get_saved_plugin_build() >= $this->plugin_build ) {
|
568 |
+
return null;
|
569 |
Â
}
|
570 |
Â
|
571 |
Â
$this->doing_data_upgrade = true;
|
572 |
Â
|
573 |
Â
require_once( self::get_core_dir() . '/setup.php' );
|
574 |
+
self::get_instance()->setup_error = ITSEC_Setup::handle_upgrade( $build );
|
575 |
+
|
576 |
+
return self::get_instance()->setup_error;
|
577 |
Â
}
|
578 |
Â
|
579 |
Â
public static function handle_activation() {
|
580 |
Â
require_once( self::get_core_dir() . '/setup.php' );
|
581 |
+
self::get_instance()->setup_error = ITSEC_Setup::handle_activation();
|
582 |
Â
}
|
583 |
Â
|
584 |
Â
public static function handle_deactivation() {
|
594 |
Â
/**
|
595 |
Â
* Register a notice to be displayed in the WordPress admin.
|
596 |
Â
*
|
597 |
+
* @param callable $callback Function that will render a notice.
|
598 |
+
* @param bool $all_pages Display the notice on all pages or only on ITSEC, plugins, and upgrade page.
|
599 |
Â
*/
|
600 |
Â
public static function add_notice( $callback, $all_pages = false ) {
|
601 |
Â
_deprecated_function( __METHOD__, '6.0.0', 'ITSEC_Lib_Admin_Notices::register' );
|
622 |
Â
}
|
623 |
Â
}
|
624 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
625 |
Â
public static function get_plugin_file() {
|
626 |
Â
$self = self::get_instance();
|
627 |
+
|
628 |
Â
return $self->plugin_file;
|
629 |
Â
}
|
630 |
Â
|
631 |
Â
public static function set_plugin_file( $plugin_file ) {
|
632 |
+
$self = self::get_instance();
|
633 |
Â
$self->plugin_file = $plugin_file;
|
634 |
+
$self->plugin_dir = dirname( $plugin_file ) . '/';
|
635 |
Â
}
|
636 |
Â
|
637 |
+
/**
|
638 |
+
* Get the build the plugin is running on.
|
639 |
+
*
|
640 |
+
* @return int
|
641 |
+
*/
|
642 |
Â
public static function get_plugin_build() {
|
643 |
Â
$self = self::get_instance();
|
644 |
+
|
645 |
Â
return $self->plugin_build;
|
646 |
Â
}
|
647 |
Â
|
648 |
+
/**
|
649 |
+
* Get the build the database is running.
|
650 |
+
*
|
651 |
+
* @param bool $use_cache
|
652 |
+
*
|
653 |
+
* @return int
|
654 |
+
*/
|
655 |
+
public static function get_saved_plugin_build( $use_cache = true ) {
|
656 |
+
if ( $use_cache ) {
|
657 |
+
return ITSEC_Modules::get_setting( 'global', 'build' );
|
658 |
+
}
|
659 |
+
|
660 |
+
$storage = get_site_option( 'itsec-storage' );
|
661 |
+
|
662 |
+
if ( ! $storage ) {
|
663 |
+
return 0;
|
664 |
+
}
|
665 |
+
|
666 |
+
if ( ! isset( $storage['global']['build'] ) ) {
|
667 |
+
return 0;
|
668 |
+
}
|
669 |
+
|
670 |
+
return (int) $storage['global']['build'];
|
671 |
+
}
|
672 |
+
|
673 |
Â
public static function get_plugin_dir() {
|
674 |
Â
$self = self::get_instance();
|
675 |
+
|
676 |
Â
return $self->plugin_dir;
|
677 |
Â
}
|
678 |
Â
|
682 |
Â
|
683 |
Â
public static function get_plugin_name() {
|
684 |
Â
$self = self::get_instance();
|
685 |
+
|
686 |
Â
return $self->plugin_name;
|
687 |
Â
}
|
688 |
Â
|
736 |
Â
*/
|
737 |
Â
public static function get_current_time() {
|
738 |
Â
$self = self::get_instance();
|
739 |
+
|
740 |
Â
return $self->current_time;
|
741 |
Â
}
|
742 |
Â
|
749 |
Â
*/
|
750 |
Â
public static function get_current_time_gmt() {
|
751 |
Â
$self = self::get_instance();
|
752 |
+
|
753 |
Â
return $self->current_time_gmt;
|
754 |
Â
}
|
755 |
Â
|
760 |
Â
*/
|
761 |
Â
public static function get_time_offset() {
|
762 |
Â
$self = self::get_instance();
|
763 |
+
|
764 |
Â
return $self->current_time - $self->current_time_gmt;
|
765 |
Â
}
|
766 |
Â
|
776 |
Â
$filters = array();
|
777 |
Â
|
778 |
Â
if ( $module ) {
|
779 |
+
$filters[] = rawurlencode( "module|{$module}" );
|
780 |
Â
}
|
781 |
Â
|
782 |
Â
if ( $type ) {
|
811 |
Â
*
|
812 |
Â
* @param bool $interactive
|
813 |
Â
*/
|
814 |
+
public static function set_interactive( $interactive = true ) {
|
815 |
+
$self = self::get_instance();
|
816 |
Â
$self->interactive = (bool) $interactive;
|
817 |
Â
}
|
818 |
Â
|
823 |
Â
*/
|
824 |
Â
public static function is_interactive() {
|
825 |
Â
$self = self::get_instance();
|
826 |
+
|
827 |
Â
return $self->interactive;
|
828 |
Â
}
|
829 |
Â
|
866 |
Â
* This value is cached for both the lifetime of the request and possibly indefinitely when WordPress is
|
867 |
Â
* using an object cache.
|
868 |
Â
*
|
869 |
+
* @return array
|
870 |
Â
* @see wp_upload_dir
|
871 |
Â
*
|
Â
|
|
872 |
Â
*/
|
873 |
Â
public static function get_wp_upload_dir() {
|
874 |
Â
$self = self::get_instance();
|
917 |
Â
/**
|
918 |
Â
* Retrieve and/or create a directory for ITSEC to store data.
|
919 |
Â
*
|
920 |
+
* @param string $dir Optionally specify an additional sub-directory.
|
921 |
Â
* @param bool $public Whether to get the public version of the directory.
|
922 |
Â
*
|
923 |
Â
* @return string
|
1002 |
Â
|
1003 |
Â
if ( ! function_exists( 'rest_get_url_prefix' ) ) {
|
1004 |
Â
$GLOBALS['__itsec_core_is_rest_api_request'] = false;
|
1005 |
+
|
1006 |
Â
return false;
|
1007 |
Â
}
|
1008 |
Â
|
1009 |
Â
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
1010 |
Â
$GLOBALS['__itsec_core_is_rest_api_request'] = true;
|
1011 |
+
|
1012 |
Â
return true;
|
1013 |
Â
}
|
1014 |
Â
|
1104 |
Â
|
1105 |
Â
return $self->version;
|
1106 |
Â
}
|
1107 |
+
|
1108 |
+
public static function is_test_suite( $suite = '' ) {
|
1109 |
+
if ( ! defined( 'ITSEC_TEST_SUITE' ) ) {
|
1110 |
+
return false;
|
1111 |
+
}
|
1112 |
+
|
1113 |
+
return $suite ? ITSEC_TEST_SUITE === $suite : true;
|
1114 |
+
}
|
1115 |
Â
}
|
1116 |
Â
}
|
core/history.txt
CHANGED
@@ -839,3 +839,41 @@
|
|
839 |
Â
New Feature: iThemes Security now includes Security Check Pro to automatically and correctly determine your visitors IP addresses. Enable this scan by running Security Check and opting in to Security Check Pro or activate the Security Check Pro module in Advanced Modules. H/t Jeremy Voisin
|
840 |
Â
Enhancement: Run Security Check Pro IP Detection automatically once a day.
|
841 |
Â
Enhancement: Manually re-run Security Check Pro IP Detection from the Global Settings page.
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
839 |
Â
New Feature: iThemes Security now includes Security Check Pro to automatically and correctly determine your visitors IP addresses. Enable this scan by running Security Check and opting in to Security Check Pro or activate the Security Check Pro module in Advanced Modules. H/t Jeremy Voisin
|
840 |
Â
Enhancement: Run Security Check Pro IP Detection automatically once a day.
|
841 |
Â
Enhancement: Manually re-run Security Check Pro IP Detection from the Global Settings page.
|
842 |
+
5.5.1 - 2019-12-18 - Timothy Jacobs
|
843 |
+
Bug Fix: The "Mulisite Tweaks -> Hide Updates" setting prevented auto-updates from running with WP Cron.
|
844 |
+
Bug Fix: Remove "get_magic_quotes()" call that existed for backwards compatibility with PHP versions 5.3 and earlier. This function call was causing a warning on PHP 7.4.
|
845 |
+
5.5.2 - 2020-01-07 - Timothy Jacobs
|
846 |
+
Bug Fix: Backup event was not added when the WP Cron Scheduler was reset manually.
|
847 |
+
Bug Fix: Admin Notices Popover was not being hidden when clicking outside the Popover on WP 5.3.
|
848 |
+
5.6.0 - 2020-02-12 - Timothy Jacobs, Josh Oakes
|
849 |
+
Important: iThemes Security requires PHP 5.6 or greater and WordPress 5.2 or greater.
|
850 |
+
New Feature: Save Time Securing WordPress With User Groups!
|
851 |
+
New Feature: Simplified connection flow when setting up iThemes Sync.
|
852 |
+
Bug Fix: Warning when loading the settings page on PHP 7.4.
|
853 |
+
Bug Fix: Warning when loading the debug page on PHP 7.4.
|
854 |
+
5.6.1 - 2020-02-13 - Timothy Jacobs
|
855 |
+
Bug Fix: A fatal error could occur when upgrading to User Groups if a custom role had been selected for Two-Factor or Passwordless Login that has since been deleted but the module's settings had not been updated.
|
856 |
+
5.6.2 - 2020-02-17 - Timothy Jacobs, Josh Oakes
|
857 |
+
Tweak: Harden iThemes Sync connection flow by adding a second verification check.
|
858 |
+
Bug Fix: Prevent UnknownIdentifierException errors when modules are loaded before expected.
|
859 |
+
Bug Fix: Add additional type checks.
|
860 |
+
5.7.0 - 2020-03-10 - Timothy Jacobs
|
861 |
+
Enhancement: Allow selecting users across all sites in a network for User Groups.
|
862 |
+
Enhancement: Add super admins as a selectable role for User Groups.
|
863 |
+
Enhancement: Add a warning if a WordPress Salt is set to an invalid value.
|
864 |
+
Enhancement: Include child log items in the logs list table. These are helpful for debugging issues.
|
865 |
+
Enhancement: Improve performance of the logs page on sites with large number of log items.
|
866 |
+
Tweak: When logging $_SERVER, only log a snapshot of available properties.
|
867 |
+
Bug Fix: New Password Requirements for already created accounts were not enforced until the second login.
|
868 |
+
Bug Fix: Prevent fatal error if invalid user IDs are encountered by User Groups.
|
869 |
+
5.7.1 - 2020-03-11 - Timothy Jacobs
|
870 |
+
Enhancement: Further improve logs performance.
|
871 |
+
5.7.2 - 2020-03-31 - Timothy Jacobs
|
872 |
+
Bug Fix: Update admin notices styling to be compatible with WordPress 5.4.
|
873 |
+
Bug Fix: Periodically clear expired opaque tokens.
|
874 |
+
Bug Fix: Exclude "Process Update" and "Process Stop" logs when other process logs are hidden.
|
875 |
+
5.7.3 - 2020-04-08 - Timothy Jacobs
|
876 |
+
Bug Fix: Don't block registration page when "wp-signup.php" is the Hide Backend register slug.
|
877 |
+
5.7.4 - 2020-04-15 - Timothy Jacobs
|
878 |
+
Bug Fix: Users with weak passwords would not be forced to change their password if the strong password requirement had been enabled after their password strength was checked.
|
879 |
+
Bug Fix: PHP warning if downgrading from Pro to Free.
|
core/img/bb-ad.jpg
DELETED
Binary file
|
core/lib.php
CHANGED
@@ -54,12 +54,12 @@ final class ITSEC_Lib {
|
|
54 |
Â
*
|
55 |
Â
* @since 4.0.0
|
56 |
Â
*
|
57 |
-
* @return
|
58 |
Â
*/
|
59 |
Â
public static function create_database_tables() {
|
60 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/schema.php' );
|
61 |
Â
|
62 |
-
ITSEC_Schema::create_database_tables();
|
63 |
Â
}
|
64 |
Â
|
65 |
Â
/**
|
@@ -514,6 +514,25 @@ final class ITSEC_Lib {
|
|
514 |
Â
return $html;
|
515 |
Â
}
|
516 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
517 |
Â
/**
|
518 |
Â
* Get a WordPress user object.
|
519 |
Â
*
|
@@ -976,16 +995,20 @@ final class ITSEC_Lib {
|
|
976 |
Â
return $storage;
|
977 |
Â
}
|
978 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
979 |
Â
public static function array_get( $array, $key, $default = null ) {
|
980 |
-
|
981 |
Â
if ( ! is_array( $array ) ) {
|
982 |
Â
return $default;
|
983 |
Â
}
|
984 |
Â
|
985 |
-
if ( null === $key ) {
|
986 |
-
return $array;
|
987 |
-
}
|
988 |
-
|
989 |
Â
if ( isset( $array[ $key ] ) ) {
|
990 |
Â
return $array[ $key ];
|
991 |
Â
}
|
@@ -1005,6 +1028,36 @@ final class ITSEC_Lib {
|
|
1005 |
Â
return $array;
|
1006 |
Â
}
|
1007 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1008 |
Â
public static function print_r( $data, $args = array() ) {
|
1009 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/debug.php' );
|
1010 |
Â
|
@@ -1759,10 +1812,10 @@ final class ITSEC_Lib {
|
|
1759 |
Â
*
|
1760 |
Â
* @return WP_Error
|
1761 |
Â
*/
|
1762 |
-
public static function combine_wp_error(
|
1763 |
Â
$combined = new WP_Error();
|
1764 |
Â
|
1765 |
-
self::add_to_wp_error( $combined,
|
1766 |
Â
|
1767 |
Â
return $combined;
|
1768 |
Â
}
|
@@ -1770,19 +1823,22 @@ final class ITSEC_Lib {
|
|
1770 |
Â
/**
|
1771 |
Â
* Add the subsequent WP Error data to the first WP Error instance.
|
1772 |
Â
*
|
1773 |
-
* @param WP_Error
|
1774 |
-
* @param WP_Error
|
1775 |
Â
*/
|
1776 |
-
public static function add_to_wp_error( WP_Error $add_to,
|
1777 |
-
if ( ! is_array( $errors ) ) {
|
1778 |
-
$errors = func_get_args();
|
1779 |
-
array_shift( $errors );
|
1780 |
-
}
|
1781 |
-
|
1782 |
Â
foreach ( $errors as $error ) {
|
1783 |
Â
if ( $error ) {
|
1784 |
Â
foreach ( $error->get_error_codes() as $code ) {
|
1785 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1786 |
Â
}
|
1787 |
Â
}
|
1788 |
Â
}
|
@@ -1829,9 +1885,9 @@ final class ITSEC_Lib {
|
|
1829 |
Â
/**
|
1830 |
Â
* Get the WordPress branch version.
|
1831 |
Â
*
|
Â
|
|
1832 |
Â
* @example 5.2.4 => 5.2
|
1833 |
Â
*
|
1834 |
-
* @return string
|
1835 |
Â
*/
|
1836 |
Â
public static function get_wp_branch() {
|
1837 |
Â
$version = get_bloginfo( 'version' );
|
@@ -1840,4 +1896,163 @@ final class ITSEC_Lib {
|
|
1840 |
Â
|
1841 |
Â
return $major . '.' . $minor;
|
1842 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1843 |
Â
}
|
54 |
Â
*
|
55 |
Â
* @since 4.0.0
|
56 |
Â
*
|
57 |
+
* @return true|WP_Error
|
58 |
Â
*/
|
59 |
Â
public static function create_database_tables() {
|
60 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/schema.php' );
|
61 |
Â
|
62 |
+
return ITSEC_Schema::create_database_tables();
|
63 |
Â
}
|
64 |
Â
|
65 |
Â
/**
|
514 |
Â
return $html;
|
515 |
Â
}
|
516 |
Â
|
517 |
+
/**
|
518 |
+
* Get an error string for all errors in a WP_Error isntance.
|
519 |
+
*
|
520 |
+
* @param WP_Error $error
|
521 |
+
*
|
522 |
+
* @return string[]
|
523 |
+
*/
|
524 |
+
public static function get_error_strings( WP_Error $error ) {
|
525 |
+
$messages = array();
|
526 |
+
|
527 |
+
foreach ( $error->get_error_codes() as $code ) {
|
528 |
+
foreach ( $error->get_error_messages( $code ) as $str ) {
|
529 |
+
$messages[] = $str;
|
530 |
+
}
|
531 |
+
}
|
532 |
+
|
533 |
+
return $messages;
|
534 |
+
}
|
535 |
+
|
536 |
Â
/**
|
537 |
Â
* Get a WordPress user object.
|
538 |
Â
*
|
995 |
Â
return $storage;
|
996 |
Â
}
|
997 |
Â
|
998 |
+
/**
|
999 |
+
* Get a dot nested value from an array.
|
1000 |
+
*
|
1001 |
+
* @param array $array
|
1002 |
+
* @param string $key
|
1003 |
+
* @param mixed $default
|
1004 |
+
*
|
1005 |
+
* @return mixed
|
1006 |
+
*/
|
1007 |
Â
public static function array_get( $array, $key, $default = null ) {
|
Â
|
|
1008 |
Â
if ( ! is_array( $array ) ) {
|
1009 |
Â
return $default;
|
1010 |
Â
}
|
1011 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1012 |
Â
if ( isset( $array[ $key ] ) ) {
|
1013 |
Â
return $array[ $key ];
|
1014 |
Â
}
|
1028 |
Â
return $array;
|
1029 |
Â
}
|
1030 |
Â
|
1031 |
+
/**
|
1032 |
+
* Set an array item to a given value using "dot" notation.
|
1033 |
+
*
|
1034 |
+
* @param array $array
|
1035 |
+
* @param string $key
|
1036 |
+
* @param mixed $value
|
1037 |
+
*
|
1038 |
+
* @return array
|
1039 |
+
*/
|
1040 |
+
public static function array_set( $array, $key, $value ) {
|
1041 |
+
$keys = explode( '.', $key );
|
1042 |
+
$modify = &$array;
|
1043 |
+
|
1044 |
+
while ( count( $keys ) > 1 ) {
|
1045 |
+
$key = array_shift( $keys );
|
1046 |
+
// If the key doesn't exist at this depth, we will just create an empty array
|
1047 |
+
// to hold the next value, allowing us to create the arrays to hold final
|
1048 |
+
// values at the correct depth. Then we'll keep digging into the array.
|
1049 |
+
if ( ! isset( $modify[ $key ] ) || ! is_array( $modify[ $key ] ) ) {
|
1050 |
+
$modify[ $key ] = [];
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
$modify = &$modify[ $key ];
|
1054 |
+
}
|
1055 |
+
|
1056 |
+
$modify[ array_shift( $keys ) ] = $value;
|
1057 |
+
|
1058 |
+
return $array;
|
1059 |
+
}
|
1060 |
+
|
1061 |
Â
public static function print_r( $data, $args = array() ) {
|
1062 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/debug.php' );
|
1063 |
Â
|
1812 |
Â
*
|
1813 |
Â
* @return WP_Error
|
1814 |
Â
*/
|
1815 |
+
public static function combine_wp_error( ...$errors ) {
|
1816 |
Â
$combined = new WP_Error();
|
1817 |
Â
|
1818 |
+
self::add_to_wp_error( $combined, ...$errors );
|
1819 |
Â
|
1820 |
Â
return $combined;
|
1821 |
Â
}
|
1823 |
Â
/**
|
1824 |
Â
* Add the subsequent WP Error data to the first WP Error instance.
|
1825 |
Â
*
|
1826 |
+
* @param WP_Error $add_to
|
1827 |
+
* @param WP_Error|null ...$errors
|
1828 |
Â
*/
|
1829 |
+
public static function add_to_wp_error( WP_Error $add_to, ...$errors ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1830 |
Â
foreach ( $errors as $error ) {
|
1831 |
Â
if ( $error ) {
|
1832 |
Â
foreach ( $error->get_error_codes() as $code ) {
|
1833 |
+
foreach ( $error->get_error_messages( $code ) as $message ) {
|
1834 |
+
$add_to->add( $code, $message );
|
1835 |
+
}
|
1836 |
+
|
1837 |
+
$data = $error->get_error_data( $code );
|
1838 |
+
|
1839 |
+
if ( null !== $data ) {
|
1840 |
+
$add_to->add_data( $data, $code );
|
1841 |
+
}
|
1842 |
Â
}
|
1843 |
Â
}
|
1844 |
Â
}
|
1885 |
Â
/**
|
1886 |
Â
* Get the WordPress branch version.
|
1887 |
Â
*
|
1888 |
+
* @return string
|
1889 |
Â
* @example 5.2.4 => 5.2
|
1890 |
Â
*
|
Â
|
|
1891 |
Â
*/
|
1892 |
Â
public static function get_wp_branch() {
|
1893 |
Â
$version = get_bloginfo( 'version' );
|
1896 |
Â
|
1897 |
Â
return $major . '.' . $minor;
|
1898 |
Â
}
|
1899 |
+
|
1900 |
+
/**
|
1901 |
+
* Are two lists equal ignoring order.
|
1902 |
+
*
|
1903 |
+
* @param array $a
|
1904 |
+
* @param array $b
|
1905 |
+
* @param callable|null $cmp
|
1906 |
+
*
|
1907 |
+
* @return bool
|
1908 |
+
*/
|
1909 |
+
public static function equal_sets( array $a, array $b, callable $cmp = null ) {
|
1910 |
+
if ( $cmp ) {
|
1911 |
+
usort( $a, $cmp );
|
1912 |
+
usort( $b, $cmp );
|
1913 |
+
} else {
|
1914 |
+
sort( $a );
|
1915 |
+
sort( $b );
|
1916 |
+
}
|
1917 |
+
|
1918 |
+
return $a === $b;
|
1919 |
+
}
|
1920 |
+
|
1921 |
+
/**
|
1922 |
+
* Convert the return val from {@see ITSEC_Modules::set_settings()} to a WP_Error object.
|
1923 |
+
*
|
1924 |
+
* @param array $updated
|
1925 |
+
*
|
1926 |
+
* @return WP_Error|null
|
1927 |
+
*/
|
1928 |
+
public static function updated_settings_to_wp_error( $updated ) {
|
1929 |
+
if ( is_wp_error( $updated ) ) {
|
1930 |
+
return $updated;
|
1931 |
+
}
|
1932 |
+
|
1933 |
+
if ( $updated['saved'] ) {
|
1934 |
+
return null;
|
1935 |
+
}
|
1936 |
+
|
1937 |
+
if ( $updated['errors'] ) {
|
1938 |
+
$error = self::combine_wp_error( ...$updated['errors'] );
|
1939 |
+
} else {
|
1940 |
+
$error = new \WP_Error( 'itsec.settings.set-failed', __( 'Failed to update settings.', 'better-wp-security' ), [ 'status' => \WP_Http::BAD_REQUEST ] );
|
1941 |
+
}
|
1942 |
+
|
1943 |
+
return $error;
|
1944 |
+
}
|
1945 |
+
|
1946 |
+
/**
|
1947 |
+
* Sanitize the list of roles.
|
1948 |
+
*
|
1949 |
+
* @param string[] $roles
|
1950 |
+
*
|
1951 |
+
* @return array
|
1952 |
+
*/
|
1953 |
+
public static function sanitize_roles( $roles ) {
|
1954 |
+
return array_filter( $roles, static function ( $role ) {
|
1955 |
+
return (bool) get_role( $role );
|
1956 |
+
} );
|
1957 |
+
}
|
1958 |
+
|
1959 |
+
/**
|
1960 |
+
* Get a snapshot of $_SERVER properties.
|
1961 |
+
*
|
1962 |
+
* @return array
|
1963 |
+
*/
|
1964 |
+
public static function get_server_snapshot() {
|
1965 |
+
$whitelist = [
|
1966 |
+
'REQUEST_TIME',
|
1967 |
+
'REQUEST_TIME_FLOAT',
|
1968 |
+
'REQUEST_METHOD',
|
1969 |
+
'HTTPS',
|
1970 |
+
'REQUEST_SCHEME',
|
1971 |
+
'SERVER_PROTOCOL',
|
1972 |
+
'SCRIPT_FILENAME',
|
1973 |
+
];
|
1974 |
+
|
1975 |
+
return array_filter( $_SERVER, static function ( $key ) use ( $whitelist ) {
|
1976 |
+
if ( $key === 'HTTP_COOKIE' ) {
|
1977 |
+
return false;
|
1978 |
+
}
|
1979 |
+
|
1980 |
+
if ( self::str_starts_with( $key, 'HTTP_' ) ) {
|
1981 |
+
return true;
|
1982 |
+
}
|
1983 |
+
|
1984 |
+
if ( self::str_starts_with( $key, 'CONTENT_' ) ) {
|
1985 |
+
return true;
|
1986 |
+
}
|
1987 |
+
|
1988 |
+
return in_array( $key, $whitelist, true );
|
1989 |
+
}, ARRAY_FILTER_USE_KEY );
|
1990 |
+
}
|
1991 |
+
|
1992 |
+
/**
|
1993 |
+
* Version of {@see is_super_admin()} that operates on a `WP_User` instance.
|
1994 |
+
*
|
1995 |
+
* This bypasses an issue where {@see is_super_admin()} cannot be used during the `determine_current_user` filter since
|
1996 |
+
* `is_super_admin` has a side effect of querying for the current user, causing an infinite loop.
|
1997 |
+
*
|
1998 |
+
* @param WP_User $user
|
1999 |
+
*
|
2000 |
+
* @return bool
|
2001 |
+
*/
|
2002 |
+
public static function is_super_admin( WP_User $user ) {
|
2003 |
+
if ( ! $user->exists() ) {
|
2004 |
+
return false;
|
2005 |
+
}
|
2006 |
+
|
2007 |
+
if ( is_multisite() ) {
|
2008 |
+
$super_admins = get_super_admins();
|
2009 |
+
if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) ) {
|
2010 |
+
return true;
|
2011 |
+
}
|
2012 |
+
} else {
|
2013 |
+
if ( $user->has_cap( 'delete_users' ) ) {
|
2014 |
+
return true;
|
2015 |
+
}
|
2016 |
+
}
|
2017 |
+
|
2018 |
+
return false;
|
2019 |
+
}
|
2020 |
+
|
2021 |
+
/**
|
2022 |
+
* Performs a {@see dbDelta()} but reports any errors encountered.
|
2023 |
+
*
|
2024 |
+
* @param string $delta
|
2025 |
+
*
|
2026 |
+
* @return WP_Error
|
2027 |
+
*/
|
2028 |
+
public static function db_delta_with_error_handling( $delta ) {
|
2029 |
+
global $wpdb, $EZSQL_ERROR;
|
2030 |
+
|
2031 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
2032 |
+
|
2033 |
+
$err_count = is_array( $EZSQL_ERROR ) ? count( $EZSQL_ERROR ) : 0;
|
2034 |
+
$showed_errors = $wpdb->show_errors( false );
|
2035 |
+
|
2036 |
+
dbDelta( $delta );
|
2037 |
+
|
2038 |
+
if ( $showed_errors ) {
|
2039 |
+
$wpdb->show_errors();
|
2040 |
+
}
|
2041 |
+
|
2042 |
+
$wp_error = new WP_Error();
|
2043 |
+
|
2044 |
+
if ( is_array( $EZSQL_ERROR ) ) {
|
2045 |
+
for ( $i = $err_count, $i_max = count( $EZSQL_ERROR ); $i < $i_max; $i ++ ) {
|
2046 |
+
$error = $EZSQL_ERROR[ $i ];
|
2047 |
+
|
2048 |
+
if ( empty( $error['error_str'] ) || empty( $error['query'] ) || 0 === strpos( $error['query'], 'DESCRIBE ' ) ) {
|
2049 |
+
continue;
|
2050 |
+
}
|
2051 |
+
|
2052 |
+
$wp_error->add( 'db_delta_error', $error['error_str'] );
|
2053 |
+
}
|
2054 |
+
}
|
2055 |
+
|
2056 |
+
return $wp_error;
|
2057 |
+
}
|
2058 |
Â
}
|
core/lib/class-itsec-lib-canonical-roles.php
CHANGED
@@ -2,6 +2,33 @@
|
|
2 |
Â
|
3 |
Â
final class ITSEC_Lib_Canonical_Roles {
|
4 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
5 |
Â
/**
|
6 |
Â
* Check if a given role is at least as or equally as powerful as a given role.
|
7 |
Â
*
|
@@ -21,11 +48,11 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
21 |
Â
'' => 0,
|
22 |
Â
);
|
23 |
Â
|
24 |
-
if ( ! isset( $roles[$role] ) || ! isset( $roles[$min_role] ) ) {
|
25 |
Â
return false;
|
26 |
Â
}
|
27 |
Â
|
28 |
-
if ( $roles[$role] >= $roles[$min_role] ) {
|
29 |
Â
return true;
|
30 |
Â
}
|
31 |
Â
|
@@ -51,13 +78,13 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
51 |
Â
'' => 0,
|
52 |
Â
);
|
53 |
Â
|
54 |
-
if ( ! isset( $roles[$role] ) ) {
|
55 |
Â
return false;
|
56 |
Â
}
|
57 |
Â
|
58 |
Â
$user_role = self::get_user_role( $user );
|
59 |
Â
|
60 |
-
if ( $roles[$user_role] >= $roles[$role] ) {
|
61 |
Â
return true;
|
62 |
Â
}
|
63 |
Â
|
@@ -105,7 +132,7 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
105 |
Â
return '';
|
106 |
Â
}
|
107 |
Â
|
108 |
-
if ( is_multisite() && is_super_admin( $user
|
109 |
Â
return 'super-admin';
|
110 |
Â
}
|
111 |
Â
|
@@ -149,6 +176,10 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
149 |
Â
public static function get_canonical_role_from_role_and_user( $role, $user ) {
|
150 |
Â
$user = ITSEC_Lib::get_user( $user );
|
151 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
152 |
Â
if ( empty( $role ) ) {
|
153 |
Â
$role_caps = array();
|
154 |
Â
} else {
|
@@ -162,7 +193,7 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
162 |
Â
|
163 |
Â
foreach ( $user->caps as $cap => $has ) {
|
164 |
Â
if ( $has && ! $wp_roles->is_role( $cap ) ) {
|
165 |
-
$user_caps[] = $
|
166 |
Â
}
|
167 |
Â
}
|
168 |
Â
}
|
@@ -170,6 +201,29 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
170 |
Â
return self::get_role_from_caps( array_merge( $role_caps, $user_caps ) );
|
171 |
Â
}
|
172 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
173 |
Â
/**
|
174 |
Â
* Get all users that have the given canonical role.
|
175 |
Â
*
|
@@ -233,7 +287,7 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
233 |
Â
'update_plugins',
|
234 |
Â
'update_themes',
|
235 |
Â
),
|
236 |
-
'editor'
|
237 |
Â
'delete_others_pages',
|
238 |
Â
'delete_others_posts',
|
239 |
Â
'delete_pages',
|
@@ -259,19 +313,19 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
259 |
Â
'read_private_posts',
|
260 |
Â
'unfiltered_html',
|
261 |
Â
),
|
262 |
-
'author'
|
263 |
Â
'delete_published_posts',
|
264 |
Â
'edit_published_posts',
|
265 |
Â
'level_2',
|
266 |
Â
'publish_posts',
|
267 |
Â
'upload_files',
|
268 |
Â
),
|
269 |
-
'contributor'
|
270 |
Â
'delete_posts',
|
271 |
Â
'edit_posts',
|
272 |
Â
'level_1',
|
273 |
Â
),
|
274 |
-
'subscriber'
|
275 |
Â
'level_0',
|
276 |
Â
'read',
|
277 |
Â
),
|
@@ -348,7 +402,7 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
348 |
Â
'update_themes',
|
349 |
Â
'upload_files',
|
350 |
Â
),
|
351 |
-
'editor'
|
352 |
Â
'delete_others_pages',
|
353 |
Â
'delete_others_posts',
|
354 |
Â
'delete_pages',
|
@@ -384,7 +438,7 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
384 |
Â
'unfiltered_html',
|
385 |
Â
'upload_files',
|
386 |
Â
),
|
387 |
-
'author'
|
388 |
Â
'delete_posts',
|
389 |
Â
'delete_published_posts',
|
390 |
Â
'edit_posts',
|
@@ -396,14 +450,14 @@ final class ITSEC_Lib_Canonical_Roles {
|
|
396 |
Â
'read',
|
397 |
Â
'upload_files',
|
398 |
Â
),
|
399 |
-
'contributor'
|
400 |
Â
'delete_posts',
|
401 |
Â
'edit_posts',
|
402 |
Â
'level_0',
|
403 |
Â
'level_1',
|
404 |
Â
'read',
|
405 |
Â
),
|
406 |
-
'subscriber'
|
407 |
Â
'level_0',
|
408 |
Â
'read',
|
409 |
Â
),
|
2 |
Â
|
3 |
Â
final class ITSEC_Lib_Canonical_Roles {
|
4 |
Â
|
5 |
+
private static $canonical = [
|
6 |
+
'super-admin',
|
7 |
+
'administrator',
|
8 |
+
'editor',
|
9 |
+
'author',
|
10 |
+
'contributor',
|
11 |
+
'subscriber',
|
12 |
+
];
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Get a list of all the canonical roles.
|
16 |
+
*
|
17 |
+
* @param bool $include_super_admin Include the super admin "role".
|
18 |
+
*
|
19 |
+
* @return string[]
|
20 |
+
*/
|
21 |
+
public static function get_canonical_roles( $include_super_admin = true ) {
|
22 |
+
$canonical = self::$canonical;
|
23 |
+
|
24 |
+
if ( ! $include_super_admin ) {
|
25 |
+
unset( $canonical[0] );
|
26 |
+
$canonical = array_values( $canonical );
|
27 |
+
}
|
28 |
+
|
29 |
+
return $canonical;
|
30 |
+
}
|
31 |
+
|
32 |
Â
/**
|
33 |
Â
* Check if a given role is at least as or equally as powerful as a given role.
|
34 |
Â
*
|
48 |
Â
'' => 0,
|
49 |
Â
);
|
50 |
Â
|
51 |
+
if ( ! isset( $roles[ $role ] ) || ! isset( $roles[ $min_role ] ) ) {
|
52 |
Â
return false;
|
53 |
Â
}
|
54 |
Â
|
55 |
+
if ( $roles[ $role ] >= $roles[ $min_role ] ) {
|
56 |
Â
return true;
|
57 |
Â
}
|
58 |
Â
|
78 |
Â
'' => 0,
|
79 |
Â
);
|
80 |
Â
|
81 |
+
if ( ! isset( $roles[ $role ] ) ) {
|
82 |
Â
return false;
|
83 |
Â
}
|
84 |
Â
|
85 |
Â
$user_role = self::get_user_role( $user );
|
86 |
Â
|
87 |
+
if ( $roles[ $user_role ] >= $roles[ $role ] ) {
|
88 |
Â
return true;
|
89 |
Â
}
|
90 |
Â
|
132 |
Â
return '';
|
133 |
Â
}
|
134 |
Â
|
135 |
+
if ( is_multisite() && ITSEC_Lib::is_super_admin( $user ) ) {
|
136 |
Â
return 'super-admin';
|
137 |
Â
}
|
138 |
Â
|
176 |
Â
public static function get_canonical_role_from_role_and_user( $role, $user ) {
|
177 |
Â
$user = ITSEC_Lib::get_user( $user );
|
178 |
Â
|
179 |
+
if ( is_multisite() && ITSEC_Lib::is_super_admin( $user ) ) {
|
180 |
+
return 'super-admin';
|
181 |
+
}
|
182 |
+
|
183 |
Â
if ( empty( $role ) ) {
|
184 |
Â
$role_caps = array();
|
185 |
Â
} else {
|
193 |
Â
|
194 |
Â
foreach ( $user->caps as $cap => $has ) {
|
195 |
Â
if ( $has && ! $wp_roles->is_role( $cap ) ) {
|
196 |
+
$user_caps[] = $cap;
|
197 |
Â
}
|
198 |
Â
}
|
199 |
Â
}
|
201 |
Â
return self::get_role_from_caps( array_merge( $role_caps, $user_caps ) );
|
202 |
Â
}
|
203 |
Â
|
204 |
+
/**
|
205 |
+
* Gets all canonical roles of at least the given canonical role capability.
|
206 |
+
*
|
207 |
+
* @example ::get_canonical_roles_of_at_least( 'editor' ) // [ 'administrator', 'editor' ]
|
208 |
+
*
|
209 |
+
* @param string $minimum
|
210 |
+
*
|
211 |
+
* @return string[]
|
212 |
+
*/
|
213 |
+
public static function get_canonical_roles_of_at_least( $minimum ) {
|
214 |
+
$at_least = [];
|
215 |
+
|
216 |
+
foreach ( self::$canonical as $role ) {
|
217 |
+
$at_least[] = $role;
|
218 |
+
|
219 |
+
if ( $role === $minimum ) {
|
220 |
+
break;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
return $at_least;
|
225 |
+
}
|
226 |
+
|
227 |
Â
/**
|
228 |
Â
* Get all users that have the given canonical role.
|
229 |
Â
*
|
287 |
Â
'update_plugins',
|
288 |
Â
'update_themes',
|
289 |
Â
),
|
290 |
+
'editor' => array(
|
291 |
Â
'delete_others_pages',
|
292 |
Â
'delete_others_posts',
|
293 |
Â
'delete_pages',
|
313 |
Â
'read_private_posts',
|
314 |
Â
'unfiltered_html',
|
315 |
Â
),
|
316 |
+
'author' => array(
|
317 |
Â
'delete_published_posts',
|
318 |
Â
'edit_published_posts',
|
319 |
Â
'level_2',
|
320 |
Â
'publish_posts',
|
321 |
Â
'upload_files',
|
322 |
Â
),
|
323 |
+
'contributor' => array(
|
324 |
Â
'delete_posts',
|
325 |
Â
'edit_posts',
|
326 |
Â
'level_1',
|
327 |
Â
),
|
328 |
+
'subscriber' => array(
|
329 |
Â
'level_0',
|
330 |
Â
'read',
|
331 |
Â
),
|
402 |
Â
'update_themes',
|
403 |
Â
'upload_files',
|
404 |
Â
),
|
405 |
+
'editor' => array(
|
406 |
Â
'delete_others_pages',
|
407 |
Â
'delete_others_posts',
|
408 |
Â
'delete_pages',
|
438 |
Â
'unfiltered_html',
|
439 |
Â
'upload_files',
|
440 |
Â
),
|
441 |
+
'author' => array(
|
442 |
Â
'delete_posts',
|
443 |
Â
'delete_published_posts',
|
444 |
Â
'edit_posts',
|
450 |
Â
'read',
|
451 |
Â
'upload_files',
|
452 |
Â
),
|
453 |
+
'contributor' => array(
|
454 |
Â
'delete_posts',
|
455 |
Â
'edit_posts',
|
456 |
Â
'level_0',
|
457 |
Â
'level_1',
|
458 |
Â
'read',
|
459 |
Â
),
|
460 |
+
'subscriber' => array(
|
461 |
Â
'level_0',
|
462 |
Â
'read',
|
463 |
Â
),
|
core/lib/class-itsec-lib-directory.php
CHANGED
@@ -171,19 +171,44 @@ if ( ! class_exists( 'ITSEC_Lib_Directory' ) ) {
|
|
171 |
Â
*
|
172 |
Â
* @since 1.15.0
|
173 |
Â
*
|
Â
|
|
Â
|
|
174 |
Â
* @return bool|WP_Error Boolean true on success or a WP_Error object if an error occurs.
|
175 |
Â
*/
|
176 |
Â
public static function remove( $dir ) {
|
177 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
178 |
Â
return true;
|
179 |
Â
}
|
180 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
181 |
Â
|
182 |
Â
if ( ! ITSEC_Lib_Utility::is_callable_function( 'rmdir' ) ) {
|
183 |
Â
return new WP_Error( 'itsec-lib-directory-remove-rmdir-is-disabled', sprintf( __( 'The directory %s could not be removed as the rmdir() function is disabled. This is a system configuration issue.', 'better-wp-security' ), $dir ) );
|
184 |
Â
}
|
185 |
Â
|
186 |
-
|
187 |
Â
$files = self::read( $dir );
|
188 |
Â
|
189 |
Â
if ( is_wp_error( $files ) ) {
|
@@ -198,15 +223,10 @@ if ( ! class_exists( 'ITSEC_Lib_Directory' ) ) {
|
|
198 |
Â
}
|
199 |
Â
}
|
200 |
Â
|
201 |
-
$result = rmdir( $dir );
|
202 |
Â
// phpcs:ignore -- Have Tide ignore the following line. We use arguments that don't exist in early versions, but these versions ignore the arguments.
|
203 |
Â
@clearstatcache( true, $dir );
|
204 |
Â
|
205 |
-
|
206 |
-
return true;
|
207 |
-
}
|
208 |
-
|
209 |
-
return new WP_Error( 'itsec-lib-directory-remove-unknown-error', sprintf( __( 'Unable to remove %s due to an unknown error.', 'better-wp-security' ), $dir ) );
|
210 |
Â
}
|
211 |
Â
|
212 |
Â
/**
|
171 |
Â
*
|
172 |
Â
* @since 1.15.0
|
173 |
Â
*
|
174 |
+
* @param string $dir
|
175 |
+
*
|
176 |
Â
* @return bool|WP_Error Boolean true on success or a WP_Error object if an error occurs.
|
177 |
Â
*/
|
178 |
Â
public static function remove( $dir ) {
|
179 |
+
$emptied = self::empty_directory( $dir );
|
180 |
+
|
181 |
+
if ( is_wp_error( $emptied ) ) {
|
182 |
+
return $emptied;
|
183 |
+
}
|
184 |
+
|
185 |
+
$result = rmdir( $dir );
|
186 |
+
// phpcs:ignore -- Have Tide ignore the following line. We use arguments that don't exist in early versions, but these versions ignore the arguments.
|
187 |
+
@clearstatcache( true, $dir );
|
188 |
+
|
189 |
+
if ( $result ) {
|
190 |
Â
return true;
|
191 |
Â
}
|
192 |
Â
|
193 |
+
return new WP_Error( 'itsec-lib-directory-remove-unknown-error', sprintf( __( 'Unable to remove %s due to an unknown error.', 'better-wp-security' ), $dir ) );
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Empty a directory of all it's contents, but don't delete the directory.
|
198 |
+
*
|
199 |
+
* @param string $dir
|
200 |
+
*
|
201 |
+
* @return bool|WP_Error
|
202 |
+
*/
|
203 |
+
public static function empty_directory( $dir ) {
|
204 |
+
if ( ! ITSEC_Lib_File::exists( $dir ) ) {
|
205 |
+
return true;
|
206 |
+
}
|
207 |
Â
|
208 |
Â
if ( ! ITSEC_Lib_Utility::is_callable_function( 'rmdir' ) ) {
|
209 |
Â
return new WP_Error( 'itsec-lib-directory-remove-rmdir-is-disabled', sprintf( __( 'The directory %s could not be removed as the rmdir() function is disabled. This is a system configuration issue.', 'better-wp-security' ), $dir ) );
|
210 |
Â
}
|
211 |
Â
|
Â
|
|
212 |
Â
$files = self::read( $dir );
|
213 |
Â
|
214 |
Â
if ( is_wp_error( $files ) ) {
|
223 |
Â
}
|
224 |
Â
}
|
225 |
Â
|
Â
|
|
226 |
Â
// phpcs:ignore -- Have Tide ignore the following line. We use arguments that don't exist in early versions, but these versions ignore the arguments.
|
227 |
Â
@clearstatcache( true, $dir );
|
228 |
Â
|
229 |
+
return true;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
230 |
Â
}
|
231 |
Â
|
232 |
Â
/**
|
core/lib/class-itsec-lib-feature-flags.php
CHANGED
@@ -8,19 +8,43 @@ class ITSEC_Lib_Feature_Flags {
|
|
8 |
Â
/** @var array */
|
9 |
Â
private static $flags = array();
|
10 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
11 |
Â
/**
|
12 |
Â
* Register a feature flag.
|
13 |
Â
*
|
14 |
Â
* @param string $name
|
15 |
Â
* @param array $args
|
Â
|
|
Â
|
|
16 |
Â
*/
|
17 |
Â
public static function register_flag( $name, $args = array() ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
18 |
Â
self::$flags[ $name ] = wp_parse_args( $args, array(
|
19 |
-
'rate'
|
20 |
-
'remote'
|
21 |
-
'title'
|
22 |
-
'description'
|
Â
|
|
23 |
Â
) );
|
Â
|
|
Â
|
|
24 |
Â
}
|
25 |
Â
|
26 |
Â
/**
|
@@ -74,6 +98,10 @@ class ITSEC_Lib_Feature_Flags {
|
|
74 |
Â
return (bool) constant( 'ITSEC_FF_' . $flag );
|
75 |
Â
}
|
76 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
77 |
Â
$flags = ITSEC_Modules::get_setting( 'global', 'feature_flags' );
|
78 |
Â
|
79 |
Â
if ( ! empty( $flags[ $flag ]['enabled'] ) ) {
|
@@ -88,8 +116,8 @@ class ITSEC_Lib_Feature_Flags {
|
|
88 |
Â
return false;
|
89 |
Â
}
|
90 |
Â
|
91 |
-
// If the
|
92 |
-
if ( ! isset( $flags[ $flag ]['rate'] ) || $flags[ $flag ]['rate']
|
93 |
Â
$enabled = mt_rand( 1, 100 ) <= $rate;
|
94 |
Â
|
95 |
Â
$flags[ $flag ] = array(
|
@@ -109,6 +137,35 @@ class ITSEC_Lib_Feature_Flags {
|
|
109 |
Â
return false;
|
110 |
Â
}
|
111 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
112 |
Â
/**
|
113 |
Â
* Manually enable a feature flag.
|
114 |
Â
*
|
@@ -151,7 +208,6 @@ class ITSEC_Lib_Feature_Flags {
|
|
151 |
Â
public static function get_flag_config( $flag ) {
|
152 |
Â
self::load();
|
153 |
Â
|
154 |
-
|
155 |
Â
if ( ! isset( self::$flags[ $flag ] ) ) {
|
156 |
Â
return null;
|
157 |
Â
}
|
8 |
Â
/** @var array */
|
9 |
Â
private static $flags = array();
|
10 |
Â
|
11 |
+
/**
|
12 |
+
* Whether the Feature Flag UI should be displayed.
|
13 |
+
*
|
14 |
+
* @return bool
|
15 |
+
*/
|
16 |
+
public static function show_ui() {
|
17 |
+
$show = count( self::get_enabled() ) > 0;
|
18 |
+
|
19 |
+
if ( defined( 'ITSEC_SHOW_FEATURE_FLAGS' ) ) {
|
20 |
+
$show = ITSEC_SHOW_FEATURE_FLAGS;
|
21 |
+
}
|
22 |
+
|
23 |
+
return apply_filters( 'itsec_show_feature_flags_ui', $show );
|
24 |
+
}
|
25 |
+
|
26 |
Â
/**
|
27 |
Â
* Register a feature flag.
|
28 |
Â
*
|
29 |
Â
* @param string $name
|
30 |
Â
* @param array $args
|
31 |
+
*
|
32 |
+
* @return true|WP_Error
|
33 |
Â
*/
|
34 |
Â
public static function register_flag( $name, $args = array() ) {
|
35 |
+
if ( ! preg_match( '/^[a-zA-Z0-9_]+$/', $name ) ) {
|
36 |
+
return new WP_Error( 'invalid_flag_name', __( 'Invalid flag name.', 'better-wp-security' ) );
|
37 |
+
}
|
38 |
+
|
39 |
Â
self::$flags[ $name ] = wp_parse_args( $args, array(
|
40 |
+
'rate' => false,
|
41 |
+
'remote' => false,
|
42 |
+
'title' => '',
|
43 |
+
'description' => '',
|
44 |
+
'documentation' => '',
|
45 |
Â
) );
|
46 |
+
|
47 |
+
return true;
|
48 |
Â
}
|
49 |
Â
|
50 |
Â
/**
|
98 |
Â
return (bool) constant( 'ITSEC_FF_' . $flag );
|
99 |
Â
}
|
100 |
Â
|
101 |
+
if ( ! empty( $config['disabled'] ) ) {
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
Â
$flags = ITSEC_Modules::get_setting( 'global', 'feature_flags' );
|
106 |
Â
|
107 |
Â
if ( ! empty( $flags[ $flag ]['enabled'] ) ) {
|
116 |
Â
return false;
|
117 |
Â
}
|
118 |
Â
|
119 |
+
// If the dice haven't been rolled, or the rate has changed since the last run, roll the dice.
|
120 |
+
if ( ! isset( $flags[ $flag ]['rate'] ) || $flags[ $flag ]['rate'] < $rate ) {
|
121 |
Â
$enabled = mt_rand( 1, 100 ) <= $rate;
|
122 |
Â
|
123 |
Â
$flags[ $flag ] = array(
|
137 |
Â
return false;
|
138 |
Â
}
|
139 |
Â
|
140 |
+
/**
|
141 |
+
* Get's the reason for the flag being enabled/disabled.
|
142 |
+
*
|
143 |
+
* @param string $flag
|
144 |
+
*
|
145 |
+
* @return array
|
146 |
+
*/
|
147 |
+
public static function get_reason( $flag ) {
|
148 |
+
if ( ! $config = self::get_flag_config( $flag ) ) {
|
149 |
+
return [ 'unknown', __( 'Unknown flag' ) ];
|
150 |
+
}
|
151 |
+
|
152 |
+
if ( defined( 'ITSEC_FF_' . $flag ) ) {
|
153 |
+
return [ 'constant', __( 'Manually configured with a constant.' ) ];
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( ! empty( $config['disabled'] ) ) {
|
157 |
+
return [ 'remote', __( 'Remotely disabled by iThemes.' ) ];
|
158 |
+
}
|
159 |
+
|
160 |
+
$flags = ITSEC_Modules::get_setting( 'global', 'feature_flags' );
|
161 |
+
|
162 |
+
if ( isset( $flags[ $flag ]['rate'] ) ) {
|
163 |
+
return [ 'rollout', __( 'Gradually rolling out.' ) ];
|
164 |
+
}
|
165 |
+
|
166 |
+
return [ 'setting', __( 'Configured in the Feature Flags settings page.' ) ];
|
167 |
+
}
|
168 |
+
|
169 |
Â
/**
|
170 |
Â
* Manually enable a feature flag.
|
171 |
Â
*
|
208 |
Â
public static function get_flag_config( $flag ) {
|
209 |
Â
self::load();
|
210 |
Â
|
Â
|
|
211 |
Â
if ( ! isset( self::$flags[ $flag ] ) ) {
|
212 |
Â
return null;
|
213 |
Â
}
|
core/lib/class-itsec-lib-fingerprinting.php
CHANGED
@@ -1,5 +1,8 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
Â
|
|
3 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint.php' );
|
4 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint-comparison.php' );
|
5 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint-value.php' );
|
@@ -155,15 +158,19 @@ class ITSEC_Lib_Fingerprinting {
|
|
155 |
Â
* @return bool
|
156 |
Â
*/
|
157 |
Â
public static function applies_to_user( $user = false ) {
|
158 |
-
|
159 |
-
if ( ! $role = ITSEC_Modules::get_setting( 'fingerprinting', 'role' ) ) {
|
160 |
Â
return false;
|
161 |
Â
}
|
162 |
Â
|
163 |
-
|
Â
|
|
Â
|
|
164 |
Â
|
165 |
Â
$had_filter = remove_filter( 'user_has_cap', array( 'ITSEC_Fingerprinting', 'restrict_capabilities' ), 10 );
|
166 |
-
|
Â
|
|
Â
|
|
Â
|
|
167 |
Â
|
168 |
Â
if ( $had_filter ) {
|
169 |
Â
add_filter( 'user_has_cap', array( 'ITSEC_Fingerprinting', 'restrict_capabilities' ), 10, 4 );
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups\Matcher;
|
4 |
+
use iThemesSecurity\User_Groups;
|
5 |
+
|
6 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint.php' );
|
7 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint-comparison.php' );
|
8 |
Â
require_once( dirname( __FILE__ ) . '/fingerprinting/class-itsec-fingerprint-value.php' );
|
158 |
Â
* @return bool
|
159 |
Â
*/
|
160 |
Â
public static function applies_to_user( $user = false ) {
|
161 |
+
if ( ! $group = ITSEC_Modules::get_setting( 'fingerprinting', 'group' ) ) {
|
Â
|
|
162 |
Â
return false;
|
163 |
Â
}
|
164 |
Â
|
165 |
+
if ( ! $user = ITSEC_Lib::get_user( $user ) ) {
|
166 |
+
return false;
|
167 |
+
}
|
168 |
Â
|
169 |
Â
$had_filter = remove_filter( 'user_has_cap', array( 'ITSEC_Fingerprinting', 'restrict_capabilities' ), 10 );
|
170 |
+
|
171 |
+
/** @var User_Groups\Matcher $matcher */
|
172 |
+
$matcher = ITSEC_Modules::get_container()->get( Matcher::class );
|
173 |
+
$applies = $matcher->matches( User_Groups\Match_Target::for_user( $user ), $group);
|
174 |
Â
|
175 |
Â
if ( $had_filter ) {
|
176 |
Â
add_filter( 'user_has_cap', array( 'ITSEC_Fingerprinting', 'restrict_capabilities' ), 10, 4 );
|
core/lib/class-itsec-lib-login-interstitial.php
CHANGED
@@ -608,7 +608,9 @@ class ITSEC_Lib_Login_Interstitial {
|
|
608 |
Â
wp_enqueue_script( 'itsec-login-interstitial-util' );
|
609 |
Â
?>
|
610 |
Â
|
611 |
-
<?php if ( $this->error ) : ?>
|
Â
|
|
Â
|
|
612 |
Â
<div id="login-error" class="message" style="border-left-color: #dc3232;">
|
613 |
Â
<?php echo $this->error->get_error_message(); ?>
|
614 |
Â
</div>
|
608 |
Â
wp_enqueue_script( 'itsec-login-interstitial-util' );
|
609 |
Â
?>
|
610 |
Â
|
611 |
+
<?php if ( $this->error && $this->error->get_error_data() === 'message' ) : ?>
|
612 |
+
<p class="message"><?php echo $this->error->get_error_message(); ?></p>
|
613 |
+
<?php elseif ( $this->error ): ?>
|
614 |
Â
<div id="login-error" class="message" style="border-left-color: #dc3232;">
|
615 |
Â
<?php echo $this->error->get_error_message(); ?>
|
616 |
Â
</div>
|
core/lib/class-itsec-lib-password-requirements.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
/**
|
4 |
Â
* Class ITSEC_Lib_Password_Requirements
|
5 |
Â
*/
|
@@ -144,19 +146,25 @@ class ITSEC_Lib_Password_Requirements {
|
|
144 |
Â
return $error;
|
145 |
Â
}
|
146 |
Â
|
147 |
-
|
148 |
Â
|
149 |
Â
if ( isset( $args['role'] ) && $user instanceof WP_User ) {
|
150 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $args['role'], $user );
|
Â
|
|
151 |
Â
} elseif ( isset( $args['role'] ) ) {
|
Â
|
|
152 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $args['role'] );
|
153 |
Â
} elseif ( empty( $user->ID ) || ! is_numeric( $user->ID ) ) {
|
154 |
-
$
|
Â
|
|
Â
|
|
155 |
Â
} else {
|
Â
|
|
156 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_user_role( $user );
|
157 |
Â
}
|
158 |
Â
|
159 |
Â
$args['canonical'] = $canonical;
|
Â
|
|
160 |
Â
|
161 |
Â
/**
|
162 |
Â
* Fires when modules should validate a password according to their rules.
|
@@ -311,4 +319,4 @@ class ITSEC_Lib_Password_Requirements {
|
|
311 |
Â
|
312 |
Â
return wp_parse_args( $settings, $requirements[ $requirement ]['defaults'] );
|
313 |
Â
}
|
314 |
-
}
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
/**
|
6 |
Â
* Class ITSEC_Lib_Password_Requirements
|
7 |
Â
*/
|
146 |
Â
return $error;
|
147 |
Â
}
|
148 |
Â
|
149 |
+
ITSEC_Lib::load( 'canonical-roles' );
|
150 |
Â
|
151 |
Â
if ( isset( $args['role'] ) && $user instanceof WP_User ) {
|
152 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $args['role'], $user );
|
153 |
+
$target = User_Groups\Match_Target::for_user( $user, $args['role'] );
|
154 |
Â
} elseif ( isset( $args['role'] ) ) {
|
155 |
+
$target = User_Groups\Match_Target::for_role( $args['role'] );
|
156 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $args['role'] );
|
157 |
Â
} elseif ( empty( $user->ID ) || ! is_numeric( $user->ID ) ) {
|
158 |
+
$args['role'] = get_option( 'default_role', 'subscriber' );
|
159 |
+
$target = User_Groups\Match_Target::for_role( $args['role'] );
|
160 |
+
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $args['role'] );
|
161 |
Â
} else {
|
162 |
+
$target = User_Groups\Match_Target::for_user( get_userdata( $user->ID ) );
|
163 |
Â
$canonical = ITSEC_Lib_Canonical_Roles::get_user_role( $user );
|
164 |
Â
}
|
165 |
Â
|
166 |
Â
$args['canonical'] = $canonical;
|
167 |
+
$args['target'] = $target;
|
168 |
Â
|
169 |
Â
/**
|
170 |
Â
* Fires when modules should validate a password according to their rules.
|
319 |
Â
|
320 |
Â
return wp_parse_args( $settings, $requirements[ $requirement ]['defaults'] );
|
321 |
Â
}
|
322 |
+
}
|
core/lib/class-itsec-lib-remote-messages.php
CHANGED
@@ -63,33 +63,58 @@ class ITSEC_Lib_Remote_Messages {
|
|
63 |
Â
* @param ITSEC_Job $job
|
64 |
Â
*/
|
65 |
Â
public static function run_event( $job ) {
|
Â
|
|
66 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
67 |
Â
$response = wp_remote_get( self::URL, array(
|
68 |
Â
'user-agent' => 'WordPress',
|
69 |
Â
) );
|
70 |
Â
|
71 |
Â
if ( is_wp_error( $response ) ) {
|
72 |
-
$
|
73 |
-
|
74 |
-
return;
|
75 |
Â
}
|
76 |
Â
|
77 |
Â
$data = wp_remote_retrieve_body( $response );
|
78 |
Â
|
79 |
Â
if ( ! $data ) {
|
80 |
-
|
81 |
-
|
82 |
-
return;
|
83 |
Â
}
|
84 |
Â
|
85 |
Â
$json = json_decode( $data, true );
|
86 |
Â
|
87 |
Â
if ( ! $json ) {
|
88 |
-
|
89 |
-
|
90 |
-
return;
|
91 |
Â
}
|
92 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
93 |
Â
$json = wp_parse_args( $json, array(
|
94 |
Â
'ttl' => HOUR_IN_SECONDS,
|
95 |
Â
'messages' => array(),
|
@@ -99,6 +124,7 @@ class ITSEC_Lib_Remote_Messages {
|
|
99 |
Â
|
100 |
Â
$sanitized = array(
|
101 |
Â
'messages' => array(),
|
Â
|
|
102 |
Â
'actions' => wp_parse_slug_list( $json['actions'] ),
|
103 |
Â
);
|
104 |
Â
|
@@ -110,11 +136,14 @@ class ITSEC_Lib_Remote_Messages {
|
|
110 |
Â
);
|
111 |
Â
}
|
112 |
Â
|
113 |
-
|
114 |
-
'
|
115 |
-
|
116 |
-
|
117 |
-
|
Â
|
|
Â
|
|
Â
|
|
118 |
Â
}
|
119 |
Â
|
120 |
Â
private static function sanitize_message( $message ) {
|
@@ -135,16 +164,25 @@ class ITSEC_Lib_Remote_Messages {
|
|
135 |
Â
return array();
|
136 |
Â
}
|
137 |
Â
|
138 |
-
if ( isset( self::$_response ) ) {
|
139 |
-
|
140 |
Â
}
|
141 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
142 |
Â
$data = self::get_stored_response();
|
143 |
Â
|
144 |
Â
if ( ! $data['response'] ) {
|
145 |
Â
self::schedule_check();
|
146 |
Â
|
147 |
-
return
|
148 |
Â
}
|
149 |
Â
|
150 |
Â
if ( $data['requested'] + $data['ttl'] < ITSEC_Core::get_current_time_gmt() ) {
|
@@ -155,7 +193,7 @@ class ITSEC_Lib_Remote_Messages {
|
|
155 |
Â
// If we are less than an hour late for processing the refresh, return the stale data.
|
156 |
Â
if ( self::EVENT === $event['id'] ) {
|
157 |
Â
if ( $event['fire_at'] + HOUR_IN_SECONDS > ITSEC_Core::get_current_time_gmt() ) {
|
158 |
-
return
|
159 |
Â
}
|
160 |
Â
|
161 |
Â
// If its been more than a day, call the API right now.
|
@@ -164,16 +202,16 @@ class ITSEC_Lib_Remote_Messages {
|
|
164 |
Â
$data = self::get_stored_response();
|
165 |
Â
|
166 |
Â
if ( $data['requested'] === ITSEC_Core::get_current_time_gmt() ) {
|
167 |
-
return
|
168 |
Â
}
|
169 |
Â
}
|
170 |
Â
}
|
171 |
Â
}
|
172 |
Â
|
173 |
-
return
|
174 |
Â
}
|
175 |
Â
|
176 |
-
return
|
177 |
Â
}
|
178 |
Â
|
179 |
Â
private static function get_stored_response() {
|
63 |
Â
* @param ITSEC_Job $job
|
64 |
Â
*/
|
65 |
Â
public static function run_event( $job ) {
|
66 |
+
$fetched = self::fetch();
|
67 |
Â
|
68 |
+
if ( is_wp_error( $fetched ) ) {
|
69 |
+
$job->reschedule_in( 5 * MINUTE_IN_SECONDS );
|
70 |
+
|
71 |
+
return;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Fetches and stores the remote messages response.
|
77 |
+
*
|
78 |
+
* @return null|WP_Error
|
79 |
+
*/
|
80 |
+
public static function fetch() {
|
81 |
Â
$response = wp_remote_get( self::URL, array(
|
82 |
Â
'user-agent' => 'WordPress',
|
83 |
Â
) );
|
84 |
Â
|
85 |
Â
if ( is_wp_error( $response ) ) {
|
86 |
+
return $response;
|
Â
|
|
Â
|
|
87 |
Â
}
|
88 |
Â
|
89 |
Â
$data = wp_remote_retrieve_body( $response );
|
90 |
Â
|
91 |
Â
if ( ! $data ) {
|
92 |
+
return new WP_Error( 'empty_body', __( 'Empty response body.', 'better-wp-security' ) );
|
Â
|
|
Â
|
|
93 |
Â
}
|
94 |
Â
|
95 |
Â
$json = json_decode( $data, true );
|
96 |
Â
|
97 |
Â
if ( ! $json ) {
|
98 |
+
return new WP_Error( 'invalid_json', __( 'Invalid json response.', 'better-wp-security' ) );
|
Â
|
|
Â
|
|
99 |
Â
}
|
100 |
Â
|
101 |
+
update_site_option( self::OPTION, array(
|
102 |
+
'response' => self::sanitize_response( $json ),
|
103 |
+
'ttl' => $json['ttl'],
|
104 |
+
'requested' => ITSEC_Core::get_current_time_gmt(),
|
105 |
+
) );
|
106 |
+
|
107 |
+
return null;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Sanitizes the JSON response.
|
112 |
+
*
|
113 |
+
* @param array $json
|
114 |
+
*
|
115 |
+
* @return array
|
116 |
+
*/
|
117 |
+
public static function sanitize_response( $json ) {
|
118 |
Â
$json = wp_parse_args( $json, array(
|
119 |
Â
'ttl' => HOUR_IN_SECONDS,
|
120 |
Â
'messages' => array(),
|
124 |
Â
|
125 |
Â
$sanitized = array(
|
126 |
Â
'messages' => array(),
|
127 |
+
'features' => array(),
|
128 |
Â
'actions' => wp_parse_slug_list( $json['actions'] ),
|
129 |
Â
);
|
130 |
Â
|
136 |
Â
);
|
137 |
Â
}
|
138 |
Â
|
139 |
+
foreach ( $json['features'] as $feature => $f_config ) {
|
140 |
+
$sanitized['features'][ $feature ] = [
|
141 |
+
'rate' => isset( $f_config['rate'] ) ? (int) $f_config['rate'] : false,
|
142 |
+
'disabled' => ! empty( $f_config['disabled'] ),
|
143 |
+
];
|
144 |
+
}
|
145 |
+
|
146 |
+
return $sanitized;
|
147 |
Â
}
|
148 |
Â
|
149 |
Â
private static function sanitize_message( $message ) {
|
164 |
Â
return array();
|
165 |
Â
}
|
166 |
Â
|
167 |
+
if ( ! isset( self::$_response ) ) {
|
168 |
+
self::$_response = self::load_response();
|
169 |
Â
}
|
170 |
Â
|
171 |
+
return apply_filters( 'itsec_remote_messages', self::$_response );
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Loads the response from the local cache or the server.
|
176 |
+
*
|
177 |
+
* @return array|mixed
|
178 |
+
*/
|
179 |
+
private static function load_response() {
|
180 |
Â
$data = self::get_stored_response();
|
181 |
Â
|
182 |
Â
if ( ! $data['response'] ) {
|
183 |
Â
self::schedule_check();
|
184 |
Â
|
185 |
+
return array();
|
186 |
Â
}
|
187 |
Â
|
188 |
Â
if ( $data['requested'] + $data['ttl'] < ITSEC_Core::get_current_time_gmt() ) {
|
193 |
Â
// If we are less than an hour late for processing the refresh, return the stale data.
|
194 |
Â
if ( self::EVENT === $event['id'] ) {
|
195 |
Â
if ( $event['fire_at'] + HOUR_IN_SECONDS > ITSEC_Core::get_current_time_gmt() ) {
|
196 |
+
return $data['response'];
|
197 |
Â
}
|
198 |
Â
|
199 |
Â
// If its been more than a day, call the API right now.
|
202 |
Â
$data = self::get_stored_response();
|
203 |
Â
|
204 |
Â
if ( $data['requested'] === ITSEC_Core::get_current_time_gmt() ) {
|
205 |
+
return $data['response'];
|
206 |
Â
}
|
207 |
Â
}
|
208 |
Â
}
|
209 |
Â
}
|
210 |
Â
|
211 |
+
return array();
|
212 |
Â
}
|
213 |
Â
|
214 |
+
return $data['response'];
|
215 |
Â
}
|
216 |
Â
|
217 |
Â
private static function get_stored_response() {
|
core/lib/class-itsec-lib-rest.php
ADDED
@@ -0,0 +1,85 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ITSEC_Lib_REST {
|
4 |
+
const LINK_REL = 'https://s.api.ithemes.com/l/ithemes-security/';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Get the URI for an iThemes Security link relation.
|
8 |
+
*
|
9 |
+
* @param string $relation
|
10 |
+
*
|
11 |
+
* @return string
|
12 |
+
*/
|
13 |
+
public static function get_link_relation( $relation ) {
|
14 |
+
return self::LINK_REL . $relation;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Converts an error to a response object.
|
19 |
+
*
|
20 |
+
* This iterates over all error codes and messages to change it into a flat
|
21 |
+
* array. This enables simpler client behaviour, as it is represented as a
|
22 |
+
* list in JSON rather than an object/map.
|
23 |
+
*
|
24 |
+
* {@see WP_REST_Server::error_to_response()}
|
25 |
+
*
|
26 |
+
* @param WP_Error $error WP_Error instance.
|
27 |
+
*
|
28 |
+
* @return WP_REST_Response List of associative arrays with code and message keys.
|
29 |
+
*/
|
30 |
+
public static function error_to_response( WP_Error $error ) {
|
31 |
+
$error_data = $error->get_error_data();
|
32 |
+
|
33 |
+
if ( is_array( $error_data ) && isset( $error_data['status'] ) ) {
|
34 |
+
$status = $error_data['status'];
|
35 |
+
} else {
|
36 |
+
$status = 500;
|
37 |
+
}
|
38 |
+
|
39 |
+
$errors = array();
|
40 |
+
|
41 |
+
foreach ( (array) $error->errors as $code => $messages ) {
|
42 |
+
foreach ( (array) $messages as $message ) {
|
43 |
+
$errors[] = array(
|
44 |
+
'code' => $code,
|
45 |
+
'message' => $message,
|
46 |
+
'data' => $error->get_error_data( $code ),
|
47 |
+
);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
$data = $errors[0];
|
52 |
+
if ( count( $errors ) > 1 ) {
|
53 |
+
// Remove the primary error.
|
54 |
+
array_shift( $errors );
|
55 |
+
$data['additional_errors'] = $errors;
|
56 |
+
}
|
57 |
+
|
58 |
+
return new WP_REST_Response( $data, $status );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Get the status code to send from the list of statuses.
|
63 |
+
*
|
64 |
+
* @param int ...$statuses
|
65 |
+
*
|
66 |
+
* @return int
|
67 |
+
*/
|
68 |
+
public static function get_status( ...$statuses ) {
|
69 |
+
if ( ! $statuses ) {
|
70 |
+
return 200;
|
71 |
+
}
|
72 |
+
|
73 |
+
$prev = $statuses[0];
|
74 |
+
|
75 |
+
foreach ( $statuses as $status ) {
|
76 |
+
if ( $prev !== $status ) {
|
77 |
+
return WP_Http::MULTI_STATUS;
|
78 |
+
}
|
79 |
+
|
80 |
+
$prev = $status;
|
81 |
+
}
|
82 |
+
|
83 |
+
return $prev;
|
84 |
+
}
|
85 |
+
}
|
core/lib/class-itsec-mutex.php
ADDED
@@ -0,0 +1,153 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class ITSEC_Mutex {
|
4 |
+
/** @var int */
|
5 |
+
private $id;
|
6 |
+
|
7 |
+
/** @var string */
|
8 |
+
private $name;
|
9 |
+
|
10 |
+
/** @var int */
|
11 |
+
private $expires;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* ITSEC_Mutex constructor.
|
15 |
+
*
|
16 |
+
* @param int $id
|
17 |
+
* @param string $name
|
18 |
+
* @param int $expires
|
19 |
+
*/
|
20 |
+
private function __construct( $id, $name, $expires ) {
|
21 |
+
$this->id = $id;
|
22 |
+
$this->name = $name;
|
23 |
+
$this->expires = $expires;
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Get a mutex.
|
28 |
+
*
|
29 |
+
* @param string $name Name of the mutex.
|
30 |
+
* @param int $ttl How long to hold the mutex for.
|
31 |
+
*
|
32 |
+
* @return ITSEC_Mutex|null Returns null if the mutex is already being held.
|
33 |
+
*/
|
34 |
+
public static function get( $name, $ttl = 30 ) {
|
35 |
+
global $wpdb;
|
36 |
+
|
37 |
+
$expires_at = time() + $ttl;
|
38 |
+
|
39 |
+
while ( ! $id = self::create( $name, $expires_at ) ) {
|
40 |
+
$existing = $wpdb->get_row( $wpdb->prepare(
|
41 |
+
"SELECT `mutex_id`, `mutex_expires` FROM `{$wpdb->base_prefix}itsec_mutexes` WHERE `mutex_name` = %s",
|
42 |
+
$name
|
43 |
+
), ARRAY_A );
|
44 |
+
|
45 |
+
if ( ! $existing ) {
|
46 |
+
continue;
|
47 |
+
}
|
48 |
+
|
49 |
+
if ( $existing['mutex_expires'] < time() ) {
|
50 |
+
self::delete_by_id( $existing['mutex_id'] );
|
51 |
+
continue;
|
52 |
+
}
|
53 |
+
|
54 |
+
return null;
|
55 |
+
}
|
56 |
+
|
57 |
+
return new self( $wpdb->insert_id, $name, $expires_at );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Release the mutex back.
|
62 |
+
*/
|
63 |
+
public function release() {
|
64 |
+
self::delete_by_id( $this->get_id() );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Has the mutex expired.
|
69 |
+
*
|
70 |
+
* @return bool
|
71 |
+
*/
|
72 |
+
public function is_expired() {
|
73 |
+
return $this->get_expires() < time();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Checks if this mutex still exists.
|
78 |
+
*
|
79 |
+
* @return bool
|
80 |
+
*/
|
81 |
+
public function exists() {
|
82 |
+
global $wpdb;
|
83 |
+
|
84 |
+
return (bool) $wpdb->get_var( $wpdb->prepare(
|
85 |
+
"SELECT `mutex_id` FROM {$wpdb->base_prefix}itsec_mutexes WHERE `mutex_id` = %d",
|
86 |
+
$this->get_id()
|
87 |
+
) );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get the mutex's id.
|
92 |
+
*
|
93 |
+
* @return int
|
94 |
+
*/
|
95 |
+
public function get_id() {
|
96 |
+
return $this->id;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Get the name of the mutex.
|
101 |
+
*
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
public function get_name() {
|
105 |
+
return $this->name;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Get the epoch the mutex expires at.
|
110 |
+
*
|
111 |
+
* @return int
|
112 |
+
*/
|
113 |
+
public function get_expires() {
|
114 |
+
return $this->expires;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Delete a mutex by it's id.
|
119 |
+
*
|
120 |
+
* @param string $id
|
121 |
+
*/
|
122 |
+
private static function delete_by_id( $id ) {
|
123 |
+
global $wpdb;
|
124 |
+
|
125 |
+
$wpdb->delete( $wpdb->base_prefix . 'itsec_mutexes', [
|
126 |
+
'mutex_id' => $id,
|
127 |
+
] );
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Create a mutex record.
|
132 |
+
*
|
133 |
+
* @param string $name
|
134 |
+
* @param int $expires_at
|
135 |
+
*
|
136 |
+
* @return int The mutex id, or 0 if it could not be acquired.
|
137 |
+
*/
|
138 |
+
private static function create( $name, $expires_at ) {
|
139 |
+
global $wpdb;
|
140 |
+
|
141 |
+
$r = $wpdb->query( $wpdb->prepare(
|
142 |
+
"INSERT IGNORE INTO `{$wpdb->base_prefix}itsec_mutexes` (`mutex_name`, `mutex_expires`) VALUES (%s, %s) /* LOCK */",
|
143 |
+
$name,
|
144 |
+
$expires_at
|
145 |
+
) );
|
146 |
+
|
147 |
+
if ( ! $r || ! $wpdb->insert_id ) {
|
148 |
+
return 0;
|
149 |
+
}
|
150 |
+
|
151 |
+
return (int) $wpdb->insert_id;
|
152 |
+
}
|
153 |
+
}
|
core/lib/class-itsec-scheduler.php
CHANGED
@@ -372,4 +372,15 @@ abstract class ITSEC_Scheduler {
|
|
372 |
Â
public function uninstall() {
|
373 |
Â
|
374 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
375 |
Â
}
|
372 |
Â
public function uninstall() {
|
373 |
Â
|
374 |
Â
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Reset the scheduler.
|
378 |
+
*
|
379 |
+
* This unregisters all events, and re-registers them.
|
380 |
+
*/
|
381 |
+
public function reset() {
|
382 |
+
$this->uninstall();
|
383 |
+
$this->run();
|
384 |
+
$this->register_events();
|
385 |
+
}
|
386 |
Â
}
|
core/lib/form.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
final class ITSEC_Form {
|
4 |
Â
private $options = array();
|
5 |
Â
private $tracked_booleans = array();
|
@@ -8,7 +10,6 @@ final class ITSEC_Form {
|
|
8 |
Â
private $input_group = '';
|
9 |
Â
private $input_group_stack = array();
|
10 |
Â
|
11 |
-
|
12 |
Â
public function __construct( $options = array() ) {
|
13 |
Â
$this->options =& $options;
|
14 |
Â
}
|
@@ -27,10 +28,6 @@ final class ITSEC_Form {
|
|
27 |
Â
parse_str( $data['data']['--itsec-form-serialized-data'], $data );
|
28 |
Â
}
|
29 |
Â
|
30 |
-
if ( get_magic_quotes_gpc() ) {
|
31 |
-
$data = stripslashes_deep( $data );
|
32 |
-
}
|
33 |
-
|
34 |
Â
$defaults = array(
|
35 |
Â
'booleans' => false,
|
36 |
Â
'strings' => '',
|
@@ -493,6 +490,54 @@ final class ITSEC_Form {
|
|
493 |
Â
$this->add_select( $var, $options );
|
494 |
Â
}
|
495 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
496 |
Â
public function get_clean_var( $var ) {
|
497 |
Â
$clean_var = trim( preg_replace( '/[^a-z0-9_]+/i', '-', $var ), '-' );
|
498 |
Â
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups\Matchables_Source;
|
4 |
+
|
5 |
Â
final class ITSEC_Form {
|
6 |
Â
private $options = array();
|
7 |
Â
private $tracked_booleans = array();
|
10 |
Â
private $input_group = '';
|
11 |
Â
private $input_group_stack = array();
|
12 |
Â
|
Â
|
|
13 |
Â
public function __construct( $options = array() ) {
|
14 |
Â
$this->options =& $options;
|
15 |
Â
}
|
28 |
Â
parse_str( $data['data']['--itsec-form-serialized-data'], $data );
|
29 |
Â
}
|
30 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
31 |
Â
$defaults = array(
|
32 |
Â
'booleans' => false,
|
33 |
Â
'strings' => '',
|
490 |
Â
$this->add_select( $var, $options );
|
491 |
Â
}
|
492 |
Â
|
493 |
+
public function add_user_group( $var, $options = array() ) {
|
494 |
+
$source = ITSEC_Modules::get_container()->get( Matchables_Source::class );
|
495 |
+
|
496 |
+
$user_groups = [];
|
497 |
+
foreach ( $source->all() as $matchable ) {
|
498 |
+
$user_groups[ $matchable->get_id() ] = $matchable->get_label();
|
499 |
+
}
|
500 |
+
|
501 |
+
if ( isset( $options['value'] ) ) {
|
502 |
+
$options['value'] = wp_parse_args( $options['value'], $user_groups );
|
503 |
+
} else {
|
504 |
+
$options['value'] = $user_groups;
|
505 |
+
}
|
506 |
+
|
507 |
+
$this->add_select( $var, $options );
|
508 |
+
}
|
509 |
+
|
510 |
+
public function add_user_groups( $var, $module, $setting = '', $options = array() ) {
|
511 |
+
$source = ITSEC_Modules::get_container()->get( Matchables_Source::class );
|
512 |
+
|
513 |
+
$user_groups = [];
|
514 |
+
foreach ( $source->all() as $matchable ) {
|
515 |
+
$user_groups[ $matchable->get_id() ] = $matchable->get_label();
|
516 |
+
}
|
517 |
+
|
518 |
+
if ( isset( $options['value'] ) ) {
|
519 |
+
$options['value'] = wp_parse_args( $options['value'], $user_groups );
|
520 |
+
} else {
|
521 |
+
$options['value'] = $user_groups;
|
522 |
+
}
|
523 |
+
|
524 |
+
$options['data-module'] = $module;
|
525 |
+
$options['data-setting'] = $setting ?: $var;
|
526 |
+
|
527 |
+
$options['class'] = 'itsec-form-input--type-user-groups';
|
528 |
+
|
529 |
+
$this->add_multi_select( $var, $options );
|
530 |
+
wp_enqueue_script( 'itsec-form-user-groups' );
|
531 |
+
wp_enqueue_style( 'itsec-jquery-multi-select' );
|
532 |
+
}
|
533 |
+
|
534 |
+
public function get_dotted_var( $var ) {
|
535 |
+
$dot = $this->input_group_stack;
|
536 |
+
$dot[] = $var;
|
537 |
+
|
538 |
+
return implode( '.', $dot );
|
539 |
+
}
|
540 |
+
|
541 |
Â
public function get_clean_var( $var ) {
|
542 |
Â
$clean_var = trim( preg_replace( '/[^a-z0-9_]+/i', '-', $var ), '-' );
|
543 |
Â
|
core/lib/lock.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
final class ITSEC_Lock {
|
4 |
-
public static function get( $name, $expiration = HOUR_IN_SECONDS, $allow_api_request = false ) {
|
5 |
-
global $wpdb;
|
6 |
-
|
7 |
-
if ( ! $allow_api_request && ITSEC_Core::is_api_request() ) {
|
8 |
-
return false;
|
9 |
-
}
|
10 |
-
|
11 |
-
$lock = "itsec-lock-$name";
|
12 |
-
$now = time();
|
13 |
-
|
14 |
-
if ( ! empty( $wpdb->sitemeta ) ) {
|
15 |
-
$result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->sitemeta` (`site_id`, `meta_key`, `meta_value`) VALUES (%d, %s, %s) /* LOCK */", $wpdb->siteid, $lock, $now ) );
|
16 |
-
} else {
|
17 |
-
$result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no') /* LOCK */", $lock, $now ) );
|
18 |
-
}
|
19 |
-
|
20 |
-
if ( ! $result ) {
|
21 |
-
// The lock exists. See if it has expired.
|
22 |
-
|
23 |
-
$locked = get_site_option( $lock );
|
24 |
-
|
25 |
-
if ( ! $locked ) {
|
26 |
-
// Can't write or read the lock. Bail due to an unknown and hopefully temporary error.
|
27 |
-
return false;
|
28 |
-
}
|
29 |
-
|
30 |
-
if ( $locked > $now - $expiration ) {
|
31 |
-
// The lock still exists and has not expired.
|
32 |
-
return false;
|
33 |
-
}
|
34 |
-
}
|
35 |
-
|
36 |
-
// Ensure that the lock is set properly by triggering all the regular actions and filters.
|
37 |
-
update_site_option( $lock, $now );
|
38 |
-
|
39 |
-
return true;
|
40 |
-
}
|
41 |
-
|
42 |
-
public static function remove( $name ) {
|
43 |
-
$lock = "itsec-lock-$name";
|
44 |
-
|
45 |
-
delete_site_option( $lock );
|
46 |
-
}
|
47 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
core/lib/log-util.php
CHANGED
@@ -4,19 +4,24 @@ final class ITSEC_Log_Util {
|
|
4 |
Â
public static function get_type_counts( $min_timestamp = 0 ) {
|
5 |
Â
global $wpdb;
|
6 |
Â
|
7 |
-
|
8 |
-
$
|
9 |
-
$prepare_args = array();
|
10 |
Â
|
11 |
Â
if ( $min_timestamp > 0 ) {
|
12 |
-
$where
|
13 |
-
$
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
14 |
Â
}
|
15 |
Â
|
16 |
-
$query = "SELECT type, COUNT(*) AS count FROM `{$wpdb->base_prefix}itsec_logs`
|
17 |
Â
|
18 |
-
if ( ! empty( $
|
19 |
-
$query = $wpdb->prepare( $query, $
|
20 |
Â
}
|
21 |
Â
|
22 |
Â
$results = $wpdb->get_results( $query, ARRAY_A );
|
@@ -38,6 +43,34 @@ final class ITSEC_Log_Util {
|
|
38 |
Â
return $counts;
|
39 |
Â
}
|
40 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
41 |
Â
public static function get_entries( $filters = array(), $limit = 100, $page = 1, $sort_by_column = 'timestamp', $sort_direction = 'DESC', $columns = false ) {
|
42 |
Â
global $wpdb;
|
43 |
Â
|
@@ -124,10 +157,6 @@ final class ITSEC_Log_Util {
|
|
124 |
Â
|
125 |
Â
$where_entries = array();
|
126 |
Â
|
127 |
-
if ( ! isset( $filters['parent_id'] ) ) {
|
128 |
-
$filters['parent_id'] = 0;
|
129 |
-
}
|
130 |
-
|
131 |
Â
foreach ( (array) $filters as $column => $value ) {
|
132 |
Â
if ( preg_match( '/^(.+)_not$/', $column, $match ) ) {
|
133 |
Â
$not = true;
|
@@ -186,8 +215,9 @@ final class ITSEC_Log_Util {
|
|
186 |
Â
$prepare_args[] = date( 'Y-m-d H:i:s', $max_timestamp );
|
187 |
Â
}
|
188 |
Â
|
189 |
-
|
190 |
-
|
Â
|
|
191 |
Â
|
192 |
Â
if ( ! $get_count ) {
|
193 |
Â
if ( ! is_array( $sort_by_column ) ) {
|
@@ -203,8 +233,9 @@ final class ITSEC_Log_Util {
|
|
203 |
Â
}
|
204 |
Â
}
|
205 |
Â
|
206 |
-
|
207 |
-
|
Â
|
|
208 |
Â
|
209 |
Â
if ( $get_count ) {
|
210 |
Â
return intval( $wpdb->get_var( $query ) );
|
4 |
Â
public static function get_type_counts( $min_timestamp = 0 ) {
|
5 |
Â
global $wpdb;
|
6 |
Â
|
7 |
+
$where = [];
|
8 |
+
$prepare = [];
|
Â
|
|
9 |
Â
|
10 |
Â
if ( $min_timestamp > 0 ) {
|
11 |
+
$where[] = 'init_timestamp > %s';
|
12 |
+
$prepare[] = date( 'Y-m-d H:i:s', $min_timestamp );
|
13 |
+
}
|
14 |
+
|
15 |
+
if ( $where ) {
|
16 |
+
$where = 'WHERE ' . implode( ' AND ', $where );
|
17 |
+
} else {
|
18 |
+
$where = '';
|
19 |
Â
}
|
20 |
Â
|
21 |
+
$query = "SELECT type, COUNT(*) AS count FROM `{$wpdb->base_prefix}itsec_logs` {$where} GROUP BY type";
|
22 |
Â
|
23 |
+
if ( ! empty( $prepare ) ) {
|
24 |
+
$query = $wpdb->prepare( $query, $prepare );
|
25 |
Â
}
|
26 |
Â
|
27 |
Â
$results = $wpdb->get_results( $query, ARRAY_A );
|
43 |
Â
return $counts;
|
44 |
Â
}
|
45 |
Â
|
46 |
+
public static function get_modules() {
|
47 |
+
global $wpdb;
|
48 |
+
|
49 |
+
$items = $wpdb->get_col( "SELECT DISTINCT module FROM {$wpdb->base_prefix}itsec_logs" );
|
50 |
+
|
51 |
+
if ( ! is_array( $items ) ) {
|
52 |
+
return array();
|
53 |
+
}
|
54 |
+
|
55 |
+
$modules = array();
|
56 |
+
|
57 |
+
foreach ( $items as $module_slug ) {
|
58 |
+
$labels = ITSEC_Modules::get_labels( $module_slug );
|
59 |
+
|
60 |
+
if ( ! $labels ) {
|
61 |
+
$labels = ITSEC_Modules::get_labels( str_replace( '_', '-', $module_slug ) );
|
62 |
+
}
|
63 |
+
|
64 |
+
if ( $labels ) {
|
65 |
+
$modules[ $module_slug ] = $labels['title'];
|
66 |
+
} else {
|
67 |
+
$modules[ $module_slug ] = $module_slug;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
return $modules;
|
72 |
+
}
|
73 |
+
|
74 |
Â
public static function get_entries( $filters = array(), $limit = 100, $page = 1, $sort_by_column = 'timestamp', $sort_direction = 'DESC', $columns = false ) {
|
75 |
Â
global $wpdb;
|
76 |
Â
|
157 |
Â
|
158 |
Â
$where_entries = array();
|
159 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
160 |
Â
foreach ( (array) $filters as $column => $value ) {
|
161 |
Â
if ( preg_match( '/^(.+)_not$/', $column, $match ) ) {
|
162 |
Â
$not = true;
|
215 |
Â
$prepare_args[] = date( 'Y-m-d H:i:s', $max_timestamp );
|
216 |
Â
}
|
217 |
Â
|
218 |
+
if ( $where_entries ) {
|
219 |
+
$query .= ' WHERE ' . implode( ' AND ', $where_entries );
|
220 |
+
}
|
221 |
Â
|
222 |
Â
if ( ! $get_count ) {
|
223 |
Â
if ( ! is_array( $sort_by_column ) ) {
|
233 |
Â
}
|
234 |
Â
}
|
235 |
Â
|
236 |
+
if ( $prepare_args ) {
|
237 |
+
$query = $wpdb->prepare( $query, $prepare_args );
|
238 |
+
}
|
239 |
Â
|
240 |
Â
if ( $get_count ) {
|
241 |
Â
return intval( $wpdb->get_var( $query ) );
|
core/lib/log.php
CHANGED
@@ -245,6 +245,8 @@ final class ITSEC_Log {
|
|
245 |
Â
'notice' => esc_html__( 'Notice', 'better-wp-security' ),
|
246 |
Â
'debug' => esc_html__( 'Debug', 'better-wp-security' ),
|
247 |
Â
'process-start' => esc_html__( 'Process', 'better-wp-security' ),
|
Â
|
|
Â
|
|
248 |
Â
);
|
249 |
Â
}
|
250 |
Â
|
245 |
Â
'notice' => esc_html__( 'Notice', 'better-wp-security' ),
|
246 |
Â
'debug' => esc_html__( 'Debug', 'better-wp-security' ),
|
247 |
Â
'process-start' => esc_html__( 'Process', 'better-wp-security' ),
|
248 |
+
'process-update' => esc_html__( 'Process Update', 'better-wp-security' ),
|
249 |
+
'process-stop' => esc_html__( 'Process Stop', 'better-wp-security' ),
|
250 |
Â
);
|
251 |
Â
}
|
252 |
Â
|
core/lib/login-interstitial/class-itsec-login-interstitial-session.php
CHANGED
@@ -183,6 +183,44 @@ class ITSEC_Login_Interstitial_Session {
|
|
183 |
Â
return $this;
|
184 |
Â
}
|
185 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
186 |
Â
/**
|
187 |
Â
* Verify the session.
|
188 |
Â
*
|
@@ -407,6 +445,8 @@ class ITSEC_Login_Interstitial_Session {
|
|
407 |
Â
if ( ! empty( $_REQUEST['rememberme'] ) ) {
|
408 |
Â
$this->set_remember_me();
|
409 |
Â
}
|
Â
|
|
Â
|
|
410 |
Â
}
|
411 |
Â
|
412 |
Â
/**
|
@@ -471,7 +511,7 @@ class ITSEC_Login_Interstitial_Session {
|
|
471 |
Â
public static function create( WP_User $user, $current = '' ) {
|
472 |
Â
$log = ITSEC_Log::add_process_start( 'login-interstitial', 'create', [
|
473 |
Â
'current' => $current,
|
474 |
-
'_server' =>
|
475 |
Â
], [ 'user_id' => $user->ID ] );
|
476 |
Â
|
477 |
Â
$data = array(
|
@@ -484,6 +524,7 @@ class ITSEC_Login_Interstitial_Session {
|
|
484 |
Â
'remember_me' => false,
|
485 |
Â
'interim_login' => false,
|
486 |
Â
'state' => array(),
|
Â
|
|
487 |
Â
'log' => $log,
|
488 |
Â
);
|
489 |
Â
|
183 |
Â
return $this;
|
184 |
Â
}
|
185 |
Â
|
186 |
+
/**
|
187 |
+
* Get a meta value by key.
|
188 |
+
*
|
189 |
+
* @param string $key
|
190 |
+
*
|
191 |
+
* @return mixed|null The meta value, or null if the meta key does not exist.
|
192 |
+
*/
|
193 |
+
public function get_meta( $key ) {
|
194 |
+
return isset( $this->data['meta'][ $key ] ) ? $this->data['meta'][ $key ] : null;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Set meta key-value pair.
|
199 |
+
*
|
200 |
+
* @param string $key The meta key to set the value for.
|
201 |
+
* @param mixed $value The value to set. Must be serializable.
|
202 |
+
*
|
203 |
+
* @return $this
|
204 |
+
*/
|
205 |
+
public function set_meta( $key, $value ) {
|
206 |
+
$this->data['meta'][ $key ] = $value;
|
207 |
+
|
208 |
+
return $this;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Remove a meta value by key.
|
213 |
+
*
|
214 |
+
* @param string $key
|
215 |
+
*
|
216 |
+
* @return $this
|
217 |
+
*/
|
218 |
+
public function remove_meta( $key ) {
|
219 |
+
unset( $this->data['meta'][ $key ] );
|
220 |
+
|
221 |
+
return $this;
|
222 |
+
}
|
223 |
+
|
224 |
Â
/**
|
225 |
Â
* Verify the session.
|
226 |
Â
*
|
445 |
Â
if ( ! empty( $_REQUEST['rememberme'] ) ) {
|
446 |
Â
$this->set_remember_me();
|
447 |
Â
}
|
448 |
+
|
449 |
+
do_action( 'itsec_initialize_login_interstitial_session_from_global_state', $this );
|
450 |
Â
}
|
451 |
Â
|
452 |
Â
/**
|
511 |
Â
public static function create( WP_User $user, $current = '' ) {
|
512 |
Â
$log = ITSEC_Log::add_process_start( 'login-interstitial', 'create', [
|
513 |
Â
'current' => $current,
|
514 |
+
'_server' => ITSEC_Lib::get_server_snapshot(),
|
515 |
Â
], [ 'user_id' => $user->ID ] );
|
516 |
Â
|
517 |
Â
$data = array(
|
524 |
Â
'remember_me' => false,
|
525 |
Â
'interim_login' => false,
|
526 |
Â
'state' => array(),
|
527 |
+
'meta' => array(),
|
528 |
Â
'log' => $log,
|
529 |
Â
);
|
530 |
Â
|
core/lib/mail-templates/small-code.html
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
Â
<td class="section-padding" align="center" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;padding-top: 10px;padding-right: 20px;padding-left: 20px;">
|
9 |
Â
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
|
10 |
Â
<tr>
|
11 |
-
<td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #545454;font-family: monospace;font-size: 16px;font-weight: bolder;line-height: 150%;text-align: center;padding-bottom: 10px;">
|
12 |
Â
{{ $content }}
|
13 |
Â
</td>
|
14 |
Â
</tr>
|
8 |
Â
<td class="section-padding" align="center" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;padding-top: 10px;padding-right: 20px;padding-left: 20px;">
|
9 |
Â
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
|
10 |
Â
<tr>
|
11 |
+
<td class="container-cell small-code" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #545454;font-family: monospace;font-size: 16px;font-weight: bolder;line-height: 150%;text-align: center;padding-bottom: 10px;">
|
12 |
Â
{{ $content }}
|
13 |
Â
</td>
|
14 |
Â
</tr>
|
core/lib/schema.php
CHANGED
@@ -1,6 +1,18 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
final class ITSEC_Schema {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
4 |
Â
/**
|
5 |
Â
* Creates appropriate database tables.
|
6 |
Â
*
|
@@ -8,7 +20,7 @@ final class ITSEC_Schema {
|
|
8 |
Â
*
|
9 |
Â
* @since 3.9.0
|
10 |
Â
*
|
11 |
-
* @return
|
12 |
Â
*/
|
13 |
Â
public static function create_database_tables() {
|
14 |
Â
global $wpdb;
|
@@ -36,6 +48,7 @@ CREATE TABLE {$wpdb->base_prefix}itsec_logs (
|
|
36 |
Â
KEY code (code),
|
37 |
Â
KEY type (type),
|
38 |
Â
KEY timestamp (timestamp),
|
Â
|
|
39 |
Â
KEY user_id (user_id),
|
40 |
Â
KEY blog_id (blog_id)
|
41 |
Â
) $charset_collate;
|
@@ -125,10 +138,51 @@ CREATE TABLE {$wpdb->base_prefix}itsec_opaque_tokens (
|
|
125 |
Â
PRIMARY KEY (token_id),
|
126 |
Â
UNIQUE KEY token_hashed (token_hashed)
|
127 |
Â
) $charset_collate;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
128 |
Â
";
|
129 |
Â
|
130 |
-
|
131 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
132 |
Â
}
|
133 |
Â
|
134 |
Â
public static function remove_database_tables() {
|
@@ -141,5 +195,7 @@ CREATE TABLE {$wpdb->base_prefix}itsec_opaque_tokens (
|
|
141 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_distributed_storage;" );
|
142 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_geolocation_cache;" );
|
143 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_fingerprints;" );
|
Â
|
|
Â
|
|
144 |
Â
}
|
145 |
Â
}
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
final class ITSEC_Schema {
|
4 |
+
const TABLES = [
|
5 |
+
'itsec_logs',
|
6 |
+
'itsec_lockouts',
|
7 |
+
'itsec_temp',
|
8 |
+
'itsec_distributed_storage',
|
9 |
+
'itsec_geolocation_cache',
|
10 |
+
'itsec_fingerprints',
|
11 |
+
'itsec_opaque_tokens',
|
12 |
+
'itsec_user_groups',
|
13 |
+
'itsec_mutexes',
|
14 |
+
];
|
15 |
+
|
16 |
Â
/**
|
17 |
Â
* Creates appropriate database tables.
|
18 |
Â
*
|
20 |
Â
*
|
21 |
Â
* @since 3.9.0
|
22 |
Â
*
|
23 |
+
* @return true|WP_Error
|
24 |
Â
*/
|
25 |
Â
public static function create_database_tables() {
|
26 |
Â
global $wpdb;
|
48 |
Â
KEY code (code),
|
49 |
Â
KEY type (type),
|
50 |
Â
KEY timestamp (timestamp),
|
51 |
+
KEY init_timestamp (init_timestamp),
|
52 |
Â
KEY user_id (user_id),
|
53 |
Â
KEY blog_id (blog_id)
|
54 |
Â
) $charset_collate;
|
138 |
Â
PRIMARY KEY (token_id),
|
139 |
Â
UNIQUE KEY token_hashed (token_hashed)
|
140 |
Â
) $charset_collate;
|
141 |
+
|
142 |
+
CREATE TABLE {$wpdb->base_prefix}itsec_user_groups (
|
143 |
+
group_id char(36) NOT NULL,
|
144 |
+
group_label varchar(255) NOT NULL default '',
|
145 |
+
group_roles TEXT,
|
146 |
+
group_canonical TEXT,
|
147 |
+
group_users TEXT,
|
148 |
+
group_min_role varchar(255),
|
149 |
+
group_created_at DATETIME,
|
150 |
+
PRIMARY KEY (group_id)
|
151 |
+
) $charset_collate;
|
152 |
+
|
153 |
+
CREATE TABLE {$wpdb->base_prefix}itsec_mutexes (
|
154 |
+
mutex_id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
155 |
+
mutex_name varchar(100) NOT NULL,
|
156 |
+
mutex_expires int(11) UNSIGNED NOT NULL,
|
157 |
+
PRIMARY KEY (mutex_id),
|
158 |
+
UNIQUE KEY mutex_name (mutex_name)
|
159 |
+
) $charset_collate;
|
160 |
Â
";
|
161 |
Â
|
162 |
+
$wp_error = new WP_Error();
|
163 |
+
ITSEC_Lib::add_to_wp_error( $wp_error, ITSEC_Lib::db_delta_with_error_handling( $tables ) );
|
164 |
+
|
165 |
+
foreach ( self::TABLES as $table ) {
|
166 |
+
if ( ! count( $wpdb->get_results( "SHOW TABLES LIKE '{$wpdb->base_prefix}{$table}'" ) ) ) {
|
167 |
+
$wp_error->add(
|
168 |
+
'missing_table',
|
169 |
+
sprintf( __( 'The %s table is not installed.', 'better-wp-security' ), $table )
|
170 |
+
);
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Fires when the DB schema is installed or updated.
|
176 |
+
*
|
177 |
+
* @param WP_Error $wp_error
|
178 |
+
*/
|
179 |
+
do_action( 'itsec_install_schema', $wp_error );
|
180 |
+
|
181 |
+
if ( $wp_error->has_errors() ) {
|
182 |
+
return $wp_error;
|
183 |
+
}
|
184 |
+
|
185 |
+
return true;
|
186 |
Â
}
|
187 |
Â
|
188 |
Â
public static function remove_database_tables() {
|
195 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_distributed_storage;" );
|
196 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_geolocation_cache;" );
|
197 |
Â
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_fingerprints;" );
|
198 |
+
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_user_groups;" );
|
199 |
+
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->base_prefix}itsec_mutexes;" );
|
200 |
Â
}
|
201 |
Â
}
|
core/lib/settings.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
abstract class ITSEC_Settings {
|
4 |
Â
protected $settings;
|
5 |
Â
|
@@ -12,7 +14,24 @@ abstract class ITSEC_Settings {
|
|
12 |
Â
abstract public function get_id();
|
13 |
Â
abstract public function get_defaults();
|
14 |
Â
protected function after_save() {}
|
15 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
16 |
Â
|
17 |
Â
public function export() {
|
18 |
Â
return $this->settings;
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
abstract class ITSEC_Settings {
|
6 |
Â
protected $settings;
|
7 |
Â
|
14 |
Â
abstract public function get_id();
|
15 |
Â
abstract public function get_defaults();
|
16 |
Â
protected function after_save() {}
|
17 |
+
|
18 |
+
protected function handle_settings_changes( $old_settings ) {
|
19 |
+
$user_group_settings = ITSEC_Modules::get_container()->get( User_Groups\Settings_Registry::class );
|
20 |
+
|
21 |
+
foreach ( $user_group_settings->get_settings() as $user_group_setting ) {
|
22 |
+
if ( $user_group_setting->get_module() !== $this->get_id() ) {
|
23 |
+
continue;
|
24 |
+
}
|
25 |
+
|
26 |
+
$current = ITSEC_Lib::array_get( $this->settings, $user_group_setting->get_setting() );
|
27 |
+
$previous = ITSEC_Lib::array_get( $old_settings, $user_group_setting->get_setting() );
|
28 |
+
|
29 |
+
if ( $previous !== $current ) {
|
30 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/user-groups', 'fetchGroupsSettings' );
|
31 |
+
break;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
}
|
35 |
Â
|
36 |
Â
public function export() {
|
37 |
Â
return $this->settings;
|
core/lib/validator.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
abstract class ITSEC_Validator {
|
4 |
Â
protected $run_validate_matching_fields = true;
|
5 |
Â
protected $run_validate_matching_types = true;
|
@@ -28,11 +30,13 @@ abstract class ITSEC_Validator {
|
|
28 |
Â
}
|
29 |
Â
|
30 |
Â
abstract public function get_id();
|
31 |
-
|
32 |
-
protected function
|
Â
|
|
Â
|
|
33 |
Â
|
34 |
Â
public function validate( $settings ) {
|
35 |
-
$this->settings
|
36 |
Â
$this->previous_settings = ITSEC_Modules::get_settings( $this->get_id() );
|
37 |
Â
|
38 |
Â
$this->sanitize_settings();
|
@@ -52,14 +56,14 @@ abstract class ITSEC_Validator {
|
|
52 |
Â
$id = $this->get_id();
|
53 |
Â
|
54 |
Â
foreach ( array_keys( $this->defaults ) as $name ) {
|
55 |
-
if ( ! isset( $this->settings[$name] ) && ! in_array( $name, $this->vars_to_skip_validate_matching_fields ) ) {
|
56 |
Â
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_fields-missing-name-$name", sprintf( __( 'A validation function for %1$s received data that did not have the required entry for %2$s.', 'better-wp-security' ), $id, $name ) ) );
|
57 |
Â
$this->set_can_save( false );
|
58 |
Â
}
|
59 |
Â
}
|
60 |
Â
|
61 |
Â
foreach ( array_keys( $this->settings ) as $name ) {
|
62 |
-
if ( ! isset( $this->defaults[$name] ) && ! in_array( $name, $this->vars_to_skip_validate_matching_fields ) ) {
|
63 |
Â
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_fields-unknown-name-$name", sprintf( __( 'A validation function for %1$s received data that has an entry for %2$s when no such entry exists.', 'better-wp-security' ), $id, $name ) ) );
|
64 |
Â
$this->set_can_save( false );
|
65 |
Â
}
|
@@ -75,14 +79,14 @@ abstract class ITSEC_Validator {
|
|
75 |
Â
continue;
|
76 |
Â
}
|
77 |
Â
|
78 |
-
if ( ! isset( $this->settings[$name] ) ) {
|
79 |
Â
// Skip missing entries to allow implementations that use validate_matching_types() but not
|
80 |
Â
// validate_matching_fields().
|
81 |
Â
continue;
|
82 |
Â
}
|
83 |
Â
|
84 |
-
if ( gettype( $value ) !== gettype( $this->settings[$name] ) ) {
|
85 |
-
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_types-inmatching-type-$name", sprintf( __( 'A validation function for %1$s received data that does not match the expected data type for the %2$s entry. A data type of %3$s was expected, but a data type of %4$s was received.', 'better-wp-security' ), $id, $name, gettype( $value ), gettype( $this->settings[$name] ) ) ) );
|
86 |
Â
$this->set_can_save( false );
|
87 |
Â
}
|
88 |
Â
}
|
@@ -90,23 +94,23 @@ abstract class ITSEC_Validator {
|
|
90 |
Â
|
91 |
Â
final protected function set_default_if_empty( $vars ) {
|
92 |
Â
foreach ( (array) $vars as $var ) {
|
93 |
-
if ( ! isset( $this->settings[$var] ) || '' === $this->settings[$var] ) {
|
94 |
-
$this->settings[$var] = $this->defaults[$var];
|
95 |
Â
}
|
96 |
Â
}
|
97 |
Â
}
|
98 |
Â
|
99 |
Â
final protected function set_previous_if_empty( $vars ) {
|
100 |
Â
foreach ( (array) $vars as $var ) {
|
101 |
-
if ( ! isset( $this->settings[$var] ) || '' === $this->settings[$var] ) {
|
102 |
-
$this->settings[$var] = $this->previous_settings[$var];
|
103 |
Â
}
|
104 |
Â
}
|
105 |
Â
}
|
106 |
Â
|
107 |
Â
final protected function preserve_setting_if_exists( $vars ) {
|
108 |
Â
foreach ( (array) $vars as $var ) {
|
109 |
-
if ( array_key_exists( $var, $this->previous_settings ) && ( ! isset( $this->settings[
|
110 |
Â
$this->settings[ $var ] = $this->previous_settings[ $var ];
|
111 |
Â
}
|
112 |
Â
}
|
@@ -115,31 +119,32 @@ abstract class ITSEC_Validator {
|
|
115 |
Â
final protected function sanitize_setting( $type, $var, $name, $prevent_save_on_error = true, $trim_value = true, $custom_error = '' ) {
|
116 |
Â
$id = $this->get_id();
|
117 |
Â
|
118 |
-
if ( ! isset( $this->settings[$var] ) ) {
|
119 |
Â
$this->add_error( new WP_Error( "itsec-validator-missing-var-$id-$var", sprintf( __( 'A validation check for %1$s failed. The %2$s value is missing. This could be due to a problem with the iThemes Security installation or an invalid modification. Please reinstall iThemes Security and try again.', 'better-wp-security' ), $id, $name ) ) );
|
Â
|
|
120 |
Â
return false;
|
121 |
Â
}
|
122 |
Â
|
123 |
-
if ( $trim_value && is_string( $this->settings[$var] ) ) {
|
124 |
-
$this->settings[$var] = trim( $this->settings[$var] );
|
125 |
Â
}
|
126 |
Â
|
127 |
Â
$error = false;
|
128 |
Â
|
129 |
Â
if ( 'string' === $type ) {
|
130 |
-
$this->settings[$var] = (string) $this->settings[$var];
|
131 |
-
}
|
132 |
-
$this->settings[$var] = (string) $this->settings[$var];
|
133 |
Â
|
134 |
-
if ( empty( $this->settings[$var] ) ) {
|
135 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
136 |
Â
}
|
137 |
-
}
|
138 |
-
$this->settings[$var] = sanitize_title( $this->settings[$var] );
|
139 |
-
}
|
140 |
-
$this->settings[$var] = sanitize_title( $this->settings[$var] );
|
141 |
Â
|
142 |
-
if ( empty( $this->settings[$var] ) ) {
|
143 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
144 |
Â
}
|
145 |
Â
} elseif ( 'text' === $type || 'non-empty-text' === $type ) {
|
@@ -155,63 +160,63 @@ abstract class ITSEC_Validator {
|
|
155 |
Â
if ( 'non-empty-text' === $type && empty( $this->settings[ $var ] ) ) {
|
156 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
157 |
Â
}
|
158 |
-
}
|
159 |
-
if ( ! is_array( $this->settings[$var] ) ) {
|
160 |
-
if ( empty( $this->settings[$var] ) ) {
|
161 |
-
$this->settings[$var] = array();
|
162 |
Â
} else {
|
163 |
-
$this->settings[$var] = array( $this->settings[$var] );
|
164 |
Â
}
|
165 |
Â
}
|
166 |
-
}
|
167 |
-
if ( 'false' === $this->settings[$var] ) {
|
168 |
-
$this->settings[$var] = false;
|
169 |
-
}
|
170 |
-
$this->settings[$var] = true;
|
171 |
Â
} else {
|
172 |
-
$this->settings[$var] = (bool) $this->settings[$var];
|
173 |
Â
}
|
174 |
-
}
|
175 |
-
$test_val = intval( $this->settings[$var] );
|
176 |
-
if ( (string) $test_val === (string) $this->settings[$var] ) {
|
177 |
-
$this->settings[$var] = $test_val;
|
178 |
Â
} else {
|
179 |
Â
$error = sprintf( __( 'The %1$s value must be an integer.', 'better-wp-security' ), $name );
|
180 |
Â
}
|
181 |
-
}
|
182 |
-
$test_val = intval( $this->settings[$var] );
|
183 |
-
if ( (string) $test_val === (string) $this->settings[$var] && $test_val >= 0 ) {
|
184 |
-
$this->settings[$var] = $test_val;
|
185 |
Â
} else {
|
186 |
Â
$error = sprintf( __( 'The %1$s value must be a positive integer.', 'better-wp-security' ), $name );
|
187 |
Â
}
|
188 |
-
}
|
189 |
-
if ( is_numeric($this->settings[ $var ] ) ) {
|
190 |
Â
$this->settings[ $var ] = (float) $this->settings[ $var ];
|
191 |
Â
} else {
|
192 |
Â
$error = sprintf( __( 'The %1$s value must be a number.', 'better-wp-security' ), $name );
|
193 |
Â
}
|
194 |
-
}
|
195 |
-
$this->settings[$var] = sanitize_text_field( $this->settings[$var] );
|
196 |
Â
|
197 |
-
if ( empty( $this->settings[$var] ) || ! is_email( $this->settings[$var] ) ) {
|
198 |
Â
$error = sprintf( __( 'The %1$s value must be a valid email address.', 'better-wp-security' ), $name );
|
199 |
Â
}
|
200 |
-
}
|
201 |
-
$this->settings[$var] = sanitize_text_field( $this->settings[$var] );
|
202 |
Â
|
203 |
-
if ( ! empty( $this->settings[$var] ) && ! validate_username( $this->settings[$var] ) ) {
|
204 |
Â
$error = sprintf( __( 'The %1$s value is not a valid username.', 'better-wp-security' ), $name );
|
205 |
Â
}
|
206 |
-
}
|
207 |
-
$val = $this->settings[$var];
|
208 |
Â
|
209 |
Â
$separator = '[\-/\. ]';
|
210 |
Â
|
211 |
Â
if ( preg_match( "|^(\d\d\d\d)$separator(\d\d?)$separator(\d\d?)$|", $val, $match ) ) {
|
212 |
-
$year
|
213 |
Â
$month = intval( $match[2] );
|
214 |
-
$day
|
215 |
Â
|
216 |
Â
if ( ! checkdate( $month, $day, $year ) ) {
|
217 |
Â
$error = sprintf( __( 'The %1$s value must be a valid date.', 'better-wp-security' ), $name );
|
@@ -219,215 +224,250 @@ abstract class ITSEC_Validator {
|
|
219 |
Â
} else {
|
220 |
Â
$error = sprintf( __( 'The %1$s value must be a valid date in the format of YYYY-MM-DD.', 'better-wp-security' ), $name );
|
221 |
Â
}
|
222 |
-
}
|
223 |
-
if ( ! is_string( $this->settings[$var] ) ) {
|
224 |
Â
$error = sprintf( __( 'The %1$s value must be a string.', 'better-wp-security' ), $name );
|
225 |
Â
} else {
|
226 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
|
227 |
Â
|
228 |
-
$this->settings[$var] = rtrim( $this->settings[$var], DIRECTORY_SEPARATOR );
|
229 |
Â
|
230 |
-
if ( ! ITSEC_Lib_Directory::is_dir( $this->settings[$var] ) ) {
|
231 |
-
$result = ITSEC_Lib_Directory::create( $this->settings[$var] );
|
232 |
Â
|
233 |
Â
if ( is_wp_error( $result ) ) {
|
234 |
Â
$error = sprintf( _x( 'The directory supplied in %1$s cannot be used as a valid directory. %2$s', '%1$s is the input name. %2$s is the error message.', 'better-wp-security' ), $name, $result->get_error_message() );
|
235 |
Â
}
|
236 |
Â
}
|
237 |
Â
|
238 |
-
if ( empty( $error ) && ! ITSEC_Lib_Directory::is_writable( $this->settings[$var] ) ) {
|
239 |
Â
$error = sprintf( __( 'The directory supplied in %1$s is not writable. Please select a directory that can be written to.', 'better-wp-security' ), $name );
|
240 |
Â
}
|
241 |
Â
|
242 |
Â
if ( empty( $error ) ) {
|
243 |
-
ITSEC_Lib_Directory::add_file_listing_protection( $this->settings[$var] );
|
244 |
Â
}
|
245 |
Â
}
|
246 |
-
}
|
247 |
-
if ( ! is_string( $this->settings[$var] ) ) {
|
248 |
Â
$error = sprintf( __( 'The %1$s value must be a string.', 'better-wp-security' ), $name );
|
249 |
Â
} else {
|
250 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
|
251 |
Â
|
252 |
-
if ( ! ITSEC_Lib_File::is_file( $this->settings[$var] ) && ITSEC_Lib_File::exists( $this->settings[$var] ) ) {
|
253 |
Â
$error = sprintf( __( 'The file path supplied in %1$s cannot be used as it already exists but is not a file. Please supply a valid file path.', 'better-wp-security' ), $name );
|
254 |
Â
} else {
|
255 |
-
$result = ITSEC_Lib_Directory::create( dirname( $this->settings[$var] ) );
|
256 |
Â
|
257 |
Â
if ( is_wp_error( $result ) ) {
|
258 |
Â
$error = sprintf( _x( 'The file path supplied in %1$s cannot be used as the parent directory cannot be created. %2$s', '%1$s is the input name. %2$s is the error message.', 'better-wp-security' ), $name, $result->get_error_message() );
|
259 |
-
}
|
260 |
-
$result = ITSEC_Lib_File::write( $this->settings[$var], '' );
|
261 |
Â
|
262 |
Â
if ( is_wp_error( $result ) ) {
|
263 |
Â
$error = sprintf( __( 'The file path supplied in %1$s could not be created. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
264 |
-
}
|
265 |
Â
$error = sprintf( __( 'The file path supplied in %1$s was successfully created, but it cannot be updated. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
266 |
Â
}
|
267 |
-
}
|
268 |
Â
$error = sprintf( __( 'The file path supplied in %1$s is not writable. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
269 |
Â
}
|
270 |
Â
}
|
271 |
Â
}
|
272 |
-
}
|
273 |
-
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
274 |
Â
|
275 |
-
if ( ! is_array( $this->settings[$var] ) ) {
|
276 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
277 |
Â
} else {
|
278 |
Â
$invalid_entries = array();
|
279 |
Â
|
280 |
-
foreach ( $this->settings[$var] as $index => $entry ) {
|
281 |
-
$entry
|
282 |
-
$this->settings[$var][$index] = $entry;
|
283 |
Â
|
284 |
Â
if ( empty( $entry ) ) {
|
285 |
-
unset( $this->settings[$var][$index] );
|
286 |
Â
} else {
|
287 |
Â
$result = call_user_func( $type, $entry );
|
288 |
Â
|
289 |
Â
if ( false === $result ) {
|
290 |
Â
$invalid_entries[] = $entry;
|
291 |
Â
} else {
|
292 |
-
$this->settings[$var][$index] = $result;
|
293 |
Â
}
|
294 |
Â
}
|
295 |
Â
}
|
296 |
Â
|
297 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
298 |
Â
|
299 |
Â
if ( ! empty( $invalid_entries ) ) {
|
300 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
301 |
Â
}
|
302 |
Â
}
|
303 |
-
}
|
304 |
-
if ( is_array( $this->settings[$var] ) ) {
|
305 |
Â
$invalid_entries = array();
|
306 |
Â
|
307 |
-
foreach ( $this->settings[$var] as $index => $entry ) {
|
308 |
-
$entry
|
309 |
-
$this->settings[$var][$index] = $entry;
|
310 |
Â
|
311 |
Â
if ( empty( $entry ) ) {
|
312 |
-
unset( $this->settings[$var][$index] );
|
313 |
-
}
|
314 |
Â
$invalid_entries[] = $entry;
|
315 |
Â
}
|
316 |
Â
}
|
317 |
Â
|
318 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
319 |
Â
|
320 |
Â
if ( ! empty( $invalid_entries ) ) {
|
321 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
322 |
Â
}
|
323 |
-
}
|
324 |
Â
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $type ), 'better-wp-security' ), $name, $type );
|
325 |
-
$type
|
326 |
Â
}
|
327 |
Â
} elseif ( 'canonical-roles' === $type ) {
|
328 |
Â
$roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
|
329 |
Â
|
330 |
-
if ( is_array( $this->settings[$var] ) ) {
|
331 |
Â
$invalid_entries = array();
|
332 |
Â
|
333 |
-
foreach ( $this->settings[$var] as $index => $entry ) {
|
334 |
-
$entry
|
335 |
-
$this->settings[$var][$index] = $entry;
|
336 |
Â
|
337 |
Â
if ( empty( $entry ) ) {
|
338 |
-
unset( $this->settings[$var][$index] );
|
339 |
-
}
|
340 |
Â
$invalid_entries[] = $entry;
|
341 |
Â
}
|
342 |
Â
}
|
343 |
Â
|
344 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
345 |
Â
|
346 |
Â
if ( ! empty( $invalid_entries ) ) {
|
347 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
348 |
Â
}
|
349 |
-
}
|
350 |
Â
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $roles ), 'better-wp-security' ), $name, $roles );
|
351 |
-
$type
|
352 |
Â
}
|
353 |
-
}
|
354 |
-
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
355 |
Â
|
356 |
-
if ( ! is_array( $this->settings[$var] ) ) {
|
357 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
358 |
Â
}
|
359 |
-
}
|
360 |
-
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
361 |
Â
|
362 |
-
if ( ! is_array( $this->settings[$var] ) ) {
|
363 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
364 |
Â
} else {
|
365 |
Â
$invalid_emails = array();
|
366 |
Â
|
367 |
-
foreach ( $this->settings[$var] as $index => $email ) {
|
368 |
-
$email
|
369 |
-
$this->settings[$var][$index] = $email;
|
370 |
Â
|
371 |
Â
if ( empty( $email ) ) {
|
372 |
-
unset( $this->settings[$var][$index] );
|
373 |
-
}
|
374 |
Â
$invalid_emails[] = $email;
|
375 |
Â
}
|
376 |
Â
}
|
377 |
Â
|
378 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
379 |
Â
|
380 |
Â
if ( ! empty( $invalid_emails ) ) {
|
381 |
Â
$error = wp_sprintf( _n( 'The following email in %1$s is invalid: %2$l', 'The following emails in %1$s are invalid: %2$l', count( $invalid_emails ), 'better-wp-security' ), $name, $invalid_emails );
|
382 |
Â
}
|
383 |
Â
}
|
384 |
-
}
|
385 |
-
$this->settings[$var] = $this->convert_string_to_array( $this->settings[$var] );
|
386 |
Â
|
387 |
-
if ( ! is_array( $this->settings[$var] ) ) {
|
388 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
389 |
Â
} else {
|
390 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-ip-tools.php' );
|
391 |
Â
|
392 |
Â
$invalid_ips = array();
|
393 |
Â
|
394 |
-
foreach ( $this->settings[$var] as $index => $ip ) {
|
395 |
Â
$ip = trim( $ip );
|
396 |
Â
|
397 |
Â
if ( '' === $ip ) {
|
398 |
-
unset( $this->settings[$var][$index] );
|
399 |
Â
} else {
|
400 |
Â
$validated_ip = ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $ip );
|
401 |
Â
|
402 |
Â
if ( false === $validated_ip ) {
|
403 |
Â
$invalid_ips[] = $ip;
|
404 |
Â
} else {
|
405 |
-
$this->settings[$var][$index] = $validated_ip;
|
406 |
Â
}
|
407 |
Â
}
|
408 |
Â
}
|
409 |
Â
|
410 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
411 |
Â
|
412 |
Â
if ( ! empty( $invalid_ips ) ) {
|
413 |
Â
$error = wp_sprintf( _n( 'The following IP in %1$s is invalid: %2$l', 'The following IPs in %1$s are invalid: %2$l', count( $invalid_ips ), 'better-wp-security' ), $name, $invalid_ips );
|
414 |
Â
}
|
415 |
Â
}
|
416 |
-
}
|
417 |
-
$
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
418 |
Â
|
419 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
420 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
421 |
Â
} else {
|
422 |
Â
$invalid_extensions = array();
|
423 |
Â
|
424 |
-
foreach ( $this->settings[$var] as $index => $extension ) {
|
425 |
Â
if ( ! preg_match( '/^(\.[^.]+)+$/', $extension ) ) {
|
426 |
Â
$invalid_extensions[] = $extension;
|
427 |
Â
}
|
428 |
Â
}
|
429 |
Â
|
430 |
-
$this->settings[$var] = array_unique( $this->settings[$var] );
|
431 |
Â
|
432 |
Â
if ( ! empty( $invalid_extensions ) ) {
|
433 |
Â
$error = wp_sprintf( _n( 'The following extension in %1$s is invalid: %2$l', 'The following extensions in %1$s are invalid: %2$l', count( $invalid_extensions ), 'better-wp-security' ), $name, $invalid_extensions );
|
@@ -452,7 +492,7 @@ abstract class ITSEC_Validator {
|
|
452 |
Â
if ( false === $result ) {
|
453 |
Â
$invalid_entries[] = is_string( $entry ) ? $entry : $index;
|
454 |
Â
} elseif ( is_wp_error( $result ) ) {
|
455 |
-
$invalid_entries[] =
|
456 |
Â
} else {
|
457 |
Â
$this->settings[ $var ][ $index ] = $result;
|
458 |
Â
}
|
@@ -494,7 +534,7 @@ abstract class ITSEC_Validator {
|
|
494 |
Â
final protected function convert_string_to_array( $string ) {
|
495 |
Â
if ( is_string( $string ) ) {
|
496 |
Â
$array = preg_split( "/[\r\n]+/", $string );
|
497 |
-
}
|
498 |
Â
$array = $string;
|
499 |
Â
} else {
|
500 |
Â
return $string;
|
@@ -504,9 +544,9 @@ abstract class ITSEC_Validator {
|
|
504 |
Â
$val = trim( $val );
|
505 |
Â
|
506 |
Â
if ( empty( $val ) ) {
|
507 |
-
unset( $array[$key] );
|
508 |
Â
} else {
|
509 |
-
$array[$key] = $val;
|
510 |
Â
}
|
511 |
Â
}
|
512 |
Â
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups\Matchables_Source;
|
4 |
+
|
5 |
Â
abstract class ITSEC_Validator {
|
6 |
Â
protected $run_validate_matching_fields = true;
|
7 |
Â
protected $run_validate_matching_types = true;
|
30 |
Â
}
|
31 |
Â
|
32 |
Â
abstract public function get_id();
|
33 |
+
|
34 |
+
protected function sanitize_settings() { }
|
35 |
+
|
36 |
+
protected function validate_settings() { }
|
37 |
Â
|
38 |
Â
public function validate( $settings ) {
|
39 |
+
$this->settings = $settings;
|
40 |
Â
$this->previous_settings = ITSEC_Modules::get_settings( $this->get_id() );
|
41 |
Â
|
42 |
Â
$this->sanitize_settings();
|
56 |
Â
$id = $this->get_id();
|
57 |
Â
|
58 |
Â
foreach ( array_keys( $this->defaults ) as $name ) {
|
59 |
+
if ( ! isset( $this->settings[ $name ] ) && ! in_array( $name, $this->vars_to_skip_validate_matching_fields ) ) {
|
60 |
Â
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_fields-missing-name-$name", sprintf( __( 'A validation function for %1$s received data that did not have the required entry for %2$s.', 'better-wp-security' ), $id, $name ) ) );
|
61 |
Â
$this->set_can_save( false );
|
62 |
Â
}
|
63 |
Â
}
|
64 |
Â
|
65 |
Â
foreach ( array_keys( $this->settings ) as $name ) {
|
66 |
+
if ( ! isset( $this->defaults[ $name ] ) && ! in_array( $name, $this->vars_to_skip_validate_matching_fields ) ) {
|
67 |
Â
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_fields-unknown-name-$name", sprintf( __( 'A validation function for %1$s received data that has an entry for %2$s when no such entry exists.', 'better-wp-security' ), $id, $name ) ) );
|
68 |
Â
$this->set_can_save( false );
|
69 |
Â
}
|
79 |
Â
continue;
|
80 |
Â
}
|
81 |
Â
|
82 |
+
if ( ! isset( $this->settings[ $name ] ) ) {
|
83 |
Â
// Skip missing entries to allow implementations that use validate_matching_types() but not
|
84 |
Â
// validate_matching_fields().
|
85 |
Â
continue;
|
86 |
Â
}
|
87 |
Â
|
88 |
+
if ( gettype( $value ) !== gettype( $this->settings[ $name ] ) ) {
|
89 |
+
$this->add_error( new WP_Error( "itsec-validator-$id-validate_matching_types-inmatching-type-$name", sprintf( __( 'A validation function for %1$s received data that does not match the expected data type for the %2$s entry. A data type of %3$s was expected, but a data type of %4$s was received.', 'better-wp-security' ), $id, $name, gettype( $value ), gettype( $this->settings[ $name ] ) ) ) );
|
90 |
Â
$this->set_can_save( false );
|
91 |
Â
}
|
92 |
Â
}
|
94 |
Â
|
95 |
Â
final protected function set_default_if_empty( $vars ) {
|
96 |
Â
foreach ( (array) $vars as $var ) {
|
97 |
+
if ( ! isset( $this->settings[ $var ] ) || '' === $this->settings[ $var ] ) {
|
98 |
+
$this->settings[ $var ] = $this->defaults[ $var ];
|
99 |
Â
}
|
100 |
Â
}
|
101 |
Â
}
|
102 |
Â
|
103 |
Â
final protected function set_previous_if_empty( $vars ) {
|
104 |
Â
foreach ( (array) $vars as $var ) {
|
105 |
+
if ( ! isset( $this->settings[ $var ] ) || '' === $this->settings[ $var ] ) {
|
106 |
+
$this->settings[ $var ] = $this->previous_settings[ $var ];
|
107 |
Â
}
|
108 |
Â
}
|
109 |
Â
}
|
110 |
Â
|
111 |
Â
final protected function preserve_setting_if_exists( $vars ) {
|
112 |
Â
foreach ( (array) $vars as $var ) {
|
113 |
+
if ( array_key_exists( $var, $this->previous_settings ) && ( ! isset( $this->settings[ $var ] ) || '' === $this->settings[ $var ] ) ) {
|
114 |
Â
$this->settings[ $var ] = $this->previous_settings[ $var ];
|
115 |
Â
}
|
116 |
Â
}
|
119 |
Â
final protected function sanitize_setting( $type, $var, $name, $prevent_save_on_error = true, $trim_value = true, $custom_error = '' ) {
|
120 |
Â
$id = $this->get_id();
|
121 |
Â
|
122 |
+
if ( ! isset( $this->settings[ $var ] ) ) {
|
123 |
Â
$this->add_error( new WP_Error( "itsec-validator-missing-var-$id-$var", sprintf( __( 'A validation check for %1$s failed. The %2$s value is missing. This could be due to a problem with the iThemes Security installation or an invalid modification. Please reinstall iThemes Security and try again.', 'better-wp-security' ), $id, $name ) ) );
|
124 |
+
|
125 |
Â
return false;
|
126 |
Â
}
|
127 |
Â
|
128 |
+
if ( $trim_value && is_string( $this->settings[ $var ] ) ) {
|
129 |
+
$this->settings[ $var ] = trim( $this->settings[ $var ] );
|
130 |
Â
}
|
131 |
Â
|
132 |
Â
$error = false;
|
133 |
Â
|
134 |
Â
if ( 'string' === $type ) {
|
135 |
+
$this->settings[ $var ] = (string) $this->settings[ $var ];
|
136 |
+
} elseif ( 'non-empty-string' === $type ) {
|
137 |
+
$this->settings[ $var ] = (string) $this->settings[ $var ];
|
138 |
Â
|
139 |
+
if ( empty( $this->settings[ $var ] ) ) {
|
140 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
141 |
Â
}
|
142 |
+
} elseif ( 'title' === $type ) {
|
143 |
+
$this->settings[ $var ] = sanitize_title( $this->settings[ $var ] );
|
144 |
+
} elseif ( 'non-empty-title' === $type ) {
|
145 |
+
$this->settings[ $var ] = sanitize_title( $this->settings[ $var ] );
|
146 |
Â
|
147 |
+
if ( empty( $this->settings[ $var ] ) ) {
|
148 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
149 |
Â
}
|
150 |
Â
} elseif ( 'text' === $type || 'non-empty-text' === $type ) {
|
160 |
Â
if ( 'non-empty-text' === $type && empty( $this->settings[ $var ] ) ) {
|
161 |
Â
$error = sprintf( __( 'The %1$s value cannot be empty.', 'better-wp-security' ), $name );
|
162 |
Â
}
|
163 |
+
} elseif ( 'array' === $type ) {
|
164 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
165 |
+
if ( empty( $this->settings[ $var ] ) ) {
|
166 |
+
$this->settings[ $var ] = array();
|
167 |
Â
} else {
|
168 |
+
$this->settings[ $var ] = array( $this->settings[ $var ] );
|
169 |
Â
}
|
170 |
Â
}
|
171 |
+
} elseif ( 'bool' === $type ) {
|
172 |
+
if ( 'false' === $this->settings[ $var ] ) {
|
173 |
+
$this->settings[ $var ] = false;
|
174 |
+
} elseif ( 'true' === $this->settings[ $var ] ) {
|
175 |
+
$this->settings[ $var ] = true;
|
176 |
Â
} else {
|
177 |
+
$this->settings[ $var ] = (bool) $this->settings[ $var ];
|
178 |
Â
}
|
179 |
+
} elseif ( 'int' === $type ) {
|
180 |
+
$test_val = intval( $this->settings[ $var ] );
|
181 |
+
if ( (string) $test_val === (string) $this->settings[ $var ] ) {
|
182 |
+
$this->settings[ $var ] = $test_val;
|
183 |
Â
} else {
|
184 |
Â
$error = sprintf( __( 'The %1$s value must be an integer.', 'better-wp-security' ), $name );
|
185 |
Â
}
|
186 |
+
} elseif ( 'positive-int' === $type ) {
|
187 |
+
$test_val = intval( $this->settings[ $var ] );
|
188 |
+
if ( (string) $test_val === (string) $this->settings[ $var ] && $test_val >= 0 ) {
|
189 |
+
$this->settings[ $var ] = $test_val;
|
190 |
Â
} else {
|
191 |
Â
$error = sprintf( __( 'The %1$s value must be a positive integer.', 'better-wp-security' ), $name );
|
192 |
Â
}
|
193 |
+
} elseif ( 'number' === $type ) {
|
194 |
+
if ( is_numeric( $this->settings[ $var ] ) ) {
|
195 |
Â
$this->settings[ $var ] = (float) $this->settings[ $var ];
|
196 |
Â
} else {
|
197 |
Â
$error = sprintf( __( 'The %1$s value must be a number.', 'better-wp-security' ), $name );
|
198 |
Â
}
|
199 |
+
} elseif ( 'email' === $type ) {
|
200 |
+
$this->settings[ $var ] = sanitize_text_field( $this->settings[ $var ] );
|
201 |
Â
|
202 |
+
if ( empty( $this->settings[ $var ] ) || ! is_email( $this->settings[ $var ] ) ) {
|
203 |
Â
$error = sprintf( __( 'The %1$s value must be a valid email address.', 'better-wp-security' ), $name );
|
204 |
Â
}
|
205 |
+
} elseif ( 'valid-username' === $type ) {
|
206 |
+
$this->settings[ $var ] = sanitize_text_field( $this->settings[ $var ] );
|
207 |
Â
|
208 |
+
if ( ! empty( $this->settings[ $var ] ) && ! validate_username( $this->settings[ $var ] ) ) {
|
209 |
Â
$error = sprintf( __( 'The %1$s value is not a valid username.', 'better-wp-security' ), $name );
|
210 |
Â
}
|
211 |
+
} elseif ( 'date' === $type ) {
|
212 |
+
$val = $this->settings[ $var ];
|
213 |
Â
|
214 |
Â
$separator = '[\-/\. ]';
|
215 |
Â
|
216 |
Â
if ( preg_match( "|^(\d\d\d\d)$separator(\d\d?)$separator(\d\d?)$|", $val, $match ) ) {
|
217 |
+
$year = intval( $match[1] );
|
218 |
Â
$month = intval( $match[2] );
|
219 |
+
$day = intval( $match[3] );
|
220 |
Â
|
221 |
Â
if ( ! checkdate( $month, $day, $year ) ) {
|
222 |
Â
$error = sprintf( __( 'The %1$s value must be a valid date.', 'better-wp-security' ), $name );
|
224 |
Â
} else {
|
225 |
Â
$error = sprintf( __( 'The %1$s value must be a valid date in the format of YYYY-MM-DD.', 'better-wp-security' ), $name );
|
226 |
Â
}
|
227 |
+
} elseif ( 'writable-directory' === $type ) {
|
228 |
+
if ( ! is_string( $this->settings[ $var ] ) ) {
|
229 |
Â
$error = sprintf( __( 'The %1$s value must be a string.', 'better-wp-security' ), $name );
|
230 |
Â
} else {
|
231 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
|
232 |
Â
|
233 |
+
$this->settings[ $var ] = rtrim( $this->settings[ $var ], DIRECTORY_SEPARATOR );
|
234 |
Â
|
235 |
+
if ( ! ITSEC_Lib_Directory::is_dir( $this->settings[ $var ] ) ) {
|
236 |
+
$result = ITSEC_Lib_Directory::create( $this->settings[ $var ] );
|
237 |
Â
|
238 |
Â
if ( is_wp_error( $result ) ) {
|
239 |
Â
$error = sprintf( _x( 'The directory supplied in %1$s cannot be used as a valid directory. %2$s', '%1$s is the input name. %2$s is the error message.', 'better-wp-security' ), $name, $result->get_error_message() );
|
240 |
Â
}
|
241 |
Â
}
|
242 |
Â
|
243 |
+
if ( empty( $error ) && ! ITSEC_Lib_Directory::is_writable( $this->settings[ $var ] ) ) {
|
244 |
Â
$error = sprintf( __( 'The directory supplied in %1$s is not writable. Please select a directory that can be written to.', 'better-wp-security' ), $name );
|
245 |
Â
}
|
246 |
Â
|
247 |
Â
if ( empty( $error ) ) {
|
248 |
+
ITSEC_Lib_Directory::add_file_listing_protection( $this->settings[ $var ] );
|
249 |
Â
}
|
250 |
Â
}
|
251 |
+
} elseif ( 'writable-file' === $type ) {
|
252 |
+
if ( ! is_string( $this->settings[ $var ] ) ) {
|
253 |
Â
$error = sprintf( __( 'The %1$s value must be a string.', 'better-wp-security' ), $name );
|
254 |
Â
} else {
|
255 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
|
256 |
Â
|
257 |
+
if ( ! ITSEC_Lib_File::is_file( $this->settings[ $var ] ) && ITSEC_Lib_File::exists( $this->settings[ $var ] ) ) {
|
258 |
Â
$error = sprintf( __( 'The file path supplied in %1$s cannot be used as it already exists but is not a file. Please supply a valid file path.', 'better-wp-security' ), $name );
|
259 |
Â
} else {
|
260 |
+
$result = ITSEC_Lib_Directory::create( dirname( $this->settings[ $var ] ) );
|
261 |
Â
|
262 |
Â
if ( is_wp_error( $result ) ) {
|
263 |
Â
$error = sprintf( _x( 'The file path supplied in %1$s cannot be used as the parent directory cannot be created. %2$s', '%1$s is the input name. %2$s is the error message.', 'better-wp-security' ), $name, $result->get_error_message() );
|
264 |
+
} elseif ( ! ITSEC_Lib_File::exists( $this->settings[ $var ] ) ) {
|
265 |
+
$result = ITSEC_Lib_File::write( $this->settings[ $var ], '' );
|
266 |
Â
|
267 |
Â
if ( is_wp_error( $result ) ) {
|
268 |
Â
$error = sprintf( __( 'The file path supplied in %1$s could not be created. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
269 |
+
} elseif ( ! is_writable( $this->settings[ $var ] ) ) {
|
270 |
Â
$error = sprintf( __( 'The file path supplied in %1$s was successfully created, but it cannot be updated. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
271 |
Â
}
|
272 |
+
} elseif ( ! is_writable( $this->settings[ $var ] ) ) {
|
273 |
Â
$error = sprintf( __( 'The file path supplied in %1$s is not writable. Please supply a file path that can be written to.', 'better-wp-security' ), $name );
|
274 |
Â
}
|
275 |
Â
}
|
276 |
Â
}
|
277 |
+
} elseif ( is_array( $type ) && 2 === count( $type ) && $this === $type[0] ) {
|
278 |
+
$this->settings[ $var ] = $this->convert_string_to_array( $this->settings[ $var ] );
|
279 |
Â
|
280 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
281 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
282 |
Â
} else {
|
283 |
Â
$invalid_entries = array();
|
284 |
Â
|
285 |
+
foreach ( $this->settings[ $var ] as $index => $entry ) {
|
286 |
+
$entry = sanitize_text_field( trim( $entry ) );
|
287 |
+
$this->settings[ $var ][ $index ] = $entry;
|
288 |
Â
|
289 |
Â
if ( empty( $entry ) ) {
|
290 |
+
unset( $this->settings[ $var ][ $index ] );
|
291 |
Â
} else {
|
292 |
Â
$result = call_user_func( $type, $entry );
|
293 |
Â
|
294 |
Â
if ( false === $result ) {
|
295 |
Â
$invalid_entries[] = $entry;
|
296 |
Â
} else {
|
297 |
+
$this->settings[ $var ][ $index ] = $result;
|
298 |
Â
}
|
299 |
Â
}
|
300 |
Â
}
|
301 |
Â
|
302 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
303 |
Â
|
304 |
Â
if ( ! empty( $invalid_entries ) ) {
|
305 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
306 |
Â
}
|
307 |
Â
}
|
308 |
+
} elseif ( is_array( $type ) ) {
|
309 |
+
if ( is_array( $this->settings[ $var ] ) ) {
|
310 |
Â
$invalid_entries = array();
|
311 |
Â
|
312 |
+
foreach ( $this->settings[ $var ] as $index => $entry ) {
|
313 |
+
$entry = sanitize_text_field( trim( $entry ) );
|
314 |
+
$this->settings[ $var ][ $index ] = $entry;
|
315 |
Â
|
316 |
Â
if ( empty( $entry ) ) {
|
317 |
+
unset( $this->settings[ $var ][ $index ] );
|
318 |
+
} elseif ( ! in_array( $entry, $type, true ) ) {
|
319 |
Â
$invalid_entries[] = $entry;
|
320 |
Â
}
|
321 |
Â
}
|
322 |
Â
|
323 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
324 |
Â
|
325 |
Â
if ( ! empty( $invalid_entries ) ) {
|
326 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
327 |
Â
}
|
328 |
+
} elseif ( ! in_array( $this->settings[ $var ], $type, true ) ) {
|
329 |
Â
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $type ), 'better-wp-security' ), $name, $type );
|
330 |
+
$type = 'array';
|
331 |
Â
}
|
332 |
Â
} elseif ( 'canonical-roles' === $type ) {
|
333 |
Â
$roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
|
334 |
Â
|
335 |
+
if ( is_array( $this->settings[ $var ] ) ) {
|
336 |
Â
$invalid_entries = array();
|
337 |
Â
|
338 |
+
foreach ( $this->settings[ $var ] as $index => $entry ) {
|
339 |
+
$entry = sanitize_text_field( trim( $entry ) );
|
340 |
+
$this->settings[ $var ][ $index ] = $entry;
|
341 |
Â
|
342 |
Â
if ( empty( $entry ) ) {
|
343 |
+
unset( $this->settings[ $var ][ $index ] );
|
344 |
+
} elseif ( ! in_array( $entry, $roles, true ) ) {
|
345 |
Â
$invalid_entries[] = $entry;
|
346 |
Â
}
|
347 |
Â
}
|
348 |
Â
|
349 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
350 |
Â
|
351 |
Â
if ( ! empty( $invalid_entries ) ) {
|
352 |
Â
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_entries ), 'better-wp-security' ), $name, $invalid_entries );
|
353 |
Â
}
|
354 |
+
} elseif ( ! in_array( $this->settings[ $var ], $roles, true ) ) {
|
355 |
Â
$error = wp_sprintf( _n( 'The valid value for %1$s is: %2$l.', 'The valid values for %1$s are: %2$l.', count( $roles ), 'better-wp-security' ), $name, $roles );
|
356 |
+
$type = 'array';
|
357 |
Â
}
|
358 |
+
} elseif ( 'newline-separated-array' === $type ) {
|
359 |
+
$this->settings[ $var ] = $this->convert_string_to_array( $this->settings[ $var ] );
|
360 |
Â
|
361 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
362 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
363 |
Â
}
|
364 |
+
} elseif ( 'newline-separated-emails' === $type ) {
|
365 |
+
$this->settings[ $var ] = $this->convert_string_to_array( $this->settings[ $var ] );
|
366 |
Â
|
367 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
368 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
369 |
Â
} else {
|
370 |
Â
$invalid_emails = array();
|
371 |
Â
|
372 |
+
foreach ( $this->settings[ $var ] as $index => $email ) {
|
373 |
+
$email = sanitize_text_field( trim( $email ) );
|
374 |
+
$this->settings[ $var ][ $index ] = $email;
|
375 |
Â
|
376 |
Â
if ( empty( $email ) ) {
|
377 |
+
unset( $this->settings[ $var ][ $index ] );
|
378 |
+
} elseif ( ! is_email( $email ) ) {
|
379 |
Â
$invalid_emails[] = $email;
|
380 |
Â
}
|
381 |
Â
}
|
382 |
Â
|
383 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
384 |
Â
|
385 |
Â
if ( ! empty( $invalid_emails ) ) {
|
386 |
Â
$error = wp_sprintf( _n( 'The following email in %1$s is invalid: %2$l', 'The following emails in %1$s are invalid: %2$l', count( $invalid_emails ), 'better-wp-security' ), $name, $invalid_emails );
|
387 |
Â
}
|
388 |
Â
}
|
389 |
+
} elseif ( 'newline-separated-ips' === $type ) {
|
390 |
+
$this->settings[ $var ] = $this->convert_string_to_array( $this->settings[ $var ] );
|
391 |
Â
|
392 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
393 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
394 |
Â
} else {
|
395 |
Â
require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-ip-tools.php' );
|
396 |
Â
|
397 |
Â
$invalid_ips = array();
|
398 |
Â
|
399 |
+
foreach ( $this->settings[ $var ] as $index => $ip ) {
|
400 |
Â
$ip = trim( $ip );
|
401 |
Â
|
402 |
Â
if ( '' === $ip ) {
|
403 |
+
unset( $this->settings[ $var ][ $index ] );
|
404 |
Â
} else {
|
405 |
Â
$validated_ip = ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $ip );
|
406 |
Â
|
407 |
Â
if ( false === $validated_ip ) {
|
408 |
Â
$invalid_ips[] = $ip;
|
409 |
Â
} else {
|
410 |
+
$this->settings[ $var ][ $index ] = $validated_ip;
|
411 |
Â
}
|
412 |
Â
}
|
413 |
Â
}
|
414 |
Â
|
415 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
416 |
Â
|
417 |
Â
if ( ! empty( $invalid_ips ) ) {
|
418 |
Â
$error = wp_sprintf( _n( 'The following IP in %1$s is invalid: %2$l', 'The following IPs in %1$s are invalid: %2$l', count( $invalid_ips ), 'better-wp-security' ), $name, $invalid_ips );
|
419 |
Â
}
|
420 |
Â
}
|
421 |
+
} elseif ( 'user-groups' === $type ) {
|
422 |
+
$source = ITSEC_Modules::get_container()->get( Matchables_Source::class );
|
423 |
+
|
424 |
+
$this->sanitize_setting( 'array', $var, $name, $prevent_save_on_error, $trim_value, $custom_error );
|
425 |
+
$invalid_user_groups = [];
|
426 |
+
|
427 |
+
foreach ( $this->settings[ $var ] as $i => $group ) {
|
428 |
+
if ( ! is_string( $group ) ) {
|
429 |
+
unset( $this->settings[ $var ][ $i ] );
|
430 |
+
|
431 |
+
continue;
|
432 |
+
}
|
433 |
Â
|
434 |
+
if ( $source->has( $group ) ) {
|
435 |
+
continue;
|
436 |
+
}
|
437 |
+
|
438 |
+
if ( in_array( $group, $this->previous_settings[ $var ], true ) ) {
|
439 |
+
unset( $this->settings[ $var ][ $i ] );
|
440 |
+
} else {
|
441 |
+
$invalid_user_groups[] = $group;
|
442 |
+
}
|
443 |
+
}
|
444 |
+
|
445 |
+
$this->settings[ $var ] = wp_is_numeric_array( $this->settings[ $var ] ) ? array_values( $this->settings[ $var ] ) : $this->settings[ $var ];
|
446 |
+
|
447 |
+
if ( $invalid_user_groups ) {
|
448 |
+
$error = wp_sprintf( _n( 'The following entry in %1$s is invalid: %2$l', 'The following entries in %1$s are invalid: %2$l', count( $invalid_user_groups ), 'better-wp-security' ), $name, $invalid_user_groups );
|
449 |
+
}
|
450 |
+
} elseif ( 'user-group' === $type ) {
|
451 |
+
$source = ITSEC_Modules::get_container()->get( Matchables_Source::class );
|
452 |
+
|
453 |
+
if ( ! $source->has( $this->settings[ $var ] ) ) {
|
454 |
+
$error = sprintf( __( 'The user group selected for %1$s is invalid.', 'better-wp-security' ), $name );
|
455 |
+
}
|
456 |
+
} elseif ( 'newline-separated-extensions' === $type ) {
|
457 |
+
$this->settings[ $var ] = $this->convert_string_to_array( $this->settings[ $var ] );
|
458 |
+
|
459 |
+
if ( ! is_array( $this->settings[ $var ] ) ) {
|
460 |
Â
$error = sprintf( __( 'The %1$s value must be a string with each entry separated by a new line.', 'better-wp-security' ), $name );
|
461 |
Â
} else {
|
462 |
Â
$invalid_extensions = array();
|
463 |
Â
|
464 |
+
foreach ( $this->settings[ $var ] as $index => $extension ) {
|
465 |
Â
if ( ! preg_match( '/^(\.[^.]+)+$/', $extension ) ) {
|
466 |
Â
$invalid_extensions[] = $extension;
|
467 |
Â
}
|
468 |
Â
}
|
469 |
Â
|
470 |
+
$this->settings[ $var ] = array_unique( $this->settings[ $var ] );
|
471 |
Â
|
472 |
Â
if ( ! empty( $invalid_extensions ) ) {
|
473 |
Â
$error = wp_sprintf( _n( 'The following extension in %1$s is invalid: %2$l', 'The following extensions in %1$s are invalid: %2$l', count( $invalid_extensions ), 'better-wp-security' ), $name, $invalid_extensions );
|
492 |
Â
if ( false === $result ) {
|
493 |
Â
$invalid_entries[] = is_string( $entry ) ? $entry : $index;
|
494 |
Â
} elseif ( is_wp_error( $result ) ) {
|
495 |
+
$invalid_entries[] = "'{$index}': {$result->get_error_message()}";
|
496 |
Â
} else {
|
497 |
Â
$this->settings[ $var ][ $index ] = $result;
|
498 |
Â
}
|
534 |
Â
final protected function convert_string_to_array( $string ) {
|
535 |
Â
if ( is_string( $string ) ) {
|
536 |
Â
$array = preg_split( "/[\r\n]+/", $string );
|
537 |
+
} elseif ( is_array( $string ) ) {
|
538 |
Â
$array = $string;
|
539 |
Â
} else {
|
540 |
Â
return $string;
|
544 |
Â
$val = trim( $val );
|
545 |
Â
|
546 |
Â
if ( empty( $val ) ) {
|
547 |
+
unset( $array[ $key ] );
|
548 |
Â
} else {
|
549 |
+
$array[ $key ] = $val;
|
550 |
Â
}
|
551 |
Â
}
|
552 |
Â
|
core/modules.php
CHANGED
@@ -1,5 +1,9 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
3 |
Â
final class ITSEC_Modules {
|
4 |
Â
/**
|
5 |
Â
* @var ITSEC_Modules - Static property to hold our singleton instance
|
@@ -15,11 +19,25 @@ final class ITSEC_Modules {
|
|
15 |
Â
private $_module_settings = false;
|
16 |
Â
private $_module_validators = false;
|
17 |
Â
private $_settings_files_loaded = false;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
18 |
Â
|
19 |
Â
protected function __construct() {
|
20 |
Â
// Action triggered from another part of Security which runs when the settings page is loaded.
|
21 |
Â
add_action( 'itsec-settings-page-init', array( $this, 'load_settings_page' ) );
|
22 |
Â
add_action( 'itsec-logs-page-init', array( $this, 'load_settings_page' ) );
|
Â
|
|
Â
|
|
Â
|
|
23 |
Â
}
|
24 |
Â
|
25 |
Â
/**
|
@@ -52,16 +70,17 @@ final class ITSEC_Modules {
|
|
52 |
Â
|
53 |
Â
if ( ! is_dir( $path ) ) {
|
54 |
Â
trigger_error( sprintf( __( 'An attempt to register the %1$s module failed since the supplied path (%2$s) is invalid. This could indicate an invalid modification or incomplete installation of the iThemes Security plugin. Please reinstall the plugin and try again.', 'better-wp-security' ), $slug, $path ) );
|
Â
|
|
55 |
Â
return false;
|
56 |
Â
}
|
57 |
Â
|
58 |
Â
$self->_module_paths[ $slug ] = $path;
|
59 |
-
$self->_available_modules
|
60 |
Â
|
61 |
Â
if ( 'always-active' === $type ) {
|
62 |
-
$self->_always_active_modules[$slug] = true;
|
63 |
-
}
|
64 |
-
$self->_default_active_modules[$slug] = true;
|
65 |
Â
}
|
66 |
Â
|
67 |
Â
return true;
|
@@ -84,8 +103,7 @@ final class ITSEC_Modules {
|
|
84 |
Â
unset( $self->_module_paths[ $slug ] );
|
85 |
Â
$self->_available_modules = array_keys( $self->_module_paths );
|
86 |
Â
|
87 |
-
unset( $self->_always_active_modules[$slug] );
|
88 |
-
unset( $self->_default_active_modules[$slug] );
|
89 |
Â
|
90 |
Â
return true;
|
91 |
Â
}
|
@@ -105,7 +123,7 @@ final class ITSEC_Modules {
|
|
105 |
Â
$self = self::get_instance();
|
106 |
Â
|
107 |
Â
foreach ( $self->_module_paths as $slug => $path ) {
|
108 |
-
$self->_module_paths[$slug] = str_replace( $old_dir, $new_dir, $path );
|
109 |
Â
}
|
110 |
Â
}
|
111 |
Â
|
@@ -115,8 +133,7 @@ final class ITSEC_Modules {
|
|
115 |
Â
* @param ITSEC_Settings $settings
|
116 |
Â
*/
|
117 |
Â
public static function register_settings( $settings ) {
|
118 |
-
|
119 |
-
$self->_module_settings[ $settings->get_id() ] = $settings;
|
120 |
Â
}
|
121 |
Â
|
122 |
Â
/**
|
@@ -150,8 +167,6 @@ final class ITSEC_Modules {
|
|
150 |
Â
* @return array
|
151 |
Â
*/
|
152 |
Â
public static function get_defaults( $slug ) {
|
153 |
-
$self = self::get_instance();
|
154 |
-
|
155 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
156 |
Â
|
157 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get_defaults' ) ) ) {
|
@@ -171,12 +186,10 @@ final class ITSEC_Modules {
|
|
171 |
Â
* @return mixed
|
172 |
Â
*/
|
173 |
Â
public static function get_default( $slug, $name, $default = null ) {
|
174 |
-
$self = self::get_instance();
|
175 |
-
|
176 |
Â
$defaults = self::get_defaults( $slug );
|
177 |
Â
|
178 |
-
if ( isset( $defaults[$name] ) ) {
|
179 |
-
return $defaults[$name];
|
180 |
Â
}
|
181 |
Â
|
182 |
Â
return $default;
|
@@ -190,8 +203,6 @@ final class ITSEC_Modules {
|
|
190 |
Â
* @return array
|
191 |
Â
*/
|
192 |
Â
public static function get_settings( $slug ) {
|
193 |
-
$self = self::get_instance();
|
194 |
-
|
195 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
196 |
Â
|
197 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get_all' ) ) ) {
|
@@ -212,8 +223,6 @@ final class ITSEC_Modules {
|
|
212 |
Â
* @return mixed
|
213 |
Â
*/
|
214 |
Â
public static function get_setting( $slug, $name, $default = null ) {
|
215 |
-
$self = self::get_instance();
|
216 |
-
|
217 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
218 |
Â
|
219 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get' ) ) ) {
|
@@ -234,8 +243,6 @@ final class ITSEC_Modules {
|
|
234 |
Â
* @return array|WP_Error
|
235 |
Â
*/
|
236 |
Â
public static function set_settings( $slug, $settings ) {
|
237 |
-
$self = self::get_instance();
|
238 |
-
|
239 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
240 |
Â
|
241 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'set_all' ) ) ) {
|
@@ -254,19 +261,18 @@ final class ITSEC_Modules {
|
|
254 |
Â
* The new value will be validated and updated in memory. The change isn't persisted until
|
255 |
Â
* the end of the request or a manual call to {@see ITSEC_Storage::save()}.
|
256 |
Â
*
|
257 |
-
* @param string $slug
|
258 |
-
* @param string $name
|
259 |
-
* @param mixed
|
260 |
Â
*
|
261 |
Â
* @return array|false
|
262 |
Â
*/
|
263 |
Â
public static function set_setting( $slug, $name, $value ) {
|
264 |
-
$self = self::get_instance();
|
265 |
-
|
266 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
267 |
Â
|
268 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'set_all' ) ) ) {
|
269 |
Â
trigger_error( sprintf( __( 'Unable to find a valid settings object for %s. Setting was unable to be saved.', 'better-wp-security' ), $slug ) );
|
Â
|
|
270 |
Â
return false;
|
271 |
Â
}
|
272 |
Â
|
@@ -281,8 +287,7 @@ final class ITSEC_Modules {
|
|
281 |
Â
* @param ITSEC_Validator $validator
|
282 |
Â
*/
|
283 |
Â
public static function register_validator( $validator ) {
|
284 |
-
|
285 |
-
$self->_module_validators[ $validator->get_id() ] = $validator;
|
286 |
Â
}
|
287 |
Â
|
288 |
Â
/**
|
@@ -350,14 +355,14 @@ final class ITSEC_Modules {
|
|
350 |
Â
|
351 |
Â
if ( ! is_array( $self->_active_modules ) ) {
|
352 |
Â
$self->_active_modules = array();
|
353 |
-
}
|
354 |
Â
// Found data from an old format.
|
355 |
Â
foreach ( $self->_active_modules as $key => $value ) {
|
356 |
Â
if ( ! is_bool( $value ) ) {
|
357 |
-
unset( $self->_active_modules[$key] );
|
358 |
Â
|
359 |
-
if ( ! isset( $self->_active_modules[$value] ) ) {
|
360 |
-
$self->_active_modules[$value] = true;
|
361 |
Â
}
|
362 |
Â
}
|
363 |
Â
}
|
@@ -399,6 +404,7 @@ final class ITSEC_Modules {
|
|
399 |
Â
*/
|
400 |
Â
public static function get_always_active_modules() {
|
401 |
Â
$self = self::get_instance();
|
Â
|
|
402 |
Â
return array_keys( $self->_always_active_modules );
|
403 |
Â
}
|
404 |
Â
|
@@ -412,7 +418,7 @@ final class ITSEC_Modules {
|
|
412 |
Â
public static function is_always_active( $module_id ) {
|
413 |
Â
$self = self::get_instance();
|
414 |
Â
|
415 |
-
if ( ! empty( $self->_always_active_modules[$module_id] ) ) {
|
416 |
Â
return true;
|
417 |
Â
}
|
418 |
Â
|
@@ -433,7 +439,7 @@ final class ITSEC_Modules {
|
|
433 |
Â
self::get_active_modules();
|
434 |
Â
}
|
435 |
Â
|
436 |
-
if ( ! empty( $self->_always_active_modules[$module_id] ) ) {
|
437 |
Â
return true;
|
438 |
Â
}
|
439 |
Â
|
@@ -469,8 +475,10 @@ final class ITSEC_Modules {
|
|
469 |
Â
$was_active = $self->_active_modules[ $module_id ];
|
470 |
Â
}
|
471 |
Â
|
472 |
-
|
473 |
-
|
Â
|
|
Â
|
|
474 |
Â
}
|
475 |
Â
|
476 |
Â
$self->_active_modules[ $module_id ] = true;
|
@@ -554,39 +562,58 @@ final class ITSEC_Modules {
|
|
554 |
Â
*
|
555 |
Â
* The file will only be loaded once and will not error if does not exist.
|
556 |
Â
*
|
557 |
-
* @param string
|
558 |
Â
* @param string|string[] $modules The modules to load the files from. Accepts either a module slug, an array of
|
559 |
Â
* module slugs, ':all' to load the files from all modules, or ':active' to load the
|
560 |
Â
* files from active modules.
|
Â
|
|
561 |
Â
*
|
562 |
Â
* @return bool|WP_Error True if a module matching the $modules parameter is found, false otherwise.
|
563 |
Â
*/
|
564 |
-
public static function load_module_file( $file, $modules = ':all' ) {
|
565 |
Â
$self = self::get_instance();
|
566 |
Â
|
567 |
Â
if ( ':all' === $modules ) {
|
568 |
Â
$modules = self::get_available_modules();
|
569 |
-
}
|
570 |
-
|
571 |
-
|
572 |
-
} else {
|
573 |
-
$modules = self::get_active_modules();
|
574 |
-
}
|
575 |
-
|
576 |
-
$modules = array_merge( $modules, array_keys( $self->_always_active_modules ) );
|
577 |
-
$modules = array_unique( $modules );
|
578 |
-
} else if ( is_string( $modules ) ) {
|
579 |
Â
$modules = array( $modules );
|
580 |
-
}
|
581 |
Â
return false;
|
582 |
Â
}
|
583 |
Â
|
584 |
Â
foreach ( $modules as $module ) {
|
585 |
-
if (
|
586 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
587 |
Â
|
588 |
-
|
589 |
-
|
Â
|
|
Â
|
|
Â
|
|
590 |
Â
}
|
591 |
Â
}
|
592 |
Â
}
|
@@ -594,6 +621,24 @@ final class ITSEC_Modules {
|
|
594 |
Â
return true;
|
595 |
Â
}
|
596 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
597 |
Â
/**
|
598 |
Â
* Fires an action to begin the registration of modules.
|
599 |
Â
*/
|
@@ -601,10 +646,22 @@ final class ITSEC_Modules {
|
|
601 |
Â
do_action( 'itsec-register-modules' );
|
602 |
Â
}
|
603 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
604 |
Â
/**
|
605 |
Â
* Load and run all active modules.
|
606 |
Â
*/
|
607 |
Â
public static function run_active_modules() {
|
Â
|
|
608 |
Â
// The active.php file is for code that will only run when the module is active.
|
609 |
Â
self::load_module_file( 'active.php', ':active' );
|
610 |
Â
}
|
@@ -648,6 +705,19 @@ final class ITSEC_Modules {
|
|
648 |
Â
do_action( 'itsec_modules_do_plugin_upgrade', $old_version, $new_version );
|
649 |
Â
}
|
650 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
651 |
Â
/**
|
652 |
Â
* Load the settings controller for all registered modules.
|
653 |
Â
*
|
@@ -662,5 +732,54 @@ final class ITSEC_Modules {
|
|
662 |
Â
|
663 |
Â
$this->_settings_files_loaded = true;
|
664 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
665 |
Â
}
|
Â
|
|
666 |
Â
ITSEC_Modules::get_instance();
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\Contracts\Runnable;
|
4 |
+
use iThemesSecurity\Exception\Unsatisfied_Module_Dependencies_Exception;
|
5 |
+
use Pimple\Container;
|
6 |
+
|
7 |
Â
final class ITSEC_Modules {
|
8 |
Â
/**
|
9 |
Â
* @var ITSEC_Modules - Static property to hold our singleton instance
|
19 |
Â
private $_module_settings = false;
|
20 |
Â
private $_module_validators = false;
|
21 |
Â
private $_settings_files_loaded = false;
|
22 |
+
private $loaded_containers = [];
|
23 |
+
private $labels = array();
|
24 |
+
|
25 |
+
/** @var Container */
|
26 |
+
private $pimple;
|
27 |
+
|
28 |
+
/** @var Psr\Container\ContainerInterface */
|
29 |
+
private $container;
|
30 |
+
|
31 |
+
/** @var bool */
|
32 |
+
private $initialized_container = false;
|
33 |
Â
|
34 |
Â
protected function __construct() {
|
35 |
Â
// Action triggered from another part of Security which runs when the settings page is loaded.
|
36 |
Â
add_action( 'itsec-settings-page-init', array( $this, 'load_settings_page' ) );
|
37 |
Â
add_action( 'itsec-logs-page-init', array( $this, 'load_settings_page' ) );
|
38 |
+
|
39 |
+
$this->pimple = new Container();
|
40 |
+
$this->container = new Pimple\Psr11\Container( $this->pimple );
|
41 |
Â
}
|
42 |
Â
|
43 |
Â
/**
|
70 |
Â
|
71 |
Â
if ( ! is_dir( $path ) ) {
|
72 |
Â
trigger_error( sprintf( __( 'An attempt to register the %1$s module failed since the supplied path (%2$s) is invalid. This could indicate an invalid modification or incomplete installation of the iThemes Security plugin. Please reinstall the plugin and try again.', 'better-wp-security' ), $slug, $path ) );
|
73 |
+
|
74 |
Â
return false;
|
75 |
Â
}
|
76 |
Â
|
77 |
Â
$self->_module_paths[ $slug ] = $path;
|
78 |
+
$self->_available_modules = array_keys( $self->_module_paths );
|
79 |
Â
|
80 |
Â
if ( 'always-active' === $type ) {
|
81 |
+
$self->_always_active_modules[ $slug ] = true;
|
82 |
+
} elseif ( 'default-active' === $type ) {
|
83 |
+
$self->_default_active_modules[ $slug ] = true;
|
84 |
Â
}
|
85 |
Â
|
86 |
Â
return true;
|
103 |
Â
unset( $self->_module_paths[ $slug ] );
|
104 |
Â
$self->_available_modules = array_keys( $self->_module_paths );
|
105 |
Â
|
106 |
+
unset( $self->_always_active_modules[ $slug ], $self->_default_active_modules[ $slug ] );
|
Â
|
|
107 |
Â
|
108 |
Â
return true;
|
109 |
Â
}
|
123 |
Â
$self = self::get_instance();
|
124 |
Â
|
125 |
Â
foreach ( $self->_module_paths as $slug => $path ) {
|
126 |
+
$self->_module_paths[ $slug ] = str_replace( $old_dir, $new_dir, $path );
|
127 |
Â
}
|
128 |
Â
}
|
129 |
Â
|
133 |
Â
* @param ITSEC_Settings $settings
|
134 |
Â
*/
|
135 |
Â
public static function register_settings( $settings ) {
|
136 |
+
self::get_instance()->_module_settings[ $settings->get_id() ] = $settings;
|
Â
|
|
137 |
Â
}
|
138 |
Â
|
139 |
Â
/**
|
167 |
Â
* @return array
|
168 |
Â
*/
|
169 |
Â
public static function get_defaults( $slug ) {
|
Â
|
|
Â
|
|
170 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
171 |
Â
|
172 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get_defaults' ) ) ) {
|
186 |
Â
* @return mixed
|
187 |
Â
*/
|
188 |
Â
public static function get_default( $slug, $name, $default = null ) {
|
Â
|
|
Â
|
|
189 |
Â
$defaults = self::get_defaults( $slug );
|
190 |
Â
|
191 |
+
if ( isset( $defaults[ $name ] ) ) {
|
192 |
+
return $defaults[ $name ];
|
193 |
Â
}
|
194 |
Â
|
195 |
Â
return $default;
|
203 |
Â
* @return array
|
204 |
Â
*/
|
205 |
Â
public static function get_settings( $slug ) {
|
Â
|
|
Â
|
|
206 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
207 |
Â
|
208 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get_all' ) ) ) {
|
223 |
Â
* @return mixed
|
224 |
Â
*/
|
225 |
Â
public static function get_setting( $slug, $name, $default = null ) {
|
Â
|
|
Â
|
|
226 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
227 |
Â
|
228 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'get' ) ) ) {
|
243 |
Â
* @return array|WP_Error
|
244 |
Â
*/
|
245 |
Â
public static function set_settings( $slug, $settings ) {
|
Â
|
|
Â
|
|
246 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
247 |
Â
|
248 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'set_all' ) ) ) {
|
261 |
Â
* The new value will be validated and updated in memory. The change isn't persisted until
|
262 |
Â
* the end of the request or a manual call to {@see ITSEC_Storage::save()}.
|
263 |
Â
*
|
264 |
+
* @param string $slug The module slug.
|
265 |
+
* @param string $name The setting name to updated.
|
266 |
+
* @param mixed $value The settings' new value.
|
267 |
Â
*
|
268 |
Â
* @return array|false
|
269 |
Â
*/
|
270 |
Â
public static function set_setting( $slug, $name, $value ) {
|
Â
|
|
Â
|
|
271 |
Â
$settings_obj = self::get_settings_obj( $slug );
|
272 |
Â
|
273 |
Â
if ( is_null( $settings_obj ) || ! is_callable( array( $settings_obj, 'set_all' ) ) ) {
|
274 |
Â
trigger_error( sprintf( __( 'Unable to find a valid settings object for %s. Setting was unable to be saved.', 'better-wp-security' ), $slug ) );
|
275 |
+
|
276 |
Â
return false;
|
277 |
Â
}
|
278 |
Â
|
287 |
Â
* @param ITSEC_Validator $validator
|
288 |
Â
*/
|
289 |
Â
public static function register_validator( $validator ) {
|
290 |
+
self::get_instance()->_module_validators[ $validator->get_id() ] = $validator;
|
Â
|
|
291 |
Â
}
|
292 |
Â
|
293 |
Â
/**
|
355 |
Â
|
356 |
Â
if ( ! is_array( $self->_active_modules ) ) {
|
357 |
Â
$self->_active_modules = array();
|
358 |
+
} elseif ( isset( $self->_active_modules[0] ) ) {
|
359 |
Â
// Found data from an old format.
|
360 |
Â
foreach ( $self->_active_modules as $key => $value ) {
|
361 |
Â
if ( ! is_bool( $value ) ) {
|
362 |
+
unset( $self->_active_modules[ $key ] );
|
363 |
Â
|
364 |
+
if ( ! isset( $self->_active_modules[ $value ] ) ) {
|
365 |
+
$self->_active_modules[ $value ] = true;
|
366 |
Â
}
|
367 |
Â
}
|
368 |
Â
}
|
404 |
Â
*/
|
405 |
Â
public static function get_always_active_modules() {
|
406 |
Â
$self = self::get_instance();
|
407 |
+
|
408 |
Â
return array_keys( $self->_always_active_modules );
|
409 |
Â
}
|
410 |
Â
|
418 |
Â
public static function is_always_active( $module_id ) {
|
419 |
Â
$self = self::get_instance();
|
420 |
Â
|
421 |
+
if ( ! empty( $self->_always_active_modules[ $module_id ] ) ) {
|
422 |
Â
return true;
|
423 |
Â
}
|
424 |
Â
|
439 |
Â
self::get_active_modules();
|
440 |
Â
}
|
441 |
Â
|
442 |
+
if ( ! empty( $self->_always_active_modules[ $module_id ] ) ) {
|
443 |
Â
return true;
|
444 |
Â
}
|
445 |
Â
|
475 |
Â
$was_active = $self->_active_modules[ $module_id ];
|
476 |
Â
}
|
477 |
Â
|
478 |
+
try {
|
479 |
+
self::load_module_file( 'activate.php', $module_id );
|
480 |
+
} catch ( Unsatisfied_Module_Dependencies_Exception $e ) {
|
481 |
+
return new WP_Error( 'itsec-modules-cannot-activate-module-unsatisfied-dependencies', $e->getMessage() );
|
482 |
Â
}
|
483 |
Â
|
484 |
Â
$self->_active_modules[ $module_id ] = true;
|
562 |
Â
*
|
563 |
Â
* The file will only be loaded once and will not error if does not exist.
|
564 |
Â
*
|
565 |
+
* @param string $file The file name to load, including extension.
|
566 |
Â
* @param string|string[] $modules The modules to load the files from. Accepts either a module slug, an array of
|
567 |
Â
* module slugs, ':all' to load the files from all modules, or ':active' to load the
|
568 |
Â
* files from active modules.
|
569 |
+
* @param callable|null $process Callback to run returned values from module files through.
|
570 |
Â
*
|
571 |
Â
* @return bool|WP_Error True if a module matching the $modules parameter is found, false otherwise.
|
572 |
Â
*/
|
573 |
+
public static function load_module_file( $file, $modules = ':all', callable $process = null ) {
|
574 |
Â
$self = self::get_instance();
|
575 |
Â
|
576 |
Â
if ( ':all' === $modules ) {
|
577 |
Â
$modules = self::get_available_modules();
|
578 |
+
} elseif ( ':active' === $modules ) {
|
579 |
+
$modules = self::get_active_modules_to_run();
|
580 |
+
} elseif ( is_string( $modules ) ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
581 |
Â
$modules = array( $modules );
|
582 |
+
} elseif ( ! is_array( $modules ) ) {
|
583 |
Â
return false;
|
584 |
Â
}
|
585 |
Â
|
586 |
Â
foreach ( $modules as $module ) {
|
587 |
+
if ( empty( $self->_module_paths[ $module ] ) ) {
|
588 |
+
continue;
|
589 |
+
}
|
590 |
+
|
591 |
+
$self->load_container_definitions( $module );
|
592 |
+
$returned = null;
|
593 |
+
|
594 |
+
if ( self::get_container()->has( "module.{$module}.files" ) ) {
|
595 |
+
$files = self::get_container()->get( "module.{$module}.files" );
|
596 |
+
|
597 |
+
if ( isset( $files[ $file ] ) ) {
|
598 |
+
$returned = $files[ $file ];
|
599 |
+
}
|
600 |
+
}
|
601 |
+
|
602 |
+
if ( ! $returned ) {
|
603 |
+
$path = "{$self->_module_paths[$module]}/{$file}";
|
604 |
+
|
605 |
+
if ( ! file_exists( $path ) ) {
|
606 |
+
continue;
|
607 |
+
}
|
608 |
+
|
609 |
+
$returned = include_once( $path );
|
610 |
+
}
|
611 |
Â
|
612 |
+
if ( $returned ) {
|
613 |
+
if ( $process ) {
|
614 |
+
$process( $returned, $module );
|
615 |
+
} else {
|
616 |
+
$self->run( $returned );
|
617 |
Â
}
|
618 |
Â
}
|
619 |
Â
}
|
621 |
Â
return true;
|
622 |
Â
}
|
623 |
Â
|
624 |
+
/**
|
625 |
+
* Get a list of the active modules to run.
|
626 |
+
*
|
627 |
+
* @return string[]
|
628 |
+
*/
|
629 |
+
protected static function get_active_modules_to_run() {
|
630 |
+
if ( ITSEC_Core::is_temp_disable_modules_set() ) {
|
631 |
+
$modules = array();
|
632 |
+
} else {
|
633 |
+
$modules = self::get_active_modules();
|
634 |
+
}
|
635 |
+
|
636 |
+
$modules = array_merge( $modules, array_keys( self::get_instance()->_always_active_modules ) );
|
637 |
+
$modules = array_unique( $modules );
|
638 |
+
|
639 |
+
return $modules;
|
640 |
+
}
|
641 |
+
|
642 |
Â
/**
|
643 |
Â
* Fires an action to begin the registration of modules.
|
644 |
Â
*/
|
646 |
Â
do_action( 'itsec-register-modules' );
|
647 |
Â
}
|
648 |
Â
|
649 |
+
/**
|
650 |
+
* Initialize the container.
|
651 |
+
*/
|
652 |
+
public static function initialize_container() {
|
653 |
+
foreach ( self::get_active_modules_to_run() as $module ) {
|
654 |
+
self::get_instance()->load_container_definitions( $module );
|
655 |
+
}
|
656 |
+
|
657 |
+
self::get_instance()->initialized_container = true;
|
658 |
+
}
|
659 |
+
|
660 |
Â
/**
|
661 |
Â
* Load and run all active modules.
|
662 |
Â
*/
|
663 |
Â
public static function run_active_modules() {
|
664 |
+
self::initialize_container();
|
665 |
Â
// The active.php file is for code that will only run when the module is active.
|
666 |
Â
self::load_module_file( 'active.php', ':active' );
|
667 |
Â
}
|
705 |
Â
do_action( 'itsec_modules_do_plugin_upgrade', $old_version, $new_version );
|
706 |
Â
}
|
707 |
Â
|
708 |
+
/**
|
709 |
+
* Get the container.
|
710 |
+
*
|
711 |
+
* @return \Psr\Container\ContainerInterface
|
712 |
+
*/
|
713 |
+
public static function get_container() {
|
714 |
+
if ( ! self::get_instance()->initialized_container ) {
|
715 |
+
self::initialize_container();
|
716 |
+
}
|
717 |
+
|
718 |
+
return self::get_instance()->container;
|
719 |
+
}
|
720 |
+
|
721 |
Â
/**
|
722 |
Â
* Load the settings controller for all registered modules.
|
723 |
Â
*
|
732 |
Â
|
733 |
Â
$this->_settings_files_loaded = true;
|
734 |
Â
}
|
735 |
+
|
736 |
+
/**
|
737 |
+
* Get labels for a module.
|
738 |
+
*
|
739 |
+
* @param string $module
|
740 |
+
*
|
741 |
+
* @return array
|
742 |
+
*/
|
743 |
+
public static function get_labels( $module ) {
|
744 |
+
if ( ! isset( self::get_instance()->labels[ $module ] ) ) {
|
745 |
+
self::get_instance()->labels[ $module ] = [];
|
746 |
+
self::load_module_file( 'labels.php', $module, function ( $labels, $module ) {
|
747 |
+
if ( is_array( $labels ) ) {
|
748 |
+
self::get_instance()->labels[ $module ] = $labels;
|
749 |
+
}
|
750 |
+
} );
|
751 |
+
}
|
752 |
+
|
753 |
+
return self::get_instance()->labels[ $module ];
|
754 |
+
}
|
755 |
+
|
756 |
+
private function run( $definition ) {
|
757 |
+
if ( $definition && is_string( $definition ) ) {
|
758 |
+
$object = $this->container->get( $definition );
|
759 |
+
|
760 |
+
if ( $object instanceof Runnable ) {
|
761 |
+
$object->run();
|
762 |
+
}
|
763 |
+
}
|
764 |
+
}
|
765 |
+
|
766 |
+
/**
|
767 |
+
* Load the container definitions for a module.
|
768 |
+
*
|
769 |
+
* @param string $module
|
770 |
+
*/
|
771 |
+
private function load_container_definitions( $module ) {
|
772 |
+
if ( ! isset( $this->loaded_containers[ $module ] ) && isset( $this->_module_paths[ $module ] ) ) {
|
773 |
+
$path = $this->_module_paths[ $module ] . '/container.php';
|
774 |
+
|
775 |
+
if ( file_exists( $this->_module_paths[ $module ] . '/container.php' ) && $register = include( $path ) ) {
|
776 |
+
$this->loaded_containers[ $module ] = true;
|
777 |
+
$register( $this->pimple );
|
778 |
+
} else {
|
779 |
+
$this->loaded_containers[ $module ] = false;
|
780 |
+
}
|
781 |
+
}
|
782 |
+
}
|
783 |
Â
}
|
784 |
+
|
785 |
Â
ITSEC_Modules::get_instance();
|
core/modules/404-detection/class-itsec-four-oh-four.php
CHANGED
@@ -35,7 +35,7 @@ class ITSEC_Four_Oh_Four {
|
|
35 |
Â
! in_array( '/' . ITSEC_Lib::get_request_path(), $this->settings['white_list'], true ) &&
|
36 |
Â
! in_array( '.' . pathinfo( $uri[0], PATHINFO_EXTENSION ), $this->settings['types'], true )
|
37 |
Â
) {
|
38 |
-
ITSEC_Log::add_notice( 'four_oh_four', 'found_404', array( 'SERVER' =>
|
39 |
Â
$itsec_lockout->do_lockout( new Host_Context( 'four_oh_four' ) );
|
40 |
Â
} else {
|
41 |
Â
do_action( 'itsec_four_oh_four_whitelisted', $uri );
|
35 |
Â
! in_array( '/' . ITSEC_Lib::get_request_path(), $this->settings['white_list'], true ) &&
|
36 |
Â
! in_array( '.' . pathinfo( $uri[0], PATHINFO_EXTENSION ), $this->settings['types'], true )
|
37 |
Â
) {
|
38 |
+
ITSEC_Log::add_notice( 'four_oh_four', 'found_404', array( 'SERVER' => ITSEC_Lib::get_server_snapshot() ) );
|
39 |
Â
$itsec_lockout->do_lockout( new Host_Context( 'four_oh_four' ) );
|
40 |
Â
} else {
|
41 |
Â
do_action( 'itsec_four_oh_four_whitelisted', $uri );
|
core/modules/404-detection/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( '404 Detection', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/admin-user/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Admin User', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/away-mode/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Away Mode', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/backup/activate.php
CHANGED
@@ -3,5 +3,6 @@
|
|
3 |
Â
$settings = ITSEC_Modules::get_settings( 'backup' );
|
4 |
Â
|
5 |
Â
if ( $settings['enabled'] && $settings['interval'] > 0 ) {
|
Â
|
|
6 |
Â
ITSEC_Core::get_scheduler()->schedule( 'backup', 'backup' );
|
7 |
-
}
|
3 |
Â
$settings = ITSEC_Modules::get_settings( 'backup' );
|
4 |
Â
|
5 |
Â
if ( $settings['enabled'] && $settings['interval'] > 0 ) {
|
6 |
+
ITSEC_Core::get_scheduler()->register_custom_schedule( 'backup', DAY_IN_SECONDS * $settings['interval'] );
|
7 |
Â
ITSEC_Core::get_scheduler()->schedule( 'backup', 'backup' );
|
8 |
+
}
|
core/modules/backup/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Backup', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/backup/settings.php
CHANGED
@@ -4,7 +4,7 @@ final class ITSEC_Backup_Settings extends ITSEC_Settings {
|
|
4 |
Â
public function get_id() {
|
5 |
Â
return 'backup';
|
6 |
Â
}
|
7 |
-
|
8 |
Â
public function get_defaults() {
|
9 |
Â
return array(
|
10 |
Â
'all_sites' => false,
|
@@ -24,6 +24,7 @@ final class ITSEC_Backup_Settings extends ITSEC_Settings {
|
|
24 |
Â
}
|
25 |
Â
|
26 |
Â
protected function handle_settings_changes( $old_settings ) {
|
Â
|
|
27 |
Â
|
28 |
Â
if ( $old_settings['enabled'] !== $this->settings['enabled'] ) {
|
29 |
Â
if ( $this->settings['enabled'] ) {
|
4 |
Â
public function get_id() {
|
5 |
Â
return 'backup';
|
6 |
Â
}
|
7 |
+
|
8 |
Â
public function get_defaults() {
|
9 |
Â
return array(
|
10 |
Â
'all_sites' => false,
|
24 |
Â
}
|
25 |
Â
|
26 |
Â
protected function handle_settings_changes( $old_settings ) {
|
27 |
+
parent::handle_settings_changes( $old_settings );
|
28 |
Â
|
29 |
Â
if ( $old_settings['enabled'] !== $this->settings['enabled'] ) {
|
30 |
Â
if ( $this->settings['enabled'] ) {
|
core/modules/ban-users/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Ban Users', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/ban-users/lists/user-agents.php
ADDED
@@ -0,0 +1,1543 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
"1Noonbot",
|
5 |
+
"1on1searchBot",
|
6 |
+
"3D_SEARCH",
|
7 |
+
"3DE_SEARCH2",
|
8 |
+
"3GSE",
|
9 |
+
"50.nu",
|
10 |
+
"192.comAgent",
|
11 |
+
"360Spider",
|
12 |
+
"A6-Indexer",
|
13 |
+
"AASP",
|
14 |
+
"ABACHOBot",
|
15 |
+
"Abonti",
|
16 |
+
"abot",
|
17 |
+
"AbotEmailSearch",
|
18 |
+
"Aboundex",
|
19 |
+
"AboutUsBot",
|
20 |
+
"AccMonitor Compliance",
|
21 |
+
"accoona",
|
22 |
+
"AChulkov.NET page walker",
|
23 |
+
"Acme.Spider",
|
24 |
+
"AcoonBot",
|
25 |
+
"acquia-crawler",
|
26 |
+
"ActiveTouristBot",
|
27 |
+
"Acunetix",
|
28 |
+
"Ad Muncher",
|
29 |
+
"AdamM",
|
30 |
+
"adbeat_bot",
|
31 |
+
"adminshop.com",
|
32 |
+
"Advanced Email",
|
33 |
+
"AESOP_com_SpiderMan",
|
34 |
+
"AESpider",
|
35 |
+
"AF Knowledge Now Verity",
|
36 |
+
"aggregator:Vocus",
|
37 |
+
"ah-ha.com",
|
38 |
+
"AIBOT",
|
39 |
+
"aiHitBot",
|
40 |
+
"aipbot",
|
41 |
+
"AISIID",
|
42 |
+
"AITCSRobot",
|
43 |
+
"Akamai-SiteSnapshot",
|
44 |
+
"AlexaWebSearchPlatform",
|
45 |
+
"AlexaBot",
|
46 |
+
"AlexfDownload",
|
47 |
+
"Alexibot",
|
48 |
+
"AlkalineBOT",
|
49 |
+
"All Acronyms",
|
50 |
+
"Amfibibot",
|
51 |
+
"AmPmPPC.com",
|
52 |
+
"AMZNKAssocBot",
|
53 |
+
"Anemone",
|
54 |
+
"Anonymous",
|
55 |
+
"Anonymouse.org",
|
56 |
+
"AnotherBot",
|
57 |
+
"AnswerBot",
|
58 |
+
"AnswerBus",
|
59 |
+
"AnswerChase PROve",
|
60 |
+
"AntBot",
|
61 |
+
"antibot-",
|
62 |
+
"AntiSantyWorm",
|
63 |
+
"Antro.Net",
|
64 |
+
"AONDE-Spider",
|
65 |
+
"Aport",
|
66 |
+
"Aqua_Products",
|
67 |
+
"AraBot",
|
68 |
+
"Arachmo",
|
69 |
+
"Arachnophilia",
|
70 |
+
"archive.org_bot",
|
71 |
+
"aria eQualizer",
|
72 |
+
"aria2",
|
73 |
+
"arianna.libero.it",
|
74 |
+
"Arikus_Spider",
|
75 |
+
"Art-Online.com",
|
76 |
+
"ArtavisBot",
|
77 |
+
"Artera",
|
78 |
+
"ASpider",
|
79 |
+
"ASPSeek",
|
80 |
+
"asterias",
|
81 |
+
"AstroFind",
|
82 |
+
"athenusbot",
|
83 |
+
"AtlocalBot",
|
84 |
+
"Atomic_Email_Hunter",
|
85 |
+
"attach",
|
86 |
+
"attrakt",
|
87 |
+
"attributor",
|
88 |
+
"Attributor.comBot",
|
89 |
+
"augurfind",
|
90 |
+
"AURESYS",
|
91 |
+
"AutoBaron",
|
92 |
+
"autoemailspider",
|
93 |
+
"autowebdir",
|
94 |
+
"AVSearch-",
|
95 |
+
"axfeedsbot",
|
96 |
+
"Axonize-bot",
|
97 |
+
"Ayna",
|
98 |
+
"b2w",
|
99 |
+
"BackDoorBot",
|
100 |
+
"BackRub",
|
101 |
+
"BackStreet Browser",
|
102 |
+
"BackWeb",
|
103 |
+
"Baiduspider-video",
|
104 |
+
"Bandit",
|
105 |
+
"BatchFTP",
|
106 |
+
"baypup",
|
107 |
+
"BDFetch",
|
108 |
+
"BecomeBot",
|
109 |
+
"BecomeJPBot",
|
110 |
+
"BeetleBot",
|
111 |
+
"Bender",
|
112 |
+
"besserscheitern-crawl",
|
113 |
+
"betaBot",
|
114 |
+
"Big Brother",
|
115 |
+
"Big Data",
|
116 |
+
"Bigado.com",
|
117 |
+
"BigCliqueBot",
|
118 |
+
"Bigfoot",
|
119 |
+
"BIGLOTRON",
|
120 |
+
"Bilbo",
|
121 |
+
"BilgiBetaBot",
|
122 |
+
"BilgiBot",
|
123 |
+
"binlar",
|
124 |
+
"bintellibot",
|
125 |
+
"bitlybot",
|
126 |
+
"BitvoUserAgent",
|
127 |
+
"bixocrawler",
|
128 |
+
"Bizbot003",
|
129 |
+
"BizBot04",
|
130 |
+
"BizBot04 kirk.overleaf.com",
|
131 |
+
"Black.Hole",
|
132 |
+
"Black Hole",
|
133 |
+
"Blackbird",
|
134 |
+
"BlackWidow",
|
135 |
+
"bladder fusion",
|
136 |
+
"Blaiz-Bee",
|
137 |
+
"BLEXBot",
|
138 |
+
"Blinkx",
|
139 |
+
"BlitzBOT",
|
140 |
+
"Blog Conversation Project",
|
141 |
+
"BlogMyWay",
|
142 |
+
"BlogPulseLive",
|
143 |
+
"BlogRefsBot",
|
144 |
+
"BlogScope",
|
145 |
+
"Blogslive",
|
146 |
+
"BloobyBot",
|
147 |
+
"BlowFish",
|
148 |
+
"BLT",
|
149 |
+
"bnf.fr_bot",
|
150 |
+
"BoaConstrictor",
|
151 |
+
"BoardReader-Image-Fetcher",
|
152 |
+
"BOI_crawl_00",
|
153 |
+
"BOIA-Scan-Agent",
|
154 |
+
"BOIA.ORG-Scan-Agent",
|
155 |
+
"boitho.com-dc",
|
156 |
+
"Bookmark Buddy",
|
157 |
+
"bosug",
|
158 |
+
"Bot Apoena",
|
159 |
+
"BotALot",
|
160 |
+
"BotRightHere",
|
161 |
+
"Botswana",
|
162 |
+
"bottybot",
|
163 |
+
"BpBot",
|
164 |
+
"BRAINTIME_SEARCH",
|
165 |
+
"BrokenLinkCheck.com",
|
166 |
+
"BrowserEmulator",
|
167 |
+
"BrowserMob",
|
168 |
+
"BruinBot",
|
169 |
+
"BSearchR&D",
|
170 |
+
"BSpider",
|
171 |
+
"btbot",
|
172 |
+
"Btsearch",
|
173 |
+
"Buddy",
|
174 |
+
"Buibui",
|
175 |
+
"BuildCMS",
|
176 |
+
"BuiltBotTough",
|
177 |
+
"Bullseye",
|
178 |
+
"bumblebee",
|
179 |
+
"BunnySlippers",
|
180 |
+
"BuscadorClarin",
|
181 |
+
"Butterfly",
|
182 |
+
"BuyHawaiiBot",
|
183 |
+
"BuzzBot",
|
184 |
+
"byindia",
|
185 |
+
"BySpider",
|
186 |
+
"byteserver",
|
187 |
+
"bzBot",
|
188 |
+
"c r a w l 3 r",
|
189 |
+
"CacheBlaster",
|
190 |
+
"CACTVS Chemistry",
|
191 |
+
"Caddbot",
|
192 |
+
"Cafi",
|
193 |
+
"Camcrawler",
|
194 |
+
"CamelStampede",
|
195 |
+
"Canon-WebRecord",
|
196 |
+
"Canon-WebRecordPro",
|
197 |
+
"CareerBot",
|
198 |
+
"casper",
|
199 |
+
"cataguru",
|
200 |
+
"CatchBot",
|
201 |
+
"CazoodleBot",
|
202 |
+
"CCBot",
|
203 |
+
"CCGCrawl",
|
204 |
+
"ccubee",
|
205 |
+
"CD-Preload",
|
206 |
+
"CE-Preload",
|
207 |
+
"Cegbfeieh",
|
208 |
+
"Cerberian Drtrs",
|
209 |
+
"CERT FigleafBot",
|
210 |
+
"cfetch",
|
211 |
+
"CFNetwork",
|
212 |
+
"Chameleon",
|
213 |
+
"ChangeDetection",
|
214 |
+
"Charlotte",
|
215 |
+
"Check&Get",
|
216 |
+
"Checkbot",
|
217 |
+
"Checklinks",
|
218 |
+
"checkprivacy",
|
219 |
+
"CheeseBot",
|
220 |
+
"ChemieDE-NodeBot",
|
221 |
+
"CherryPicker",
|
222 |
+
"CherryPickerElite",
|
223 |
+
"CherryPickerSE",
|
224 |
+
"Chilkat",
|
225 |
+
"ChinaClaw",
|
226 |
+
"CipinetBot",
|
227 |
+
"cis455crawler",
|
228 |
+
"citeseerxbot",
|
229 |
+
"cizilla.com",
|
230 |
+
"ClariaBot",
|
231 |
+
"clshttp",
|
232 |
+
"Clushbot",
|
233 |
+
"cmsworldmap",
|
234 |
+
"coccoc",
|
235 |
+
"CollapsarWEB",
|
236 |
+
"Collector",
|
237 |
+
"combine",
|
238 |
+
"conceptbot",
|
239 |
+
"ConnectSearch",
|
240 |
+
"conpilot",
|
241 |
+
"ContentSmartz",
|
242 |
+
"ContextAd",
|
243 |
+
"contype",
|
244 |
+
"cookieNET",
|
245 |
+
"CoolBot†",
|
246 |
+
"CoolCheck",
|
247 |
+
"Copernic",
|
248 |
+
"Copier",
|
249 |
+
"CopyRightCheck",
|
250 |
+
"core-project",
|
251 |
+
"cosmos",
|
252 |
+
"Covario-IDS",
|
253 |
+
"Cowbot-",
|
254 |
+
"Cowdog",
|
255 |
+
"crabbyBot",
|
256 |
+
"crawl",
|
257 |
+
"Crawl_Application",
|
258 |
+
"crawl.UserAgent",
|
259 |
+
"CrawlConvera",
|
260 |
+
"crawler",
|
261 |
+
"crawler_for_infomine",
|
262 |
+
"CRAWLER-ALTSE.VUNET.ORG-Lynx",
|
263 |
+
"crawler-upgrade-config",
|
264 |
+
"crawler.kpricorn.org",
|
265 |
+
"crawler@",
|
266 |
+
"crawler4j",
|
267 |
+
"crawler43.ejupiter.com",
|
268 |
+
"Crawly",
|
269 |
+
"CreativeCommons",
|
270 |
+
"Crescent",
|
271 |
+
"Crescent Internet ToolPak HTTP OLE Control",
|
272 |
+
"cs-crawler",
|
273 |
+
"CSE HTML Validator",
|
274 |
+
"CSHttpClient",
|
275 |
+
"Cuasarbot",
|
276 |
+
"culsearch",
|
277 |
+
"Curl",
|
278 |
+
"Custo",
|
279 |
+
"Cutbot",
|
280 |
+
"cvaulev",
|
281 |
+
"Cyberdog",
|
282 |
+
"CyberNavi_WebGet",
|
283 |
+
"CyberSpyder",
|
284 |
+
"CydralSpider",
|
285 |
+
"D1GArabicEngine",
|
286 |
+
"DataCha0s",
|
287 |
+
"DataFountains",
|
288 |
+
"DataparkSearch",
|
289 |
+
"DataSpearSpiderBot",
|
290 |
+
"DataSpider",
|
291 |
+
"Dattatec.com",
|
292 |
+
"Dattatec.com-Sitios-Top",
|
293 |
+
"Daumoa",
|
294 |
+
"DAUMOA-video",
|
295 |
+
"DAUMOA-web",
|
296 |
+
"Declumbot",
|
297 |
+
"Deepindex",
|
298 |
+
"deepnet",
|
299 |
+
"DeepTrawl",
|
300 |
+
"dejan",
|
301 |
+
"del.icio.us-thumbnails",
|
302 |
+
"DelvuBot",
|
303 |
+
"Deweb",
|
304 |
+
"DiaGem",
|
305 |
+
"Diamond",
|
306 |
+
"DiamondBot",
|
307 |
+
"diavol",
|
308 |
+
"DiBot",
|
309 |
+
"didaxusbot",
|
310 |
+
"DigExt",
|
311 |
+
"Digger",
|
312 |
+
"DiGi-RSSBot",
|
313 |
+
"DigitalArchivesBot",
|
314 |
+
"DigOut4U",
|
315 |
+
"DIIbot",
|
316 |
+
"Dillo",
|
317 |
+
"Dir_Snatch.exe",
|
318 |
+
"DISCo",
|
319 |
+
"DISCo Pump",
|
320 |
+
"discobot",
|
321 |
+
"DISCoFinder",
|
322 |
+
"Distilled-Reputation-Monitor",
|
323 |
+
"Dit",
|
324 |
+
"DittoSpyder",
|
325 |
+
"DjangoTraineeBot",
|
326 |
+
"DKIMRepBot",
|
327 |
+
"DoCoMo",
|
328 |
+
"DOF-Verify",
|
329 |
+
"domaincrawler",
|
330 |
+
"DomainScan",
|
331 |
+
"DomainWatcher",
|
332 |
+
"dotbot",
|
333 |
+
"DotSpotsBot",
|
334 |
+
"Dow Jonesbot",
|
335 |
+
"Download",
|
336 |
+
"Download Demon",
|
337 |
+
"Downloader",
|
338 |
+
"DOY",
|
339 |
+
"dragonfly",
|
340 |
+
"Drip",
|
341 |
+
"drone",
|
342 |
+
"DTAAgent",
|
343 |
+
"dtSearchSpider",
|
344 |
+
"dumbot",
|
345 |
+
"Dwaar",
|
346 |
+
"Dwaarbot",
|
347 |
+
"DXSeeker",
|
348 |
+
"EAH",
|
349 |
+
"EasouSpider",
|
350 |
+
"EasyDL",
|
351 |
+
"ebingbong",
|
352 |
+
"EC2LinkFinder",
|
353 |
+
"eCairn-Grabber",
|
354 |
+
"eCatch",
|
355 |
+
"eChooseBot",
|
356 |
+
"ecxi",
|
357 |
+
"EdisterBot",
|
358 |
+
"EduGovSearch",
|
359 |
+
"egothor",
|
360 |
+
"eidetica.com",
|
361 |
+
"EirGrabber",
|
362 |
+
"ElisaBot",
|
363 |
+
"EllerdaleBot",
|
364 |
+
"EMail Exractor",
|
365 |
+
"EmailCollector",
|
366 |
+
"EmailLeach",
|
367 |
+
"EmailSiphon",
|
368 |
+
"EmailWolf",
|
369 |
+
"EMPAS_ROBOT",
|
370 |
+
"EnaBot",
|
371 |
+
"endeca",
|
372 |
+
"EnigmaBot",
|
373 |
+
"Enswer Neuro",
|
374 |
+
"EntityCubeBot",
|
375 |
+
"EroCrawler",
|
376 |
+
"eStyleSearch",
|
377 |
+
"eSyndiCat",
|
378 |
+
"Eurosoft-Bot",
|
379 |
+
"Evaal",
|
380 |
+
"Eventware",
|
381 |
+
"Everest-Vulcan",
|
382 |
+
"Exabot",
|
383 |
+
"Exabot-Images",
|
384 |
+
"Exabot-Test",
|
385 |
+
"Exabot-XXX",
|
386 |
+
"ExaBotTest",
|
387 |
+
"ExactSearch",
|
388 |
+
"exactseek.com",
|
389 |
+
"exooba",
|
390 |
+
"Exploder",
|
391 |
+
"explorersearch",
|
392 |
+
"extract",
|
393 |
+
"Extractor",
|
394 |
+
"ExtractorPro",
|
395 |
+
"EyeNetIE",
|
396 |
+
"ez-robot",
|
397 |
+
"Ezooms",
|
398 |
+
"factbot",
|
399 |
+
"FairAd Client",
|
400 |
+
"falcon",
|
401 |
+
"Falconsbot",
|
402 |
+
"fast-search-engine",
|
403 |
+
"FAST Data Document",
|
404 |
+
"FAST ESP",
|
405 |
+
"fastbot",
|
406 |
+
"fastbot.de",
|
407 |
+
"FatBot",
|
408 |
+
"Favcollector",
|
409 |
+
"Faviconizer",
|
410 |
+
"FDM",
|
411 |
+
"FedContractorBot",
|
412 |
+
"feedfinder",
|
413 |
+
"FelixIDE",
|
414 |
+
"fembot",
|
415 |
+
"fetch_ici",
|
416 |
+
"Fetch API Request",
|
417 |
+
"fgcrawler",
|
418 |
+
"FHscan",
|
419 |
+
"fido",
|
420 |
+
"Filangy",
|
421 |
+
"FileHound",
|
422 |
+
"FindAnISP.com_ISP_Finder",
|
423 |
+
"findlinks",
|
424 |
+
"FindWeb",
|
425 |
+
"Firebat",
|
426 |
+
"Fish-Search-Robot",
|
427 |
+
"Flaming AttackBot",
|
428 |
+
"Flamingo_SearchEngine",
|
429 |
+
"FlashCapture",
|
430 |
+
"FlashGet",
|
431 |
+
"flicky",
|
432 |
+
"FlickySearchBot",
|
433 |
+
"flunky",
|
434 |
+
"focused_crawler",
|
435 |
+
"FollowSite",
|
436 |
+
"Foobot",
|
437 |
+
"Fooooo_Web_Video_Crawl",
|
438 |
+
"Fopper",
|
439 |
+
"FormulaFinderBot",
|
440 |
+
"Forschungsportal",
|
441 |
+
"fr_crawler",
|
442 |
+
"Francis",
|
443 |
+
"Freecrawl",
|
444 |
+
"FreshDownload",
|
445 |
+
"freshlinks.exe",
|
446 |
+
"FriendFeedBot",
|
447 |
+
"frodo.at",
|
448 |
+
"froGgle",
|
449 |
+
"FrontPage",
|
450 |
+
"Froola",
|
451 |
+
"FU-NBI",
|
452 |
+
"full_breadth_crawler",
|
453 |
+
"FunnelBack",
|
454 |
+
"FunWebProducts",
|
455 |
+
"FurlBot",
|
456 |
+
"g00g1e",
|
457 |
+
"G10-Bot",
|
458 |
+
"Gaisbot",
|
459 |
+
"GalaxyBot",
|
460 |
+
"gazz",
|
461 |
+
"gcreep",
|
462 |
+
"generate_infomine_category_classifiers",
|
463 |
+
"genevabot",
|
464 |
+
"genieBot",
|
465 |
+
"GenieBotRD_SmallCrawl",
|
466 |
+
"Genieo",
|
467 |
+
"Geomaxenginebot",
|
468 |
+
"geometabot",
|
469 |
+
"GeonaBot",
|
470 |
+
"GeoVisu",
|
471 |
+
"GermCrawler",
|
472 |
+
"GetHTMLContents",
|
473 |
+
"Getleft",
|
474 |
+
"GetRight",
|
475 |
+
"GetSmart",
|
476 |
+
"GetURL.rexx",
|
477 |
+
"GetWeb!",
|
478 |
+
"Giant",
|
479 |
+
"GigablastOpenSource",
|
480 |
+
"Gigabot",
|
481 |
+
"Girafabot",
|
482 |
+
"GleameBot",
|
483 |
+
"gnome-vfs",
|
484 |
+
"Go-Ahead-Got-It",
|
485 |
+
"Go!Zilla",
|
486 |
+
"GoForIt.com",
|
487 |
+
"GOFORITBOT",
|
488 |
+
"gold",
|
489 |
+
"Golem",
|
490 |
+
"GoodJelly",
|
491 |
+
"Gordon-College-Google-Mini",
|
492 |
+
"goroam",
|
493 |
+
"GoSeebot",
|
494 |
+
"gotit",
|
495 |
+
"Govbot",
|
496 |
+
"GPU p2p",
|
497 |
+
"grab",
|
498 |
+
"Grabber",
|
499 |
+
"GrabNet",
|
500 |
+
"Grafula",
|
501 |
+
"grapeFX",
|
502 |
+
"grapeshot",
|
503 |
+
"GrapeshotCrawler",
|
504 |
+
"grbot",
|
505 |
+
"GreenYogi [ZSEBOT]",
|
506 |
+
"Gromit",
|
507 |
+
"GroupMe",
|
508 |
+
"GroupHigh",
|
509 |
+
"grub",
|
510 |
+
"grub-client",
|
511 |
+
"Grubclient-",
|
512 |
+
"GrubNG",
|
513 |
+
"GruBot",
|
514 |
+
"GSLFbot",
|
515 |
+
"GT::WWW",
|
516 |
+
"Gulliver",
|
517 |
+
"GulperBot",
|
518 |
+
"GurujiBot",
|
519 |
+
"GVC",
|
520 |
+
"GVC BUSINESS",
|
521 |
+
"gvcbot.com",
|
522 |
+
"HappyFunBot",
|
523 |
+
"harvest",
|
524 |
+
"HarvestMan",
|
525 |
+
"Hatena Antenna",
|
526 |
+
"Hawler",
|
527 |
+
"Hazel's Ferret hopper",
|
528 |
+
"hcat",
|
529 |
+
"hclsreport-crawler",
|
530 |
+
"HD nutch agent",
|
531 |
+
"Header_Test_Client",
|
532 |
+
"healia",
|
533 |
+
"Helix",
|
534 |
+
"hijbul-heritrix-crawler",
|
535 |
+
"HiScan",
|
536 |
+
"HiSoftware AccMonitor",
|
537 |
+
"HiSoftware AccVerify",
|
538 |
+
"hitcrawler_",
|
539 |
+
"hivaBot",
|
540 |
+
"hloader",
|
541 |
+
"HMSEbot",
|
542 |
+
"HMView",
|
543 |
+
"hoge",
|
544 |
+
"holmes",
|
545 |
+
"HomePageSearch",
|
546 |
+
"Hooblybot-Image",
|
547 |
+
"HooWWWer",
|
548 |
+
"Hostcrawler",
|
549 |
+
"HSFT - Link",
|
550 |
+
"HSFT - LVU",
|
551 |
+
"HSlide",
|
552 |
+
"ht:",
|
553 |
+
"htdig",
|
554 |
+
"Html Link Validator",
|
555 |
+
"HTMLParser",
|
556 |
+
"HTTP::Lite",
|
557 |
+
"httplib",
|
558 |
+
"HTTrack",
|
559 |
+
"Huaweisymantecspider",
|
560 |
+
"hul-wax",
|
561 |
+
"humanlinks",
|
562 |
+
"HyperEstraier",
|
563 |
+
"Hyperix",
|
564 |
+
"ia_archiver",
|
565 |
+
"IAArchiver-",
|
566 |
+
"ibuena",
|
567 |
+
"iCab",
|
568 |
+
"ICDS-Ingestion",
|
569 |
+
"ichiro",
|
570 |
+
"iCopyright Conductor",
|
571 |
+
"id-search",
|
572 |
+
"IDBot",
|
573 |
+
"IEAutoDiscovery",
|
574 |
+
"IECheck",
|
575 |
+
"iHWebChecker",
|
576 |
+
"IIITBOT",
|
577 |
+
"iim_405",
|
578 |
+
"IlseBot",
|
579 |
+
"IlTrovatore",
|
580 |
+
"Iltrovatore-Setaccio",
|
581 |
+
"ImageBot",
|
582 |
+
"imagefortress",
|
583 |
+
"ImagesHereImagesThereImagesEverywhere",
|
584 |
+
"ImageVisu",
|
585 |
+
"imds_monitor",
|
586 |
+
"imo-google-robot-intelink",
|
587 |
+
"IncyWincy",
|
588 |
+
"Industry Cortexcrawler",
|
589 |
+
"indylabs_marius",
|
590 |
+
"InelaBot",
|
591 |
+
"Inet32 Ctrl",
|
592 |
+
"inetbot",
|
593 |
+
"InfoLink",
|
594 |
+
"INFOMINE",
|
595 |
+
"infomine.ucr.edu",
|
596 |
+
"InfoNaviRobot",
|
597 |
+
"Informant",
|
598 |
+
"Infoseek",
|
599 |
+
"InfoTekies",
|
600 |
+
"InfoUSABot",
|
601 |
+
"INGRID",
|
602 |
+
"Inktomi",
|
603 |
+
"InsightsCollector",
|
604 |
+
"InsightsWorksBot",
|
605 |
+
"InspireBot",
|
606 |
+
"InsumaScout",
|
607 |
+
"Intelix",
|
608 |
+
"InterGET",
|
609 |
+
"Internet Ninja",
|
610 |
+
"InternetLinkAgent",
|
611 |
+
"Interseek",
|
612 |
+
"IOI",
|
613 |
+
"ip-web-crawler.com",
|
614 |
+
"IPAdd",
|
615 |
+
"Ipselonbot",
|
616 |
+
"Iria",
|
617 |
+
"IRLbot",
|
618 |
+
"Iron33",
|
619 |
+
"Isara",
|
620 |
+
"iSearch",
|
621 |
+
"iSiloX",
|
622 |
+
"IsraeliSearch",
|
623 |
+
"IstellaBot",
|
624 |
+
"its-learning",
|
625 |
+
"IU_CSCI_B659_class_crawler",
|
626 |
+
"iVia",
|
627 |
+
"iVia Page Fetcher",
|
628 |
+
"JadynAve",
|
629 |
+
"JadynAveBot",
|
630 |
+
"jakarta",
|
631 |
+
"Java",
|
632 |
+
"Jbot",
|
633 |
+
"JemmaTheTourist",
|
634 |
+
"JennyBot",
|
635 |
+
"Jetbot",
|
636 |
+
"JetBrains Omea Pro",
|
637 |
+
"JetCar",
|
638 |
+
"Jim",
|
639 |
+
"JoBo",
|
640 |
+
"JobSpider_BA",
|
641 |
+
"JOC",
|
642 |
+
"JoeDog",
|
643 |
+
"JoyScapeBot",
|
644 |
+
"JSpyda",
|
645 |
+
"JubiiRobot",
|
646 |
+
"jumpstation",
|
647 |
+
"Junut",
|
648 |
+
"JustView",
|
649 |
+
"Jyxobot",
|
650 |
+
"K.S.Bot",
|
651 |
+
"KakcleBot",
|
652 |
+
"kalooga",
|
653 |
+
"KaloogaBot",
|
654 |
+
"kanagawa",
|
655 |
+
"KATATUDO-Spider",
|
656 |
+
"Katipo",
|
657 |
+
"kbeta1",
|
658 |
+
"Kenjin.Spider",
|
659 |
+
"KeywenBot",
|
660 |
+
"Keyword.Density",
|
661 |
+
"Keyword Density",
|
662 |
+
"kinjabot",
|
663 |
+
"KIT-Fireball",
|
664 |
+
"Kitenga-crawler-bot",
|
665 |
+
"KiwiStatus",
|
666 |
+
"kmbot-",
|
667 |
+
"kmccrew",
|
668 |
+
"Knight",
|
669 |
+
"KnowItAll",
|
670 |
+
"Knowledge.com",
|
671 |
+
"Knowledge Engine",
|
672 |
+
"KoepaBot",
|
673 |
+
"Koninklijke",
|
674 |
+
"KrOWLer",
|
675 |
+
"KSbot",
|
676 |
+
"kuloko-bot",
|
677 |
+
"kulturarw3",
|
678 |
+
"KummHttp",
|
679 |
+
"Kurzor",
|
680 |
+
"Kyluka",
|
681 |
+
"L.webis",
|
682 |
+
"LabelGrab",
|
683 |
+
"Labhoo",
|
684 |
+
"labourunions411",
|
685 |
+
"lachesis",
|
686 |
+
"Lament",
|
687 |
+
"LamerExterminator",
|
688 |
+
"LapozzBot",
|
689 |
+
"larbin",
|
690 |
+
"LARBIN-EXPERIMENTAL",
|
691 |
+
"LBot",
|
692 |
+
"LBBROWSER",
|
693 |
+
"LeapTag",
|
694 |
+
"LeechFTP",
|
695 |
+
"LeechGet",
|
696 |
+
"LetsCrawl.com",
|
697 |
+
"LexiBot",
|
698 |
+
"LexxeBot",
|
699 |
+
"lftp",
|
700 |
+
"libcrawl",
|
701 |
+
"libiViaCore",
|
702 |
+
"libWeb",
|
703 |
+
"libwww",
|
704 |
+
"libwww-perl",
|
705 |
+
"likse",
|
706 |
+
"Linguee",
|
707 |
+
"Link",
|
708 |
+
"link_checker",
|
709 |
+
"LinkAlarm",
|
710 |
+
"linkbot",
|
711 |
+
"LinkCheck by Siteimprove.com",
|
712 |
+
"LinkChecker",
|
713 |
+
"linkdexbot",
|
714 |
+
"linkdex.com",
|
715 |
+
"LinkextractorPro",
|
716 |
+
"LinkLint",
|
717 |
+
"linklooker",
|
718 |
+
"Linkman",
|
719 |
+
"LinkScan",
|
720 |
+
"LinksCrawler",
|
721 |
+
"LinksManager.com_bot",
|
722 |
+
"LinkSweeper",
|
723 |
+
"linkwalker",
|
724 |
+
"LiteFinder",
|
725 |
+
"LitlrBot",
|
726 |
+
"Little Grabber at Skanktale.com",
|
727 |
+
"Livelapbot",
|
728 |
+
"LM Harvester",
|
729 |
+
"LMQueueBot",
|
730 |
+
"LNSpiderguy",
|
731 |
+
"LoadTimeBot",
|
732 |
+
"LocalcomBot",
|
733 |
+
"locust",
|
734 |
+
"LolongBot",
|
735 |
+
"LookBot",
|
736 |
+
"Lsearch",
|
737 |
+
"lssbot",
|
738 |
+
"LWP",
|
739 |
+
"lwp-request",
|
740 |
+
"lwp-trivial",
|
741 |
+
"LWP::Simple",
|
742 |
+
"Lycos_Spider",
|
743 |
+
"Lydia Entity",
|
744 |
+
"LynnBot",
|
745 |
+
"Lytranslate",
|
746 |
+
"Mag-Net",
|
747 |
+
"Magnet",
|
748 |
+
"magpie-crawler",
|
749 |
+
"Magus",
|
750 |
+
"Mail.Ru",
|
751 |
+
"Mail.Ru_Bot",
|
752 |
+
"MAINSEEK_BOT",
|
753 |
+
"Mammoth",
|
754 |
+
"MarkWatch",
|
755 |
+
"MaSagool",
|
756 |
+
"masidani_bot_",
|
757 |
+
"Mass",
|
758 |
+
"Mata.Hari",
|
759 |
+
"Mata Hari",
|
760 |
+
"matentzn at cs dot man dot ac dot uk",
|
761 |
+
"maxamine.com--robot",
|
762 |
+
"maxamine.com-robot",
|
763 |
+
"maxomobot",
|
764 |
+
"Maxthon$",
|
765 |
+
"McBot",
|
766 |
+
"MediaFox",
|
767 |
+
"medrabbit",
|
768 |
+
"Megite",
|
769 |
+
"MemacBot",
|
770 |
+
"Memo",
|
771 |
+
"MendeleyBot",
|
772 |
+
"Mercator-",
|
773 |
+
"mercuryboard_user_agent_sql_injection.nasl",
|
774 |
+
"MerzScope",
|
775 |
+
"metacarta",
|
776 |
+
"Metager2",
|
777 |
+
"metager2-verification-bot",
|
778 |
+
"MetaGloss",
|
779 |
+
"METAGOPHER",
|
780 |
+
"metal",
|
781 |
+
"metaquerier.cs.uiuc.edu",
|
782 |
+
"METASpider",
|
783 |
+
"Metaspinner",
|
784 |
+
"MetaURI",
|
785 |
+
"MetaURI API",
|
786 |
+
"MFC_Tear_Sample",
|
787 |
+
"MFcrawler",
|
788 |
+
"MFHttpScan",
|
789 |
+
"Microsoft.URL",
|
790 |
+
"MIIxpc",
|
791 |
+
"miner",
|
792 |
+
"mini-robot",
|
793 |
+
"minibot",
|
794 |
+
"miniRank",
|
795 |
+
"Mirror",
|
796 |
+
"Missigua Locator",
|
797 |
+
"Mister.PiX",
|
798 |
+
"Mister PiX",
|
799 |
+
"Miva",
|
800 |
+
"MJ12bot",
|
801 |
+
"mnoGoSearch",
|
802 |
+
"mod_accessibility",
|
803 |
+
"moduna.com",
|
804 |
+
"moget",
|
805 |
+
"MojeekBot",
|
806 |
+
"MOMspider",
|
807 |
+
"MonkeyCrawl",
|
808 |
+
"MOSES",
|
809 |
+
"Motor",
|
810 |
+
"mowserbot",
|
811 |
+
"MQbot",
|
812 |
+
"MSE360",
|
813 |
+
"MSFrontPage",
|
814 |
+
"MSIECrawler",
|
815 |
+
"MSIndianWebcrawl",
|
816 |
+
"MSMOBOT",
|
817 |
+
"Msnbot",
|
818 |
+
"msnbot-products",
|
819 |
+
"MSNPTC",
|
820 |
+
"MSRBOT",
|
821 |
+
"MT-Soft",
|
822 |
+
"MultiText",
|
823 |
+
"My_Little_SearchEngine_Project",
|
824 |
+
"my-heritrix-crawler",
|
825 |
+
"MyApp",
|
826 |
+
"MYCOMPANYBOT",
|
827 |
+
"mycrawler",
|
828 |
+
"MyEngines-US-Bot",
|
829 |
+
"MyFamilyBot",
|
830 |
+
"Myra",
|
831 |
+
"nabot",
|
832 |
+
"nabot_",
|
833 |
+
"Najdi.si",
|
834 |
+
"Nambu",
|
835 |
+
"NAMEPROTECT",
|
836 |
+
"NatchCVS",
|
837 |
+
"naver",
|
838 |
+
"naverbookmarkcrawler",
|
839 |
+
"NaverBot",
|
840 |
+
"Navroad",
|
841 |
+
"NearSite",
|
842 |
+
"NEC-MeshExplorer",
|
843 |
+
"NeoScioCrawler",
|
844 |
+
"NerdByNature.Bot",
|
845 |
+
"NerdyBot",
|
846 |
+
"Nerima-crawl-",
|
847 |
+
"Nessus",
|
848 |
+
"NESSUS::SOAP",
|
849 |
+
"nestReader",
|
850 |
+
"Net::Trackback",
|
851 |
+
"NetAnts",
|
852 |
+
"NetCarta CyberPilot Pro",
|
853 |
+
"Netcraft",
|
854 |
+
"NetID.com",
|
855 |
+
"NetMechanic",
|
856 |
+
"Netprospector",
|
857 |
+
"NetResearchServer",
|
858 |
+
"NetScoop",
|
859 |
+
"NetSeer",
|
860 |
+
"NetShift=",
|
861 |
+
"NetSongBot",
|
862 |
+
"Netsparker",
|
863 |
+
"NetSpider",
|
864 |
+
"NetSrcherP",
|
865 |
+
"NetZip",
|
866 |
+
"NetZip-Downloader",
|
867 |
+
"NewMedhunt",
|
868 |
+
"news",
|
869 |
+
"News_Search_App",
|
870 |
+
"NewsGatherer",
|
871 |
+
"Newsgroupreporter",
|
872 |
+
"NewsTroveBot",
|
873 |
+
"NextGenSearchBot",
|
874 |
+
"nextthing.org",
|
875 |
+
"NHSEWalker",
|
876 |
+
"nicebot",
|
877 |
+
"NICErsPRO",
|
878 |
+
"niki-bot",
|
879 |
+
"NimbleCrawler",
|
880 |
+
"nimbus-1",
|
881 |
+
"ninetowns",
|
882 |
+
"Ninja",
|
883 |
+
"NjuiceBot",
|
884 |
+
"NLese",
|
885 |
+
"Nogate",
|
886 |
+
"Nomad-V2.x",
|
887 |
+
"NoteworthyBot",
|
888 |
+
"NPbot",
|
889 |
+
"NPBot-",
|
890 |
+
"NRCan intranet",
|
891 |
+
"NSDL_Search_Bot",
|
892 |
+
"nu_tch-princeton",
|
893 |
+
"nuggetize.com",
|
894 |
+
"nutch",
|
895 |
+
"nutch1",
|
896 |
+
"NutchCVS",
|
897 |
+
"NutchOrg",
|
898 |
+
"NWSpider",
|
899 |
+
"Nymesis",
|
900 |
+
"nys-crawler",
|
901 |
+
"ObjectsSearch",
|
902 |
+
"oBot",
|
903 |
+
"Obvius external linkcheck",
|
904 |
+
"Occam",
|
905 |
+
"Ocelli",
|
906 |
+
"Octopus",
|
907 |
+
"ODP entries",
|
908 |
+
"Offline.Explorer",
|
909 |
+
"Offline Explorer",
|
910 |
+
"Offline Navigator",
|
911 |
+
"OGspider",
|
912 |
+
"OmiExplorer_Bot",
|
913 |
+
"OmniExplorer_Bot",
|
914 |
+
"omnifind",
|
915 |
+
"OmniWeb",
|
916 |
+
"OnetSzukaj",
|
917 |
+
"online link validator",
|
918 |
+
"OOZBOT",
|
919 |
+
"Openbot",
|
920 |
+
"Openfind",
|
921 |
+
"Openfind data",
|
922 |
+
"OpenHoseBot",
|
923 |
+
"OpenIntelligenceData",
|
924 |
+
"OpenISearch",
|
925 |
+
"OpenSearchServer_Bot",
|
926 |
+
"OpiDig",
|
927 |
+
"optidiscover",
|
928 |
+
"OrangeBot",
|
929 |
+
"ORISBot",
|
930 |
+
"ornl_crawler_1",
|
931 |
+
"ORNL_Mercury",
|
932 |
+
"osis-project.jp",
|
933 |
+
"OutfoxBot",
|
934 |
+
"OutfoxMelonBot",
|
935 |
+
"OWLER-BOT",
|
936 |
+
"Owlin",
|
937 |
+
"owsBot",
|
938 |
+
"ozelot",
|
939 |
+
"P3P Client",
|
940 |
+
"page_verifier",
|
941 |
+
"PageBitesHyperBot",
|
942 |
+
"Pagebull",
|
943 |
+
"PageDown",
|
944 |
+
"PageFetcher",
|
945 |
+
"PageGrabber",
|
946 |
+
"PagePeeker",
|
947 |
+
"PageRank Monitor",
|
948 |
+
"pamsnbot.htm",
|
949 |
+
"Panopy",
|
950 |
+
"panscient.com",
|
951 |
+
"Pansophica",
|
952 |
+
"Papa Foto",
|
953 |
+
"PaperLiBot",
|
954 |
+
"parasite",
|
955 |
+
"parsijoo",
|
956 |
+
"Pathtraq",
|
957 |
+
"Pattern",
|
958 |
+
"Patwebbot",
|
959 |
+
"pavuk",
|
960 |
+
"PaxleFramework",
|
961 |
+
"PBBOT",
|
962 |
+
"pcBrowser",
|
963 |
+
"pd-crawler",
|
964 |
+
"PECL::HTTP",
|
965 |
+
"Pcore-HTTP",
|
966 |
+
"penthesila",
|
967 |
+
"PeoplePal",
|
968 |
+
"perform_crawl",
|
969 |
+
"PerMan",
|
970 |
+
"PGP-KA",
|
971 |
+
"PHPCrawl",
|
972 |
+
"PhpDig",
|
973 |
+
"PicoSearch",
|
974 |
+
"pipBot",
|
975 |
+
"pipeLiner",
|
976 |
+
"Pita",
|
977 |
+
"pixfinder",
|
978 |
+
"PiyushBot",
|
979 |
+
"planetwork",
|
980 |
+
"PleaseCrawl",
|
981 |
+
"Plucker",
|
982 |
+
"Plukkie",
|
983 |
+
"Plumtree",
|
984 |
+
"Pockey",
|
985 |
+
"Pockey-GetHTML",
|
986 |
+
"PoCoHTTP",
|
987 |
+
"pogodak.ba",
|
988 |
+
"Pogodak.co.yu",
|
989 |
+
"Poirot",
|
990 |
+
"polybot",
|
991 |
+
"Pompos",
|
992 |
+
"Poodle predictor",
|
993 |
+
"PopScreenBot",
|
994 |
+
"PostPost",
|
995 |
+
"PrivacyFinder",
|
996 |
+
"ProjectWF-java-test-crawler",
|
997 |
+
"ProPowerBot",
|
998 |
+
"ProWebWalker",
|
999 |
+
"psbot",
|
1000 |
+
"psbot-page",
|
1001 |
+
"PSS-Bot",
|
1002 |
+
"psycheclone",
|
1003 |
+
"pub-crawler",
|
1004 |
+
"pucl",
|
1005 |
+
"pulseBot (pulse",
|
1006 |
+
"Pump",
|
1007 |
+
"purebot",
|
1008 |
+
"PWeBot",
|
1009 |
+
"pycurl",
|
1010 |
+
"Python-urllib",
|
1011 |
+
"pythonic-crawler",
|
1012 |
+
"PythonWikipediaBot",
|
1013 |
+
"q1",
|
1014 |
+
"QEAVis agent",
|
1015 |
+
"QFKBot",
|
1016 |
+
"qualidade",
|
1017 |
+
"Qualidator.com",
|
1018 |
+
"QuepasaCreep",
|
1019 |
+
"QueryN.Metasearch",
|
1020 |
+
"QueryN Metasearch",
|
1021 |
+
"quest.durato",
|
1022 |
+
"Quintura-Crw",
|
1023 |
+
"QunarBot",
|
1024 |
+
"Qweery_robot.txt_CheckBot",
|
1025 |
+
"QweeryBot",
|
1026 |
+
"r2iBot",
|
1027 |
+
"R6_CommentReader",
|
1028 |
+
"R6_FeedFetcher",
|
1029 |
+
"R6_VoteReader",
|
1030 |
+
"RaBot",
|
1031 |
+
"Radian6",
|
1032 |
+
"radian6_linkcheck",
|
1033 |
+
"RAMPyBot",
|
1034 |
+
"RankurBot",
|
1035 |
+
"RcStartBot",
|
1036 |
+
"RealDownload",
|
1037 |
+
"Reaper",
|
1038 |
+
"REBI-shoveler",
|
1039 |
+
"Recorder",
|
1040 |
+
"RedBot",
|
1041 |
+
"RedCarpet",
|
1042 |
+
"ReGet",
|
1043 |
+
"RepoMonkey",
|
1044 |
+
"RepoMonkey Bait",
|
1045 |
+
"Riddler",
|
1046 |
+
"RIIGHTBOT",
|
1047 |
+
"RiseNetBot",
|
1048 |
+
"RiverglassScanner",
|
1049 |
+
"RoboPal",
|
1050 |
+
"Robosourcer",
|
1051 |
+
"robot",
|
1052 |
+
"robotek",
|
1053 |
+
"robots",
|
1054 |
+
"Robozilla",
|
1055 |
+
"rogerBot",
|
1056 |
+
"Rome Client",
|
1057 |
+
"Rondello",
|
1058 |
+
"Rotondo",
|
1059 |
+
"Roverbot",
|
1060 |
+
"RPT-HTTPClient",
|
1061 |
+
"rtgibot",
|
1062 |
+
"RufusBot",
|
1063 |
+
"Runnk online rss reader",
|
1064 |
+
"SafetyNet",
|
1065 |
+
"s~stremor-crawler",
|
1066 |
+
"S2Bot",
|
1067 |
+
"SafariBookmarkChecker",
|
1068 |
+
"SaladSpoon",
|
1069 |
+
"Sapienti",
|
1070 |
+
"SBIder",
|
1071 |
+
"SBL-BOT",
|
1072 |
+
"SCFCrawler",
|
1073 |
+
"Scich",
|
1074 |
+
"ScientificCommons.org",
|
1075 |
+
"ScollSpider",
|
1076 |
+
"ScooperBot",
|
1077 |
+
"Scooter",
|
1078 |
+
"ScoutJet",
|
1079 |
+
"ScrapeBox",
|
1080 |
+
"Scrapy",
|
1081 |
+
"SCrawlTest",
|
1082 |
+
"Scrubby",
|
1083 |
+
"scSpider",
|
1084 |
+
"Scumbot",
|
1085 |
+
"SeaMonkey$",
|
1086 |
+
"Search-Channel",
|
1087 |
+
"Search-Engine-Studio",
|
1088 |
+
"search.KumKie.com",
|
1089 |
+
"search.msn.com",
|
1090 |
+
"search.updated.com",
|
1091 |
+
"search.usgs.gov",
|
1092 |
+
"Search Publisher",
|
1093 |
+
"Searcharoo.NET",
|
1094 |
+
"SearchBlox",
|
1095 |
+
"searchbot",
|
1096 |
+
"searchengine",
|
1097 |
+
"searchhippo.com",
|
1098 |
+
"SearchIt-Bot",
|
1099 |
+
"searchmarking",
|
1100 |
+
"searchmarks",
|
1101 |
+
"searchmee_v",
|
1102 |
+
"SearchmetricsBot",
|
1103 |
+
"searchmining",
|
1104 |
+
"SearchnowBot_v1",
|
1105 |
+
"searchpreview",
|
1106 |
+
"SearchSpider.com",
|
1107 |
+
"SearQuBot",
|
1108 |
+
"Seekbot",
|
1109 |
+
"Seeker.lookseek.com",
|
1110 |
+
"SeeqBot",
|
1111 |
+
"seeqpod-vertical-crawler",
|
1112 |
+
"Selflinkchecker",
|
1113 |
+
"Semager",
|
1114 |
+
"semanticdiscovery",
|
1115 |
+
"Semantifire1",
|
1116 |
+
"semisearch",
|
1117 |
+
"SemrushBot",
|
1118 |
+
"Senrigan",
|
1119 |
+
"SEOENGWorldBot",
|
1120 |
+
"ShablastBot",
|
1121 |
+
"ShadowWebAnalyzer",
|
1122 |
+
"Shareaza",
|
1123 |
+
"Shelob",
|
1124 |
+
"sherlock",
|
1125 |
+
"ShopWiki",
|
1126 |
+
"ShowLinks",
|
1127 |
+
"ShowyouBot",
|
1128 |
+
"siclab",
|
1129 |
+
"silk",
|
1130 |
+
"Siphon",
|
1131 |
+
"SiteArchive",
|
1132 |
+
"SiteCheck-sitecrawl",
|
1133 |
+
"sitecheck.internetseer.com",
|
1134 |
+
"SiteFinder",
|
1135 |
+
"SiteGuardBot",
|
1136 |
+
"SiteOrbiter",
|
1137 |
+
"SiteSnagger",
|
1138 |
+
"SiteSucker",
|
1139 |
+
"SiteSweeper",
|
1140 |
+
"SiteXpert",
|
1141 |
+
"SkimBot",
|
1142 |
+
"SkimWordsBot",
|
1143 |
+
"SkreemRBot",
|
1144 |
+
"skygrid",
|
1145 |
+
"Skywalker",
|
1146 |
+
"Sleipnir",
|
1147 |
+
"slow-crawler",
|
1148 |
+
"SlySearch",
|
1149 |
+
"smart-crawler",
|
1150 |
+
"SmartDownload",
|
1151 |
+
"Smarte",
|
1152 |
+
"smartwit.com",
|
1153 |
+
"Snake",
|
1154 |
+
"Snapbot",
|
1155 |
+
"SnapPreviewBot",
|
1156 |
+
"Snappy",
|
1157 |
+
"snookit",
|
1158 |
+
"Snooper",
|
1159 |
+
"Snoopy",
|
1160 |
+
"SocialSearcher",
|
1161 |
+
"SocSciBot",
|
1162 |
+
"SOFT411 Directory",
|
1163 |
+
"sogou",
|
1164 |
+
"sohu-search",
|
1165 |
+
"sohu agent",
|
1166 |
+
"Sokitomi",
|
1167 |
+
"Solbot",
|
1168 |
+
"sootle",
|
1169 |
+
"Sosospider",
|
1170 |
+
"Space Bison",
|
1171 |
+
"Space Fung",
|
1172 |
+
"SpaceBison",
|
1173 |
+
"SpankBot",
|
1174 |
+
"spanner",
|
1175 |
+
"Spatineo Monitor Controller",
|
1176 |
+
"special_archiver",
|
1177 |
+
"SpeedySpider",
|
1178 |
+
"Sphider",
|
1179 |
+
"Sphider2",
|
1180 |
+
"spider",
|
1181 |
+
"Spider.TerraNautic.net",
|
1182 |
+
"SpiderEngine",
|
1183 |
+
"SpiderKU",
|
1184 |
+
"SpiderMan",
|
1185 |
+
"Spinn3r",
|
1186 |
+
"Spinne",
|
1187 |
+
"sportcrew-Bot",
|
1188 |
+
"spyder3.microsys.com",
|
1189 |
+
"sqlmap",
|
1190 |
+
"Squid-Prefetch",
|
1191 |
+
"SquidClamAV_Redirector",
|
1192 |
+
"Sqworm",
|
1193 |
+
"SrevBot",
|
1194 |
+
"sslbot",
|
1195 |
+
"SSM Agent",
|
1196 |
+
"StackRambler",
|
1197 |
+
"StarDownloader",
|
1198 |
+
"statbot",
|
1199 |
+
"statcrawler",
|
1200 |
+
"statedept-crawler",
|
1201 |
+
"Steeler",
|
1202 |
+
"STEGMANN-Bot",
|
1203 |
+
"stero",
|
1204 |
+
"Stripper",
|
1205 |
+
"Stumbler",
|
1206 |
+
"suchclip",
|
1207 |
+
"sucker",
|
1208 |
+
"SumeetBot",
|
1209 |
+
"SumitBot",
|
1210 |
+
"SummizeBot",
|
1211 |
+
"SummizeFeedReader",
|
1212 |
+
"SuperBot",
|
1213 |
+
"superbot.com",
|
1214 |
+
"SuperHTTP",
|
1215 |
+
"SuperLumin",
|
1216 |
+
"SuperPagesBot",
|
1217 |
+
"Supybot",
|
1218 |
+
"SURF",
|
1219 |
+
"Surfbot",
|
1220 |
+
"SurfControl",
|
1221 |
+
"SurveyBot",
|
1222 |
+
"suzuran",
|
1223 |
+
"SWEBot",
|
1224 |
+
"swish-e",
|
1225 |
+
"SygolBot",
|
1226 |
+
"SynapticWalker",
|
1227 |
+
"Syntryx ANT Scout Chassis Pheromone",
|
1228 |
+
"SystemSearch-robot",
|
1229 |
+
"Szukacz",
|
1230 |
+
"T-H-U-N-D-E-R-S-T-O-N-E",
|
1231 |
+
"Tailrank",
|
1232 |
+
"tAkeOut",
|
1233 |
+
"TAMU_CRAWLER",
|
1234 |
+
"TapuzBot",
|
1235 |
+
"Tarantula",
|
1236 |
+
"targetblaster.com",
|
1237 |
+
"TargetYourNews.com",
|
1238 |
+
"TAUSDataBot",
|
1239 |
+
"taxinomiabot",
|
1240 |
+
"Tecomi",
|
1241 |
+
"TeezirBot",
|
1242 |
+
"Teleport",
|
1243 |
+
"Teleport Pro",
|
1244 |
+
"TeleportPro",
|
1245 |
+
"Telesoft",
|
1246 |
+
"Teradex Mapper",
|
1247 |
+
"TERAGRAM_CRAWLER",
|
1248 |
+
"TerrawizBot",
|
1249 |
+
"testbot",
|
1250 |
+
"testing of",
|
1251 |
+
"TextBot",
|
1252 |
+
"thatrobotsite.com",
|
1253 |
+
"The.Intraformant",
|
1254 |
+
"The Dyslexalizer",
|
1255 |
+
"The Intraformant",
|
1256 |
+
"TheNomad",
|
1257 |
+
"Theophrastus",
|
1258 |
+
"theusefulbot",
|
1259 |
+
"TheUsefulbot_",
|
1260 |
+
"ThumbBot",
|
1261 |
+
"thumbshots-de-bot",
|
1262 |
+
"tigerbot",
|
1263 |
+
"TightTwatBot",
|
1264 |
+
"TinEye",
|
1265 |
+
"Titan",
|
1266 |
+
"to-dress_ru_bot_",
|
1267 |
+
"to-night-Bot",
|
1268 |
+
"toCrawl",
|
1269 |
+
"Topicalizer",
|
1270 |
+
"topicblogs",
|
1271 |
+
"Toplistbot",
|
1272 |
+
"TopServer PHP",
|
1273 |
+
"topyx-crawler",
|
1274 |
+
"Touche",
|
1275 |
+
"TourlentaScanner",
|
1276 |
+
"TPSystem",
|
1277 |
+
"TRAAZI",
|
1278 |
+
"TranSGeniKBot",
|
1279 |
+
"travel-search",
|
1280 |
+
"TravelBot",
|
1281 |
+
"TravelLazerBot",
|
1282 |
+
"Treezy",
|
1283 |
+
"TREX",
|
1284 |
+
"TridentSpider",
|
1285 |
+
"Trovator",
|
1286 |
+
"True_Robot",
|
1287 |
+
"tScholarsBot",
|
1288 |
+
"TsWebBot",
|
1289 |
+
"TulipChain",
|
1290 |
+
"turingos",
|
1291 |
+
"turnit",
|
1292 |
+
"TurnitinBot",
|
1293 |
+
"TutorGigBot",
|
1294 |
+
"TweetedTimes",
|
1295 |
+
"TweetmemeBot",
|
1296 |
+
"TwengaBot",
|
1297 |
+
"TwengaBot-Discover",
|
1298 |
+
"Twiceler",
|
1299 |
+
"Twikle",
|
1300 |
+
"twinuffbot",
|
1301 |
+
"Twisted PageGetter",
|
1302 |
+
"Twitturls",
|
1303 |
+
"Twitturly",
|
1304 |
+
"TygoBot",
|
1305 |
+
"TygoProwler",
|
1306 |
+
"Typhoeus",
|
1307 |
+
"U.S. Government Printing Office",
|
1308 |
+
"uberbot",
|
1309 |
+
"ucb-nutch",
|
1310 |
+
"UCSD-Crawler",
|
1311 |
+
"UdmSearch",
|
1312 |
+
"UFAM-crawler-",
|
1313 |
+
"Ultraseek",
|
1314 |
+
"UnChaos",
|
1315 |
+
"unchaos_crawler_",
|
1316 |
+
"UnisterBot",
|
1317 |
+
"UniversalSearch",
|
1318 |
+
"UnwindFetchor",
|
1319 |
+
"UofTDB_experiment",
|
1320 |
+
"updated",
|
1321 |
+
"URI::Fetch",
|
1322 |
+
"url_gather",
|
1323 |
+
"URL-Checker",
|
1324 |
+
"URL Control",
|
1325 |
+
"URLAppendBot",
|
1326 |
+
"URLBlaze",
|
1327 |
+
"urlchecker",
|
1328 |
+
"urlck",
|
1329 |
+
"UrlDispatcher",
|
1330 |
+
"urllib",
|
1331 |
+
"URLSpiderPro",
|
1332 |
+
"URLy.Warning",
|
1333 |
+
"USAF AFKN",
|
1334 |
+
"usasearch",
|
1335 |
+
"USS-Cosmix",
|
1336 |
+
"USyd-NLP-Spider",
|
1337 |
+
"Vacobot",
|
1338 |
+
"Vacuum",
|
1339 |
+
"VadixBot",
|
1340 |
+
"Vagabondo",
|
1341 |
+
"Validator",
|
1342 |
+
"Valkyrie",
|
1343 |
+
"vBSEO",
|
1344 |
+
"VCI",
|
1345 |
+
"Vegi bot",
|
1346 |
+
"VerbstarBot",
|
1347 |
+
"VeriCiteCrawler",
|
1348 |
+
"Verifactrola",
|
1349 |
+
"Verity-URL-Gateway",
|
1350 |
+
"vermut",
|
1351 |
+
"versus",
|
1352 |
+
"versus.integis.ch",
|
1353 |
+
"viasarchivinginformation.html",
|
1354 |
+
"vikspider",
|
1355 |
+
"VIP",
|
1356 |
+
"VIPr",
|
1357 |
+
"virus-detector",
|
1358 |
+
"VisBot",
|
1359 |
+
"Vishal For CLIA",
|
1360 |
+
"VisWeb",
|
1361 |
+
"vlad",
|
1362 |
+
"vlsearch",
|
1363 |
+
"VMBot",
|
1364 |
+
"VocusBot",
|
1365 |
+
"VoidEYE",
|
1366 |
+
"VoilaBot",
|
1367 |
+
"Vortex",
|
1368 |
+
"voyager",
|
1369 |
+
"voyager-hc",
|
1370 |
+
"voyager-partner-deep",
|
1371 |
+
"VSE",
|
1372 |
+
"vspider",
|
1373 |
+
"W3C_Unicorn",
|
1374 |
+
"W3C-WebCon",
|
1375 |
+
"w3m",
|
1376 |
+
"w3search",
|
1377 |
+
"wacbot",
|
1378 |
+
"wastrix",
|
1379 |
+
"WatzBot",
|
1380 |
+
"wauuu engine",
|
1381 |
+
"Wavefire",
|
1382 |
+
"Waypath",
|
1383 |
+
"Wazzup",
|
1384 |
+
"Wazzup1.0.4800",
|
1385 |
+
"wbdbot",
|
1386 |
+
"web-agent",
|
1387 |
+
"Web-Sniffer",
|
1388 |
+
"Web.Image.Collector",
|
1389 |
+
"Web Link Validator",
|
1390 |
+
"Web Magnet",
|
1391 |
+
"webalta",
|
1392 |
+
"WebaltBot",
|
1393 |
+
"WebAuto",
|
1394 |
+
"webbandit",
|
1395 |
+
"webbot",
|
1396 |
+
"webbul-bot",
|
1397 |
+
"WebCapture",
|
1398 |
+
"webcheck",
|
1399 |
+
"Webclipping.com",
|
1400 |
+
"webcollage",
|
1401 |
+
"WebCopier",
|
1402 |
+
"WebCopy",
|
1403 |
+
"WebCorp",
|
1404 |
+
"webcrawl.net",
|
1405 |
+
"webcrawler",
|
1406 |
+
"WebDownloader for",
|
1407 |
+
"Webdup",
|
1408 |
+
"WebEMailExtrac",
|
1409 |
+
"WebEMailExtrac.*",
|
1410 |
+
"WebEnhancer",
|
1411 |
+
"WebFerret",
|
1412 |
+
"webfetch",
|
1413 |
+
"WebFetcher",
|
1414 |
+
"WebGather",
|
1415 |
+
"WebGo IS",
|
1416 |
+
"webGobbler",
|
1417 |
+
"WebImages",
|
1418 |
+
"Webinator-search2.fasthealth.com",
|
1419 |
+
"Webinator-WBI",
|
1420 |
+
"WebIndex",
|
1421 |
+
"WebIndexer",
|
1422 |
+
"weblayers",
|
1423 |
+
"WebLeacher",
|
1424 |
+
"WeblexBot",
|
1425 |
+
"WebLinker",
|
1426 |
+
"webLyzard",
|
1427 |
+
"WebmasterCoffee",
|
1428 |
+
"WebmasterWorld",
|
1429 |
+
"WebmasterWorldForumBot",
|
1430 |
+
"WebMiner",
|
1431 |
+
"WebMoose",
|
1432 |
+
"WeBot",
|
1433 |
+
"WebPix",
|
1434 |
+
"WebReaper",
|
1435 |
+
"WebRipper",
|
1436 |
+
"WebSauger",
|
1437 |
+
"Webscan",
|
1438 |
+
"websearchbench",
|
1439 |
+
"WebSite",
|
1440 |
+
"websitemirror",
|
1441 |
+
"WebSpear",
|
1442 |
+
"websphinx.test",
|
1443 |
+
"WebSpider",
|
1444 |
+
"Webster",
|
1445 |
+
"Webster.Pro",
|
1446 |
+
"Webster Pro",
|
1447 |
+
"WebStripper",
|
1448 |
+
"WebTrafficExpress",
|
1449 |
+
"WebTrends Link Analyzer",
|
1450 |
+
"webvac",
|
1451 |
+
"webwalk",
|
1452 |
+
"WebWalker",
|
1453 |
+
"Webwasher",
|
1454 |
+
"WebWatch",
|
1455 |
+
"WebWhacker",
|
1456 |
+
"WebXM",
|
1457 |
+
"WebZip",
|
1458 |
+
"Weddings.info",
|
1459 |
+
"wenbin",
|
1460 |
+
"WEPA",
|
1461 |
+
"WeRelateBot",
|
1462 |
+
"Whacker",
|
1463 |
+
"whisper",
|
1464 |
+
"Widow",
|
1465 |
+
"WikiaBot",
|
1466 |
+
"Wikio",
|
1467 |
+
"wikiwix-bot-",
|
1468 |
+
"WinHttp.WinHttpRequest",
|
1469 |
+
"WinHTTP Example",
|
1470 |
+
"WIRE",
|
1471 |
+
"wired-digital-newsbot",
|
1472 |
+
"WISEbot",
|
1473 |
+
"WISENutbot",
|
1474 |
+
"wish-la",
|
1475 |
+
"wish-project",
|
1476 |
+
"wisponbot",
|
1477 |
+
"WMCAI-robot",
|
1478 |
+
"wminer",
|
1479 |
+
"WMSBot",
|
1480 |
+
"woriobot",
|
1481 |
+
"worldshop",
|
1482 |
+
"WorQmada",
|
1483 |
+
"Wotbox",
|
1484 |
+
"WPScan",
|
1485 |
+
"wume_crawler",
|
1486 |
+
"WWW-Mechanize",
|
1487 |
+
"www.freeloader.com.",
|
1488 |
+
"WWW Collector",
|
1489 |
+
"WWWOFFLE",
|
1490 |
+
"wwwrobot",
|
1491 |
+
"wwwster",
|
1492 |
+
"WWWWanderer",
|
1493 |
+
"wwwxref",
|
1494 |
+
"Wysigot",
|
1495 |
+
"X-clawler",
|
1496 |
+
"Xaldon",
|
1497 |
+
"Xenu",
|
1498 |
+
"Xenu's",
|
1499 |
+
"Xerka MetaBot",
|
1500 |
+
"XGET",
|
1501 |
+
"xirq",
|
1502 |
+
"XmarksFetch",
|
1503 |
+
"XoviBot",
|
1504 |
+
"xqrobot",
|
1505 |
+
"Y!J",
|
1506 |
+
"Y!TunnelPro",
|
1507 |
+
"yacy.net",
|
1508 |
+
"yacybot",
|
1509 |
+
"yarienavoir.net",
|
1510 |
+
"Yasaklibot",
|
1511 |
+
"yBot",
|
1512 |
+
"YebolBot",
|
1513 |
+
"yellowJacket",
|
1514 |
+
"yes",
|
1515 |
+
"YesupBot",
|
1516 |
+
"Yeti",
|
1517 |
+
"YioopBot",
|
1518 |
+
"YisouSpider",
|
1519 |
+
"yolinkBot",
|
1520 |
+
"yoogliFetchAgent",
|
1521 |
+
"yoono",
|
1522 |
+
"Yoriwa",
|
1523 |
+
"YottaCars_Bot",
|
1524 |
+
"you-dir",
|
1525 |
+
"Z-Add Link",
|
1526 |
+
"zagrebin",
|
1527 |
+
"Zao",
|
1528 |
+
"zedzo.digest",
|
1529 |
+
"zedzo.validate",
|
1530 |
+
"zermelo",
|
1531 |
+
"Zeus",
|
1532 |
+
"Zeus Link Scout",
|
1533 |
+
"zibber-v",
|
1534 |
+
"zimeno",
|
1535 |
+
"Zing-BottaBot",
|
1536 |
+
"ZipppBot",
|
1537 |
+
"zmeu",
|
1538 |
+
"ZoomSpider",
|
1539 |
+
"ZuiBot",
|
1540 |
+
"ZumBot",
|
1541 |
+
"Zyborg",
|
1542 |
+
"Zyte",
|
1543 |
+
];
|
core/modules/brute-force/class-itsec-brute-force.php
CHANGED
@@ -39,7 +39,7 @@ class ITSEC_Brute_Force {
|
|
39 |
Â
// Failed authentication.
|
40 |
Â
|
41 |
Â
$details = ITSEC_Lib::get_login_details();
|
42 |
-
$SERVER =
|
43 |
Â
|
44 |
Â
if ( 'admin' === $username && $this->settings['auto_ban_admin'] ) {
|
45 |
Â
ITSEC_Log::add_notice( 'brute_force', 'auto-ban-admin-username', compact( 'details', 'user', 'username', 'SERVER' ) );
|
39 |
Â
// Failed authentication.
|
40 |
Â
|
41 |
Â
$details = ITSEC_Lib::get_login_details();
|
42 |
+
$SERVER = ITSEC_Lib::get_server_snapshot();
|
43 |
Â
|
44 |
Â
if ( 'admin' === $username && $this->settings['auto_ban_admin'] ) {
|
45 |
Â
ITSEC_Log::add_notice( 'brute_force', 'auto-ban-admin-username', compact( 'details', 'user', 'username', 'SERVER' ) );
|
core/modules/brute-force/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Brute Force', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/content-directory/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Change Content Directory', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/core/entries/admin-notices/components/admin-bar/index.js
CHANGED
@@ -24,7 +24,7 @@ function AdminBar( { notices, noticesLoaded, isToggled, setState } ) {
|
|
24 |
Â
<AdminBarFill>
|
25 |
Â
<div className="itsec-admin-bar__admin-notices">
|
26 |
Â
<div className={ classnames( 'itsec-admin-bar-admin-notices__trigger', { 'itsec-admin-bar-admin-notices__trigger--has-notices': notices.length > 0 } ) }>
|
27 |
-
<Button aria-expanded={ isToggled } onClick={ () => setState( { isToggled: ! isToggled } ) }>
|
28 |
Â
<Dashicon icon="megaphone" size={ 15 } />
|
29 |
Â
{ __( 'Notifications', 'better-wp-security' ) }
|
30 |
Â
</Button>
|
@@ -38,9 +38,22 @@ function AdminBar( { notices, noticesLoaded, isToggled, setState } ) {
|
|
38 |
Â
onClose={ () => setState( { isToggled: false } ) }
|
39 |
Â
onClickOutside={ ( e ) => {
|
40 |
Â
if (
|
41 |
-
e.target
|
42 |
-
|
43 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
44 |
Â
) {
|
45 |
Â
setState( { isToggled: false } );
|
46 |
Â
}
|
24 |
Â
<AdminBarFill>
|
25 |
Â
<div className="itsec-admin-bar__admin-notices">
|
26 |
Â
<div className={ classnames( 'itsec-admin-bar-admin-notices__trigger', { 'itsec-admin-bar-admin-notices__trigger--has-notices': notices.length > 0 } ) }>
|
27 |
+
<Button aria-expanded={ isToggled } onClick={ () => setState( { isToggled: ! isToggled } ) } isSecondary>
|
28 |
Â
<Dashicon icon="megaphone" size={ 15 } />
|
29 |
Â
{ __( 'Notifications', 'better-wp-security' ) }
|
30 |
Â
</Button>
|
38 |
Â
onClose={ () => setState( { isToggled: false } ) }
|
39 |
Â
onClickOutside={ ( e ) => {
|
40 |
Â
if (
|
41 |
+
! e.target || (
|
42 |
+
e.target.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
43 |
+
e.target.parentNode.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
44 |
+
! doesElementBelongToPanel( e.target )
|
45 |
+
)
|
46 |
+
) {
|
47 |
+
setState( { isToggled: false } );
|
48 |
+
}
|
49 |
+
} }
|
50 |
+
onFocusOutside={ () => {
|
51 |
+
const activeElement = document.activeElement;
|
52 |
+
|
53 |
+
if (
|
54 |
+
activeElement.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
55 |
+
( ! activeElement.parentNode || activeElement.parentNode.id !== 'itsec-admin-notices-toolbar-trigger' ) &&
|
56 |
+
! doesElementBelongToPanel( activeElement )
|
57 |
Â
) {
|
58 |
Â
setState( { isToggled: false } );
|
59 |
Â
}
|
core/modules/core/entries/admin-notices/components/admin-bar/style.scss
CHANGED
@@ -6,6 +6,8 @@
|
|
6 |
Â
|
7 |
Â
& .itsec-admin-bar-admin-notices__trigger > .components-button {
|
8 |
Â
color: $main-blue;
|
Â
|
|
Â
|
|
9 |
Â
|
10 |
Â
&:hover {
|
11 |
Â
color: lighten($main-blue, 20%);
|
6 |
Â
|
7 |
Â
& .itsec-admin-bar-admin-notices__trigger > .components-button {
|
8 |
Â
color: $main-blue;
|
9 |
+
border: none;
|
10 |
+
background: transparent;
|
11 |
Â
|
12 |
Â
&:hover {
|
13 |
Â
color: lighten($main-blue, 20%);
|
core/modules/core/entries/admin-notices/components/panel/style.scss
CHANGED
@@ -42,7 +42,7 @@
|
|
42 |
Â
}
|
43 |
Â
}
|
44 |
Â
|
45 |
-
& .itsec-admin-notice-panel__configure-trigger.components-
|
46 |
Â
padding: 5px;
|
47 |
Â
height: 30px;
|
48 |
Â
position: absolute;
|
@@ -56,7 +56,7 @@
|
|
56 |
Â
}
|
57 |
Â
}
|
58 |
Â
|
59 |
-
&.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-
|
60 |
Â
color: $main-blue;
|
61 |
Â
|
62 |
Â
&:hover {
|
42 |
Â
}
|
43 |
Â
}
|
44 |
Â
|
45 |
+
& .itsec-admin-notice-panel__configure-trigger.components-button {
|
46 |
Â
padding: 5px;
|
47 |
Â
height: 30px;
|
48 |
Â
position: absolute;
|
56 |
Â
}
|
57 |
Â
}
|
58 |
Â
|
59 |
+
&.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-button {
|
60 |
Â
color: $main-blue;
|
61 |
Â
|
62 |
Â
&:hover {
|
core/modules/core/entries/admin-notices/components/toolbar/index.js
CHANGED
@@ -50,9 +50,22 @@ function Toolbar( { notices, noticesLoaded, isToggled, setState } ) {
|
|
50 |
Â
onClose={ () => setState( { isToggled: false } ) }
|
51 |
Â
onClickOutside={ ( e ) => {
|
52 |
Â
if (
|
53 |
-
e.target
|
54 |
-
|
55 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
56 |
Â
) {
|
57 |
Â
setState( { isToggled: false } );
|
58 |
Â
}
|
50 |
Â
onClose={ () => setState( { isToggled: false } ) }
|
51 |
Â
onClickOutside={ ( e ) => {
|
52 |
Â
if (
|
53 |
+
! e.target || (
|
54 |
+
e.target.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
55 |
+
e.target.parentNode.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
56 |
+
! doesElementBelongToPanel( e.target )
|
57 |
+
)
|
58 |
+
) {
|
59 |
+
setState( { isToggled: false } );
|
60 |
+
}
|
61 |
+
} }
|
62 |
+
onFocusOutside={ () => {
|
63 |
+
const activeElement = document.activeElement;
|
64 |
+
|
65 |
+
if (
|
66 |
+
activeElement.id !== 'itsec-admin-notices-toolbar-trigger' &&
|
67 |
+
( ! activeElement.parentNode || activeElement.parentNode.id !== 'itsec-admin-notices-toolbar-trigger' ) &&
|
68 |
+
! doesElementBelongToPanel( activeElement )
|
69 |
Â
) {
|
70 |
Â
setState( { isToggled: false } );
|
71 |
Â
}
|
core/modules/core/entries/admin-notices/store/controls.js
CHANGED
@@ -12,7 +12,7 @@ import { default as triggerApiFetch } from '@wordpress/api-fetch';
|
|
12 |
Â
/**
|
13 |
Â
* Internal dependencies
|
14 |
Â
*/
|
15 |
-
import responseToError from '@ithemes/security-utils';
|
16 |
Â
|
17 |
Â
/**
|
18 |
Â
* Trigger an API Fetch request.
|
12 |
Â
/**
|
13 |
Â
* Internal dependencies
|
14 |
Â
*/
|
15 |
+
import { responseToError } from '@ithemes/security-utils';
|
16 |
Â
|
17 |
Â
/**
|
18 |
Â
* Trigger an API Fetch request.
|
core/modules/core/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Core', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/core/notices.php
ADDED
@@ -0,0 +1,73 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ITSEC_Admin_Notice_New_Feature_Core implements ITSEC_Admin_Notice {
|
4 |
+
|
5 |
+
public function get_id() {
|
6 |
+
return 'release-user-groups';
|
7 |
+
}
|
8 |
+
|
9 |
+
public function get_title() {
|
10 |
+
return '';
|
11 |
+
}
|
12 |
+
|
13 |
+
public function get_message() {
|
14 |
+
return sprintf(
|
15 |
+
esc_html__( 'New in iThemes Security version %1$s, %2$sSave Time Securing WordPress With User Groups%3$s!', 'better-wp-security' ),
|
16 |
+
ITSEC_Core::is_pro() ? '6.4.0' : '7.7.0',
|
17 |
+
'<a href="{{ $blog }}">',
|
18 |
+
'</a>'
|
19 |
+
);
|
20 |
+
}
|
21 |
+
|
22 |
+
public function get_meta() {
|
23 |
+
return array();
|
24 |
+
}
|
25 |
+
|
26 |
+
public function get_severity() {
|
27 |
+
return self::S_INFO;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function show_for_context( ITSEC_Admin_Notice_Context $context ) {
|
31 |
+
return true;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function get_actions() {
|
35 |
+
return array(
|
36 |
+
'blog' => new ITSEC_Admin_Notice_Action_Link(
|
37 |
+
add_query_arg( 'itsec_view_release_post', 'user-groups', admin_url( 'index.php' ) ),
|
38 |
+
esc_html__( 'See How It Works', 'better-wp-security' ),
|
39 |
+
ITSEC_Admin_Notice_Action::S_PRIMARY,
|
40 |
+
function () {
|
41 |
+
$this->handle_dismiss();
|
42 |
+
|
43 |
+
wp_redirect( 'https://ithemes.com/new-save-time-securing-wordpress-with-user-groups' );
|
44 |
+
die;
|
45 |
+
}
|
46 |
+
)
|
47 |
+
);
|
48 |
+
}
|
49 |
+
|
50 |
+
private function handle_dismiss() {
|
51 |
+
$dismissed = $this->get_storage();
|
52 |
+
$dismissed[] = $this->get_id();
|
53 |
+
$this->save_storage( $dismissed );
|
54 |
+
|
55 |
+
return null;
|
56 |
+
}
|
57 |
+
|
58 |
+
private function get_storage() {
|
59 |
+
$dismissed = get_site_option( 'itsec_dismissed_notices', array() );
|
60 |
+
|
61 |
+
if ( ! is_array( $dismissed ) ) {
|
62 |
+
$dismissed = array();
|
63 |
+
}
|
64 |
+
|
65 |
+
return $dismissed;
|
66 |
+
}
|
67 |
+
|
68 |
+
private function save_storage( $storage ) {
|
69 |
+
update_site_option( 'itsec_dismissed_notices', $storage );
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
ITSEC_Lib_Admin_Notices::register( new ITSEC_Admin_Notice_Globally_Dismissible( new ITSEC_Admin_Notice_Managers_Only( new ITSEC_Admin_Notice_New_Feature_Core() ) ) );
|
core/modules/database-prefix/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Change Database Prefix', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/feature-flags/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Feature Flags', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/feature-flags/settings-page.php
CHANGED
@@ -7,21 +7,21 @@ class ITSEC_Feature_Flags_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
7 |
Â
|
8 |
Â
$this->id = 'feature-flags';
|
9 |
Â
$this->title = esc_html__( 'Feature Flags', 'better-wp-security' );
|
10 |
-
$this->description = esc_html__( '
|
11 |
Â
$this->type = 'advanced';
|
12 |
Â
}
|
13 |
Â
|
14 |
Â
public function register() {
|
15 |
Â
ITSEC_Lib::load( 'feature-flags' );
|
16 |
Â
|
17 |
-
if ( ITSEC_Lib_Feature_Flags::get_available_flags() ) {
|
18 |
Â
parent::register();
|
19 |
Â
}
|
20 |
Â
}
|
21 |
Â
|
22 |
Â
protected function render_description( $form ) {
|
23 |
Â
echo '<p>';
|
24 |
-
echo
|
25 |
Â
echo '</p>';
|
26 |
Â
}
|
27 |
Â
|
@@ -43,11 +43,13 @@ class ITSEC_Feature_Flags_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
43 |
Â
$description = $config['description'];
|
44 |
Â
}
|
45 |
Â
|
46 |
-
$
|
Â
|
|
Â
|
|
47 |
Â
|
48 |
Â
$cb_opts = array();
|
49 |
Â
|
50 |
-
if (
|
51 |
Â
$cb_opts['disabled'] = true;
|
52 |
Â
}
|
53 |
Â
?>
|
@@ -60,8 +62,19 @@ class ITSEC_Feature_Flags_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
60 |
Â
<td>
|
61 |
Â
<?php $form->add_checkbox( $flag, $cb_opts ); ?>
|
62 |
Â
<?php if ( $description ): ?>
|
63 |
-
<p
|
Â
|
|
Â
|
|
Â
|
|
64 |
Â
<?php endif; ?>
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
65 |
Â
</td>
|
66 |
Â
</tr>
|
67 |
Â
</tbody>
|
7 |
Â
|
8 |
Â
$this->id = 'feature-flags';
|
9 |
Â
$this->title = esc_html__( 'Feature Flags', 'better-wp-security' );
|
10 |
+
$this->description = esc_html__( 'Feature Flags in iThemes Security allow you to try experimental features before they are released.', 'better-wp-security' );
|
11 |
Â
$this->type = 'advanced';
|
12 |
Â
}
|
13 |
Â
|
14 |
Â
public function register() {
|
15 |
Â
ITSEC_Lib::load( 'feature-flags' );
|
16 |
Â
|
17 |
+
if ( ITSEC_Lib_Feature_Flags::get_available_flags() && ITSEC_Lib_Feature_Flags::show_ui() ) {
|
18 |
Â
parent::register();
|
19 |
Â
}
|
20 |
Â
}
|
21 |
Â
|
22 |
Â
protected function render_description( $form ) {
|
23 |
Â
echo '<p>';
|
24 |
+
echo $this->description;
|
25 |
Â
echo '</p>';
|
26 |
Â
}
|
27 |
Â
|
43 |
Â
$description = $config['description'];
|
44 |
Â
}
|
45 |
Â
|
46 |
+
$enabled = ITSEC_Lib_Feature_Flags::is_enabled( $flag );
|
47 |
+
$form->set_option( $flag, $enabled );
|
48 |
+
list( $reason_code, $reason ) = ITSEC_Lib_Feature_Flags::get_reason( $flag );
|
49 |
Â
|
50 |
Â
$cb_opts = array();
|
51 |
Â
|
52 |
+
if ( 'constant' === $reason_code ) {
|
53 |
Â
$cb_opts['disabled'] = true;
|
54 |
Â
}
|
55 |
Â
?>
|
62 |
Â
<td>
|
63 |
Â
<?php $form->add_checkbox( $flag, $cb_opts ); ?>
|
64 |
Â
<?php if ( $description ): ?>
|
65 |
+
<p><?php echo $description; ?></p>
|
66 |
+
<?php endif; ?>
|
67 |
+
<?php if ( $config['documentation'] ): ?>
|
68 |
+
<p><a href="<?php echo esc_url( $config['documentation'] ) ?>"><?php esc_html_e( 'Read the documentation', 'better-wp-security' ); ?></a></p>
|
69 |
Â
<?php endif; ?>
|
70 |
+
|
71 |
+
<p class="description">
|
72 |
+
<?php if ( $enabled ): ?>
|
73 |
+
<?php echo esc_html( sprintf( __( 'Enabled reason: %s', 'better-wp-security' ), $reason ) ); ?>
|
74 |
+
<?php else: ?>
|
75 |
+
<?php echo esc_html( sprintf( __( 'Disabled reason: %s', 'better-wp-security' ), $reason ) ); ?>
|
76 |
+
<?php endif; ?>
|
77 |
+
</p>
|
78 |
Â
</td>
|
79 |
Â
</tr>
|
80 |
Â
</tbody>
|
core/modules/file-change/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'File Change', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/file-permissions/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'File Permissions', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/global/active.php
CHANGED
@@ -1,8 +1,11 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
function itsec_global_filter_whitelisted_ips( $whitelisted_ips ) {
|
4 |
Â
return array_merge( $whitelisted_ips, ITSEC_Modules::get_setting( 'global', 'lockout_white_list', array() ) );
|
5 |
Â
}
|
Â
|
|
6 |
Â
add_filter( 'itsec_white_ips', 'itsec_global_filter_whitelisted_ips', 0 );
|
7 |
Â
|
8 |
Â
/**
|
@@ -115,3 +118,14 @@ function itsec_basename_attachment_thumbs( $data ) {
|
|
115 |
Â
}
|
116 |
Â
|
117 |
Â
add_filter( 'wp_update_attachment_metadata', 'itsec_basename_attachment_thumbs' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use \iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
function itsec_global_filter_whitelisted_ips( $whitelisted_ips ) {
|
6 |
Â
return array_merge( $whitelisted_ips, ITSEC_Modules::get_setting( 'global', 'lockout_white_list', array() ) );
|
7 |
Â
}
|
8 |
+
|
9 |
Â
add_filter( 'itsec_white_ips', 'itsec_global_filter_whitelisted_ips', 0 );
|
10 |
Â
|
11 |
Â
/**
|
118 |
Â
}
|
119 |
Â
|
120 |
Â
add_filter( 'wp_update_attachment_metadata', 'itsec_basename_attachment_thumbs' );
|
121 |
+
|
122 |
+
function itsec_register_global_user_group_settings( User_Groups\Settings_Registry $registry ) {
|
123 |
+
$registry->register( new User_Groups\Settings_Registration( 'global', 'manage_group', User_Groups\Settings_Registration::T_MULTIPLE, static function () {
|
124 |
+
return [
|
125 |
+
'title' => __( 'Manage iThemes Security', 'better-wp-security' ),
|
126 |
+
'description' => __( 'Allow users in the group to manage iThemes Security.', 'better-wp-security' ),
|
127 |
+
];
|
128 |
+
} ) );
|
129 |
+
}
|
130 |
+
|
131 |
+
add_action( 'itsec_register_user_group_settings', 'itsec_register_global_user_group_settings', 0 );
|
core/modules/global/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Global', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/global/settings-page.php
CHANGED
@@ -223,6 +223,19 @@ final class ITSEC_Global_Settings_Page extends ITSEC_Module_Settings_Page {
|
|
223 |
Â
</p>
|
224 |
Â
</td>
|
225 |
Â
</tr>
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
226 |
Â
<tr>
|
227 |
Â
<th scope="row"><label for="itsec-global-log_type"><?php _e( 'Log Type', 'better-wp-security' ); ?></label></th>
|
228 |
Â
<td>
|
223 |
Â
</p>
|
224 |
Â
</td>
|
225 |
Â
</tr>
|
226 |
+
<tr>
|
227 |
+
<th scope="row">
|
228 |
+
<label for="itsec-global-manage_group">
|
229 |
+
<?php esc_html_e( 'Manage iThemes Security', 'better-wp-security' ) ?>
|
230 |
+
</label>
|
231 |
+
</th>
|
232 |
+
<td>
|
233 |
+
<p class="description">
|
234 |
+
<?php esc_html_e( 'Select the group of users that can manage iThemes Security. If no groups are selected, all administrator users will have access.', 'better-wp-security' ); ?>
|
235 |
+
</p>
|
236 |
+
<?php $form->add_user_groups( 'manage_group', $this->id ); ?>
|
237 |
+
</td>
|
238 |
+
</tr>
|
239 |
Â
<tr>
|
240 |
Â
<th scope="row"><label for="itsec-global-log_type"><?php _e( 'Log Type', 'better-wp-security' ); ?></label></th>
|
241 |
Â
<td>
|
core/modules/global/settings.php
CHANGED
@@ -40,10 +40,13 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
40 |
Â
'enable_grade_report' => false,
|
41 |
Â
'server_ips' => array(),
|
42 |
Â
'feature_flags' => array(),
|
Â
|
|
43 |
Â
);
|
44 |
Â
}
|
45 |
Â
|
46 |
Â
protected function handle_settings_changes( $old_settings ) {
|
Â
|
|
Â
|
|
47 |
Â
if ( $this->settings['write_files'] && ! $old_settings['write_files'] ) {
|
48 |
Â
ITSEC_Response::regenerate_server_config();
|
49 |
Â
ITSEC_Response::regenerate_wp_config();
|
@@ -58,7 +61,7 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
|
|
58 |
Â
ITSEC_Modules::load_module_file( 'activate.php', 'grade-report' );
|
59 |
Â
ITSEC_Response::flag_new_notifications_available();
|
60 |
Â
ITSEC_Response::refresh_page();
|
61 |
-
}
|
62 |
Â
update_site_option( 'itsec-enable-grade-report', false );
|
63 |
Â
ITSEC_Modules::load_module_file( 'deactivate.php', 'grade-report' );
|
64 |
Â
ITSEC_Response::refresh_page();
|
40 |
Â
'enable_grade_report' => false,
|
41 |
Â
'server_ips' => array(),
|
42 |
Â
'feature_flags' => array(),
|
43 |
+
'manage_group' => array(),
|
44 |
Â
);
|
45 |
Â
}
|
46 |
Â
|
47 |
Â
protected function handle_settings_changes( $old_settings ) {
|
48 |
+
parent::handle_settings_changes( $old_settings );
|
49 |
+
|
50 |
Â
if ( $this->settings['write_files'] && ! $old_settings['write_files'] ) {
|
51 |
Â
ITSEC_Response::regenerate_server_config();
|
52 |
Â
ITSEC_Response::regenerate_wp_config();
|
61 |
Â
ITSEC_Modules::load_module_file( 'activate.php', 'grade-report' );
|
62 |
Â
ITSEC_Response::flag_new_notifications_available();
|
63 |
Â
ITSEC_Response::refresh_page();
|
64 |
+
} elseif ( ! $this->settings['enable_grade_report'] && $old_settings['enable_grade_report'] ) {
|
65 |
Â
update_site_option( 'itsec-enable-grade-report', false );
|
66 |
Â
ITSEC_Modules::load_module_file( 'deactivate.php', 'grade-report' );
|
67 |
Â
ITSEC_Response::refresh_page();
|
core/modules/global/validator.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
class ITSEC_Global_Validator extends ITSEC_Validator {
|
4 |
Â
public function get_id() {
|
5 |
Â
return 'global';
|
@@ -60,6 +62,18 @@ class ITSEC_Global_Validator extends ITSEC_Validator {
|
|
60 |
Â
|
61 |
Â
$this->sanitize_setting( 'newline-separated-ips', 'server_ips', __( 'Server IPs', 'better-wp-security' ) );
|
62 |
Â
$this->sanitize_setting( 'array', 'feature_flags', __( 'Feature Flags', 'better-wp-security' ) );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
63 |
Â
}
|
64 |
Â
|
65 |
Â
public function get_proxy_types() {
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use \iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
class ITSEC_Global_Validator extends ITSEC_Validator {
|
6 |
Â
public function get_id() {
|
7 |
Â
return 'global';
|
62 |
Â
|
63 |
Â
$this->sanitize_setting( 'newline-separated-ips', 'server_ips', __( 'Server IPs', 'better-wp-security' ) );
|
64 |
Â
$this->sanitize_setting( 'array', 'feature_flags', __( 'Feature Flags', 'better-wp-security' ) );
|
65 |
+
$this->sanitize_setting( 'user-groups', 'manage_group', __( 'Manage Group', 'better-wp-security' ) );
|
66 |
+
}
|
67 |
+
|
68 |
+
protected function validate_settings() {
|
69 |
+
if ( ITSEC_Core::is_interactive() && $this->settings['manage_group'] && $this->settings['manage_group'] !== $this->previous_settings['manage_group'] ) {
|
70 |
+
$matcher = ITSEC_Modules::get_container()->get( User_Groups\Matcher::class );
|
71 |
+
|
72 |
+
if ( ! $matcher->matches( User_Groups\Match_Target::for_user( wp_get_current_user() ), $this->settings['manage_group'] ) ) {
|
73 |
+
$this->add_error( new WP_Error( 'itsec-validator-global-cannot-exclude-self', __( 'The configuration you have chosen removes your capability to manage iThemes Security.', 'better-wp-security' ), [ 'status' => 400 ] ) );
|
74 |
+
$this->set_can_save( false );
|
75 |
+
}
|
76 |
+
}
|
77 |
Â
}
|
78 |
Â
|
79 |
Â
public function get_proxy_types() {
|
core/modules/hide-backend/class-itsec-hide-backend.php
CHANGED
@@ -55,7 +55,7 @@ class ITSEC_Hide_Backend {
|
|
55 |
Â
// The email is plain text and the links are at the end of lines, so a lazy match can be used.
|
56 |
Â
if ( preg_match_all( '|(https?:\/\/((.*)wp-admin(.*)))|', $text, $urls ) ) {
|
57 |
Â
foreach ( $urls[0] as $url ) {
|
58 |
-
$url
|
59 |
Â
$text = str_replace( $url, wp_login_url( $url ), $text );
|
60 |
Â
}
|
61 |
Â
}
|
@@ -139,17 +139,27 @@ class ITSEC_Hide_Backend {
|
|
139 |
Â
|
140 |
Â
if ( 'postpass' === $action ) {
|
141 |
Â
return;
|
142 |
-
}
|
143 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
144 |
Â
return;
|
145 |
-
}
|
Â
|
|
Â
|
|
146 |
Â
// Jetpack handles authentication for this action. Processing is left to it.
|
147 |
Â
return;
|
148 |
-
}
|
Â
|
|
Â
|
|
149 |
Â
// Jetpack's SSO redirects from wordpress.com to wp-login.php on the site. Only allow this process to
|
150 |
Â
// continue if they successfully log in, which should happen by login_init in Jetpack which happens just
|
151 |
Â
// before this action fires.
|
152 |
Â
add_action( 'login_form_jetpack-sso', array( $this, 'block_access' ) );
|
Â
|
|
153 |
Â
return;
|
154 |
Â
}
|
155 |
Â
|
@@ -239,9 +249,9 @@ class ITSEC_Hide_Backend {
|
|
239 |
Â
$this->set_cookie( $type );
|
240 |
Â
|
241 |
Â
// Preserve existing query vars and add access token query arg.
|
242 |
-
$query_vars
|
243 |
-
$query_vars[$this->token_var] = $this->get_access_token( $type );
|
244 |
-
$query
|
245 |
Â
|
246 |
Â
// Disable the Hide Backend URL filters to prevent infinite loops when calling site_url().
|
247 |
Â
$this->disable_filters = true;
|
@@ -285,7 +295,7 @@ class ITSEC_Hide_Backend {
|
|
285 |
Â
} elseif ( 'wp-login.php' !== $request_path || empty( $_GET['action'] ) || 'register' !== $_GET['action'] ) {
|
286 |
Â
$url = $this->add_token_to_url( $url, 'login' );
|
287 |
Â
}
|
288 |
-
}
|
289 |
Â
$url = $this->add_token_to_url( $url, 'register' );
|
290 |
Â
}
|
291 |
Â
|
@@ -295,7 +305,7 @@ class ITSEC_Hide_Backend {
|
|
295 |
Â
/**
|
296 |
Â
* Filter the admin URL to include hide backend tokens when necessary.
|
297 |
Â
*
|
298 |
-
* @param string $url
|
299 |
Â
* @param string $path Path passed to the admin_url function.
|
300 |
Â
*
|
301 |
Â
* @return string
|
@@ -443,10 +453,11 @@ class ITSEC_Hide_Backend {
|
|
443 |
Â
private function is_validated( $type ) {
|
444 |
Â
$token = $this->get_access_token( $type );
|
445 |
Â
|
446 |
-
if ( isset( $_REQUEST[$this->token_var] ) && $_REQUEST[$this->token_var] === $token ) {
|
447 |
Â
$this->set_cookie( $type );
|
Â
|
|
448 |
Â
return true;
|
449 |
-
}
|
450 |
Â
return true;
|
451 |
Â
}
|
452 |
Â
|
@@ -461,8 +472,8 @@ class ITSEC_Hide_Backend {
|
|
461 |
Â
* @return string The access token.
|
462 |
Â
*/
|
463 |
Â
private function get_access_token( $type ) {
|
464 |
-
if ( isset( $this->settings[$type] ) ) {
|
465 |
-
return $this->settings[$type];
|
466 |
Â
}
|
467 |
Â
|
468 |
Â
return $this->settings['slug'];
|
55 |
Â
// The email is plain text and the links are at the end of lines, so a lazy match can be used.
|
56 |
Â
if ( preg_match_all( '|(https?:\/\/((.*)wp-admin(.*)))|', $text, $urls ) ) {
|
57 |
Â
foreach ( $urls[0] as $url ) {
|
58 |
+
$url = trim( $url );
|
59 |
Â
$text = str_replace( $url, wp_login_url( $url ), $text );
|
60 |
Â
}
|
61 |
Â
}
|
139 |
Â
|
140 |
Â
if ( 'postpass' === $action ) {
|
141 |
Â
return;
|
142 |
+
}
|
143 |
+
|
144 |
+
if ( 'register' === $action ) {
|
145 |
+
if ( 'wp-signup.php' !== $this->settings['register'] ) {
|
146 |
+
$this->block_access( 'register' );
|
147 |
+
}
|
148 |
+
|
149 |
Â
return;
|
150 |
+
}
|
151 |
+
|
152 |
+
if ( 'jetpack_json_api_authorization' === $action && has_filter( 'login_form_jetpack_json_api_authorization' ) ) {
|
153 |
Â
// Jetpack handles authentication for this action. Processing is left to it.
|
154 |
Â
return;
|
155 |
+
}
|
156 |
+
|
157 |
+
if ( 'jetpack-sso' === $action && has_filter( 'login_form_jetpack-sso' ) ) {
|
158 |
Â
// Jetpack's SSO redirects from wordpress.com to wp-login.php on the site. Only allow this process to
|
159 |
Â
// continue if they successfully log in, which should happen by login_init in Jetpack which happens just
|
160 |
Â
// before this action fires.
|
161 |
Â
add_action( 'login_form_jetpack-sso', array( $this, 'block_access' ) );
|
162 |
+
|
163 |
Â
return;
|
164 |
Â
}
|
165 |
Â
|
249 |
Â
$this->set_cookie( $type );
|
250 |
Â
|
251 |
Â
// Preserve existing query vars and add access token query arg.
|
252 |
+
$query_vars = $_GET;
|
253 |
+
$query_vars[ $this->token_var ] = $this->get_access_token( $type );
|
254 |
+
$query = http_build_query( $query_vars, null, '&' );
|
255 |
Â
|
256 |
Â
// Disable the Hide Backend URL filters to prevent infinite loops when calling site_url().
|
257 |
Â
$this->disable_filters = true;
|
295 |
Â
} elseif ( 'wp-login.php' !== $request_path || empty( $_GET['action'] ) || 'register' !== $_GET['action'] ) {
|
296 |
Â
$url = $this->add_token_to_url( $url, 'login' );
|
297 |
Â
}
|
298 |
+
} elseif ( 'wp-signup.php' === $clean_path && 'wp-signup.php' !== $this->settings['register'] ) {
|
299 |
Â
$url = $this->add_token_to_url( $url, 'register' );
|
300 |
Â
}
|
301 |
Â
|
305 |
Â
/**
|
306 |
Â
* Filter the admin URL to include hide backend tokens when necessary.
|
307 |
Â
*
|
308 |
+
* @param string $url Complete admin URL.
|
309 |
Â
* @param string $path Path passed to the admin_url function.
|
310 |
Â
*
|
311 |
Â
* @return string
|
453 |
Â
private function is_validated( $type ) {
|
454 |
Â
$token = $this->get_access_token( $type );
|
455 |
Â
|
456 |
+
if ( isset( $_REQUEST[ $this->token_var ] ) && $_REQUEST[ $this->token_var ] === $token ) {
|
457 |
Â
$this->set_cookie( $type );
|
458 |
+
|
459 |
Â
return true;
|
460 |
+
} elseif ( isset( $_COOKIE[ "itsec-hb-$type-" . COOKIEHASH ] ) && $_COOKIE[ "itsec-hb-$type-" . COOKIEHASH ] === $token ) {
|
461 |
Â
return true;
|
462 |
Â
}
|
463 |
Â
|
472 |
Â
* @return string The access token.
|
473 |
Â
*/
|
474 |
Â
private function get_access_token( $type ) {
|
475 |
+
if ( isset( $this->settings[ $type ] ) ) {
|
476 |
+
return $this->settings[ $type ];
|
477 |
Â
}
|
478 |
Â
|
479 |
Â
return $this->settings['slug'];
|
core/modules/hide-backend/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Hide Backend', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/hide-backend/settings.php
CHANGED
@@ -17,6 +17,7 @@ final class ITSEC_Hide_Backend_Settings extends ITSEC_Settings {
|
|
17 |
Â
}
|
18 |
Â
|
19 |
Â
protected function handle_settings_changes( $old_settings ) {
|
Â
|
|
20 |
Â
|
21 |
Â
if ( $this->settings['enabled'] && ! $old_settings['enabled'] ) {
|
22 |
Â
$url = get_site_url() . '/' . $this->settings['slug'];
|
17 |
Â
}
|
18 |
Â
|
19 |
Â
protected function handle_settings_changes( $old_settings ) {
|
20 |
+
parent::handle_settings_changes( $old_settings );
|
21 |
Â
|
22 |
Â
if ( $this->settings['enabled'] && ! $old_settings['enabled'] ) {
|
23 |
Â
$url = get_site_url() . '/' . $this->settings['slug'];
|
core/modules/ipcheck/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Network Brute Force', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/malware/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Malware', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/malware/settings-page.php
CHANGED
@@ -5,8 +5,10 @@ class ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan extends ITSEC_Settings_Pag
|
|
5 |
Â
|
6 |
Â
|
7 |
Â
public function __construct() {
|
8 |
-
|
9 |
-
|
Â
|
|
Â
|
|
10 |
Â
$this->priority = 8;
|
11 |
Â
|
12 |
Â
parent::__construct();
|
@@ -23,6 +25,7 @@ class ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan extends ITSEC_Settings_Pag
|
|
23 |
Â
wp_localize_script( 'itsec-settings-malware-scan-settings-script', 'itsecMalwareScanData', $vars );
|
24 |
Â
|
25 |
Â
wp_enqueue_style( 'itsec-settings-malware-scan-style', plugins_url( 'css/settings.css', __FILE__ ), array(), $this->script_version );
|
Â
|
|
26 |
Â
}
|
27 |
Â
|
28 |
Â
public function handle_ajax_request( $data ) {
|
@@ -46,21 +49,32 @@ class ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan extends ITSEC_Settings_Pag
|
|
46 |
Â
}
|
47 |
Â
|
48 |
Â
public function render( $form ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
49 |
Â
|
50 |
-
?>
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
<?php
|
61 |
Â
}
|
62 |
Â
|
63 |
Â
protected function save( $data ) {
|
64 |
Â
}
|
65 |
Â
}
|
Â
|
|
66 |
Â
new ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan();
|
5 |
Â
|
6 |
Â
|
7 |
Â
public function __construct() {
|
8 |
+
ITSEC_Lib::load( 'feature-flags' );
|
9 |
+
|
10 |
+
$this->id = 'malware-scan';
|
11 |
+
$this->title = ITSEC_Lib_Feature_Flags::is_enabled( 'site_scanner' ) ? __( 'Site Scan', 'better-wp-security' ) : __( 'Malware Scan', 'better-wp-security' );
|
12 |
Â
$this->priority = 8;
|
13 |
Â
|
14 |
Â
parent::__construct();
|
25 |
Â
wp_localize_script( 'itsec-settings-malware-scan-settings-script', 'itsecMalwareScanData', $vars );
|
26 |
Â
|
27 |
Â
wp_enqueue_style( 'itsec-settings-malware-scan-style', plugins_url( 'css/settings.css', __FILE__ ), array(), $this->script_version );
|
28 |
+
wp_enqueue_style( 'itsec-core-packages-components-site-scan-results-style' );
|
29 |
Â
}
|
30 |
Â
|
31 |
Â
public function handle_ajax_request( $data ) {
|
49 |
Â
}
|
50 |
Â
|
51 |
Â
public function render( $form ) {
|
52 |
+
if ( ITSEC_Lib_Feature_Flags::is_enabled( 'site_scanner' ) ) {
|
53 |
+
$button = __( 'Scan Now', 'better-wp-security' );
|
54 |
+
$module = 'site-scanner';
|
55 |
+
$description = __( 'This %1$ssite scan is powered by iThemes%2$s. We use several datapoints to check for known malware, blacklisting status, website errors and out-of-date software. These datapoints are not 100% accurate, but we try our best to provide thorough results.', 'better-wp-security' );
|
56 |
+
$description = sprintf( $description, '<a href="https://help.ithemes.com/hc/en-us/articles/360046334433" target="_blank">', '</a>' );
|
57 |
+
} else {
|
58 |
+
$button = __( 'Scan Homepage for Malware', 'better-wp-security' );
|
59 |
+
$module = 'malware';
|
60 |
+
$description = sprintf( __( 'This malware scan is powered by <a href="%s">Sucuri SiteCheck</a>. It checks for known malware, blacklisting status, website errors and out-of-date software. Although the Sucuri team does its best to provide thorough results, 100%% accuracy is not realistic and is not guaranteed.', 'better-wp-security' ), esc_url( 'https://ithemes.com/sitecheck' ) );
|
61 |
+
}
|
62 |
Â
|
63 |
+
?>
|
64 |
+
<div class="hide-if-no-js">
|
65 |
+
<p><?php echo $description; ?></p>
|
66 |
+
<p><?php printf( __( 'Results of previous scans can be found on the <a href="%s">logs page</a>.', 'better-wp-security' ), ITSEC_Core::get_logs_page_url( $module ) ); ?></p>
|
67 |
+
<div class='itsec-malware-scan-results-wrapper'></div>
|
68 |
+
<?php $form->add_button( 'start', array( 'value' => $button, 'class' => 'button-primary' ) ); ?>
|
69 |
+
</div>
|
70 |
+
<div class="hide-if-js">
|
71 |
+
<p><?php _e( 'The malware scanner requires Javascript in order to function. If Javascript is disabled in your browser, please enable it. If Javascript is not disabled, a script from another plugin, the theme, or a broken WordPress file is preventing the malware scanner\'s script from executing properly. Please try disabling other plugins to see if that resolves the issue.', 'better-wp-security' ); ?></p>
|
72 |
+
</div>
|
73 |
+
<?php
|
74 |
Â
}
|
75 |
Â
|
76 |
Â
protected function save( $data ) {
|
77 |
Â
}
|
78 |
Â
}
|
79 |
+
|
80 |
Â
new ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan();
|
core/modules/multisite-tweaks/class-itsec-multisite-tweaks.php
CHANGED
@@ -6,34 +6,34 @@ final class ITSEC_Multisite_Tweaks {
|
|
6 |
Â
// Don't risk blocking anything with WP_CLI.
|
7 |
Â
return;
|
8 |
Â
}
|
9 |
-
|
10 |
Â
add_action( 'init', array( $this, 'init' ) );
|
11 |
Â
}
|
12 |
-
|
13 |
Â
public function init() {
|
14 |
Â
if ( ITSEC_Core::is_iwp_call() ) {
|
15 |
Â
return;
|
16 |
Â
}
|
17 |
-
|
18 |
-
if ( current_user_can( 'manage_options' ) ) {
|
19 |
Â
return;
|
20 |
Â
}
|
21 |
-
|
22 |
-
|
23 |
Â
$settings = ITSEC_Modules::get_settings( 'multisite-tweaks' );
|
24 |
-
|
25 |
Â
if ( $settings['theme_updates'] ) {
|
26 |
Â
remove_action( 'load-update-core.php', 'wp_update_themes' );
|
27 |
Â
add_filter( 'pre_site_transient_update_themes', '__return_null' );
|
28 |
Â
wp_clear_scheduled_hook( 'wp_update_themes' );
|
29 |
Â
}
|
30 |
-
|
31 |
Â
if ( $settings['plugin_updates'] ) {
|
32 |
Â
remove_action( 'load-update-core.php', 'wp_update_plugins' );
|
33 |
Â
add_filter( 'pre_site_transient_update_plugins', '__return_null' );
|
34 |
Â
wp_clear_scheduled_hook( 'wp_update_plugins' );
|
35 |
Â
}
|
36 |
-
|
37 |
Â
if ( $settings['core_updates'] ) {
|
38 |
Â
remove_action( 'admin_notices', 'update_nag', 3 );
|
39 |
Â
add_filter( 'pre_site_transient_update_core', '__return_null' );
|
6 |
Â
// Don't risk blocking anything with WP_CLI.
|
7 |
Â
return;
|
8 |
Â
}
|
9 |
+
|
10 |
Â
add_action( 'init', array( $this, 'init' ) );
|
11 |
Â
}
|
12 |
+
|
13 |
Â
public function init() {
|
14 |
Â
if ( ITSEC_Core::is_iwp_call() ) {
|
15 |
Â
return;
|
16 |
Â
}
|
17 |
+
|
18 |
+
if ( current_user_can( 'manage_options' ) || wp_doing_cron() ) {
|
19 |
Â
return;
|
20 |
Â
}
|
21 |
+
|
22 |
+
|
23 |
Â
$settings = ITSEC_Modules::get_settings( 'multisite-tweaks' );
|
24 |
+
|
25 |
Â
if ( $settings['theme_updates'] ) {
|
26 |
Â
remove_action( 'load-update-core.php', 'wp_update_themes' );
|
27 |
Â
add_filter( 'pre_site_transient_update_themes', '__return_null' );
|
28 |
Â
wp_clear_scheduled_hook( 'wp_update_themes' );
|
29 |
Â
}
|
30 |
+
|
31 |
Â
if ( $settings['plugin_updates'] ) {
|
32 |
Â
remove_action( 'load-update-core.php', 'wp_update_plugins' );
|
33 |
Â
add_filter( 'pre_site_transient_update_plugins', '__return_null' );
|
34 |
Â
wp_clear_scheduled_hook( 'wp_update_plugins' );
|
35 |
Â
}
|
36 |
+
|
37 |
Â
if ( $settings['core_updates'] ) {
|
38 |
Â
remove_action( 'admin_notices', 'update_nag', 3 );
|
39 |
Â
add_filter( 'pre_site_transient_update_core', '__return_null' );
|
core/modules/multisite-tweaks/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Multisite Tweaks', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/multisite-tweaks/settings-page.php
CHANGED
@@ -6,22 +6,21 @@ final class ITSEC_Multisite_Tweaks_Settings_Page extends ITSEC_Module_Settings_P
|
|
6 |
Â
$this->title = __( 'Multisite Tweaks', 'better-wp-security' );
|
7 |
Â
$this->description = __( 'Advanced settings that improve security by changing default WordPress Multisite behavior.', 'better-wp-security' );
|
8 |
Â
$this->type = 'recommended';
|
9 |
-
|
10 |
Â
parent::__construct();
|
11 |
Â
}
|
12 |
-
|
13 |
Â
protected function render_description( $form ) {
|
14 |
-
|
15 |
Â
?>
|
16 |
Â
<p><?php _e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
|
17 |
Â
<?php
|
18 |
-
|
19 |
Â
}
|
20 |
-
|
21 |
Â
protected function render_settings( $form ) {
|
22 |
-
|
23 |
Â
?>
|
24 |
-
<p><?php _e( 'Note: These settings are listed as advanced because they block common forms of attacks but they can also block legitimate plugins and themes that rely on the same techniques. When activating the settings below, we recommend enabling them one by one to test that everything on your site is still working as expected.', 'better-wp-security' ); ?></p>
|
25 |
Â
<p><?php _e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
|
26 |
Â
<table class="form-table">
|
27 |
Â
<tr>
|
@@ -29,7 +28,7 @@ final class ITSEC_Multisite_Tweaks_Settings_Page extends ITSEC_Module_Settings_P
|
|
29 |
Â
<td>
|
30 |
Â
<?php $form->add_checkbox( 'theme_updates' ); ?>
|
31 |
Â
<label for="itsec-multisite-tweaks-theme_updates"><?php _e( 'Hide Theme Update Notifications', 'better-wp-security' ); ?></label>
|
32 |
-
<p class="description"><?php _e( 'Hides theme update notifications from users who cannot update themes.
|
33 |
Â
</td>
|
34 |
Â
</tr>
|
35 |
Â
<tr>
|
@@ -37,7 +36,7 @@ final class ITSEC_Multisite_Tweaks_Settings_Page extends ITSEC_Module_Settings_P
|
|
37 |
Â
<td>
|
38 |
Â
<?php $form->add_checkbox( 'plugin_updates' ); ?>
|
39 |
Â
<label for="itsec-multisite-tweaks-plugin_updates"><?php _e( 'Hide Plugin Update Notifications', 'better-wp-security' ); ?></label>
|
40 |
-
<p class="description"><?php _e( 'Hides plugin update notifications from users who cannot update plugins.
|
41 |
Â
</td>
|
42 |
Â
</tr>
|
43 |
Â
<tr>
|
@@ -45,12 +44,12 @@ final class ITSEC_Multisite_Tweaks_Settings_Page extends ITSEC_Module_Settings_P
|
|
45 |
Â
<td>
|
46 |
Â
<?php $form->add_checkbox( 'core_updates' ); ?>
|
47 |
Â
<label for="itsec-multisite-tweaks-core_updates"><?php _e( 'Hide Core Update Notifications', 'better-wp-security' ); ?></label>
|
48 |
-
<p class="description"><?php _e( 'Hides core update notifications from users who cannot update core.
|
49 |
Â
</td>
|
50 |
Â
</tr>
|
51 |
Â
</table>
|
52 |
Â
<?php
|
53 |
-
|
54 |
Â
}
|
55 |
Â
}
|
56 |
Â
|
6 |
Â
$this->title = __( 'Multisite Tweaks', 'better-wp-security' );
|
7 |
Â
$this->description = __( 'Advanced settings that improve security by changing default WordPress Multisite behavior.', 'better-wp-security' );
|
8 |
Â
$this->type = 'recommended';
|
9 |
+
|
10 |
Â
parent::__construct();
|
11 |
Â
}
|
12 |
+
|
13 |
Â
protected function render_description( $form ) {
|
14 |
+
|
15 |
Â
?>
|
16 |
Â
<p><?php _e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
|
17 |
Â
<?php
|
18 |
+
|
19 |
Â
}
|
20 |
+
|
21 |
Â
protected function render_settings( $form ) {
|
22 |
+
|
23 |
Â
?>
|
Â
|
|
24 |
Â
<p><?php _e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
|
25 |
Â
<table class="form-table">
|
26 |
Â
<tr>
|
28 |
Â
<td>
|
29 |
Â
<?php $form->add_checkbox( 'theme_updates' ); ?>
|
30 |
Â
<label for="itsec-multisite-tweaks-theme_updates"><?php _e( 'Hide Theme Update Notifications', 'better-wp-security' ); ?></label>
|
31 |
+
<p class="description"><?php _e( 'Hides theme update notifications from users who cannot update themes.', 'better-wp-security' ); ?></p>
|
32 |
Â
</td>
|
33 |
Â
</tr>
|
34 |
Â
<tr>
|
36 |
Â
<td>
|
37 |
Â
<?php $form->add_checkbox( 'plugin_updates' ); ?>
|
38 |
Â
<label for="itsec-multisite-tweaks-plugin_updates"><?php _e( 'Hide Plugin Update Notifications', 'better-wp-security' ); ?></label>
|
39 |
+
<p class="description"><?php _e( 'Hides plugin update notifications from users who cannot update plugins.', 'better-wp-security' ); ?></p>
|
40 |
Â
</td>
|
41 |
Â
</tr>
|
42 |
Â
<tr>
|
44 |
Â
<td>
|
45 |
Â
<?php $form->add_checkbox( 'core_updates' ); ?>
|
46 |
Â
<label for="itsec-multisite-tweaks-core_updates"><?php _e( 'Hide Core Update Notifications', 'better-wp-security' ); ?></label>
|
47 |
+
<p class="description"><?php _e( 'Hides core update notifications from users who cannot update core.', 'better-wp-security' ); ?></p>
|
48 |
Â
</td>
|
49 |
Â
</tr>
|
50 |
Â
</table>
|
51 |
Â
<?php
|
52 |
+
|
53 |
Â
}
|
54 |
Â
}
|
55 |
Â
|
core/modules/notification-center/class-notification-center.php
CHANGED
@@ -728,6 +728,14 @@ final class ITSEC_Notification_Center {
|
|
728 |
Â
}
|
729 |
Â
}
|
730 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
731 |
Â
$ret = array();
|
732 |
Â
|
733 |
Â
if ( $to_send ) {
|
728 |
Â
}
|
729 |
Â
}
|
730 |
Â
|
731 |
+
/**
|
732 |
+
* Filters the list of scheduled notifications to send on this request.
|
733 |
+
*
|
734 |
+
* @param string[] $to_send Notification slugs to send.
|
735 |
+
* @param array $notifications List of available notifications that could be sent.
|
736 |
+
*/
|
737 |
+
$to_send = apply_filters( 'itsec_notification_center_send_scheduled_notifications', $to_send, $notifications );
|
738 |
+
|
739 |
Â
$ret = array();
|
740 |
Â
|
741 |
Â
if ( $to_send ) {
|
core/modules/notification-center/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Notification Center', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/notification-center/settings.php
CHANGED
@@ -61,6 +61,7 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
61 |
Â
}
|
62 |
Â
|
63 |
Â
protected function handle_settings_changes( $old_settings ) {
|
Â
|
|
64 |
Â
|
65 |
Â
$nc = ITSEC_Core::get_notification_center();
|
66 |
Â
|
@@ -220,4 +221,4 @@ class ITSEC_Notification_Center_Settings extends ITSEC_Settings {
|
|
220 |
Â
}
|
221 |
Â
}
|
222 |
Â
|
223 |
-
ITSEC_Modules::register_settings( new ITSEC_Notification_Center_Settings() );
|
61 |
Â
}
|
62 |
Â
|
63 |
Â
protected function handle_settings_changes( $old_settings ) {
|
64 |
+
parent::handle_settings_changes( $old_settings );
|
65 |
Â
|
66 |
Â
$nc = ITSEC_Core::get_notification_center();
|
67 |
Â
|
221 |
Â
}
|
222 |
Â
}
|
223 |
Â
|
224 |
+
ITSEC_Modules::register_settings( new ITSEC_Notification_Center_Settings() );
|
core/modules/password-requirements/class-itsec-password-requirements.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
/**
|
4 |
Â
* Class ITSEC_Password_Requirements
|
5 |
Â
*/
|
@@ -22,7 +24,8 @@ class ITSEC_Password_Requirements {
|
|
22 |
Â
|
23 |
Â
add_action( 'itsec_validate_password', array( $this, 'validate_password' ), 10, 4 );
|
24 |
Â
|
25 |
-
|
Â
|
|
26 |
Â
|
27 |
Â
add_action( 'itsec_login_interstitial_init', array( $this, 'register_interstitial' ) );
|
28 |
Â
}
|
@@ -102,6 +105,7 @@ class ITSEC_Password_Requirements {
|
|
102 |
Â
$args = array(
|
103 |
Â
'role' => $user->role,
|
104 |
Â
'canonical' => ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $user->role, $user ),
|
Â
|
|
105 |
Â
);
|
106 |
Â
|
107 |
Â
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], $args );
|
@@ -243,7 +247,9 @@ class ITSEC_Password_Requirements {
|
|
243 |
Â
continue;
|
244 |
Â
}
|
245 |
Â
|
246 |
-
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], array(
|
Â
|
|
Â
|
|
247 |
Â
|
248 |
Â
if ( true === $validated ) {
|
249 |
Â
continue;
|
@@ -333,7 +339,23 @@ class ITSEC_Password_Requirements {
|
|
333 |
Â
if ( $requirement['flag_check'] && call_user_func( $requirement['flag_check'], $user, $settings ) ) {
|
334 |
Â
ITSEC_Lib_Password_Requirements::flag_password_change_required( $user, $code );
|
335 |
Â
|
336 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
337 |
Â
}
|
338 |
Â
}
|
339 |
Â
}
|
@@ -422,7 +444,7 @@ class ITSEC_Password_Requirements {
|
|
422 |
Â
<div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator', 'better-wp-security' ); ?></div>
|
423 |
Â
<div class="pw-weak">
|
424 |
Â
<label>
|
425 |
-
<input type="checkbox" name="pw_weak" class="pw-checkbox"
|
426 |
Â
<?php _e( 'Confirm use of weak password' ); ?>
|
427 |
Â
</label>
|
428 |
Â
</div>
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use \iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
Â
/**
|
6 |
Â
* Class ITSEC_Password_Requirements
|
7 |
Â
*/
|
24 |
Â
|
25 |
Â
add_action( 'itsec_validate_password', array( $this, 'validate_password' ), 10, 4 );
|
26 |
Â
|
27 |
+
// This needs to run before the interstitial runs.
|
28 |
+
add_action( 'wp_login', array( $this, 'flag_check' ), - 2000, 2 );
|
29 |
Â
|
30 |
Â
add_action( 'itsec_login_interstitial_init', array( $this, 'register_interstitial' ) );
|
31 |
Â
}
|
105 |
Â
$args = array(
|
106 |
Â
'role' => $user->role,
|
107 |
Â
'canonical' => ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $user->role, $user ),
|
108 |
+
'target' => User_Groups\Match_Target::for_user( get_userdata( $user->ID ), $user->role )
|
109 |
Â
);
|
110 |
Â
|
111 |
Â
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], $args );
|
247 |
Â
continue;
|
248 |
Â
}
|
249 |
Â
|
250 |
+
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], array(
|
251 |
+
'target' => User_Groups\Match_Target::for_user( $user ),
|
252 |
+
) );
|
253 |
Â
|
254 |
Â
if ( true === $validated ) {
|
255 |
Â
continue;
|
339 |
Â
if ( $requirement['flag_check'] && call_user_func( $requirement['flag_check'], $user, $settings ) ) {
|
340 |
Â
ITSEC_Lib_Password_Requirements::flag_password_change_required( $user, $code );
|
341 |
Â
|
342 |
+
continue;
|
343 |
+
}
|
344 |
+
|
345 |
+
if ( $requirement['validate'] ) {
|
346 |
+
$evaluation = get_user_meta( $user->ID, $requirement['meta'], true );
|
347 |
+
|
348 |
+
if ( '' !== $evaluation ) {
|
349 |
+
$validated = call_user_func( $requirement['validate'], $evaluation, $user, $settings[ $code ], array(
|
350 |
+
'target' => User_Groups\Match_Target::for_user( $user ),
|
351 |
+
) );
|
352 |
+
|
353 |
+
if ( true !== $validated ) {
|
354 |
+
ITSEC_Lib_Password_Requirements::flag_password_change_required( $user, $code );
|
355 |
+
|
356 |
+
continue;
|
357 |
+
}
|
358 |
+
}
|
359 |
Â
}
|
360 |
Â
}
|
361 |
Â
}
|
444 |
Â
<div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator', 'better-wp-security' ); ?></div>
|
445 |
Â
<div class="pw-weak">
|
446 |
Â
<label>
|
447 |
+
<input type="checkbox" name="pw_weak" class="pw-checkbox"/>
|
448 |
Â
<?php _e( 'Confirm use of weak password' ); ?>
|
449 |
Â
</label>
|
450 |
Â
</div>
|
core/modules/password-requirements/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Password Requirements', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/password-requirements/settings.php
CHANGED
@@ -46,6 +46,15 @@ class ITSEC_Password_Requirements_Settings extends ITSEC_Settings {
|
|
46 |
Â
$this->settings['requirement_settings'][ $code ] = wp_parse_args( $current, $requirement['defaults'] );
|
47 |
Â
}
|
48 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
49 |
Â
}
|
50 |
Â
|
51 |
-
ITSEC_Modules::register_settings( new ITSEC_Password_Requirements_Settings() );
|
46 |
Â
$this->settings['requirement_settings'][ $code ] = wp_parse_args( $current, $requirement['defaults'] );
|
47 |
Â
}
|
48 |
Â
}
|
49 |
+
|
50 |
+
protected function handle_settings_changes( $old_settings ) {
|
51 |
+
parent::handle_settings_changes( $old_settings );
|
52 |
+
|
53 |
+
if ( $this->settings['enabled_requirements'] !== $old_settings['enabled_requirements'] ) {
|
54 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/user-groups', 'fetchGroupsSettings' );
|
55 |
+
ITSEC_Response::add_store_dispatch( 'ithemes-security/core', 'fetchIndex', [ true ] );
|
56 |
+
}
|
57 |
+
}
|
58 |
Â
}
|
59 |
Â
|
60 |
+
ITSEC_Modules::register_settings( new ITSEC_Password_Requirements_Settings() );
|
core/modules/password-requirements/validator.php
CHANGED
@@ -13,6 +13,7 @@ class ITSEC_Password_Requirements_Validator extends ITSEC_Validator {
|
|
13 |
Â
}
|
14 |
Â
|
15 |
Â
protected function sanitize_settings() {
|
Â
|
|
16 |
Â
$this->sanitize_setting( 'array', 'enabled_requirements', __( 'Enabled Requirements', 'better-wp-security' ) );
|
17 |
Â
$this->sanitize_setting( 'array', 'requirement_settings', __( 'Requirement Settings', 'better-wp-security' ) );
|
18 |
Â
|
@@ -59,4 +60,4 @@ class ITSEC_Password_Requirements_Validator extends ITSEC_Validator {
|
|
59 |
Â
}
|
60 |
Â
}
|
61 |
Â
|
62 |
-
ITSEC_Modules::register_validator( new ITSEC_Password_Requirements_Validator() );
|
13 |
Â
}
|
14 |
Â
|
15 |
Â
protected function sanitize_settings() {
|
16 |
+
$this->set_previous_if_empty( [ 'enabled_requirements', 'requirement_settings' ] );
|
17 |
Â
$this->sanitize_setting( 'array', 'enabled_requirements', __( 'Enabled Requirements', 'better-wp-security' ) );
|
18 |
Â
$this->sanitize_setting( 'array', 'requirement_settings', __( 'Requirement Settings', 'better-wp-security' ) );
|
19 |
Â
|
60 |
Â
}
|
61 |
Â
}
|
62 |
Â
|
63 |
+
ITSEC_Modules::register_validator( new ITSEC_Password_Requirements_Validator() );
|
core/modules/privacy/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Privacy', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/salts/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'WordPress Salts', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/salts/settings-page.php
CHANGED
@@ -6,24 +6,43 @@ final class ITSEC_WordPress_Salts_Settings_Page extends ITSEC_Module_Settings_Pa
|
|
6 |
Â
$this->title = __( 'WordPress Salts', 'better-wp-security' );
|
7 |
Â
$this->description = __( 'Update the secret keys WordPress uses to increase the security of your site.', 'better-wp-security' );
|
8 |
Â
$this->type = 'recommended';
|
9 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
10 |
Â
parent::__construct();
|
11 |
Â
}
|
12 |
-
|
13 |
Â
protected function render_description( $form ) {
|
14 |
-
|
15 |
Â
?>
|
16 |
-
<p
|
17 |
-
<p
|
18 |
Â
<?php
|
19 |
-
|
20 |
Â
}
|
21 |
-
|
22 |
Â
protected function render_settings( $form ) {
|
23 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
24 |
Â
?>
|
25 |
Â
<div class="itsec-write-files-enabled">
|
26 |
-
<p><strong
|
27 |
Â
<table class="form-table itsec-settings-section">
|
28 |
Â
<tr>
|
29 |
Â
<th scope="row"><label for="itsec-wordpress-salts-regenerate"><?php _e( 'Change WordPress Salts', 'better-wp-security' ); ?></label></th>
|
@@ -39,7 +58,7 @@ final class ITSEC_WordPress_Salts_Settings_Page extends ITSEC_Module_Settings_Pa
|
|
39 |
Â
<div class="itsec-warning-message"><?php _e( 'The "Write to Files" setting is disabled in Global Settings. In order to use this feature, you must enable the "Write to Files" setting.', 'better-wp-security' ); ?></div>
|
40 |
Â
</div>
|
41 |
Â
<?php
|
42 |
-
|
43 |
Â
}
|
44 |
Â
}
|
45 |
Â
|
6 |
Â
$this->title = __( 'WordPress Salts', 'better-wp-security' );
|
7 |
Â
$this->description = __( 'Update the secret keys WordPress uses to increase the security of your site.', 'better-wp-security' );
|
8 |
Â
$this->type = 'recommended';
|
9 |
+
|
10 |
+
require_once( __DIR__ . '/utilities.php' );
|
11 |
+
|
12 |
+
if ( ! ITSEC_WordPress_Salts_Utilities::check_valid_salts() ) {
|
13 |
+
$this->status = 'warning';
|
14 |
+
}
|
15 |
+
|
16 |
Â
parent::__construct();
|
17 |
Â
}
|
18 |
+
|
19 |
Â
protected function render_description( $form ) {
|
20 |
+
|
21 |
Â
?>
|
22 |
+
<p><?php esc_html_e( 'A secret key makes your site harder to hack and access by adding random elements to the password.', 'better-wp-security' ) ?></p>
|
23 |
+
<p><?php esc_html_e( 'In simple terms, a secret key is a password with elements that make it harder to generate enough options to break through your security barriers. A password like "password" or "test" is simple and easily broken. A random, unpredictable password such as "88a7da62429ba6ad3cb3c76a09641fc" takes years to come up with the right combination. A salt is used to further enhance the security of the generated result.', 'better-wp-security' ); ?></p>
|
24 |
Â
<?php
|
Â
|
|
25 |
Â
}
|
26 |
+
|
27 |
Â
protected function render_settings( $form ) {
|
28 |
+
|
29 |
+
if ( $this->status === 'warning' ) {
|
30 |
+
?>
|
31 |
+
<div class="notice notice-warning notice-alt below-h2">
|
32 |
+
<p>
|
33 |
+
<?php printf(
|
34 |
+
esc_html__( 'Currently one or more of your salts is invalid. Please either use the tool below, or %1$smanually update your wp-config.php file%2$s.', 'better-wp-security' ),
|
35 |
+
'<a href="https://ithemes.com/easily-change-wordpress-security-keys-salts-ithemes-security-plugin/">',
|
36 |
+
'</a>'
|
37 |
+
); ?>
|
38 |
+
</p>
|
39 |
+
</div>
|
40 |
+
<?php
|
41 |
+
}
|
42 |
+
|
43 |
Â
?>
|
44 |
Â
<div class="itsec-write-files-enabled">
|
45 |
+
<p><strong><?php esc_html_e( 'Note that changing the salts will log you out of your WordPress site.', 'better-wp-security' ) ?></strong></p>
|
46 |
Â
<table class="form-table itsec-settings-section">
|
47 |
Â
<tr>
|
48 |
Â
<th scope="row"><label for="itsec-wordpress-salts-regenerate"><?php _e( 'Change WordPress Salts', 'better-wp-security' ); ?></label></th>
|
58 |
Â
<div class="itsec-warning-message"><?php _e( 'The "Write to Files" setting is disabled in Global Settings. In order to use this feature, you must enable the "Write to Files" setting.', 'better-wp-security' ); ?></div>
|
59 |
Â
</div>
|
60 |
Â
<?php
|
61 |
+
|
62 |
Â
}
|
63 |
Â
}
|
64 |
Â
|
core/modules/salts/utilities.php
CHANGED
@@ -1,40 +1,60 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
final class ITSEC_WordPress_Salts_Utilities {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
4 |
Â
public static function generate_new_salts() {
|
5 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'write_files' ) ) {
|
6 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-write-files-disabled', __( 'The "Write to Files" setting is disabled in Global Settings. In order to use this feature, you must enable the "Write to Files" setting.', 'better-wp-security' ) );
|
7 |
Â
}
|
8 |
-
|
9 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-config-file.php' );
|
10 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-file.php' );
|
11 |
-
|
12 |
Â
$config_file_path = ITSEC_Lib_Config_File::get_wp_config_file_path();
|
13 |
Â
$config = ITSEC_Lib_File::read( $config_file_path );
|
14 |
-
|
15 |
Â
if ( is_wp_error( $config ) ) {
|
16 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-cannot-read-wp-config.php', sprintf( __( 'Unable to read the <code>wp-config.php</code> file in order to update the salts. You will need to manually update the file. Error details as follows: %1$s (%2$s)', 'better-wp-security' ), $config->get_error_message(), $config->get_error_code() ) );
|
17 |
Â
}
|
18 |
-
|
19 |
-
|
20 |
-
$defines = array(
|
21 |
-
'AUTH_KEY',
|
22 |
-
'SECURE_AUTH_KEY',
|
23 |
-
'LOGGED_IN_KEY',
|
24 |
-
'NONCE_KEY',
|
25 |
-
'AUTH_SALT',
|
26 |
-
'SECURE_AUTH_SALT',
|
27 |
-
'LOGGED_IN_SALT',
|
28 |
-
'NONCE_SALT',
|
29 |
-
);
|
30 |
-
|
31 |
-
foreach ( $defines as $define ) {
|
32 |
Â
if ( empty( $salts ) ) {
|
33 |
Â
$salts = self::get_new_salts();
|
34 |
Â
}
|
35 |
-
|
36 |
Â
$salt = array_pop( $salts );
|
37 |
-
|
38 |
Â
if ( empty( $salt ) ) {
|
39 |
Â
$salt = wp_generate_password( 64, true, true );
|
40 |
Â
}
|
@@ -45,17 +65,17 @@ final class ITSEC_WordPress_Salts_Utilities {
|
|
45 |
Â
}
|
46 |
Â
|
47 |
Â
$write_result = ITSEC_Lib_File::write( $config_file_path, $config );
|
48 |
-
|
49 |
Â
if ( is_wp_error( $write_result ) ) {
|
50 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-cannot-save-wp-config.php', sprintf( __( 'Unable to update the <code>wp-config.php</code> file in order to update the salts. You will need to manually update the file. Error details as follows: %1$s (%2$s)', 'better-wp-security' ), $config->get_error_message(), $config->get_error_code() ) );
|
51 |
Â
}
|
52 |
-
|
53 |
Â
return true;
|
54 |
Â
}
|
55 |
-
|
56 |
Â
public static function get_new_salts() {
|
57 |
Â
// From wp-admin/setup-config.php in WordPress 4.5.
|
58 |
-
|
59 |
Â
// Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
|
60 |
Â
try {
|
61 |
Â
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
|
@@ -69,7 +89,7 @@ final class ITSEC_WordPress_Salts_Utilities {
|
|
69 |
Â
}
|
70 |
Â
} catch ( Exception $ex ) {
|
71 |
Â
$secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
|
72 |
-
|
73 |
Â
if ( is_wp_error( $secret_keys ) ) {
|
74 |
Â
$secret_keys = array();
|
75 |
Â
for ( $i = 0; $i < 8; $i++ ) {
|
@@ -82,7 +102,7 @@ final class ITSEC_WordPress_Salts_Utilities {
|
|
82 |
Â
}
|
83 |
Â
}
|
84 |
Â
}
|
85 |
-
|
86 |
Â
return $secret_keys;
|
87 |
Â
}
|
88 |
Â
}
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
final class ITSEC_WordPress_Salts_Utilities {
|
4 |
+
private static $defines = [
|
5 |
+
'AUTH_KEY',
|
6 |
+
'SECURE_AUTH_KEY',
|
7 |
+
'LOGGED_IN_KEY',
|
8 |
+
'NONCE_KEY',
|
9 |
+
'AUTH_SALT',
|
10 |
+
'SECURE_AUTH_SALT',
|
11 |
+
'LOGGED_IN_SALT',
|
12 |
+
'NONCE_SALT',
|
13 |
+
];
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Check that all the salts have valid values.
|
17 |
+
*
|
18 |
+
* @return bool
|
19 |
+
*/
|
20 |
+
public static function check_valid_salts() {
|
21 |
+
foreach ( self::$defines as $define ) {
|
22 |
+
if ( ! defined( $define ) ) {
|
23 |
+
return false;
|
24 |
+
}
|
25 |
+
|
26 |
+
$value = constant( $define );
|
27 |
+
|
28 |
+
if ( ! $value || 'put your unique phrase here' === $value ) {
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
|
36 |
Â
public static function generate_new_salts() {
|
37 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'write_files' ) ) {
|
38 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-write-files-disabled', __( 'The "Write to Files" setting is disabled in Global Settings. In order to use this feature, you must enable the "Write to Files" setting.', 'better-wp-security' ) );
|
39 |
Â
}
|
40 |
+
|
41 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-config-file.php' );
|
42 |
Â
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-file.php' );
|
43 |
+
|
44 |
Â
$config_file_path = ITSEC_Lib_Config_File::get_wp_config_file_path();
|
45 |
Â
$config = ITSEC_Lib_File::read( $config_file_path );
|
46 |
+
|
47 |
Â
if ( is_wp_error( $config ) ) {
|
48 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-cannot-read-wp-config.php', sprintf( __( 'Unable to read the <code>wp-config.php</code> file in order to update the salts. You will need to manually update the file. Error details as follows: %1$s (%2$s)', 'better-wp-security' ), $config->get_error_message(), $config->get_error_code() ) );
|
49 |
Â
}
|
50 |
+
|
51 |
+
foreach ( self::$defines as $define ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
52 |
Â
if ( empty( $salts ) ) {
|
53 |
Â
$salts = self::get_new_salts();
|
54 |
Â
}
|
55 |
+
|
56 |
Â
$salt = array_pop( $salts );
|
57 |
+
|
58 |
Â
if ( empty( $salt ) ) {
|
59 |
Â
$salt = wp_generate_password( 64, true, true );
|
60 |
Â
}
|
65 |
Â
}
|
66 |
Â
|
67 |
Â
$write_result = ITSEC_Lib_File::write( $config_file_path, $config );
|
68 |
+
|
69 |
Â
if ( is_wp_error( $write_result ) ) {
|
70 |
Â
return new WP_Error( 'itsec-wordpress-salts-utilities-cannot-save-wp-config.php', sprintf( __( 'Unable to update the <code>wp-config.php</code> file in order to update the salts. You will need to manually update the file. Error details as follows: %1$s (%2$s)', 'better-wp-security' ), $config->get_error_message(), $config->get_error_code() ) );
|
71 |
Â
}
|
72 |
+
|
73 |
Â
return true;
|
74 |
Â
}
|
75 |
+
|
76 |
Â
public static function get_new_salts() {
|
77 |
Â
// From wp-admin/setup-config.php in WordPress 4.5.
|
78 |
+
|
79 |
Â
// Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
|
80 |
Â
try {
|
81 |
Â
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
|
89 |
Â
}
|
90 |
Â
} catch ( Exception $ex ) {
|
91 |
Â
$secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
|
92 |
+
|
93 |
Â
if ( is_wp_error( $secret_keys ) ) {
|
94 |
Â
$secret_keys = array();
|
95 |
Â
for ( $i = 0; $i < 8; $i++ ) {
|
102 |
Â
}
|
103 |
Â
}
|
104 |
Â
}
|
105 |
+
|
106 |
Â
return $secret_keys;
|
107 |
Â
}
|
108 |
Â
}
|
core/modules/security-check-pro/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Security Check Pro', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/security-check-pro/utility.php
CHANGED
@@ -129,6 +129,9 @@ final class ITSEC_Security_Check_Pro_Utility {
|
|
129 |
Â
public static function get_remote_ip_index() {
|
130 |
Â
$remote_ips = self::get_remote_ips();
|
131 |
Â
|
Â
|
|
Â
|
|
Â
|
|
132 |
Â
|
133 |
Â
$standard_indexes = array(
|
134 |
Â
'REMOTE_ADDR',
|
@@ -288,6 +291,11 @@ final class ITSEC_Security_Check_Pro_Utility {
|
|
288 |
Â
return $key;
|
289 |
Â
}
|
290 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
291 |
Â
public static function get_remote_ips() {
|
292 |
Â
$remote_ips = apply_filters( 'itsec-security-check-pro-remote-ips', array() );
|
293 |
Â
|
@@ -295,28 +303,28 @@ final class ITSEC_Security_Check_Pro_Utility {
|
|
295 |
Â
return $remote_ips;
|
296 |
Â
}
|
297 |
Â
|
298 |
-
|
299 |
Â
$settings = ITSEC_Modules::get_settings( 'security-check-pro' );
|
300 |
Â
|
301 |
Â
if ( $settings['remote_ips_timestamp'] + ( 5 * MINUTE_IN_SECONDS ) > time() && ! empty( $settings['remote_ips'] ) ) {
|
302 |
Â
return $settings['remote_ips'];
|
303 |
Â
}
|
304 |
Â
|
305 |
-
|
306 |
Â
$response = wp_remote_get( self::$config_url );
|
307 |
Â
|
308 |
Â
if ( is_wp_error( $response ) ) {
|
309 |
-
return
|
310 |
Â
}
|
311 |
Â
|
312 |
-
|
313 |
Â
$body = $response['body'];
|
314 |
Â
$data = json_decode( $body, true );
|
315 |
Â
|
316 |
-
if (
|
317 |
-
return
|
318 |
Â
}
|
319 |
Â
|
Â
|
|
Â
|
|
Â
|
|
320 |
Â
|
321 |
Â
$settings['remote_ips_timestamp'] = time();
|
322 |
Â
$settings['remote_ips'] = $data['ips'];
|
129 |
Â
public static function get_remote_ip_index() {
|
130 |
Â
$remote_ips = self::get_remote_ips();
|
131 |
Â
|
132 |
+
if ( is_wp_error( $remote_ips ) ) {
|
133 |
+
return false;
|
134 |
+
}
|
135 |
Â
|
136 |
Â
$standard_indexes = array(
|
137 |
Â
'REMOTE_ADDR',
|
291 |
Â
return $key;
|
292 |
Â
}
|
293 |
Â
|
294 |
+
/**
|
295 |
+
* Get the list of remote IPs that the SSL Proxy Detect server may be issuing requests from.
|
296 |
+
*
|
297 |
+
* @return string[]|WP_Error
|
298 |
+
*/
|
299 |
Â
public static function get_remote_ips() {
|
300 |
Â
$remote_ips = apply_filters( 'itsec-security-check-pro-remote-ips', array() );
|
301 |
Â
|
303 |
Â
return $remote_ips;
|
304 |
Â
}
|
305 |
Â
|
Â
|
|
306 |
Â
$settings = ITSEC_Modules::get_settings( 'security-check-pro' );
|
307 |
Â
|
308 |
Â
if ( $settings['remote_ips_timestamp'] + ( 5 * MINUTE_IN_SECONDS ) > time() && ! empty( $settings['remote_ips'] ) ) {
|
309 |
Â
return $settings['remote_ips'];
|
310 |
Â
}
|
311 |
Â
|
Â
|
|
312 |
Â
$response = wp_remote_get( self::$config_url );
|
313 |
Â
|
314 |
Â
if ( is_wp_error( $response ) ) {
|
315 |
+
return $response;
|
316 |
Â
}
|
317 |
Â
|
Â
|
|
318 |
Â
$body = $response['body'];
|
319 |
Â
$data = json_decode( $body, true );
|
320 |
Â
|
321 |
+
if ( json_last_error() !== JSON_ERROR_NONE ) {
|
322 |
+
return new WP_Error( 'itsec_security_check_pro_invalid_json_response', json_last_error_msg() );
|
323 |
Â
}
|
324 |
Â
|
325 |
+
if ( ! is_array( $data ) || ! isset( $data['ips'] ) || ! is_array( $data['ips'] ) ) {
|
326 |
+
return new WP_Error( 'itsec_security_check_pro_malformed_response', __( 'The response body is missing the "ips" entry.', 'better-wp-security' ) );
|
327 |
+
}
|
328 |
Â
|
329 |
Â
$settings['remote_ips_timestamp'] = time();
|
330 |
Â
$settings['remote_ips'] = $data['ips'];
|
core/modules/security-check/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Security Check', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/security-check/scanner.php
CHANGED
@@ -41,6 +41,8 @@ final class ITSEC_Security_Check_Scanner {
|
|
41 |
Â
}
|
42 |
Â
|
43 |
Â
public static function run_scan() {
|
Â
|
|
Â
|
|
44 |
Â
require_once( dirname( __FILE__ ) . '/feedback.php' );
|
45 |
Â
|
46 |
Â
self::$feedback = new ITSEC_Security_Check_Feedback();
|
@@ -84,7 +86,7 @@ final class ITSEC_Security_Check_Scanner {
|
|
84 |
Â
self::enforce_activation( 'two-factor', __( 'Two-Factor Authentication', 'better-wp-security' ) );
|
85 |
Â
self::enforce_setting( 'two-factor', 'available_methods', 'all', esc_html__( 'Changed the Authentication Methods Available to Users setting in Two-Factor Authentication to "All Methods".', 'better-wp-security' ) );
|
86 |
Â
self::enforce_setting( 'two-factor', 'exclude_type', 'disabled', esc_html__( 'Changed the Disabled Force Two-Factor for Certain Users to "None".', 'better-wp-security' ) );
|
87 |
-
self::enforce_setting( 'two-factor', '
|
88 |
Â
self::enforce_setting( 'two-factor', 'protect_vulnerable_users', true, esc_html__( 'Enabled the Vulnerable User Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
89 |
Â
self::enforce_setting( 'two-factor', 'protect_vulnerable_site', true, esc_html__( 'Enabled the Vulnerable Site Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
90 |
Â
|
41 |
Â
}
|
42 |
Â
|
43 |
Â
public static function run_scan() {
|
44 |
+
$admin_group = ( $group_id = ITSEC_Modules::get_settings_obj( 'user-groups' )->get_default_group_id( 'administrator' ) ) ? [ $group_id ] : [];
|
45 |
+
|
46 |
Â
require_once( dirname( __FILE__ ) . '/feedback.php' );
|
47 |
Â
|
48 |
Â
self::$feedback = new ITSEC_Security_Check_Feedback();
|
86 |
Â
self::enforce_activation( 'two-factor', __( 'Two-Factor Authentication', 'better-wp-security' ) );
|
87 |
Â
self::enforce_setting( 'two-factor', 'available_methods', 'all', esc_html__( 'Changed the Authentication Methods Available to Users setting in Two-Factor Authentication to "All Methods".', 'better-wp-security' ) );
|
88 |
Â
self::enforce_setting( 'two-factor', 'exclude_type', 'disabled', esc_html__( 'Changed the Disabled Force Two-Factor for Certain Users to "None".', 'better-wp-security' ) );
|
89 |
+
self::enforce_setting( 'two-factor', 'protect_user_group', $admin_group, esc_html__( 'Changed the User Type Protection setting in Two-Factor Authentication to "Privileged Users".', 'better-wp-security' ) );
|
90 |
Â
self::enforce_setting( 'two-factor', 'protect_vulnerable_users', true, esc_html__( 'Enabled the Vulnerable User Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
91 |
Â
self::enforce_setting( 'two-factor', 'protect_vulnerable_site', true, esc_html__( 'Enabled the Vulnerable Site Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
|
92 |
Â
|
core/modules/ssl/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'SSL', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/strong-passwords/active.php
CHANGED
@@ -1,3 +1,5 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
-
require_once( 'class-itsec-strong-passwords.php' );
|
Â
|
|
Â
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
require_once( __DIR__ . '/class-itsec-strong-passwords.php' );
|
4 |
+
|
5 |
+
return 'ITSEC_Strong_Passwords';
|
core/modules/strong-passwords/class-itsec-strong-passwords.php
CHANGED
@@ -1,13 +1,27 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
-
|
Â
|
|
Â
|
|
Â
|
|
4 |
Â
|
5 |
Â
const STRENGTH_KEY = 'itsec-password-strength';
|
6 |
Â
|
7 |
-
|
Â
|
|
8 |
Â
|
9 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
10 |
Â
|
Â
|
|
Â
|
|
Â
|
|
11 |
Â
add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
|
12 |
Â
add_action( 'resetpass_form', array( $this, 'add_scripts_to_wp_login' ) );
|
13 |
Â
add_action( 'itsec_password_requirements_change_form', array( $this, 'add_scripts_to_wp_login' ) );
|
@@ -23,18 +37,30 @@ final class ITSEC_Strong_Passwords {
|
|
23 |
Â
'reason' => array( $this, 'reason' ),
|
24 |
Â
'meta' => self::STRENGTH_KEY,
|
25 |
Â
'evaluate_if_not_enabled' => true,
|
26 |
-
'defaults' => array(
|
Â
|
|
Â
|
|
27 |
Â
'settings_config' => array( $this, 'get_settings_config' ),
|
28 |
Â
) );
|
29 |
Â
}
|
30 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
31 |
Â
/**
|
32 |
Â
* Enqueue script to hide the acknowledge weak password checkbox.
|
33 |
Â
*
|
34 |
Â
* @return void
|
35 |
Â
*/
|
36 |
Â
public function add_scripts() {
|
37 |
-
|
38 |
Â
global $pagenow;
|
39 |
Â
|
40 |
Â
if ( 'profile.php' !== $pagenow ) {
|
@@ -46,11 +72,8 @@ final class ITSEC_Strong_Passwords {
|
|
46 |
Â
}
|
47 |
Â
|
48 |
Â
$settings = ITSEC_Lib_Password_Requirements::get_requirement_settings( 'strength' );
|
49 |
-
$role = isset( $settings['role'] ) ? $settings['role'] : 'administrator';
|
50 |
-
|
51 |
-
require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-canonical-roles.php' );
|
52 |
Â
|
53 |
-
if (
|
54 |
Â
wp_enqueue_script( 'itsec_strong_passwords', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
55 |
Â
}
|
56 |
Â
}
|
@@ -69,11 +92,8 @@ final class ITSEC_Strong_Passwords {
|
|
69 |
Â
}
|
70 |
Â
|
71 |
Â
$settings = ITSEC_Lib_Password_Requirements::get_requirement_settings( 'strength' );
|
72 |
-
$role = isset( $settings['role'] ) ? $settings['role'] : 'administrator';
|
73 |
Â
|
74 |
-
|
75 |
-
|
76 |
-
if ( ITSEC_Lib_Canonical_Roles::is_user_at_least( $role, $user ) ) {
|
77 |
Â
wp_enqueue_script( 'itsec_strong_passwords', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
78 |
Â
}
|
79 |
Â
}
|
@@ -112,16 +132,17 @@ final class ITSEC_Strong_Passwords {
|
|
112 |
Â
* @return bool
|
113 |
Â
*/
|
114 |
Â
public function validate( $strength, $user, $settings, $args ) {
|
115 |
-
|
116 |
Â
if ( (int) $strength === 4 ) {
|
117 |
Â
return true;
|
118 |
Â
}
|
119 |
Â
|
120 |
-
|
Â
|
|
Â
|
|
121 |
Â
|
122 |
-
$
|
123 |
Â
|
124 |
-
if ( !
|
125 |
Â
return true;
|
126 |
Â
}
|
127 |
Â
|
@@ -143,22 +164,17 @@ final class ITSEC_Strong_Passwords {
|
|
143 |
Â
* @param ITSEC_Form $form
|
144 |
Â
*/
|
145 |
Â
public function render_settings( $form ) {
|
146 |
-
|
147 |
-
$href = 'http://codex.wordpress.org/Roles_and_Capabilities';
|
148 |
-
$link = '<a href="' . $href . '" target="_blank" rel="noopener noreferrer">' . $href . '</a>';
|
149 |
Â
?>
|
150 |
Â
<tr>
|
151 |
Â
<th scope="row">
|
152 |
-
<label for="itsec-password-requirements-requirement_settings-strength-
|
153 |
-
<?php esc_html_e( '
|
154 |
Â
</label>
|
155 |
Â
</th>
|
156 |
Â
<td>
|
157 |
-
<?php $form->
|
158 |
Â
<br/>
|
159 |
-
<label for="itsec-password-requirements-requirement_settings-strength-
|
160 |
-
<p class="description"><?php printf( __( 'For more information on WordPress roles and capabilities please see %s.', 'better-wp-security' ), $link ); ?></p>
|
161 |
-
<p class="warningtext description"><?php _e( 'Warning: If your site invites public registrations setting the role too low may annoy your members.', 'better-wp-security' ); ?></p>
|
162 |
Â
</td>
|
163 |
Â
</tr>
|
164 |
Â
<?php
|
@@ -173,8 +189,7 @@ final class ITSEC_Strong_Passwords {
|
|
173 |
Â
*/
|
174 |
Â
public function sanitize_settings( $settings ) {
|
175 |
Â
return array(
|
176 |
-
array( '
|
177 |
-
array( 'canonical-roles', 'role', esc_html__( 'Minimum Role for Strong Passwords', 'better-wp-security' ) ),
|
178 |
Â
);
|
179 |
Â
}
|
180 |
Â
|
@@ -215,5 +230,3 @@ final class ITSEC_Strong_Passwords {
|
|
215 |
Â
return $results->score;
|
216 |
Â
}
|
217 |
Â
}
|
218 |
-
|
219 |
-
new ITSEC_Strong_Passwords();
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\Contracts\Runnable;
|
4 |
+
use iThemesSecurity\User_Groups;
|
5 |
+
|
6 |
+
final class ITSEC_Strong_Passwords implements Runnable {
|
7 |
Â
|
8 |
Â
const STRENGTH_KEY = 'itsec-password-strength';
|
9 |
Â
|
10 |
+
/** @var User_Groups\Matcher */
|
11 |
+
private $matcher;
|
12 |
Â
|
13 |
+
/**
|
14 |
+
* ITSEC_Strong_Passwords constructor.
|
15 |
+
*
|
16 |
+
* @param User_Groups\Matcher $matcher
|
17 |
+
*/
|
18 |
+
public function __construct( User_Groups\Matcher $matcher ) {
|
19 |
+
$this->matcher = $matcher;
|
20 |
+
}
|
21 |
Â
|
22 |
+
public function run() {
|
23 |
+
add_action( 'itsec_register_password_requirements', array( $this, 'register_requirements' ) );
|
24 |
+
add_action( 'itsec_register_user_group_settings', [ $this, 'register_group_setting' ] );
|
25 |
Â
add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
|
26 |
Â
add_action( 'resetpass_form', array( $this, 'add_scripts_to_wp_login' ) );
|
27 |
Â
add_action( 'itsec_password_requirements_change_form', array( $this, 'add_scripts_to_wp_login' ) );
|
37 |
Â
'reason' => array( $this, 'reason' ),
|
38 |
Â
'meta' => self::STRENGTH_KEY,
|
39 |
Â
'evaluate_if_not_enabled' => true,
|
40 |
+
'defaults' => array(
|
41 |
+
'group' => ITSEC_Modules::get_settings_obj( 'user-groups' )->get_groups_for_all_users(),
|
42 |
+
),
|
43 |
Â
'settings_config' => array( $this, 'get_settings_config' ),
|
44 |
Â
) );
|
45 |
Â
}
|
46 |
Â
|
47 |
+
public function register_group_setting( User_Groups\Settings_Registry $registry ) {
|
48 |
+
if ( ITSEC_Lib_Password_Requirements::is_requirement_enabled( 'strength' ) ) {
|
49 |
+
$registry->register( new User_Groups\Settings_Registration( 'password-requirements', 'requirement_settings.strength.group', User_Groups\Settings_Registration::T_MULTIPLE, static function () {
|
50 |
+
return [
|
51 |
+
'title' => __( 'Require Strong Passwords', 'better-wp-security' ),
|
52 |
+
'description' => __( 'Force users in the group to use strong passwords.', 'better-wp-security' ),
|
53 |
+
];
|
54 |
+
} ) );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
Â
/**
|
59 |
Â
* Enqueue script to hide the acknowledge weak password checkbox.
|
60 |
Â
*
|
61 |
Â
* @return void
|
62 |
Â
*/
|
63 |
Â
public function add_scripts() {
|
Â
|
|
64 |
Â
global $pagenow;
|
65 |
Â
|
66 |
Â
if ( 'profile.php' !== $pagenow ) {
|
72 |
Â
}
|
73 |
Â
|
74 |
Â
$settings = ITSEC_Lib_Password_Requirements::get_requirement_settings( 'strength' );
|
Â
|
|
Â
|
|
Â
|
|
75 |
Â
|
76 |
+
if ( $this->matcher->matches( User_Groups\Match_Target::for_user( wp_get_current_user() ), $settings['group'] ) ) {
|
77 |
Â
wp_enqueue_script( 'itsec_strong_passwords', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
78 |
Â
}
|
79 |
Â
}
|
92 |
Â
}
|
93 |
Â
|
94 |
Â
$settings = ITSEC_Lib_Password_Requirements::get_requirement_settings( 'strength' );
|
Â
|
|
95 |
Â
|
96 |
+
if ( $this->matcher->matches( User_Groups\Match_Target::for_user( $user ), $settings['group'] ) ) {
|
Â
|
|
Â
|
|
97 |
Â
wp_enqueue_script( 'itsec_strong_passwords', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), ITSEC_Core::get_plugin_build() );
|
98 |
Â
}
|
99 |
Â
}
|
132 |
Â
* @return bool
|
133 |
Â
*/
|
134 |
Â
public function validate( $strength, $user, $settings, $args ) {
|
Â
|
|
135 |
Â
if ( (int) $strength === 4 ) {
|
136 |
Â
return true;
|
137 |
Â
}
|
138 |
Â
|
139 |
+
if ( ! $user = get_userdata( $user->ID ) ) {
|
140 |
+
return true;
|
141 |
+
}
|
142 |
Â
|
143 |
+
$target = isset( $args['target'] ) ? $args['target'] : User_Groups\Match_Target::for_user( $user );
|
144 |
Â
|
145 |
+
if ( ! $this->matcher->matches( $target, $settings['group'] ) ) {
|
146 |
Â
return true;
|
147 |
Â
}
|
148 |
Â
|
164 |
Â
* @param ITSEC_Form $form
|
165 |
Â
*/
|
166 |
Â
public function render_settings( $form ) {
|
Â
|
|
Â
|
|
Â
|
|
167 |
Â
?>
|
168 |
Â
<tr>
|
169 |
Â
<th scope="row">
|
170 |
+
<label for="itsec-password-requirements-requirement_settings-strength-group">
|
171 |
+
<?php esc_html_e( 'User Group', 'better-wp-security' ); ?>
|
172 |
Â
</label>
|
173 |
Â
</th>
|
174 |
Â
<td>
|
175 |
+
<?php $form->add_user_groups( 'group', 'password-requirements', 'requirement_settings.strength.group' ); ?>
|
176 |
Â
<br/>
|
177 |
+
<label for="itsec-password-requirements-requirement_settings-strength-group"><?php _e( 'Force users in the selected groups to use strong passwords.', 'better-wp-security' ); ?></label>
|
Â
|
|
Â
|
|
178 |
Â
</td>
|
179 |
Â
</tr>
|
180 |
Â
<?php
|
189 |
Â
*/
|
190 |
Â
public function sanitize_settings( $settings ) {
|
191 |
Â
return array(
|
192 |
+
array( 'user-groups', 'group', esc_html__( 'User Groups for Strong Passwords', 'better-wp-security' ) ),
|
Â
|
|
193 |
Â
);
|
194 |
Â
}
|
195 |
Â
|
230 |
Â
return $results->score;
|
231 |
Â
}
|
232 |
Â
}
|
Â
|
|
Â
|
core/modules/strong-passwords/container.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use iThemesSecurity\User_Groups\Matcher;
|
4 |
+
|
5 |
+
return static function ( \Pimple\Container $c ) {
|
6 |
+
$c['ITSEC_Strong_Passwords'] = static function ( \Pimple\Container $c ) {
|
7 |
+
return new ITSEC_Strong_Passwords( $c[ Matcher::class ] );
|
8 |
+
};
|
9 |
+
};
|
core/modules/strong-passwords/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Strong Passwords', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/strong-passwords/setup.php
CHANGED
@@ -1,117 +1,94 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
-
|
4 |
Â
|
5 |
-
|
6 |
Â
|
7 |
-
|
Â
|
|
Â
|
|
8 |
Â
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
13 |
Â
|
14 |
-
|
15 |
Â
|
16 |
-
|
17 |
-
* Execute module activation.
|
18 |
-
*
|
19 |
-
* @since 4.0
|
20 |
-
*
|
21 |
-
* @return void
|
22 |
-
*/
|
23 |
-
public function execute_activate() {
|
24 |
-
}
|
25 |
Â
|
26 |
-
|
27 |
-
* Execute module deactivation
|
28 |
-
*
|
29 |
-
* @return void
|
30 |
-
*/
|
31 |
-
public function execute_deactivate() {
|
32 |
-
}
|
33 |
Â
|
34 |
-
|
35 |
-
|
36 |
-
*
|
37 |
-
* @return void
|
38 |
-
*/
|
39 |
-
public function execute_uninstall() {
|
40 |
Â
|
41 |
-
|
Â
|
|
42 |
Â
|
43 |
-
|
Â
|
|
44 |
Â
|
45 |
Â
}
|
46 |
Â
|
47 |
-
|
48 |
-
|
49 |
-
*
|
50 |
-
* @return void
|
51 |
-
*/
|
52 |
-
public function execute_upgrade( $itsec_old_version ) {
|
53 |
-
|
54 |
-
if ( $itsec_old_version < 4000 ) {
|
55 |
Â
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
$current_options['enabled'] = isset( $itsec_bwps_options['st_enablepassword'] ) && $itsec_bwps_options['st_enablepassword'] == 1 ? true : false;
|
64 |
-
$current_options['roll'] = isset( $itsec_bwps_options['st_passrole'] ) ? $itsec_bwps_options['st_passrole'] : 'administrator';
|
65 |
-
|
66 |
-
update_site_option( 'itsec_strong_passwords', $current_options );
|
67 |
Â
}
|
68 |
Â
|
69 |
-
|
70 |
-
|
71 |
-
if ( $itsec_old_version < 4041 ) {
|
72 |
-
$current_options = get_site_option( 'itsec_strong_passwords' );
|
73 |
Â
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
if ( $current_options['enabled'] ) {
|
78 |
-
ITSEC_Modules::activate( 'strong-passwords' );
|
79 |
-
} else {
|
80 |
-
ITSEC_Modules::deactivate( 'strong-passwords' );
|
81 |
-
}
|
82 |
Â
|
83 |
-
|
Â
|
|
84 |
Â
|
85 |
-
|
86 |
-
|
Â
|
|
Â
|
|
87 |
Â
}
|
88 |
Â
|
89 |
-
|
90 |
-
|
Â
|
|
91 |
Â
|
92 |
-
|
93 |
-
$active_requirements = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
94 |
-
$active_requirements['strength'] = true;
|
95 |
-
ITSEC_Modules::set_setting( 'password-requirements', 'enabled_requirements', $active_requirements );
|
96 |
-
}
|
97 |
Â
|
98 |
-
|
99 |
-
|
100 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
101 |
Â
|
102 |
-
|
Â
|
|
Â
|
|
103 |
Â
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
}
|
110 |
Â
}
|
111 |
-
}
|
112 |
Â
|
Â
|
|
Â
|
|
113 |
Â
}
|
114 |
-
|
115 |
Â
}
|
116 |
Â
|
117 |
Â
new ITSEC_Strong_Passwords_Setup();
|
1 |
Â
<?php
|
2 |
Â
|
3 |
+
use iThemesSecurity\User_Groups\Upgrader;
|
4 |
Â
|
5 |
+
class ITSEC_Strong_Passwords_Setup {
|
6 |
Â
|
7 |
+
public function __construct() {
|
8 |
+
add_action( 'itsec_modules_do_plugin_upgrade', array( $this, 'execute_upgrade' ), 0 );
|
9 |
+
}
|
10 |
Â
|
11 |
+
/**
|
12 |
+
* Execute module upgrade
|
13 |
+
*
|
14 |
+
* @param int $itsec_old_version
|
15 |
+
*
|
16 |
+
* @return void
|
17 |
+
*/
|
18 |
+
public function execute_upgrade( $itsec_old_version ) {
|
19 |
Â
|
20 |
+
if ( $itsec_old_version < 4000 ) {
|
21 |
Â
|
22 |
+
global $itsec_bwps_options;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
23 |
Â
|
24 |
+
$current_options = get_site_option( 'itsec_strong_passwords' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
25 |
Â
|
26 |
+
// Don't do anything if settings haven't already been set, defaults exist in the module system and we prefer to use those
|
27 |
+
if ( false !== $current_options ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
28 |
Â
|
29 |
+
$current_options['enabled'] = isset( $itsec_bwps_options['st_enablepassword'] ) && $itsec_bwps_options['st_enablepassword'] == 1 ? true : false;
|
30 |
+
$current_options['roll'] = isset( $itsec_bwps_options['st_passrole'] ) ? $itsec_bwps_options['st_passrole'] : 'administrator';
|
31 |
Â
|
32 |
+
update_site_option( 'itsec_strong_passwords', $current_options );
|
33 |
+
}
|
34 |
Â
|
35 |
Â
}
|
36 |
Â
|
37 |
+
if ( $itsec_old_version < 4041 ) {
|
38 |
+
$current_options = get_site_option( 'itsec_strong_passwords' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
39 |
Â
|
40 |
+
// If there are no current options, go with the new defaults by not saving anything
|
41 |
+
if ( is_array( $current_options ) ) {
|
42 |
+
// Make sure the new module is properly activated or deactivated
|
43 |
+
if ( $current_options['enabled'] ) {
|
44 |
+
ITSEC_Modules::activate( 'strong-passwords' );
|
45 |
+
} else {
|
46 |
+
ITSEC_Modules::deactivate( 'strong-passwords' );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
47 |
Â
}
|
48 |
Â
|
49 |
+
$settings = array( 'role' => $current_options['roll'] );
|
Â
|
|
Â
|
|
Â
|
|
50 |
Â
|
51 |
+
ITSEC_Modules::set_settings( 'strong-passwords', $settings );
|
52 |
+
}
|
53 |
+
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
54 |
Â
|
55 |
+
if ( $itsec_old_version < 4096 ) {
|
56 |
+
$active = get_site_option( 'itsec_active_modules', array() );
|
57 |
Â
|
58 |
+
if ( ! empty( $active['strong-passwords'] ) ) {
|
59 |
+
$active_requirements = ITSEC_Modules::get_setting( 'password-requirements', 'enabled_requirements' );
|
60 |
+
$active_requirements['strength'] = true;
|
61 |
+
ITSEC_Modules::set_setting( 'password-requirements', 'enabled_requirements', $active_requirements );
|
62 |
Â
}
|
63 |
Â
|
64 |
+
$requirement_settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
65 |
+
$requirement_settings['strength']['role'] = ITSEC_Modules::get_setting( 'strong-passwords', 'role', 'administrator' );
|
66 |
+
ITSEC_Modules::set_setting( 'password-requirements', 'requirement_settings', $requirement_settings );
|
67 |
Â
|
68 |
+
unset( $active['strong-passwords'] );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
69 |
Â
|
70 |
+
// Need to do this directly to be able to remove a module from the list entirely.
|
71 |
+
if ( is_multisite() ) {
|
72 |
+
update_site_option( 'itsec_active_modules', $active );
|
73 |
+
} else {
|
74 |
+
update_option( 'itsec_active_modules', $active );
|
75 |
+
}
|
76 |
+
}
|
77 |
Â
|
78 |
+
if ( $itsec_old_version < 4117 ) {
|
79 |
+
delete_site_option( 'itsec_strong_passwords' );
|
80 |
+
$settings = ITSEC_Modules::get_setting( 'password-requirements', 'requirement_settings' );
|
81 |
Â
|
82 |
+
if ( isset( $settings['strength']['role'] ) ) {
|
83 |
+
$settings['strength']['group'] = ITSEC_Modules::get_container()
|
84 |
+
->get( Upgrader::class )
|
85 |
+
->upgrade_from_min_role( $settings['strength']['role'] );
|
86 |
+
unset( $settings['strength']['role'] );
|
Â
|
|
87 |
Â
}
|
Â
|
|
88 |
Â
|
89 |
+
ITSEC_Modules::set_setting( 'password-requirements', 'requirement_settings', $settings );
|
90 |
+
}
|
91 |
Â
}
|
Â
|
|
92 |
Â
}
|
93 |
Â
|
94 |
Â
new ITSEC_Strong_Passwords_Setup();
|
core/modules/sync-connect/active.php
ADDED
@@ -0,0 +1,6 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once( __DIR__ . '/class-itsec-sync-connect.php' );
|
4 |
+
|
5 |
+
$sync_connect = new ITSEC_Sync_Connect();
|
6 |
+
$sync_connect->run();
|
core/modules/sync-connect/class-itsec-sync-connect-interstitial.php
ADDED
@@ -0,0 +1,136 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ITSEC_Sync_Connect_Interstitial extends ITSEC_Login_Interstitial {
|
4 |
+
|
5 |
+
/** @var string */
|
6 |
+
private $sync_dashboard = 'https://sync.ithemes.com/manage/site/';
|
7 |
+
|
8 |
+
/** @var ITSEC_Sync_Connect */
|
9 |
+
private $sync_connect;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* ITSEC_Sync_Connect_Interstitial constructor.
|
13 |
+
*
|
14 |
+
* @param ITSEC_Sync_Connect $sync_connect
|
15 |
+
*/
|
16 |
+
public function __construct( ITSEC_Sync_Connect $sync_connect ) {
|
17 |
+
$this->sync_connect = $sync_connect;
|
18 |
+
}
|
19 |
+
|
20 |
+
public function render( ITSEC_Login_Interstitial_Session $session, array $args ) {
|
21 |
+
|
22 |
+
$user = $session->get_user();
|
23 |
+
|
24 |
+
if ( $user && $this->sync_connect->user_can_install_and_activate( $user ) ) {
|
25 |
+
require_once( __DIR__ . '/templates/connect-prompt.php' );
|
26 |
+
} else {
|
27 |
+
require_once( __DIR__ . '/templates/connect-unauthorized.php' );
|
28 |
+
}
|
29 |
+
|
30 |
+
}
|
31 |
+
|
32 |
+
public function pre_render( ITSEC_Login_Interstitial_Session $session ) {
|
33 |
+
add_action( 'login_enqueue_scripts', static function () {
|
34 |
+
wp_enqueue_style( 'itsec-sync-connect', plugin_dir_url( __FILE__ ) . 'css/connect.css' );
|
35 |
+
} );
|
36 |
+
}
|
37 |
+
|
38 |
+
public function is_completion_forced( ITSEC_Login_Interstitial_Session $session ) {
|
39 |
+
return false;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function has_submit() {
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
|
46 |
+
public function submit( ITSEC_Login_Interstitial_Session $session, array $post_data ) {
|
47 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
48 |
+
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
49 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
50 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
|
51 |
+
|
52 |
+
$user = $session->get_user();
|
53 |
+
|
54 |
+
if ( ! $user || ! $this->sync_connect->user_can_install_and_activate( $user ) ) {
|
55 |
+
return null;
|
56 |
+
}
|
57 |
+
|
58 |
+
// If the plugin is not installed, install it
|
59 |
+
if ( ! $this->sync_connect->is_plugin_installed() ) {
|
60 |
+
$install = $this->sync_connect->install_plugin();
|
61 |
+
|
62 |
+
// Could not install plugin, return error to manually install
|
63 |
+
if ( is_wp_error( $install ) ) {
|
64 |
+
return new WP_Error(
|
65 |
+
'itsec-sync-connect-plugin-install-failure',
|
66 |
+
sprintf(
|
67 |
+
__( 'The plugin could not be installed. Please manually install the plugin. Error: %s', 'better-wp-security' ),
|
68 |
+
implode( ' ', $install->get_error_messages() )
|
69 |
+
)
|
70 |
+
);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
// Activate the plugin
|
75 |
+
if ( ! is_plugin_active( ITSEC_Sync_Connect::PLUGIN_SLUG ) ) {
|
76 |
+
$activate = activate_plugin( ITSEC_Sync_Connect::PLUGIN_SLUG );
|
77 |
+
|
78 |
+
// Could not activate plugin, return error to activate or try reinstalling
|
79 |
+
if ( is_wp_error( $activate ) ) {
|
80 |
+
return new WP_Error(
|
81 |
+
'itsec-sync-connect-plugin-activate-failure',
|
82 |
+
sprintf(
|
83 |
+
__( 'The plugin could not be activated. Please manually activate the plugin. Error: %s', 'better-wp-security' ),
|
84 |
+
implode( ' ', $activate->get_error_messages() )
|
85 |
+
)
|
86 |
+
);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
$token = $session->get_meta( 'itsec_sync_connect_token' );
|
91 |
+
|
92 |
+
if ( ! $token && isset( $post_data['itsec_sync_connect_token'] ) ) {
|
93 |
+
$token = $post_data['itsec_sync_connect_token'];
|
94 |
+
}
|
95 |
+
|
96 |
+
// Link to iThemes account
|
97 |
+
if ( ! $token ) {
|
98 |
+
return new WP_Error( 'itsec-sync-connect-plugin-token-missing', __( 'Missing sync connect token.', 'better-wp-security' ) );
|
99 |
+
}
|
100 |
+
|
101 |
+
require_once( WP_PLUGIN_DIR . '/ithemes-sync/functions.php' );
|
102 |
+
$sync_nonce = Ithemes_Sync_Functions::generate_sync_nonce( 'itsec-connect' );
|
103 |
+
|
104 |
+
$response = $this->sync_connect->send_activation_request( $user->user_login, $token, $sync_nonce );
|
105 |
+
|
106 |
+
if ( is_wp_error( $response ) ) {
|
107 |
+
return $response;
|
108 |
+
}
|
109 |
+
|
110 |
+
require_once( WP_PLUGIN_DIR . '/ithemes-sync/settings.php' );
|
111 |
+
$GLOBALS['ithemes-sync-settings']->add_authentication( $response['site_id'], $response['username'], $response['key'], $user->user_login );
|
112 |
+
|
113 |
+
ITSEC_Log::add_notice( 'sync_connect', 'successful_authentication::' . $user->ID, compact( 'post_data' ), compact( 'site_id' ) );
|
114 |
+
|
115 |
+
wp_redirect( $this->sync_dashboard . $response['site_id'] );
|
116 |
+
exit;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Whether the sync interstitial should be shown to the given user.
|
121 |
+
*
|
122 |
+
* We only show this interstitial if it was requested by the user.
|
123 |
+
*
|
124 |
+
* @param WP_User $user
|
125 |
+
* @param bool $is_requested
|
126 |
+
*
|
127 |
+
* @return bool
|
128 |
+
*/
|
129 |
+
public function show_to_user( WP_User $user, $is_requested ) {
|
130 |
+
return $is_requested;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function get_priority() {
|
134 |
+
return PHP_INT_MAX;
|
135 |
+
}
|
136 |
+
}
|
core/modules/sync-connect/class-itsec-sync-connect.php
ADDED
@@ -0,0 +1,183 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Sync-Connection Execution
|
5 |
+
*
|
6 |
+
* Handles the Sync Connection Interstitial
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
class ITSEC_Sync_Connect {
|
10 |
+
|
11 |
+
/** @var string */
|
12 |
+
private $sync_api = 'https://sync.ithemes.com/plugin-api/authenticate-token';
|
13 |
+
|
14 |
+
const R_SYNC_TOKEN = 'itsec_sync_connect_token';
|
15 |
+
const PLUGIN_SLUG = 'ithemes-sync/init.php';
|
16 |
+
|
17 |
+
public function run() {
|
18 |
+
add_action( 'itsec_login_interstitial_init', array( $this, 'register_interstitial' ) );
|
19 |
+
add_action( 'login_form', array( $this, 'ferry_sync_connect_token' ) );
|
20 |
+
add_action( 'itsec_initialize_login_interstitial_session_from_global_state', array( $this, 'set_sync_token_meta' ) );
|
21 |
+
add_filter( 'itsec_rest_supports', array( $this, 'add_sync_connect_to_rest_supports' ) );
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Register the sync connect interstitial.
|
26 |
+
*
|
27 |
+
* @param ITSEC_Lib_Login_Interstitial $lib
|
28 |
+
*/
|
29 |
+
public function register_interstitial( $lib ) {
|
30 |
+
require_once( __DIR__ . '/class-itsec-sync-connect-interstitial.php' );
|
31 |
+
|
32 |
+
$lib->register( 'sync-connect', new ITSEC_Sync_Connect_Interstitial( $this ) );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Is the given plugin installed.
|
37 |
+
*
|
38 |
+
* @return bool
|
39 |
+
*/
|
40 |
+
public function is_plugin_installed() {
|
41 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
42 |
+
|
43 |
+
$plugins = get_plugins();
|
44 |
+
|
45 |
+
return ! empty( $plugins[ self::PLUGIN_SLUG ] );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Install the plugin contained in a zip file.
|
50 |
+
*
|
51 |
+
* @return true|WP_Error
|
52 |
+
*/
|
53 |
+
public function install_plugin() {
|
54 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
55 |
+
require_once( __DIR__ . '/includes/upgrader-skin.php' );
|
56 |
+
|
57 |
+
$skin = new ITSEC_Ithemes_Sync_Upgrader_Skin();
|
58 |
+
$upgrader = new Plugin_Upgrader( $skin );
|
59 |
+
$installed = $upgrader->install( 'https://downloads.wordpress.org/plugin/ithemes-sync.zip' );
|
60 |
+
|
61 |
+
if ( true !== $installed && ! is_wp_error( $installed ) ) {
|
62 |
+
$error = new WP_Error();
|
63 |
+
|
64 |
+
foreach ( $skin->errors as $additional ) {
|
65 |
+
if ( is_wp_error( $additional ) ) {
|
66 |
+
ITSEC_Lib::add_to_wp_error( $error, $additional );
|
67 |
+
} elseif ( is_string( $additional ) ) {
|
68 |
+
$error->add( '', $additional );
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
if ( ! $error->has_errors() ) {
|
73 |
+
$error->add( 'installation_failed_unknown_reason', __( 'Installation failed for an unknown reason.', 'better-wp-security' ) );
|
74 |
+
}
|
75 |
+
|
76 |
+
if ( $messages = $skin->get_upgrade_messages() ) {
|
77 |
+
$error->add( 'feedback', implode( ' ', $messages ) );
|
78 |
+
}
|
79 |
+
|
80 |
+
return $error;
|
81 |
+
}
|
82 |
+
|
83 |
+
return $installed;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Check if the user has permission to install and activate plugins.
|
88 |
+
*
|
89 |
+
* @param WP_User $user
|
90 |
+
*
|
91 |
+
* @return bool
|
92 |
+
*/
|
93 |
+
public function user_can_install_and_activate( WP_User $user ) {
|
94 |
+
return $user->has_cap( 'install_plugins' ) && $user->has_cap( 'activate_plugins' ) && $user->has_cap( 'activate_plugin', self::PLUGIN_SLUG );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Send the activation request to iThemes Sync.
|
99 |
+
*
|
100 |
+
* @param string $username Username of the WordPress user installing Sync.
|
101 |
+
* @param string $token The secure token to pass back to iThemes Sync.
|
102 |
+
* @param string $sync_nonce Generated by sync plugin to verify connection from Sync dashboard.
|
103 |
+
*
|
104 |
+
* @return array|WP_Error
|
105 |
+
*/
|
106 |
+
public function send_activation_request( $username, $token, $sync_nonce ) {
|
107 |
+
|
108 |
+
$data = array(
|
109 |
+
'site' => get_home_url(),
|
110 |
+
'u' => $username,
|
111 |
+
'token' => $token,
|
112 |
+
'wp' => get_bloginfo( 'version' ),
|
113 |
+
'nonce' => $sync_nonce
|
114 |
+
);
|
115 |
+
|
116 |
+
$remote_post_args = array(
|
117 |
+
'method' => 'POST',
|
118 |
+
'timeout' => 30,
|
119 |
+
'body' => $data,
|
120 |
+
'data_format' => 'body'
|
121 |
+
);
|
122 |
+
|
123 |
+
$request = wp_remote_post( $this->sync_api, $remote_post_args );
|
124 |
+
|
125 |
+
if ( is_wp_error( $request ) ) {
|
126 |
+
if ( 'connect() timed out!' === $request->get_error_message() ) {
|
127 |
+
return new WP_Error( 'http_request_failed', __( 'The server was unable to be contacted.', 'better-wp-security' ) );
|
128 |
+
}
|
129 |
+
|
130 |
+
return $request;
|
131 |
+
}
|
132 |
+
|
133 |
+
if ( $request['response']['code'] !== 200 ) {
|
134 |
+
return new WP_Error( 'itsec-sync-connect-invalid-response', sprintf( __( 'Invalid response from the server (Code: %d). Please manually activate the plugin.', 'better-wp-security' ), $request['response']['code'] ) );
|
135 |
+
}
|
136 |
+
|
137 |
+
$response_body = json_decode( wp_remote_retrieve_body( $request ), true );
|
138 |
+
|
139 |
+
if ( ! $response_body ) {
|
140 |
+
return new WP_Error( 'itsec-sync-connect-invalid-json', __( 'Invalid JSON response from Sync API. Please manually activate the plugin.', 'better-wp-security' ) );
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( ! $response_body['success'] ) {
|
144 |
+
return new WP_Error( 'itsec-sync-connect-invalid-token', 'Sync user or connection token could not be validated.' );
|
145 |
+
}
|
146 |
+
|
147 |
+
return $response_body;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Ferry the sync connection token into the form
|
152 |
+
*
|
153 |
+
* @internal
|
154 |
+
*/
|
155 |
+
public function ferry_sync_connect_token() {
|
156 |
+
if ( ! empty( $_REQUEST[ self::R_SYNC_TOKEN ] ) ) {
|
157 |
+
echo '<input type="hidden" name="' . esc_attr( self::R_SYNC_TOKEN ) . '" value="' . esc_attr( $_REQUEST[ self::R_SYNC_TOKEN ] ) . '">';
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Saves the sync token as meta for the interstitial.
|
163 |
+
*
|
164 |
+
* When Sync redirects the user to the login page, capture the secure sync token provided in the URL.
|
165 |
+
*
|
166 |
+
* @param ITSEC_Login_Interstitial_Session $session
|
167 |
+
*/
|
168 |
+
public function set_sync_token_meta( ITSEC_Login_Interstitial_Session $session ) {
|
169 |
+
if ( ! empty( $_REQUEST[ self::R_SYNC_TOKEN ] ) ) {
|
170 |
+
$session->set_meta( self::R_SYNC_TOKEN, $_REQUEST[ self::R_SYNC_TOKEN ] );
|
171 |
+
|
172 |
+
if ( ! in_array( 'sync-connect', $session->get_show_after() ) ) {
|
173 |
+
$session->add_show_after( 'sync-connect' );
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
public function add_sync_connect_to_rest_supports( $supported ) {
|
179 |
+
$supported[] = 'sync-connect';
|
180 |
+
|
181 |
+
return $supported;
|
182 |
+
}
|
183 |
+
}
|
core/modules/sync-connect/css/connect.css
ADDED
@@ -0,0 +1,84 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-sync-connect__logo {
|
2 |
+
margin: 0 auto 20px auto;
|
3 |
+
display: block;
|
4 |
+
width: 100%;
|
5 |
+
}
|
6 |
+
|
7 |
+
.itsec-sync-connect__title,
|
8 |
+
.itsec-sync-connect__description,
|
9 |
+
.itsec-sync-connect__link-wrap,
|
10 |
+
.itsec-sync-connect-fallback__link-wrap {
|
11 |
+
text-align: center;
|
12 |
+
}
|
13 |
+
|
14 |
+
.itsec-sync-connect__title {
|
15 |
+
font-weight: bold;
|
16 |
+
margin-bottom: 10px !important;
|
17 |
+
}
|
18 |
+
|
19 |
+
.itsec-sync-connect__description {
|
20 |
+
margin-bottom: 10px !important;
|
21 |
+
}
|
22 |
+
|
23 |
+
.itsec-sync-connect__link {
|
24 |
+
margin: 20px 0 !important;
|
25 |
+
}
|
26 |
+
|
27 |
+
.itsec-sync-connect__link {
|
28 |
+
vertical-align: top;
|
29 |
+
display: block;
|
30 |
+
text-decoration: none;
|
31 |
+
height: 28px;
|
32 |
+
margin: 0;
|
33 |
+
cursor: pointer;
|
34 |
+
-webkit-appearance: none;
|
35 |
+
border-radius: 3px;
|
36 |
+
white-space: nowrap;
|
37 |
+
box-sizing: border-box;
|
38 |
+
background: #0084CB;
|
39 |
+
color: #fff;
|
40 |
+
text-shadow: none;
|
41 |
+
padding: 20px 30px;
|
42 |
+
line-height: 0;
|
43 |
+
box-shadow: none;
|
44 |
+
font-weight: 300;
|
45 |
+
font-size: 1.2em;
|
46 |
+
border: none;
|
47 |
+
width: 100%;
|
48 |
+
}
|
49 |
+
|
50 |
+
.itsec-sync-connect__link::-moz-focus-inner {
|
51 |
+
border-width: 0;
|
52 |
+
border-style: none;
|
53 |
+
padding: 0;
|
54 |
+
}
|
55 |
+
|
56 |
+
.itsec-sync-connect__link:hover {
|
57 |
+
background: #006799;
|
58 |
+
color: #fff;
|
59 |
+
}
|
60 |
+
|
61 |
+
.itsec-sync-connect-fallback__or {
|
62 |
+
width: 100%;
|
63 |
+
margin-bottom: 10px;
|
64 |
+
position: relative;
|
65 |
+
text-align: center;
|
66 |
+
}
|
67 |
+
|
68 |
+
.itsec-sync-connect-fallback__or:before {
|
69 |
+
background: #E5E5E5;
|
70 |
+
content: '';
|
71 |
+
height: 1px;
|
72 |
+
position: absolute;
|
73 |
+
left: 0;
|
74 |
+
top: 50%;
|
75 |
+
width: 100%;
|
76 |
+
}
|
77 |
+
|
78 |
+
.itsec-sync-connect-fallback__or span {
|
79 |
+
background: #fff;
|
80 |
+
color: #777;
|
81 |
+
position: relative;
|
82 |
+
padding: 0 8px;
|
83 |
+
text-transform: uppercase
|
84 |
+
}
|
core/modules/sync-connect/css/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/sync-connect/img/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/sync-connect/img/sync-logo.svg
ADDED
@@ -0,0 +1,98 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
3 |
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
4 |
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
5 |
+
y="0px"
|
6 |
+
width="282.653px" height="102.378px" viewBox="0 0 282.653 102.378" enable-background="new 0 0 282.653 102.378"
|
7 |
+
xml:space="preserve">
|
8 |
+
<g>
|
9 |
+
<g>
|
10 |
+
<path fill="#0084CB" d="M159.311,68.345c0,4.953-1.641,8.755-4.92,11.403c-3.281,2.648-7.847,3.974-13.697,3.974
|
11 |
+
c-2.819,0-5.276-0.2-7.373-0.593c-2.093-0.397-4.051-1.053-5.87-1.979v-9.803c4.138,2.373,8.341,3.559,12.611,3.559
|
12 |
+
c2.106,0,3.833-0.429,5.177-1.285c1.343-0.855,2.015-2.021,2.015-3.498c0-1.133-0.488-2.146-1.462-3.044
|
13 |
+
c-0.975-0.894-2.701-2.027-5.179-3.399c-3.186-1.79-5.415-3.576-6.678-5.355c-1.266-1.777-1.897-3.88-1.897-6.305
|
14 |
+
c0-4.481,1.457-7.952,4.367-10.416c2.911-2.461,7.07-3.694,12.47-3.694c5.299,0,10.079,1.251,14.35,3.755l-3.914,8.498
|
15 |
+
c-3.69-2.213-7.088-3.32-10.198-3.32c-1.502,0-2.714,0.336-3.636,1.008c-0.924,0.672-1.383,1.575-1.383,2.708
|
16 |
+
c0,1.026,0.42,1.929,1.265,2.707c0.843,0.777,2.425,1.758,4.742,2.943c3.241,1.661,5.587,3.466,7.036,5.415
|
17 |
+
C158.585,63.575,159.311,65.813,159.311,68.345z"/>
|
18 |
+
<path fill="#0084CB" d="M165.971,38.74h11.661l2.212,20.475c0.371,3.215,0.554,7.074,0.554,11.58h0.237
|
19 |
+
c0.529-1.345,1.108-2.919,1.739-4.722c0.635-1.807,1.488-3.83,2.569-6.068l10.277-21.265h12.925l-26.877,50.515
|
20 |
+
c-4.663,8.748-11.027,13.123-19.093,13.123c-2.371,0-4.307-0.253-5.81-0.752V92.14c1.791,0.342,3.321,0.512,4.585,0.512
|
21 |
+
c2.213,0,4.155-0.631,5.829-1.896c1.675-1.264,3.223-3.227,4.646-5.889l1.027-1.938L165.971,38.74z"/>
|
22 |
+
<path fill="#0084CB" d="M238.525,82.929h-11.896l5.414-25.81c0.421-1.791,0.632-3.36,0.632-4.703c0-3.242-1.423-4.863-4.268-4.863
|
23 |
+
c-2.425,0-4.625,1.502-6.601,4.506c-1.978,3.005-3.533,7.193-4.664,12.569l-3.876,18.3h-11.896l9.367-44.189h9.091L219,46.922
|
24 |
+
h0.236c3.849-6.009,8.523-9.013,14.032-9.013c3.636,0,6.449,1.101,8.438,3.301c1.99,2.201,2.984,5.341,2.984,9.425
|
25 |
+
c0,1.927-0.304,4.298-0.91,7.116L238.525,82.929z"/>
|
26 |
+
<path fill="#0084CB" d="M262.73,83.722c-5.295,0-9.362-1.42-12.193-4.251c-2.832-2.833-4.248-6.831-4.248-11.997
|
27 |
+
c0-5.584,0.982-10.663,2.942-15.236c1.964-4.572,4.726-8.104,8.282-10.593c3.559-2.49,7.614-3.736,12.174-3.736
|
28 |
+
c4.797,0,9.116,0.95,12.966,2.846l-3.638,9.051c-1.423-0.604-2.82-1.131-4.189-1.58c-1.369-0.447-2.925-0.672-4.665-0.672
|
29 |
+
c-2.238,0-4.261,0.844-6.066,2.531c-1.805,1.686-3.216,3.999-4.229,6.936c-1.014,2.938-1.521,6.093-1.521,9.466
|
30 |
+
c0,2.531,0.599,4.436,1.799,5.711c1.199,1.279,2.865,1.919,5,1.919c2,0,3.86-0.311,5.573-0.931
|
31 |
+
c1.715-0.617,3.479-1.389,5.295-2.312v9.725C272.007,82.679,267.579,83.722,262.73,83.722z"/>
|
32 |
+
</g>
|
33 |
+
<g>
|
34 |
+
<path fill="#8CC63F" d="M140.895,31.638h-3.789l2.984-14.076h3.79L140.895,31.638z M140.694,14.264
|
35 |
+
c0-0.729,0.199-1.281,0.597-1.656c0.398-0.373,0.963-0.559,1.695-0.559c0.611,0,1.077,0.129,1.397,0.39
|
36 |
+
c0.318,0.259,0.477,0.633,0.477,1.12c0,0.673-0.185,1.215-0.554,1.63c-0.37,0.416-0.939,0.623-1.712,0.623
|
37 |
+
C141.328,15.812,140.694,15.296,140.694,14.264z"/>
|
38 |
+
<path fill="#8CC63F" d="M150.766,28.831c0.546,0,1.225-0.146,2.039-0.442v2.833c-0.933,0.444-2.048,0.667-3.349,0.667
|
39 |
+
c-1.259,0-2.185-0.264-2.776-0.792c-0.591-0.53-0.888-1.348-0.888-2.457c0-0.419,0.051-0.89,0.15-1.41l1.449-6.787h-1.914
|
40 |
+
l0.365-1.85l2.468-1.057l1.662-2.973h2.442l-0.617,2.997h3.563l-0.63,2.882h-3.551l-1.449,6.787
|
41 |
+
c-0.049,0.251-0.075,0.474-0.075,0.667C149.656,28.519,150.026,28.831,150.766,28.831z"/>
|
42 |
+
<path fill="#8CC63F" d="M166.108,31.638h-3.791l1.726-8.222c0.134-0.569,0.202-1.07,0.202-1.497c0-1.034-0.453-1.549-1.359-1.549
|
43 |
+
c-0.773,0-1.475,0.479-2.103,1.436c-0.63,0.956-1.125,2.291-1.486,4.003l-1.233,5.829h-3.79l4.154-19.589h3.789
|
44 |
+
c-0.327,1.519-0.577,2.686-0.754,3.499c-0.177,0.815-0.537,2.111-1.084,3.892h0.102c0.521-0.647,1.1-1.165,1.736-1.555
|
45 |
+
c0.639-0.392,1.378-0.586,2.217-0.586c1.158,0,2.054,0.35,2.688,1.05c0.634,0.704,0.95,1.704,0.95,3.003
|
46 |
+
c0,0.612-0.097,1.37-0.289,2.267L166.108,31.638z"/>
|
47 |
+
<path fill="#8CC63F" d="M174.874,31.89c-1.763,0-3.131-0.474-4.104-1.421c-0.975-0.95-1.46-2.289-1.46-4.018
|
48 |
+
c0-1.737,0.346-3.321,1.038-4.752c0.693-1.432,1.63-2.521,2.812-3.273c1.185-0.751,2.523-1.127,4.017-1.127
|
49 |
+
c1.486,0,2.645,0.341,3.475,1.026c0.833,0.684,1.248,1.623,1.248,2.815c0,1.568-0.701,2.779-2.103,3.63
|
50 |
+
c-1.402,0.854-3.404,1.279-6.005,1.279h-0.643l-0.026,0.264v0.252c0,0.766,0.217,1.366,0.649,1.807
|
51 |
+
c0.432,0.442,1.051,0.66,1.855,0.66c0.731,0,1.394-0.08,1.989-0.238c0.598-0.16,1.318-0.44,2.166-0.842v2.856
|
52 |
+
C178.341,31.528,176.703,31.89,174.874,31.89z M176.938,20.03c-0.737,0-1.436,0.336-2.09,1.007
|
53 |
+
c-0.655,0.671-1.083,1.49-1.284,2.456h0.566c1.302,0,2.313-0.205,3.039-0.611c0.727-0.407,1.09-0.959,1.09-1.656
|
54 |
+
C178.26,20.429,177.819,20.03,176.938,20.03z"/>
|
55 |
+
<path fill="#8CC63F" d="M191.116,17.298c1.837,0,2.938,0.958,3.298,2.87h0.076c0.571-0.922,1.243-1.632,2.021-2.127
|
56 |
+
c0.775-0.496,1.605-0.743,2.486-0.743c1.142,0,2.012,0.357,2.613,1.071c0.598,0.713,0.9,1.708,0.9,2.982
|
57 |
+
c0,0.639-0.097,1.395-0.29,2.267l-1.675,8.02h-3.79l1.737-8.222c0.135-0.569,0.202-1.07,0.202-1.497
|
58 |
+
c0-1.034-0.411-1.549-1.234-1.549c-0.772,0-1.472,0.47-2.095,1.41c-0.627,0.941-1.124,2.274-1.494,4.004l-1.207,5.854h-3.791
|
59 |
+
l1.726-8.222c0.135-0.569,0.201-1.07,0.201-1.497c0-1.034-0.41-1.549-1.233-1.549c-0.771,0-1.473,0.479-2.103,1.436
|
60 |
+
c-0.629,0.956-1.126,2.291-1.485,4.003l-1.233,5.829h-3.79l2.984-14.076h2.896l-0.265,2.606h0.075
|
61 |
+
C187.872,18.256,189.361,17.298,191.116,17.298z"/>
|
62 |
+
<path fill="#8CC63F" d="M208.584,31.89c-1.764,0-3.131-0.474-4.104-1.421c-0.975-0.95-1.461-2.289-1.461-4.018
|
63 |
+
c0-1.737,0.346-3.321,1.039-4.752c0.691-1.432,1.629-2.521,2.814-3.273c1.182-0.751,2.521-1.127,4.015-1.127
|
64 |
+
c1.486,0,2.645,0.341,3.475,1.026c0.831,0.684,1.247,1.623,1.247,2.815c0,1.568-0.7,2.779-2.104,3.63
|
65 |
+
c-1.401,0.854-3.402,1.279-6.005,1.279h-0.642l-0.025,0.264v0.252c0,0.766,0.216,1.366,0.648,1.807
|
66 |
+
c0.432,0.442,1.052,0.66,1.856,0.66c0.731,0,1.395-0.08,1.99-0.238c0.597-0.16,1.316-0.44,2.164-0.842v2.856
|
67 |
+
C212.05,31.528,210.412,31.89,208.584,31.89z M210.648,20.03c-0.738,0-1.436,0.336-2.092,1.007
|
68 |
+
c-0.653,0.671-1.081,1.49-1.283,2.456h0.566c1.301,0,2.316-0.205,3.042-0.611c0.725-0.407,1.088-0.959,1.088-1.656
|
69 |
+
C211.97,20.429,211.529,20.03,210.648,20.03z"/>
|
70 |
+
<path fill="#8CC63F" d="M225.398,26.993c0,1.577-0.523,2.787-1.568,3.631c-1.044,0.845-2.498,1.265-4.362,1.265
|
71 |
+
c-0.897,0-1.681-0.063-2.348-0.189c-0.667-0.125-1.29-0.335-1.87-0.63v-3.12c1.318,0.755,2.657,1.132,4.018,1.132
|
72 |
+
c0.671,0,1.221-0.136,1.647-0.409c0.429-0.273,0.644-0.645,0.644-1.115c0-0.361-0.156-0.684-0.467-0.97
|
73 |
+
c-0.31-0.285-0.86-0.646-1.648-1.081c-1.016-0.571-1.725-1.141-2.129-1.706c-0.402-0.567-0.604-1.237-0.604-2.009
|
74 |
+
c0-1.427,0.466-2.533,1.393-3.318c0.928-0.784,2.252-1.176,3.972-1.176c1.688,0,3.211,0.399,4.571,1.197l-1.247,2.706
|
75 |
+
c-1.176-0.706-2.259-1.058-3.248-1.058c-0.479,0-0.865,0.107-1.159,0.322c-0.294,0.215-0.44,0.501-0.44,0.862
|
76 |
+
c0,0.327,0.135,0.616,0.403,0.862c0.269,0.248,0.772,0.561,1.511,0.938c1.032,0.528,1.779,1.104,2.24,1.726
|
77 |
+
C225.167,25.473,225.398,26.187,225.398,26.993z"/>
|
78 |
+
</g>
|
79 |
+
</g>
|
80 |
+
<path fill="#8CC63F" d="M115.257,20.541L97.52,24.091C89.779,9.219,74.633,0,57.876,0c-2.739,0-5.503,0.256-8.214,0.759
|
81 |
+
c-2.579,0.479-5.146,1.196-7.63,2.128C21.849,10.474,9.955,31.32,13.66,52.533L0,69.843l18.391-3.68
|
82 |
+
c7.827,14.521,22.855,23.523,39.338,23.523l0,0c2.739,0,5.503-0.255,8.215-0.76c2.58-0.479,5.147-1.195,7.631-2.127
|
83 |
+
c20.081-7.549,31.989-28.306,28.404-49.433L115.257,20.541z M4.73,66.942L14.99,53.94l0.721-0.912l-0.207-1.109
|
84 |
+
c-3.381-20.175,8.059-40.042,27.202-47.237c2.373-0.892,4.831-1.578,7.306-2.038c2.597-0.482,5.243-0.727,7.866-0.727
|
85 |
+
c16.15,0,31.213,9.381,38.374,23.898l0.217,0.44l14.058-2.813L99.938,36.859l0.127,0.688c3.505,20.264-7.919,40.223-27.167,47.458
|
86 |
+
c-2.379,0.895-4.837,1.58-7.307,2.038c-2.596,0.482-5.241,0.728-7.863,0.728c-15.864,0-30.347-8.732-37.776-22.744l-0.248-0.567
|
87 |
+
l-0.258-0.463L4.73,66.942z"/>
|
88 |
+
<path fill="#0084CB" d="M57.859,78.396c-11.458,0-21.991-5.525-28.174-14.781l-0.107-0.215l-0.58-1.648l25.604-5.125
|
89 |
+
c-6.569-3.504-21.57-11.568-22.904-12.852c-2.959-2.846-3.445-4.716-3.959-6.696l-0.036-0.138c-0.476-1.827,0.097-5.077,0.831-7.324
|
90 |
+
c1.826-5.278,5.44-11.891,17.326-16.359c3.824-1.438,7.816-2.167,11.866-2.167c11.407,0,22.302,5.963,28.434,15.562l0.077,0.147
|
91 |
+
l0.699,1.679l-26.482,5.301c5.007,2.769,16.539,9.151,18.273,10.173c4.735,2.793,7.432,5.83,8.242,9.282
|
92 |
+
c0.91,3.874,0.118,6.825-0.673,8.963c-0.871,2.643-7.35,11.087-16.718,14.252C65.761,77.741,61.817,78.396,57.859,78.396z
|
93 |
+
M31.701,63.164c5.876,8.352,15.598,13.315,26.158,13.315c3.75,0,7.486-0.62,11.107-1.844c8.823-2.98,14.823-10.946,15.522-13.069
|
94 |
+
c0.709-1.918,1.409-4.516,0.616-7.892c-0.675-2.876-3.148-5.592-7.35-8.07C75.6,44.334,57.422,34.294,57.239,34.193l-2.291-1.265
|
95 |
+
l29.203-5.845c-5.848-8.701-15.905-14.076-26.424-14.076c-3.818,0-7.584,0.688-11.192,2.044
|
96 |
+
C35.46,19.214,32.139,25.059,30.35,30.228c-0.75,2.3-1.101,5.044-0.792,6.23l0.036,0.139c0.482,1.858,0.863,3.325,3.433,5.796
|
97 |
+
c1.06,1.01,15.8,9,24.842,13.8l2.372,1.259L31.701,63.164z"/>
|
98 |
+
</svg>
|
core/modules/sync-connect/includes/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/sync-connect/includes/upgrader-skin.php
ADDED
@@ -0,0 +1,23 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ITSEC_Ithemes_Sync_Upgrader_Skin extends Automatic_Upgrader_Skin {
|
4 |
+
public $errors = [];
|
5 |
+
|
6 |
+
public function error( $errors ) {
|
7 |
+
$this->errors[] = $errors;
|
8 |
+
}
|
9 |
+
|
10 |
+
public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
|
11 |
+
if ( ! function_exists( 'submit_button' ) ) {
|
12 |
+
require_once( ABSPATH . 'wp-admin/includes/template.php' );
|
13 |
+
}
|
14 |
+
|
15 |
+
$r = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership );
|
16 |
+
|
17 |
+
if ( false === $r ) {
|
18 |
+
$this->error( __( 'Could not request filesystem credentials.', 'better-wp-security' ) );
|
19 |
+
}
|
20 |
+
|
21 |
+
return $r;
|
22 |
+
}
|
23 |
+
}
|
core/modules/sync-connect/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/sync-connect/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'Sync Connect', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/sync-connect/templates/connect-prompt.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div class="itsec-sync-connect-wrap">
|
2 |
+
<img class="itsec-sync-connect__logo" height="116" src="<?php echo esc_url( plugin_dir_url( __DIR__ ) . 'img/sync-logo.svg' ); ?>" alt="">
|
3 |
+
<p class="itsec-sync-connect__title"><?php esc_html_e( 'Connecting iThemes Sync', 'better-wp-security' ); ?></p>
|
4 |
+
<p class="itsec-sync-connect__description"><?php esc_html_e( 'This will install the iThemes Sync plugin and connect the plugin to your Sync account.', 'better-wp-security' ); ?></p>
|
5 |
+
|
6 |
+
<?php require( __DIR__ . '/prompt-link.php' ); ?>
|
7 |
+
|
8 |
+
<?php require( __DIR__ . '/fallback.php' ); ?>
|
9 |
+
</div>
|
core/modules/sync-connect/templates/connect-unauthorized.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div class="itsec-sync-connect-wrap">
|
2 |
+
<img class="itsec-sync-connect__logo" height="116" src="<?php echo esc_url( plugin_dir_url( __DIR__ ) . 'img/sync-logo.svg' ); ?>" alt="">
|
3 |
+
<p class="itsec-sync-connect__title"><?php esc_html_e( 'Account is not authorized', 'better-wp-security' ); ?></p>
|
4 |
+
<p class="itsec-sync-connect__description"><?php esc_html_e( 'Your user account does not have the ability to install or activate plugins. Please ask your site administrator to install Sync.', 'better-wp-security' ); ?></p>
|
5 |
+
|
6 |
+
<p class="itsec-sync-connect__link-wrap">
|
7 |
+
<a class="itsec-sync-connect__link" href="https://sync.ithemes.com">
|
8 |
+
<?php esc_html_e( 'Take me back to Sync', 'better-wp-security' ); ?>
|
9 |
+
</a>
|
10 |
+
</p>
|
11 |
+
</div>
|
core/modules/sync-connect/templates/fallback.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div class="itsec-sync-connect-fallback">
|
2 |
+
<?php require( __DIR__ . '/or.php' ); ?>
|
3 |
+
|
4 |
+
<p class="itsec-sync-connect-fallback__link-wrap itsec-sync-connect-fallback__link-wrap--type-wp">
|
5 |
+
<a class="itsec-sync-connect-fallback__link"
|
6 |
+
href="https://sync.ithemes.com">
|
7 |
+
<?php esc_html_e( 'Take me back to Sync', 'better-wp-security' ); ?>
|
8 |
+
</a>
|
9 |
+
</p>
|
10 |
+
|
11 |
+
</div>
|
core/modules/sync-connect/templates/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/sync-connect/templates/or.php
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div class="itsec-sync-connect-fallback__or">
|
2 |
+
<span><?php esc_html_e( 'Or', 'better-wp-security' ) ?></span>
|
3 |
+
</div>
|
core/modules/sync-connect/templates/prompt-link.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<p class="itsec-sync-connect__link-wrap">
|
2 |
+
<input type="submit" class="itsec-sync-connect__link" value="<?php esc_html_e( 'Connect Sync', 'better-wp-security' ) ?>">
|
3 |
+
</p>
|
4 |
+
|
5 |
+
<?php
|
6 |
+
if ( isset( $_REQUEST['itsec_sync_connect_token'] ) ) {
|
7 |
+
echo '<input type="hidden" name="itsec_sync_connect_token" value="' . esc_attr( $_REQUEST['itsec_sync_connect_token'] ) . '">';
|
8 |
+
}
|
9 |
+
?>
|
core/modules/system-tweaks/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'System Tweaks', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/user-groups/All_Users.php
ADDED
@@ -0,0 +1,17 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
final class All_Users implements Matchable {
|
6 |
+
public function get_id() {
|
7 |
+
return ':all';
|
8 |
+
}
|
9 |
+
|
10 |
+
public function get_label() {
|
11 |
+
return __( 'All Users', 'better-wp-security' );
|
12 |
+
}
|
13 |
+
|
14 |
+
public function matches( Match_Target $target ) {
|
15 |
+
return true;
|
16 |
+
}
|
17 |
+
}
|
core/modules/user-groups/Everybody_Else.php
ADDED
@@ -0,0 +1,38 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
6 |
+
|
7 |
+
final class Everybody_Else implements Matchable {
|
8 |
+
|
9 |
+
const ID = 'everybody-else';
|
10 |
+
|
11 |
+
/** @var Repository */
|
12 |
+
private $repository;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Everybody_Else constructor.
|
16 |
+
*
|
17 |
+
* @param Repository $repository
|
18 |
+
*/
|
19 |
+
public function __construct( Repository $repository ) { $this->repository = $repository; }
|
20 |
+
|
21 |
+
public function matches( Match_Target $target ) {
|
22 |
+
foreach ( $this->repository->all() as $user_group ) {
|
23 |
+
if ( $user_group->matches( $target ) ) {
|
24 |
+
return false;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
return true;
|
29 |
+
}
|
30 |
+
|
31 |
+
public function get_id() {
|
32 |
+
return self::ID;
|
33 |
+
}
|
34 |
+
|
35 |
+
public function get_label() {
|
36 |
+
return __( 'Everybody Else', 'better-wp-security' );
|
37 |
+
}
|
38 |
+
}
|
core/modules/user-groups/Match/Default_Matcher.php
ADDED
@@ -0,0 +1,33 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
final class Default_Matcher implements Matcher {
|
6 |
+
|
7 |
+
/** @var Matchables_Source */
|
8 |
+
private $source;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Default_Matcher constructor.
|
12 |
+
*
|
13 |
+
* @param Matchables_Source $source
|
14 |
+
*/
|
15 |
+
public function __construct( Matchables_Source $source ) { $this->source = $source; }
|
16 |
+
|
17 |
+
public function matches( Match_Target $target, $groups ) {
|
18 |
+
foreach ( $groups as $group ) {
|
19 |
+
try {
|
20 |
+
$matchable = $this->source->find( $group );
|
21 |
+
} catch ( Matchable_Not_Found $e ) {
|
22 |
+
continue;
|
23 |
+
}
|
24 |
+
|
25 |
+
if ( $matchable->matches( $target ) ) {
|
26 |
+
return true;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
return false;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
core/modules/user-groups/Match/Match_Target.php
ADDED
@@ -0,0 +1,66 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use WP_User;
|
6 |
+
|
7 |
+
final class Match_Target {
|
8 |
+
|
9 |
+
/** @var WP_User|null */
|
10 |
+
private $user;
|
11 |
+
|
12 |
+
/** @var string */
|
13 |
+
private $role;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Match_Target constructor.
|
17 |
+
*
|
18 |
+
* @param WP_User|null $user
|
19 |
+
* @param string $role
|
20 |
+
*/
|
21 |
+
private function __construct( WP_User $user = null, $role = '' ) {
|
22 |
+
$this->user = $user;
|
23 |
+
$this->role = $role;
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Creates a new Match Target with a user.
|
28 |
+
*
|
29 |
+
* @param WP_User $user User to match against.
|
30 |
+
* @param string $role Optionally, specify the role to check against instead of the user's current role.
|
31 |
+
*
|
32 |
+
* @return Match_Target
|
33 |
+
*/
|
34 |
+
public static function for_user( WP_User $user, $role = '' ) {
|
35 |
+
return new self( $user, $role );
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Creates a new Match Target for a role.
|
40 |
+
*
|
41 |
+
* @param string $role
|
42 |
+
*
|
43 |
+
* @return Match_Target
|
44 |
+
*/
|
45 |
+
public static function for_role( $role ) {
|
46 |
+
return new self( null, $role );
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Gets the user to match against.
|
51 |
+
*
|
52 |
+
* @return WP_User|null The user may not be defined.
|
53 |
+
*/
|
54 |
+
public function get_user() {
|
55 |
+
return $this->user;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Gets the role to check against.
|
60 |
+
*
|
61 |
+
* @return string
|
62 |
+
*/
|
63 |
+
public function get_role() {
|
64 |
+
return $this->role;
|
65 |
+
}
|
66 |
+
}
|
core/modules/user-groups/Match/Matchable_Not_Found.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Exception;
|
6 |
+
|
7 |
+
final class Matchable_Not_Found extends \OutOfBoundsException implements Exception {
|
8 |
+
|
9 |
+
}
|
core/modules/user-groups/Match/Matcher.php
ADDED
@@ -0,0 +1,16 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
interface Matcher {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Checks if their is a match for one of the group identifiers.
|
9 |
+
*
|
10 |
+
* @param Match_Target $target
|
11 |
+
* @param string[] $groups
|
12 |
+
*
|
13 |
+
* @return bool
|
14 |
+
*/
|
15 |
+
public function matches( Match_Target $target, $groups );
|
16 |
+
}
|
core/modules/user-groups/Match/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/Matchable.php
ADDED
@@ -0,0 +1,29 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
interface Matchable {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Checks if the given user matches the rules for this user group
|
9 |
+
*
|
10 |
+
* @param Match_Target $target
|
11 |
+
*
|
12 |
+
* @return bool
|
13 |
+
*/
|
14 |
+
public function matches( Match_Target $target );
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Get a globally unique identifier for this matchable object.
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
public function get_id();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets the label for this group.
|
25 |
+
*
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
+
public function get_label();
|
29 |
+
}
|
core/modules/user-groups/Matchables_Source.php
ADDED
@@ -0,0 +1,77 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
7 |
+
use iThemesSecurity\User_Groups\Repository\User_Group_Not_Found;
|
8 |
+
|
9 |
+
final class Matchables_Source {
|
10 |
+
|
11 |
+
/** @var Repository */
|
12 |
+
private $repository;
|
13 |
+
|
14 |
+
/** @var Matchable[] */
|
15 |
+
private $additional = [];
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Matchables_Source constructor.
|
19 |
+
*
|
20 |
+
* @param Repository $repository
|
21 |
+
*/
|
22 |
+
public function __construct( Repository $repository ) { $this->repository = $repository; }
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Add a matchable.
|
26 |
+
*
|
27 |
+
* @param Matchable $matchable
|
28 |
+
*
|
29 |
+
* @return $this
|
30 |
+
*/
|
31 |
+
public function add( Matchable $matchable ) {
|
32 |
+
$this->additional[ $matchable->get_id() ] = $matchable;
|
33 |
+
|
34 |
+
return $this;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Find a matchable by its string identifier.
|
39 |
+
*
|
40 |
+
* @param string $id
|
41 |
+
*
|
42 |
+
* @return Matchable
|
43 |
+
*
|
44 |
+
* @throws Matchable_Not_Found
|
45 |
+
*/
|
46 |
+
public function find( $id ) {
|
47 |
+
if ( ! is_string( $id ) ) {
|
48 |
+
throw new Invalid_Argument_Exception( 'Id must be a string.' );
|
49 |
+
}
|
50 |
+
|
51 |
+
try {
|
52 |
+
return isset( $this->additional[ $id ] ) ? $this->additional[ $id ] : $this->repository->get( $id );
|
53 |
+
} catch ( User_Group_Not_Found $e ) {
|
54 |
+
throw new Matchable_Not_Found( $e->getMessage(), $e->getCode(), $e );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Check if the matchables source has a matchable identified by the given id.
|
60 |
+
*
|
61 |
+
* @param string $id
|
62 |
+
*
|
63 |
+
* @return bool
|
64 |
+
*/
|
65 |
+
public function has( $id ) {
|
66 |
+
return isset( $this->additional[ $id ] ) || $this->repository->has( $id );
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get all matchables.
|
71 |
+
*
|
72 |
+
* @return Matchable[]
|
73 |
+
*/
|
74 |
+
public function all() {
|
75 |
+
return array_merge( $this->repository->all(), array_values( $this->additional ) );
|
76 |
+
}
|
77 |
+
}
|
core/modules/user-groups/Module/Module.php
ADDED
@@ -0,0 +1,95 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Module;
|
4 |
+
|
5 |
+
use iThemesSecurity\Contracts\Runnable;
|
6 |
+
use iThemesSecurity\User_Groups\Everybody_Else;
|
7 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
8 |
+
use iThemesSecurity\User_Groups\Settings_Proxy;
|
9 |
+
use iThemesSecurity\User_Groups\Settings_Registry;
|
10 |
+
use iThemesSecurity\User_Groups\User_Group;
|
11 |
+
|
12 |
+
class Module implements Runnable {
|
13 |
+
|
14 |
+
/** @var Repository */
|
15 |
+
private $repository;
|
16 |
+
|
17 |
+
/** @var Settings_Registry */
|
18 |
+
private $settings_registry;
|
19 |
+
|
20 |
+
/** @var Settings_Proxy */
|
21 |
+
private $settings_proxy;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Active constructor.
|
25 |
+
*
|
26 |
+
* @param Repository $repository
|
27 |
+
* @param Settings_Registry $settings_registry
|
28 |
+
* @param Settings_Proxy $settings_proxy
|
29 |
+
*/
|
30 |
+
public function __construct( Repository $repository, Settings_Registry $settings_registry, Settings_Proxy $settings_proxy ) {
|
31 |
+
$this->repository = $repository;
|
32 |
+
$this->settings_registry = $settings_registry;
|
33 |
+
$this->settings_proxy = $settings_proxy;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function run() {
|
37 |
+
add_action( 'itsec_initialized', [ $this, 'trigger_setting_registration' ] );
|
38 |
+
add_filter( 'map_meta_cap', [ $this, 'map_meta_cap' ], 10, 4 );
|
39 |
+
add_action( 'itsec_create_user_group', [ $this, 'initialize_settings' ] );
|
40 |
+
}
|
41 |
+
|
42 |
+
public function trigger_setting_registration() {
|
43 |
+
do_action( 'itsec_register_user_group_settings', $this->settings_registry );
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Map meta capabilities.
|
48 |
+
*
|
49 |
+
* @param string[] $caps
|
50 |
+
* @param string $cap
|
51 |
+
* @param int $user_id
|
52 |
+
* @param array $args
|
53 |
+
*
|
54 |
+
* @return string[]
|
55 |
+
*/
|
56 |
+
public function map_meta_cap( $caps, $cap, $user_id, $args ) {
|
57 |
+
switch ( $cap ) {
|
58 |
+
case 'itsec_list_user_groups':
|
59 |
+
case 'itsec_create_user_groups':
|
60 |
+
case 'itsec_edit_user_groups':
|
61 |
+
return [ \ITSEC_Core::get_required_cap() ];
|
62 |
+
case 'itsec_read_user_group':
|
63 |
+
case 'itsec_edit_user_group':
|
64 |
+
case 'itsec_delete_user_group':
|
65 |
+
if ( empty( $args[0] ) || ! is_string( $args[0] ) || ! $this->repository->has( $args[0] ) ) {
|
66 |
+
return [ 'do_not_allow' ];
|
67 |
+
}
|
68 |
+
|
69 |
+
return [ \ITSEC_Core::get_required_cap() ];
|
70 |
+
default:
|
71 |
+
return $caps;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Initialize a new user group's settings to use the configuration for the Everybody Else group.
|
77 |
+
*
|
78 |
+
* @param User_Group $user_group
|
79 |
+
*/
|
80 |
+
public function initialize_settings( User_Group $user_group ) {
|
81 |
+
if ( \ITSEC_Core::is_importing() ) {
|
82 |
+
// During an import, there is no need to initialize these groups as "new" since we'll
|
83 |
+
// be importing their settings shortly.
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
|
87 |
+
foreach ( $this->settings_registry->get_settings() as $registration ) {
|
88 |
+
$value = $this->settings_proxy->is_enabled( new Everybody_Else( $this->repository ), $registration );
|
89 |
+
|
90 |
+
if ( $value ) {
|
91 |
+
$this->settings_proxy->set_enabled( $user_group, $registration );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
}
|
core/modules/user-groups/Module/Settings.php
ADDED
@@ -0,0 +1,149 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Module;
|
4 |
+
|
5 |
+
use iThemesSecurity\Contracts\Runnable;
|
6 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
7 |
+
use iThemesSecurity\User_Groups\Everybody_Else;
|
8 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
9 |
+
use iThemesSecurity\User_Groups\User_Group;
|
10 |
+
use ITSEC_Settings;
|
11 |
+
|
12 |
+
class Settings extends ITSEC_Settings implements Runnable {
|
13 |
+
/** @var Repository */
|
14 |
+
private $repository;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Settings constructor.
|
18 |
+
*
|
19 |
+
* @param Repository $repository
|
20 |
+
*/
|
21 |
+
public function __construct( Repository $repository ) {
|
22 |
+
$this->repository = $repository;
|
23 |
+
parent::__construct();
|
24 |
+
}
|
25 |
+
|
26 |
+
public function run() {
|
27 |
+
\ITSEC_Modules::register_settings( $this );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function get_id() {
|
31 |
+
return 'user-groups';
|
32 |
+
}
|
33 |
+
|
34 |
+
public function get_defaults() {
|
35 |
+
return [
|
36 |
+
'default_groups' => [],
|
37 |
+
];
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Get the default user group.
|
42 |
+
*
|
43 |
+
* @param string $name The name of the gorup.
|
44 |
+
* @param bool $recreate Whether to recreate the group if it was deleted.
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*
|
48 |
+
* @throws Invalid_Argument_Exception
|
49 |
+
* @throws \iThemesSecurity\Exception\WP_Error
|
50 |
+
*/
|
51 |
+
public function get_default_group_id( $name, $recreate = false ) {
|
52 |
+
if ( ! in_array( $name, \ITSEC_Lib_Canonical_Roles::get_canonical_roles( false ), true ) ) {
|
53 |
+
throw new Invalid_Argument_Exception( sprintf( __( 'No default group called %s', 'better-wp-security' ), $name ) );
|
54 |
+
}
|
55 |
+
|
56 |
+
$defaults = $this->get( 'default_groups' );
|
57 |
+
|
58 |
+
if ( ! isset( $defaults[ $name ] ) ) {
|
59 |
+
$this->create_default_groups();
|
60 |
+
$defaults = $this->get( 'default_groups' );
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( $this->repository->has( $defaults[ $name ] ) ) {
|
64 |
+
return $defaults[ $name ];
|
65 |
+
}
|
66 |
+
|
67 |
+
$prototype = new User_Group( $this->repository->next_id() );
|
68 |
+
$this->configure_group( $prototype, $name );
|
69 |
+
|
70 |
+
foreach ( $this->repository->all() as $group ) {
|
71 |
+
if ( $group->equals( $prototype ) ) {
|
72 |
+
$defaults[ $name ] = $group->get_id();
|
73 |
+
$this->set( 'default_groups', $defaults );
|
74 |
+
|
75 |
+
return $group->get_id();
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
if ( $recreate ) {
|
80 |
+
$this->repository->persist( $prototype );
|
81 |
+
$defaults[ $name ] = $prototype->get_id();
|
82 |
+
|
83 |
+
$this->set( 'default_groups', $defaults );
|
84 |
+
|
85 |
+
return $prototype->get_id();
|
86 |
+
}
|
87 |
+
|
88 |
+
return '';
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get the default canonical groups and the everybody-else group.
|
93 |
+
*
|
94 |
+
* @return string[]
|
95 |
+
*/
|
96 |
+
public function get_groups_for_all_users() {
|
97 |
+
$groups = [];
|
98 |
+
|
99 |
+
foreach ( \ITSEC_Lib_Canonical_Roles::get_canonical_roles( false ) as $canonical ) {
|
100 |
+
if ( $group = $this->get_default_group_id( $canonical ) ) {
|
101 |
+
$groups[] = $group;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
$groups[] = Everybody_Else::ID;
|
106 |
+
|
107 |
+
return $groups;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Create the default user groups.
|
112 |
+
*/
|
113 |
+
private function create_default_groups() {
|
114 |
+
$defaults = $this->get( 'default_groups' );
|
115 |
+
$save = false;
|
116 |
+
|
117 |
+
foreach ( \ITSEC_Lib_Canonical_Roles::get_canonical_roles( false ) as $role ) {
|
118 |
+
if ( ! isset( $defaults[ $role ] ) ) {
|
119 |
+
$group = new User_Group( $this->repository->next_id() );
|
120 |
+
$this->configure_group( $group, $role );
|
121 |
+
$this->repository->persist( $group );
|
122 |
+
$defaults[ $role ] = $group->get_id();
|
123 |
+
|
124 |
+
$save = true;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
if ( $save ) {
|
129 |
+
$this->set( 'default_groups', $defaults );
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Configure a group
|
135 |
+
*
|
136 |
+
* @param User_Group $group
|
137 |
+
* @param string $type
|
138 |
+
*
|
139 |
+
* @return void
|
140 |
+
*/
|
141 |
+
private function configure_group( User_Group $group, $type ) {
|
142 |
+
$group->add_canonical_role( $type );
|
143 |
+
$group->set_label( sprintf( __( '%s Users', 'better-wp-security' ), translate_user_role( ucfirst( $type ) ) ) );
|
144 |
+
|
145 |
+
if ( $type === 'administrator' && is_multisite() ) {
|
146 |
+
$group->add_canonical_role( 'super-admin' );
|
147 |
+
}
|
148 |
+
}
|
149 |
+
}
|
core/modules/user-groups/Module/Validator.php
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Module;
|
4 |
+
|
5 |
+
use iThemesSecurity\Contracts\Runnable;
|
6 |
+
|
7 |
+
class Validator extends \ITSEC_Validator implements Runnable {
|
8 |
+
public function get_id() {
|
9 |
+
return 'user-groups';
|
10 |
+
}
|
11 |
+
|
12 |
+
public function run() {
|
13 |
+
\ITSEC_Modules::register_validator( $this );
|
14 |
+
}
|
15 |
+
|
16 |
+
protected function sanitize_settings() {
|
17 |
+
$this->sanitize_setting( 'user-groups', 'default_groups', __( 'Default Groups', 'better-wp-security' ) );
|
18 |
+
}
|
19 |
+
}
|
core/modules/user-groups/Module/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/REST/Matchables.php
ADDED
@@ -0,0 +1,133 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\REST;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\Matchable;
|
6 |
+
use iThemesSecurity\User_Groups\Matchables_Source;
|
7 |
+
use iThemesSecurity\User_Groups\User_Group;
|
8 |
+
|
9 |
+
class Matchables extends \WP_REST_Controller {
|
10 |
+
|
11 |
+
/** @var Matchables_Source */
|
12 |
+
private $source;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Matchables constructor.
|
16 |
+
*
|
17 |
+
* @param Matchables_Source $source
|
18 |
+
*/
|
19 |
+
public function __construct( Matchables_Source $source ) {
|
20 |
+
$this->source = $source;
|
21 |
+
$this->namespace = 'ithemes-security/v1';
|
22 |
+
$this->rest_base = 'user-matchables';
|
23 |
+
}
|
24 |
+
|
25 |
+
public function register_routes() {
|
26 |
+
register_rest_route( $this->namespace, $this->rest_base, [
|
27 |
+
'methods' => \WP_REST_Server::READABLE,
|
28 |
+
'callback' => [ $this, 'get_items' ],
|
29 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
30 |
+
'schema' => [ $this, 'get_public_item_schema' ],
|
31 |
+
] );
|
32 |
+
}
|
33 |
+
|
34 |
+
public function get_items_permissions_check( $request ) {
|
35 |
+
if ( ! current_user_can( 'itsec_list_user_groups' ) ) {
|
36 |
+
return new \WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to list user matchables.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
37 |
+
}
|
38 |
+
|
39 |
+
return true;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function get_items( $request ) {
|
43 |
+
$data = [];
|
44 |
+
|
45 |
+
foreach ( $this->source->all() as $matchable ) {
|
46 |
+
$data[] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $matchable, $request ) );
|
47 |
+
}
|
48 |
+
|
49 |
+
return new \WP_REST_Response( $data );
|
50 |
+
}
|
51 |
+
|
52 |
+
public function prepare_item_for_response( $item, $request ) {
|
53 |
+
if ( ! $item instanceof Matchable ) {
|
54 |
+
return new \WP_REST_Response();
|
55 |
+
}
|
56 |
+
|
57 |
+
$data = [
|
58 |
+
'id' => $item->get_id(),
|
59 |
+
'label' => $item->get_label(),
|
60 |
+
'type' => $item instanceof User_Group ? 'user-group' : 'meta',
|
61 |
+
];
|
62 |
+
|
63 |
+
$response = new \WP_REST_Response( $data );
|
64 |
+
$response->add_links( $this->prepare_links( $item ) );
|
65 |
+
|
66 |
+
return $response;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Prepare the links for each user group.
|
71 |
+
*
|
72 |
+
* @param Matchable $matchable
|
73 |
+
*
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
public function prepare_links( Matchable $matchable ) {
|
77 |
+
$links = [];
|
78 |
+
|
79 |
+
if ( $matchable instanceof User_Group ) {
|
80 |
+
$links['self'] = [
|
81 |
+
'href' => add_query_arg( 'context', 'view', rest_url( "{$this->namespace}/user-groups/{$matchable->get_id()}" ) ),
|
82 |
+
'embeddable' => true,
|
83 |
+
];
|
84 |
+
}
|
85 |
+
|
86 |
+
$links[ \ITSEC_Lib_REST::get_link_relation( 'user-matchable-settings' ) ] = [
|
87 |
+
'href' => rest_url( "{$this->namespace}/user-matchable-settings/{$matchable->get_id()}" ),
|
88 |
+
'embeddable' => true,
|
89 |
+
];
|
90 |
+
|
91 |
+
return $links;
|
92 |
+
}
|
93 |
+
|
94 |
+
public function get_item_schema() {
|
95 |
+
if ( ! empty( $this->schema ) && ! \ITSEC_Core::is_test_suite( 'wpunit' ) ) {
|
96 |
+
return $this->schema;
|
97 |
+
}
|
98 |
+
|
99 |
+
$schema = [
|
100 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
101 |
+
'title' => 'ithemes-security-user-matchable',
|
102 |
+
'type' => 'object',
|
103 |
+
'properties' => [
|
104 |
+
'id' => [
|
105 |
+
'type' => 'string',
|
106 |
+
],
|
107 |
+
'label' => [
|
108 |
+
'type' => 'string',
|
109 |
+
],
|
110 |
+
],
|
111 |
+
'links' => [
|
112 |
+
[
|
113 |
+
'rel' => 'self',
|
114 |
+
'href' => rest_url( sprintf( '%s/user-groups/{id}', $this->rest_base ) ),
|
115 |
+
'hrefSchema' => [
|
116 |
+
'type' => 'object',
|
117 |
+
'properties' => [
|
118 |
+
'id' => [
|
119 |
+
'type' => 'string',
|
120 |
+
],
|
121 |
+
],
|
122 |
+
]
|
123 |
+
]
|
124 |
+
]
|
125 |
+
];
|
126 |
+
|
127 |
+
if ( isset( $this->schema ) ) {
|
128 |
+
$this->schema = $schema;
|
129 |
+
}
|
130 |
+
|
131 |
+
return $schema;
|
132 |
+
}
|
133 |
+
}
|
core/modules/user-groups/REST/REST.php
ADDED
@@ -0,0 +1,28 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\REST;
|
4 |
+
|
5 |
+
use iThemesSecurity\Contracts\Runnable;
|
6 |
+
|
7 |
+
class REST implements Runnable {
|
8 |
+
|
9 |
+
/** @var \WP_REST_Controller[] */
|
10 |
+
private $controllers;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* REST constructor.
|
14 |
+
*
|
15 |
+
* @param \WP_REST_Controller[] $controllers
|
16 |
+
*/
|
17 |
+
public function __construct( array $controllers ) { $this->controllers = $controllers; }
|
18 |
+
|
19 |
+
public function run() {
|
20 |
+
add_action( 'rest_api_init', [ $this, 'register_routes' ] );
|
21 |
+
}
|
22 |
+
|
23 |
+
public function register_routes() {
|
24 |
+
foreach ( $this->controllers as $controller ) {
|
25 |
+
$controller->register_routes();
|
26 |
+
}
|
27 |
+
}
|
28 |
+
}
|
core/modules/user-groups/REST/Settings.php
ADDED
@@ -0,0 +1,355 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\REST;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\Matchable;
|
6 |
+
use iThemesSecurity\User_Groups\Matchables_Source;
|
7 |
+
use iThemesSecurity\User_Groups\Settings_Proxy;
|
8 |
+
use iThemesSecurity\User_Groups\Settings_Registration;
|
9 |
+
use iThemesSecurity\User_Groups\Settings_Registry;
|
10 |
+
use iThemesSecurity\User_Groups\Repository\User_Group_Not_Found;
|
11 |
+
|
12 |
+
class Settings extends \WP_REST_Controller {
|
13 |
+
|
14 |
+
/** @var Matchables_Source */
|
15 |
+
private $source;
|
16 |
+
|
17 |
+
/** @var Settings_Registry */
|
18 |
+
private $settings_registry;
|
19 |
+
|
20 |
+
/** @var Settings_Proxy */
|
21 |
+
private $proxy;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* REST constructor.
|
25 |
+
*
|
26 |
+
* @param Matchables_Source $source
|
27 |
+
* @param Settings_Registry $settings_registry
|
28 |
+
* @param Settings_Proxy $proxy
|
29 |
+
*/
|
30 |
+
public function __construct( Matchables_Source $source, Settings_Registry $settings_registry, Settings_Proxy $proxy ) {
|
31 |
+
$this->source = $source;
|
32 |
+
$this->settings_registry = $settings_registry;
|
33 |
+
$this->proxy = $proxy;
|
34 |
+
$this->namespace = 'ithemes-security/v1';
|
35 |
+
$this->rest_base = 'user-matchable-settings';
|
36 |
+
}
|
37 |
+
|
38 |
+
public function register_routes() {
|
39 |
+
register_rest_route( $this->namespace, $this->rest_base, [
|
40 |
+
[
|
41 |
+
'methods' => \WP_REST_Server::READABLE,
|
42 |
+
'callback' => [ $this, 'get_items' ],
|
43 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
44 |
+
'args' => $this->get_collection_params(),
|
45 |
+
],
|
46 |
+
[
|
47 |
+
'methods' => 'PATCH',
|
48 |
+
'callback' => [ $this, 'patch_items' ],
|
49 |
+
'permission_callback' => [ $this, 'patch_items_permissions_check' ],
|
50 |
+
'args' => array_merge(
|
51 |
+
$this->get_endpoint_args_for_item_schema( 'PATCH' ),
|
52 |
+
$this->get_collection_params()
|
53 |
+
),
|
54 |
+
],
|
55 |
+
'schema' => [ $this, 'get_public_item_schema' ],
|
56 |
+
] );
|
57 |
+
|
58 |
+
register_rest_route( $this->namespace, $this->rest_base . '/(?P<id>.*)', [
|
59 |
+
[
|
60 |
+
'methods' => \WP_REST_Server::READABLE,
|
61 |
+
'callback' => [ $this, 'get_item' ],
|
62 |
+
'permission_callback' => [ $this, 'get_item_permissions_check' ],
|
63 |
+
'args' => [
|
64 |
+
'context' => $this->get_context_param( [ 'default' => 'view' ] ),
|
65 |
+
],
|
66 |
+
],
|
67 |
+
[
|
68 |
+
'methods' => 'PUT',
|
69 |
+
'callback' => [ $this, 'update_item' ],
|
70 |
+
'permission_callback' => [ $this, 'update_item_permissions_check' ],
|
71 |
+
'args' => $this->get_endpoint_args_for_item_schema( 'PUT' ),
|
72 |
+
],
|
73 |
+
'schema' => [ $this, 'get_public_item_schema' ],
|
74 |
+
'args' => [
|
75 |
+
'id' => [
|
76 |
+
'type' => 'string',
|
77 |
+
],
|
78 |
+
],
|
79 |
+
'show_in_index' => false,
|
80 |
+
] );
|
81 |
+
}
|
82 |
+
|
83 |
+
public function get_items_permissions_check( $request ) {
|
84 |
+
return \ITSEC_Core::current_user_can_manage();
|
85 |
+
}
|
86 |
+
|
87 |
+
public function get_items( $request ) {
|
88 |
+
$matchables = $this->source->all();
|
89 |
+
$return = [];
|
90 |
+
|
91 |
+
foreach ( $matchables as $matchable ) {
|
92 |
+
$return[ $matchable->get_id() ] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $matchable, $request ) );
|
93 |
+
}
|
94 |
+
|
95 |
+
return new \WP_REST_Response( $return );
|
96 |
+
}
|
97 |
+
|
98 |
+
public function get_item_permissions_check( $request ) {
|
99 |
+
return $this->update_item_permissions_check( $request );
|
100 |
+
}
|
101 |
+
|
102 |
+
public function get_item( $request ) {
|
103 |
+
try {
|
104 |
+
return $this->prepare_item_for_response( $this->source->find( $request['id'] ), $request );
|
105 |
+
} catch ( User_Group_Not_Found $e ) {
|
106 |
+
return new \WP_Error( 'rest_user_group_not_found', $e->getMessage(), [ 'status' => \WP_Http::NOT_FOUND ] );
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
public function update_item_permissions_check( $request ) {
|
111 |
+
if ( ! \ITSEC_Core::current_user_can_manage() ) {
|
112 |
+
return false;
|
113 |
+
}
|
114 |
+
|
115 |
+
if ( ! $this->source->has( $request['id'] ) ) {
|
116 |
+
return new \WP_Error( 'rest_user_group_not_found', __( 'No user group found.', 'better-wp-security' ), [ 'status' => \WP_Http::NOT_FOUND ] );
|
117 |
+
}
|
118 |
+
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
|
122 |
+
public function update_item( $request ) {
|
123 |
+
\ITSEC_Core::set_interactive();
|
124 |
+
|
125 |
+
try {
|
126 |
+
$matchable = $this->source->find( $request['id'] );
|
127 |
+
$maybe_error = $this->update_matchable_for_request( $matchable, $request );
|
128 |
+
|
129 |
+
if ( is_wp_error( $maybe_error ) ) {
|
130 |
+
return $maybe_error;
|
131 |
+
}
|
132 |
+
|
133 |
+
$request['context'] = 'edit';
|
134 |
+
|
135 |
+
return $this->prepare_item_for_response( $matchable, $request );
|
136 |
+
} catch ( User_Group_Not_Found $e ) {
|
137 |
+
return new \WP_Error( 'rest_user_group_not_found', $e->getMessage(), [ 'status' => \WP_Http::NOT_FOUND ] );
|
138 |
+
} catch ( \Exception $e ) {
|
139 |
+
return new \WP_Error( 'internal_server_error', __( 'An unexpected error occurred.', 'better-wp-security' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Patch items.
|
145 |
+
*
|
146 |
+
* @param \WP_REST_Request $request
|
147 |
+
*
|
148 |
+
* @return \WP_REST_Response
|
149 |
+
*/
|
150 |
+
public function patch_items( \WP_REST_Request $request ) {
|
151 |
+
\ITSEC_Core::set_interactive();
|
152 |
+
|
153 |
+
$request['context'] = 'edit';
|
154 |
+
|
155 |
+
$return = [];
|
156 |
+
|
157 |
+
if ( isset( $request['include'] ) ) {
|
158 |
+
$matchables = $request['include'];
|
159 |
+
} else {
|
160 |
+
$matchables = $this->source->all();
|
161 |
+
}
|
162 |
+
|
163 |
+
foreach ( $matchables as $matchable ) {
|
164 |
+
if ( $matchable instanceof Matchable ) {
|
165 |
+
$id = $matchable->get_id();
|
166 |
+
} else {
|
167 |
+
$id = $matchable;
|
168 |
+
}
|
169 |
+
|
170 |
+
$href = rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $id ) );
|
171 |
+
|
172 |
+
try {
|
173 |
+
if ( ! $matchable instanceof Matchable ) {
|
174 |
+
$matchable = $this->source->find( $id );
|
175 |
+
}
|
176 |
+
|
177 |
+
$maybe_error = $this->update_matchable_for_request( $matchable, $request );
|
178 |
+
|
179 |
+
if ( is_wp_error( $maybe_error ) ) {
|
180 |
+
$return[] = [
|
181 |
+
'href' => $href,
|
182 |
+
'status' => \WP_Http::BAD_REQUEST,
|
183 |
+
'error' => rest_get_server()->response_to_data( \ITSEC_Lib_REST::error_to_response( $maybe_error ), false ),
|
184 |
+
];
|
185 |
+
|
186 |
+
continue;
|
187 |
+
}
|
188 |
+
|
189 |
+
$return[] = [
|
190 |
+
'href' => $href,
|
191 |
+
'status' => \WP_Http::OK,
|
192 |
+
'response' => $this->prepare_response_for_collection( $this->prepare_item_for_response( $matchable, $request ) ),
|
193 |
+
];
|
194 |
+
} catch ( User_Group_Not_Found $e ) {
|
195 |
+
$return[] = [
|
196 |
+
'href' => $href,
|
197 |
+
'status' => \WP_Http::NOT_FOUND,
|
198 |
+
'error' => rest_get_server()->response_to_data( \ITSEC_Lib_REST::error_to_response(
|
199 |
+
new \WP_Error( 'rest_user_group_not_found', $e->getMessage(), [ 'status' => \WP_Http::NOT_FOUND ] )
|
200 |
+
), false ),
|
201 |
+
];
|
202 |
+
} catch ( \Exception $e ) {
|
203 |
+
$return[] = [
|
204 |
+
'href' => $href,
|
205 |
+
'status' => \WP_Http::NOT_FOUND,
|
206 |
+
'error' => rest_get_server()->response_to_data( \ITSEC_Lib_REST::error_to_response(
|
207 |
+
new \WP_Error( 'internal_server_error', __( 'An unexpected error occurred.', 'better-wp-security' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] )
|
208 |
+
), false ),
|
209 |
+
];
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
return new \WP_REST_Response( $return, 207 );
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Check if the user has permissions to perform a patch.
|
218 |
+
*
|
219 |
+
* @param \WP_REST_Request $request
|
220 |
+
*
|
221 |
+
* @return bool
|
222 |
+
*/
|
223 |
+
public function patch_items_permissions_check( $request ) {
|
224 |
+
return \ITSEC_Core::current_user_can_manage();
|
225 |
+
}
|
226 |
+
|
227 |
+
public function prepare_item_for_response( $item, $request ) {
|
228 |
+
$schema = $this->get_item_schema();
|
229 |
+
$data = [];
|
230 |
+
|
231 |
+
if ( ! $item instanceof Matchable ) {
|
232 |
+
return new \WP_REST_Response( $data );
|
233 |
+
}
|
234 |
+
|
235 |
+
foreach ( $this->settings_registry->get_settings() as $registration ) {
|
236 |
+
if ( ! isset( $schema['properties'][ $registration->get_module() ]['properties'][ $registration->get_setting() ] ) ) {
|
237 |
+
continue;
|
238 |
+
}
|
239 |
+
|
240 |
+
$data[ $registration->get_module() ][ $registration->get_setting() ] = $this->proxy->is_enabled( $item, $registration );
|
241 |
+
}
|
242 |
+
|
243 |
+
$data = $this->filter_response_by_context( $data, $request['context'] );
|
244 |
+
|
245 |
+
return new \WP_REST_Response( $data );
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Update a matchable based on the request data.
|
250 |
+
*
|
251 |
+
* @param Matchable $matchable
|
252 |
+
* @param \WP_REST_Request $request
|
253 |
+
*
|
254 |
+
* @return \WP_Error|null
|
255 |
+
*/
|
256 |
+
protected function update_matchable_for_request( Matchable $matchable, \WP_REST_Request $request ) {
|
257 |
+
$schema = $this->get_item_schema();
|
258 |
+
|
259 |
+
foreach ( $this->settings_registry->get_settings() as $registration ) {
|
260 |
+
if ( ! isset( $request[ $registration->get_module() ][ $registration->get_setting() ] ) ) {
|
261 |
+
continue;
|
262 |
+
}
|
263 |
+
|
264 |
+
if ( ! isset( $schema['properties'][ $registration->get_module() ]['properties'][ $registration->get_setting() ] ) ) {
|
265 |
+
continue;
|
266 |
+
}
|
267 |
+
|
268 |
+
$enabled = $request[ $registration->get_module() ][ $registration->get_setting() ];
|
269 |
+
$updated = $this->proxy->set_enabled( $matchable, $registration, $enabled );
|
270 |
+
|
271 |
+
if ( is_wp_error( $updated ) ) {
|
272 |
+
return $updated;
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
return null;
|
277 |
+
}
|
278 |
+
|
279 |
+
public function get_item_schema() {
|
280 |
+
if ( ! empty( $this->schema ) && ! \ITSEC_Core::is_test_suite( 'wpunit' ) ) {
|
281 |
+
return $this->schema;
|
282 |
+
}
|
283 |
+
|
284 |
+
$schema = [
|
285 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
286 |
+
'title' => 'ithemes-security-user-group-settings',
|
287 |
+
'type' => 'object',
|
288 |
+
'properties' => [],
|
289 |
+
'additionalProperties' => false,
|
290 |
+
'links' => [
|
291 |
+
[
|
292 |
+
'rel' => 'self',
|
293 |
+
'href' => rest_url( sprintf( '%s/%s/{id}', $this->namespace, $this->rest_base ) ),
|
294 |
+
'hrefSchema' => [
|
295 |
+
'type' => 'object',
|
296 |
+
'properties' => [
|
297 |
+
'id' => [
|
298 |
+
'type' => 'string',
|
299 |
+
],
|
300 |
+
],
|
301 |
+
]
|
302 |
+
]
|
303 |
+
],
|
304 |
+
];
|
305 |
+
|
306 |
+
foreach ( $this->settings_registry->get_settings() as $registration ) {
|
307 |
+
if ( Settings_Registration::T_MULTIPLE !== $registration->get_type() ) {
|
308 |
+
continue;
|
309 |
+
}
|
310 |
+
|
311 |
+
$title = $registration->get_module();
|
312 |
+
|
313 |
+
if ( $labels = \ITSEC_Modules::get_labels( $registration->get_module() ) ) {
|
314 |
+
$title = $labels['title'];
|
315 |
+
}
|
316 |
+
|
317 |
+
if ( ! isset( $schema['properties'][ $registration->get_module() ] ) ) {
|
318 |
+
$schema['properties'][ $registration->get_module() ] = [
|
319 |
+
'title' => $title,
|
320 |
+
'type' => 'object',
|
321 |
+
'properties' => [],
|
322 |
+
'context' => [ 'view', 'edit', 'embed' ],
|
323 |
+
'additionalProperties' => false,
|
324 |
+
];
|
325 |
+
}
|
326 |
+
|
327 |
+
$labels = $registration->get_labels();
|
328 |
+
|
329 |
+
$schema['properties'][ $registration->get_module() ]['properties'][ $registration->get_setting() ] = [
|
330 |
+
'title' => isset( $labels['title'] ) ? $labels['title'] : '',
|
331 |
+
'description' => isset( $labels['description'] ) ? $labels['description'] : '',
|
332 |
+
'type' => 'boolean',
|
333 |
+
'context' => [ 'view', 'edit', 'embed' ],
|
334 |
+
];
|
335 |
+
}
|
336 |
+
|
337 |
+
if ( isset( $this->schema ) ) {
|
338 |
+
$this->schema = $schema;
|
339 |
+
}
|
340 |
+
|
341 |
+
return $schema;
|
342 |
+
}
|
343 |
+
|
344 |
+
public function get_collection_params() {
|
345 |
+
return [
|
346 |
+
'context' => $this->get_context_param( [ 'default' => 'view' ] ),
|
347 |
+
'include' => [
|
348 |
+
'type' => 'array',
|
349 |
+
'items' => [
|
350 |
+
'type' => 'string',
|
351 |
+
],
|
352 |
+
],
|
353 |
+
];
|
354 |
+
}
|
355 |
+
}
|
core/modules/user-groups/REST/User_Groups.php
ADDED
@@ -0,0 +1,467 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\REST;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
6 |
+
use iThemesSecurity\User_Groups\User_Group;
|
7 |
+
use iThemesSecurity\User_Groups\Repository\User_Group_Not_Found;
|
8 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
9 |
+
use iThemesSecurity\Exception\WP_Error;
|
10 |
+
|
11 |
+
class User_Groups extends \WP_REST_Controller {
|
12 |
+
|
13 |
+
const ID_PATTERN = '(?P<id>[\\w_:-]+)';
|
14 |
+
|
15 |
+
/** @var \iThemesSecurity\User_Groups\Repository\Repository */
|
16 |
+
private $repository;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* REST constructor.
|
20 |
+
*
|
21 |
+
* @param \iThemesSecurity\User_Groups\Repository\Repository $repository
|
22 |
+
*/
|
23 |
+
public function __construct( Repository $repository ) {
|
24 |
+
$this->repository = $repository;
|
25 |
+
$this->namespace = 'ithemes-security/v1';
|
26 |
+
$this->rest_base = 'user-groups';
|
27 |
+
}
|
28 |
+
|
29 |
+
public function register_routes() {
|
30 |
+
register_rest_route( $this->namespace, $this->rest_base, [
|
31 |
+
[
|
32 |
+
'methods' => \WP_REST_Server::READABLE,
|
33 |
+
'callback' => [ $this, 'get_items' ],
|
34 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
35 |
+
'args' => $this->get_collection_params(),
|
36 |
+
],
|
37 |
+
[
|
38 |
+
'methods' => \WP_REST_Server::CREATABLE,
|
39 |
+
'callback' => [ $this, 'create_item' ],
|
40 |
+
'permission_callback' => [ $this, 'create_item_permissions_check' ],
|
41 |
+
'args' => array_merge( $this->get_endpoint_args_for_item_schema(), [
|
42 |
+
'ignore_duplicate' => [
|
43 |
+
'type' => 'boolean',
|
44 |
+
],
|
45 |
+
] ),
|
46 |
+
],
|
47 |
+
'schema' => [ $this, 'get_public_item_schema' ],
|
48 |
+
] );
|
49 |
+
|
50 |
+
register_rest_route( $this->namespace, $this->rest_base . '/' . self::ID_PATTERN, [
|
51 |
+
[
|
52 |
+
'methods' => \WP_REST_Server::READABLE,
|
53 |
+
'callback' => [ $this, 'get_item' ],
|
54 |
+
'permission_callback' => [ $this, 'get_item_permissions_check' ],
|
55 |
+
'args' => [
|
56 |
+
'context' => $this->get_context_param( [ 'default' => 'view' ] ),
|
57 |
+
],
|
58 |
+
],
|
59 |
+
[
|
60 |
+
'methods' => 'PUT',
|
61 |
+
'callback' => [ $this, 'update_item' ],
|
62 |
+
'permission_callback' => [ $this, 'update_item_permissions_check' ],
|
63 |
+
'args' => $this->get_endpoint_args_for_item_schema( 'PUT' ),
|
64 |
+
],
|
65 |
+
[
|
66 |
+
'methods' => 'DELETE',
|
67 |
+
'callback' => [ $this, 'delete_item' ],
|
68 |
+
'permission_callback' => [ $this, 'delete_item_permissions_check' ],
|
69 |
+
],
|
70 |
+
'schema' => [ $this, 'get_public_item_schema' ],
|
71 |
+
'args' => [
|
72 |
+
'id' => [
|
73 |
+
'type' => 'string',
|
74 |
+
],
|
75 |
+
],
|
76 |
+
] );
|
77 |
+
}
|
78 |
+
|
79 |
+
public function get_items_permissions_check( $request ) {
|
80 |
+
if ( 'edit' === $request['context'] && ! current_user_can( 'itsec_edit_user_groups' ) ) {
|
81 |
+
return new \WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit user groups.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
82 |
+
}
|
83 |
+
|
84 |
+
if ( ! current_user_can( 'itsec_list_user_groups' ) ) {
|
85 |
+
return new \WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to list user groups.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
86 |
+
}
|
87 |
+
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
|
91 |
+
public function get_items( $request ) {
|
92 |
+
$data = [];
|
93 |
+
|
94 |
+
foreach ( $this->repository->all() as $user_group ) {
|
95 |
+
$data[] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $user_group, $request ) );
|
96 |
+
}
|
97 |
+
|
98 |
+
return new \WP_REST_Response( $data );
|
99 |
+
}
|
100 |
+
|
101 |
+
public function get_item_permissions_check( $request ) {
|
102 |
+
if ( true !== ( $error = $this->check_group_exists( $request ) ) ) {
|
103 |
+
return $error;
|
104 |
+
}
|
105 |
+
|
106 |
+
if ( 'edit' === $request['context'] && ! current_user_can( 'itsec_edit_user_group', $request['id'] ) ) {
|
107 |
+
return new \WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this user group.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
108 |
+
}
|
109 |
+
|
110 |
+
if ( ! current_user_can( 'itsec_read_user_group', $request['id'] ) ) {
|
111 |
+
return new \WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to view this user group.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
112 |
+
}
|
113 |
+
|
114 |
+
return true;
|
115 |
+
}
|
116 |
+
|
117 |
+
public function get_item( $request ) {
|
118 |
+
try {
|
119 |
+
return $this->prepare_item_for_response( $this->repository->get( $request['id'] ), $request );
|
120 |
+
} catch ( User_Group_Not_Found $e ) {
|
121 |
+
return new \WP_Error( 'rest_user_group_not_found', $e->getMessage(), [ 'status' => \WP_Http::NOT_FOUND ] );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
public function create_item_permissions_check( $request ) {
|
126 |
+
if ( ! current_user_can( 'itsec_create_user_groups' ) ) {
|
127 |
+
return new \WP_Error( 'rest_cannot_create', __( 'Sorry, you are not allowed to create user groups.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
128 |
+
}
|
129 |
+
|
130 |
+
return true;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function create_item( $request ) {
|
134 |
+
try {
|
135 |
+
$user_group = $this->prepare_item_for_database( $request );
|
136 |
+
|
137 |
+
if ( is_wp_error( $user_group ) ) {
|
138 |
+
return $user_group;
|
139 |
+
}
|
140 |
+
|
141 |
+
if ( ! $request['ignore_duplicate'] && $response = $this->handle_duplicate_check( $user_group ) ) {
|
142 |
+
return $response;
|
143 |
+
}
|
144 |
+
|
145 |
+
$this->repository->persist( $user_group );
|
146 |
+
$request['context'] = 'edit';
|
147 |
+
|
148 |
+
$response = $this->prepare_item_for_response( $user_group, $request );
|
149 |
+
$response->set_status( \WP_Http::CREATED );
|
150 |
+
$response->header( 'Location', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $user_group->get_id() ) ) );
|
151 |
+
|
152 |
+
return $response;
|
153 |
+
} catch ( \Exception $e ) {
|
154 |
+
return new \WP_Error( 'internal_server_error', __( 'An unexpected error occurred.', 'better-wp-security' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] );
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
public function update_item_permissions_check( $request ) {
|
159 |
+
if ( true !== ( $error = $this->check_group_exists( $request ) ) ) {
|
160 |
+
return $error;
|
161 |
+
}
|
162 |
+
|
163 |
+
if ( ! current_user_can( 'itsec_edit_user_group', $request['id'] ) ) {
|
164 |
+
return new \WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user group.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
165 |
+
}
|
166 |
+
|
167 |
+
return true;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Handle checking for duplicate user groups.
|
172 |
+
*
|
173 |
+
* @param User_Group $user_group
|
174 |
+
*
|
175 |
+
* @return \WP_REST_Response|null
|
176 |
+
*/
|
177 |
+
private function handle_duplicate_check( User_Group $user_group ) {
|
178 |
+
/** @var User_Group[] $duplicates */
|
179 |
+
$duplicates = array_filter( $this->repository->all(), static function ( User_Group $maybe_group ) use ( $user_group ) {
|
180 |
+
return $user_group->equals( $maybe_group );
|
181 |
+
} );
|
182 |
+
|
183 |
+
if ( ! $duplicates ) {
|
184 |
+
return null;
|
185 |
+
}
|
186 |
+
|
187 |
+
\ITSEC_Lib::load( 'rest' );
|
188 |
+
$error = new \WP_Error( 'rest_duplicate_user_group', __( 'Another user group with this configuration already exists.', 'better-wp-security' ), [ 'status' => \WP_Http::BAD_REQUEST ] );
|
189 |
+
$response = \ITSEC_Lib_REST::error_to_response( $error );
|
190 |
+
|
191 |
+
foreach ( $duplicates as $duplicate ) {
|
192 |
+
$response->add_link( 'duplicate', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $duplicate->get_id() ) ) );
|
193 |
+
}
|
194 |
+
|
195 |
+
return $response;
|
196 |
+
}
|
197 |
+
|
198 |
+
public function update_item( $request ) {
|
199 |
+
try {
|
200 |
+
$user_group = $this->prepare_item_for_database( $request );
|
201 |
+
|
202 |
+
if ( is_wp_error( $user_group ) ) {
|
203 |
+
return $user_group;
|
204 |
+
}
|
205 |
+
|
206 |
+
$this->repository->persist( $user_group );
|
207 |
+
$request['context'] = 'edit';
|
208 |
+
|
209 |
+
return $this->prepare_item_for_response( $user_group, $request );
|
210 |
+
} catch ( WP_Error $e ) {
|
211 |
+
return $e->get_error();
|
212 |
+
} catch ( \Exception $e ) {
|
213 |
+
return new \WP_Error( 'internal_server_error', __( 'An unexpected error occurred.', 'better-wp-security' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] );
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
public function delete_item_permissions_check( $request ) {
|
218 |
+
if ( true !== ( $error = $this->check_group_exists( $request ) ) ) {
|
219 |
+
return $error;
|
220 |
+
}
|
221 |
+
|
222 |
+
if ( ! current_user_can( 'itsec_delete_user_group', $request['id'] ) ) {
|
223 |
+
return new \WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this user group.', 'better-wp-security' ), [ 'status' => rest_authorization_required_code() ] );
|
224 |
+
}
|
225 |
+
|
226 |
+
return true;
|
227 |
+
}
|
228 |
+
|
229 |
+
public function delete_item( $request ) {
|
230 |
+
try {
|
231 |
+
$user_group = $this->repository->get( $request['id'] );
|
232 |
+
$this->repository->delete( $user_group );
|
233 |
+
|
234 |
+
return new \WP_REST_Response( null, \WP_Http::NO_CONTENT );
|
235 |
+
} catch ( User_Group_Not_Found $e ) {
|
236 |
+
return new \WP_Error( 'rest_user_group_not_found', $e->getMessage(), [ 'status' => \WP_Http::NOT_FOUND ] );
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
protected function prepare_item_for_database( $request ) {
|
241 |
+
try {
|
242 |
+
if ( isset( $request->get_url_params()['id'] ) ) {
|
243 |
+
$user_group = $this->repository->get( $request->get_url_params()['id'] );
|
244 |
+
} elseif ( isset( $request['id'] ) ) {
|
245 |
+
if ( $this->repository->has( $request['id'] ) ) {
|
246 |
+
throw WP_Error::from_code(
|
247 |
+
'rest_duplicate_user_group_id',
|
248 |
+
sprintf( __( 'A user group already exists with the id \'%s\'.', 'better-wp-security' ), $request['id'] ),
|
249 |
+
[ 'status' => \WP_Http::BAD_REQUEST ]
|
250 |
+
);
|
251 |
+
}
|
252 |
+
|
253 |
+
$user_group = new User_Group( $request['id'] );
|
254 |
+
} else {
|
255 |
+
$user_group = new User_Group( $this->repository->next_id() );
|
256 |
+
}
|
257 |
+
|
258 |
+
if ( isset( $request['users'] ) ) {
|
259 |
+
$user_group->set_users( array_map( static function ( $id ) {
|
260 |
+
if ( ! $user = get_userdata( $id ) ) {
|
261 |
+
throw WP_Error::from_code( 'rest_user_not_found', sprintf( __( 'No user found for %d.', 'better-wp-security' ), $id ), [ 'status' => \WP_Http::BAD_REQUEST ] );
|
262 |
+
}
|
263 |
+
|
264 |
+
return $user;
|
265 |
+
}, $request['users'] ) );
|
266 |
+
}
|
267 |
+
|
268 |
+
if ( isset( $request['roles'] ) ) {
|
269 |
+
$user_group->set_roles( $request['roles'] );
|
270 |
+
}
|
271 |
+
|
272 |
+
if ( isset( $request['canonical'] ) ) {
|
273 |
+
$user_group->set_canonical_roles( $request['canonical'] );
|
274 |
+
}
|
275 |
+
|
276 |
+
if ( isset( $request['min_role'] ) ) {
|
277 |
+
$user_group->set_min_role( $request['min_role'] );
|
278 |
+
}
|
279 |
+
|
280 |
+
if ( isset( $request['label'] ) ) {
|
281 |
+
$user_group->set_label( $request['label'] );
|
282 |
+
}
|
283 |
+
} catch ( WP_Error $e ) {
|
284 |
+
return $e->get_error();
|
285 |
+
} catch ( Invalid_Argument_Exception $e ) {
|
286 |
+
return new \WP_Error( 'rest_invalid_param', $e->getMessage(), [ 'status' => \WP_Http::BAD_REQUEST ] );
|
287 |
+
} catch ( \Exception $e ) {
|
288 |
+
return new \WP_Error( 'internal_server_error', __( 'An unexpected error occurred.', 'better-wp-security' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] );
|
289 |
+
}
|
290 |
+
|
291 |
+
if ( ! $user_group->is_configured() ) {
|
292 |
+
return new \WP_Error(
|
293 |
+
'rest_user_group_not_configured',
|
294 |
+
__( 'A user group must have a minimum role, list of roles, or list of users to be created.' ),
|
295 |
+
[ 'status' => \WP_Http::BAD_REQUEST ]
|
296 |
+
);
|
297 |
+
}
|
298 |
+
|
299 |
+
return $user_group;
|
300 |
+
}
|
301 |
+
|
302 |
+
public function prepare_item_for_response( $item, $request ) {
|
303 |
+
if ( ! $item instanceof User_Group ) {
|
304 |
+
return new \WP_REST_Response();
|
305 |
+
}
|
306 |
+
|
307 |
+
$fields = $this->get_fields_for_response( $request );
|
308 |
+
$data = [
|
309 |
+
'id' => $item->get_id(),
|
310 |
+
];
|
311 |
+
|
312 |
+
if ( in_array( 'label', $fields, true ) ) {
|
313 |
+
$data['label'] = $item->get_label();
|
314 |
+
}
|
315 |
+
|
316 |
+
if ( in_array( 'description', $fields, true ) ) {
|
317 |
+
$data['description'] = $item->get_description();
|
318 |
+
}
|
319 |
+
|
320 |
+
if ( in_array( 'users', $fields, true ) ) {
|
321 |
+
$data['users'] = wp_list_pluck( $item->get_users(), 'ID' );
|
322 |
+
}
|
323 |
+
|
324 |
+
if ( in_array( 'roles', $fields, true ) ) {
|
325 |
+
$data['roles'] = $item->get_roles();
|
326 |
+
}
|
327 |
+
|
328 |
+
if ( in_array( 'canonical', $fields, true ) ) {
|
329 |
+
$data['canonical'] = $item->get_canonical_roles();
|
330 |
+
}
|
331 |
+
|
332 |
+
if ( in_array( 'min_role', $fields, true ) ) {
|
333 |
+
$data['min_role'] = $item->get_min_role();
|
334 |
+
}
|
335 |
+
|
336 |
+
$response = new \WP_REST_Response( $data );
|
337 |
+
$response->add_links( $this->prepare_links( $item ) );
|
338 |
+
|
339 |
+
return $response;
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Check that a user group exists.
|
344 |
+
*
|
345 |
+
* @param \WP_REST_Request $request
|
346 |
+
*
|
347 |
+
* @return bool|\WP_Error
|
348 |
+
*/
|
349 |
+
protected function check_group_exists( \WP_REST_Request $request ) {
|
350 |
+
if ( $this->repository->has( $request['id'] ) ) {
|
351 |
+
return true;
|
352 |
+
}
|
353 |
+
|
354 |
+
return new \WP_Error( 'rest_not_found', __( 'Sorry, no user group exists with that id.', 'better-wp-security' ), [ 'status' => \WP_Http::NOT_FOUND ] );
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Prepare the links for each user group.
|
359 |
+
*
|
360 |
+
* @param User_Group $user_group
|
361 |
+
*
|
362 |
+
* @return array
|
363 |
+
*/
|
364 |
+
public function prepare_links( User_Group $user_group ) {
|
365 |
+
$links = [
|
366 |
+
'self' => [
|
367 |
+
'href' => rest_url( "{$this->namespace}/{$this->rest_base}/{$user_group->get_id()}" ),
|
368 |
+
],
|
369 |
+
|
370 |
+
\ITSEC_Lib_REST::get_link_relation( 'user-matchable-settings' ) => [
|
371 |
+
'href' => rest_url( "{$this->namespace}/user-matchable-settings/{$user_group->get_id()}" ),
|
372 |
+
'embeddable' => true,
|
373 |
+
],
|
374 |
+
];
|
375 |
+
|
376 |
+
foreach ( $user_group->get_users() as $user ) {
|
377 |
+
$links[ \ITSEC_Lib_REST::get_link_relation( 'user-group-member' ) ][] = [
|
378 |
+
'href' => rest_url( "wp/v2/users/{$user->ID}" ),
|
379 |
+
'embeddable' => true
|
380 |
+
];
|
381 |
+
}
|
382 |
+
|
383 |
+
return $links;
|
384 |
+
}
|
385 |
+
|
386 |
+
public function get_item_schema() {
|
387 |
+
if ( ! empty( $this->schema ) && ! \ITSEC_Core::is_test_suite( 'wpunit' ) ) {
|
388 |
+
return $this->schema;
|
389 |
+
}
|
390 |
+
|
391 |
+
$schema = [
|
392 |
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
393 |
+
'title' => 'ithemes-security-user-group',
|
394 |
+
'type' => 'object',
|
395 |
+
'properties' => [
|
396 |
+
'id' => [
|
397 |
+
'type' => 'string',
|
398 |
+
'readonly' => true,
|
399 |
+
'context' => [ 'view', 'edit', 'embed' ],
|
400 |
+
],
|
401 |
+
'label' => [
|
402 |
+
'type' => 'string',
|
403 |
+
'minLength' => 1,
|
404 |
+
'required' => true,
|
405 |
+
'context' => [ 'view', 'edit', 'embed' ],
|
406 |
+
],
|
407 |
+
'description' => [
|
408 |
+
'type' => 'string',
|
409 |
+
'readonly' => true,
|
410 |
+
'context' => [ 'view', 'edit', 'embed' ],
|
411 |
+
],
|
412 |
+
'users' => [
|
413 |
+
'type' => 'array',
|
414 |
+
'items' => [
|
415 |
+
'type' => 'integer',
|
416 |
+
'minimum' => 0,
|
417 |
+
],
|
418 |
+
'uniqueItems' => true,
|
419 |
+
'context' => [ 'view', 'edit' ],
|
420 |
+
],
|
421 |
+
'roles' => [
|
422 |
+
'type' => 'array',
|
423 |
+
'items' => [
|
424 |
+
'type' => 'string',
|
425 |
+
'enum' => array_keys( wp_roles()->get_names() ),
|
426 |
+
],
|
427 |
+
'context' => [ 'view', 'edit' ],
|
428 |
+
],
|
429 |
+
'canonical' => [
|
430 |
+
'type' => 'array',
|
431 |
+
'items' => [
|
432 |
+
'type' => 'string',
|
433 |
+
'enum' => \ITSEC_Lib_Canonical_Roles::get_canonical_roles( is_multisite() ),
|
434 |
+
],
|
435 |
+
'arg_options' => [
|
436 |
+
'validate_callback' => static function ( $value ) {
|
437 |
+
return rest_validate_value_from_schema( $value, [
|
438 |
+
'type' => 'array',
|
439 |
+
'items' => [
|
440 |
+
'type' => 'string',
|
441 |
+
'enum' => \ITSEC_Lib_Canonical_Roles::get_canonical_roles(),
|
442 |
+
],
|
443 |
+
] );
|
444 |
+
},
|
445 |
+
],
|
446 |
+
],
|
447 |
+
'min_role' => [
|
448 |
+
'type' => 'string',
|
449 |
+
'enum' => array_merge( [ '' ], array_keys( wp_roles()->get_names() ) ),
|
450 |
+
'context' => [ 'view', 'edit' ],
|
451 |
+
],
|
452 |
+
]
|
453 |
+
];
|
454 |
+
|
455 |
+
if ( isset( $this->schema ) ) {
|
456 |
+
$this->schema = $schema;
|
457 |
+
}
|
458 |
+
|
459 |
+
return $schema;
|
460 |
+
}
|
461 |
+
|
462 |
+
public function get_collection_params() {
|
463 |
+
return [
|
464 |
+
'context' => $this->get_context_param( [ 'default' => 'view' ] ),
|
465 |
+
];
|
466 |
+
}
|
467 |
+
}
|
core/modules/user-groups/REST/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/Repository/DB_Repository.php
ADDED
@@ -0,0 +1,139 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
use iThemesSecurity\Exception\WP_Error;
|
7 |
+
use iThemesSecurity\User_Groups\User_Group;
|
8 |
+
|
9 |
+
final class DB_Repository implements Repository {
|
10 |
+
|
11 |
+
/** @var \wpdb */
|
12 |
+
private $wpdb;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* DB_Repository constructor.
|
16 |
+
*
|
17 |
+
* @param \wpdb $wpdb
|
18 |
+
*/
|
19 |
+
public function __construct( \wpdb $wpdb ) { $this->wpdb = $wpdb; }
|
20 |
+
|
21 |
+
public function next_id() {
|
22 |
+
return wp_generate_uuid4();
|
23 |
+
}
|
24 |
+
|
25 |
+
public function get( $id ) {
|
26 |
+
if ( ! is_string( $id ) ) {
|
27 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
28 |
+
}
|
29 |
+
|
30 |
+
$record = $this->wpdb->get_row( $this->wpdb->prepare(
|
31 |
+
"SELECT * FROM {$this->tn()} WHERE group_id = %s",
|
32 |
+
$id
|
33 |
+
), ARRAY_A );
|
34 |
+
|
35 |
+
if ( ! $record ) {
|
36 |
+
throw new User_Group_Not_Found( sprintf( __( "No user group found for '%s'", 'better-wp-security' ), $id ) );
|
37 |
+
}
|
38 |
+
|
39 |
+
return $this->hydrate( $record );
|
40 |
+
}
|
41 |
+
|
42 |
+
public function has( $id ) {
|
43 |
+
if ( ! is_string( $id ) ) {
|
44 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
45 |
+
}
|
46 |
+
|
47 |
+
return (bool) $this->wpdb->get_var( $this->wpdb->prepare(
|
48 |
+
"SELECT count(1) FROM {$this->tn()} WHERE group_id = %s",
|
49 |
+
$id
|
50 |
+
) );
|
51 |
+
}
|
52 |
+
|
53 |
+
public function persist( User_Group $user_group ) {
|
54 |
+
$this->wpdb->query( $this->wpdb->prepare(
|
55 |
+
"INSERT INTO {$this->tn()} (group_id, group_label, group_roles, group_canonical, group_users, group_min_role, group_created_at) VALUES (%s, %s, %s, %s, %s, %s, %s)" .
|
56 |
+
'ON DUPLICATE KEY UPDATE group_label = VALUES(group_label), group_roles = VALUES(group_roles), group_canonical = VALUES(group_canonical), group_users = VALUES(group_users), group_min_role = VALUES(group_min_role)',
|
57 |
+
$user_group->get_id(),
|
58 |
+
$user_group->get_label(),
|
59 |
+
implode( ',', $user_group->get_roles() ),
|
60 |
+
implode( ',', $user_group->get_canonical_roles() ),
|
61 |
+
implode( ',', wp_list_pluck( $user_group->get_users(), 'ID' ) ),
|
62 |
+
$user_group->get_min_role(),
|
63 |
+
date( 'Y-m-d H:i:s' )
|
64 |
+
) );
|
65 |
+
|
66 |
+
// When a on duplicate key update updates a record, the number of affected rows is 2 instead of 1 for creating.
|
67 |
+
$affected = $this->wpdb->rows_affected;
|
68 |
+
|
69 |
+
if ( $affected === 1 ) {
|
70 |
+
/**
|
71 |
+
* Fires when a user group is created.
|
72 |
+
*
|
73 |
+
* @since 6.4.0
|
74 |
+
*
|
75 |
+
* @param User_Group $user_group
|
76 |
+
*/
|
77 |
+
do_action( 'itsec_create_user_group', $user_group );
|
78 |
+
} else {
|
79 |
+
/**
|
80 |
+
* Fires when a user group is updated.
|
81 |
+
*
|
82 |
+
* @since 6.4.0
|
83 |
+
*
|
84 |
+
* @param User_Group $user_group
|
85 |
+
*/
|
86 |
+
do_action( 'itsec_update_user_group', $user_group );
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
public function delete( User_Group $user_group ) {
|
91 |
+
$deleted = $this->wpdb->delete( $this->tn(), [ 'group_id' => $user_group->get_id() ] );
|
92 |
+
|
93 |
+
if ( false === $deleted ) {
|
94 |
+
throw WP_Error::from_code( 'itsec-delete-user-group-failed', __( 'Failed to delete group.', 'better-wp-security' ) );
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
public function all() {
|
99 |
+
$records = $this->wpdb->get_results( "SELECT * FROM {$this->tn()} ORDER BY group_created_at ASC", ARRAY_A );
|
100 |
+
|
101 |
+
return array_map( [ $this, 'hydrate' ], $records );
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Hydrate a user group record.
|
106 |
+
*
|
107 |
+
* @param array $record
|
108 |
+
*
|
109 |
+
* @return User_Group
|
110 |
+
*/
|
111 |
+
private function hydrate( array $record ) {
|
112 |
+
$group = new User_Group( $record['group_id'] );
|
113 |
+
$group->set_label( $record['group_label'] );
|
114 |
+
|
115 |
+
foreach ( wp_parse_list( $record['group_roles'] ) as $role ) {
|
116 |
+
if ( get_role( $role ) ) {
|
117 |
+
$group->add_role( $role );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( get_role( $record['group_min_role'] ) ) {
|
122 |
+
$group->set_min_role( $record['group_min_role'] );
|
123 |
+
}
|
124 |
+
|
125 |
+
if ( ! empty( $record['group_canonical'] ) ) {
|
126 |
+
$group->set_canonical_roles( wp_parse_list( $record['group_canonical'] ) );
|
127 |
+
}
|
128 |
+
|
129 |
+
$group->set_users( array_filter( array_map( static function ( $id ) {
|
130 |
+
return get_userdata( $id ) ?: null;
|
131 |
+
}, wp_parse_id_list( $record['group_users'] ) ) ) );
|
132 |
+
|
133 |
+
return $group;
|
134 |
+
}
|
135 |
+
|
136 |
+
private function tn() {
|
137 |
+
return $this->wpdb->base_prefix . 'itsec_user_groups';
|
138 |
+
}
|
139 |
+
}
|
core/modules/user-groups/Repository/Decorator.php
ADDED
@@ -0,0 +1,35 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\User_Group;
|
6 |
+
|
7 |
+
trait Decorator {
|
8 |
+
|
9 |
+
/** @var Repository */
|
10 |
+
private $decorates;
|
11 |
+
|
12 |
+
public function next_id() {
|
13 |
+
return $this->decorates->next_id();
|
14 |
+
}
|
15 |
+
|
16 |
+
public function get( $id ) {
|
17 |
+
$this->decorates->get( $id );
|
18 |
+
}
|
19 |
+
|
20 |
+
public function has( $id ) {
|
21 |
+
return $this->decorates->has( $id );
|
22 |
+
}
|
23 |
+
|
24 |
+
public function persist( User_Group $user_group ) {
|
25 |
+
$this->decorates->persist( $user_group );
|
26 |
+
}
|
27 |
+
|
28 |
+
public function delete( User_Group $user_group ) {
|
29 |
+
$this->decorates->delete( $user_group );
|
30 |
+
}
|
31 |
+
|
32 |
+
public function all() {
|
33 |
+
return $this->decorates->all();
|
34 |
+
}
|
35 |
+
}
|
core/modules/user-groups/Repository/Eager_Loading_Decorator.php
ADDED
@@ -0,0 +1,68 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
use iThemesSecurity\User_Groups\User_Group;
|
7 |
+
|
8 |
+
final class Eager_Loading_Decorator implements Repository {
|
9 |
+
use Decorator;
|
10 |
+
|
11 |
+
/** @var User_Group[] */
|
12 |
+
private $all;
|
13 |
+
|
14 |
+
public function __construct( Repository $decorates ) {
|
15 |
+
$this->decorates = $decorates;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function get( $id ) {
|
19 |
+
if ( ! is_string( $id ) ) {
|
20 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
21 |
+
}
|
22 |
+
|
23 |
+
$this->all();
|
24 |
+
|
25 |
+
if ( ! isset( $this->all[ $id ] ) ) {
|
26 |
+
throw new User_Group_Not_Found( sprintf( __( "No user group found for '%s'", 'better-wp-security' ), $id ) );
|
27 |
+
}
|
28 |
+
|
29 |
+
return clone $this->all[ $id ];
|
30 |
+
}
|
31 |
+
|
32 |
+
public function has( $id ) {
|
33 |
+
if ( ! is_string( $id ) ) {
|
34 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->all();
|
38 |
+
|
39 |
+
return isset( $this->all[ $id ] );
|
40 |
+
}
|
41 |
+
|
42 |
+
public function persist( User_Group $user_group ) {
|
43 |
+
$this->decorates->persist( $user_group );
|
44 |
+
|
45 |
+
if ( null !== $this->all ) {
|
46 |
+
$this->all[ $user_group->get_id() ] = $user_group;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
public function delete( User_Group $user_group ) {
|
51 |
+
$this->decorates->delete( $user_group );
|
52 |
+
if ( null !== $this->all ) {
|
53 |
+
unset( $this->all[ $user_group->get_id() ] );
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
public function all() {
|
58 |
+
if ( null === $this->all ) {
|
59 |
+
$this->all = [];
|
60 |
+
|
61 |
+
foreach ( $this->decorates->all() as $user_group ) {
|
62 |
+
$this->all[ $user_group->get_id() ] = $user_group;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
return array_map( 'wp_clone', array_values( $this->all ) );
|
67 |
+
}
|
68 |
+
}
|
core/modules/user-groups/Repository/In_Memory_Repository.php
ADDED
@@ -0,0 +1,72 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
use iThemesSecurity\User_Groups\User_Group;
|
7 |
+
|
8 |
+
final class In_Memory_Repository implements Repository {
|
9 |
+
/** @var array */
|
10 |
+
private $memory;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* In_Memory_Repository constructor.
|
14 |
+
*
|
15 |
+
* @param array $memory
|
16 |
+
*/
|
17 |
+
public function __construct( array $memory = [] ) { $this->memory = $memory; }
|
18 |
+
|
19 |
+
public function next_id() {
|
20 |
+
return wp_generate_uuid4();
|
21 |
+
}
|
22 |
+
|
23 |
+
public function get( $id ) {
|
24 |
+
if ( ! is_string( $id ) ) {
|
25 |
+
throw new Invalid_Argument_Exception( __( 'uuid must be a string.', 'better-wp-security' ) );
|
26 |
+
}
|
27 |
+
|
28 |
+
if ( ! $this->has( $id ) ) {
|
29 |
+
throw new User_Group_Not_Found( sprintf( __( "No user group found for '%s'", 'better-wp-security' ), $id ) );
|
30 |
+
}
|
31 |
+
|
32 |
+
return clone $this->memory[ $id ];
|
33 |
+
}
|
34 |
+
|
35 |
+
public function has( $id ) {
|
36 |
+
return isset( $this->memory[ $id ] );
|
37 |
+
}
|
38 |
+
|
39 |
+
public function persist( User_Group $user_group ) {
|
40 |
+
$created = empty( $this->memory[ $user_group->get_id() ] );
|
41 |
+
|
42 |
+
$this->memory[ $user_group->get_id() ] = $user_group;
|
43 |
+
|
44 |
+
if ( $created ) {
|
45 |
+
/**
|
46 |
+
* Fires when a user group is created.
|
47 |
+
*
|
48 |
+
* @since 6.4.0
|
49 |
+
*
|
50 |
+
* @param User_Group $user_group
|
51 |
+
*/
|
52 |
+
do_action( 'itsec_create_user_group', $user_group );
|
53 |
+
} else {
|
54 |
+
/**
|
55 |
+
* Fires when a user group is updated.
|
56 |
+
*
|
57 |
+
* @since 6.4.0
|
58 |
+
*
|
59 |
+
* @param User_Group $user_group
|
60 |
+
*/
|
61 |
+
do_action( 'itsec_update_user_group', $user_group );
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
public function delete( User_Group $user_group ) {
|
66 |
+
unset( $this->memory[ $user_group->get_id() ] );
|
67 |
+
}
|
68 |
+
|
69 |
+
public function all() {
|
70 |
+
return array_values( $this->memory );
|
71 |
+
}
|
72 |
+
}
|
core/modules/user-groups/Repository/Object_Caching_Decorator.php
ADDED
@@ -0,0 +1,118 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
use iThemesSecurity\User_Groups\User_Group;
|
7 |
+
|
8 |
+
final class Object_Caching_Decorator implements Repository {
|
9 |
+
|
10 |
+
use Decorator;
|
11 |
+
|
12 |
+
const GROUP = 'itsec-user-group';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Caching_Decorator constructor.
|
16 |
+
*
|
17 |
+
* @param Repository $decorates
|
18 |
+
*/
|
19 |
+
public function __construct( Repository $decorates ) { $this->decorates = $decorates; }
|
20 |
+
|
21 |
+
public function get( $id ) {
|
22 |
+
if ( ! is_string( $id ) ) {
|
23 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
24 |
+
}
|
25 |
+
|
26 |
+
$serialized = wp_cache_get( $id, self::GROUP );
|
27 |
+
|
28 |
+
if ( $serialized ) {
|
29 |
+
return $this->hydrate( $id, $serialized );
|
30 |
+
}
|
31 |
+
|
32 |
+
$user_group = $this->decorates->get( $id );
|
33 |
+
$this->cache( $user_group );
|
34 |
+
|
35 |
+
return $user_group;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function has( $id ) {
|
39 |
+
if ( ! is_string( $id ) ) {
|
40 |
+
throw new Invalid_Argument_Exception( __( 'Id must be a string.', 'better-wp-security' ) );
|
41 |
+
}
|
42 |
+
|
43 |
+
if ( wp_cache_get( $id, self::GROUP ) ) {
|
44 |
+
return true;
|
45 |
+
}
|
46 |
+
|
47 |
+
return $this->decorates->has( $id );
|
48 |
+
}
|
49 |
+
|
50 |
+
public function persist( User_Group $user_group ) {
|
51 |
+
$this->decorates->persist( $user_group );
|
52 |
+
$this->cache( $user_group );
|
53 |
+
}
|
54 |
+
|
55 |
+
public function delete( User_Group $user_group ) {
|
56 |
+
$this->decorates->delete( $user_group );
|
57 |
+
wp_cache_delete( $user_group->get_id(), self::GROUP );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Cache the user group's data.
|
62 |
+
*
|
63 |
+
* @param User_Group $user_group
|
64 |
+
*/
|
65 |
+
private function cache( User_Group $user_group ) {
|
66 |
+
wp_cache_set( $user_group->get_id(), $this->serialize( $user_group ), self::GROUP );
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Serialize a user group to an array.
|
71 |
+
*
|
72 |
+
* @param User_Group $group
|
73 |
+
*
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
private function serialize( User_Group $group ) {
|
77 |
+
return [
|
78 |
+
'label' => $group->get_label(),
|
79 |
+
'roles' => $group->get_roles(),
|
80 |
+
'canonical' => $group->get_canonical_roles(),
|
81 |
+
'min_role' => $group->get_min_role(),
|
82 |
+
'users' => wp_list_pluck( $group->get_users(), 'ID' ),
|
83 |
+
];
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Hydrate a user group record.
|
88 |
+
*
|
89 |
+
* @param string $uuid
|
90 |
+
* @param array $record
|
91 |
+
*
|
92 |
+
* @return User_Group
|
93 |
+
*/
|
94 |
+
private function hydrate( $uuid, $record ) {
|
95 |
+
$group = new User_Group( $uuid );
|
96 |
+
$group->set_label( $record['label'] );
|
97 |
+
|
98 |
+
foreach ( $record['roles'] as $role ) {
|
99 |
+
if ( get_role( $role ) ) {
|
100 |
+
$group->add_role( $role );
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
if ( get_role( $record['min_role'] ) ) {
|
105 |
+
$group->set_min_role( $record['min_role'] );
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( ! empty( $record['canonical'] ) ) {
|
109 |
+
$group->set_canonical_roles( $record['canonical'] );
|
110 |
+
}
|
111 |
+
|
112 |
+
$group->set_users( array_filter( array_map( static function ( $id ) {
|
113 |
+
return get_userdata( $id ) ?: null;
|
114 |
+
}, $record['users'] ) ) );
|
115 |
+
|
116 |
+
return $group;
|
117 |
+
}
|
118 |
+
}
|
core/modules/user-groups/Repository/Repository.php
ADDED
@@ -0,0 +1,62 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\WP_Error;
|
6 |
+
use iThemesSecurity\User_Groups\User_Group;
|
7 |
+
|
8 |
+
interface Repository {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Get the next id for a user group.
|
12 |
+
*
|
13 |
+
* @return string
|
14 |
+
*/
|
15 |
+
public function next_id();
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Get a user group by it's id.
|
19 |
+
*
|
20 |
+
* @param string $id
|
21 |
+
*
|
22 |
+
* @return User_Group
|
23 |
+
* @throws User_Group_Not_Found
|
24 |
+
*/
|
25 |
+
public function get( $id );
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Does the repository have a user group identified by the uuid.
|
29 |
+
*
|
30 |
+
* @param string $id
|
31 |
+
*
|
32 |
+
* @return bool
|
33 |
+
*/
|
34 |
+
public function has( $id );
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Persist a user group.
|
38 |
+
*
|
39 |
+
* @param User_Group $user_group
|
40 |
+
*
|
41 |
+
* @return void
|
42 |
+
*
|
43 |
+
* @throws WP_Error
|
44 |
+
*/
|
45 |
+
public function persist( User_Group $user_group );
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Delete a user group.
|
49 |
+
*
|
50 |
+
* @param User_Group $user_group
|
51 |
+
*
|
52 |
+
* @return void
|
53 |
+
*/
|
54 |
+
public function delete( User_Group $user_group );
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Get a list of all the user groups.
|
58 |
+
*
|
59 |
+
* @return User_Group[]
|
60 |
+
*/
|
61 |
+
public function all();
|
62 |
+
}
|
core/modules/user-groups/Repository/User_Group_Not_Found.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups\Repository;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Exception;
|
6 |
+
|
7 |
+
final class User_Group_Not_Found extends \OutOfBoundsException implements Exception {
|
8 |
+
|
9 |
+
}
|
core/modules/user-groups/Repository/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/Settings/Settings_Proxy.php
ADDED
@@ -0,0 +1,46 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
final class Settings_Proxy {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Check if a matchable has the given setting enabled.
|
9 |
+
*
|
10 |
+
* @param Matchable $matchable The matchable to check for.
|
11 |
+
* @param Settings_Registration $registration The setting to check.
|
12 |
+
*
|
13 |
+
* @return bool
|
14 |
+
*/
|
15 |
+
public function is_enabled( Matchable $matchable, Settings_Registration $registration ) {
|
16 |
+
$value = \ITSEC_Lib::array_get( \ITSEC_Modules::get_settings( $registration->get_module() ), $registration->get_setting() );
|
17 |
+
|
18 |
+
return in_array( $matchable->get_id(), $value, true );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Set whether a setting is enabled.
|
23 |
+
*
|
24 |
+
* @param Matchable $matchable The matchable to enable/disable the setting for.
|
25 |
+
* @param Settings_Registration $registration The setting.
|
26 |
+
* @param bool $enabled Whether the setting should be enabled.
|
27 |
+
*
|
28 |
+
* @return \WP_Error|null Null on success, WP_Error on error.
|
29 |
+
*/
|
30 |
+
public function set_enabled( Matchable $matchable, Settings_Registration $registration, $enabled = true ) {
|
31 |
+
$settings = \ITSEC_Modules::get_settings( $registration->get_module() );
|
32 |
+
$current = \ITSEC_Lib::array_get( $settings, $registration->get_setting() );
|
33 |
+
|
34 |
+
if ( $enabled && ! in_array( $matchable->get_id(), $current, true ) ) {
|
35 |
+
$current[] = $matchable->get_id();
|
36 |
+
} elseif ( ! $enabled && ( $i = array_search( $matchable->get_id(), $current, true ) ) !== false ) {
|
37 |
+
unset( $current[ $i ] );
|
38 |
+
}
|
39 |
+
|
40 |
+
$settings = \ITSEC_Lib::array_set( $settings, $registration->get_setting(), $current );
|
41 |
+
|
42 |
+
$updated = \ITSEC_Modules::set_settings( $registration->get_module(), $settings );
|
43 |
+
|
44 |
+
return \ITSEC_Lib::updated_settings_to_wp_error( $updated );
|
45 |
+
}
|
46 |
+
}
|
core/modules/user-groups/Settings/Settings_Registration.php
ADDED
@@ -0,0 +1,87 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use iThemesSecurity\Exception\Invalid_Argument_Exception;
|
6 |
+
|
7 |
+
final class Settings_Registration {
|
8 |
+
|
9 |
+
const T_SINGLE = 'single';
|
10 |
+
const T_MULTIPLE = 'multiple';
|
11 |
+
|
12 |
+
/** @var string */
|
13 |
+
private $module;
|
14 |
+
|
15 |
+
/** @var string */
|
16 |
+
private $setting;
|
17 |
+
|
18 |
+
/** @var string */
|
19 |
+
private $type;
|
20 |
+
|
21 |
+
/** @var callable */
|
22 |
+
private $labels;
|
23 |
+
|
24 |
+
/** @var string */
|
25 |
+
private $generated;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Settings_Registration constructor.
|
29 |
+
*
|
30 |
+
* @param string $module
|
31 |
+
* @param string $setting
|
32 |
+
* @param string $type
|
33 |
+
* @param callable $labels
|
34 |
+
*/
|
35 |
+
public function __construct( $module, $setting, $type, callable $labels ) {
|
36 |
+
if ( ! in_array( $type, [ self::T_SINGLE, self::T_MULTIPLE ], true ) ) {
|
37 |
+
throw new Invalid_Argument_Exception( __( 'Type must be either single or multiple.', 'better-wp-security' ) );
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->module = $module;
|
41 |
+
$this->setting = $setting;
|
42 |
+
$this->type = $type;
|
43 |
+
$this->labels = $labels;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get the slug of the module.
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
public function get_module() {
|
52 |
+
return $this->module;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Get the slug of the setting.
|
57 |
+
*
|
58 |
+
* @return string
|
59 |
+
*/
|
60 |
+
public function get_setting() {
|
61 |
+
return $this->setting;
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Get the setting type.
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
public function get_type() {
|
70 |
+
return $this->type;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Get the labels for this setting.
|
75 |
+
*
|
76 |
+
* Has 'title' and 'description' keys.
|
77 |
+
*
|
78 |
+
* @return string[]
|
79 |
+
*/
|
80 |
+
public function get_labels() {
|
81 |
+
if ( ! $this->generated ) {
|
82 |
+
$this->generated = call_user_func( $this->labels );
|
83 |
+
}
|
84 |
+
|
85 |
+
return $this->generated;
|
86 |
+
}
|
87 |
+
}
|
core/modules/user-groups/Settings/Settings_Registry.php
ADDED
@@ -0,0 +1,73 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
final class Settings_Registry {
|
6 |
+
|
7 |
+
/** @var Settings_Registration[] */
|
8 |
+
private $settings = [];
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Register the setting.
|
12 |
+
*
|
13 |
+
* @param Settings_Registration $registration
|
14 |
+
*/
|
15 |
+
public function register( Settings_Registration $registration ) {
|
16 |
+
$this->settings[] = $registration;
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Unregister a setting.
|
21 |
+
*
|
22 |
+
* @param string $module
|
23 |
+
* @param string $setting
|
24 |
+
*
|
25 |
+
* @return bool True if the setting was unregistered.
|
26 |
+
*/
|
27 |
+
public function unregister( $module, $setting ) {
|
28 |
+
foreach ( $this->settings as $i => $registration ) {
|
29 |
+
if ( $registration->get_module() === $module && $registration->get_setting() === $setting ) {
|
30 |
+
unset( $this->settings[ $i ] );
|
31 |
+
$this->settings = array_values( $this->settings );
|
32 |
+
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
return false;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Get a list of all the settings.
|
42 |
+
*
|
43 |
+
* @return Settings_Registration[]
|
44 |
+
*/
|
45 |
+
public function get_settings() {
|
46 |
+
return $this->settings;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Find a setting registration by module and setting.
|
51 |
+
*
|
52 |
+
* @param string $module
|
53 |
+
* @param string $setting
|
54 |
+
*
|
55 |
+
* @return Settings_Registration|null
|
56 |
+
*/
|
57 |
+
public function find( $module, $setting ) {
|
58 |
+
foreach ( $this->get_settings() as $registration ) {
|
59 |
+
if ( $registration->get_module() === $module && $registration->get_setting() === $setting ) {
|
60 |
+
return $registration;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
return null;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Clear all registered settings.
|
69 |
+
*/
|
70 |
+
public function clear_settings() {
|
71 |
+
$this->settings = [];
|
72 |
+
}
|
73 |
+
}
|
core/modules/user-groups/Settings/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/Upgrader.php
ADDED
@@ -0,0 +1,76 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use iThemesSecurity\User_Groups\Module\Settings;
|
6 |
+
use iThemesSecurity\User_Groups\Repository\Repository;
|
7 |
+
use ITSEC_Lib_Canonical_Roles;
|
8 |
+
|
9 |
+
final class Upgrader {
|
10 |
+
|
11 |
+
/** @var Repository */
|
12 |
+
private $user_groups;
|
13 |
+
|
14 |
+
/** @var Settings */
|
15 |
+
private $settings;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Upgrader constructor.
|
19 |
+
*
|
20 |
+
* @param Repository $user_groups
|
21 |
+
* @param Settings $settings
|
22 |
+
*/
|
23 |
+
public function __construct( Repository $user_groups, Settings $settings ) {
|
24 |
+
$this->user_groups = $user_groups;
|
25 |
+
$this->settings = $settings;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Upgrade an existing setting to a user group.
|
30 |
+
*
|
31 |
+
* @param string $label Label to give the user group if a new one has to be created.
|
32 |
+
* @param callable $configure Callable to configure the user group.
|
33 |
+
*
|
34 |
+
* @return User_Group Either the newly created user group, or an existing user group that was an exact match.
|
35 |
+
*/
|
36 |
+
public function find_or_create( $label, callable $configure ) {
|
37 |
+
$user_group = new User_Group( $this->user_groups->next_id() );
|
38 |
+
$configure( $user_group );
|
39 |
+
|
40 |
+
foreach ( $this->user_groups->all() as $maybe_group ) {
|
41 |
+
if ( $maybe_group->equals( $user_group ) ) {
|
42 |
+
return $maybe_group;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
$user_group->set_label( $label );
|
47 |
+
$this->user_groups->persist( $user_group );
|
48 |
+
|
49 |
+
return $user_group;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Upgrade a min role based setting to a group based setting.
|
54 |
+
*
|
55 |
+
* @param string $min_role The minimum canonical role.
|
56 |
+
*
|
57 |
+
* @return string[] The list of user group IDs to store.
|
58 |
+
*/
|
59 |
+
public function upgrade_from_min_role( $min_role ) {
|
60 |
+
$groups = [];
|
61 |
+
|
62 |
+
foreach ( ITSEC_Lib_Canonical_Roles::get_canonical_roles_of_at_least( $min_role ) as $role ) {
|
63 |
+
if ( 'super-admin' === $role ) {
|
64 |
+
continue;
|
65 |
+
}
|
66 |
+
|
67 |
+
$groups[] = $this->settings->get_default_group_id( $role, true );
|
68 |
+
}
|
69 |
+
|
70 |
+
if ( 'subscriber' === $min_role ) {
|
71 |
+
$groups[] = 'everybody-else';
|
72 |
+
}
|
73 |
+
|
74 |
+
return $groups;
|
75 |
+
}
|
76 |
+
}
|
core/modules/user-groups/User_Group.php
ADDED
@@ -0,0 +1,436 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
use InvalidArgumentException;
|
6 |
+
use WP_User;
|
7 |
+
use ITSEC_Lib;
|
8 |
+
use ITSEC_Lib_Canonical_Roles;
|
9 |
+
|
10 |
+
final class User_Group implements Matchable {
|
11 |
+
|
12 |
+
/** @var string */
|
13 |
+
private $id;
|
14 |
+
|
15 |
+
/** @var string */
|
16 |
+
private $label = '';
|
17 |
+
|
18 |
+
/** @var int[] */
|
19 |
+
private $users = [];
|
20 |
+
|
21 |
+
/** @var string[] */
|
22 |
+
private $roles = [];
|
23 |
+
|
24 |
+
/** @var array */
|
25 |
+
private $canonical_roles = [];
|
26 |
+
|
27 |
+
/** @var string */
|
28 |
+
private $min_role = '';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* $this constructor.
|
32 |
+
*
|
33 |
+
* @param string $id
|
34 |
+
*/
|
35 |
+
public function __construct( $id ) {
|
36 |
+
if ( ! wp_is_uuid( $id, 4 ) ) {
|
37 |
+
throw new InvalidArgumentException( 'id must be a UUIDv4' );
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->id = $id;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Get the id.
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function get_id() {
|
49 |
+
return $this->id;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Add a user to this group.
|
54 |
+
*
|
55 |
+
* @param WP_User $user
|
56 |
+
*
|
57 |
+
* @return $this
|
58 |
+
*/
|
59 |
+
public function add_user( WP_User $user ) {
|
60 |
+
if ( ! in_array( $user->ID, $this->users, true ) ) {
|
61 |
+
$this->users[] = $user->ID;
|
62 |
+
}
|
63 |
+
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Remove a user from this group.
|
69 |
+
*
|
70 |
+
* @param WP_User $user
|
71 |
+
*
|
72 |
+
* @return $this
|
73 |
+
*/
|
74 |
+
public function remove_user( WP_User $user ) {
|
75 |
+
if ( ( $i = array_search( $user->ID, $this->users, true ) ) !== false ) {
|
76 |
+
unset( $this->users[ $i ] );
|
77 |
+
}
|
78 |
+
|
79 |
+
return $this;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Set the list of users to contain in this group.
|
84 |
+
*
|
85 |
+
* @param WP_User[] $users
|
86 |
+
*
|
87 |
+
* @return $this
|
88 |
+
*/
|
89 |
+
public function set_users( array $users ) {
|
90 |
+
$this->users = [];
|
91 |
+
array_walk( $users, [ $this, 'add_user' ] );
|
92 |
+
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Get the list of users contained in this group.
|
98 |
+
*
|
99 |
+
* @return WP_User[]
|
100 |
+
*/
|
101 |
+
public function get_users() {
|
102 |
+
return array_filter( array_map( 'get_userdata', $this->users ), static function ( $user ) {
|
103 |
+
return $user instanceof WP_User;
|
104 |
+
} );
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Add a role to the user group.
|
109 |
+
*
|
110 |
+
* @param string $role
|
111 |
+
*
|
112 |
+
* @return $this
|
113 |
+
*/
|
114 |
+
public function add_role( $role ) {
|
115 |
+
if ( ! get_role( $role ) ) {
|
116 |
+
throw new InvalidArgumentException( sprintf( 'Role %s not found.', $role ) );
|
117 |
+
}
|
118 |
+
|
119 |
+
$this->roles[] = $role;
|
120 |
+
|
121 |
+
return $this;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Remove a role from the user group.
|
126 |
+
*
|
127 |
+
* @param string $role
|
128 |
+
*
|
129 |
+
* @return $this
|
130 |
+
*/
|
131 |
+
public function remove_role( $role ) {
|
132 |
+
if ( ( $i = array_search( $role, $this->roles, true ) ) !== false ) {
|
133 |
+
unset( $this->roles[ $i ] );
|
134 |
+
}
|
135 |
+
|
136 |
+
return $this;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Set the list of roles for the user group.
|
141 |
+
*
|
142 |
+
* @param string[] $roles
|
143 |
+
*
|
144 |
+
* @return $this
|
145 |
+
*/
|
146 |
+
public function set_roles( array $roles ) {
|
147 |
+
$this->roles = [];
|
148 |
+
array_walk( $roles, [ $this, 'add_role' ] );
|
149 |
+
|
150 |
+
return $this;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Get the list of roles for the user group.
|
155 |
+
*
|
156 |
+
* @return string[]
|
157 |
+
*/
|
158 |
+
public function get_roles() {
|
159 |
+
return $this->roles;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Add a canonical role to the user group.
|
164 |
+
*
|
165 |
+
* @param string $role
|
166 |
+
*
|
167 |
+
* @return $this
|
168 |
+
*/
|
169 |
+
public function add_canonical_role( $role ) {
|
170 |
+
if ( ! in_array( $role, ITSEC_Lib_Canonical_Roles::get_canonical_roles(), true ) ) {
|
171 |
+
throw new InvalidArgumentException( sprintf( 'Role %s is not a valid canonical role.', $role ) );
|
172 |
+
}
|
173 |
+
|
174 |
+
$this->canonical_roles[] = $role;
|
175 |
+
|
176 |
+
return $this;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Remove a canonical role from the user group.
|
181 |
+
*
|
182 |
+
* @param string $role
|
183 |
+
*
|
184 |
+
* @return $this
|
185 |
+
*/
|
186 |
+
public function remove_canonical_role( $role ) {
|
187 |
+
if ( ( $i = array_search( $role, $this->canonical_roles, true ) ) !== false ) {
|
188 |
+
unset( $this->canonical_roles[ $i ] );
|
189 |
+
}
|
190 |
+
|
191 |
+
return $this;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Set the list of roles for the user group.
|
196 |
+
*
|
197 |
+
* @param string[] $roles
|
198 |
+
*
|
199 |
+
* @return $this
|
200 |
+
*/
|
201 |
+
public function set_canonical_roles( array $roles ) {
|
202 |
+
$this->canonical_roles = [];
|
203 |
+
array_walk( $roles, [ $this, 'add_canonical_role' ] );
|
204 |
+
|
205 |
+
return $this;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Get the list of canonical roles for the user group.
|
210 |
+
*
|
211 |
+
* @return string[]
|
212 |
+
*/
|
213 |
+
public function get_canonical_roles() {
|
214 |
+
return $this->canonical_roles;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Get the role that users must be greater than for the group to apply.
|
219 |
+
*
|
220 |
+
* @return string
|
221 |
+
*/
|
222 |
+
public function get_min_role() {
|
223 |
+
return $this->min_role;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Set the role that users must be greater than for the group to apply.
|
228 |
+
*
|
229 |
+
* @param string $role
|
230 |
+
*
|
231 |
+
* @return $this
|
232 |
+
*/
|
233 |
+
public function set_min_role( $role ) {
|
234 |
+
if ( '' !== $role && ! get_role( $role ) ) {
|
235 |
+
throw new InvalidArgumentException( sprintf( 'Role %s not found.', $role ) );
|
236 |
+
}
|
237 |
+
|
238 |
+
$this->min_role = $role;
|
239 |
+
|
240 |
+
return $this;
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Get the user provided label for this user group.
|
245 |
+
*
|
246 |
+
* @return string
|
247 |
+
*/
|
248 |
+
public function get_label() {
|
249 |
+
return $this->label;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Set the label for this user group.
|
254 |
+
*
|
255 |
+
* @param string $label
|
256 |
+
*
|
257 |
+
* @return $this
|
258 |
+
*/
|
259 |
+
public function set_label( $label ) {
|
260 |
+
if ( ! is_string( $label ) ) {
|
261 |
+
throw new InvalidArgumentException( '$label must be a string.' );
|
262 |
+
}
|
263 |
+
|
264 |
+
$this->label = $label;
|
265 |
+
|
266 |
+
return $this;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Get the generated description for this user group.
|
271 |
+
*
|
272 |
+
* @return string
|
273 |
+
*/
|
274 |
+
public function get_description() {
|
275 |
+
$parts = [];
|
276 |
+
|
277 |
+
if ( $roles = $this->get_roles() ) {
|
278 |
+
$parts[] = wp_sprintf( __( 'the following roles: %l', 'better-wp-security' ), array_map( 'translate_user_role', $roles ) );
|
279 |
+
}
|
280 |
+
|
281 |
+
if ( $canonical = $this->get_canonical_roles() ) {
|
282 |
+
$parts[] = wp_sprintf( __( 'the following canonical roles: %l', 'better-wp-security' ), array_map( 'translate_user_role', $canonical ) );
|
283 |
+
}
|
284 |
+
|
285 |
+
if ( $min_role = $this->get_min_role() ) {
|
286 |
+
$parts[] = sprintf( __( 'roles greater than %s', 'better-wp-security' ), translate_user_role( $min_role ) );
|
287 |
+
}
|
288 |
+
|
289 |
+
if ( $users = $this->get_users() ) {
|
290 |
+
$parts[] = wp_sprintf( __( 'the following users: %l', 'better-wp-security' ), wp_list_pluck( $users, 'user_login' ) );
|
291 |
+
}
|
292 |
+
|
293 |
+
if ( ! $parts ) {
|
294 |
+
return wp_sprintf( __( 'This user group contains no users.', 'better-wp-security' ) );
|
295 |
+
}
|
296 |
+
|
297 |
+
return wp_sprintf( __( 'This user group contains %l.', 'better-wp-security' ), $parts );
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Get the computed list of roles this user group applies to.
|
302 |
+
*
|
303 |
+
* This is the manually selected list of roles, as well as all roles greater
|
304 |
+
* than the minimum role.
|
305 |
+
*
|
306 |
+
* @return string[]
|
307 |
+
*/
|
308 |
+
public function get_computed_role_list() {
|
309 |
+
ITSEC_Lib::load( 'canonical-roles' );
|
310 |
+
$roles = $this->get_roles();
|
311 |
+
$min_role = $this->get_min_role();
|
312 |
+
$canonical_roles = $this->get_canonical_roles();
|
313 |
+
|
314 |
+
foreach ( wp_roles()->get_names() as $role => $name ) {
|
315 |
+
if ( in_array( $role, $roles, true ) ) {
|
316 |
+
continue;
|
317 |
+
}
|
318 |
+
|
319 |
+
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $role );
|
320 |
+
|
321 |
+
if ( in_array( $canonical, $canonical_roles, true ) ) {
|
322 |
+
$roles[] = $role;
|
323 |
+
continue;
|
324 |
+
}
|
325 |
+
|
326 |
+
if ( $min_role && ITSEC_Lib_Canonical_Roles::is_canonical_role_at_least( $min_role, $canonical ) ) {
|
327 |
+
$roles[] = $role;
|
328 |
+
continue;
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
return $roles;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Is the user group properly configured.
|
337 |
+
*
|
338 |
+
* @return bool
|
339 |
+
*/
|
340 |
+
public function is_configured() {
|
341 |
+
return $this->min_role || $this->roles || $this->users || $this->canonical_roles;
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Does the given user match this user group.
|
346 |
+
*
|
347 |
+
* @param Match_Target $target
|
348 |
+
*
|
349 |
+
* @return bool
|
350 |
+
*/
|
351 |
+
public function matches( Match_Target $target ) {
|
352 |
+
if ( ( $user = $target->get_user() ) && in_array( $user->ID, $this->users, true ) ) {
|
353 |
+
return true;
|
354 |
+
}
|
355 |
+
|
356 |
+
if ( array_intersect( $this->get_roles(), $target->get_role() ? [ $target->get_role() ] : $user->roles ) ) {
|
357 |
+
return true;
|
358 |
+
}
|
359 |
+
|
360 |
+
$min_role = $this->get_min_role();
|
361 |
+
$canonical_roles = $this->get_canonical_roles();
|
362 |
+
|
363 |
+
if ( $min_role || $canonical_roles ) {
|
364 |
+
ITSEC_Lib::load( 'canonical-roles' );
|
365 |
+
|
366 |
+
if ( $target->get_role() && $target->get_user() ) {
|
367 |
+
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role_and_user( $target->get_role(), $target->get_user() );
|
368 |
+
} elseif ( $target->get_role() ) {
|
369 |
+
$canonical = ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $target->get_role() );
|
370 |
+
} elseif ( $target->get_user() ) {
|
371 |
+
$canonical = ITSEC_Lib_Canonical_Roles::get_user_role( $target->get_user() );
|
372 |
+
} else {
|
373 |
+
$canonical = '';
|
374 |
+
}
|
375 |
+
|
376 |
+
if ( $canonical ) {
|
377 |
+
if ( $min_role && ITSEC_Lib_Canonical_Roles::is_canonical_role_at_least( $min_role, $canonical ) ) {
|
378 |
+
return true;
|
379 |
+
}
|
380 |
+
|
381 |
+
if ( $canonical_roles && in_array( $canonical, $canonical_roles, true ) ) {
|
382 |
+
return true;
|
383 |
+
}
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
return false;
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Is this user group the same record as the given user group.
|
392 |
+
*
|
393 |
+
* @param User_Group $user_group
|
394 |
+
*
|
395 |
+
* @return bool
|
396 |
+
*/
|
397 |
+
public function identical( User_Group $user_group ) {
|
398 |
+
return $this->get_id() === $user_group->get_id();
|
399 |
+
}
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Is this user group made up of the same restrictions as the given user group.
|
403 |
+
*
|
404 |
+
* @param User_Group $user_group
|
405 |
+
*
|
406 |
+
* @return bool
|
407 |
+
*/
|
408 |
+
public function equals( User_Group $user_group ) {
|
409 |
+
if ( $this->get_min_role() !== $user_group->get_min_role() ) {
|
410 |
+
return false;
|
411 |
+
}
|
412 |
+
|
413 |
+
if ( ! ITSEC_Lib::equal_sets( $this->get_roles(), $user_group->get_roles() ) ) {
|
414 |
+
return false;
|
415 |
+
}
|
416 |
+
|
417 |
+
if ( ! ITSEC_Lib::equal_sets( $this->get_canonical_roles(), $user_group->get_canonical_roles() ) ) {
|
418 |
+
return false;
|
419 |
+
}
|
420 |
+
|
421 |
+
if ( ! ITSEC_Lib::equal_sets( $this->users, $user_group->users ) ) {
|
422 |
+
return false;
|
423 |
+
}
|
424 |
+
|
425 |
+
return true;
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Converts the user group to a string.
|
430 |
+
*
|
431 |
+
* @return string
|
432 |
+
*/
|
433 |
+
public function __toString() {
|
434 |
+
return $this->get_label();
|
435 |
+
}
|
436 |
+
}
|
core/modules/user-groups/container.php
ADDED
@@ -0,0 +1,90 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use iThemesSecurity\User_Groups;
|
4 |
+
use iThemesSecurity\User_Groups\REST;
|
5 |
+
use Pimple\Container;
|
6 |
+
|
7 |
+
return static function ( Container $c ) {
|
8 |
+
$c['module.user-groups.files'] = [
|
9 |
+
'active.php' => User_Groups\Module\Module::class,
|
10 |
+
'settings.php' => User_Groups\Module\Settings::class,
|
11 |
+
'validator.php' => User_Groups\Module\Validator::class,
|
12 |
+
'rest.php' => REST\REST::class,
|
13 |
+
];
|
14 |
+
|
15 |
+
$c[ User_Groups\Module\Settings::class ] = static function ( Container $c ) {
|
16 |
+
return new User_Groups\Module\Settings( $c[ User_Groups\Repository\Repository::class ] );
|
17 |
+
};
|
18 |
+
|
19 |
+
$c[ User_Groups\Module\Validator::class ] = static function ( Container $c ) {
|
20 |
+
return new User_Groups\Module\Validator();
|
21 |
+
};
|
22 |
+
|
23 |
+
$c[ User_Groups\Module\Module::class ] = static function ( Container $c ) {
|
24 |
+
return new User_Groups\Module\Module(
|
25 |
+
$c[ User_Groups\Repository\Repository::class ],
|
26 |
+
$c[ User_Groups\Settings_Registry::class ],
|
27 |
+
$c[ User_Groups\Settings_Proxy::class ]
|
28 |
+
);
|
29 |
+
};
|
30 |
+
|
31 |
+
$c[ User_Groups\Repository\Repository::class ] = static function ( Container $c ) {
|
32 |
+
return new User_Groups\Repository\Eager_Loading_Decorator( $c[ User_Groups\Repository\DB_Repository::class ] );
|
33 |
+
};
|
34 |
+
|
35 |
+
$c[ User_Groups\Repository\DB_Repository::class ] = static function ( Container $c ) {
|
36 |
+
return new User_Groups\Repository\DB_Repository( $GLOBALS['wpdb'] );
|
37 |
+
};
|
38 |
+
|
39 |
+
$c[ User_Groups\Upgrader::class ] = static function ( Container $c ) {
|
40 |
+
return new User_Groups\Upgrader(
|
41 |
+
$c[ User_Groups\Repository\Repository::class ],
|
42 |
+
$c[ User_Groups\Module\Settings::class ]
|
43 |
+
);
|
44 |
+
};
|
45 |
+
|
46 |
+
$c[ User_Groups\Matcher::class ] = static function ( Container $c ) {
|
47 |
+
return $c[ User_Groups\Default_Matcher::class ];
|
48 |
+
};
|
49 |
+
|
50 |
+
$c[ User_Groups\Default_Matcher::class ] = static function ( Container $c ) {
|
51 |
+
return new User_Groups\Default_Matcher( $c[ User_Groups\Matchables_Source::class ] );
|
52 |
+
};
|
53 |
+
|
54 |
+
$c[ User_Groups\Matchables_Source::class ] = static function ( Container $c ) {
|
55 |
+
return ( new User_Groups\Matchables_Source( $c[ User_Groups\Repository\Repository::class ] ) )
|
56 |
+
->add( new User_Groups\Everybody_Else( $c[ User_Groups\Repository\Repository::class ] ) );
|
57 |
+
};
|
58 |
+
|
59 |
+
$c[ User_Groups\Settings_Registry::class ] = static function ( Container $c ) {
|
60 |
+
return new User_Groups\Settings_Registry();
|
61 |
+
};
|
62 |
+
|
63 |
+
$c[ User_Groups\Settings_Proxy::class ] = static function () {
|
64 |
+
return new User_Groups\Settings_Proxy();
|
65 |
+
};
|
66 |
+
|
67 |
+
$c[ User_Groups\REST\REST::class ] = static function ( Container $c ) {
|
68 |
+
return new User_Groups\REST\REST( array(
|
69 |
+
$c[ REST\User_Groups::class ],
|
70 |
+
$c[ REST\Matchables::class ],
|
71 |
+
$c[ REST\Settings::class ],
|
72 |
+
) );
|
73 |
+
};
|
74 |
+
|
75 |
+
$c[ REST\User_Groups::class ] = static function ( Container $c ) {
|
76 |
+
return new REST\User_Groups( $c[ User_Groups\Repository\Repository::class ] );
|
77 |
+
};
|
78 |
+
|
79 |
+
$c[ REST\Matchables::class ] = static function ( Container $c ) {
|
80 |
+
return new REST\Matchables( $c[ User_Groups\Matchables_Source::class ] );
|
81 |
+
};
|
82 |
+
|
83 |
+
$c[ REST\Settings::class ] = static function ( Container $c ) {
|
84 |
+
return new REST\Settings(
|
85 |
+
$c[ User_Groups\Matchables_Source::class ],
|
86 |
+
$c[ User_Groups\Settings_Registry::class ],
|
87 |
+
$c[ User_Groups\Settings_Proxy::class ]
|
88 |
+
);
|
89 |
+
};
|
90 |
+
};
|
core/modules/user-groups/entries/api.js
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
import store from './store';
|
2 |
+
|
3 |
+
export { store };
|
core/modules/user-groups/entries/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings.js
ADDED
@@ -0,0 +1,37 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { setLocaleData } from '@wordpress/i18n';
|
5 |
+
import { render } from '@wordpress/element';
|
6 |
+
import domReady from '@wordpress/dom-ready';
|
7 |
+
|
8 |
+
// Silence warnings until JS i18n is stable.
|
9 |
+
setLocaleData( { '': {} }, 'ithemes-security-pro' );
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Internal dependencies
|
13 |
+
*/
|
14 |
+
import App from './settings/app.js';
|
15 |
+
|
16 |
+
domReady( () => {
|
17 |
+
init();
|
18 |
+
|
19 |
+
if ( window.itsecSettingsPage ) {
|
20 |
+
window.itsecSettingsPage.events.on( 'modulesReloaded', init );
|
21 |
+
window.itsecSettingsPage.events.on( 'moduleReloaded', function( _, module ) {
|
22 |
+
if ( 'user-groups' === module ) {
|
23 |
+
init();
|
24 |
+
}
|
25 |
+
} );
|
26 |
+
}
|
27 |
+
} );
|
28 |
+
|
29 |
+
function init() {
|
30 |
+
const containerEl = document.getElementById( 'itsec-user-groups-settings-root' );
|
31 |
+
const noticeEl = document.getElementById( 'itsec-module-messages-container-user-groups' );
|
32 |
+
|
33 |
+
return render(
|
34 |
+
<App noticeEl={ noticeEl } />,
|
35 |
+
containerEl,
|
36 |
+
);
|
37 |
+
}
|
core/modules/user-groups/entries/settings/app.js
ADDED
@@ -0,0 +1,26 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import '@wordpress/notices';
|
5 |
+
import { createPortal } from '@wordpress/element';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal dependencies
|
9 |
+
*/
|
10 |
+
import '@ithemes/security-data';
|
11 |
+
import '@ithemes/security.user-groups.api';
|
12 |
+
import { ModuleSettingsNoticeList } from '@ithemes/security-components';
|
13 |
+
import './store';
|
14 |
+
import { Layout } from './components';
|
15 |
+
import './style.scss';
|
16 |
+
|
17 |
+
function App( { noticeEl } ) {
|
18 |
+
return (
|
19 |
+
<div className="itsec-user-groups-app">
|
20 |
+
{ createPortal( <ModuleSettingsNoticeList />, noticeEl ) }
|
21 |
+
<Layout />
|
22 |
+
</div>
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
export default App;
|
core/modules/user-groups/entries/settings/components/edit-group-fields/index.js
ADDED
@@ -0,0 +1,17 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import { GroupLabel, PanelRoles, PanelUsers, TabBody } from '../';
|
5 |
+
import './style.scss';
|
6 |
+
|
7 |
+
function EditGroupFields( { groupId, disabled } ) {
|
8 |
+
return (
|
9 |
+
<TabBody.Row name="edit-fields">
|
10 |
+
<GroupLabel groupId={ groupId } disabled={ disabled } />
|
11 |
+
<PanelRoles groupId={ groupId } disabled={ disabled } />
|
12 |
+
<PanelUsers groupId={ groupId } disabled={ disabled } />
|
13 |
+
</TabBody.Row>
|
14 |
+
);
|
15 |
+
}
|
16 |
+
|
17 |
+
export default EditGroupFields;
|
core/modules/user-groups/entries/settings/components/edit-group-fields/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/edit-group-fields/style.scss
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-user-groups-group-tab__row--edit-fields > .components-base-control:first-child {
|
2 |
+
margin-bottom: 16px;
|
3 |
+
}
|
4 |
+
|
5 |
+
.itsec-user-groups-group-tab__row--edit-fields .components-base-control__label {
|
6 |
+
font-weight: 600;
|
7 |
+
margin-bottom: 1em;
|
8 |
+
font-size: 1.2em;
|
9 |
+
}
|
core/modules/user-groups/entries/settings/components/group-header/index.js
ADDED
@@ -0,0 +1,17 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import './style.scss';
|
5 |
+
|
6 |
+
export function GroupHeader( { label, children } ) {
|
7 |
+
return (
|
8 |
+
<div className="itsec-user-group-header">
|
9 |
+
<h4 className="itsec-user-group-header__label">{ label }</h4>
|
10 |
+
{ children }
|
11 |
+
</div>
|
12 |
+
);
|
13 |
+
}
|
14 |
+
|
15 |
+
export SingleGroupHeader from './single';
|
16 |
+
export NewGroupHeader from './new';
|
17 |
+
export MultiGroupHeader from './multi';
|
core/modules/user-groups/entries/settings/components/group-header/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/group-header/multi.js
ADDED
@@ -0,0 +1,22 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect } from '@wordpress/data';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal dependencies
|
9 |
+
*/
|
10 |
+
import { GroupHeader } from './';
|
11 |
+
|
12 |
+
function MultiGroupHeader( { label } ) {
|
13 |
+
return (
|
14 |
+
<GroupHeader label={ label } />
|
15 |
+
);
|
16 |
+
}
|
17 |
+
|
18 |
+
export default compose( [
|
19 |
+
withSelect( ( select, { groupIds } ) => ( {
|
20 |
+
label: groupIds.map( select( 'ithemes-security/user-groups' ).getMatchableLabel ).join( ', ' ),
|
21 |
+
} ) ),
|
22 |
+
] )( MultiGroupHeader );
|
core/modules/user-groups/entries/settings/components/group-header/new.js
ADDED
@@ -0,0 +1,29 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { __ } from '@wordpress/i18n';
|
5 |
+
import { compose } from '@wordpress/compose';
|
6 |
+
import { withSelect } from '@wordpress/data';
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Internal dependencies
|
10 |
+
*/
|
11 |
+
import { GroupHeader } from './';
|
12 |
+
|
13 |
+
function NewGroupHeader( { label } ) {
|
14 |
+
if ( ! label || ! label.length ) {
|
15 |
+
label = __( 'New Group', 'better-wp-security' );
|
16 |
+
}
|
17 |
+
|
18 |
+
return (
|
19 |
+
<GroupHeader label={ label } />
|
20 |
+
);
|
21 |
+
}
|
22 |
+
|
23 |
+
export default compose( [
|
24 |
+
withSelect( ( select ) => {
|
25 |
+
return ( {
|
26 |
+
label: select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( 'new', 'label' ),
|
27 |
+
} );
|
28 |
+
} ),
|
29 |
+
] )( NewGroupHeader );
|
core/modules/user-groups/entries/settings/components/group-header/single.js
ADDED
@@ -0,0 +1,58 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { Button } from '@wordpress/components';
|
7 |
+
import { __ } from '@wordpress/i18n';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { GroupHeader } from './';
|
13 |
+
|
14 |
+
function SingleGroupHeader( { type, label, isDeleting, deleteGroup } ) {
|
15 |
+
const canDelete = type === 'user-group';
|
16 |
+
|
17 |
+
if ( ! label || ! label.length ) {
|
18 |
+
label = __( 'Untitled', 'better-wp-security' );
|
19 |
+
}
|
20 |
+
|
21 |
+
return (
|
22 |
+
<GroupHeader label={ label }>
|
23 |
+
{ canDelete && (
|
24 |
+
<Button onClick={ deleteGroup } isBusy={ isDeleting } isLink isDestructive>
|
25 |
+
{ __( 'Delete Group', 'better-wp-security' ) }
|
26 |
+
</Button>
|
27 |
+
) }
|
28 |
+
</GroupHeader>
|
29 |
+
);
|
30 |
+
}
|
31 |
+
|
32 |
+
export default compose( [
|
33 |
+
withSelect( ( select, { groupId } ) => {
|
34 |
+
const type = select( 'ithemes-security/user-groups' ).getMatchableType( groupId );
|
35 |
+
const isDeleting = type === 'user-group' ? select( 'ithemes-security/user-groups' ).isDeleting( groupId ) : false;
|
36 |
+
|
37 |
+
let label;
|
38 |
+
|
39 |
+
if ( type === 'user-group' ) {
|
40 |
+
label = select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'label' );
|
41 |
+
}
|
42 |
+
|
43 |
+
if ( label === undefined ) {
|
44 |
+
label = select( 'ithemes-security/user-groups' ).getMatchableLabel( groupId );
|
45 |
+
}
|
46 |
+
|
47 |
+
return ( {
|
48 |
+
type,
|
49 |
+
label,
|
50 |
+
isDeleting,
|
51 |
+
} );
|
52 |
+
} ),
|
53 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
54 |
+
deleteGroup() {
|
55 |
+
return dispatch( 'ithemes-security/user-groups' ).deleteGroup( groupId );
|
56 |
+
},
|
57 |
+
} ) ),
|
58 |
+
] )( SingleGroupHeader );
|
core/modules/user-groups/entries/settings/components/group-header/style.scss
ADDED
@@ -0,0 +1,20 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-user-group-header {
|
2 |
+
display: flex;
|
3 |
+
align-items: center;
|
4 |
+
justify-content: space-between;
|
5 |
+
margin-bottom: 1em;
|
6 |
+
height: 1.2em;
|
7 |
+
}
|
8 |
+
|
9 |
+
.itsec-user-group-header__label {
|
10 |
+
margin: 0 .5em 0 0;
|
11 |
+
font-size: 1.2em;
|
12 |
+
line-height: 1.2em;
|
13 |
+
text-overflow: ellipsis;
|
14 |
+
overflow: hidden;
|
15 |
+
white-space: nowrap;
|
16 |
+
}
|
17 |
+
|
18 |
+
.itsec-user-group-header .components-button {
|
19 |
+
flex-shrink: 0;
|
20 |
+
}
|
core/modules/user-groups/entries/settings/components/group-label/index.js
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress Dependencies
|
3 |
+
*/
|
4 |
+
import { TextControl } from '@wordpress/components';
|
5 |
+
import { __ } from '@wordpress/i18n';
|
6 |
+
import { compose } from '@wordpress/compose';
|
7 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import './style.scss';
|
13 |
+
|
14 |
+
function GroupLabel( { label, edit, disabled = false } ) {
|
15 |
+
return (
|
16 |
+
<TextControl
|
17 |
+
label={ __( 'Group Name', 'better-wp-security' ) }
|
18 |
+
value={ label }
|
19 |
+
maxLength={ 50 }
|
20 |
+
disabled={ disabled }
|
21 |
+
onChange={ ( newLabel ) => edit( { label: newLabel } ) } />
|
22 |
+
);
|
23 |
+
}
|
24 |
+
|
25 |
+
export default compose( [
|
26 |
+
withSelect( ( select, { groupId } ) => ( {
|
27 |
+
label: select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'label' ) || '',
|
28 |
+
} ) ),
|
29 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
30 |
+
edit( edit ) {
|
31 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).editGroup( groupId, edit );
|
32 |
+
},
|
33 |
+
} ) ),
|
34 |
+
] )( GroupLabel );
|
core/modules/user-groups/entries/settings/components/group-label/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/group-label/style.scss
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-user-group-label h4 {
|
2 |
+
margin-top: 0;
|
3 |
+
}
|
core/modules/user-groups/entries/settings/components/group-nav/index.js
ADDED
@@ -0,0 +1,111 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import memize from 'memize';
|
5 |
+
import { filter } from 'lodash';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { compose } from '@wordpress/compose';
|
11 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
12 |
+
import { Icon } from '@wordpress/components';
|
13 |
+
import { __ } from '@wordpress/i18n';
|
14 |
+
import { Fragment, useEffect } from '@wordpress/element';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Internal dependencies
|
18 |
+
*/
|
19 |
+
import { ControlledMultiTabPanel } from '@ithemes/security-components';
|
20 |
+
import { ManageGroup, ManageMultipleGroups } from '../';
|
21 |
+
import './style.scss';
|
22 |
+
|
23 |
+
const convertToTabs = memize( ( groups ) => groups
|
24 |
+
.sort( ( groupA, groupB ) => {
|
25 |
+
if ( groupA.type === groupB.type ) {
|
26 |
+
return 0;
|
27 |
+
}
|
28 |
+
|
29 |
+
if ( groupA.type === 'user-group' ) {
|
30 |
+
return -1;
|
31 |
+
}
|
32 |
+
|
33 |
+
if ( groupB.type === 'user-group' ) {
|
34 |
+
return 1;
|
35 |
+
}
|
36 |
+
|
37 |
+
return 0;
|
38 |
+
} )
|
39 |
+
.map( ( group ) => ( {
|
40 |
+
name: group.id,
|
41 |
+
title: group.label,
|
42 |
+
className: 'itsec-user-groups-list__item',
|
43 |
+
group,
|
44 |
+
} ) )
|
45 |
+
.concat( {
|
46 |
+
name: 'new',
|
47 |
+
title: (
|
48 |
+
<Fragment>
|
49 |
+
<Icon icon="plus" />
|
50 |
+
{ __( 'New Group', 'better-wp-security' ) }
|
51 |
+
</Fragment>
|
52 |
+
),
|
53 |
+
className: 'itsec-user-groups-list__item itsec-user-groups-list__item--new',
|
54 |
+
allowMultiple: false,
|
55 |
+
} )
|
56 |
+
);
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Group Navigation component.
|
60 |
+
*
|
61 |
+
* @return {Element|null}
|
62 |
+
*/
|
63 |
+
function GroupNav( { matchables, resolvingMatchables, selectedGroup, selectGroup } ) {
|
64 |
+
useEffect( () => {
|
65 |
+
if ( ! resolvingMatchables && matchables.length && selectedGroup.length === 0 ) {
|
66 |
+
selectGroup( [ matchables[ 0 ].id ] );
|
67 |
+
}
|
68 |
+
}, [ resolvingMatchables ] );
|
69 |
+
|
70 |
+
if ( resolvingMatchables && ! matchables.length ) {
|
71 |
+
return null;
|
72 |
+
}
|
73 |
+
|
74 |
+
const tabs = convertToTabs( matchables );
|
75 |
+
|
76 |
+
return (
|
77 |
+
<ControlledMultiTabPanel
|
78 |
+
tabs={ tabs }
|
79 |
+
selected={ selectedGroup }
|
80 |
+
onSelect={ selectGroup }
|
81 |
+
allowMultiple
|
82 |
+
orientation="vertical"
|
83 |
+
className="itsec-user-groups-list"
|
84 |
+
>
|
85 |
+
{ ( selectedTabs ) => {
|
86 |
+
if ( selectedTabs.length > 1 ) {
|
87 |
+
const groupIds = filter( selectedTabs.map( ( { group } ) => group && group.id ) );
|
88 |
+
|
89 |
+
return <ManageMultipleGroups groupIds={ groupIds } />;
|
90 |
+
}
|
91 |
+
|
92 |
+
if ( selectedTabs[ 0 ] ) {
|
93 |
+
return <ManageGroup groupId={ selectedTabs[ 0 ].name } isNew={ selectedTabs[ 0 ].name === 'new' } />;
|
94 |
+
}
|
95 |
+
|
96 |
+
return null;
|
97 |
+
} }
|
98 |
+
</ControlledMultiTabPanel>
|
99 |
+
);
|
100 |
+
}
|
101 |
+
|
102 |
+
export default compose( [
|
103 |
+
withSelect( ( select ) => ( {
|
104 |
+
matchables: select( 'ithemes-security/user-groups' ).getMatchables(),
|
105 |
+
resolvingMatchables: select( 'core/data' ).isResolving( 'ithemes-security/user-groups', 'getMatchables' ),
|
106 |
+
selectedGroup: select( 'ithemes-security/user-groups-editor' ).getSelectedGroup(),
|
107 |
+
} ) ),
|
108 |
+
withDispatch( ( dispatch ) => ( {
|
109 |
+
selectGroup: dispatch( 'ithemes-security/user-groups-editor' ).selectGroup,
|
110 |
+
} ) ),
|
111 |
+
] )( GroupNav );
|
core/modules/user-groups/entries/settings/components/group-nav/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/group-nav/style.scss
ADDED
@@ -0,0 +1,46 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@import "colors.scss";
|
2 |
+
|
3 |
+
.itsec-user-groups-list {
|
4 |
+
display: grid;
|
5 |
+
grid-template-columns: 200px minmax(0, auto);
|
6 |
+
grid-gap: 1.25em;
|
7 |
+
padding-bottom: 2em;
|
8 |
+
|
9 |
+
& > .components-tab-panel__tabs {
|
10 |
+
display: flex;
|
11 |
+
flex-direction: column;
|
12 |
+
margin-top: 2.2em; // Matches .itsec-manage-user-group__label
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
.itsec-user-groups-list__item {
|
17 |
+
padding: 1em .5em;
|
18 |
+
margin: 1.25em 0 0;
|
19 |
+
border: 1px solid $dark-gray-200;
|
20 |
+
border-radius: 4px;
|
21 |
+
text-align: left;
|
22 |
+
height: auto;
|
23 |
+
|
24 |
+
&.is-active {
|
25 |
+
border-color: $blue-medium-focus;
|
26 |
+
box-shadow: 0 0 0 1px $blue-medium-focus;
|
27 |
+
outline: 2px solid transparent;
|
28 |
+
}
|
29 |
+
|
30 |
+
&:first-child {
|
31 |
+
margin-top: 0;
|
32 |
+
}
|
33 |
+
|
34 |
+
&:last-child {
|
35 |
+
margin-bottom: 0;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
.itsec-user-groups-list__item--new {
|
40 |
+
justify-content: center;
|
41 |
+
align-items: center;
|
42 |
+
|
43 |
+
& .dashicon {
|
44 |
+
margin-right: 10px;
|
45 |
+
}
|
46 |
+
}
|
core/modules/user-groups/entries/settings/components/index.js
ADDED
@@ -0,0 +1,16 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
export { default as Layout } from './layout';
|
2 |
+
export { default as GroupNav } from './group-nav';
|
3 |
+
export { default as ManageGroup } from './manage-group';
|
4 |
+
export { default as ManageMultipleGroups } from './manage-multiple-groups';
|
5 |
+
export { default as GroupLabel } from './group-label';
|
6 |
+
export { default as TabBody } from './tab-body';
|
7 |
+
export { default as TabCreateGroup } from './tab-create-group';
|
8 |
+
export { default as TabEditGroup } from './tab-edit-group';
|
9 |
+
export { default as TabSettings } from './tab-settings';
|
10 |
+
export { default as TabSettingsBulk } from './tab-settings-bulk';
|
11 |
+
export { default as PanelMinimumRole } from './panel-minimum-role';
|
12 |
+
export { default as PanelRoles } from './panel-roles';
|
13 |
+
export { default as PanelUsers } from './panel-users';
|
14 |
+
export { NewGroupHeader, SingleGroupHeader, MultiGroupHeader } from './group-header';
|
15 |
+
export { default as EditGroupFields } from './edit-group-fields';
|
16 |
+
export { default as SettingsForm } from './settings-form';
|
core/modules/user-groups/entries/settings/components/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/layout/index.js
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
import { GroupNav } from '../';
|
2 |
+
|
3 |
+
export default function Layout() {
|
4 |
+
return (
|
5 |
+
<div>
|
6 |
+
<GroupNav />
|
7 |
+
</div>
|
8 |
+
);
|
9 |
+
}
|
core/modules/user-groups/entries/settings/components/layout/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/manage-group/index.js
ADDED
@@ -0,0 +1,70 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import memize from 'memize';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { __ } from '@wordpress/i18n';
|
10 |
+
import { compose } from '@wordpress/compose';
|
11 |
+
import { withSelect } from '@wordpress/data';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Internal dependencies
|
15 |
+
*/
|
16 |
+
import { TabPanel } from '@ithemes/security-components';
|
17 |
+
import { TabCreateGroup, TabEditGroup, TabSettings, NewGroupHeader, SingleGroupHeader } from '../';
|
18 |
+
import './style.scss';
|
19 |
+
|
20 |
+
const getTabs = memize( ( groupId, type ) => {
|
21 |
+
if ( groupId === 'new' ) {
|
22 |
+
return [
|
23 |
+
{
|
24 |
+
name: 'create',
|
25 |
+
title: __( 'Edit Group', 'better-wp-security' ),
|
26 |
+
className: 'itsec-manage-user-group-tabs__tab',
|
27 |
+
Component: TabCreateGroup,
|
28 |
+
},
|
29 |
+
];
|
30 |
+
}
|
31 |
+
|
32 |
+
const tabs = [
|
33 |
+
{
|
34 |
+
name: 'settings',
|
35 |
+
title: __( 'Features', 'better-wp-security' ),
|
36 |
+
className: 'itsec-manage-user-group-tabs__tab',
|
37 |
+
Component: TabSettings,
|
38 |
+
},
|
39 |
+
];
|
40 |
+
|
41 |
+
if ( type === 'user-group' ) {
|
42 |
+
tabs.push( {
|
43 |
+
name: 'edit',
|
44 |
+
title: __( 'Edit Group', 'better-wp-security' ),
|
45 |
+
className: 'itsec-manage-user-group-tabs__tab',
|
46 |
+
Component: TabEditGroup,
|
47 |
+
} );
|
48 |
+
}
|
49 |
+
|
50 |
+
return tabs;
|
51 |
+
} );
|
52 |
+
|
53 |
+
function ManageGroup( { groupId, type, isNew } ) {
|
54 |
+
return (
|
55 |
+
<div className="itsec-manage-user-group">
|
56 |
+
{ isNew ? <NewGroupHeader /> : <SingleGroupHeader groupId={ groupId } /> }
|
57 |
+
<TabPanel tabs={ getTabs( groupId, type ) } className="itsec-manage-user-group-tabs">
|
58 |
+
{ ( { Component } ) => (
|
59 |
+
<Component groupId={ groupId } />
|
60 |
+
) }
|
61 |
+
</TabPanel>
|
62 |
+
</div>
|
63 |
+
);
|
64 |
+
}
|
65 |
+
|
66 |
+
export default compose( [
|
67 |
+
withSelect( ( select, { groupId } ) => ( {
|
68 |
+
type: select( 'ithemes-security/user-groups' ).getMatchableType( groupId ),
|
69 |
+
} ) ),
|
70 |
+
] )( ManageGroup );
|
core/modules/user-groups/entries/settings/components/manage-group/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/manage-group/style.scss
ADDED
@@ -0,0 +1,51 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@import "colors.scss";
|
2 |
+
|
3 |
+
.itsec-manage-user-group-tabs {
|
4 |
+
border: 1px solid $dark-gray-200;
|
5 |
+
border-radius: 4px;
|
6 |
+
}
|
7 |
+
|
8 |
+
.itsec-manage-user-group-tabs .components-tab-panel__tabs {
|
9 |
+
background: $light-gray-200;
|
10 |
+
border-radius: 4px 4px 0 0;
|
11 |
+
display: flex;
|
12 |
+
flex-basis: 0;
|
13 |
+
}
|
14 |
+
|
15 |
+
.itsec-manage-user-group-tabs__tab.components-button {
|
16 |
+
flex-grow: 1;
|
17 |
+
flex-basis: 0;
|
18 |
+
height: 40px;
|
19 |
+
padding: 3px 15px 0;
|
20 |
+
border-bottom: 1px solid $dark-gray-200;
|
21 |
+
border-right: 1px solid $dark-gray-200;
|
22 |
+
cursor: pointer;
|
23 |
+
font-weight: 400;
|
24 |
+
justify-content: center;
|
25 |
+
align-items: center;
|
26 |
+
text-transform: uppercase;
|
27 |
+
outline-offset: -1px;
|
28 |
+
border-radius: 0;
|
29 |
+
|
30 |
+
&:hover {
|
31 |
+
box-shadow: none !important;
|
32 |
+
}
|
33 |
+
|
34 |
+
&:first-child {
|
35 |
+
border-top-left-radius: 3px;
|
36 |
+
}
|
37 |
+
|
38 |
+
&:last-child {
|
39 |
+
border-top-right-radius: 3px;
|
40 |
+
border-right: none;
|
41 |
+
}
|
42 |
+
|
43 |
+
&.is-active {
|
44 |
+
padding-top: 0;
|
45 |
+
background: white;
|
46 |
+
border-top: 3px solid $main-blue;
|
47 |
+
border-bottom-color: transparent;
|
48 |
+
font-weight: 600;
|
49 |
+
outline: none;
|
50 |
+
}
|
51 |
+
}
|
core/modules/user-groups/entries/settings/components/manage-multiple-groups/index.js
ADDED
@@ -0,0 +1,39 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import memize from 'memize';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { __ } from '@wordpress/i18n';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Internal dependencies
|
13 |
+
*/
|
14 |
+
import { TabPanel } from '@ithemes/security-components';
|
15 |
+
import { MultiGroupHeader, TabSettingsBulk } from '../';
|
16 |
+
|
17 |
+
const getTabs = memize( () => ( [
|
18 |
+
{
|
19 |
+
name: 'settings',
|
20 |
+
title: __( 'Features', 'better-wp-security' ),
|
21 |
+
className: 'itsec-manage-user-group-tabs__tab',
|
22 |
+
Component: TabSettingsBulk,
|
23 |
+
},
|
24 |
+
] ) );
|
25 |
+
|
26 |
+
function ManageMultipleGroups( { groupIds } ) {
|
27 |
+
return (
|
28 |
+
<div className="itsec-manage-multiple-user-groups">
|
29 |
+
<MultiGroupHeader groupIds={ groupIds } />
|
30 |
+
<TabPanel tabs={ getTabs() } className="itsec-manage-user-group-tabs">
|
31 |
+
{ ( { Component } ) => (
|
32 |
+
<Component groupIds={ groupIds } />
|
33 |
+
) }
|
34 |
+
</TabPanel>
|
35 |
+
</div>
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
+
export default ManageMultipleGroups;
|
core/modules/user-groups/entries/settings/components/manage-multiple-groups/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/panel-minimum-role/index.js
ADDED
@@ -0,0 +1,36 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { SelectControl } from '@wordpress/components';
|
5 |
+
import { __ } from '@wordpress/i18n';
|
6 |
+
import { compose } from '@wordpress/compose';
|
7 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { getCanonicalRoles } from '@ithemes/security-i18n';
|
13 |
+
|
14 |
+
function PanelMinimumRole( { minRole, onChange } ) {
|
15 |
+
return (
|
16 |
+
<div>
|
17 |
+
<SelectControl
|
18 |
+
options={ getCanonicalRoles() }
|
19 |
+
label={ __( 'Minimum Role', 'better-wp-security' ) }
|
20 |
+
value={ minRole }
|
21 |
+
onChange={ ( newMinRole ) => onChange( { min_role: newMinRole } ) }
|
22 |
+
help={ __( 'Add users with the selected minimum role to this group. To edit roles, go to Users in your WordPress Dashboard.', 'better-wp-security' ) } />
|
23 |
+
</div>
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
export default compose( [
|
28 |
+
withSelect( ( select, { groupId } ) => ( {
|
29 |
+
minRole: select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'min_role' ),
|
30 |
+
} ) ),
|
31 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
32 |
+
onChange( edit ) {
|
33 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).editGroup( groupId, edit );
|
34 |
+
},
|
35 |
+
} ) ),
|
36 |
+
] )( PanelMinimumRole );
|
core/modules/user-groups/entries/settings/components/panel-minimum-role/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/panel-roles/index.js
ADDED
@@ -0,0 +1,114 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import memize from 'memize';
|
5 |
+
import { without, some, get } from 'lodash';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { compose } from '@wordpress/compose';
|
11 |
+
import { withDispatch, withSelect } from '@wordpress/data';
|
12 |
+
import { __ } from '@wordpress/i18n';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Internal dependencies
|
16 |
+
*/
|
17 |
+
import { HierarchicalCheckboxControl } from '@ithemes/security-components';
|
18 |
+
import { bifurcate } from '@ithemes/security-utils';
|
19 |
+
|
20 |
+
const toCanonicalGroup = memize( ( availableRoles, includeSuperAdmin ) => {
|
21 |
+
const group = [
|
22 |
+
{
|
23 |
+
value: '$administrator$',
|
24 |
+
label: __( 'Administrator Capabilities', 'better-wp-security' ),
|
25 |
+
},
|
26 |
+
{
|
27 |
+
value: '$editor$',
|
28 |
+
label: __( 'Editor Capabilities', 'better-wp-security' ),
|
29 |
+
},
|
30 |
+
{
|
31 |
+
value: '$author$',
|
32 |
+
label: __( 'Author Capabilities', 'better-wp-security' ),
|
33 |
+
},
|
34 |
+
{
|
35 |
+
value: '$contributor$',
|
36 |
+
label: __( 'Contributor Capabilities', 'better-wp-security' ),
|
37 |
+
},
|
38 |
+
{
|
39 |
+
value: '$subscriber$',
|
40 |
+
label: __( 'Subscriber Capabilities', 'better-wp-security' ),
|
41 |
+
},
|
42 |
+
];
|
43 |
+
|
44 |
+
if ( includeSuperAdmin ) {
|
45 |
+
group.unshift( {
|
46 |
+
value: '$super-admin$',
|
47 |
+
label: __( 'Super Admin', 'better-wp-security' ),
|
48 |
+
} );
|
49 |
+
}
|
50 |
+
|
51 |
+
if ( some( availableRoles, ( role ) => role.canonical === '' ) ) {
|
52 |
+
group.push( {
|
53 |
+
value: '$other$',
|
54 |
+
label: __( 'Other', 'better-wp-security' ),
|
55 |
+
selectable: false,
|
56 |
+
} );
|
57 |
+
}
|
58 |
+
|
59 |
+
for ( const role in availableRoles ) {
|
60 |
+
if ( ! availableRoles.hasOwnProperty( role ) ) {
|
61 |
+
continue;
|
62 |
+
}
|
63 |
+
|
64 |
+
const { canonical, label } = availableRoles[ role ];
|
65 |
+
|
66 |
+
group.push( {
|
67 |
+
value: role,
|
68 |
+
parent: canonical.length > 0 ? `$${ canonical }$` : '$other$',
|
69 |
+
label,
|
70 |
+
} );
|
71 |
+
}
|
72 |
+
|
73 |
+
return Object.values( group );
|
74 |
+
} );
|
75 |
+
|
76 |
+
function PanelRoles( { canonical, roles, onChange, available, schema, disabled = false } ) {
|
77 |
+
const includeSuperAdmin = get( schema, [ 'properties', 'canonical', 'items', 'enum' ], [] ).includes( 'super-admin' );
|
78 |
+
const value = [
|
79 |
+
...roles,
|
80 |
+
...canonical.map( ( role ) => `$${ role }$` ),
|
81 |
+
];
|
82 |
+
|
83 |
+
return (
|
84 |
+
<HierarchicalCheckboxControl
|
85 |
+
label={ __( 'Select Roles', 'better-wp-security' ) }
|
86 |
+
help={ __( 'Add users with the selected roles to this group.', 'better-wp-security' ) }
|
87 |
+
value={ value }
|
88 |
+
disabled={ disabled }
|
89 |
+
options={ toCanonicalGroup( available, includeSuperAdmin ) }
|
90 |
+
onChange={ ( change ) => {
|
91 |
+
const [ newCanonical, newRoles ] = bifurcate( change, ( role ) => role.startsWith( '$' ) && role.endsWith( '$' ) );
|
92 |
+
|
93 |
+
onChange( {
|
94 |
+
roles: newRoles,
|
95 |
+
canonical: without( newCanonical.map( ( role ) => role.slice( 1, -1 ) ), 'other' ),
|
96 |
+
} );
|
97 |
+
} }
|
98 |
+
/>
|
99 |
+
);
|
100 |
+
}
|
101 |
+
|
102 |
+
export default compose( [
|
103 |
+
withSelect( ( select, { groupId } ) => ( {
|
104 |
+
roles: select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'roles' ) || [],
|
105 |
+
canonical: select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'canonical' ) || [],
|
106 |
+
available: select( 'ithemes-security/core' ).getRoles(),
|
107 |
+
schema: select( 'ithemes-security/core' ).getSchema( 'ithemes-security-user-group' ),
|
108 |
+
} ) ),
|
109 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
110 |
+
onChange( edit ) {
|
111 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).editGroup( groupId, edit );
|
112 |
+
},
|
113 |
+
} ) ),
|
114 |
+
] )( PanelRoles );
|
core/modules/user-groups/entries/settings/components/panel-roles/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/panel-users/index.js
ADDED
@@ -0,0 +1,90 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { map } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import apiFetch from '@wordpress/api-fetch';
|
10 |
+
import { addQueryArgs } from '@wordpress/url';
|
11 |
+
import { compose, withState, withInstanceId } from '@wordpress/compose';
|
12 |
+
import { withDispatch, withSelect, dispatch as dataDispatch } from '@wordpress/data';
|
13 |
+
import { __ } from '@wordpress/i18n';
|
14 |
+
import { BaseControl } from '@wordpress/components';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Internal dependencies
|
18 |
+
*/
|
19 |
+
import { AsyncSelect } from '@ithemes/security-components';
|
20 |
+
import './style.scss';
|
21 |
+
|
22 |
+
function formatUser( user ) {
|
23 |
+
return { value: user.id, label: user.name, user };
|
24 |
+
}
|
25 |
+
|
26 |
+
const loadUsers = ( search ) => new Promise( ( resolve, reject ) => {
|
27 |
+
apiFetch( { path: addQueryArgs( '/wp/v2/users', { search, per_page: 100, context: 'embed', itsec_global: true } ) } )
|
28 |
+
.then( ( response ) => {
|
29 |
+
response.forEach( dataDispatch( 'ithemes-security/core' ).receiveUser );
|
30 |
+
|
31 |
+
return response;
|
32 |
+
} )
|
33 |
+
.then( ( response ) => resolve( response.map( formatUser ) ) )
|
34 |
+
.catch( reject );
|
35 |
+
} );
|
36 |
+
|
37 |
+
function PanelUsers( { instanceId, users, loading, onChange, disabled = false, selectSearch, setState } ) {
|
38 |
+
const selectId = `itsec-user-group-panel-users__select-${ instanceId }`;
|
39 |
+
const values = loading ? [] : users.map( formatUser );
|
40 |
+
|
41 |
+
return (
|
42 |
+
<BaseControl className="itsec-user-group-panel-users__select-control"
|
43 |
+
label={ __( 'Select Users', 'better-wp-security' ) }
|
44 |
+
help={ __( 'Select specific users to add to this group.', 'better-wp-security' ) }
|
45 |
+
id={ selectId }>
|
46 |
+
<AsyncSelect
|
47 |
+
classNamePrefix="components-itsec-async-select-control"
|
48 |
+
inputId={ selectId }
|
49 |
+
isDisabled={ disabled || loading } isLoading={ loading }
|
50 |
+
isMulti
|
51 |
+
cacheOptions defaultOptions loadOptions={ loadUsers }
|
52 |
+
value={ values } onChange={ ( newUsers ) => onChange( { users: map( newUsers, 'value' ) } ) }
|
53 |
+
inputValue={ selectSearch } onInputChange={ ( newSelect ) => setState( { selectSearch: newSelect } ) }
|
54 |
+
/>
|
55 |
+
</BaseControl>
|
56 |
+
);
|
57 |
+
}
|
58 |
+
|
59 |
+
export default compose( [
|
60 |
+
withState( { selectSearch: '' } ),
|
61 |
+
withSelect( ( select, { groupId } ) => {
|
62 |
+
const userIds = select( 'ithemes-security/user-groups-editor' ).getEditedGroupAttribute( groupId, 'users' ) || [];
|
63 |
+
const users = [];
|
64 |
+
let loading = false;
|
65 |
+
|
66 |
+
userIds.forEach( ( userId ) => {
|
67 |
+
const user = select( 'ithemes-security/core' ).getUser( userId );
|
68 |
+
|
69 |
+
if ( user ) {
|
70 |
+
users.push( user );
|
71 |
+
} else if ( select( 'core/data' ).isResolving( 'ithemes-security/core', 'getUser', [ userId ] ) ) {
|
72 |
+
loading = true;
|
73 |
+
}
|
74 |
+
} );
|
75 |
+
|
76 |
+
return ( {
|
77 |
+
users,
|
78 |
+
userIds,
|
79 |
+
loading,
|
80 |
+
} );
|
81 |
+
} ),
|
82 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
83 |
+
receiveUser: dispatch( 'ithemes-security/core' ).receiveUser,
|
84 |
+
onChange( edit ) {
|
85 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).editGroup( groupId, edit );
|
86 |
+
},
|
87 |
+
} ) ),
|
88 |
+
withInstanceId,
|
89 |
+
] )( PanelUsers );
|
90 |
+
|
core/modules/user-groups/entries/settings/components/panel-users/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/panel-users/style.scss
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-user-group-panel-users__selected span {
|
2 |
+
padding-right: .5em;
|
3 |
+
}
|
4 |
+
|
5 |
+
.components-itsec-async-select-control__input input {
|
6 |
+
min-height: 0;
|
7 |
+
|
8 |
+
&:focus {
|
9 |
+
box-shadow: none;
|
10 |
+
}
|
11 |
+
}
|
core/modules/user-groups/entries/settings/components/settings-form/index.js
ADDED
@@ -0,0 +1,25 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { map } from 'lodash';
|
5 |
+
|
6 |
+
export default function SettingsForm( { schema, settingComponent: SettingComponent, ...props } ) {
|
7 |
+
return (
|
8 |
+
<ul className="itsec-user-groups-group-tab__modules-list">
|
9 |
+
{ map( schema.properties, ( moduleSchema, module ) => (
|
10 |
+
<li key={ module }>
|
11 |
+
<fieldset>
|
12 |
+
<legend>{ moduleSchema.title }</legend>
|
13 |
+
<ul>
|
14 |
+
{ map( moduleSchema.properties, ( settingSchema, setting ) => (
|
15 |
+
<li key={ setting }>
|
16 |
+
<SettingComponent schema={ settingSchema } module={ module } setting={ setting } { ...props } />
|
17 |
+
</li>
|
18 |
+
) ) }
|
19 |
+
</ul>
|
20 |
+
</fieldset>
|
21 |
+
</li>
|
22 |
+
) ) }
|
23 |
+
</ul>
|
24 |
+
);
|
25 |
+
}
|
core/modules/user-groups/entries/settings/components/settings-form/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-body/index.js
ADDED
@@ -0,0 +1,30 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import classnames from 'classnames';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import './style.scss';
|
10 |
+
|
11 |
+
TabBody.Row = function( { name, children } ) {
|
12 |
+
return (
|
13 |
+
<div className={ `itsec-user-groups-group-tab__row itsec-user-groups-group-tab__row--${ name }` }>
|
14 |
+
{ children }
|
15 |
+
</div>
|
16 |
+
);
|
17 |
+
};
|
18 |
+
|
19 |
+
export default function TabBody( { name, isLoading, children } ) {
|
20 |
+
const className = classnames( 'itsec-user-groups-group-tab', {
|
21 |
+
[ `itsec-user-groups-group-tab--${ name }` ]: name,
|
22 |
+
'itsec-user-groups-group-tab--is-loading': isLoading,
|
23 |
+
} );
|
24 |
+
|
25 |
+
return (
|
26 |
+
<div className={ className }>
|
27 |
+
{ children }
|
28 |
+
</div>
|
29 |
+
);
|
30 |
+
}
|
core/modules/user-groups/entries/settings/components/tab-body/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-body/style.scss
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@import "colors.scss";
|
2 |
+
|
3 |
+
.itsec-user-groups-group-tab__row {
|
4 |
+
padding: 1em;
|
5 |
+
}
|
6 |
+
|
7 |
+
.itsec-user-groups-group-tab__row--save {
|
8 |
+
border-top: 1px solid $dark-gray-200;
|
9 |
+
text-align: right;
|
10 |
+
}
|
11 |
+
|
12 |
+
.itsec-user-groups-group-tab--is-loading {
|
13 |
+
opacity: .5;
|
14 |
+
pointer-events: none;
|
15 |
+
}
|
core/modules/user-groups/entries/settings/components/tab-create-group/index.js
ADDED
@@ -0,0 +1,37 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { Button } from '@wordpress/components';
|
7 |
+
import { __ } from '@wordpress/i18n';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { EditGroupFields, TabBody } from '../';
|
13 |
+
|
14 |
+
function TabCreateGroup( { hasEdits, save, isSaving } ) {
|
15 |
+
return (
|
16 |
+
<TabBody name="create-group">
|
17 |
+
<EditGroupFields groupId="new" />
|
18 |
+
<TabBody.Row name="save">
|
19 |
+
<Button disabled={ ! hasEdits } isPrimary onClick={ save } isBusy={ isSaving }>
|
20 |
+
{ __( 'Create', 'better-wp-security' ) }
|
21 |
+
</Button>
|
22 |
+
</TabBody.Row>
|
23 |
+
</TabBody>
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
export default compose( [
|
28 |
+
withSelect( ( select ) => ( {
|
29 |
+
hasEdits: select( 'ithemes-security/user-groups-editor' ).hasEdits( 'new' ),
|
30 |
+
isSaving: select( 'ithemes-security/user-groups-editor' ).isCreating( 'new' ),
|
31 |
+
} ) ),
|
32 |
+
withDispatch( ( dispatch ) => ( {
|
33 |
+
save() {
|
34 |
+
dispatch( 'ithemes-security/user-groups-editor' ).createGroup();
|
35 |
+
},
|
36 |
+
} ) ),
|
37 |
+
] )( TabCreateGroup );
|
core/modules/user-groups/entries/settings/components/tab-create-group/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-edit-group/index.js
ADDED
@@ -0,0 +1,39 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { Button } from '@wordpress/components';
|
7 |
+
import { __ } from '@wordpress/i18n';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { EditGroupFields, TabBody } from '../';
|
13 |
+
|
14 |
+
function TabEditGroup( { groupId, hasEdits, save, isSaving, isLoading } ) {
|
15 |
+
return (
|
16 |
+
<TabBody name="edit-group" isLoading={ isLoading }>
|
17 |
+
<EditGroupFields groupId={ groupId } disabled={ isLoading } />
|
18 |
+
<TabBody.Row name="save">
|
19 |
+
<Button disabled={ ! hasEdits } isPrimary onClick={ save } isBusy={ isSaving }>
|
20 |
+
{ __( 'Save', 'better-wp-security' ) }
|
21 |
+
</Button>
|
22 |
+
</TabBody.Row>
|
23 |
+
</TabBody>
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
export default compose( [
|
28 |
+
withSelect( ( select, { groupId } ) => ( {
|
29 |
+
isLoading: select( 'core/data' ).isResolving( 'ithemes-security/user-groups', 'getGroup', [ groupId ] ) ||
|
30 |
+
select( 'core/data' ).isResolving( 'ithemes-security/core', 'getIndex' ),
|
31 |
+
hasEdits: select( 'ithemes-security/user-groups-editor' ).hasEdits( groupId ),
|
32 |
+
isSaving: select( 'ithemes-security/user-groups' ).isUpdating( groupId ),
|
33 |
+
} ) ),
|
34 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
35 |
+
save() {
|
36 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).saveGroup( groupId );
|
37 |
+
},
|
38 |
+
} ) ),
|
39 |
+
] )( TabEditGroup );
|
core/modules/user-groups/entries/settings/components/tab-edit-group/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-settings-bulk/field.js
ADDED
@@ -0,0 +1,33 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal dependencies
|
9 |
+
*/
|
10 |
+
import { CheckboxControl } from '@ithemes/security-components';
|
11 |
+
|
12 |
+
function Field( { schema, value, edit, disabled = false } ) {
|
13 |
+
return (
|
14 |
+
<CheckboxControl
|
15 |
+
checked={ value === true }
|
16 |
+
indeterminate={ value === null || value === undefined }
|
17 |
+
label={ schema.title }
|
18 |
+
help={ schema.description }
|
19 |
+
disabled={ disabled }
|
20 |
+
onChange={ ( checked ) => edit( checked ) } />
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
export default compose( [
|
25 |
+
withSelect( ( select, { module, setting, groupIds } ) => ( {
|
26 |
+
value: select( 'ithemes-security/user-groups-editor' ).getBulkSettingValue( groupIds, module, setting ),
|
27 |
+
} ) ),
|
28 |
+
withDispatch( ( dispatch, { module, setting } ) => ( {
|
29 |
+
edit( value ) {
|
30 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).bulkEditGroupSetting( module, setting, value );
|
31 |
+
},
|
32 |
+
} ) ),
|
33 |
+
] )( Field );
|
core/modules/user-groups/entries/settings/components/tab-settings-bulk/index.js
ADDED
@@ -0,0 +1,47 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { Button } from '@wordpress/components';
|
7 |
+
import { __ } from '@wordpress/i18n';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { TabBody, SettingsForm } from '../';
|
13 |
+
import Field from './field';
|
14 |
+
|
15 |
+
function TabSettingsBulk( { schema, hasEdits, save, isSaving, groupIds } ) {
|
16 |
+
if ( ! schema ) {
|
17 |
+
return null;
|
18 |
+
}
|
19 |
+
|
20 |
+
return (
|
21 |
+
<TabBody name="settings">
|
22 |
+
<TabBody.Row>
|
23 |
+
<SettingsForm schema={ schema } settingComponent={ Field } groupIds={ groupIds } />
|
24 |
+
</TabBody.Row>
|
25 |
+
<TabBody.Row name="save">
|
26 |
+
<Button disabled={ ! hasEdits } isPrimary onClick={ save } isBusy={ isSaving }>
|
27 |
+
{ __( 'Save', 'better-wp-security' ) }
|
28 |
+
</Button>
|
29 |
+
</TabBody.Row>
|
30 |
+
</TabBody>
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
export default compose( [
|
35 |
+
withSelect( ( select, { groupIds } ) => {
|
36 |
+
return ( {
|
37 |
+
schema: select( 'ithemes-security/core' ).getSchema( 'ithemes-security-user-group-settings' ),
|
38 |
+
hasEdits: select( 'ithemes-security/user-groups-editor' ).hasBulkSettingEdits(),
|
39 |
+
isSaving: select( 'ithemes-security/user-groups-editor' ).isSavingBulkEdits( groupIds ),
|
40 |
+
} );
|
41 |
+
} ),
|
42 |
+
withDispatch( ( dispatch, { groupIds } ) => ( {
|
43 |
+
save() {
|
44 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).saveBulkEdits( groupIds );
|
45 |
+
},
|
46 |
+
} ) ),
|
47 |
+
] )( TabSettingsBulk );
|
core/modules/user-groups/entries/settings/components/tab-settings-bulk/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-settings/field.js
ADDED
@@ -0,0 +1,29 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { ToggleControl } from '@wordpress/components';
|
7 |
+
|
8 |
+
function Field( { schema, value, edit, disabled = false } ) {
|
9 |
+
return (
|
10 |
+
<ToggleControl
|
11 |
+
checked={ value === true }
|
12 |
+
label={ schema.title }
|
13 |
+
help={ schema.description }
|
14 |
+
disabled={ disabled }
|
15 |
+
onChange={ ( checked ) => edit( checked ) } />
|
16 |
+
);
|
17 |
+
}
|
18 |
+
|
19 |
+
export default compose( [
|
20 |
+
withSelect( ( select, { groupId, module, setting } ) => ( {
|
21 |
+
value: select( 'ithemes-security/user-groups-editor' ).getEditedGroupSetting( groupId, module, setting ),
|
22 |
+
} ) ),
|
23 |
+
withDispatch( ( dispatch, { groupId, module, setting } ) => ( {
|
24 |
+
edit( value ) {
|
25 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).editGroupSetting( groupId, module, setting, value );
|
26 |
+
},
|
27 |
+
} ) ),
|
28 |
+
] )( Field );
|
29 |
+
|
core/modules/user-groups/entries/settings/components/tab-settings/index.js
ADDED
@@ -0,0 +1,48 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { compose } from '@wordpress/compose';
|
5 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6 |
+
import { Button } from '@wordpress/components';
|
7 |
+
import { __ } from '@wordpress/i18n';
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Internal dependencies
|
11 |
+
*/
|
12 |
+
import { TabBody, SettingsForm } from '../';
|
13 |
+
import Field from './field';
|
14 |
+
import './style.scss';
|
15 |
+
|
16 |
+
function TabSettings( { schema, groupId, hasEdits, save, isSaving, isLoading } ) {
|
17 |
+
if ( ! schema ) {
|
18 |
+
return null;
|
19 |
+
}
|
20 |
+
|
21 |
+
return (
|
22 |
+
<TabBody name="settings" isLoading={ isLoading }>
|
23 |
+
<TabBody.Row>
|
24 |
+
<SettingsForm schema={ schema } settingComponent={ Field } groupId={ groupId } disabled={ isLoading } />
|
25 |
+
</TabBody.Row>
|
26 |
+
<TabBody.Row name="save">
|
27 |
+
<Button disabled={ ! hasEdits } isPrimary onClick={ save } isBusy={ isSaving }>
|
28 |
+
{ __( 'Save', 'better-wp-security' ) }
|
29 |
+
</Button>
|
30 |
+
</TabBody.Row>
|
31 |
+
</TabBody>
|
32 |
+
);
|
33 |
+
}
|
34 |
+
|
35 |
+
export default compose( [
|
36 |
+
withSelect( ( select, { groupId } ) => ( {
|
37 |
+
groupSettings: select( 'ithemes-security/user-groups' ).getGroupSettings( groupId ), // Hack to make sure isResolving is triggered in this component
|
38 |
+
isLoading: select( 'core/data' ).isResolving( 'ithemes-security/user-groups', 'getGroupSettings', [ groupId ] ),
|
39 |
+
schema: select( 'ithemes-security/core' ).getSchema( 'ithemes-security-user-group-settings' ),
|
40 |
+
hasEdits: select( 'ithemes-security/user-groups-editor' ).settingHasEdits( groupId ),
|
41 |
+
isSaving: select( 'ithemes-security/user-groups' ).isUpdatingSettings( groupId ),
|
42 |
+
} ) ),
|
43 |
+
withDispatch( ( dispatch, { groupId } ) => ( {
|
44 |
+
save() {
|
45 |
+
return dispatch( 'ithemes-security/user-groups-editor' ).saveGroupSettings( groupId );
|
46 |
+
},
|
47 |
+
} ) ),
|
48 |
+
] )( TabSettings );
|
core/modules/user-groups/entries/settings/components/tab-settings/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/components/tab-settings/style.scss
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-user-groups-group-tab--settings {
|
2 |
+
& .itsec-user-groups-group-tab__modules-list {
|
3 |
+
padding-left: 0;
|
4 |
+
}
|
5 |
+
|
6 |
+
& ul {
|
7 |
+
list-style-type: none;
|
8 |
+
}
|
9 |
+
|
10 |
+
& legend {
|
11 |
+
font-weight: 600;
|
12 |
+
margin-bottom: 1em;
|
13 |
+
font-size: 1.2em;
|
14 |
+
}
|
15 |
+
}
|
core/modules/user-groups/entries/settings/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/store/actions.js
ADDED
@@ -0,0 +1,226 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { get, map } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { __, _n, sprintf } from '@wordpress/i18n';
|
10 |
+
import { dispatch as dataDispatch } from '@wordpress/data';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Internal dependencies
|
14 |
+
*/
|
15 |
+
import { castWPError } from '@ithemes/security-utils';
|
16 |
+
import { select, dispatch, createNotice } from './controls';
|
17 |
+
|
18 |
+
export function selectGroup( ids ) {
|
19 |
+
return {
|
20 |
+
type: SELECT_GROUP,
|
21 |
+
ids,
|
22 |
+
};
|
23 |
+
}
|
24 |
+
|
25 |
+
export function editGroup( id, edit ) {
|
26 |
+
return {
|
27 |
+
type: EDIT_GROUP,
|
28 |
+
id,
|
29 |
+
edit,
|
30 |
+
};
|
31 |
+
}
|
32 |
+
|
33 |
+
export function* saveGroup( id ) {
|
34 |
+
const group = yield select( 'ithemes-security/user-groups-editor', 'getEditedGroup', id );
|
35 |
+
|
36 |
+
if ( ! group ) {
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
|
40 |
+
yield { type: START_SAVE_GROUP, id };
|
41 |
+
|
42 |
+
const updated = yield dispatch( 'ithemes-security/user-groups', 'updateGroup', id, group );
|
43 |
+
|
44 |
+
if ( updated instanceof Error ) {
|
45 |
+
yield createNotice( 'error', updated.message );
|
46 |
+
yield { type: FAILED_SAVE_GROUP, id, error: updated };
|
47 |
+
} else {
|
48 |
+
yield { type: FINISH_SAVE_GROUP, id, updated };
|
49 |
+
yield createNotice( 'success', __( 'Updated group.', 'better-wp-security' ), { type: 'snackbar' } );
|
50 |
+
}
|
51 |
+
|
52 |
+
return updated;
|
53 |
+
}
|
54 |
+
|
55 |
+
export function resetEdits( id ) {
|
56 |
+
return {
|
57 |
+
type: RESET_EDITS,
|
58 |
+
id,
|
59 |
+
};
|
60 |
+
}
|
61 |
+
|
62 |
+
export function* createGroup( args = {} ) {
|
63 |
+
const group = yield select( 'ithemes-security/user-groups-editor', 'getEditedGroup', 'new' );
|
64 |
+
|
65 |
+
if ( ! group ) {
|
66 |
+
return;
|
67 |
+
}
|
68 |
+
|
69 |
+
yield { type: START_CREATE_GROUP };
|
70 |
+
const created = yield dispatch( 'ithemes-security/user-groups', 'createGroup', {
|
71 |
+
...group,
|
72 |
+
...args,
|
73 |
+
} );
|
74 |
+
|
75 |
+
if ( created instanceof Error ) {
|
76 |
+
if ( created.code === 'rest_duplicate_user_group' ) {
|
77 |
+
yield createNotice( 'error', created.message, {
|
78 |
+
actions: [
|
79 |
+
{
|
80 |
+
label: __( 'View Duplicate', 'better-wp-security' ),
|
81 |
+
isLink: true,
|
82 |
+
onClick() {
|
83 |
+
const duplicateLink = get( created, [ '_links', 'duplicate', 0, 'href' ] );
|
84 |
+
const duplicateId = duplicateLink.split( '/' ).pop();
|
85 |
+
|
86 |
+
dataDispatch( 'ithemes-security/user-groups-editor' ).selectGroup( [ duplicateId ] );
|
87 |
+
},
|
88 |
+
},
|
89 |
+
{
|
90 |
+
label: __( 'Create Anyway', 'better-wp-security' ),
|
91 |
+
onClick() {
|
92 |
+
dataDispatch( 'ithemes-security/user-groups-editor' ).createGroup( {
|
93 |
+
ignore_duplicate: true,
|
94 |
+
} );
|
95 |
+
},
|
96 |
+
},
|
97 |
+
],
|
98 |
+
} );
|
99 |
+
} else {
|
100 |
+
yield createNotice( 'error', created.message );
|
101 |
+
}
|
102 |
+
|
103 |
+
yield { type: FAILED_CREATE_GROUP, error: created };
|
104 |
+
} else {
|
105 |
+
yield resetEdits( 'new' );
|
106 |
+
yield { type: FINISH_CREATE_GROUP, created };
|
107 |
+
yield dispatch( 'ithemes-security/user-groups-editor', 'selectGroup', created.id );
|
108 |
+
yield createNotice( 'success', __( 'Created group.', 'better-wp-security' ), { type: 'snackbar' } );
|
109 |
+
}
|
110 |
+
|
111 |
+
return created;
|
112 |
+
}
|
113 |
+
|
114 |
+
export function editGroupSetting( id, module, setting, value ) {
|
115 |
+
return {
|
116 |
+
type: EDIT_GROUP_SETTING,
|
117 |
+
id,
|
118 |
+
module,
|
119 |
+
setting,
|
120 |
+
value,
|
121 |
+
};
|
122 |
+
}
|
123 |
+
|
124 |
+
export function* saveGroupSettings( id ) {
|
125 |
+
const settings = yield select( 'ithemes-security/user-groups-editor', 'getEditedGroupSettings', id );
|
126 |
+
|
127 |
+
if ( ! settings ) {
|
128 |
+
return;
|
129 |
+
}
|
130 |
+
|
131 |
+
yield { type: START_SAVE_GROUP_SETTINGS, id };
|
132 |
+
|
133 |
+
const updated = yield dispatch( 'ithemes-security/user-groups', 'updateGroupSettings', id, settings );
|
134 |
+
|
135 |
+
if ( updated instanceof Error ) {
|
136 |
+
yield createNotice( 'error', updated.message );
|
137 |
+
yield { type: FAILED_SAVE_GROUP_SETTINGS, id, error: updated };
|
138 |
+
} else {
|
139 |
+
yield { type: FINISH_SAVE_GROUP_SETTINGS, id, updated };
|
140 |
+
yield createNotice( 'success', __( 'Updated group settings.', 'better-wp-security' ), { type: 'snackbar' } );
|
141 |
+
}
|
142 |
+
|
143 |
+
return updated;
|
144 |
+
}
|
145 |
+
|
146 |
+
export function bulkEditGroupSetting( module, setting, value ) {
|
147 |
+
return {
|
148 |
+
type: BULK_EDIT_GROUP_SETTING,
|
149 |
+
module,
|
150 |
+
setting,
|
151 |
+
value,
|
152 |
+
};
|
153 |
+
}
|
154 |
+
|
155 |
+
export function resetBulkGroupSettingEdit( module, setting ) {
|
156 |
+
return {
|
157 |
+
type: RESET_BULK_GROUP_SETTING_EDIT,
|
158 |
+
module,
|
159 |
+
setting,
|
160 |
+
};
|
161 |
+
}
|
162 |
+
|
163 |
+
export function resetBulkGroupSettingEdits() {
|
164 |
+
return {
|
165 |
+
type: RESET_BULK_GROUP_SETTING_EDITS,
|
166 |
+
};
|
167 |
+
}
|
168 |
+
|
169 |
+
export function* saveBulkEdits( groupIds ) {
|
170 |
+
const edits = yield select( 'ithemes-security/user-groups-editor', 'getBulkSettingEdits' );
|
171 |
+
const response = yield dispatch(
|
172 |
+
'ithemes-security/user-groups',
|
173 |
+
'patchBulkGroupSettings',
|
174 |
+
groupIds,
|
175 |
+
edits
|
176 |
+
);
|
177 |
+
|
178 |
+
if ( response instanceof Error ) {
|
179 |
+
yield createNotice( 'error', response.message );
|
180 |
+
} else if ( map( response, 'status' ).every( ( status ) => status === 200 ) ) {
|
181 |
+
yield createNotice( 'success', __( 'Updated group settings.', 'better-wp-security' ), { type: 'snackbar' } );
|
182 |
+
} else {
|
183 |
+
const errors = response.filter( ( { status } ) => status !== 200 ).map( ( { error } ) => castWPError( error ) );
|
184 |
+
const combinedMessage = errors.map( ( error ) => error.getAllErrorMessages().join( ' ' ) ).join( ' ' );
|
185 |
+
|
186 |
+
if ( errors.length === response.length ) {
|
187 |
+
yield createNotice( 'error', combinedMessage );
|
188 |
+
} else {
|
189 |
+
yield createNotice(
|
190 |
+
'warning',
|
191 |
+
sprintf(
|
192 |
+
_n( '%1$d group was not updated: %2$s', '%1$d groups were not updated: %2$s', errors.length, 'better-wp-security' ),
|
193 |
+
errors.length,
|
194 |
+
combinedMessage
|
195 |
+
)
|
196 |
+
);
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
200 |
+
yield resetBulkGroupSettingEdits();
|
201 |
+
|
202 |
+
return response;
|
203 |
+
}
|
204 |
+
|
205 |
+
export const SELECT_GROUP = 'SELECT_GROUP';
|
206 |
+
|
207 |
+
export const EDIT_GROUP = 'EDIT_GROUP';
|
208 |
+
export const RESET_EDITS = 'RESET_EDITS';
|
209 |
+
|
210 |
+
export const START_SAVE_GROUP = 'START_SAVE_GROUP';
|
211 |
+
export const FINISH_SAVE_GROUP = 'FINISH_SAVE_GROUP';
|
212 |
+
export const FAILED_SAVE_GROUP = 'FAILED_SAVE_GROUP';
|
213 |
+
|
214 |
+
export const START_CREATE_GROUP = 'START_CREATE_GROUP';
|
215 |
+
export const FINISH_CREATE_GROUP = 'FINISH_CREATE_GROUP';
|
216 |
+
export const FAILED_CREATE_GROUP = 'FAILED_CREATE_GROUP';
|
217 |
+
|
218 |
+
export const EDIT_GROUP_SETTING = 'EDIT_GROUP_SETTING';
|
219 |
+
|
220 |
+
export const START_SAVE_GROUP_SETTINGS = 'START_SAVE_GROUP_SETTINGS';
|
221 |
+
export const FINISH_SAVE_GROUP_SETTINGS = 'FINISH_SAVE_GROUP_SETTINGS';
|
222 |
+
export const FAILED_SAVE_GROUP_SETTINGS = 'FAILED_SAVE_GROUP_SETTINGS';
|
223 |
+
|
224 |
+
export const BULK_EDIT_GROUP_SETTING = 'BULK_EDIT_GROUP_SETTING';
|
225 |
+
export const RESET_BULK_GROUP_SETTING_EDIT = 'RESET_BULK_GROUP_SETTING_EDIT';
|
226 |
+
export const RESET_BULK_GROUP_SETTING_EDITS = 'RESET_BULK_GROUP_SETTING_EDITS';
|
core/modules/user-groups/entries/settings/store/controls.js
ADDED
@@ -0,0 +1,135 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { uniqueId } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { select as selectData, dispatch as dispatchData } from '@wordpress/data';
|
10 |
+
import { default as triggerApiFetch } from '@wordpress/api-fetch';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Internal dependencies
|
14 |
+
*/
|
15 |
+
import { responseToError } from '@ithemes/security-utils';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Trigger an API Fetch request.
|
19 |
+
*
|
20 |
+
* @param {Object} request API Fetch Request Object.
|
21 |
+
* @return {Object} control descriptor.
|
22 |
+
*/
|
23 |
+
export function apiFetch( request ) {
|
24 |
+
return {
|
25 |
+
type: 'API_FETCH',
|
26 |
+
request,
|
27 |
+
};
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Calls a selector using the current state.
|
32 |
+
* @param {string} storeKey Store key.
|
33 |
+
* @param {string} selectorName Selector name.
|
34 |
+
* @param {Array} args Selector arguments.
|
35 |
+
*
|
36 |
+
* @return {Object} control descriptor.
|
37 |
+
*/
|
38 |
+
export function select( storeKey, selectorName, ...args ) {
|
39 |
+
return {
|
40 |
+
type: 'SELECT',
|
41 |
+
storeKey,
|
42 |
+
selectorName,
|
43 |
+
args,
|
44 |
+
};
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Dispatches a control action for triggering a registry dispatch.
|
49 |
+
*
|
50 |
+
* @param {string} storeKey The key for the store the action belongs to
|
51 |
+
* @param {string} actionName The name of the action to dispatch
|
52 |
+
* @param {Array} args Arguments for the dispatch action.
|
53 |
+
*
|
54 |
+
* @example
|
55 |
+
* ```js
|
56 |
+
* import { dispatch } from '@wordpress/data-controls';
|
57 |
+
*
|
58 |
+
* // Action generator using dispatch
|
59 |
+
* export function* myAction() {
|
60 |
+
* yield dispatch( 'core/edit-post', 'togglePublishSidebar' );
|
61 |
+
* // do some other things.
|
62 |
+
* }
|
63 |
+
* ```
|
64 |
+
*
|
65 |
+
* @return {Object} The control descriptor.
|
66 |
+
*/
|
67 |
+
export function dispatch( storeKey, actionName, ...args ) {
|
68 |
+
return {
|
69 |
+
type: 'DISPATCH',
|
70 |
+
storeKey,
|
71 |
+
actionName,
|
72 |
+
args,
|
73 |
+
};
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Yields action objects used in signalling that a notice is to be created.
|
78 |
+
*
|
79 |
+
* @see @wordpress/notices#createNotice()
|
80 |
+
*
|
81 |
+
* @param {?string} status Notice status.
|
82 |
+
* Defaults to `info`.
|
83 |
+
* @param {string} content Notice message.
|
84 |
+
* @param {?Object} options Notice options.
|
85 |
+
* @param {?string} options.context Context under which to
|
86 |
+
* group notice.
|
87 |
+
* @param {?string} options.id Identifier for notice.
|
88 |
+
* Automatically assigned
|
89 |
+
* if not specified.
|
90 |
+
* @param {?boolean} options.isDismissible Whether the notice can
|
91 |
+
* be dismissed by user.
|
92 |
+
* Defaults to `true`.
|
93 |
+
* @param {?number} options.autoDismiss Whether the notice should
|
94 |
+
* by automatically dismissed
|
95 |
+
* after x milliseconds.
|
96 |
+
* Defaults to `false`.
|
97 |
+
* @param {?string} options.type Notice type. Either 'default' or 'snackbar'.
|
98 |
+
* @param {?Array<WPNoticeAction>} options.actions User actions to be
|
99 |
+
* presented with notice.
|
100 |
+
*
|
101 |
+
* @return {Object} control descriptor.
|
102 |
+
*/
|
103 |
+
export function createNotice( status = 'info', content, options = {} ) {
|
104 |
+
return {
|
105 |
+
type: 'CREATE_NOTICE',
|
106 |
+
status,
|
107 |
+
content,
|
108 |
+
options: {
|
109 |
+
context: 'ithemes-security',
|
110 |
+
...options,
|
111 |
+
},
|
112 |
+
};
|
113 |
+
}
|
114 |
+
|
115 |
+
const controls = {
|
116 |
+
API_FETCH( { request } ) {
|
117 |
+
return triggerApiFetch( request ).catch( responseToError );
|
118 |
+
},
|
119 |
+
SELECT( { storeKey, selectorName, args } ) {
|
120 |
+
return selectData( storeKey )[ selectorName ]( ...args );
|
121 |
+
},
|
122 |
+
DISPATCH( { storeKey, actionName, args } ) {
|
123 |
+
return dispatchData( storeKey )[ actionName ]( ...args );
|
124 |
+
},
|
125 |
+
CREATE_NOTICE( { status, content, options } ) {
|
126 |
+
if ( options.autoDismiss ) {
|
127 |
+
options.id = options.id || uniqueId( 'itsec-auto-dismiss-' );
|
128 |
+
setTimeout( () => dispatchData( 'core/notices' ).removeNotice( options.id, options.context ), options.autoDismiss );
|
129 |
+
}
|
130 |
+
|
131 |
+
dispatchData( 'core/notices' ).createNotice( status, content, options );
|
132 |
+
},
|
133 |
+
};
|
134 |
+
|
135 |
+
export default controls;
|
core/modules/user-groups/entries/settings/store/index.js
ADDED
@@ -0,0 +1,23 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { registerStore } from '@wordpress/data';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import controls from './controls';
|
10 |
+
import * as actions from './actions';
|
11 |
+
import * as selectors from './selectors';
|
12 |
+
import * as resolvers from './resolvers';
|
13 |
+
import userGroupsEditor from './reducers';
|
14 |
+
|
15 |
+
const store = registerStore( 'ithemes-security/user-groups-editor', {
|
16 |
+
controls,
|
17 |
+
actions,
|
18 |
+
selectors,
|
19 |
+
resolvers,
|
20 |
+
reducer: userGroupsEditor,
|
21 |
+
} );
|
22 |
+
|
23 |
+
export default store;
|
core/modules/user-groups/entries/settings/store/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/settings/store/reducers.js
ADDED
@@ -0,0 +1,116 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { get, omit } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import {
|
10 |
+
EDIT_GROUP,
|
11 |
+
FINISH_SAVE_GROUP,
|
12 |
+
EDIT_GROUP_SETTING,
|
13 |
+
FINISH_SAVE_GROUP_SETTINGS,
|
14 |
+
START_CREATE_GROUP,
|
15 |
+
FINISH_CREATE_GROUP,
|
16 |
+
FAILED_CREATE_GROUP,
|
17 |
+
RESET_EDITS,
|
18 |
+
SELECT_GROUP,
|
19 |
+
BULK_EDIT_GROUP_SETTING, RESET_BULK_GROUP_SETTING_EDIT, RESET_BULK_GROUP_SETTING_EDITS,
|
20 |
+
} from './actions';
|
21 |
+
|
22 |
+
const DEFAULT_STATE = {
|
23 |
+
edits: {},
|
24 |
+
settingEdits: {},
|
25 |
+
bulkSettingEdits: {},
|
26 |
+
creating: false,
|
27 |
+
selectedGroup: [],
|
28 |
+
};
|
29 |
+
|
30 |
+
export default function userGroupsEditor( state = DEFAULT_STATE, action ) {
|
31 |
+
switch ( action.type ) {
|
32 |
+
case SELECT_GROUP:
|
33 |
+
return {
|
34 |
+
...state,
|
35 |
+
selectedGroup: action.ids,
|
36 |
+
};
|
37 |
+
case EDIT_GROUP:
|
38 |
+
return {
|
39 |
+
...state,
|
40 |
+
edits: {
|
41 |
+
...state.edits,
|
42 |
+
[ action.id ]: {
|
43 |
+
...( state.edits[ action.id ] || {} ),
|
44 |
+
...action.edit,
|
45 |
+
},
|
46 |
+
},
|
47 |
+
};
|
48 |
+
case FINISH_SAVE_GROUP:
|
49 |
+
return {
|
50 |
+
...state,
|
51 |
+
edits: omit( state.edits, [ action.id ] ),
|
52 |
+
};
|
53 |
+
case EDIT_GROUP_SETTING:
|
54 |
+
return {
|
55 |
+
...state,
|
56 |
+
settingEdits: {
|
57 |
+
...state.settingEdits,
|
58 |
+
[ action.id ]: {
|
59 |
+
...get( state, [ 'settingEdits', action.id ], {} ),
|
60 |
+
[ action.module ]: {
|
61 |
+
...get( state, [ 'settingEdits', action.id, action.module ], {} ),
|
62 |
+
[ action.setting ]: action.value,
|
63 |
+
},
|
64 |
+
},
|
65 |
+
},
|
66 |
+
};
|
67 |
+
case FINISH_SAVE_GROUP_SETTINGS:
|
68 |
+
return {
|
69 |
+
...state,
|
70 |
+
settingEdits: omit( state.settingEdits, [ action.id ] ),
|
71 |
+
};
|
72 |
+
case START_CREATE_GROUP:
|
73 |
+
return {
|
74 |
+
...state,
|
75 |
+
creating: true,
|
76 |
+
};
|
77 |
+
case FAILED_CREATE_GROUP:
|
78 |
+
return {
|
79 |
+
...state,
|
80 |
+
creating: false,
|
81 |
+
};
|
82 |
+
case FINISH_CREATE_GROUP:
|
83 |
+
return {
|
84 |
+
...state,
|
85 |
+
creating: false,
|
86 |
+
};
|
87 |
+
case RESET_EDITS:
|
88 |
+
return {
|
89 |
+
...state,
|
90 |
+
edits: omit( state.edits, [ action.id ] ),
|
91 |
+
};
|
92 |
+
case BULK_EDIT_GROUP_SETTING:
|
93 |
+
return {
|
94 |
+
...state,
|
95 |
+
bulkSettingEdits: {
|
96 |
+
...state.bulkSettingEdits,
|
97 |
+
[ action.module ]: {
|
98 |
+
...( state.bulkSettingEdits[ action.module ] || {} ),
|
99 |
+
[ action.setting ]: action.value,
|
100 |
+
},
|
101 |
+
},
|
102 |
+
};
|
103 |
+
case RESET_BULK_GROUP_SETTING_EDIT:
|
104 |
+
return {
|
105 |
+
...state,
|
106 |
+
bulkSettingEdits: omit( state.bulkSettingEdits, `${ action.module }.${ action.setting }` ),
|
107 |
+
};
|
108 |
+
case RESET_BULK_GROUP_SETTING_EDITS:
|
109 |
+
return {
|
110 |
+
...state,
|
111 |
+
bulkSettingEdits: {},
|
112 |
+
};
|
113 |
+
default:
|
114 |
+
return state;
|
115 |
+
}
|
116 |
+
}
|
core/modules/user-groups/entries/settings/store/resolvers.js
ADDED
@@ -0,0 +1,14 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import { dispatch } from './controls';
|
5 |
+
|
6 |
+
export function* getAvailableGroups() {
|
7 |
+
const groups = yield dispatch( 'ithemes-security/user-groups', 'query', 'available', { _embed: 1 } );
|
8 |
+
|
9 |
+
if ( groups.length > 0 ) {
|
10 |
+
yield dispatch( 'ithemes-security/user-groups-editor', 'selectGroup', [ groups[ 0 ].id ] );
|
11 |
+
}
|
12 |
+
|
13 |
+
return groups;
|
14 |
+
}
|
core/modules/user-groups/entries/settings/store/selectors.js
ADDED
@@ -0,0 +1,188 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { get, isEmpty } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { select } from '@wordpress/data';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Get the group being edited.
|
13 |
+
* @param {Object} state
|
14 |
+
* @return {Array<string>}
|
15 |
+
*/
|
16 |
+
export function getSelectedGroup( state ) {
|
17 |
+
return state.selectedGroup;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Is a new group being created.
|
22 |
+
* @param {Object} state
|
23 |
+
* @return {boolean}
|
24 |
+
*/
|
25 |
+
export function isCreating( state ) {
|
26 |
+
return state.creating;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Get the full edited group object.
|
31 |
+
* @param {Object} state
|
32 |
+
* @param {string} id
|
33 |
+
* @return {Object|undefined}
|
34 |
+
*/
|
35 |
+
export function getEditedGroup( state, id ) {
|
36 |
+
return state.edits[ id ];
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Get the edited attribute for a group.
|
41 |
+
* @param {Object} state
|
42 |
+
* @param {string} id
|
43 |
+
* @param {string} attribute
|
44 |
+
* @return {*}
|
45 |
+
*/
|
46 |
+
export function getEditedGroupAttribute( state, id, attribute ) {
|
47 |
+
const edited = get( state, [ 'edits', id, attribute ] );
|
48 |
+
|
49 |
+
if ( typeof edited !== 'undefined' ) {
|
50 |
+
return edited;
|
51 |
+
}
|
52 |
+
|
53 |
+
if ( id === 'new' ) {
|
54 |
+
return undefined;
|
55 |
+
}
|
56 |
+
|
57 |
+
return select( 'ithemes-security/user-groups' ).getGroupAttribute( id, attribute );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Checks if there are changes to be saved for a group.
|
62 |
+
* @param {Object} state
|
63 |
+
* @param {string} id
|
64 |
+
* @return {boolean}
|
65 |
+
*/
|
66 |
+
export function hasEdits( state, id ) {
|
67 |
+
return !! state.edits[ id ];
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Are there any unsaved changes for a group's settings.
|
72 |
+
* @param {Object} state
|
73 |
+
* @param {string} id
|
74 |
+
* @return {boolean}
|
75 |
+
*/
|
76 |
+
export function settingHasEdits( state, id ) {
|
77 |
+
return !! state.settingEdits[ id ];
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Get the full edited group settings.
|
82 |
+
*
|
83 |
+
* @param {Object} state
|
84 |
+
* @param {string} id
|
85 |
+
* @return {Object}
|
86 |
+
*/
|
87 |
+
export function getEditedGroupSettings( state, id ) {
|
88 |
+
return state.settingEdits[ id ];
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get a group's edited value for a setting.
|
93 |
+
*
|
94 |
+
* @param {Object} state
|
95 |
+
* @param {string} id
|
96 |
+
* @param {string} module
|
97 |
+
* @param {string} setting
|
98 |
+
* @return {boolean}
|
99 |
+
*/
|
100 |
+
export function getEditedGroupSetting( state, id, module, setting ) {
|
101 |
+
const value = get( state, [ 'settingEdits', id, module, setting ] );
|
102 |
+
|
103 |
+
if ( value !== undefined ) {
|
104 |
+
return value;
|
105 |
+
}
|
106 |
+
|
107 |
+
return select( 'ithemes-security/user-groups' ).getGroupSetting( id, module, setting );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Check if there have been bulk setting edits.
|
112 |
+
* @param {Object} state
|
113 |
+
* @return {boolean}
|
114 |
+
*/
|
115 |
+
export function hasBulkSettingEdits( state ) {
|
116 |
+
return ! isEmpty( state.bulkSettingEdits );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Get all the bulk setting edits.
|
121 |
+
* @param {Object} state
|
122 |
+
* @return {{}}
|
123 |
+
*/
|
124 |
+
export function getBulkSettingEdits( state ) {
|
125 |
+
return state.bulkSettingEdits;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Get the bulk edited setting value.
|
130 |
+
*
|
131 |
+
* @param {Object} state
|
132 |
+
* @param {string} module
|
133 |
+
* @param {string} setting
|
134 |
+
* @return {boolean|undefined}
|
135 |
+
*/
|
136 |
+
export function getBulkSettingEdit( state, module, setting ) {
|
137 |
+
return get( state, [ 'bulkSettingEdits', module, setting ] );
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Get the value for a bulk edited setting.
|
142 |
+
*
|
143 |
+
* @param {Object} state
|
144 |
+
* @param {Array<Object>} groupIds
|
145 |
+
* @param {string} module
|
146 |
+
* @param {string} setting
|
147 |
+
* @return {null|boolean}
|
148 |
+
*/
|
149 |
+
export function getBulkSettingValue( state, groupIds, module, setting ) {
|
150 |
+
const edit = getBulkSettingEdit( state, module, setting );
|
151 |
+
|
152 |
+
if ( edit !== undefined ) {
|
153 |
+
return edit;
|
154 |
+
}
|
155 |
+
|
156 |
+
const getValue = ( groupId ) => select( 'ithemes-security/user-groups' ).getGroupSetting( groupId, module, setting );
|
157 |
+
|
158 |
+
const firstVal = getValue( groupIds[ 0 ] );
|
159 |
+
const allSame = groupIds.every( ( groupId ) => getValue( groupId ) === firstVal );
|
160 |
+
|
161 |
+
if ( allSame ) {
|
162 |
+
return firstVal;
|
163 |
+
}
|
164 |
+
|
165 |
+
return null;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Are bulk edits being saved.
|
170 |
+
*
|
171 |
+
* @param {Object} state The state object.
|
172 |
+
* @param {Array<string>} groupIds The list of group ids.
|
173 |
+
* @return {boolean}
|
174 |
+
*/
|
175 |
+
export function isSavingBulkEdits( state, groupIds ) {
|
176 |
+
const edits = getBulkSettingEdits( state );
|
177 |
+
|
178 |
+
return select( 'ithemes-security/user-groups' ).isBulkPatchingSettings( groupIds, edits );
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Get the list of available groups.
|
183 |
+
*
|
184 |
+
* @return {Array<Object>}
|
185 |
+
*/
|
186 |
+
export function getAvailableGroups() {
|
187 |
+
return select( 'ithemes-security/user-groups' ).getGroups( 'available' );
|
188 |
+
}
|
core/modules/user-groups/entries/settings/style.scss
ADDED
File without changes
|
core/modules/user-groups/entries/store/actions.js
ADDED
@@ -0,0 +1,404 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { get } from 'lodash';
|
5 |
+
import UriTemplate from 'uri-templates';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { addQueryArgs } from '@wordpress/url';
|
11 |
+
import { select } from '@wordpress/data';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Internal dependencies
|
15 |
+
*/
|
16 |
+
import { getSchemaLink } from '@ithemes/security-utils';
|
17 |
+
import { apiFetch, dispatch } from './controls';
|
18 |
+
|
19 |
+
export const path = '/ithemes-security/v1/user-groups';
|
20 |
+
|
21 |
+
export function* query( queryId, queryParams ) {
|
22 |
+
const items = yield apiFetch( {
|
23 |
+
path: addQueryArgs( path, queryParams ),
|
24 |
+
} );
|
25 |
+
yield receiveQuery( queryId, items );
|
26 |
+
|
27 |
+
for ( const item of items ) {
|
28 |
+
yield* processItem( item );
|
29 |
+
}
|
30 |
+
|
31 |
+
return items;
|
32 |
+
}
|
33 |
+
|
34 |
+
export function* appendToQuery( queryId, item ) {
|
35 |
+
yield {
|
36 |
+
type: APPEND_TO_QUERY,
|
37 |
+
queryId,
|
38 |
+
item,
|
39 |
+
};
|
40 |
+
yield* processItem( item );
|
41 |
+
}
|
42 |
+
|
43 |
+
export function receiveQuery( queryId, items ) {
|
44 |
+
return {
|
45 |
+
type: RECEIVE_QUERY,
|
46 |
+
queryId,
|
47 |
+
items,
|
48 |
+
};
|
49 |
+
}
|
50 |
+
|
51 |
+
export function* processItem( item ) {
|
52 |
+
const users = get( item, [ '_embedded', 'ithemes-security:user-group-member' ], [] );
|
53 |
+
const settings = get( item, [ '_embedded', 'ithemes-security:user-matchable-settings', 0 ] );
|
54 |
+
|
55 |
+
for ( const user of users ) {
|
56 |
+
yield dispatch( 'ithemes-security/core', 'receiveUser', user );
|
57 |
+
}
|
58 |
+
|
59 |
+
if ( settings ) {
|
60 |
+
yield receiveGroupSettings( item.id, settings );
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
export function receiveGroup( group ) {
|
65 |
+
return {
|
66 |
+
type: RECEIVE_GROUP,
|
67 |
+
group,
|
68 |
+
};
|
69 |
+
}
|
70 |
+
|
71 |
+
export function receiveMatchables( matchables ) {
|
72 |
+
return {
|
73 |
+
type: RECEIVE_MATCHABLES,
|
74 |
+
matchables,
|
75 |
+
};
|
76 |
+
}
|
77 |
+
|
78 |
+
export function startCreateGroup( group ) {
|
79 |
+
return { type: START_CREATE_GROUP, group };
|
80 |
+
}
|
81 |
+
|
82 |
+
export function failedCreateGroup( group, error ) {
|
83 |
+
return { type: FAILED_CREATE_GROUP, group, error };
|
84 |
+
}
|
85 |
+
|
86 |
+
export function finishCreateGroup( group, response ) {
|
87 |
+
return { type: FINISH_CREATE_GROUP, group, response };
|
88 |
+
}
|
89 |
+
|
90 |
+
export function startUpdateGroup( id, group ) {
|
91 |
+
return { type: START_UPDATE_GROUP, id, group };
|
92 |
+
}
|
93 |
+
|
94 |
+
export function failedUpdateGroup( id, error ) {
|
95 |
+
return { type: FAILED_UPDATE_GROUP, id, error };
|
96 |
+
}
|
97 |
+
|
98 |
+
export function finishUpdateGroup( id, response ) {
|
99 |
+
return { type: FINISH_UPDATE_GROUP, id, response };
|
100 |
+
}
|
101 |
+
|
102 |
+
export function startDeleteGroup( id ) {
|
103 |
+
return { type: START_DELETE_GROUP, id };
|
104 |
+
}
|
105 |
+
|
106 |
+
export function failedDeleteGroup( id, error ) {
|
107 |
+
return { type: FAILED_DELETE_GROUP, id, error };
|
108 |
+
}
|
109 |
+
|
110 |
+
export function finishDeleteGroup( id ) {
|
111 |
+
return { type: FINISH_DELETE_GROUP, id };
|
112 |
+
}
|
113 |
+
|
114 |
+
export function receiveGroupSettings( id, settings ) {
|
115 |
+
return {
|
116 |
+
type: RECEIVE_GROUP_SETTINGS,
|
117 |
+
id,
|
118 |
+
settings,
|
119 |
+
};
|
120 |
+
}
|
121 |
+
|
122 |
+
export function startUpdateGroupSettings( id, settings ) {
|
123 |
+
return { type: START_UPDATE_GROUP_SETTINGS, id, settings };
|
124 |
+
}
|
125 |
+
|
126 |
+
export function failedUpdateGroupSettings( id, error ) {
|
127 |
+
return { type: FAILED_UPDATE_GROUP_SETTINGS, id, error };
|
128 |
+
}
|
129 |
+
|
130 |
+
export function finishUpdateGroupSettings( id, response ) {
|
131 |
+
return { type: FINISH_UPDATE_GROUP_SETTINGS, id, response };
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Creates a new user group.
|
136 |
+
*
|
137 |
+
* @param {Object} group Group data.
|
138 |
+
* @return {IterableIterator<*>} Iterator
|
139 |
+
*/
|
140 |
+
export function* createGroup( group ) {
|
141 |
+
yield startCreateGroup( group );
|
142 |
+
|
143 |
+
let response;
|
144 |
+
|
145 |
+
try {
|
146 |
+
response = yield apiFetch( {
|
147 |
+
path: addQueryArgs( path, { _embed: 1 } ),
|
148 |
+
method: 'POST',
|
149 |
+
data: group,
|
150 |
+
} );
|
151 |
+
} catch ( e ) {
|
152 |
+
yield failedCreateGroup( group, e );
|
153 |
+
return e;
|
154 |
+
}
|
155 |
+
|
156 |
+
yield finishCreateGroup( group, response );
|
157 |
+
yield receiveGroup( response );
|
158 |
+
yield* processItem( response );
|
159 |
+
|
160 |
+
return response;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Updates a user group.
|
165 |
+
*
|
166 |
+
* @param {string} id Group id id to update.
|
167 |
+
* @param {Object} group Group data.
|
168 |
+
* @return {IterableIterator<*>} Iterator
|
169 |
+
*/
|
170 |
+
export function* updateGroup( id, group ) {
|
171 |
+
yield startUpdateGroup( id, group );
|
172 |
+
|
173 |
+
let response;
|
174 |
+
|
175 |
+
try {
|
176 |
+
response = yield apiFetch( {
|
177 |
+
path: path + '/' + id,
|
178 |
+
method: 'PUT',
|
179 |
+
data: group,
|
180 |
+
} );
|
181 |
+
} catch ( e ) {
|
182 |
+
yield failedUpdateGroup( id, e );
|
183 |
+
return e;
|
184 |
+
}
|
185 |
+
|
186 |
+
yield finishUpdateGroup( id, response );
|
187 |
+
yield receiveGroup( response );
|
188 |
+
|
189 |
+
return response;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Deletes a user group.
|
194 |
+
*
|
195 |
+
* @param {string} id Group id to delete.
|
196 |
+
* @return {IterableIterator<*>} Iterator
|
197 |
+
*/
|
198 |
+
export function* deleteGroup( id ) {
|
199 |
+
yield startDeleteGroup( id );
|
200 |
+
|
201 |
+
try {
|
202 |
+
yield apiFetch( {
|
203 |
+
path: `${ path }/${ id }`,
|
204 |
+
method: 'DELETE',
|
205 |
+
} );
|
206 |
+
} catch ( e ) {
|
207 |
+
yield failedDeleteGroup( id, e );
|
208 |
+
return e;
|
209 |
+
}
|
210 |
+
|
211 |
+
yield finishDeleteGroup( id );
|
212 |
+
|
213 |
+
return null;
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Updates a user group.
|
218 |
+
*
|
219 |
+
* @param {Object} id Id of group.
|
220 |
+
* @param {Object} settings New settings.
|
221 |
+
* @return {IterableIterator<*>} Iterator
|
222 |
+
*/
|
223 |
+
export function* updateGroupSettings( id, settings ) {
|
224 |
+
yield startUpdateGroupSettings( id, settings );
|
225 |
+
|
226 |
+
let response;
|
227 |
+
|
228 |
+
try {
|
229 |
+
response = yield apiFetch( {
|
230 |
+
path: `ithemes-security/v1/user-matchable-settings/${ id }`,
|
231 |
+
method: 'PUT',
|
232 |
+
data: settings,
|
233 |
+
} );
|
234 |
+
} catch ( e ) {
|
235 |
+
yield failedUpdateGroupSettings( id, e );
|
236 |
+
return e;
|
237 |
+
}
|
238 |
+
|
239 |
+
yield finishUpdateGroupSettings( id, response );
|
240 |
+
yield receiveGroupSettings( id, response );
|
241 |
+
|
242 |
+
return response;
|
243 |
+
}
|
244 |
+
|
245 |
+
export function* fetchGroupsSettings( groupIds = [] ) {
|
246 |
+
yield startFetchGroupsSettings( groupIds );
|
247 |
+
|
248 |
+
let response;
|
249 |
+
|
250 |
+
try {
|
251 |
+
let fetchPath = 'ithemes-security/v1/user-matchable-settings';
|
252 |
+
|
253 |
+
if ( groupIds.length > 0 ) {
|
254 |
+
fetchPath = addQueryArgs( fetchPath, { include: groupIds } );
|
255 |
+
}
|
256 |
+
|
257 |
+
response = yield apiFetch( {
|
258 |
+
path: fetchPath,
|
259 |
+
} );
|
260 |
+
} catch ( e ) {
|
261 |
+
yield failedFetchGroupsSettings( groupIds, e );
|
262 |
+
|
263 |
+
return e;
|
264 |
+
}
|
265 |
+
|
266 |
+
yield finishFetchGroupsSettings( groupIds, response );
|
267 |
+
|
268 |
+
for ( const groupId in response ) {
|
269 |
+
if ( ! response.hasOwnProperty( groupId ) ) {
|
270 |
+
continue;
|
271 |
+
}
|
272 |
+
|
273 |
+
yield receiveGroupSettings( groupId, response[ groupId ] );
|
274 |
+
}
|
275 |
+
|
276 |
+
return response;
|
277 |
+
}
|
278 |
+
|
279 |
+
export function startFetchGroupsSettings( groupIds ) {
|
280 |
+
return {
|
281 |
+
type: START_FETCH_GROUPS_SETTINGS,
|
282 |
+
groupIds,
|
283 |
+
};
|
284 |
+
}
|
285 |
+
|
286 |
+
export function finishFetchGroupsSettings( groupIds, response ) {
|
287 |
+
return {
|
288 |
+
type: FINISH_FETCH_GROUPS_SETTINGS,
|
289 |
+
groupIds,
|
290 |
+
response,
|
291 |
+
};
|
292 |
+
}
|
293 |
+
|
294 |
+
export function failedFetchGroupsSettings( groupIds, error ) {
|
295 |
+
return {
|
296 |
+
type: FAILED_FETCH_GROUPS_SETTINGS,
|
297 |
+
groupIds,
|
298 |
+
error,
|
299 |
+
};
|
300 |
+
}
|
301 |
+
|
302 |
+
export function* patchBulkGroupSettings( groupIds, patch ) {
|
303 |
+
yield startPatchBulkGroupSettings( groupIds, patch );
|
304 |
+
|
305 |
+
let response;
|
306 |
+
|
307 |
+
try {
|
308 |
+
response = yield apiFetch( {
|
309 |
+
path: addQueryArgs( `ithemes-security/v1/user-matchable-settings`, { include: groupIds } ),
|
310 |
+
method: 'PATCH',
|
311 |
+
data: patch,
|
312 |
+
} );
|
313 |
+
} catch ( e ) {
|
314 |
+
yield failedPatchBulkGroupSettings( groupIds, patch, e );
|
315 |
+
|
316 |
+
return e;
|
317 |
+
}
|
318 |
+
|
319 |
+
yield finishPatchBulkGroupSettings( groupIds, patch, response );
|
320 |
+
|
321 |
+
const schema = select( 'ithemes-security/core' ).getSchema( 'ithemes-security-user-group-settings' );
|
322 |
+
const selfLink = getSchemaLink( schema, 'self' );
|
323 |
+
|
324 |
+
if ( ! selfLink ) {
|
325 |
+
return response;
|
326 |
+
}
|
327 |
+
|
328 |
+
const template = new UriTemplate( selfLink.href );
|
329 |
+
|
330 |
+
for ( const result of response ) {
|
331 |
+
if ( result.status !== 200 ) {
|
332 |
+
continue;
|
333 |
+
}
|
334 |
+
|
335 |
+
const props = template.fromUri( result.href );
|
336 |
+
|
337 |
+
if ( ! props.id ) {
|
338 |
+
continue;
|
339 |
+
}
|
340 |
+
|
341 |
+
yield receiveGroupSettings( props.id, result.response );
|
342 |
+
}
|
343 |
+
|
344 |
+
return response;
|
345 |
+
}
|
346 |
+
|
347 |
+
export function startPatchBulkGroupSettings( groupIds, patch ) {
|
348 |
+
return {
|
349 |
+
type: START_PATCH_BULK_GROUP_SETTINGS,
|
350 |
+
groupIds,
|
351 |
+
patch,
|
352 |
+
};
|
353 |
+
}
|
354 |
+
|
355 |
+
export function finishPatchBulkGroupSettings( groupIds, patch, response ) {
|
356 |
+
return {
|
357 |
+
type: FINISH_PATCH_BULK_GROUP_SETTINGS,
|
358 |
+
groupIds,
|
359 |
+
patch,
|
360 |
+
response,
|
361 |
+
};
|
362 |
+
}
|
363 |
+
|
364 |
+
export function failedPatchBulkGroupSettings( groupIds, patch, error ) {
|
365 |
+
return {
|
366 |
+
type: FAILED_PATCH_BULK_GROUP_SETTINGS,
|
367 |
+
groupIds,
|
368 |
+
patch,
|
369 |
+
error,
|
370 |
+
};
|
371 |
+
}
|
372 |
+
|
373 |
+
export const RECEIVE_QUERY = 'RECEIVE_QUERY';
|
374 |
+
export const APPEND_TO_QUERY = 'APPEND_TO_QUERY';
|
375 |
+
|
376 |
+
export const RECEIVE_MATCHABLES = 'RECEIVE_MATCHABLES';
|
377 |
+
|
378 |
+
export const START_CREATE_GROUP = 'START_CREATE_GROUP';
|
379 |
+
export const FINISH_CREATE_GROUP = 'FINISH_CREATE_GROUP';
|
380 |
+
export const FAILED_CREATE_GROUP = 'FAILED_CREATE_GROUP';
|
381 |
+
|
382 |
+
export const RECEIVE_GROUP = 'RECEIVE_GROUP';
|
383 |
+
|
384 |
+
export const START_UPDATE_GROUP = 'START_UPDATE_GROUP';
|
385 |
+
export const FINISH_UPDATE_GROUP = 'FINISH_UPDATE_GROUP';
|
386 |
+
export const FAILED_UPDATE_GROUP = 'FAILED_UPDATE_GROUP';
|
387 |
+
|
388 |
+
export const START_DELETE_GROUP = 'START_DELETE_GROUP';
|
389 |
+
export const FINISH_DELETE_GROUP = 'FINISH_DELETE_GROUP';
|
390 |
+
export const FAILED_DELETE_GROUP = 'FAILED_DELETE_GROUP';
|
391 |
+
|
392 |
+
export const RECEIVE_GROUP_SETTINGS = 'RECEIVE_GROUP_SETTINGS';
|
393 |
+
|
394 |
+
export const START_UPDATE_GROUP_SETTINGS = 'START_UPDATE_GROUP_SETTINGS';
|
395 |
+
export const FINISH_UPDATE_GROUP_SETTINGS = 'FINISH_UPDATE_GROUP_SETTINGS';
|
396 |
+
export const FAILED_UPDATE_GROUP_SETTINGS = 'FAILED_UPDATE_GROUP_SETTINGS';
|
397 |
+
|
398 |
+
export const START_FETCH_GROUPS_SETTINGS = 'START_FETCH_GROUPS_SETTINGS';
|
399 |
+
export const FINISH_FETCH_GROUPS_SETTINGS = 'FINISH_FETCH_GROUPS_SETTINGS';
|
400 |
+
export const FAILED_FETCH_GROUPS_SETTINGS = 'FAILED_FETCH_GROUPS_SETTINGS';
|
401 |
+
|
402 |
+
export const START_PATCH_BULK_GROUP_SETTINGS = 'START_PATCH_BULK_GROUP_SETTINGS';
|
403 |
+
export const FINISH_PATCH_BULK_GROUP_SETTINGS = 'FINISH_PATCH_BULK_GROUP_SETTINGS';
|
404 |
+
export const FAILED_PATCH_BULK_GROUP_SETTINGS = 'FAILED_PATCH_BULK_GROUP_SETTINGS';
|
core/modules/user-groups/entries/store/controls.js
ADDED
@@ -0,0 +1,83 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { dispatch as dispatchData, select as selectData } from '@wordpress/data';
|
5 |
+
import { default as triggerApiFetch } from '@wordpress/api-fetch';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal dependencies
|
9 |
+
*/
|
10 |
+
import { responseToError } from '@ithemes/security-utils';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Trigger an API Fetch request.
|
14 |
+
*
|
15 |
+
* @param {Object} request API Fetch Request Object.
|
16 |
+
* @return {Object} control descriptor.
|
17 |
+
*/
|
18 |
+
export function apiFetch( request ) {
|
19 |
+
return {
|
20 |
+
type: 'API_FETCH',
|
21 |
+
request,
|
22 |
+
};
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Calls a selector using the current state.
|
27 |
+
* @param {string} storeKey Store key.
|
28 |
+
* @param {string} selectorName Selector name.
|
29 |
+
* @param {Array} args Selector arguments.
|
30 |
+
*
|
31 |
+
* @return {Object} control descriptor.
|
32 |
+
*/
|
33 |
+
export function select( storeKey, selectorName, ...args ) {
|
34 |
+
return {
|
35 |
+
type: 'SELECT',
|
36 |
+
storeKey,
|
37 |
+
selectorName,
|
38 |
+
args,
|
39 |
+
};
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Dispatches a control action for triggering a registry dispatch.
|
44 |
+
*
|
45 |
+
* @param {string} storeKey The key for the store the action belongs to
|
46 |
+
* @param {string} actionName The name of the action to dispatch
|
47 |
+
* @param {Array} args Arguments for the dispatch action.
|
48 |
+
*
|
49 |
+
* @example
|
50 |
+
* ```js
|
51 |
+
* import { dispatch } from '@wordpress/data-controls';
|
52 |
+
*
|
53 |
+
* // Action generator using dispatch
|
54 |
+
* export function* myAction() {
|
55 |
+
* yield dispatch( 'core/edit-post', 'togglePublishSidebar' );
|
56 |
+
* // do some other things.
|
57 |
+
* }
|
58 |
+
* ```
|
59 |
+
*
|
60 |
+
* @return {Object} The control descriptor.
|
61 |
+
*/
|
62 |
+
export function dispatch( storeKey, actionName, ...args ) {
|
63 |
+
return {
|
64 |
+
type: 'DISPATCH',
|
65 |
+
storeKey,
|
66 |
+
actionName,
|
67 |
+
args,
|
68 |
+
};
|
69 |
+
}
|
70 |
+
|
71 |
+
const controls = {
|
72 |
+
API_FETCH( { request } ) {
|
73 |
+
return triggerApiFetch( request ).catch( responseToError );
|
74 |
+
},
|
75 |
+
SELECT( { storeKey, selectorName, args } ) {
|
76 |
+
return selectData( storeKey )[ selectorName ]( ...args );
|
77 |
+
},
|
78 |
+
DISPATCH( { storeKey, actionName, args } ) {
|
79 |
+
return dispatchData( storeKey )[ actionName ]( ...args );
|
80 |
+
},
|
81 |
+
};
|
82 |
+
|
83 |
+
export default controls;
|
core/modules/user-groups/entries/store/index.js
ADDED
@@ -0,0 +1,23 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { registerStore } from '@wordpress/data';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import controls from './controls';
|
10 |
+
import * as actions from './actions';
|
11 |
+
import * as selectors from './selectors';
|
12 |
+
import userGroups from './reducers';
|
13 |
+
import * as resolvers from './resolvers';
|
14 |
+
|
15 |
+
const store = registerStore( 'ithemes-security/user-groups', {
|
16 |
+
controls,
|
17 |
+
actions,
|
18 |
+
selectors,
|
19 |
+
resolvers,
|
20 |
+
reducer: userGroups,
|
21 |
+
} );
|
22 |
+
|
23 |
+
export default store;
|
core/modules/user-groups/entries/store/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/entries/store/reducers.js
ADDED
@@ -0,0 +1,199 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { omit, keyBy, map } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import {
|
10 |
+
FAILED_CREATE_GROUP,
|
11 |
+
FAILED_DELETE_GROUP,
|
12 |
+
FAILED_UPDATE_GROUP,
|
13 |
+
FINISH_CREATE_GROUP,
|
14 |
+
FINISH_DELETE_GROUP,
|
15 |
+
FINISH_UPDATE_GROUP,
|
16 |
+
RECEIVE_GROUP,
|
17 |
+
RECEIVE_GROUP_SETTINGS,
|
18 |
+
RECEIVE_QUERY,
|
19 |
+
START_CREATE_GROUP,
|
20 |
+
START_DELETE_GROUP,
|
21 |
+
START_UPDATE_GROUP,
|
22 |
+
START_UPDATE_GROUP_SETTINGS,
|
23 |
+
FINISH_UPDATE_GROUP_SETTINGS,
|
24 |
+
FAILED_UPDATE_GROUP_SETTINGS,
|
25 |
+
APPEND_TO_QUERY,
|
26 |
+
START_PATCH_BULK_GROUP_SETTINGS,
|
27 |
+
FINISH_PATCH_BULK_GROUP_SETTINGS,
|
28 |
+
FAILED_PATCH_BULK_GROUP_SETTINGS, RECEIVE_MATCHABLES,
|
29 |
+
} from './actions';
|
30 |
+
|
31 |
+
const DEFAULT_STATE = {
|
32 |
+
matchablesById: {},
|
33 |
+
matchableIds: [],
|
34 |
+
byId: {},
|
35 |
+
queries: {},
|
36 |
+
creating: [],
|
37 |
+
updating: [],
|
38 |
+
deleting: [],
|
39 |
+
settings: {},
|
40 |
+
updatingSettings: [],
|
41 |
+
bulkPatchingSettings: {},
|
42 |
+
};
|
43 |
+
|
44 |
+
export default function userGroups( state = DEFAULT_STATE, action ) {
|
45 |
+
switch ( action.type ) {
|
46 |
+
case RECEIVE_MATCHABLES:
|
47 |
+
return {
|
48 |
+
...state,
|
49 |
+
matchableIds: map( action.matchables, 'id' ),
|
50 |
+
matchablesById: keyBy( action.matchables, 'id' ),
|
51 |
+
};
|
52 |
+
case RECEIVE_QUERY:
|
53 |
+
return {
|
54 |
+
...state,
|
55 |
+
byId: {
|
56 |
+
...state.byId,
|
57 |
+
...keyBy( action.items, 'id' ),
|
58 |
+
},
|
59 |
+
queries: {
|
60 |
+
...state.queries,
|
61 |
+
[ action.queryId ]: map( action.items, 'id' ),
|
62 |
+
},
|
63 |
+
};
|
64 |
+
case APPEND_TO_QUERY:
|
65 |
+
return {
|
66 |
+
...state,
|
67 |
+
byId: {
|
68 |
+
...state.byId,
|
69 |
+
[ action.item.id ]: action.item,
|
70 |
+
},
|
71 |
+
queries: {
|
72 |
+
...state.queries,
|
73 |
+
[ action.queryId ]: [
|
74 |
+
...( state.queries[ action.queryId ] || [] ),
|
75 |
+
action.item.id,
|
76 |
+
],
|
77 |
+
},
|
78 |
+
};
|
79 |
+
case RECEIVE_GROUP:
|
80 |
+
return {
|
81 |
+
...state,
|
82 |
+
byId: {
|
83 |
+
...state.byId,
|
84 |
+
[ action.group.id ]: action.group,
|
85 |
+
},
|
86 |
+
matchablesById: state.matchablesById[ action.group.id ] ? {
|
87 |
+
...state.matchablesById,
|
88 |
+
[ action.group.id ]: {
|
89 |
+
...state.matchablesById[ action.group.id ],
|
90 |
+
label: action.group.label,
|
91 |
+
},
|
92 |
+
} : state.matchablesById,
|
93 |
+
};
|
94 |
+
case START_CREATE_GROUP:
|
95 |
+
return {
|
96 |
+
...state,
|
97 |
+
creating: [
|
98 |
+
...state.creating,
|
99 |
+
action.group,
|
100 |
+
],
|
101 |
+
};
|
102 |
+
case FINISH_CREATE_GROUP:
|
103 |
+
return {
|
104 |
+
...state,
|
105 |
+
creating: state.creating.filter( ( group ) => group !== action.group ),
|
106 |
+
matchablesById: {
|
107 |
+
...state.matchablesById,
|
108 |
+
[ action.response.id ]: {
|
109 |
+
id: action.response.id,
|
110 |
+
label: action.response.label,
|
111 |
+
type: 'user-group',
|
112 |
+
},
|
113 |
+
},
|
114 |
+
matchableIds: [
|
115 |
+
...state.matchableIds,
|
116 |
+
[ action.response.id ],
|
117 |
+
],
|
118 |
+
};
|
119 |
+
case FAILED_CREATE_GROUP:
|
120 |
+
return {
|
121 |
+
...state,
|
122 |
+
creating: state.creating.filter( ( group ) => group !== action.group ),
|
123 |
+
};
|
124 |
+
case START_UPDATE_GROUP:
|
125 |
+
return {
|
126 |
+
...state,
|
127 |
+
updating: [
|
128 |
+
...state.updating,
|
129 |
+
action.id,
|
130 |
+
],
|
131 |
+
};
|
132 |
+
case FINISH_UPDATE_GROUP:
|
133 |
+
case FAILED_UPDATE_GROUP:
|
134 |
+
return {
|
135 |
+
...state,
|
136 |
+
updating: state.updating.filter( ( id ) => id !== action.id ),
|
137 |
+
};
|
138 |
+
case START_DELETE_GROUP:
|
139 |
+
return {
|
140 |
+
...state,
|
141 |
+
deleting: [
|
142 |
+
...state.deleting,
|
143 |
+
action.id,
|
144 |
+
],
|
145 |
+
};
|
146 |
+
case FINISH_DELETE_GROUP:
|
147 |
+
return {
|
148 |
+
...state,
|
149 |
+
deleting: state.deleting.filter( ( id ) => id !== action.id ),
|
150 |
+
byId: omit( state.byId, [ action.id ] ),
|
151 |
+
matchablesById: omit( state.matchablesById, [ action.id ] ),
|
152 |
+
matchableIds: state.matchableIds.filter( ( id ) => id !== action.id ),
|
153 |
+
settings: omit( state.settings, [ action.id ] ),
|
154 |
+
};
|
155 |
+
case FAILED_DELETE_GROUP:
|
156 |
+
return {
|
157 |
+
...state,
|
158 |
+
deleting: state.deleting.filter( ( id ) => id !== action.id ),
|
159 |
+
};
|
160 |
+
case RECEIVE_GROUP_SETTINGS:
|
161 |
+
return {
|
162 |
+
...state,
|
163 |
+
settings: {
|
164 |
+
...state.settings,
|
165 |
+
[ action.id ]: action.settings,
|
166 |
+
},
|
167 |
+
};
|
168 |
+
case START_UPDATE_GROUP_SETTINGS:
|
169 |
+
return {
|
170 |
+
...state,
|
171 |
+
updatingSettings: [
|
172 |
+
...state.updatingSettings,
|
173 |
+
action.id,
|
174 |
+
],
|
175 |
+
};
|
176 |
+
case FINISH_UPDATE_GROUP_SETTINGS:
|
177 |
+
case FAILED_UPDATE_GROUP_SETTINGS:
|
178 |
+
return {
|
179 |
+
...state,
|
180 |
+
updatingSettings: state.updatingSettings.filter( ( id ) => id !== action.id ),
|
181 |
+
};
|
182 |
+
case START_PATCH_BULK_GROUP_SETTINGS:
|
183 |
+
return {
|
184 |
+
...state,
|
185 |
+
bulkPatchingSettings: {
|
186 |
+
...state.bulkPatchingSettings,
|
187 |
+
[ action.groupIds.join( '_' ) ]: action.patch,
|
188 |
+
},
|
189 |
+
};
|
190 |
+
case FINISH_PATCH_BULK_GROUP_SETTINGS:
|
191 |
+
case FAILED_PATCH_BULK_GROUP_SETTINGS:
|
192 |
+
return {
|
193 |
+
...state,
|
194 |
+
bulkPatchingSettings: omit( state.bulkPatchingSettings, [ action.groupIds.join( '_' ) ] ),
|
195 |
+
};
|
196 |
+
default:
|
197 |
+
return state;
|
198 |
+
}
|
199 |
+
}
|
core/modules/user-groups/entries/store/resolvers.js
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { isEmpty, get } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import { apiFetch } from './controls';
|
10 |
+
import { path, receiveGroup, receiveGroupSettings, receiveMatchables, processItem } from './actions';
|
11 |
+
|
12 |
+
export const getGroup = {
|
13 |
+
*fulfill( id ) {
|
14 |
+
const group = yield apiFetch( { path: `${ path }/${ id }?_embed=1` } );
|
15 |
+
yield receiveGroup( group );
|
16 |
+
yield* processItem( group );
|
17 |
+
},
|
18 |
+
isFulfilled( state, id ) {
|
19 |
+
return state.byId.hasOwnProperty( id );
|
20 |
+
},
|
21 |
+
};
|
22 |
+
|
23 |
+
export const getMatchables = {
|
24 |
+
*fulfill() {
|
25 |
+
const matchables = yield apiFetch( { path: '/ithemes-security/v1/user-matchables?_embed=1' } );
|
26 |
+
yield receiveMatchables( matchables );
|
27 |
+
|
28 |
+
for ( const matchable of matchables ) {
|
29 |
+
const group = get( matchable, [ '_embedded', 'self', 0 ] );
|
30 |
+
const settings = get( matchable, [ '_embedded', 'ithemes-security:user-matchable-settings', 0 ] );
|
31 |
+
|
32 |
+
if ( group ) {
|
33 |
+
yield receiveGroup( group );
|
34 |
+
}
|
35 |
+
|
36 |
+
if ( settings ) {
|
37 |
+
yield receiveGroupSettings( matchable.id, settings );
|
38 |
+
}
|
39 |
+
}
|
40 |
+
},
|
41 |
+
isFulfilled( state ) {
|
42 |
+
return ! isEmpty( state.matchablesById );
|
43 |
+
},
|
44 |
+
};
|
45 |
+
|
46 |
+
export const getGroupSettings = {
|
47 |
+
*fulfill( id ) {
|
48 |
+
const settings = yield apiFetch( { path: `ithemes-security/v1/user-matchable-settings/${ id }` } );
|
49 |
+
yield receiveGroupSettings( id, settings );
|
50 |
+
},
|
51 |
+
isFulfilled( state, id ) {
|
52 |
+
return state.settings.hasOwnProperty( id );
|
53 |
+
},
|
54 |
+
};
|
core/modules/user-groups/entries/store/selectors.js
ADDED
@@ -0,0 +1,204 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import createSelector from 'rememo';
|
5 |
+
import { map, filter, isObject, get } from 'lodash';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { select } from '@wordpress/data';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Get the list of matchables.
|
14 |
+
*
|
15 |
+
* @param {Object} state
|
16 |
+
* @return {Array<Object>}
|
17 |
+
*/
|
18 |
+
export const getMatchables = createSelector(
|
19 |
+
( state ) => filter( map( state.matchableIds, ( id ) => state.matchablesById[ id ] ), isObject ),
|
20 |
+
( state ) => [ state.matchablesById, state.matchableIds ],
|
21 |
+
);
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Gets the type of a matchable.
|
25 |
+
*
|
26 |
+
* @param {Object} state Store state.
|
27 |
+
* @param {string} id Matchable id.
|
28 |
+
*
|
29 |
+
* @return {string} Either 'user-group' or 'meta'.
|
30 |
+
*/
|
31 |
+
export function getMatchableType( state, id ) {
|
32 |
+
return ( state.matchablesById[ id ] || {} ).type;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Gets the label for a matchable.
|
37 |
+
*
|
38 |
+
* @param {Object} state Store state.
|
39 |
+
* @param {string} id Matchable id.
|
40 |
+
*
|
41 |
+
* @return {string} The matchable's label.
|
42 |
+
*/
|
43 |
+
export function getMatchableLabel( state, id ) {
|
44 |
+
return ( state.matchablesById[ id ] || {} ).label;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Returns all the groups returned by a query ID.
|
49 |
+
*
|
50 |
+
* @param {Object} state Data state.
|
51 |
+
* @param {string} queryId Query ID.
|
52 |
+
*
|
53 |
+
* @return {Array} Groups list.
|
54 |
+
*/
|
55 |
+
export const getGroups = createSelector(
|
56 |
+
( state, queryId ) => filter( map( state.queries[ queryId ], ( id ) => state.byId[ id ] ), isObject ),
|
57 |
+
( state, queryId ) => [ state.queries[ queryId ], state.byId ],
|
58 |
+
);
|
59 |
+
|
60 |
+
const UNKNOWN_QUERIED_OBJECTS = [];
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Get the object ids returned by a query.
|
64 |
+
* @param {Object} state
|
65 |
+
* @param {string} queryId
|
66 |
+
* @return {Array<string|number>}
|
67 |
+
*/
|
68 |
+
export function getQueriedObjectIds( state, queryId ) {
|
69 |
+
return state.queries[ queryId ] || UNKNOWN_QUERIED_OBJECTS;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Gets the data for the group.
|
74 |
+
*
|
75 |
+
* @param {Object} state
|
76 |
+
* @param {string} id
|
77 |
+
* @return {Object|undefined}
|
78 |
+
*/
|
79 |
+
export function getGroup( state, id ) {
|
80 |
+
return state.byId[ id ];
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Get a group's attribute value.
|
85 |
+
* @param {Object} state
|
86 |
+
* @param {string} id
|
87 |
+
* @param {string} attribute
|
88 |
+
* @return {*}
|
89 |
+
*/
|
90 |
+
export function getGroupAttribute( state, id, attribute ) {
|
91 |
+
const group = select( 'ithemes-security/user-groups' ).getGroup( id );
|
92 |
+
|
93 |
+
return group ? group[ attribute ] : undefined;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Checks if the given user group is being updated.
|
98 |
+
* @param {Object} state
|
99 |
+
* @param {string} id
|
100 |
+
* @return {boolean}
|
101 |
+
*/
|
102 |
+
export function isUpdating( state, id ) {
|
103 |
+
return state.updating.includes( id );
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Checks if the given user group is being deleted.
|
108 |
+
* @param {Object} state
|
109 |
+
* @param {string} id
|
110 |
+
* @return {boolean}
|
111 |
+
*/
|
112 |
+
export function isDeleting( state, id ) {
|
113 |
+
return state.deleting.includes( id );
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Get all the settings for a group.
|
118 |
+
*
|
119 |
+
* @param {Object} state
|
120 |
+
* @param {string} id
|
121 |
+
* @return {Object|undefined}
|
122 |
+
*/
|
123 |
+
export function getGroupSettings( state, id ) {
|
124 |
+
return state.settings[ id ];
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Get a group's value for a setting.
|
129 |
+
*
|
130 |
+
* @param {Object} state
|
131 |
+
* @param {string} id
|
132 |
+
* @param {string} module
|
133 |
+
* @param {string} setting
|
134 |
+
* @return {boolean}
|
135 |
+
*/
|
136 |
+
export function getGroupSetting( state, id, module, setting ) {
|
137 |
+
const settings = select( 'ithemes-security/user-groups' ).getGroupSettings( id );
|
138 |
+
|
139 |
+
return get( settings, [ module, setting ] );
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Is the application updating a group's settings.
|
144 |
+
* @param {Object} state
|
145 |
+
* @param {string} id
|
146 |
+
* @return {boolean}
|
147 |
+
*/
|
148 |
+
export function isUpdatingSettings( state, id ) {
|
149 |
+
return state.updatingSettings.includes( id );
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Is a bulk patch in progress.
|
154 |
+
* @param {Object} state
|
155 |
+
* @param {Array<string>} groupIds
|
156 |
+
* @param {Object} patch
|
157 |
+
* @return {boolean}
|
158 |
+
*/
|
159 |
+
export function isBulkPatchingSettings( state, groupIds, patch ) {
|
160 |
+
const id = groupIds.join( '_' );
|
161 |
+
|
162 |
+
return state.bulkPatchingSettings[ id ] === patch;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Gets the groups for each setting.
|
167 |
+
* @param {Object} state State object.
|
168 |
+
* @return {{}} Object of modules -> setting -> array of group ids.
|
169 |
+
*/
|
170 |
+
export function getGroupsBySetting( state ) {
|
171 |
+
const bySetting = {};
|
172 |
+
|
173 |
+
for ( const groupId in state.settings ) {
|
174 |
+
if ( ! state.settings.hasOwnProperty( groupId ) ) {
|
175 |
+
continue;
|
176 |
+
}
|
177 |
+
|
178 |
+
for ( const module in state.settings[ groupId ] ) {
|
179 |
+
if ( ! state.settings[ groupId ].hasOwnProperty( module ) ) {
|
180 |
+
continue;
|
181 |
+
}
|
182 |
+
|
183 |
+
for ( const setting in state.settings[ groupId ][ module ] ) {
|
184 |
+
if ( ! state.settings[ groupId ][ module ].hasOwnProperty( setting ) ) {
|
185 |
+
continue;
|
186 |
+
}
|
187 |
+
|
188 |
+
if ( ! bySetting[ module ] ) {
|
189 |
+
bySetting[ module ] = {};
|
190 |
+
}
|
191 |
+
|
192 |
+
if ( ! bySetting[ module ][ setting ] ) {
|
193 |
+
bySetting[ module ][ setting ] = [];
|
194 |
+
}
|
195 |
+
|
196 |
+
if ( state.settings[ groupId ][ module ][ setting ] ) {
|
197 |
+
bySetting[ module ][ setting ].push( groupId );
|
198 |
+
}
|
199 |
+
}
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
return bySetting;
|
204 |
+
}
|
core/modules/user-groups/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/modules/user-groups/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'User Groups', 'better-wp-security' ),
|
5 |
+
];
|
core/modules/user-groups/settings-page.php
ADDED
@@ -0,0 +1,43 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace iThemesSecurity\User_Groups;
|
4 |
+
|
5 |
+
class Settings_Page extends \ITSEC_Module_Settings_Page {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
$this->id = 'user-groups';
|
9 |
+
$this->title = __( 'User Groups', 'better-wp-security' );
|
10 |
+
$this->description = __( 'Manage user groups.', 'better-wp-security' );
|
11 |
+
$this->type = 'recommended';
|
12 |
+
$this->can_save = false;
|
13 |
+
$this->documentation = 'https://ithemeshelp.zendesk.com/hc/en-us/articles/360042653774';
|
14 |
+
|
15 |
+
parent::__construct();
|
16 |
+
}
|
17 |
+
|
18 |
+
public function enqueue_scripts_and_styles() {
|
19 |
+
$preload = \ITSEC_Lib::preload_rest_requests( [
|
20 |
+
'/ithemes-security/v1/user-matchables?_embed=1' => [
|
21 |
+
'route' => '/ithemes-security/v1/user-matchables',
|
22 |
+
'embed' => true,
|
23 |
+
],
|
24 |
+
'/ithemes-security/v1?context=help' => [
|
25 |
+
'route' => '/ithemes-security/v1',
|
26 |
+
'query' => [ 'context' => 'help' ],
|
27 |
+
]
|
28 |
+
] );
|
29 |
+
|
30 |
+
wp_enqueue_script( 'itsec-user-groups-settings' );
|
31 |
+
wp_enqueue_style( 'itsec-user-groups-settings' );
|
32 |
+
wp_add_inline_script(
|
33 |
+
'itsec-user-groups-settings',
|
34 |
+
sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload ) )
|
35 |
+
);
|
36 |
+
}
|
37 |
+
|
38 |
+
public function render( $form ) {
|
39 |
+
echo '<div id="itsec-user-groups-settings-root"></div>';
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
new Settings_Page();
|
core/modules/wordpress-tweaks/labels.php
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
return [
|
4 |
+
'title' => __( 'WordPress Tweaks', 'better-wp-security' ),
|
5 |
+
];
|
core/package.json
CHANGED
@@ -9,28 +9,28 @@
|
|
9 |
Â
"dependencies": {
|
10 |
Â
"@wordpress/a11y": "*",
|
11 |
Â
"@wordpress/api-fetch": "*",
|
12 |
-
"@wordpress/autop": "
|
13 |
-
"@wordpress/components": "
|
14 |
-
"@wordpress/compose": "
|
15 |
-
"@wordpress/data": "
|
16 |
-
"@wordpress/date": "
|
17 |
Â
"@wordpress/dom-ready": "*",
|
18 |
Â
"@wordpress/element": "*",
|
19 |
Â
"@wordpress/hooks": "*",
|
20 |
Â
"@wordpress/html-entities": "*",
|
21 |
Â
"@wordpress/i18n": "*",
|
22 |
Â
"@wordpress/is-shallow-equal": "*",
|
23 |
-
"@wordpress/keycodes": "
|
24 |
Â
"@wordpress/notices": "*",
|
25 |
-
"@wordpress/plugins": "
|
26 |
Â
"@wordpress/redux-routine": "*",
|
27 |
-
"@wordpress/rich-text": "
|
28 |
Â
"@wordpress/url": "*",
|
29 |
Â
"@wordpress/viewport": "*",
|
30 |
Â
"classnames": "^2.2.6",
|
31 |
Â
"contrast": "^1.0.1",
|
32 |
Â
"li": "^1.3.0",
|
33 |
-
"lodash": "^4.17.
|
34 |
Â
"memize": "^1.0.5",
|
35 |
Â
"react": "^16.6.3",
|
36 |
Â
"react-error-boundary": "^1.2.3",
|
@@ -38,11 +38,14 @@
|
|
38 |
Â
"react-select": "^2.4.1",
|
39 |
Â
"react-transition-group": "^2.0.0",
|
40 |
Â
"recharts": "^1.5.0",
|
41 |
-
"rememo": "^3.0.0"
|
Â
|
|
Â
|
|
42 |
Â
},
|
43 |
Â
"devDependencies": {
|
44 |
Â
"@babel/core": "^7.3.3",
|
45 |
Â
"@babel/plugin-proposal-class-properties": "^7.3.3",
|
Â
|
|
46 |
Â
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
47 |
Â
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
48 |
Â
"@babel/runtime-corejs2": "^7.3.1",
|
@@ -110,8 +113,11 @@
|
|
110 |
Â
"test-unit:update": "npm run test-unit -- --updateSnapshot",
|
111 |
Â
"test-unit:watch": "npm run test-unit -- --watch",
|
112 |
Â
"watch": "./node_modules/.bin/webpack --watch",
|
Â
|
|
113 |
Â
"test-wpunit": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpunit",
|
114 |
Â
"test-acceptance": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run acceptance",
|
115 |
-
"test-
|
Â
|
|
Â
|
|
116 |
Â
}
|
117 |
Â
}
|
9 |
Â
"dependencies": {
|
10 |
Â
"@wordpress/a11y": "*",
|
11 |
Â
"@wordpress/api-fetch": "*",
|
12 |
+
"@wordpress/autop": "*",
|
13 |
+
"@wordpress/components": "*",
|
14 |
+
"@wordpress/compose": "*",
|
15 |
+
"@wordpress/data": "*",
|
16 |
+
"@wordpress/date": "*",
|
17 |
Â
"@wordpress/dom-ready": "*",
|
18 |
Â
"@wordpress/element": "*",
|
19 |
Â
"@wordpress/hooks": "*",
|
20 |
Â
"@wordpress/html-entities": "*",
|
21 |
Â
"@wordpress/i18n": "*",
|
22 |
Â
"@wordpress/is-shallow-equal": "*",
|
23 |
+
"@wordpress/keycodes": "*",
|
24 |
Â
"@wordpress/notices": "*",
|
25 |
+
"@wordpress/plugins": "*",
|
26 |
Â
"@wordpress/redux-routine": "*",
|
27 |
+
"@wordpress/rich-text": "*",
|
28 |
Â
"@wordpress/url": "*",
|
29 |
Â
"@wordpress/viewport": "*",
|
30 |
Â
"classnames": "^2.2.6",
|
31 |
Â
"contrast": "^1.0.1",
|
32 |
Â
"li": "^1.3.0",
|
33 |
+
"lodash": "^4.17.15",
|
34 |
Â
"memize": "^1.0.5",
|
35 |
Â
"react": "^16.6.3",
|
36 |
Â
"react-error-boundary": "^1.2.3",
|
38 |
Â
"react-select": "^2.4.1",
|
39 |
Â
"react-transition-group": "^2.0.0",
|
40 |
Â
"recharts": "^1.5.0",
|
41 |
+
"rememo": "^3.0.0",
|
42 |
+
"uri-templates": "^0.2.0",
|
43 |
+
"uuid": "^3.3.3"
|
44 |
Â
},
|
45 |
Â
"devDependencies": {
|
46 |
Â
"@babel/core": "^7.3.3",
|
47 |
Â
"@babel/plugin-proposal-class-properties": "^7.3.3",
|
48 |
+
"@babel/plugin-proposal-export-default-from": "^7.8.3",
|
49 |
Â
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
50 |
Â
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
51 |
Â
"@babel/runtime-corejs2": "^7.3.1",
|
113 |
Â
"test-unit:update": "npm run test-unit -- --updateSnapshot",
|
114 |
Â
"test-unit:watch": "npm run test-unit -- --watch",
|
115 |
Â
"watch": "./node_modules/.bin/webpack --watch",
|
116 |
+
"test-up": "./bin/test-up.sh",
|
117 |
Â
"test-wpunit": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpunit",
|
118 |
Â
"test-acceptance": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run acceptance",
|
119 |
+
"test-cli": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpcli",
|
120 |
+
"test-upgrade": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run upgrade",
|
121 |
+
"test-build": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept build"
|
122 |
Â
}
|
123 |
Â
}
|
core/packages/components/src/checkbox-control/index.js
ADDED
@@ -0,0 +1,44 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { withInstanceId } from '@wordpress/compose';
|
5 |
+
import { BaseControl, Dashicon } from '@wordpress/components';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Internal dependencies
|
9 |
+
*/
|
10 |
+
import './style.scss';
|
11 |
+
|
12 |
+
function CheckboxControl( { label, className, heading, checked, help, instanceId, onChange, indeterminate, ...props } ) {
|
13 |
+
const id = `inspector-checkbox-control-${ instanceId }`;
|
14 |
+
const onChangeValue = ( event ) => onChange( event.target.checked );
|
15 |
+
|
16 |
+
return (
|
17 |
+
<BaseControl label={ heading } id={ id } help={ help } className={ className }>
|
18 |
+
<span className="components-checkbox-control__input-container">
|
19 |
+
<input
|
20 |
+
id={ id }
|
21 |
+
className="components-checkbox-control__input"
|
22 |
+
type="checkbox"
|
23 |
+
value="1"
|
24 |
+
onChange={ onChangeValue }
|
25 |
+
checked={ checked }
|
26 |
+
aria-describedby={ !! help ? id + '__help' : undefined }
|
27 |
+
ref={ ( ref ) => {
|
28 |
+
if ( ref ) {
|
29 |
+
ref.indeterminate = indeterminate;
|
30 |
+
}
|
31 |
+
} }
|
32 |
+
{ ...props }
|
33 |
+
/>
|
34 |
+
{ checked ? <Dashicon icon="yes" className="components-checkbox-control__checked" role="presentation" /> : null }
|
35 |
+
{ indeterminate ? <Dashicon icon="minus" className="components-checkbox-control__checked components-checkbox-control__checked--indeterminate" role="presentation" /> : null }
|
36 |
+
</span>
|
37 |
+
<label className="components-checkbox-control__label" htmlFor={ id }>
|
38 |
+
{ label }
|
39 |
+
</label>
|
40 |
+
</BaseControl>
|
41 |
+
);
|
42 |
+
}
|
43 |
+
|
44 |
+
export default withInstanceId( CheckboxControl );
|
core/packages/components/src/checkbox-control/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/checkbox-control/style.scss
ADDED
@@ -0,0 +1,111 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@import "mixins.scss";
|
2 |
+
|
3 |
+
$checkbox-input-size: 16px;
|
4 |
+
$checkbox-input-size-sm: 25px; // width + height for small viewports
|
5 |
+
|
6 |
+
.components-checkbox-control__input[type="checkbox"] {
|
7 |
+
border: 1px solid #b4b9be;
|
8 |
+
background: #fff;
|
9 |
+
color: #555;
|
10 |
+
clear: none;
|
11 |
+
cursor: pointer;
|
12 |
+
display: inline-block;
|
13 |
+
line-height: 0;
|
14 |
+
margin: 0 4px 0 0;
|
15 |
+
outline: 0;
|
16 |
+
padding: 0 !important;
|
17 |
+
text-align: center;
|
18 |
+
vertical-align: top;
|
19 |
+
width: $checkbox-input-size-sm;
|
20 |
+
height: $checkbox-input-size-sm;
|
21 |
+
@include break-small() {
|
22 |
+
height: $checkbox-input-size;
|
23 |
+
width: $checkbox-input-size;
|
24 |
+
}
|
25 |
+
-webkit-appearance: none;
|
26 |
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
27 |
+
transition: 0.05s border-color ease-in-out;
|
28 |
+
|
29 |
+
&:focus {
|
30 |
+
border-color: #5b9dd9;
|
31 |
+
box-shadow: 0 0 2px rgba(30, 140, 190, 0.8);
|
32 |
+
// Only visible in Windows High Contrast mode.
|
33 |
+
outline: 2px solid transparent;
|
34 |
+
}
|
35 |
+
|
36 |
+
&:checked {
|
37 |
+
background: #11a0d2;
|
38 |
+
border-color: #11a0d2;
|
39 |
+
|
40 |
+
// Hide default checkbox styles in IE.
|
41 |
+
&::-ms-check {
|
42 |
+
opacity: 0;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
&:focus:checked {
|
47 |
+
border: none;
|
48 |
+
}
|
49 |
+
|
50 |
+
&:checked::before {
|
51 |
+
content: none;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
.components-checkbox-control__input-container {
|
56 |
+
position: relative;
|
57 |
+
display: inline-block;
|
58 |
+
margin-right: 12px;
|
59 |
+
vertical-align: middle;
|
60 |
+
width: $checkbox-input-size-sm;
|
61 |
+
height: $checkbox-input-size-sm;
|
62 |
+
@include break-small() {
|
63 |
+
width: $checkbox-input-size;
|
64 |
+
height: $checkbox-input-size;
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
svg.dashicon.components-checkbox-control__checked {
|
69 |
+
fill: #fff;
|
70 |
+
cursor: pointer;
|
71 |
+
position: absolute;
|
72 |
+
left: -4px;
|
73 |
+
top: -2px;
|
74 |
+
width: 31px;
|
75 |
+
height: 31px;
|
76 |
+
@include break-small() {
|
77 |
+
width: 21px;
|
78 |
+
height: 21px;
|
79 |
+
left: -3px;
|
80 |
+
}
|
81 |
+
user-select: none;
|
82 |
+
pointer-events: none;
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
.components-checkbox-control__input[type="checkbox"] {
|
87 |
+
&:indeterminate {
|
88 |
+
background: #11a0d2;
|
89 |
+
border-color: #11a0d2;
|
90 |
+
|
91 |
+
// Hide default checkbox styles in IE.
|
92 |
+
&::-ms-check {
|
93 |
+
opacity: 0;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
&:focus:checked,
|
98 |
+
&:focus:indeterminate {
|
99 |
+
border: none;
|
100 |
+
}
|
101 |
+
|
102 |
+
&:checked::before,
|
103 |
+
&:indeterminate::before {
|
104 |
+
content: none;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
svg.dashicon.components-checkbox-control__checked.components-checkbox-control__checked--indeterminate {
|
109 |
+
width: 16px;
|
110 |
+
left: 0;
|
111 |
+
}
|
core/packages/components/src/checkbox-group-control/index.js
ADDED
@@ -0,0 +1,35 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { omit, isArray } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { CheckboxControl } from '@wordpress/components';
|
10 |
+
|
11 |
+
export default function CheckboxGroupControl( { value, onChange, options, label, help } ) {
|
12 |
+
let isChecked, update;
|
13 |
+
|
14 |
+
if ( isArray( value ) ) {
|
15 |
+
isChecked = ( option ) => value.includes( option.value );
|
16 |
+
update = ( option ) => ( checked ) => onChange( checked ? [ ...value, option.value ] : value.filter( ( maybeValue ) => maybeValue !== option.value ) );
|
17 |
+
} else {
|
18 |
+
isChecked = ( option ) => value[ option.value ] || false;
|
19 |
+
update = ( option ) => ( checked ) => onChange( { ...value, [ option.value ]: checked } );
|
20 |
+
}
|
21 |
+
|
22 |
+
return (
|
23 |
+
<fieldset className="components-base-control">
|
24 |
+
<div className="components-base-control__field">
|
25 |
+
<legend className="components-base-control__label">{ label }</legend>
|
26 |
+
{ help && <p className="components-base-control__help">{ help }</p> }
|
27 |
+
{ options.map( ( option ) => (
|
28 |
+
<div key={ option.value }>
|
29 |
+
<CheckboxControl { ...omit( option, [ 'value' ] ) } checked={ isChecked( option ) } onChange={ update( option ) } />
|
30 |
+
</div>
|
31 |
+
) ) }
|
32 |
+
</div>
|
33 |
+
</fieldset>
|
34 |
+
);
|
35 |
+
}
|
core/packages/components/src/checkbox-group-control/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/hierarchical-checkbox-control/index.js
ADDED
@@ -0,0 +1,267 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { isArray } from 'lodash';
|
5 |
+
import memize from 'memize';
|
6 |
+
import classnames from 'classnames';
|
7 |
+
|
8 |
+
/**
|
9 |
+
* WordPress dependencies
|
10 |
+
*/
|
11 |
+
import { Component } from '@wordpress/element';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Internal dependencies
|
15 |
+
*/
|
16 |
+
import { CheckboxControl } from '../';
|
17 |
+
import './style.scss';
|
18 |
+
|
19 |
+
class Node {
|
20 |
+
tree;
|
21 |
+
name;
|
22 |
+
data;
|
23 |
+
parent;
|
24 |
+
children;
|
25 |
+
|
26 |
+
constructor( tree, name, data, parent = null, children = [] ) {
|
27 |
+
this.tree = tree;
|
28 |
+
this.name = name;
|
29 |
+
this.data = data;
|
30 |
+
this.parent = parent;
|
31 |
+
this.children = children;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Get the parent node.
|
36 |
+
* @return {Node|null}
|
37 |
+
*/
|
38 |
+
getParent() {
|
39 |
+
if ( ! this.parent ) {
|
40 |
+
return null;
|
41 |
+
}
|
42 |
+
|
43 |
+
return this.tree.nodes[ this.parent ];
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get all parents of an option.
|
48 |
+
*
|
49 |
+
* @return {[string]}
|
50 |
+
*/
|
51 |
+
getAllParents() {
|
52 |
+
const all = [];
|
53 |
+
let parent = this.getParent();
|
54 |
+
|
55 |
+
while ( parent ) {
|
56 |
+
all.push( parent.name );
|
57 |
+
parent = parent.getParent();
|
58 |
+
}
|
59 |
+
|
60 |
+
return all;
|
61 |
+
}
|
62 |
+
|
63 |
+
hasChildren() {
|
64 |
+
return this.children.length > 0;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get all children.
|
69 |
+
*
|
70 |
+
* @return {[string]}
|
71 |
+
*/
|
72 |
+
getAllChildren() {
|
73 |
+
const all = [];
|
74 |
+
|
75 |
+
if ( ! this.hasChildren() ) {
|
76 |
+
return all;
|
77 |
+
}
|
78 |
+
|
79 |
+
for ( const child of this ) {
|
80 |
+
all.push( child.name, ...child.getAllChildren() );
|
81 |
+
}
|
82 |
+
|
83 |
+
return all;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Iterator over all children of the node.
|
88 |
+
* @yields {Node}
|
89 |
+
*/
|
90 |
+
*[Symbol.iterator]() {
|
91 |
+
for ( let i = 0; i < this.children.length; i++ ) {
|
92 |
+
const name = this.children[ i ];
|
93 |
+
yield this.tree.nodes[ name ];
|
94 |
+
}
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
class Tree {
|
99 |
+
nodes = {};
|
100 |
+
ordered = [];
|
101 |
+
|
102 |
+
add( name, data, parent = null ) {
|
103 |
+
this.ordered.push( name );
|
104 |
+
|
105 |
+
if ( this.nodes[ name ] ) {
|
106 |
+
this.nodes[ name ].data = data;
|
107 |
+
this.nodes[ name ].parent = parent;
|
108 |
+
} else {
|
109 |
+
this.nodes[ name ] = new Node( this, name, data, parent );
|
110 |
+
}
|
111 |
+
|
112 |
+
if ( parent ) {
|
113 |
+
if ( this.nodes[ parent ] ) {
|
114 |
+
this.nodes[ parent ].children.push( name );
|
115 |
+
} else {
|
116 |
+
this.nodes[ parent ] = new Node( this, parent );
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
*[Symbol.iterator]() {
|
122 |
+
for ( let i = 0; i < this.ordered.length; i++ ) {
|
123 |
+
const name = this.ordered[ i ];
|
124 |
+
|
125 |
+
if ( ! this.nodes[ name ].parent ) {
|
126 |
+
yield this.nodes[ name ];
|
127 |
+
}
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
const toTree = memize( ( options ) => {
|
133 |
+
const tree = new Tree();
|
134 |
+
|
135 |
+
for ( const option of options ) {
|
136 |
+
tree.add( option.value, option, option.parent );
|
137 |
+
}
|
138 |
+
|
139 |
+
return tree;
|
140 |
+
} );
|
141 |
+
|
142 |
+
class HierarchicalCheckboxControl extends Component {
|
143 |
+
props;
|
144 |
+
|
145 |
+
constructor() {
|
146 |
+
super( ...arguments );
|
147 |
+
|
148 |
+
this.renderOption = this.renderOption.bind( this );
|
149 |
+
this.isChecked = this.isChecked.bind( this );
|
150 |
+
this.isIndeterminate = this.isIndeterminate.bind( this );
|
151 |
+
this.onChange = this.onChange.bind( this );
|
152 |
+
}
|
153 |
+
|
154 |
+
indeterminate( ref ) {
|
155 |
+
ref.indeterminate = true;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Is the given option checked.
|
160 |
+
* @param {Node|null} value
|
161 |
+
* @return {boolean}
|
162 |
+
*/
|
163 |
+
isChecked( value ) {
|
164 |
+
if ( ! value ) {
|
165 |
+
return false;
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( isArray( this.props.value ) ) {
|
169 |
+
return this.props.value.includes( value.name ) || this.isChecked( value.getParent() );
|
170 |
+
}
|
171 |
+
|
172 |
+
return this.props.value[ value.name ] || this.isChecked( value.getParent() );
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Does this option have an indeterminate value.
|
177 |
+
* @param {Node} option
|
178 |
+
* @return {boolean}
|
179 |
+
*/
|
180 |
+
isIndeterminate( option ) {
|
181 |
+
if ( ! option.hasChildren() ) {
|
182 |
+
return false;
|
183 |
+
}
|
184 |
+
|
185 |
+
for ( const child of option ) {
|
186 |
+
if ( this.isChecked( child ) ) {
|
187 |
+
return true;
|
188 |
+
}
|
189 |
+
|
190 |
+
if ( this.isIndeterminate( child ) ) {
|
191 |
+
return true;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
return false;
|
196 |
+
}
|
197 |
+
|
198 |
+
onChange( option, checked ) {
|
199 |
+
const values = [ option.name, ...option.getAllChildren() ];
|
200 |
+
const parents = checked ? [] : option.getAllParents();
|
201 |
+
|
202 |
+
if ( isArray( this.props.value ) ) {
|
203 |
+
let changed;
|
204 |
+
|
205 |
+
if ( checked ) {
|
206 |
+
changed = [ ...this.props.value, ...values ];
|
207 |
+
} else {
|
208 |
+
changed = this.props.value.filter( ( maybeValue ) => ! values.includes( maybeValue ) && ! parents.includes( maybeValue ) );
|
209 |
+
}
|
210 |
+
|
211 |
+
this.props.onChange( changed );
|
212 |
+
} else {
|
213 |
+
this.props.onChange( {
|
214 |
+
...this.props.value,
|
215 |
+
...values.reduce( ( acc, key ) => acc[ key ] = checked, {} ),
|
216 |
+
...parents.reduce( ( acc, key ) => acc[ key ] = false, {} ),
|
217 |
+
} );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
render() {
|
222 |
+
const { label, help, options } = this.props;
|
223 |
+
const tree = toTree( options );
|
224 |
+
|
225 |
+
return (
|
226 |
+
<fieldset className="components-base-control">
|
227 |
+
<div className="components-base-control__field">
|
228 |
+
<legend className="components-base-control__label">{ label }</legend>
|
229 |
+
{ help && <p className="components-base-control__help">{ help }</p> }
|
230 |
+
</div>
|
231 |
+
<ul className="components-hierarchical-checkbox-control__group">
|
232 |
+
{ Array.from( tree, this.renderOption ) }
|
233 |
+
</ul>
|
234 |
+
</fieldset>
|
235 |
+
);
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Render a single option and its children.
|
240 |
+
* @param {Node} option
|
241 |
+
* @return {*}
|
242 |
+
*/
|
243 |
+
renderOption( option ) {
|
244 |
+
const { value, selectable = true, ...rest } = option.data;
|
245 |
+
const checked = this.isChecked( option );
|
246 |
+
const indeterminate = ! checked && this.isIndeterminate( option );
|
247 |
+
|
248 |
+
return (
|
249 |
+
<li key={ value } className={ classnames( 'components-hierarchical-checkbox-control__option', {
|
250 |
+
'components-hierarchical-checkbox-control__option--has-children': option.hasChildren(),
|
251 |
+
} ) }>
|
252 |
+
<CheckboxControl { ...rest }
|
253 |
+
checked={ selectable ? checked : false }
|
254 |
+
disabled={ ! selectable || this.props.disabled }
|
255 |
+
indeterminate={ indeterminate }
|
256 |
+
onChange={ ( newChecked ) => this.onChange( option, newChecked ) } />
|
257 |
+
{ option.hasChildren() && (
|
258 |
+
<ul className="components-hierarchical-checkbox-control__group">
|
259 |
+
{ Array.from( option, this.renderOption ) }
|
260 |
+
</ul>
|
261 |
+
) }
|
262 |
+
</li>
|
263 |
+
);
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
export default HierarchicalCheckboxControl;
|
core/packages/components/src/hierarchical-checkbox-control/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/hierarchical-checkbox-control/style.scss
ADDED
@@ -0,0 +1,20 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.components-base-control > ul.components-hierarchical-checkbox-control__group {
|
2 |
+
padding-left: 0;
|
3 |
+
}
|
4 |
+
|
5 |
+
ul.components-hierarchical-checkbox-control__group {
|
6 |
+
padding-left: 1em;
|
7 |
+
}
|
8 |
+
|
9 |
+
.components-hierarchical-checkbox-control__group .components-hierarchical-checkbox-control__option {
|
10 |
+
list-style-type: none;
|
11 |
+
}
|
12 |
+
|
13 |
+
.components-hierarchical-checkbox-control__option--has-children {
|
14 |
+
margin-bottom: 1em;
|
15 |
+
}
|
16 |
+
|
17 |
+
.components-hierarchical-checkbox-control__option--has-children > .components-base-control {
|
18 |
+
font-weight: bold;
|
19 |
+
}
|
20 |
+
|
core/packages/components/src/index.js
CHANGED
@@ -6,3 +6,10 @@ export { default as AsyncSelect } from './async-select';
|
|
6 |
Â
export { default as HoverDetector } from './hover-detector';
|
7 |
Â
export { default as CloseButton } from './close-button';
|
8 |
Â
export { default as Loader } from './loader';
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
6 |
Â
export { default as HoverDetector } from './hover-detector';
|
7 |
Â
export { default as CloseButton } from './close-button';
|
8 |
Â
export { default as Loader } from './loader';
|
9 |
+
export { default as CheckboxGroupControl } from './checkbox-group-control';
|
10 |
+
export { default as HierarchicalCheckboxControl } from './hierarchical-checkbox-control';
|
11 |
+
export { default as NoticeList } from './notice-list';
|
12 |
+
export { default as ModuleSettingsNoticeList } from './module-settings-notice-list';
|
13 |
+
export { default as ToggleControl } from './toggle-control';
|
14 |
+
export { default as CheckboxControl } from './checkbox-control';
|
15 |
+
export { default as TabPanel, ControlledTabPanel, ControlledMultiTabPanel } from './tab-panel';
|
core/packages/components/src/module-settings-notice-list/index.js
ADDED
@@ -0,0 +1,95 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { filter, omit } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { SnackbarList } from '@wordpress/components';
|
10 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
11 |
+
import { compose } from '@wordpress/compose';
|
12 |
+
import { Fragment, useEffect, useRef } from '@wordpress/element';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Internal dependencies
|
16 |
+
*/
|
17 |
+
import Notice from './notice';
|
18 |
+
import './style.scss';
|
19 |
+
|
20 |
+
function usePrevious( value ) {
|
21 |
+
const ref = useRef();
|
22 |
+
useEffect( () => {
|
23 |
+
ref.current = value;
|
24 |
+
} );
|
25 |
+
return ref.current;
|
26 |
+
}
|
27 |
+
|
28 |
+
function calculateLength( notices ) {
|
29 |
+
if ( ! SnackbarList ) {
|
30 |
+
return notices.length;
|
31 |
+
}
|
32 |
+
|
33 |
+
let length = 0;
|
34 |
+
|
35 |
+
for ( const notice of notices ) {
|
36 |
+
if ( notice.type !== 'snackbar' ) {
|
37 |
+
length++;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
return length;
|
42 |
+
}
|
43 |
+
|
44 |
+
function ModuleSettingsNoticeList( { notices, onRemove } ) {
|
45 |
+
const length = calculateLength( notices );
|
46 |
+
const prevLength = usePrevious( length );
|
47 |
+
useEffect( () => {
|
48 |
+
if ( length > prevLength && window.itsecSettingsPage ) {
|
49 |
+
window.itsecSettingsPage.scrollTop();
|
50 |
+
}
|
51 |
+
}, [ length, prevLength ] );
|
52 |
+
|
53 |
+
const createRemoveNotice = ( id ) => () => onRemove( id );
|
54 |
+
const snackbarNotices = SnackbarList ? filter( notices, {
|
55 |
+
type: 'snackbar',
|
56 |
+
} ) : [];
|
57 |
+
|
58 |
+
return (
|
59 |
+
<Fragment>
|
60 |
+
<div className="itsec-module-settings-notice-list">
|
61 |
+
{ notices.map( ( notice ) => {
|
62 |
+
if ( notice.type === 'snackbar' && SnackbarList ) {
|
63 |
+
return null;
|
64 |
+
}
|
65 |
+
|
66 |
+
return (
|
67 |
+
<Notice
|
68 |
+
{ ...omit( notice, [ 'content' ] ) }
|
69 |
+
key={ notice.id }
|
70 |
+
onRemove={ createRemoveNotice( notice.id ) }
|
71 |
+
>
|
72 |
+
{ notice.content }
|
73 |
+
</Notice>
|
74 |
+
);
|
75 |
+
} ) }
|
76 |
+
</div>
|
77 |
+
{ SnackbarList && <SnackbarList
|
78 |
+
notices={ snackbarNotices }
|
79 |
+
className="components-editor-notices__snackbar"
|
80 |
+
onRemove={ onRemove } />
|
81 |
+
}
|
82 |
+
</Fragment>
|
83 |
+
);
|
84 |
+
}
|
85 |
+
|
86 |
+
export default compose( [
|
87 |
+
withSelect( ( select, { context = 'ithemes-security' } ) => ( {
|
88 |
+
notices: select( 'core/notices' ).getNotices( context ),
|
89 |
+
} ) ),
|
90 |
+
withDispatch( ( dispatch, { context = 'ithemes-security' } ) => ( {
|
91 |
+
onRemove( noticeId ) {
|
92 |
+
return dispatch( 'core/notices' ).removeNotice( noticeId, context );
|
93 |
+
},
|
94 |
+
} ) ),
|
95 |
+
] )( ModuleSettingsNoticeList );
|
core/packages/components/src/module-settings-notice-list/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/module-settings-notice-list/notice.js
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { noop } from 'lodash';
|
5 |
+
import classnames from 'classnames';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { __ } from '@wordpress/i18n';
|
11 |
+
import { Button } from '@wordpress/components';
|
12 |
+
|
13 |
+
function Notice( {
|
14 |
+
className,
|
15 |
+
status,
|
16 |
+
children,
|
17 |
+
onRemove = noop,
|
18 |
+
isDismissible = true,
|
19 |
+
actions = [],
|
20 |
+
} ) {
|
21 |
+
const classes = classnames( className, 'notice', 'notice-alt', 'notice-' + status, {
|
22 |
+
'is-dismissible': isDismissible,
|
23 |
+
} );
|
24 |
+
|
25 |
+
return (
|
26 |
+
<div className={ classes }>
|
27 |
+
<p>
|
28 |
+
{ children }
|
29 |
+
{ actions.map( ( { className: buttonCustomClasses, label, onClick, url, isLink = false }, index ) => (
|
30 |
+
<Button
|
31 |
+
key={ index }
|
32 |
+
href={ url }
|
33 |
+
isSmall={ ! isLink && ! url }
|
34 |
+
isLink={ isLink || url }
|
35 |
+
onClick={ url ? undefined : () => {
|
36 |
+
onRemove();
|
37 |
+
onClick();
|
38 |
+
} }
|
39 |
+
className={ classnames( 'notice__action', buttonCustomClasses ) }
|
40 |
+
>
|
41 |
+
{ label }
|
42 |
+
</Button>
|
43 |
+
) ) }
|
44 |
+
</p>
|
45 |
+
{ isDismissible && (
|
46 |
+
<button type="button" className="notice-dismiss" onClick={ onRemove }>
|
47 |
+
<span className="screen-reader-text">{ __( 'Dismiss this notice', 'better-wp-security' ) }</span>
|
48 |
+
</button>
|
49 |
+
) }
|
50 |
+
</div>
|
51 |
+
);
|
52 |
+
}
|
53 |
+
|
54 |
+
export default Notice;
|
core/packages/components/src/module-settings-notice-list/style.scss
ADDED
@@ -0,0 +1,25 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-module-settings-notice-list .notice .notice__action {
|
2 |
+
margin-left: .5em;
|
3 |
+
}
|
4 |
+
|
5 |
+
.itsec-module-settings-notice-list {
|
6 |
+
position: relative;
|
7 |
+
padding-bottom: 1em;
|
8 |
+
font-size: 13px;
|
9 |
+
|
10 |
+
&:empty {
|
11 |
+
display: none;
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
15 |
+
.itsec-module-settings-content .components-editor-notices__snackbar {
|
16 |
+
position: fixed;
|
17 |
+
bottom: 100px;
|
18 |
+
padding-left: 16px;
|
19 |
+
padding-right: 16px;
|
20 |
+
width: max-content;
|
21 |
+
}
|
22 |
+
|
23 |
+
.itsec-module-settings-content .components-snackbar {
|
24 |
+
width: max-content;
|
25 |
+
}
|
core/packages/components/src/notice-list/index.js
ADDED
@@ -0,0 +1,48 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { filter } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { Fragment } from '@wordpress/element';
|
10 |
+
import { NoticeList, SnackbarList } from '@wordpress/components';
|
11 |
+
import { withSelect, withDispatch } from '@wordpress/data';
|
12 |
+
import { compose } from '@wordpress/compose';
|
13 |
+
|
14 |
+
function CompositeNoticeList( { notices, onRemove } ) {
|
15 |
+
const dismissibleNotices = filter( notices, ( notice ) => notice.isDismissible && ( ! notice.type || notice.type === 'default' ) );
|
16 |
+
const nonDismissibleNotices = filter( notices, ( notice ) => ! notice.isDismissible && ( ! notice.type || notice.type === 'default' ) );
|
17 |
+
const snackbarNotices = SnackbarList ? filter( notices, {
|
18 |
+
type: 'snackbar',
|
19 |
+
} ) : [];
|
20 |
+
|
21 |
+
return (
|
22 |
+
<Fragment>
|
23 |
+
<NoticeList
|
24 |
+
notices={ nonDismissibleNotices }
|
25 |
+
className="components-editor-notices__pinned" />
|
26 |
+
<NoticeList
|
27 |
+
notices={ dismissibleNotices }
|
28 |
+
className="components-editor-notices__dismissible"
|
29 |
+
onRemove={ onRemove } />
|
30 |
+
{ SnackbarList && <SnackbarList
|
31 |
+
notices={ snackbarNotices }
|
32 |
+
className="components-editor-notices__snackbar"
|
33 |
+
onRemove={ onRemove } />
|
34 |
+
}
|
35 |
+
</Fragment>
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
+
export default compose( [
|
40 |
+
withSelect( ( select, { context = 'ithemes-security' } ) => ( {
|
41 |
+
notices: select( 'core/notices' ).getNotices( context ),
|
42 |
+
} ) ),
|
43 |
+
withDispatch( ( dispatch, { context = 'ithemes-security' } ) => ( {
|
44 |
+
onRemove( noticeId ) {
|
45 |
+
return dispatch( 'core/notices' ).removeNotice( noticeId, context );
|
46 |
+
},
|
47 |
+
} ) ),
|
48 |
+
] )( CompositeNoticeList );
|
core/packages/components/src/notice-list/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/tab-panel/controlled.js
ADDED
@@ -0,0 +1,98 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import classnames from 'classnames';
|
5 |
+
import { find, noop, partial } from 'lodash';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { Component } from '@wordpress/element';
|
11 |
+
import { NavigableMenu } from '@wordpress/components';
|
12 |
+
import { withInstanceId } from '@wordpress/compose';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Internal dependencies
|
16 |
+
*/
|
17 |
+
import TabButton from './tab-button';
|
18 |
+
|
19 |
+
class ControlledTabPanel extends Component {
|
20 |
+
constructor() {
|
21 |
+
super( ...arguments );
|
22 |
+
|
23 |
+
this.handleClick = this.handleClick.bind( this );
|
24 |
+
this.onNavigate = this.onNavigate.bind( this );
|
25 |
+
this.onKeyDown = this.onKeyDown.bind( this );
|
26 |
+
}
|
27 |
+
|
28 |
+
handleClick( tabKey ) {
|
29 |
+
const { onSelect = noop } = this.props;
|
30 |
+
onSelect( tabKey );
|
31 |
+
}
|
32 |
+
|
33 |
+
onNavigate( childIndex, child ) {
|
34 |
+
const event = this.event;
|
35 |
+
|
36 |
+
if ( event && event.target.getAttribute( 'role' ) === 'tab' ) {
|
37 |
+
event.preventDefault();
|
38 |
+
}
|
39 |
+
|
40 |
+
child.click();
|
41 |
+
}
|
42 |
+
|
43 |
+
onKeyDown( event ) {
|
44 |
+
// Stores the event for use in onNavigate. We don't need to persist the event
|
45 |
+
// since onNavigate is called during the original onKeyDown event handler.
|
46 |
+
this.event = event;
|
47 |
+
}
|
48 |
+
|
49 |
+
render() {
|
50 |
+
const {
|
51 |
+
activeClass = 'is-active',
|
52 |
+
className,
|
53 |
+
instanceId,
|
54 |
+
orientation = 'horizontal',
|
55 |
+
tabs,
|
56 |
+
selected,
|
57 |
+
} = this.props;
|
58 |
+
|
59 |
+
const selectedTab = find( tabs, { name: selected } ) || tabs[ 0 ];
|
60 |
+
const selectedId = instanceId + '-' + selectedTab.name;
|
61 |
+
|
62 |
+
return (
|
63 |
+
<div className={ className }>
|
64 |
+
<NavigableMenu
|
65 |
+
role="tablist"
|
66 |
+
orientation={ orientation }
|
67 |
+
onNavigate={ this.onNavigate }
|
68 |
+
onKeyDown={ this.onKeyDown }
|
69 |
+
className="components-tab-panel__tabs"
|
70 |
+
>
|
71 |
+
{ tabs.map( ( tab ) => (
|
72 |
+
<TabButton className={ classnames( tab.className, { [ activeClass ]: tab.name === selectedTab.name } ) }
|
73 |
+
tabId={ instanceId + '-' + tab.name }
|
74 |
+
aria-controls={ instanceId + '-' + tab.name + '-view' }
|
75 |
+
selected={ tab.name === selectedTab.name }
|
76 |
+
key={ tab.name }
|
77 |
+
onClick={ partial( this.handleClick, tab.name ) }
|
78 |
+
>
|
79 |
+
{ tab.title }
|
80 |
+
</TabButton>
|
81 |
+
) ) }
|
82 |
+
</NavigableMenu>
|
83 |
+
{ selectedTab && (
|
84 |
+
<div aria-labelledby={ selectedId }
|
85 |
+
role="tabpanel"
|
86 |
+
id={ selectedId + '-view' }
|
87 |
+
className="components-tab-panel__tab-content"
|
88 |
+
tabIndex="0"
|
89 |
+
>
|
90 |
+
{ this.props.children( selectedTab ) }
|
91 |
+
</div>
|
92 |
+
) }
|
93 |
+
</div>
|
94 |
+
);
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
export default withInstanceId( ControlledTabPanel );
|
core/packages/components/src/tab-panel/index.js
ADDED
@@ -0,0 +1,30 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { Component } from '@wordpress/element';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import ControlledTabPanel from './controlled';
|
10 |
+
import ControlledMultiTabPanel from './multi';
|
11 |
+
|
12 |
+
export { ControlledTabPanel, ControlledMultiTabPanel };
|
13 |
+
|
14 |
+
export default class UncontrolledTabPanel extends Component {
|
15 |
+
constructor() {
|
16 |
+
super( ...arguments );
|
17 |
+
|
18 |
+
this.state = {
|
19 |
+
selected: this.props.initialTab || '',
|
20 |
+
};
|
21 |
+
}
|
22 |
+
|
23 |
+
onSelect = ( selected ) => {
|
24 |
+
this.setState( { selected } );
|
25 |
+
};
|
26 |
+
|
27 |
+
render() {
|
28 |
+
return ( <ControlledTabPanel { ...this.props } selected={ this.state.selected } onSelect={ this.onSelect } /> );
|
29 |
+
}
|
30 |
+
}
|
core/packages/components/src/tab-panel/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/tab-panel/multi.js
ADDED
@@ -0,0 +1,277 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import classnames from 'classnames';
|
5 |
+
import { partial, map, find, findIndex } from 'lodash';
|
6 |
+
|
7 |
+
/**
|
8 |
+
* WordPress dependencies
|
9 |
+
*/
|
10 |
+
import { Component } from '@wordpress/element';
|
11 |
+
import { NavigableMenu } from '@wordpress/components';
|
12 |
+
import { withInstanceId, compose } from '@wordpress/compose';
|
13 |
+
import isShallowEqual from '@wordpress/is-shallow-equal';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Internal dependencies
|
17 |
+
*/
|
18 |
+
import { withPressedModifierKeys } from '@ithemes/security-hocs';
|
19 |
+
import TabButton from './tab-button';
|
20 |
+
|
21 |
+
class ControlledMultiTabPanel extends Component {
|
22 |
+
constructor() {
|
23 |
+
super( ...arguments );
|
24 |
+
|
25 |
+
this.handleClick = this.handleClick.bind( this );
|
26 |
+
this.onNavigate = this.onNavigate.bind( this );
|
27 |
+
this.onKeyDown = this.onKeyDown.bind( this );
|
28 |
+
this.toggleTab = this.toggleTab.bind( this );
|
29 |
+
this.getSelectedTabs = this.getSelectedTabs.bind( this );
|
30 |
+
this.isSelected = this.isSelected.bind( this );
|
31 |
+
this.getSelectedId = this.getSelectedId.bind( this );
|
32 |
+
this.getLabelledBy = this.getLabelledBy.bind( this );
|
33 |
+
this.getTabId = this.getTabId.bind( this );
|
34 |
+
this.getTabPanelId = this.getTabPanelId.bind( this );
|
35 |
+
this.isTabDisabled = this.isTabDisabled.bind( this );
|
36 |
+
this.isNonMultiSelectableTabSelected = this.isNonMultiSelectableTabSelected.bind( this );
|
37 |
+
}
|
38 |
+
|
39 |
+
handleClick( tabKey, event ) {
|
40 |
+
if ( event.metaKey || event.ctrlKey ) {
|
41 |
+
this.toggleTab( tabKey );
|
42 |
+
} else {
|
43 |
+
this.props.onSelect( [ tabKey ] );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
onNavigate( childIndex, child ) {
|
48 |
+
const event = this.event;
|
49 |
+
|
50 |
+
if ( event ) {
|
51 |
+
if ( event.target.getAttribute( 'role' ) === 'tab' ) {
|
52 |
+
event.preventDefault();
|
53 |
+
}
|
54 |
+
|
55 |
+
if ( event.ctrlKey ) {
|
56 |
+
return;
|
57 |
+
}
|
58 |
+
|
59 |
+
if ( event.shiftKey ) {
|
60 |
+
if ( this.isTabDisabled( this.props.tabs[ childIndex ] ) ) {
|
61 |
+
return;
|
62 |
+
}
|
63 |
+
|
64 |
+
const name = this.props.tabs[ childIndex ].name;
|
65 |
+
this.toggleTab( name );
|
66 |
+
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
child.click();
|
72 |
+
}
|
73 |
+
|
74 |
+
onKeyDown( event ) {
|
75 |
+
// onKeyDown is not omitted from the NavigableContainer GB-19694
|
76 |
+
if ( event.nativeEvent ) {
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
|
80 |
+
// Stores the event for use in onNavigate. We don't need to persist the event
|
81 |
+
// since onNavigate is called during the original onKeyDown event handler.
|
82 |
+
this.event = event;
|
83 |
+
|
84 |
+
if ( event.ctrlKey && ( event.code === 'Space' || event.keyCode === 32 ) ) {
|
85 |
+
event.preventDefault();
|
86 |
+
const tabName = event.target.dataset.tabname;
|
87 |
+
|
88 |
+
if ( tabName ) {
|
89 |
+
this.toggleTab( tabName );
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
toggleTab( name ) {
|
95 |
+
const tab = find( this.props.tabs, { name } );
|
96 |
+
|
97 |
+
if ( tab && tab.allowMultiple === false ) {
|
98 |
+
return;
|
99 |
+
}
|
100 |
+
|
101 |
+
if ( this.props.selected.includes( name ) ) {
|
102 |
+
this.props.onSelect( this.props.selected.filter( ( maybeName ) => maybeName !== name ) );
|
103 |
+
} else {
|
104 |
+
this.props.onSelect( [
|
105 |
+
...this.props.selected,
|
106 |
+
name,
|
107 |
+
] );
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
getSelectedTabs() {
|
112 |
+
const selectedNames = this.props.selected;
|
113 |
+
|
114 |
+
if ( ! selectedNames.length && this.props.initialTab ) {
|
115 |
+
selectedNames.push( this.props.initialTab );
|
116 |
+
}
|
117 |
+
|
118 |
+
const tabs = [];
|
119 |
+
|
120 |
+
this.props.tabs.forEach( ( tab ) => {
|
121 |
+
if ( this.props.selected.includes( tab.name ) ) {
|
122 |
+
tabs.push( tab );
|
123 |
+
}
|
124 |
+
} );
|
125 |
+
|
126 |
+
return tabs;
|
127 |
+
}
|
128 |
+
|
129 |
+
isSelected( selectedTabs, maybeTab ) {
|
130 |
+
return selectedTabs.some( ( tab ) => tab.name === maybeTab.name );
|
131 |
+
}
|
132 |
+
|
133 |
+
isTabDisabled( tab ) {
|
134 |
+
const { pressedModifierKeys } = this.props;
|
135 |
+
|
136 |
+
if ( this.props.selected.includes( tab.name ) ) {
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
|
140 |
+
if ( tab.allowMultiple !== false && ! this.isNonMultiSelectableTabSelected() ) {
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
|
144 |
+
if ( pressedModifierKeys.meta || pressedModifierKeys.ctrl ) {
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
|
148 |
+
if ( pressedModifierKeys.shift ) {
|
149 |
+
const { activeElement } = document;
|
150 |
+
|
151 |
+
if ( activeElement.parentElement && activeElement.parentElement.id === `components-tab-panel__tabs-${ this.props.instanceId }` ) {
|
152 |
+
return true;
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
return false;
|
157 |
+
}
|
158 |
+
|
159 |
+
isNonMultiSelectableTabSelected() {
|
160 |
+
if ( this.props.selected.length !== 1 ) {
|
161 |
+
return false;
|
162 |
+
}
|
163 |
+
|
164 |
+
const selectedTab = find( this.props.tabs, { name: this.props.selected[ 0 ] } );
|
165 |
+
|
166 |
+
return selectedTab && selectedTab.allowMultiple === false;
|
167 |
+
}
|
168 |
+
|
169 |
+
getSelectedId( selectedTabs ) {
|
170 |
+
if ( selectedTabs.length === 1 ) {
|
171 |
+
return this.getTabPanelId( selectedTabs[ 0 ].name );
|
172 |
+
}
|
173 |
+
|
174 |
+
return `components-tab-panel__panel-${ this.props.instanceId }-${ map( selectedTabs, 'name' ).join( '-' ) }`;
|
175 |
+
}
|
176 |
+
|
177 |
+
getLabelledBy( selectedTabs ) {
|
178 |
+
return selectedTabs.map( ( tab ) => this.getTabId( tab.name ) ).join( ',' );
|
179 |
+
}
|
180 |
+
|
181 |
+
getTabId( tabName ) {
|
182 |
+
return `components-tab-panel__tab-${ this.props.instanceId }-${ tabName }`;
|
183 |
+
}
|
184 |
+
|
185 |
+
getTabPanelId( tabName ) {
|
186 |
+
return `components-tab-panel__panel-${ this.props.instanceId }-${ tabName }`;
|
187 |
+
}
|
188 |
+
|
189 |
+
componentDidUpdate( prevProps ) {
|
190 |
+
if ( this.props.selected.length !== 1 ) {
|
191 |
+
return;
|
192 |
+
}
|
193 |
+
|
194 |
+
if ( ! isShallowEqual( this.props.selected, prevProps.selected ) ) {
|
195 |
+
return;
|
196 |
+
}
|
197 |
+
|
198 |
+
const selected = this.props.selected[ 0 ];
|
199 |
+
|
200 |
+
if ( find( this.props.tabs, { name: selected } ) ) {
|
201 |
+
return;
|
202 |
+
}
|
203 |
+
|
204 |
+
const removedIndex = findIndex( prevProps.tabs, { name: selected } );
|
205 |
+
|
206 |
+
if ( removedIndex === -1 ) {
|
207 |
+
return;
|
208 |
+
}
|
209 |
+
|
210 |
+
const prevIndex = Math.max( removedIndex - 1, 0 );
|
211 |
+
const tab = this.props.tabs[ prevIndex ];
|
212 |
+
|
213 |
+
if ( tab ) {
|
214 |
+
this.props.onSelect( [ tab.name ] );
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
render() {
|
219 |
+
const {
|
220 |
+
tabs,
|
221 |
+
className,
|
222 |
+
activeClass = 'is-active',
|
223 |
+
orientation = 'horizontal',
|
224 |
+
} = this.props;
|
225 |
+
|
226 |
+
const selectedTabs = this.getSelectedTabs();
|
227 |
+
const selectedId = this.getSelectedId( selectedTabs );
|
228 |
+
|
229 |
+
return (
|
230 |
+
<div className={ className }>
|
231 |
+
<NavigableMenu
|
232 |
+
role="tablist"
|
233 |
+
aria-multiselectable
|
234 |
+
orientation={ orientation }
|
235 |
+
onNavigate={ this.onNavigate }
|
236 |
+
onKeyDown={ this.onKeyDown }
|
237 |
+
className="components-tab-panel__tabs"
|
238 |
+
id={ `components-tab-panel__tabs-${ this.props.instanceId }` }
|
239 |
+
>
|
240 |
+
{ tabs.map( ( tab ) => {
|
241 |
+
const isSelected = this.isSelected( selectedTabs, tab );
|
242 |
+
const controls = isSelected && selectedTabs.length > 1 ? selectedId : this.getTabPanelId( tab.name );
|
243 |
+
|
244 |
+
return (
|
245 |
+
<TabButton className={ classnames( tab.className, { [ activeClass ]: isSelected } ) }
|
246 |
+
tabId={ this.getTabId( tab.name ) }
|
247 |
+
aria-controls={ controls }
|
248 |
+
selected={ isSelected }
|
249 |
+
disabled={ this.isTabDisabled( tab ) }
|
250 |
+
key={ tab.name }
|
251 |
+
onClick={ partial( this.handleClick, tab.name ) }
|
252 |
+
data-tabname={ tab.name }
|
253 |
+
>
|
254 |
+
{ tab.title }
|
255 |
+
</TabButton>
|
256 |
+
);
|
257 |
+
} ) }
|
258 |
+
</NavigableMenu>
|
259 |
+
{ selectedTabs.length > 0 && (
|
260 |
+
<div aria-labelledby={ this.getLabelledBy( selectedTabs ) }
|
261 |
+
role="tabpanel"
|
262 |
+
id={ selectedId }
|
263 |
+
className="components-tab-panel__tab-content"
|
264 |
+
tabIndex="0"
|
265 |
+
>
|
266 |
+
{ this.props.children( selectedTabs ) }
|
267 |
+
</div>
|
268 |
+
) }
|
269 |
+
</div>
|
270 |
+
);
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
export default compose( [
|
275 |
+
withInstanceId,
|
276 |
+
withPressedModifierKeys,
|
277 |
+
] )( ControlledMultiTabPanel );
|
core/packages/components/src/tab-panel/tab-button.js
ADDED
@@ -0,0 +1,16 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { Button } from '@wordpress/components';
|
5 |
+
|
6 |
+
export default function TabButton( { tabId, onClick, children, selected, ...rest } ) {
|
7 |
+
return <Button role="tab"
|
8 |
+
tabIndex={ selected ? null : -1 }
|
9 |
+
aria-selected={ selected }
|
10 |
+
id={ tabId }
|
11 |
+
onClick={ onClick }
|
12 |
+
{ ...rest }
|
13 |
+
>
|
14 |
+
{ children }
|
15 |
+
</Button>;
|
16 |
+
}
|
core/packages/components/src/toggle-control/index.js
ADDED
@@ -0,0 +1,68 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { isFunction } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { Component } from '@wordpress/element';
|
10 |
+
import { withInstanceId } from '@wordpress/compose';
|
11 |
+
import { FormToggle, BaseControl } from '@wordpress/components';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Internal dependencies
|
15 |
+
*/
|
16 |
+
import './style.scss';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* This is a copy of core's toggle control but passes thru additional props to the FormToggle.
|
20 |
+
*/
|
21 |
+
class ToggleControl extends Component {
|
22 |
+
constructor() {
|
23 |
+
super( ...arguments );
|
24 |
+
|
25 |
+
this.onChange = this.onChange.bind( this );
|
26 |
+
}
|
27 |
+
|
28 |
+
onChange( event ) {
|
29 |
+
if ( this.props.onChange ) {
|
30 |
+
this.props.onChange( event.target.checked );
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
render() {
|
35 |
+
const { label, checked, help, instanceId, ...props } = this.props;
|
36 |
+
const id = `inspector-toggle-control-${ instanceId }`;
|
37 |
+
|
38 |
+
let describedBy, helpLabel;
|
39 |
+
if ( help ) {
|
40 |
+
describedBy = id + '__help';
|
41 |
+
helpLabel = isFunction( help ) ? help( checked ) : help;
|
42 |
+
}
|
43 |
+
|
44 |
+
return (
|
45 |
+
<BaseControl
|
46 |
+
id={ id }
|
47 |
+
help={ helpLabel }
|
48 |
+
className="components-toggle-control"
|
49 |
+
>
|
50 |
+
<FormToggle
|
51 |
+
{ ...props }
|
52 |
+
id={ id }
|
53 |
+
checked={ checked }
|
54 |
+
onChange={ this.onChange }
|
55 |
+
aria-describedby={ describedBy }
|
56 |
+
/>
|
57 |
+
<label
|
58 |
+
htmlFor={ id }
|
59 |
+
className="components-toggle-control__label"
|
60 |
+
>
|
61 |
+
{ label }
|
62 |
+
</label>
|
63 |
+
</BaseControl>
|
64 |
+
);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
export default withInstanceId( ToggleControl );
|
core/packages/components/src/toggle-control/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/components/src/toggle-control/style.scss
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.components-form-toggle__input:disabled + .components-form-toggle__track {
|
2 |
+
opacity: .5;
|
3 |
+
}
|
core/packages/data/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/data/src/actions.js
ADDED
@@ -0,0 +1,40 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import { apiFetch } from './controls';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Fetch the index.
|
8 |
+
*
|
9 |
+
* @param {boolean} breakCache Whether to break the cache or not.
|
10 |
+
* @return {Object} The index.
|
11 |
+
*/
|
12 |
+
export function* fetchIndex( breakCache = false ) {
|
13 |
+
let path = '/ithemes-security/v1?context=help';
|
14 |
+
|
15 |
+
if ( breakCache ) {
|
16 |
+
path += '&_=' + Date.now();
|
17 |
+
}
|
18 |
+
|
19 |
+
const index = yield apiFetch( { path } );
|
20 |
+
yield receiveIndex( index );
|
21 |
+
|
22 |
+
return index;
|
23 |
+
}
|
24 |
+
|
25 |
+
export function receiveIndex( index ) {
|
26 |
+
return {
|
27 |
+
type: RECEIVE_INDEX,
|
28 |
+
index,
|
29 |
+
};
|
30 |
+
}
|
31 |
+
|
32 |
+
export function receiveUser( user ) {
|
33 |
+
return {
|
34 |
+
type: RECEIVE_USER,
|
35 |
+
user,
|
36 |
+
};
|
37 |
+
}
|
38 |
+
|
39 |
+
export const RECEIVE_INDEX = 'RECEIVE_INDEX';
|
40 |
+
export const RECEIVE_USER = 'RECEIVE_USER';
|
core/packages/data/src/controls.js
ADDED
@@ -0,0 +1,172 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* External dependencies
|
3 |
+
*/
|
4 |
+
import { uniqueId } from 'lodash';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WordPress dependencies
|
8 |
+
*/
|
9 |
+
import { select as selectData, dispatch as dispatchData, subscribe } from '@wordpress/data';
|
10 |
+
import { default as triggerApiFetch } from '@wordpress/api-fetch';
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Internal dependencies
|
14 |
+
*/
|
15 |
+
import { responseToError } from '@ithemes/security-utils';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Utility for returning a promise that handles a selector with a resolver.
|
19 |
+
*
|
20 |
+
* @param {Object} options
|
21 |
+
* @param {string} options.storeKey The store the selector belongs to
|
22 |
+
* @param {string} options.selectorName The selector name
|
23 |
+
* @param {Array} options.args The arguments fed to the selector
|
24 |
+
*
|
25 |
+
* @return {Promise} A promise for resolving the given selector.
|
26 |
+
*/
|
27 |
+
const resolveSelect = ( { storeKey, selectorName, args } ) => {
|
28 |
+
return new Promise( ( resolve ) => {
|
29 |
+
const hasFinished = () => selectData( 'core/data' ).hasFinishedResolution( storeKey, selectorName, args );
|
30 |
+
const getResult = () => selectData( storeKey )[ selectorName ].apply( null, args );
|
31 |
+
|
32 |
+
// trigger the selector (to trigger the resolver)
|
33 |
+
const result = getResult();
|
34 |
+
|
35 |
+
if ( hasFinished() ) {
|
36 |
+
return resolve( result );
|
37 |
+
}
|
38 |
+
|
39 |
+
const unsubscribe = subscribe( () => {
|
40 |
+
if ( hasFinished() ) {
|
41 |
+
unsubscribe();
|
42 |
+
resolve( getResult() );
|
43 |
+
}
|
44 |
+
} );
|
45 |
+
} );
|
46 |
+
};
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Trigger an API Fetch request.
|
50 |
+
*
|
51 |
+
* @param {Object} request API Fetch Request Object.
|
52 |
+
* @return {Object} control descriptor.
|
53 |
+
*/
|
54 |
+
export function apiFetch( request ) {
|
55 |
+
return {
|
56 |
+
type: 'API_FETCH',
|
57 |
+
request,
|
58 |
+
};
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Calls a selector using the current state.
|
63 |
+
* @param {string} storeKey Store key.
|
64 |
+
* @param {string} selectorName Selector name.
|
65 |
+
* @param {Array} args Selector arguments.
|
66 |
+
*
|
67 |
+
* @return {Object} control descriptor.
|
68 |
+
*/
|
69 |
+
export function select( storeKey, selectorName, ...args ) {
|
70 |
+
return {
|
71 |
+
type: 'SELECT',
|
72 |
+
storeKey,
|
73 |
+
selectorName,
|
74 |
+
args,
|
75 |
+
};
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Dispatches a control action for triggering a registry dispatch.
|
80 |
+
*
|
81 |
+
* @param {string} storeKey The key for the store the action belongs to
|
82 |
+
* @param {string} actionName The name of the action to dispatch
|
83 |
+
* @param {Array} args Arguments for the dispatch action.
|
84 |
+
*
|
85 |
+
* @example
|
86 |
+
* ```js
|
87 |
+
* import { dispatch } from '@wordpress/data-controls';
|
88 |
+
*
|
89 |
+
* // Action generator using dispatch
|
90 |
+
* export function* myAction() {
|
91 |
+
* yield dispatch( 'core/edit-post', 'togglePublishSidebar' );
|
92 |
+
* // do some other things.
|
93 |
+
* }
|
94 |
+
* ```
|
95 |
+
*
|
96 |
+
* @return {Object} The control descriptor.
|
97 |
+
*/
|
98 |
+
export function dispatch( storeKey, actionName, ...args ) {
|
99 |
+
return {
|
100 |
+
type: 'DISPATCH',
|
101 |
+
storeKey,
|
102 |
+
actionName,
|
103 |
+
args,
|
104 |
+
};
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Yields action objects used in signalling that a notice is to be created.
|
109 |
+
*
|
110 |
+
* @see @wordpress/notices#createNotice()
|
111 |
+
*
|
112 |
+
* @param {?string} status Notice status.
|
113 |
+
* Defaults to `info`.
|
114 |
+
* @param {string} content Notice message.
|
115 |
+
* @param {?Object} options Notice options.
|
116 |
+
* @param {?string} options.context Context under which to
|
117 |
+
* group notice.
|
118 |
+
* @param {?string} options.id Identifier for notice.
|
119 |
+
* Automatically assigned
|
120 |
+
* if not specified.
|
121 |
+
* @param {?boolean} options.isDismissible Whether the notice can
|
122 |
+
* be dismissed by user.
|
123 |
+
* Defaults to `true`.
|
124 |
+
* @param {?number} options.autoDismiss Whether the notice should
|
125 |
+
* by automatically dismissed
|
126 |
+
* after x milliseconds.
|
127 |
+
* Defaults to `false`.
|
128 |
+
* @param {?string} options.type Notice type. Either 'default' or 'snackbar'.
|
129 |
+
* @param {?Array<WPNoticeAction>} options.actions User actions to be
|
130 |
+
* presented with notice.
|
131 |
+
*
|
132 |
+
* @return {Object} control descriptor.
|
133 |
+
*/
|
134 |
+
export function createNotice( status = 'info', content, options = {} ) {
|
135 |
+
return {
|
136 |
+
type: 'CREATE_NOTICE',
|
137 |
+
status,
|
138 |
+
content,
|
139 |
+
options: {
|
140 |
+
context: 'ithemes-security',
|
141 |
+
...options,
|
142 |
+
},
|
143 |
+
};
|
144 |
+
}
|
145 |
+
|
146 |
+
const controls = {
|
147 |
+
API_FETCH( { request } ) {
|
148 |
+
return triggerApiFetch( request ).catch( responseToError );
|
149 |
+
},
|
150 |
+
SELECT( { storeKey, selectorName, args } ) {
|
151 |
+
const selector = selectData( storeKey )[ selectorName ];
|
152 |
+
|
153 |
+
if ( selector.hasResolver ) {
|
154 |
+
return resolveSelect( { storeKey, selectorName, args } );
|
155 |
+
}
|
156 |
+
|
157 |
+
return selector( ...args );
|
158 |
+
},
|
159 |
+
DISPATCH( { storeKey, actionName, args } ) {
|
160 |
+
return dispatchData( storeKey )[ actionName ]( ...args );
|
161 |
+
},
|
162 |
+
CREATE_NOTICE( { status, content, options } ) {
|
163 |
+
if ( options.autoDismiss ) {
|
164 |
+
options.id = options.id || uniqueId( 'itsec-auto-dismiss-' );
|
165 |
+
setTimeout( () => dispatchData( 'core/notices' ).removeNotice( options.id, options.context ), options.autoDismiss );
|
166 |
+
}
|
167 |
+
|
168 |
+
dispatchData( 'core/notices' ).createNotice( status, content, options );
|
169 |
+
},
|
170 |
+
};
|
171 |
+
|
172 |
+
export default controls;
|
core/packages/data/src/index.js
ADDED
@@ -0,0 +1,21 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { registerStore } from '@wordpress/data';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Internal dependencies
|
8 |
+
*/
|
9 |
+
import controls from './controls';
|
10 |
+
import * as selectors from './selectors';
|
11 |
+
import * as resolvers from './resolvers';
|
12 |
+
import * as actions from './actions';
|
13 |
+
import reducer from './reducers';
|
14 |
+
|
15 |
+
registerStore( 'ithemes-security/core', {
|
16 |
+
controls,
|
17 |
+
selectors,
|
18 |
+
resolvers,
|
19 |
+
actions,
|
20 |
+
reducer,
|
21 |
+
} );
|
core/packages/data/src/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/data/src/reducers.js
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import { RECEIVE_INDEX, RECEIVE_USER } from './actions';
|
5 |
+
|
6 |
+
const DEFAULT_STATE = {
|
7 |
+
users: {
|
8 |
+
byId: {},
|
9 |
+
},
|
10 |
+
index: null,
|
11 |
+
};
|
12 |
+
|
13 |
+
export default function reducer( state = DEFAULT_STATE, action ) {
|
14 |
+
switch ( action.type ) {
|
15 |
+
case RECEIVE_INDEX:
|
16 |
+
return {
|
17 |
+
...state,
|
18 |
+
index: action.index,
|
19 |
+
};
|
20 |
+
case RECEIVE_USER:
|
21 |
+
return {
|
22 |
+
...state,
|
23 |
+
users: {
|
24 |
+
...state.users,
|
25 |
+
byId: {
|
26 |
+
...state.users.byId,
|
27 |
+
[ action.user.id ]: action.user,
|
28 |
+
},
|
29 |
+
},
|
30 |
+
};
|
31 |
+
default:
|
32 |
+
return state;
|
33 |
+
}
|
34 |
+
}
|
core/packages/data/src/resolvers.js
ADDED
@@ -0,0 +1,24 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Internal dependencies
|
3 |
+
*/
|
4 |
+
import { apiFetch } from './controls';
|
5 |
+
import { receiveIndex, receiveUser } from './actions';
|
6 |
+
|
7 |
+
export function* getIndex() {
|
8 |
+
const index = yield apiFetch( { path: '/ithemes-security/v1?context=help' } );
|
9 |
+
yield receiveIndex( index );
|
10 |
+
}
|
11 |
+
|
12 |
+
export const getUser = {
|
13 |
+
*fulfill( userId ) {
|
14 |
+
const user = yield apiFetch( {
|
15 |
+
path: `/wp/v2/users/${ userId }`,
|
16 |
+
} );
|
17 |
+
|
18 |
+
yield receiveUser( user );
|
19 |
+
},
|
20 |
+
isFulfilled( state, userId ) {
|
21 |
+
return !! state.users.byId[ userId ];
|
22 |
+
},
|
23 |
+
};
|
24 |
+
|
core/packages/data/src/selectors.js
ADDED
@@ -0,0 +1,56 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { select } from '@wordpress/data';
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Get a WP User by its ID.
|
8 |
+
* @param {Object} state
|
9 |
+
* @param {number} userId
|
10 |
+
* @return {Object}
|
11 |
+
*/
|
12 |
+
export function getUser( state, userId ) {
|
13 |
+
return state.users.byId[ userId ];
|
14 |
+
}
|
15 |
+
|
16 |
+
export function getIndex( state ) {
|
17 |
+
return state.index;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Get a schema from the root index.
|
22 |
+
* @param {Object} state
|
23 |
+
* @param {string} schemaId The full schema ID like ithemes-security-user-group
|
24 |
+
* @return {Object|null}
|
25 |
+
*/
|
26 |
+
export function getSchema( state, schemaId ) {
|
27 |
+
const index = select( 'ithemes-security/core' ).getIndex();
|
28 |
+
|
29 |
+
if ( ! index ) {
|
30 |
+
return null;
|
31 |
+
}
|
32 |
+
|
33 |
+
for ( const route in index.routes ) {
|
34 |
+
if ( ! index.routes.hasOwnProperty( route ) ) {
|
35 |
+
continue;
|
36 |
+
}
|
37 |
+
|
38 |
+
const schema = index.routes[ route ].schema;
|
39 |
+
|
40 |
+
if ( schema && schema.title === schemaId ) {
|
41 |
+
return schema;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
return null;
|
46 |
+
}
|
47 |
+
|
48 |
+
export function getRoles() {
|
49 |
+
const index = select( 'ithemes-security/core' ).getIndex();
|
50 |
+
|
51 |
+
if ( ! index ) {
|
52 |
+
return null;
|
53 |
+
}
|
54 |
+
|
55 |
+
return index.roles;
|
56 |
+
}
|
core/packages/hocs/src/index.js
CHANGED
@@ -3,3 +3,4 @@ export { default as withDebounceHandler } from './with-debounce-handler';
|
|
3 |
Â
export { default as withPropChangeCallback } from './with-prop-change-callback';
|
4 |
Â
export { default as withInterval } from './with-interval';
|
5 |
Â
export { default as withWidth } from './with-width';
|
Â
|
3 |
Â
export { default as withPropChangeCallback } from './with-prop-change-callback';
|
4 |
Â
export { default as withInterval } from './with-interval';
|
5 |
Â
export { default as withWidth } from './with-width';
|
6 |
+
export { default as withPressedModifierKeys } from './with-pressed-modifier-keys';
|
core/packages/hocs/src/with-pressed-modifier-keys.js
ADDED
@@ -0,0 +1,78 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* WordPress dependencies
|
3 |
+
*/
|
4 |
+
import { createHigherOrderComponent } from '@wordpress/compose';
|
5 |
+
import { Component } from '@wordpress/element';
|
6 |
+
|
7 |
+
export default createHigherOrderComponent( ( WrappedComponent ) => {
|
8 |
+
return class WithPressedModifierKeys extends Component {
|
9 |
+
state = {
|
10 |
+
pressed: {
|
11 |
+
shift: false,
|
12 |
+
ctrl: false,
|
13 |
+
meta: false,
|
14 |
+
alt: false,
|
15 |
+
},
|
16 |
+
};
|
17 |
+
|
18 |
+
mounted = false;
|
19 |
+
|
20 |
+
constructor() {
|
21 |
+
super( ...arguments );
|
22 |
+
|
23 |
+
this.listener = this.listener.bind( this );
|
24 |
+
this.onBlur = this.onBlur.bind( this );
|
25 |
+
}
|
26 |
+
|
27 |
+
componentDidMount() {
|
28 |
+
this.mounted = true;
|
29 |
+
window.addEventListener( 'keydown', this.listener );
|
30 |
+
window.addEventListener( 'keyup', this.listener );
|
31 |
+
window.addEventListener( 'click', this.listener );
|
32 |
+
window.addEventListener( 'blur', this.onBlur );
|
33 |
+
}
|
34 |
+
|
35 |
+
componentWillUnmount() {
|
36 |
+
this.mounted = false;
|
37 |
+
window.removeEventListener( 'keydown', this.listener );
|
38 |
+
window.removeEventListener( 'keyup', this.listener );
|
39 |
+
window.removeEventListener( 'click', this.listener );
|
40 |
+
window.removeEventListener( 'blur', this.onBlur );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Fires whenever a key is pressed down.
|
45 |
+
* @param {KeyboardEvent} e
|
46 |
+
*/
|
47 |
+
listener( e ) {
|
48 |
+
if ( this.mounted ) {
|
49 |
+
this.setState( {
|
50 |
+
pressed: {
|
51 |
+
shift: e.shiftKey,
|
52 |
+
ctrl: e.ctrlKey,
|
53 |
+
meta: e.metaKey,
|
54 |
+
alt: e.altKey,
|
55 |
+
},
|
56 |
+
} );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* When the window blurs, remove all pressed modifier keys.
|
62 |
+
*/
|
63 |
+
onBlur() {
|
64 |
+
this.setState( {
|
65 |
+
pressed: {
|
66 |
+
shift: false,
|
67 |
+
ctrl: false,
|
68 |
+
meta: false,
|
69 |
+
alt: false,
|
70 |
+
},
|
71 |
+
} );
|
72 |
+
}
|
73 |
+
|
74 |
+
render() {
|
75 |
+
return <WrappedComponent pressedModifierKeys={ this.state.pressed } { ...this.props } />;
|
76 |
+
}
|
77 |
+
};
|
78 |
+
}, 'withPressedModifierKeys' );
|
core/packages/i18n/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/i18n/src/index.js
ADDED
@@ -0,0 +1,26 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
import { _x } from '@wordpress/i18n';
|
2 |
+
|
3 |
+
export function getCanonicalRoles() {
|
4 |
+
return [
|
5 |
+
{
|
6 |
+
value: 'administrator',
|
7 |
+
label: _x( 'Administrator', 'User role', 'default' ),
|
8 |
+
},
|
9 |
+
{
|
10 |
+
value: 'editor',
|
11 |
+
label: _x( 'Editor', 'User role', 'default' ),
|
12 |
+
},
|
13 |
+
{
|
14 |
+
value: 'author',
|
15 |
+
label: _x( 'Author', 'User role', 'default' ),
|
16 |
+
},
|
17 |
+
{
|
18 |
+
value: 'contributor',
|
19 |
+
label: _x( 'Contributor', 'User role', 'default' ),
|
20 |
+
},
|
21 |
+
{
|
22 |
+
value: 'subscriber',
|
23 |
+
label: _x( 'Subscriber', 'User role', 'default' ),
|
24 |
+
},
|
25 |
+
];
|
26 |
+
}
|
core/packages/i18n/src/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/preload/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/preload/src/index.js
ADDED
@@ -0,0 +1,78 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
const cache = {};
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Given a path, returns a normalized path where equal query parameter values
|
5 |
+
* will be treated as identical, regardless of order they appear in the original
|
6 |
+
* text.
|
7 |
+
*
|
8 |
+
* @param {string} path Original path.
|
9 |
+
*
|
10 |
+
* @return {string} Normalized path.
|
11 |
+
*/
|
12 |
+
export function getStablePath( path ) {
|
13 |
+
const splitted = path.split( '?' );
|
14 |
+
const query = splitted[ 1 ];
|
15 |
+
const base = splitted[ 0 ];
|
16 |
+
if ( ! query ) {
|
17 |
+
return base;
|
18 |
+
}
|
19 |
+
|
20 |
+
// 'b=1&c=2&a=5'
|
21 |
+
return base + '?' + query
|
22 |
+
// [ 'b=1', 'c=2', 'a=5' ]
|
23 |
+
.split( '&' )
|
24 |
+
// [ [ 'b, '1' ], [ 'c', '2' ], [ 'a', '5' ] ]
|
25 |
+
.map( function( entry ) {
|
26 |
+
return entry.split( '=' );
|
27 |
+
} )
|
28 |
+
// [ [ 'a', '5' ], [ 'b, '1' ], [ 'c', '2' ] ]
|
29 |
+
.sort( function( a, b ) {
|
30 |
+
return a[ 0 ].localeCompare( b[ 0 ] );
|
31 |
+
} )
|
32 |
+
// [ 'a=5', 'b=1', 'c=2' ]
|
33 |
+
.map( function( pair ) {
|
34 |
+
return pair.join( '=' );
|
35 |
+
} )
|
36 |
+
// 'a=5&b=1&c=2'
|
37 |
+
.join( '&' );
|
38 |
+
}
|
39 |
+
|
40 |
+
export function createMiddleware( preloadedData ) {
|
41 |
+
Object.keys( preloadedData ).reduce( ( result, path ) => {
|
42 |
+
result[ getStablePath( path ) ] = preloadedData[ path ];
|
43 |
+
return result;
|
44 |
+
}, cache );
|
45 |
+
|
46 |
+
return ( options, next ) => {
|
47 |
+
const { parse = true } = options;
|
48 |
+
if ( typeof options.path === 'string' ) {
|
49 |
+
const method = options.method || 'GET';
|
50 |
+
const path = getStablePath( options.path );
|
51 |
+
|
52 |
+
if ( parse && 'GET' === method && cache[ path ] ) {
|
53 |
+
return Promise.resolve( cache[ path ].body );
|
54 |
+
} else if (
|
55 |
+
'OPTIONS' === method &&
|
56 |
+
cache[ method ] &&
|
57 |
+
cache[ method ][ path ]
|
58 |
+
) {
|
59 |
+
return Promise.resolve( cache[ method ][ path ] );
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
return next( options );
|
64 |
+
};
|
65 |
+
}
|
66 |
+
|
67 |
+
export function invalidatePreload( { path } ) {
|
68 |
+
delete cache[ getStablePath( path ) ];
|
69 |
+
}
|
70 |
+
|
71 |
+
export const CONTROL = 'INVALIDATE_API_FETCH_PRELOAD';
|
72 |
+
|
73 |
+
export function invalidatePreloadControl( path ) {
|
74 |
+
return {
|
75 |
+
type: CONTROL,
|
76 |
+
path,
|
77 |
+
};
|
78 |
+
}
|
core/packages/preload/src/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
core/packages/style-guide/src/breakpoints.scss
CHANGED
@@ -4,3 +4,45 @@ $large: 960px;
|
|
4 |
Â
$medium: 782px;
|
5 |
Â
$small: 600px;
|
6 |
Â
$mobile: 480px;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
4 |
Â
$medium: 782px;
|
5 |
Â
$small: 600px;
|
6 |
Â
$mobile: 480px;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Breakpoints & Media Queries
|
10 |
+
*/
|
11 |
+
|
12 |
+
// Most used breakpoints
|
13 |
+
$break-huge: 1440px;
|
14 |
+
$break-wide: 1280px;
|
15 |
+
$break-xlarge: 1080px;
|
16 |
+
$break-large: 960px; // admin sidebar auto folds
|
17 |
+
$break-medium: 782px; // adminbar goes big
|
18 |
+
$break-small: 600px;
|
19 |
+
$break-mobile: 480px;
|
20 |
+
$break-zoomed-in: 280px;
|
21 |
+
|
22 |
+
// All media queries currently in WordPress:
|
23 |
+
//
|
24 |
+
// min-width: 2000px
|
25 |
+
// min-width: 1680px
|
26 |
+
// min-width: 1250px
|
27 |
+
// max-width: 1120px *
|
28 |
+
// max-width: 1000px
|
29 |
+
// min-width: 769px and max-width: 1000px
|
30 |
+
// max-width: 960px *
|
31 |
+
// max-width: 900px
|
32 |
+
// max-width: 850px
|
33 |
+
// min-width: 800px and max-width: 1499px
|
34 |
+
// max-width: 800px
|
35 |
+
// max-width: 799px
|
36 |
+
// max-width: 782px *
|
37 |
+
// max-width: 768px
|
38 |
+
// max-width: 640px *
|
39 |
+
// max-width: 600px *
|
40 |
+
// max-width: 520px
|
41 |
+
// max-width: 500px
|
42 |
+
// max-width: 480px *
|
43 |
+
// max-width: 400px *
|
44 |
+
// max-width: 380px
|
45 |
+
// max-width: 320px *
|
46 |
+
//
|
47 |
+
// Those marked * seem to be more commonly used than the others.
|
48 |
+
// Let's try and use as few of these as possible, and be mindful about adding new ones, so we don't make the situation worse
|
core/packages/style-guide/src/mixins.scss
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
Â
@import "colors.scss";
|
Â
|
|
2 |
Â
|
3 |
Â
@mixin sticky-table($spacing: 1em) {
|
4 |
Â
& thead th {
|
@@ -74,3 +75,55 @@
|
|
74 |
Â
}
|
75 |
Â
}
|
76 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
Â
@import "colors.scss";
|
2 |
+
@import "breakpoints.scss";
|
3 |
Â
|
4 |
Â
@mixin sticky-table($spacing: 1em) {
|
5 |
Â
& thead th {
|
75 |
Â
}
|
76 |
Â
}
|
77 |
Â
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Breakpoint mixins
|
81 |
+
*/
|
82 |
+
|
83 |
+
@mixin break-huge() {
|
84 |
+
@media (min-width: #{ ($break-huge) }) {
|
85 |
+
@content;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
@mixin break-wide() {
|
90 |
+
@media (min-width: #{ ($break-wide) }) {
|
91 |
+
@content;
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
@mixin break-xlarge() {
|
96 |
+
@media (min-width: #{ ($break-xlarge) }) {
|
97 |
+
@content;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
@mixin break-large() {
|
102 |
+
@media (min-width: #{ ($break-large) }) {
|
103 |
+
@content;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
@mixin break-medium() {
|
108 |
+
@media (min-width: #{ ($break-medium) }) {
|
109 |
+
@content;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
@mixin break-small() {
|
114 |
+
@media (min-width: #{ ($break-small) }) {
|
115 |
+
@content;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
@mixin break-mobile() {
|
120 |
+
@media (min-width: #{ ($break-mobile) }) {
|
121 |
+
@content;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
@mixin break-zoomed-in() {
|
126 |
+
@media (min-width: #{ ($break-zoomed-in) }) {
|
127 |
+
@content;
|
128 |
+
}
|
129 |
+
}
|
core/packages/utils/src/index.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
Â
/**
|
2 |
Â
* External dependencies
|
3 |
Â
*/
|
4 |
-
import { isPlainObject } from 'lodash';
|
5 |
Â
|
6 |
Â
/**
|
7 |
Â
* Internal dependencies
|
@@ -149,12 +149,28 @@ export function entriesToObject( entries ) {
|
|
149 |
Â
return obj;
|
150 |
Â
}
|
151 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
152 |
Â
/**
|
153 |
Â
* Convert a response object from @wordpress/apiFetch to an Error object.
|
154 |
Â
*
|
155 |
Â
* @param {Object} response
|
156 |
Â
*/
|
157 |
-
export
|
158 |
Â
if ( response instanceof Error ) {
|
159 |
Â
throw response;
|
160 |
Â
}
|
@@ -163,3 +179,44 @@ export default function responseToError( response ) {
|
|
163 |
Â
}
|
164 |
Â
|
165 |
Â
export const MYSTERY_MAN_AVATAR = 'https://secure.gravatar.com/avatar/d7a973c7dab26985da5f961be7b74480?s=96&d=mm&f=y&r=g';
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
Â
/**
|
2 |
Â
* External dependencies
|
3 |
Â
*/
|
4 |
+
import { get, isPlainObject } from 'lodash';
|
5 |
Â
|
6 |
Â
/**
|
7 |
Â
* Internal dependencies
|
149 |
Â
return obj;
|
150 |
Â
}
|
151 |
Â
|
152 |
+
/**
|
153 |
+
* Splits a list into two arrays, with items that pass the filter in the first array, and ones that fail in the second.
|
154 |
+
* @param {Array} array
|
155 |
+
* @param {Function} filter
|
156 |
+
* @return {[][]}
|
157 |
+
*/
|
158 |
+
export function bifurcate( array, filter ) {
|
159 |
+
const bifurcated = [ [], [] ];
|
160 |
+
|
161 |
+
for ( const value of array ) {
|
162 |
+
bifurcated[ filter( value ) ? 0 : 1 ].push( value );
|
163 |
+
}
|
164 |
+
|
165 |
+
return bifurcated;
|
166 |
+
}
|
167 |
+
|
168 |
Â
/**
|
169 |
Â
* Convert a response object from @wordpress/apiFetch to an Error object.
|
170 |
Â
*
|
171 |
Â
* @param {Object} response
|
172 |
Â
*/
|
173 |
+
export function responseToError( response ) {
|
174 |
Â
if ( response instanceof Error ) {
|
175 |
Â
throw response;
|
176 |
Â
}
|
179 |
Â
}
|
180 |
Â
|
181 |
Â
export const MYSTERY_MAN_AVATAR = 'https://secure.gravatar.com/avatar/d7a973c7dab26985da5f961be7b74480?s=96&d=mm&f=y&r=g';
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Get the "self" link for a REST API object.
|
185 |
+
*
|
186 |
+
* @param {Object} object
|
187 |
+
* @return {string|undefined}
|
188 |
+
*/
|
189 |
+
export function getSelf( object ) {
|
190 |
+
return getLink( object, 'self' );
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Get the href for a link with the given relation.
|
195 |
+
*
|
196 |
+
* @param {Object} object
|
197 |
+
* @param {string} rel
|
198 |
+
* @return {string|undefined}
|
199 |
+
*/
|
200 |
+
export function getLink( object, rel ) {
|
201 |
+
return get( object, [ '_links', rel, 0, 'href' ] );
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Get a link from a schema document.
|
206 |
+
*
|
207 |
+
* @param {Object} schema
|
208 |
+
* @param {string} rel
|
209 |
+
*
|
210 |
+
* @return {Object|undefined}
|
211 |
+
*/
|
212 |
+
export function getSchemaLink( schema, rel ) {
|
213 |
+
if ( ! schema || ! schema.links ) {
|
214 |
+
return;
|
215 |
+
}
|
216 |
+
|
217 |
+
for ( const link of schema.links ) {
|
218 |
+
if ( link.rel === rel ) {
|
219 |
+
return link;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
core/packages/utils/src/wp-error.js
CHANGED
@@ -124,4 +124,20 @@ export default class WPError {
|
|
124 |
Â
|
125 |
Â
return this.#errorData[ code ];
|
126 |
Â
};
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
127 |
Â
}
|
124 |
Â
|
125 |
Â
return this.#errorData[ code ];
|
126 |
Â
};
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Get all error messages combined into one string.
|
130 |
+
* @return {Array<string>} All error messages combined into a single array ignoring code.
|
131 |
+
*/
|
132 |
+
getAllErrorMessages = () => {
|
133 |
+
const messages = [];
|
134 |
+
|
135 |
+
for ( const errorCode in this.#errors ) {
|
136 |
+
if ( this.#errors.hasOwnProperty( errorCode ) ) {
|
137 |
+
messages.push( ...this.#errors[ errorCode ] );
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
return messages
|
142 |
+
};
|
143 |
Â
}
|
core/packages/webpack/src/babel.js
CHANGED
@@ -11,5 +11,6 @@ module.exports = {
|
|
11 |
Â
} ],
|
12 |
Â
'@babel/plugin-proposal-class-properties',
|
13 |
Â
'@babel/plugin-syntax-dynamic-import',
|
Â
|
|
14 |
Â
],
|
15 |
Â
};
|
11 |
Â
} ],
|
12 |
Â
'@babel/plugin-proposal-class-properties',
|
13 |
Â
'@babel/plugin-syntax-dynamic-import',
|
14 |
+
'@babel/plugin-proposal-export-default-from',
|
15 |
Â
],
|
16 |
Â
};
|
core/packages/webpack/src/config/index.js
CHANGED
@@ -54,6 +54,7 @@ module.exports = function makeConfig( directory, pro ) {
|
|
54 |
Â
entry: {
|
55 |
Â
...entries,
|
56 |
Â
'core/packages/components/site-scan-results/style': './core/packages/components/src/site-scan-results/style.scss',
|
Â
|
|
57 |
Â
},
|
58 |
Â
output: {
|
59 |
Â
path: path.resolve( directory, 'dist' ),
|
@@ -174,6 +175,8 @@ module.exports = function makeConfig( directory, pro ) {
|
|
174 |
Â
'@ithemes/security-style-guide': path.resolve( directory, './core/packages/style-guide/src/index.js' ),
|
175 |
Â
'@ithemes/security-hocs': path.resolve( directory, './core/packages/hocs/src/index.js' ),
|
176 |
Â
'@ithemes/security-components': path.resolve( directory, './core/packages/components/src/index.js' ),
|
Â
|
|
Â
|
|
177 |
Â
...Object.keys( entries ).reduce( function( acc, entry ) {
|
178 |
Â
const parts = entry.split( '/' );
|
179 |
Â
const alias = `@ithemes/security.${ parts[ 0 ] }.${ parts[ 1 ] }`;
|
54 |
Â
entry: {
|
55 |
Â
...entries,
|
56 |
Â
'core/packages/components/site-scan-results/style': './core/packages/components/src/site-scan-results/style.scss',
|
57 |
+
'packages/preload': './core/packages/preload/src/index.js',
|
58 |
Â
},
|
59 |
Â
output: {
|
60 |
Â
path: path.resolve( directory, 'dist' ),
|
175 |
Â
'@ithemes/security-style-guide': path.resolve( directory, './core/packages/style-guide/src/index.js' ),
|
176 |
Â
'@ithemes/security-hocs': path.resolve( directory, './core/packages/hocs/src/index.js' ),
|
177 |
Â
'@ithemes/security-components': path.resolve( directory, './core/packages/components/src/index.js' ),
|
178 |
+
'@ithemes/security-i18n': path.resolve( directory, './core/packages/i18n/src/index.js' ),
|
179 |
+
'@ithemes/security-data': path.resolve( directory, './core/packages/data/src/index.js' ),
|
180 |
Â
...Object.keys( entries ).reduce( function( acc, entry ) {
|
181 |
Â
const parts = entry.split( '/' );
|
182 |
Â
const alias = `@ithemes/security.${ parts[ 0 ] }.${ parts[ 1 ] }`;
|
core/response.php
CHANGED
@@ -10,6 +10,7 @@ final class ITSEC_Response {
|
|
10 |
Â
private $infos;
|
11 |
Â
private $success;
|
12 |
Â
private $js_function_calls;
|
Â
|
|
13 |
Â
private $show_default_success_message;
|
14 |
Â
private $show_default_error_message;
|
15 |
Â
private $force_logout;
|
@@ -162,6 +163,14 @@ final class ITSEC_Response {
|
|
162 |
Â
} ) );
|
163 |
Â
}
|
164 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
165 |
Â
public static function set_show_default_success_message( $show_default_success_message ) {
|
166 |
Â
$self = self::get_instance();
|
167 |
Â
|
@@ -334,6 +343,7 @@ final class ITSEC_Response {
|
|
334 |
Â
'messages' => $self->messages,
|
335 |
Â
'infos' => $self->infos,
|
336 |
Â
'functionCalls' => self::parse_js_function_calls_for_module_reloads(),
|
Â
|
|
337 |
Â
'redirect' => $self->redirect,
|
338 |
Â
'closeModal' => $self->close_modal,
|
339 |
Â
'newNotifications' => $self->has_new_notifications,
|
@@ -365,6 +375,7 @@ final class ITSEC_Response {
|
|
365 |
Â
$this->infos = array();
|
366 |
Â
$this->success = true;
|
367 |
Â
$this->js_function_calls = array();
|
Â
|
|
368 |
Â
$this->show_default_success_message = true;
|
369 |
Â
$this->show_default_error_message = true;
|
370 |
Â
$this->force_logout = false;
|
10 |
Â
private $infos;
|
11 |
Â
private $success;
|
12 |
Â
private $js_function_calls;
|
13 |
+
private $store_dispatches;
|
14 |
Â
private $show_default_success_message;
|
15 |
Â
private $show_default_error_message;
|
16 |
Â
private $force_logout;
|
163 |
Â
} ) );
|
164 |
Â
}
|
165 |
Â
|
166 |
+
public static function add_store_dispatch( $store, $action, $args = array() ) {
|
167 |
+
self::get_instance()->store_dispatches[] = compact( 'store', 'action', 'args' );
|
168 |
+
}
|
169 |
+
|
170 |
+
public static function get_store_dispatches() {
|
171 |
+
return self::get_instance()->store_dispatches;
|
172 |
+
}
|
173 |
+
|
174 |
Â
public static function set_show_default_success_message( $show_default_success_message ) {
|
175 |
Â
$self = self::get_instance();
|
176 |
Â
|
343 |
Â
'messages' => $self->messages,
|
344 |
Â
'infos' => $self->infos,
|
345 |
Â
'functionCalls' => self::parse_js_function_calls_for_module_reloads(),
|
346 |
+
'storeDispatches' => $self->store_dispatches,
|
347 |
Â
'redirect' => $self->redirect,
|
348 |
Â
'closeModal' => $self->close_modal,
|
349 |
Â
'newNotifications' => $self->has_new_notifications,
|
375 |
Â
$this->infos = array();
|
376 |
Â
$this->success = true;
|
377 |
Â
$this->js_function_calls = array();
|
378 |
+
$this->store_dispatches = array();
|
379 |
Â
$this->show_default_success_message = true;
|
380 |
Â
$this->show_default_error_message = true;
|
381 |
Â
$this->force_logout = false;
|
core/rest.php
ADDED
@@ -0,0 +1,103 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ITSEC_REST {
|
4 |
+
public function run() {
|
5 |
+
add_action( 'rest_api_init', array( $this, 'rest_api_init' ), 0 );
|
6 |
+
add_filter( 'rest_response_link_curies', array( $this, 'register_curie' ) );
|
7 |
+
add_filter( 'rest_namespace_index', array( $this, 'modify_index' ) );
|
8 |
+
add_filter( 'rest_user_collection_params', [ $this, 'register_global_users_query' ] );
|
9 |
+
add_filter( 'rest_user_query', [ $this, 'apply_global_users_query' ], 10, 2 );
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Runs when the REST API is initialized.
|
14 |
+
*/
|
15 |
+
public function rest_api_init() {
|
16 |
+
ITSEC_Modules::load_module_file( 'rest.php', ':active' );
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Register the CURIE to shorten link refs.
|
21 |
+
*
|
22 |
+
* @param array $curies
|
23 |
+
*
|
24 |
+
* @return array
|
25 |
+
*/
|
26 |
+
public function register_curie( $curies ) {
|
27 |
+
ITSEC_Lib::load( 'rest' );
|
28 |
+
|
29 |
+
$curies[] = array(
|
30 |
+
'name' => 'ithemes-security',
|
31 |
+
'href' => ITSEC_Lib_REST::LINK_REL . '{rel}',
|
32 |
+
'templated' => true,
|
33 |
+
);
|
34 |
+
|
35 |
+
return $curies;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Modify the ithemes-security/v1 index to include some additional global information we need.
|
40 |
+
*
|
41 |
+
* @param WP_REST_Response $response
|
42 |
+
*
|
43 |
+
* @return WP_REST_Response
|
44 |
+
*/
|
45 |
+
public function modify_index( $response ) {
|
46 |
+
if (
|
47 |
+
ITSEC_Core::current_user_can_manage() ||
|
48 |
+
current_user_can( 'create_users' ) ||
|
49 |
+
current_user_can( 'edit_users' ) ||
|
50 |
+
current_user_can( 'promote_users' )
|
51 |
+
) {
|
52 |
+
$roles = [];
|
53 |
+
|
54 |
+
foreach ( wp_roles()->get_names() as $role => $label ) {
|
55 |
+
$roles[ $role ] = [
|
56 |
+
'label' => translate_user_role( $label ),
|
57 |
+
'canonical' => ITSEC_Lib_Canonical_Roles::get_canonical_role_from_role( $role ),
|
58 |
+
];
|
59 |
+
}
|
60 |
+
|
61 |
+
$response->data['roles'] = $roles;
|
62 |
+
}
|
63 |
+
|
64 |
+
$response->data['supports'] = apply_filters( 'itsec_rest_supports', [] );
|
65 |
+
|
66 |
+
return $response;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Registers the "itsec_global" query parameter for the users endpoint.
|
71 |
+
*
|
72 |
+
* @param array $params
|
73 |
+
*
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
public function register_global_users_query( $params ) {
|
77 |
+
if ( is_multisite() ) {
|
78 |
+
$params['itsec_global'] = [
|
79 |
+
'description' => __( 'Return results for users across the entire network, not just the current site.', 'better-wp-security' ),
|
80 |
+
'type' => 'boolean',
|
81 |
+
'default' => false,
|
82 |
+
];
|
83 |
+
}
|
84 |
+
|
85 |
+
return $params;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Applies the "itsec_global" query parameter.
|
90 |
+
*
|
91 |
+
* @param array $prepared_args
|
92 |
+
* @param WP_REST_Request $request
|
93 |
+
*
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
public function apply_global_users_query( $prepared_args, $request ) {
|
97 |
+
if ( is_multisite() && $request['itsec_global'] && current_user_can( 'manage_network_users' ) ) {
|
98 |
+
$prepared_args['blog_id'] = null;
|
99 |
+
}
|
100 |
+
|
101 |
+
return $prepared_args;
|
102 |
+
}
|
103 |
+
}
|
core/setup.php
CHANGED
@@ -3,16 +3,31 @@
|
|
3 |
Â
/**
|
4 |
Â
* Plugin activation, upgrade, deactivation and uninstall
|
5 |
Â
*
|
6 |
-
* @package iThemes-Security
|
7 |
Â
* @since 4.0
|
Â
|
|
8 |
Â
*/
|
9 |
Â
final class ITSEC_Setup {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
10 |
Â
public static function handle_activation() {
|
11 |
-
self::setup_plugin_data();
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
12 |
Â
|
13 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'initial_build' ) ) {
|
14 |
Â
ITSEC_Modules::set_setting( 'global', 'initial_build', ITSEC_Core::get_plugin_build() );
|
15 |
Â
}
|
Â
|
|
Â
|
|
16 |
Â
}
|
17 |
Â
|
18 |
Â
public static function handle_deactivation() {
|
@@ -45,15 +60,31 @@ final class ITSEC_Setup {
|
|
45 |
Â
}
|
46 |
Â
}
|
47 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
48 |
Â
public static function handle_upgrade( $build = false ) {
|
49 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'initial_build' ) ) {
|
50 |
Â
ITSEC_Modules::set_setting( 'global', 'initial_build', ITSEC_Core::get_plugin_build() - 1 );
|
51 |
Â
}
|
52 |
Â
|
53 |
-
self::setup_plugin_data( $build );
|
54 |
Â
}
|
55 |
Â
|
56 |
Â
private static function setup_plugin_data( $build = false ) {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
57 |
Â
// Determine build number of current data if it was not passed in.
|
58 |
Â
|
59 |
Â
if ( empty( $build ) ) {
|
@@ -91,8 +122,17 @@ final class ITSEC_Setup {
|
|
91 |
Â
ITSEC_Modules::set_setting( 'global', 'activation_timestamp', ITSEC_Core::get_current_time_gmt() );
|
92 |
Â
}
|
93 |
Â
|
94 |
-
|
95 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
96 |
Â
|
97 |
Â
// Run activation routines for modules to ensure that they are properly set up.
|
98 |
Â
$itsec_modules = ITSEC_Modules::get_instance();
|
@@ -171,6 +211,93 @@ final class ITSEC_Setup {
|
|
171 |
Â
|
172 |
Â
// Update stored build number.
|
173 |
Â
ITSEC_Modules::set_setting( 'global', 'build', ITSEC_Core::get_plugin_build() );
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
174 |
Â
}
|
175 |
Â
|
176 |
Â
private static function deactivate() {
|
@@ -277,7 +404,7 @@ final class ITSEC_Setup {
|
|
277 |
Â
|
278 |
Â
if ( is_multisite() ) {
|
279 |
Â
$network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
|
280 |
-
$active_plugins
|
281 |
Â
}
|
282 |
Â
|
283 |
Â
return $active_plugins;
|
3 |
Â
/**
|
4 |
Â
* Plugin activation, upgrade, deactivation and uninstall
|
5 |
Â
*
|
Â
|
|
6 |
Â
* @since 4.0
|
7 |
+
* @package iThemes-Security
|
8 |
Â
*/
|
9 |
Â
final class ITSEC_Setup {
|
10 |
+
private static $protected = [
|
11 |
+
4117,
|
12 |
+
];
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Setups plugin data when activating the plugin.
|
16 |
+
*
|
17 |
+
* @return true|WP_Error
|
18 |
+
*/
|
19 |
Â
public static function handle_activation() {
|
20 |
+
$setup = self::setup_plugin_data();
|
21 |
+
|
22 |
+
if ( is_wp_error( $setup ) ) {
|
23 |
+
return $setup;
|
24 |
+
}
|
25 |
Â
|
26 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'initial_build' ) ) {
|
27 |
Â
ITSEC_Modules::set_setting( 'global', 'initial_build', ITSEC_Core::get_plugin_build() );
|
28 |
Â
}
|
29 |
+
|
30 |
+
return true;
|
31 |
Â
}
|
32 |
Â
|
33 |
Â
public static function handle_deactivation() {
|
60 |
Â
}
|
61 |
Â
}
|
62 |
Â
|
63 |
+
/**
|
64 |
+
* Setups plugin data for the latest build.
|
65 |
+
*
|
66 |
+
* @param int|false $build The build number to upgrade from. Pass false to use the current build.
|
67 |
+
*
|
68 |
+
* @return true|WP_Error
|
69 |
+
*/
|
70 |
Â
public static function handle_upgrade( $build = false ) {
|
71 |
Â
if ( ! ITSEC_Modules::get_setting( 'global', 'initial_build' ) ) {
|
72 |
Â
ITSEC_Modules::set_setting( 'global', 'initial_build', ITSEC_Core::get_plugin_build() - 1 );
|
73 |
Â
}
|
74 |
Â
|
75 |
+
return self::setup_plugin_data( $build );
|
76 |
Â
}
|
77 |
Â
|
78 |
Â
private static function setup_plugin_data( $build = false ) {
|
79 |
+
// Ensure that the database tables are present and updated to the current schema.
|
80 |
+
$created = ITSEC_Lib::create_database_tables();
|
81 |
+
|
82 |
+
if ( is_wp_error( $created ) ) {
|
83 |
+
return $created;
|
84 |
+
}
|
85 |
+
|
86 |
+
ITSEC_Modules::initialize_container();
|
87 |
+
|
88 |
Â
// Determine build number of current data if it was not passed in.
|
89 |
Â
|
90 |
Â
if ( empty( $build ) ) {
|
122 |
Â
ITSEC_Modules::set_setting( 'global', 'activation_timestamp', ITSEC_Core::get_current_time_gmt() );
|
123 |
Â
}
|
124 |
Â
|
125 |
+
$mutex = null;
|
126 |
+
|
127 |
+
if ( self::should_do_protected_upgrade( $build ) ) {
|
128 |
+
$mutex = self::init_protected_upgrade();
|
129 |
+
|
130 |
+
if ( ! $mutex ) {
|
131 |
+
ITSEC_Storage::reload();
|
132 |
+
|
133 |
+
return new WP_Error( 'no_mutex', __( 'Failed to acquire a mutex.', 'better-wp-security' ) );
|
134 |
+
}
|
135 |
+
}
|
136 |
Â
|
137 |
Â
// Run activation routines for modules to ensure that they are properly set up.
|
138 |
Â
$itsec_modules = ITSEC_Modules::get_instance();
|
211 |
Â
|
212 |
Â
// Update stored build number.
|
213 |
Â
ITSEC_Modules::set_setting( 'global', 'build', ITSEC_Core::get_plugin_build() );
|
214 |
+
ITSEC_Storage::save();
|
215 |
+
|
216 |
+
if ( $mutex ) {
|
217 |
+
$mutex->release();
|
218 |
+
}
|
219 |
+
|
220 |
+
return true;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Should the upgrade routine be done in a protected manner with locks.
|
225 |
+
*
|
226 |
+
* @param int $current_build
|
227 |
+
*
|
228 |
+
* @return bool
|
229 |
+
*/
|
230 |
+
private static function should_do_protected_upgrade( $current_build ) {
|
231 |
+
foreach ( self::$protected as $build ) {
|
232 |
+
if ( $current_build < $build ) {
|
233 |
+
return true;
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
return false;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Initialize the protected upgrade.
|
242 |
+
*
|
243 |
+
* @return ITSEC_Mutex|null
|
244 |
+
*/
|
245 |
+
private static function init_protected_upgrade() {
|
246 |
+
usleep( 50000 );
|
247 |
+
$mutex = ITSEC_Mutex::get( 'protected-upgrade', 5 );
|
248 |
+
|
249 |
+
if ( ! $mutex ) {
|
250 |
+
if ( self::wait_for_completed_upgrade() ) {
|
251 |
+
return null;
|
252 |
+
}
|
253 |
+
|
254 |
+
self::handle_uncompleted_upgrade();
|
255 |
+
}
|
256 |
+
|
257 |
+
usleep( 50000 );
|
258 |
+
|
259 |
+
if ( ! $mutex->exists() ) {
|
260 |
+
if ( self::wait_for_completed_upgrade() ) {
|
261 |
+
return null;
|
262 |
+
}
|
263 |
+
|
264 |
+
self::handle_uncompleted_upgrade();
|
265 |
+
}
|
266 |
+
|
267 |
+
return $mutex;
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Wait for the upgrade routine to be completed.
|
272 |
+
*
|
273 |
+
* @return bool
|
274 |
+
*/
|
275 |
+
private static function wait_for_completed_upgrade() {
|
276 |
+
$count = 0;
|
277 |
+
|
278 |
+
do {
|
279 |
+
$count ++;
|
280 |
+
usleep( 50000 );
|
281 |
+
|
282 |
+
if ( ITSEC_Core::get_plugin_build() === ITSEC_Core::get_saved_plugin_build( false ) ) {
|
283 |
+
return true;
|
284 |
+
}
|
285 |
+
|
286 |
+
} while ( $count < 20 );
|
287 |
+
|
288 |
+
return false;
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Handle when an upgrade has not been able to be completed.
|
293 |
+
*/
|
294 |
+
private static function handle_uncompleted_upgrade() {
|
295 |
+
if ( 'cli' === php_sapi_name() ) {
|
296 |
+
die( 'Upgrade in progress. Please try again later' );
|
297 |
+
}
|
298 |
+
|
299 |
+
wp_safe_redirect( $_SERVER['REQUEST_URI'] );
|
300 |
+
die;
|
301 |
Â
}
|
302 |
Â
|
303 |
Â
private static function deactivate() {
|
404 |
Â
|
405 |
Â
if ( is_multisite() ) {
|
406 |
Â
$network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
|
407 |
+
$active_plugins = array_merge( $active_plugins, array_keys( $network_plugins ) );
|
408 |
Â
}
|
409 |
Â
|
410 |
Â
return $active_plugins;
|
dist/8.min.js
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
(window.itsecWebpackJsonP=window.itsecWebpackJsonP||[]).push([[8],{"+8qv":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.css=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.css=function(e){var t=e.isDisabled,n=e.theme,r=n.spacing,o=n.colors;return{color:t?o.neutral40:o.neutral80,marginLeft:r.baseUnit/2,marginRight:r.baseUnit/2,maxWidth:"calc(100% - ".concat(2*r.baseUnit,"px)"),overflow:"hidden",position:"absolute",textOverflow:"ellipsis",whiteSpace:"nowrap",top:"50%",transform:"translateY(-50%)"}};var a=function(e){var t=e.children,n=e.className,r=e.cx,a=e.getStyles,s=e.isDisabled,l=e.innerProps;return o.default.createElement("div",i({className:r((0,u.css)(a("singleValue",e)),{"single-value":!0,"single-value--is-disabled":s},n)},l),t)};t.default=a},"+URl":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LoadingIndicator=t.loadingIndicatorCSS=t.IndicatorSeparator=t.indicatorSeparatorCSS=t.ClearIndicator=t.clearIndicatorCSS=t.DropdownIndicator=t.dropdownIndicatorCSS=t.DownChevron=t.CrossIcon=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function a(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=function(e){var t=e.size,n=a(e,["size"]);return o.default.createElement("svg",i({height:t,width:t,viewBox:"0 0 20 20","aria-hidden":"true",focusable:"false",className:(0,u.css)({display:"inline-block",fill:"currentColor",lineHeight:1,stroke:"currentColor",strokeWidth:0})},n))},l=function(e){return o.default.createElement(s,i({size:20},e),o.default.createElement("path",{d:"M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"}))};t.CrossIcon=l;var c=function(e){return o.default.createElement(s,i({size:20},e),o.default.createElement("path",{d:"M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"}))};t.DownChevron=c;var p=function(e){var t=e.isFocused,n=e.theme,r=n.spacing.baseUnit,o=n.colors;return{color:t?o.neutral60:o.neutral20,display:"flex",padding:2*r,transition:"color 150ms",":hover":{color:t?o.neutral80:o.neutral40}}},f=p;t.dropdownIndicatorCSS=f;t.DropdownIndicator=function(e){var t=e.children,n=e.className,r=e.cx,a=e.getStyles,s=e.innerProps;return o.default.createElement("div",i({},s,{className:r((0,u.css)(a("dropdownIndicator",e)),{indicator:!0,"dropdown-indicator":!0},n)}),t||o.default.createElement(c,null))};var d=p;t.clearIndicatorCSS=d;t.ClearIndicator=function(e){var t=e.children,n=e.className,r=e.cx,a=e.getStyles,s=e.innerProps;return o.default.createElement("div",i({},s,{className:r((0,u.css)(a("clearIndicator",e)),{indicator:!0,"clear-indicator":!0},n)}),t||o.default.createElement(l,null))};t.indicatorSeparatorCSS=function(e){var t=e.isDisabled,n=e.theme,r=n.spacing.baseUnit,o=n.colors;return{alignSelf:"stretch",backgroundColor:t?o.neutral10:o.neutral20,marginBottom:2*r,marginTop:2*r,width:1}};t.IndicatorSeparator=function(e){var t=e.className,n=e.cx,r=e.getStyles,a=e.innerProps;return o.default.createElement("span",i({},a,{className:n((0,u.css)(r("indicatorSeparator",e)),{"indicator-separator":!0},t)}))};var h=!1;t.loadingIndicatorCSS=function(e){var t=e.isFocused,n=e.size,r=e.theme,o=r.colors,u=r.spacing.baseUnit;return{color:t?o.neutral60:o.neutral20,display:"flex",padding:2*u,transition:"color 150ms",alignSelf:"center",fontSize:n,lineHeight:1,marginRight:n,textAlign:"center",verticalAlign:"middle"}};var b=function(e){var t=e.color,n=e.delay,r=e.offset;return o.default.createElement("span",{className:(0,u.css)({animationDuration:"1s",animationDelay:"".concat(n,"ms"),animationIterationCount:"infinite",animationName:"react-select-loading-indicator",animationTimingFunction:"ease-in-out",backgroundColor:t,borderRadius:"1em",display:"inline-block",marginLeft:r?"1em":null,height:"1em",verticalAlign:"top",width:"1em"})})},m=function(e){var t=e.className,n=e.cx,r=e.getStyles,a=e.innerProps,s=e.isFocused,l=e.isRtl,c=e.theme.colors,p=s?c.neutral80:c.neutral20;return h||((0,u.injectGlobal)("@keyframes ","react-select-loading-indicator","{0%,80%,100%{opacity:0;}40%{opacity:1;}};"),h=!0),o.default.createElement("div",i({},a,{className:n((0,u.css)(r("loadingIndicator",e)),{indicator:!0,"loading-indicator":!0},t)}),o.default.createElement(b,{color:p,delay:0,offset:l}),o.default.createElement(b,{color:p,delay:160,offset:!0}),o.default.createElement(b,{color:p,delay:320,offset:!l}))};t.LoadingIndicator=m,m.defaultProps={size:4}},"/+00":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}var a=function(e){return o.default.createElement("span",i({className:(0,u.css)({zIndex:9999,border:0,clip:"rect(1px, 1px, 1px, 1px)",height:1,width:1,position:"absolute",overflow:"hidden",padding:0,whiteSpace:"nowrap",backgroundColor:"red",color:"blue"})},e))};t.default=a},"2cv3":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.IndicatorsContainer=t.indicatorsContainerCSS=t.ValueContainer=t.valueContainerCSS=t.SelectContainer=t.containerCSS=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=n("PAeb");function u(e){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t){return!t||"object"!==u(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function c(){return(c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.containerCSS=function(e){var t=e.isDisabled;return{direction:e.isRtl?"rtl":null,pointerEvents:t?"none":null,position:"relative"}};t.SelectContainer=function(e){var t=e.children,n=e.className,u=e.cx,i=e.getStyles,a=e.innerProps,s=e.isDisabled,l=e.isRtl;return r.default.createElement("div",c({className:u((0,o.css)(i("container",e)),{"--is-disabled":s,"--is-rtl":l},n)},a),t)};t.valueContainerCSS=function(e){var t=e.theme.spacing;return{alignItems:"center",display:"flex",flex:1,flexWrap:"wrap",padding:"".concat(t.baseUnit/2,"px ").concat(2*t.baseUnit,"px"),WebkitOverflowScrolling:"touch",position:"relative",overflow:"hidden"}};var p=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),a(this,s(t).apply(this,arguments))}var n,u,c;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&l(e,t)}(t,r.Component),n=t,(u=[{key:"render",value:function(){var e=this.props,t=e.children,n=e.className,u=e.cx,i=e.isMulti,a=e.getStyles,s=e.hasValue;return r.default.createElement("div",{className:u((0,o.css)(a("valueContainer",this.props)),{"value-container":!0,"value-container--is-multi":i,"value-container--has-value":s},n)},t)}}])&&i(n.prototype,u),c&&i(n,c),t}();t.ValueContainer=p;t.indicatorsContainerCSS=function(){return{alignItems:"center",alignSelf:"stretch",display:"flex",flexShrink:0}};t.IndicatorsContainer=function(e){var t=e.children,n=e.className,u=e.cx,i=e.getStyles;return r.default.createElement("div",{className:u((0,o.css)(i("indicatorsContainer",e)),{indicators:!0},n)},t)}},"3lEq":function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){try{return function e(t,n){if(t===n)return!0;if(t&&n&&"object"==r(t)&&"object"==r(n)){var a,s,l,c=o(t),p=o(n);if(c&&p){if((s=t.length)!=n.length)return!1;for(a=s;0!=a--;)if(!e(t[a],n[a]))return!1;return!0}if(c!=p)return!1;var f=t instanceof Date,d=n instanceof Date;if(f!=d)return!1;if(f&&d)return t.getTime()==n.getTime();var h=t instanceof RegExp,b=n instanceof RegExp;if(h!=b)return!1;if(h&&b)return t.toString()==n.toString();var m=u(t);if((s=m.length)!==u(n).length)return!1;for(a=s;0!=a--;)if(!i.call(n,m[a]))return!1;for(a=s;0!=a--;)if(!("_owner"===(l=m[a])&&t.$$typeof||e(t[l],n[l])))return!1;return!0}return t!=t&&n!=n}(e,t)}catch(e){if(e.message&&e.message.match(/stack|recursion/i))return console.warn("Warning: react-fast-compare does not handle circular references.",e.name,e.message),!1;throw e}};var o=Array.isArray,u=Object.keys,i=Object.prototype.hasOwnProperty},"59S1":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.resultsAriaMessage=t.optionFocusAriaMessage=t.valueFocusAriaMessage=t.valueEventAriaMessage=t.instructionsAriaMessage=void 0;t.instructionsAriaMessage=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.isSearchable,r=t.isMulti,o=t.label;switch(e){case"menu":return"Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.";case"input":return"".concat(o||"Select"," is focused ").concat(n?",type to refine list":"",", press Down to open the menu, ").concat(r?" press left to focus selected values":"");case"value":return"Use left and right to toggle between focused values, press Backspace to remove the currently focused value"}};t.valueEventAriaMessage=function(e,t){var n=t.value;if(n)switch(e){case"deselect-option":case"pop-value":case"remove-value":return"option ".concat(n,", deselected.");case"select-option":return"option ".concat(n,", selected.")}};t.valueFocusAriaMessage=function(e){var t=e.focusedValue,n=e.getOptionLabel,r=e.selectValue;return"value ".concat(n(t)," focused, ").concat(r.indexOf(t)+1," of ").concat(r.length,".")};t.optionFocusAriaMessage=function(e){var t=e.focusedOption,n=e.getOptionLabel,r=e.options;return"option ".concat(n(t)," focused, ").concat(r.indexOf(t)+1," of ").concat(r.length,".")};t.resultsAriaMessage=function(e){var t=e.inputValue,n=e.screenReaderMessage;return"".concat(n).concat(t?" for search term "+t:"",".")}},"5bE3":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.defaultComponents=t.components=void 0;var r=n("2cv3"),o=n("+URl"),u=h(n("rc6b")),i=d(n("n929")),a=h(n("KIQE")),s=d(n("Avrx")),l=d(n("lQ6M")),c=h(n("SrCC")),p=h(n("BCie")),f=h(n("+8qv"));function d(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}function h(e){return e&&e.__esModule?e:{default:e}}function b(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var m={ClearIndicator:o.ClearIndicator,Control:u.default,DropdownIndicator:o.DropdownIndicator,DownChevron:o.DownChevron,CrossIcon:o.CrossIcon,Group:i.default,GroupHeading:i.GroupHeading,IndicatorsContainer:r.IndicatorsContainer,IndicatorSeparator:o.IndicatorSeparator,Input:a.default,LoadingIndicator:o.LoadingIndicator,Menu:s.default,MenuList:s.MenuList,MenuPortal:s.MenuPortal,LoadingMessage:s.LoadingMessage,NoOptionsMessage:s.NoOptionsMessage,MultiValue:l.default,MultiValueContainer:l.MultiValueContainer,MultiValueLabel:l.MultiValueLabel,MultiValueRemove:l.MultiValueRemove,Option:c.default,Placeholder:p.default,SelectContainer:r.SelectContainer,SingleValue:f.default,ValueContainer:r.ValueContainer};t.components=m;t.defaultComponents=function(e){return function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){b(e,t,n[t])})}return e}({},m,e.components)}},"8oxB":function(e,t){var n,r,o=e.exports={};function u(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function a(e){if(n===setTimeout)return setTimeout(e,0);if((n===u||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:u}catch(e){n=u}try{r="function"==typeof clearTimeout?clearTimeout:i}catch(e){r=i}}();var s,l=[],c=!1,p=-1;function f(){c&&s&&(c=!1,s.length?l=s.concat(l):p=-1,l.length&&d())}function d(){if(!c){var e=a(f);c=!0;for(var t=l.length;t;){for(s=l,l=[];++p<t;)s&&s[p].run();p=-1,t=l.length}s=null,c=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===i||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function h(e,t){this.fun=e,this.array=t}function b(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];l.push(new h(e,t)),1!==l.length||c||a(d)},h.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=b,o.addListener=b,o.once=b,o.off=b,o.removeListener=b,o.removeAllListeners=b,o.emit=b,o.prependListener=b,o.prependOnceListener=b,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},Avrx:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getMenuPlacement=O,t.MenuPortal=t.menuPortalCSS=t.LoadingMessage=t.NoOptionsMessage=t.loadingMessageCSS=t.noOptionsMessageCSS=t.MenuList=t.menuListCSS=t.default=t.MenuPlacer=t.menuCSS=void 0;var r,o=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),u=n("PAeb"),i=n("faye"),a=(r=n("17x9"))&&r.__esModule?r:{default:r},s=n("b+PA");function l(e){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function c(){return(c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function p(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function f(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function d(e,t,n){return t&&f(e.prototype,t),n&&f(e,n),e}function h(e,t){return!t||"object"!==l(t)&&"function"!=typeof t?g(e):t}function b(e){return(b=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function m(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&v(e,t)}function v(e,t){return(v=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function g(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function y(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function O(e){var t=e.maxHeight,n=e.menuEl,r=e.minHeight,o=e.placement,u=e.shouldScroll,i=e.isFixedPosition,a=e.theme.spacing,l=(0,s.getScrollParent)(n),c={placement:"bottom",maxHeight:t};if(!n||!n.offsetParent)return c;var p=l.getBoundingClientRect().height,f=n.getBoundingClientRect(),d=f.bottom,h=f.height,b=f.top,m=n.offsetParent.getBoundingClientRect().top,v=window.innerHeight,g=(0,s.getScrollTop)(l),y=parseInt(getComputedStyle(n).marginBottom,10),O=parseInt(getComputedStyle(n).marginTop,10),E=m-O,S=v-b,C=E+g,w=p-g-b,P=d-v+g+y,A=g+b-O;switch(o){case"auto":case"bottom":if(S>=h)return{placement:"bottom",maxHeight:t};if(w>=h&&!i)return u&&(0,s.animatedScrollTo)(l,P,160),{placement:"bottom",maxHeight:t};if(!i&&w>=r||i&&S>=r)return u&&(0,s.animatedScrollTo)(l,P,160),{placement:"bottom",maxHeight:i?S-y:w-y};if("auto"===o||i){var j=t,D=i?E:C;return D>=r&&(j=Math.min(D-y-a.controlHeight,t)),{placement:"top",maxHeight:j}}if("bottom"===o)return(0,s.scrollTo)(l,P),{placement:"bottom",maxHeight:t};break;case"top":if(E>=h)return{placement:"top",maxHeight:t};if(C>=h&&!i)return u&&(0,s.animatedScrollTo)(l,A,160),{placement:"top",maxHeight:t};if(!i&&C>=r||i&&E>=r){var M=t;return(!i&&C>=r||i&&E>=r)&&(M=i?E-O:C-O),u&&(0,s.animatedScrollTo)(l,A,160),{placement:"top",maxHeight:M}}return{placement:"bottom",maxHeight:t};default:throw new Error('Invalid placement provided "'.concat(o,'".'))}return c}var E=function(e){return"auto"===e?"bottom":e};t.menuCSS=function(e){var t,n=e.placement,r=e.theme,o=r.borderRadius,u=r.spacing,i=r.colors;return y(t={},function(e){return e?{bottom:"top",top:"bottom"}[e]:"bottom"}(n),"100%"),y(t,"backgroundColor",i.neutral0),y(t,"borderRadius",o),y(t,"boxShadow","0 0 0 1px hsla(0, 0%, 0%, 0.1), 0 4px 11px hsla(0, 0%, 0%, 0.1)"),y(t,"marginBottom",u.menuGutter),y(t,"marginTop",u.menuGutter),y(t,"position","absolute"),y(t,"width","100%"),y(t,"zIndex",1),t};var S=function(e){function t(){var e,n;p(this,t);for(var r=arguments.length,o=new Array(r),u=0;u<r;u++)o[u]=arguments[u];return y(g(g(n=h(this,(e=b(t)).call.apply(e,[this].concat(o))))),"state",{maxHeight:n.props.maxMenuHeight,placement:null}),y(g(g(n)),"getPlacement",function(e){var t=n.props,r=t.minMenuHeight,o=t.maxMenuHeight,u=t.menuPlacement,i=t.menuPosition,a=t.menuShouldScrollIntoView,s=t.theme,l=n.context.getPortalPlacement;if(e){var c="fixed"===i,p=O({maxHeight:o,menuEl:e,minHeight:r,placement:u,shouldScroll:a&&!c,isFixedPosition:c,theme:s});l&&l(p),n.setState(p)}}),y(g(g(n)),"getUpdatedProps",function(){var e=n.props.menuPlacement,t=n.state.placement||E(e);return function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){y(e,t,n[t])})}return e}({},n.props,{placement:t,maxHeight:n.state.maxHeight})}),n}return m(t,o.Component),d(t,[{key:"render",value:function(){return(0,this.props.children)({ref:this.getPlacement,placerProps:this.getUpdatedProps()})}}]),t}();t.MenuPlacer=S,y(S,"contextTypes",{getPortalPlacement:a.default.func});var C=function(e){var t=e.children,n=e.className,r=e.cx,i=e.getStyles,a=e.innerRef,s=e.innerProps,l=r((0,u.css)(i("menu",e)),{menu:!0},n);return o.default.createElement("div",c({className:l},s,{ref:a}),t)};t.default=C;t.menuListCSS=function(e){var t=e.maxHeight,n=e.theme.spacing.baseUnit;return{maxHeight:t,overflowY:"auto",paddingBottom:n,paddingTop:n,position:"relative",WebkitOverflowScrolling:"touch"}};t.MenuList=function(e){var t=e.children,n=e.className,r=e.cx,i=e.getStyles,a=e.isMulti,s=e.innerRef;return o.default.createElement("div",{className:r((0,u.css)(i("menuList",e)),{"menu-list":!0,"menu-list--is-multi":a},n),ref:s},t)};var w=function(e){var t=e.theme,n=t.spacing.baseUnit;return{color:t.colors.neutral40,padding:"".concat(2*n,"px ").concat(3*n,"px"),textAlign:"center"}},P=w;t.noOptionsMessageCSS=P;var A=w;t.loadingMessageCSS=A;var j=function(e){var t=e.children,n=e.className,r=e.cx,i=e.getStyles,a=e.innerProps;return o.default.createElement("div",c({className:r((0,u.css)(i("noOptionsMessage",e)),{"menu-notice":!0,"menu-notice--no-options":!0},n)},a),t)};t.NoOptionsMessage=j,j.defaultProps={children:"No options"};var D=function(e){var t=e.children,n=e.className,r=e.cx,i=e.getStyles,a=e.innerProps;return o.default.createElement("div",c({className:r((0,u.css)(i("loadingMessage",e)),{"menu-notice":!0,"menu-notice--loading":!0},n)},a),t)};t.LoadingMessage=D,D.defaultProps={children:"Loading..."};t.menuPortalCSS=function(e){var t=e.rect,n=e.offset,r=e.position;return{left:t.left,position:r,top:n,width:t.width,zIndex:1}};var M=function(e){function t(){var e,n;p(this,t);for(var r=arguments.length,o=new Array(r),u=0;u<r;u++)o[u]=arguments[u];return y(g(g(n=h(this,(e=b(t)).call.apply(e,[this].concat(o))))),"state",{placement:null}),y(g(g(n)),"getPortalPlacement",function(e){var t=e.placement;t!==E(n.props.menuPlacement)&&n.setState({placement:t})}),n}return m(t,o.Component),d(t,[{key:"getChildContext",value:function(){return{getPortalPlacement:this.getPortalPlacement}}},{key:"render",value:function(){var e=this.props,t=e.appendTo,n=e.children,r=e.controlElement,a=e.menuPlacement,l=e.menuPosition,c=e.getStyles,p="fixed"===l;if(!t&&!p||!r)return null;var f=this.state.placement||E(a),d=(0,s.getBoundingClientObj)(r),h=p?0:window.pageYOffset,b={offset:d[f]+h,position:l,rect:d},m=o.default.createElement("div",{className:(0,u.css)(c("menuPortal",b))},n);return t?(0,i.createPortal)(m,t):m}}]),t}();t.MenuPortal=M,y(M,"childContextTypes",{getPortalPlacement:a.default.func})},BCie:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.placeholderCSS=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.placeholderCSS=function(e){var t=e.theme,n=t.spacing;return{color:t.colors.neutral50,marginLeft:n.baseUnit/2,marginRight:n.baseUnit/2,position:"absolute",top:"50%",transform:"translateY(-50%)"}};var a=function(e){var t=e.children,n=e.className,r=e.cx,a=e.getStyles,s=e.innerProps;return o.default.createElement("div",i({className:r((0,u.css)(a("placeholder",e)),{placeholder:!0},n)},s),t)};t.default=a},CXKz:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n("cDcd"),o=n("GlKT"),u=n("SHH1");function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function c(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function p(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var f=!("undefined"==typeof window||!window.document||!window.document.createElement),d=0,h=function(e){function t(){var e,n,r,o;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var u=arguments.length,a=new Array(u),l=0;l<u;l++)a[l]=arguments[l];return r=this,n=!(o=(e=s(t)).call.apply(e,[this].concat(a)))||"object"!==i(o)&&"function"!=typeof o?c(r):o,p(c(c(n)),"originalStyles",{}),p(c(c(n)),"listenerOptions",{capture:!1,passive:!1}),n}var n,h,b;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&l(e,t)}(t,r.Component),n=t,(h=[{key:"componentDidMount",value:function(){var e=this;if(f){var t=this.props,n=t.accountForScrollbars,r=t.touchScrollTarget,i=document.body,a=i&&i.style;if(n&&o.STYLE_KEYS.forEach(function(t){var n=a&&a[t];e.originalStyles[t]=n}),n&&d<1){var s=parseInt(this.originalStyles.paddingRight,10)||0,l=document.body?document.body.clientWidth:0,c=window.innerWidth-l+s||0;Object.keys(o.LOCK_STYLES).forEach(function(e){var t=o.LOCK_STYLES[e];a&&(a[e]=t)}),a&&(a.paddingRight="".concat(c,"px"))}i&&(0,u.isTouchDevice)()&&(i.addEventListener("touchmove",u.preventTouchMove,this.listenerOptions),r&&(r.addEventListener("touchstart",u.preventInertiaScroll,this.listenerOptions),r.addEventListener("touchmove",u.allowTouchMove,this.listenerOptions))),d+=1}}},{key:"componentWillUnmount",value:function(){var e=this;if(f){var t=this.props,n=t.accountForScrollbars,r=t.touchScrollTarget,i=document.body,a=i&&i.style;d=Math.max(d-1,0),n&&d<1&&o.STYLE_KEYS.forEach(function(t){var n=e.originalStyles[t];a&&(a[t]=n)}),i&&(0,u.isTouchDevice)()&&(i.removeEventListener("touchmove",u.preventTouchMove,this.listenerOptions),r&&(r.removeEventListener("touchstart",u.preventInertiaScroll,this.listenerOptions),r.removeEventListener("touchmove",u.allowTouchMove,this.listenerOptions)))}}},{key:"render",value:function(){return null}}])&&a(n.prototype,h),b&&a(n,b),t}();t.default=h,p(h,"defaultProps",{accountForScrollbars:!0})},FUBA:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=n("cDcd"),i=s(u),a=s(n("17x9"));function s(e){return e&&e.__esModule?e:{default:e}}var l={position:"absolute",top:0,left:0,visibility:"hidden",height:0,overflow:"scroll",whiteSpace:"pre"},c=["extraWidth","injectStyles","inputClassName","inputRef","inputStyle","minWidth","onAutosize","placeholderIsMinWidth"],p=function(e,t){t.style.fontSize=e.fontSize,t.style.fontFamily=e.fontFamily,t.style.fontWeight=e.fontWeight,t.style.fontStyle=e.fontStyle,t.style.letterSpacing=e.letterSpacing,t.style.textTransform=e.textTransform},f=!("undefined"==typeof window||!window.navigator)&&/MSIE |Trident\/|Edge\//.test(window.navigator.userAgent),d=function(){return f?"_"+Math.random().toString(36).substr(2,12):void 0},h=function(e){function t(e){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.inputRef=function(e){n.input=e,"function"==typeof n.props.inputRef&&n.props.inputRef(e)},n.placeHolderSizerRef=function(e){n.placeHolderSizer=e},n.sizerRef=function(e){n.sizer=e},n.state={inputWidth:e.minWidth,inputId:e.id||d()},n}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,u.Component),o(t,[{key:"componentDidMount",value:function(){this.mounted=!0,this.copyInputStyles(),this.updateInputWidth()}},{key:"componentWillReceiveProps",value:function(e){var t=e.id;t!==this.props.id&&this.setState({inputId:t||d()})}},{key:"componentDidUpdate",value:function(e,t){t.inputWidth!==this.state.inputWidth&&"function"==typeof this.props.onAutosize&&this.props.onAutosize(this.state.inputWidth),this.updateInputWidth()}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"copyInputStyles",value:function(){if(this.mounted&&window.getComputedStyle){var e=this.input&&window.getComputedStyle(this.input);e&&(p(e,this.sizer),this.placeHolderSizer&&p(e,this.placeHolderSizer))}}},{key:"updateInputWidth",value:function(){if(this.mounted&&this.sizer&&void 0!==this.sizer.scrollWidth){var e=void 0;e=this.props.placeholder&&(!this.props.value||this.props.value&&this.props.placeholderIsMinWidth)?Math.max(this.sizer.scrollWidth,this.placeHolderSizer.scrollWidth)+2:this.sizer.scrollWidth+2,(e+="number"===this.props.type&&void 0===this.props.extraWidth?16:parseInt(this.props.extraWidth)||0)<this.props.minWidth&&(e=this.props.minWidth),e!==this.state.inputWidth&&this.setState({inputWidth:e})}}},{key:"getInput",value:function(){return this.input}},{key:"focus",value:function(){this.input.focus()}},{key:"blur",value:function(){this.input.blur()}},{key:"select",value:function(){this.input.select()}},{key:"renderStyles",value:function(){var e=this.props.injectStyles;return f&&e?i.default.createElement("style",{dangerouslySetInnerHTML:{__html:"input#"+this.state.inputId+"::-ms-clear {display: none;}"}}):null}},{key:"render",value:function(){var e=[this.props.defaultValue,this.props.value,""].reduce(function(e,t){return null!=e?e:t}),t=r({},this.props.style);t.display||(t.display="inline-block");var n=r({boxSizing:"content-box",width:this.state.inputWidth+"px"},this.props.inputStyle),o=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(this.props,[]);return function(e){c.forEach(function(t){return delete e[t]})}(o),o.className=this.props.inputClassName,o.id=this.state.inputId,o.style=n,i.default.createElement("div",{className:this.props.className,style:t},this.renderStyles(),i.default.createElement("input",r({},o,{ref:this.inputRef})),i.default.createElement("div",{ref:this.sizerRef,style:l},e),this.props.placeholder?i.default.createElement("div",{ref:this.placeHolderSizerRef,style:l},this.props.placeholder):null)}}]),t}();h.propTypes={className:a.default.string,defaultValue:a.default.any,extraWidth:a.default.oneOfType([a.default.number,a.default.string]),id:a.default.string,injectStyles:a.default.bool,inputClassName:a.default.string,inputRef:a.default.func,inputStyle:a.default.object,minWidth:a.default.oneOfType([a.default.number,a.default.string]),onAutosize:a.default.func,onChange:a.default.func,placeholder:a.default.string,placeholderIsMinWidth:a.default.bool,style:a.default.object,value:a.default.any},h.defaultProps={minWidth:1,injectStyles:!0},t.default=h},GlKT:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LOCK_STYLES=t.STYLE_KEYS=void 0;t.STYLE_KEYS=["boxSizing","height","overflow","paddingRight","position"];t.LOCK_STYLES={boxSizing:"border-box",overflow:"hidden",position:"relative",height:"100%"}},H0AD:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.makeAsyncSelect=t.defaultProps=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=a(n("jMYa")),u=n("b+PA"),i=a(n("oUUL"));function a(e){return e&&e.__esModule?e:{default:e}}function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function l(){return(l=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function c(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function p(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function f(e){return(f=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function d(e,t){return(d=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function h(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function b(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var m={cacheOptions:!1,defaultOptions:!1,filterOption:null};t.defaultProps=m;var v=function(e){var t,n;return n=t=function(t){function n(e){var t,r,o;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),r=this,o=f(n).call(this),t=!o||"object"!==s(o)&&"function"!=typeof o?h(r):o,b(h(h(t)),"select",void 0),b(h(h(t)),"lastRequest",void 0),b(h(h(t)),"mounted",!1),b(h(h(t)),"optionsCache",{}),b(h(h(t)),"handleInputChange",function(e,n){var r=t.props,o=r.cacheOptions,i=r.onInputChange,a=(0,u.handleInputChange)(e,n,i);if(!a)return delete t.lastRequest,void t.setState({inputValue:"",loadedInputValue:"",loadedOptions:[],isLoading:!1,passEmptyOptions:!1});if(o&&t.optionsCache[a])t.setState({inputValue:a,loadedInputValue:a,loadedOptions:t.optionsCache[a],isLoading:!1,passEmptyOptions:!1});else{var s=t.lastRequest={};t.setState({inputValue:a,isLoading:!0,passEmptyOptions:!t.state.loadedInputValue},function(){t.loadOptions(a,function(e){t.mounted&&(e&&(t.optionsCache[a]=e),s===t.lastRequest&&(delete t.lastRequest,t.setState({isLoading:!1,loadedInputValue:a,loadedOptions:e||[],passEmptyOptions:!1})))})})}return a}),t.state={defaultOptions:Array.isArray(e.defaultOptions)?e.defaultOptions:void 0,inputValue:void 0!==e.inputValue?e.inputValue:"",isLoading:!0===e.defaultOptions,loadedOptions:[],passEmptyOptions:!1},t}var o,i,a;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&d(e,t)}(n,r.Component),o=n,(i=[{key:"componentDidMount",value:function(){var e=this;this.mounted=!0;var t=this.props.defaultOptions,n=this.state.inputValue;!0===t&&this.loadOptions(n,function(t){if(e.mounted){var n=!!e.lastRequest;e.setState({defaultOptions:t||[],isLoading:n})}})}},{key:"componentWillReceiveProps",value:function(e){e.cacheOptions!==this.props.cacheOptions&&(this.optionsCache={}),e.defaultOptions!==this.props.defaultOptions&&this.setState({defaultOptions:Array.isArray(e.defaultOptions)?e.defaultOptions:void 0})}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"focus",value:function(){this.select.focus()}},{key:"blur",value:function(){this.select.blur()}},{key:"loadOptions",value:function(e,t){var n=this.props.loadOptions;if(!n)return t();var r=n(e,t);r&&"function"==typeof r.then&&r.then(t,function(){return t()})}},{key:"render",value:function(){var t=this,n=this.props,o=(n.loadOptions,c(n,["loadOptions"])),u=this.state,i=u.defaultOptions,a=u.inputValue,s=u.isLoading,p=u.loadedInputValue,f=u.loadedOptions,d=u.passEmptyOptions?[]:a&&p?f:i||[];return r.default.createElement(e,l({},o,{ref:function(e){t.select=e},options:d,isLoading:s,onInputChange:this.handleInputChange}))}}])&&p(o.prototype,i),a&&p(o,a),n}(),b(t,"defaultProps",m),n};t.makeAsyncSelect=v;var g=v((0,i.default)(o.default));t.default=g},H6Zs:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=n("PAeb");function u(e){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function a(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function s(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function l(e,t){return!t||"object"!==u(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function p(e,t){return(p=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var f=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),l(this,c(t).apply(this,arguments))}var n,u,f;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&p(e,t)}(t,r.Component),n=t,(u=[{key:"render",value:function(){var e=this.props,t=(e.in,e.out,e.onExited,e.appear,e.enter,e.exit,e.innerRef),n=(e.emotion,a(e,["in","out","onExited","appear","enter","exit","innerRef","emotion"]));return r.default.createElement("input",i({ref:t},n,{className:(0,o.css)({background:0,border:0,fontSize:"inherit",outline:0,padding:0,width:1,color:"transparent",left:-100,opacity:0,position:"relative",transform:"scale(0)"})}))}}])&&s(n.prototype,u),f&&s(n,f),t}();t.default=f},KIQE:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.inputCSS=void 0;var r=i(n("cDcd")),o=n("PAeb"),u=i(n("FUBA"));function i(e){return e&&e.__esModule?e:{default:e}}function a(){return(a=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){l(e,t,n[t])})}return e}function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}t.inputCSS=function(e){var t=e.isDisabled,n=e.theme,r=n.spacing,o=n.colors;return{margin:r.baseUnit/2,paddingBottom:r.baseUnit/2,paddingTop:r.baseUnit/2,visibility:t?"hidden":"visible",color:o.neutral80}};var p=function(e){return{background:0,border:0,fontSize:"inherit",opacity:e?0:1,outline:0,padding:0,color:"inherit"}},f=function(e){var t=e.className,n=e.cx,i=e.getStyles,l=e.innerRef,f=e.isHidden,d=e.isDisabled,h=e.theme,b=(e.selectProps,c(e,["className","cx","getStyles","innerRef","isHidden","isDisabled","theme","selectProps"]));return r.default.createElement("div",{className:(0,o.css)(i("input",s({theme:h},b)))},r.default.createElement(u.default,a({className:n(null,{input:!0},t),inputRef:l,inputStyle:p(f),disabled:d},b)))};t.default=f},KXCe:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.defaultTheme=t.spacing=t.colors=void 0;var r={primary:"#2684FF",primary75:"#4C9AFF",primary50:"#B2D4FF",primary25:"#DEEBFF",danger:"#DE350B",dangerLight:"#FFBDAD",neutral0:"hsl(0, 0%, 100%)",neutral5:"hsl(0, 0%, 95%)",neutral10:"hsl(0, 0%, 90%)",neutral20:"hsl(0, 0%, 80%)",neutral30:"hsl(0, 0%, 70%)",neutral40:"hsl(0, 0%, 60%)",neutral50:"hsl(0, 0%, 50%)",neutral60:"hsl(0, 0%, 40%)",neutral70:"hsl(0, 0%, 30%)",neutral80:"hsl(0, 0%, 20%)",neutral90:"hsl(0, 0%, 10%)"};t.colors=r;var o={baseUnit:4,controlHeight:38,menuGutter:8};t.spacing=o;var u={borderRadius:4,colors:r,spacing:o};t.defaultTheme=u},N3bB:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=n("cDcd"),o=n("faye");function u(e){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function a(e,t){return!t||"object"!==u(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var c=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),a(this,s(t).apply(this,arguments))}var n,u,c;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&l(e,t)}(t,r.Component),n=t,(u=[{key:"componentDidMount",value:function(){this.props.innerRef((0,o.findDOMNode)(this))}},{key:"componentWillUnmount",value:function(){this.props.innerRef(null)}},{key:"render",value:function(){return this.props.children}}])&&i(n.prototype,u),c&&i(n,c),t}();t.default=c},PAeb:function(e,t,n){"use strict";n.r(t),function(e){n.d(t,"flush",function(){return i}),n.d(t,"hydrate",function(){return a}),n.d(t,"cx",function(){return s}),n.d(t,"merge",function(){return l}),n.d(t,"getRegisteredStyles",function(){return c}),n.d(t,"injectGlobal",function(){return p}),n.d(t,"keyframes",function(){return f}),n.d(t,"css",function(){return d}),n.d(t,"sheet",function(){return h}),n.d(t,"caches",function(){return b});var r=n("oj4i"),o=void 0!==e?e:{},u=Object(r.a)(o),i=u.flush,a=u.hydrate,s=u.cx,l=u.merge,c=u.getRegisteredStyles,p=u.injectGlobal,f=u.keyframes,d=u.css,h=u.sheet,b=u.caches}.call(this,n("yLpj"))},QcsS:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=n("PAeb"),u=a(n("N3bB")),i=a(n("CXKz"));function a(e){return e&&e.__esModule?e:{default:e}}function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function l(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function p(e,t){return(p=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function f(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function d(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var h=function(e){function t(){var e,n,r,o;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var u=arguments.length,i=new Array(u),a=0;a<u;a++)i[a]=arguments[a];return r=this,o=(e=c(t)).call.apply(e,[this].concat(i)),n=!o||"object"!==s(o)&&"function"!=typeof o?f(r):o,d(f(f(n)),"state",{touchScrollTarget:null}),d(f(f(n)),"getScrollTarget",function(e){e!==n.state.touchScrollTarget&&n.setState({touchScrollTarget:e})}),d(f(f(n)),"blurSelectInput",function(){document.activeElement&&document.activeElement.blur()}),n}var n,a,h;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&p(e,t)}(t,r.PureComponent),n=t,(a=[{key:"render",value:function(){var e=this.props,t=e.children,n=e.isEnabled,a=this.state.touchScrollTarget;return n?r.default.createElement("div",null,r.default.createElement("div",{onClick:this.blurSelectInput,className:(0,o.css)({position:"fixed",left:0,bottom:0,right:0,top:0})}),r.default.createElement(u.default,{innerRef:this.getScrollTarget},t),a?r.default.createElement(i.default,{touchScrollTarget:a}):null):t}}])&&l(n.prototype,a),h&&l(n,h),t}();t.default=h},SHH1:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.preventTouchMove=function(e){e.preventDefault()},t.allowTouchMove=function(e){e.stopPropagation()},t.preventInertiaScroll=function(){var e=this.scrollTop,t=this.scrollHeight,n=e+this.offsetHeight;0===e?this.scrollTop=1:n===t&&(this.scrollTop=e-1)},t.isTouchDevice=function(){return"ontouchstart"in window||navigator.maxTouchPoints}},SrCC:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.optionCSS=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.optionCSS=function(e){var t=e.isDisabled,n=e.isFocused,r=e.isSelected,o=e.theme,u=o.spacing,i=o.colors;return{backgroundColor:r?i.primary:n?i.primary25:"transparent",color:t?i.neutral20:r?i.neutral0:"inherit",cursor:"default",display:"block",fontSize:"inherit",padding:"".concat(2*u.baseUnit,"px ").concat(3*u.baseUnit,"px"),width:"100%",userSelect:"none",WebkitTapHighlightColor:"rgba(0, 0, 0, 0)",":active":{backgroundColor:r?i.primary:i.primary50}}};var a=function(e){var t=e.children,n=e.className,r=e.cx,a=e.getStyles,s=e.isDisabled,l=e.isFocused,c=e.isSelected,p=e.innerRef,f=e.innerProps;return o.default.createElement("div",i({ref:p,className:r((0,u.css)(a("option",e)),{option:!0,"option--is-disabled":s,"option--is-focused":l,"option--is-selected":c},n)},f),t)};t.default=a},TAZq:function(e,t,n){e.exports=function(){"use strict";return function(e){function t(t){if(t)try{e(t+"}")}catch(e){}}return function(n,r,o,u,i,a,s,l,c,p){switch(n){case 1:if(0===c&&64===r.charCodeAt(0))return e(r+";"),"";break;case 2:if(0===l)return r+"/*|*/";break;case 3:switch(l){case 102:case 112:return e(o[0]+r),"";default:return r+(0===p?"/*|*/":"")}case-2:r.split("/*|*/}").forEach(t)}}}}()},WvHe:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.mergeStyles=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){d(e,t,n[t])})}return e}({},e);return Object.keys(t).forEach(function(r){e[r]?n[r]=function(n,o){return t[r](e[r](n,o),o)}:n[r]=t[r]}),n},t.defaultStyles=void 0;var r=n("2cv3"),o=n("rc6b"),u=n("n929"),i=n("+URl"),a=n("KIQE"),s=n("BCie"),l=n("SrCC"),c=n("Avrx"),p=n("+8qv"),f=n("lQ6M");function d(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var h={clearIndicator:i.clearIndicatorCSS,container:r.containerCSS,control:o.css,dropdownIndicator:i.dropdownIndicatorCSS,group:u.groupCSS,groupHeading:u.groupHeadingCSS,indicatorsContainer:r.indicatorsContainerCSS,indicatorSeparator:i.indicatorSeparatorCSS,input:a.inputCSS,loadingIndicator:i.loadingIndicatorCSS,loadingMessage:c.loadingMessageCSS,menu:c.menuCSS,menuList:c.menuListCSS,menuPortal:c.menuPortalCSS,multiValue:f.multiValueCSS,multiValueLabel:f.multiValueLabelCSS,multiValueRemove:f.multiValueRemoveCSS,noOptionsMessage:c.noOptionsMessageCSS,option:l.optionCSS,placeholder:s.placeholderCSS,singleValue:p.css,valueContainer:r.valueContainerCSS};t.defaultStyles=h},Wwog:function(e,t,n){"use strict";n.r(t);var r=function(e,t){return e.length===t.length&&e.every(function(e,n){return r=e,o=t[n],r===o;var r,o})};t.default=function(e,t){var n;void 0===t&&(t=r);var o,u=[],i=!1;return function(){for(var r=arguments.length,a=new Array(r),s=0;s<r;s++)a[s]=arguments[s];return i&&n===this&&t(a,u)?o:(o=e.apply(this,a),i=!0,n=this,u=a,o)}}},"b+PA":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.classNames=function(e,t,n,r){var o=[t,r];if(n&&e)for(var u in n)n.hasOwnProperty(u)&&n[u]&&o.push("".concat(a(e,u)));return o.filter(function(e){return e}).map(function(e){return String(e).trim()}).join(" ")},t.handleInputChange=function(e,t,n){if(n){var r=n(e,t);if("string"==typeof r)return r}return e},t.isDocumentElement=s,t.normalizedHeight=function(e){if(s(e))return window.innerHeight;return e.clientHeight},t.getScrollTop=l,t.scrollTo=c,t.getScrollParent=function(e){var t=getComputedStyle(e),n="absolute"===t.position,r=/(auto|scroll)/,o=document.documentElement;if("fixed"===t.position)return o;for(var u=e;u=u.parentElement;)if(t=getComputedStyle(u),(!n||"static"!==t.position)&&r.test(t.overflow+t.overflowY+t.overflowX))return u;return o},t.animatedScrollTo=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:200,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:i,u=l(e),a=t-u,s=10,p=0;!function t(){p+=s;var i=(l=p,f=u,d=a,h=n,d*((l=l/h-1)*l*l+1)+f);var l,f,d,h;c(e,i);p<n?(0,o.default)(t):r(e)}()},t.scrollIntoView=function(e,t){var n=e.getBoundingClientRect(),r=t.getBoundingClientRect(),o=t.offsetHeight/3;r.bottom+o>n.bottom?c(e,Math.min(t.offsetTop+t.clientHeight-e.offsetHeight+o,e.scrollHeight)):r.top-o<n.top&&c(e,Math.max(t.offsetTop-o,0))},t.getBoundingClientObj=function(e){var t=e.getBoundingClientRect();return{bottom:t.bottom,height:t.height,left:t.left,right:t.right,top:t.top,width:t.width}},t.toKey=function(e){return e.replace(/\W/g,"-")},t.isTouchCapable=function(){try{return document.createEvent("TouchEvent"),!0}catch(e){return!1}},t.isMobileDevice=function(){try{return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}catch(e){return!1}},t.cleanValue=t.emptyString=t.noop=void 0;var r,o=(r=n("xEkU"))&&r.__esModule?r:{default:r};function u(e){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var i=function(){};t.noop=i;function a(e,t){return t?"-"===t[0]?e+t:e+"__"+t:e}t.emptyString=function(){return""};function s(e){return[document.documentElement,document.body,window].indexOf(e)>-1}function l(e){return s(e)?window.pageYOffset:e.scrollTop}function c(e,t){s(e)?window.scrollTo(0,t):e.scrollTop=t}t.cleanValue=function(e){return Array.isArray(e)?e.filter(Boolean):"object"===u(e)&&null!==e?[e]:[]}},bQgK:function(e,t,n){(function(t){(function(){var n,r,o,u,i,a;"undefined"!=typeof performance&&null!==performance&&performance.now?e.exports=function(){return performance.now()}:null!=t&&t.hrtime?(e.exports=function(){return(n()-i)/1e6},r=t.hrtime,u=(n=function(){var e;return 1e9*(e=r())[0]+e[1]})(),a=1e9*t.uptime(),i=u-a):Date.now?(e.exports=function(){return Date.now()-o},o=Date.now()):(e.exports=function(){return(new Date).getTime()-o},o=(new Date).getTime())}).call(this)}).call(this,n("8oxB"))},"c+lM":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.stripDiacritics=void 0;var r=[{base:"A",letters:/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},{base:"AA",letters:/[\uA732]/g},{base:"AE",letters:/[\u00C6\u01FC\u01E2]/g},{base:"AO",letters:/[\uA734]/g},{base:"AU",letters:/[\uA736]/g},{base:"AV",letters:/[\uA738\uA73A]/g},{base:"AY",letters:/[\uA73C]/g},{base:"B",letters:/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},{base:"C",letters:/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},{base:"D",letters:/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},{base:"DZ",letters:/[\u01F1\u01C4]/g},{base:"Dz",letters:/[\u01F2\u01C5]/g},{base:"E",letters:/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},{base:"F",letters:/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},{base:"G",letters:/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},{base:"H",letters:/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},{base:"I",letters:/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},{base:"J",letters:/[\u004A\u24BF\uFF2A\u0134\u0248]/g},{base:"K",letters:/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},{base:"L",letters:/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},{base:"LJ",letters:/[\u01C7]/g},{base:"Lj",letters:/[\u01C8]/g},{base:"M",letters:/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},{base:"N",letters:/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},{base:"NJ",letters:/[\u01CA]/g},{base:"Nj",letters:/[\u01CB]/g},{base:"O",letters:/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},{base:"OI",letters:/[\u01A2]/g},{base:"OO",letters:/[\uA74E]/g},{base:"OU",letters:/[\u0222]/g},{base:"P",letters:/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},{base:"Q",letters:/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},{base:"R",letters:/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},{base:"S",letters:/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},{base:"T",letters:/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},{base:"TZ",letters:/[\uA728]/g},{base:"U",letters:/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},{base:"V",letters:/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},{base:"VY",letters:/[\uA760]/g},{base:"W",letters:/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},{base:"X",letters:/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},{base:"Y",letters:/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},{base:"Z",letters:/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},{base:"a",letters:/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},{base:"aa",letters:/[\uA733]/g},{base:"ae",letters:/[\u00E6\u01FD\u01E3]/g},{base:"ao",letters:/[\uA735]/g},{base:"au",letters:/[\uA737]/g},{base:"av",letters:/[\uA739\uA73B]/g},{base:"ay",letters:/[\uA73D]/g},{base:"b",letters:/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},{base:"c",letters:/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},{base:"d",letters:/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},{base:"dz",letters:/[\u01F3\u01C6]/g},{base:"e",letters:/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},{base:"f",letters:/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},{base:"g",letters:/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},{base:"h",letters:/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},{base:"hv",letters:/[\u0195]/g},{base:"i",letters:/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},{base:"j",letters:/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},{base:"k",letters:/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},{base:"l",letters:/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},{base:"lj",letters:/[\u01C9]/g},{base:"m",letters:/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},{base:"n",letters:/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},{base:"nj",letters:/[\u01CC]/g},{base:"o",letters:/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},{base:"oi",letters:/[\u01A3]/g},{base:"ou",letters:/[\u0223]/g},{base:"oo",letters:/[\uA74F]/g},{base:"p",letters:/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},{base:"q",letters:/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},{base:"r",letters:/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},{base:"s",letters:/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},{base:"t",letters:/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},{base:"tz",letters:/[\uA729]/g},{base:"u",letters:/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},{base:"v",letters:/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},{base:"vy",letters:/[\uA761]/g},{base:"w",letters:/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},{base:"x",letters:/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},{base:"y",letters:/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},{base:"z",letters:/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}];t.stripDiacritics=function(e){for(var t=0;t<r.length;t++)e=e.replace(r[t].letters,r[t].base);return e}},d6Hc:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,o=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),u=(r=n("N3bB"))&&r.__esModule?r:{default:r};function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function c(e,t,n){return t&&l(e.prototype,t),n&&l(e,n),e}function p(e,t){return!t||"object"!==a(t)&&"function"!=typeof t?b(e):t}function f(e){return(f=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function d(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&h(e,t)}function h(e,t){return(h=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function b(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var v=function(e){function t(){var e,n;s(this,t);for(var r=arguments.length,o=new Array(r),u=0;u<r;u++)o[u]=arguments[u];return m(b(b(n=p(this,(e=f(t)).call.apply(e,[this].concat(o))))),"isBottom",!1),m(b(b(n)),"isTop",!1),m(b(b(n)),"scrollTarget",void 0),m(b(b(n)),"touchStart",void 0),m(b(b(n)),"cancelScroll",function(e){e.preventDefault(),e.stopPropagation()}),m(b(b(n)),"handleEventDelta",function(e,t){var r=n.props,o=r.onBottomArrive,u=r.onBottomLeave,i=r.onTopArrive,a=r.onTopLeave,s=n.scrollTarget,l=s.scrollTop,c=s.scrollHeight,p=s.clientHeight,f=n.scrollTarget,d=t>0,h=c-p-l,b=!1;h>t&&n.isBottom&&(u&&u(e),n.isBottom=!1),d&&n.isTop&&(a&&a(e),n.isTop=!1),d&&t>h?(o&&!n.isBottom&&o(e),f.scrollTop=c,b=!0,n.isBottom=!0):!d&&-t>l&&(i&&!n.isTop&&i(e),f.scrollTop=0,b=!0,n.isTop=!0),b&&n.cancelScroll(e)}),m(b(b(n)),"onWheel",function(e){n.handleEventDelta(e,e.deltaY)}),m(b(b(n)),"onTouchStart",function(e){n.touchStart=e.changedTouches[0].clientY}),m(b(b(n)),"onTouchMove",function(e){var t=n.touchStart-e.changedTouches[0].clientY;n.handleEventDelta(e,t)}),m(b(b(n)),"getScrollTarget",function(e){n.scrollTarget=e}),n}return d(t,o.Component),c(t,[{key:"componentDidMount",value:function(){this.startListening(this.scrollTarget)}},{key:"componentWillUnmount",value:function(){this.stopListening(this.scrollTarget)}},{key:"startListening",value:function(e){e&&(e.scrollHeight<=e.clientHeight||("function"==typeof e.addEventListener&&e.addEventListener("wheel",this.onWheel,!1),"function"==typeof e.addEventListener&&e.addEventListener("touchstart",this.onTouchStart,!1),"function"==typeof e.addEventListener&&e.addEventListener("touchmove",this.onTouchMove,!1)))}},{key:"stopListening",value:function(e){e.scrollHeight<=e.clientHeight||("function"==typeof e.removeEventListener&&e.removeEventListener("wheel",this.onWheel,!1),"function"==typeof e.removeEventListener&&e.removeEventListener("touchstart",this.onTouchStart,!1),"function"==typeof e.removeEventListener&&e.removeEventListener("touchmove",this.onTouchMove,!1))}},{key:"render",value:function(){return o.default.createElement(u.default,{innerRef:this.getScrollTarget},this.props.children)}}]),t}(),g=function(e){function t(){return s(this,t),p(this,f(t).apply(this,arguments))}return d(t,o.Component),c(t,[{key:"render",value:function(){var e=this.props,t=e.isEnabled,n=i(e,["isEnabled"]);return t?o.default.createElement(v,n):this.props.children}}]),t}();t.default=g,m(g,"defaultProps",{isEnabled:!0})},grMF:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createFilter=void 0;var r=n("c+lM");function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var u=function(e){return e.replace(/^\s+|\s+$/g,"")},i=function(e){return"".concat(e.label," ").concat(e.value)};t.createFilter=function(e){return function(t,n){var a=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){o(e,t,n[t])})}return e}({ignoreCase:!0,ignoreAccents:!0,stringify:i,trim:!0,matchFrom:"any"},e),s=a.ignoreCase,l=a.ignoreAccents,c=a.stringify,p=a.trim,f=a.matchFrom,d=p?u(n):n,h=p?u(c(t)):c(t);return s&&(d=d.toLowerCase(),h=h.toLowerCase()),l&&(d=(0,r.stripDiacritics)(d),h=(0,r.stripDiacritics)(h)),"start"===f?h.substr(0,d.length)===d:h.indexOf(d)>-1}}},jMYa:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.defaultProps=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=b(n("Wwog")),u=n("Avrx"),i=b(n("3lEq")),a=n("grMF"),s=n("tJT6"),l=n("59S1"),c=n("b+PA"),p=n("oZmp"),f=n("5bE3"),d=n("WvHe"),h=n("KXCe");function b(e){return e&&e.__esModule?e:{default:e}}function m(e){return(m="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function v(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function g(){return(g=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function y(e){return function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function O(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){P(e,t,n[t])})}return e}function E(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function S(e){return(S=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function C(e,t){return(C=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function w(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function P(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var A={backspaceRemovesValue:!0,blurInputOnSelect:(0,c.isTouchCapable)(),captureMenuScroll:!(0,c.isTouchCapable)(),closeMenuOnSelect:!0,closeMenuOnScroll:!1,components:{},controlShouldRenderValue:!0,escapeClearsValue:!1,filterOption:(0,a.createFilter)(),formatGroupLabel:p.formatGroupLabel,getOptionLabel:p.getOptionLabel,getOptionValue:p.getOptionValue,isDisabled:!1,isLoading:!1,isMulti:!1,isRtl:!1,isSearchable:!0,isOptionDisabled:p.isOptionDisabled,loadingMessage:function(){return"Loading..."},maxMenuHeight:300,minMenuHeight:140,menuIsOpen:!1,menuPlacement:"bottom",menuPosition:"absolute",menuShouldBlockScroll:!1,menuShouldScrollIntoView:!(0,c.isMobileDevice)(),noOptionsMessage:function(){return"No options"},openMenuOnFocus:!1,openMenuOnClick:!0,options:[],pageSize:5,placeholder:"Select...",screenReaderStatus:function(e){var t=e.count;return"".concat(t," result").concat(1!==t?"s":""," available")},styles:{},tabIndex:"0",tabSelectsValue:!0};t.defaultProps=A;var j=1,D=function(e){function t(e){var n,r,u;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),r=this,u=S(t).call(this,e),n=!u||"object"!==m(u)&&"function"!=typeof u?w(r):u,P(w(w(n)),"state",{ariaLiveSelection:"",ariaLiveContext:"",focusedOption:null,focusedValue:null,inputIsHidden:!1,isFocused:!1,isComposing:!1,menuOptions:{render:[],focusable:[]},selectValue:[]}),P(w(w(n)),"blockOptionHover",!1),P(w(w(n)),"clearFocusValueOnUpdate",!1),P(w(w(n)),"commonProps",void 0),P(w(w(n)),"components",void 0),P(w(w(n)),"hasGroups",!1),P(w(w(n)),"initialTouchX",0),P(w(w(n)),"initialTouchY",0),P(w(w(n)),"inputIsHiddenAfterUpdate",void 0),P(w(w(n)),"instancePrefix",""),P(w(w(n)),"openAfterFocus",!1),P(w(w(n)),"scrollToFocusedOptionOnUpdate",!1),P(w(w(n)),"userIsDragging",void 0),P(w(w(n)),"controlRef",null),P(w(w(n)),"getControlRef",function(e){n.controlRef=e}),P(w(w(n)),"focusedOptionRef",null),P(w(w(n)),"getFocusedOptionRef",function(e){n.focusedOptionRef=e}),P(w(w(n)),"menuListRef",null),P(w(w(n)),"getMenuListRef",function(e){n.menuListRef=e}),P(w(w(n)),"inputRef",null),P(w(w(n)),"getInputRef",function(e){n.inputRef=e}),P(w(w(n)),"cacheComponents",function(e){n.components=(0,f.defaultComponents)({components:e})}),P(w(w(n)),"focus",n.focusInput),P(w(w(n)),"blur",n.blurInput),P(w(w(n)),"onChange",function(e,t){var r=n.props;(0,r.onChange)(e,O({},t,{name:r.name}))}),P(w(w(n)),"setValue",function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"set-value",r=arguments.length>2?arguments[2]:void 0,o=n.props,u=o.closeMenuOnSelect,i=o.isMulti;n.onInputChange("",{action:"set-value"}),u&&(n.inputIsHiddenAfterUpdate=!i,n.onMenuClose()),n.clearFocusValueOnUpdate=!0,n.onChange(e,{action:t,option:r})}),P(w(w(n)),"selectOption",function(e){var t=n.props,r=t.blurInputOnSelect;if(t.isMulti){var o=n.state.selectValue;if(n.isOptionSelected(e,o)){var u=n.getOptionValue(e);n.setValue(o.filter(function(e){return n.getOptionValue(e)!==u}),"deselect-option",e),n.announceAriaLiveSelection({event:"deselect-option",context:{value:n.getOptionLabel(e)}})}else n.setValue([].concat(y(o),[e]),"select-option",e),n.announceAriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e)}})}else n.setValue(e,"select-option"),n.announceAriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e)}});r&&n.blurInput()}),P(w(w(n)),"removeValue",function(e){var t=n.state.selectValue,r=n.getOptionValue(e);n.onChange(t.filter(function(e){return n.getOptionValue(e)!==r}),{action:"remove-value",removedValue:e}),n.announceAriaLiveSelection({event:"remove-value",context:{value:e?n.getOptionLabel(e):""}}),n.focusInput()}),P(w(w(n)),"clearValue",function(){var e=n.props.isMulti;n.onChange(e?[]:null,{action:"clear"})}),P(w(w(n)),"popValue",function(){var e=n.state.selectValue,t=e[e.length-1];n.announceAriaLiveSelection({event:"pop-value",context:{value:t?n.getOptionLabel(t):""}}),n.onChange(e.slice(0,e.length-1),{action:"pop-value",removedValue:t})}),P(w(w(n)),"getOptionLabel",function(e){return n.props.getOptionLabel(e)}),P(w(w(n)),"getOptionValue",function(e){return n.props.getOptionValue(e)}),P(w(w(n)),"getStyles",function(e,t){var r=d.defaultStyles[e](t);r.boxSizing="border-box";var o=n.props.styles[e];return o?o(r,t):r}),P(w(w(n)),"getElementId",function(e){return"".concat(n.instancePrefix,"-").concat(e)}),P(w(w(n)),"getActiveDescendentId",function(){var e=n.props.menuIsOpen,t=n.state,r=t.menuOptions,o=t.focusedOption;if(o&&e){var u=r.focusable.indexOf(o),i=r.render[u];return i&&i.key}}),P(w(w(n)),"announceAriaLiveSelection",function(e){var t=e.event,r=e.context;n.setState({ariaLiveSelection:(0,l.valueEventAriaMessage)(t,r)})}),P(w(w(n)),"announceAriaLiveContext",function(e){var t=e.event,r=e.context;n.setState({ariaLiveContext:(0,l.instructionsAriaMessage)(t,O({},r,{label:n.props["aria-label"]}))})}),P(w(w(n)),"onMenuMouseDown",function(e){0===e.button&&(e.stopPropagation(),e.preventDefault(),n.focusInput())}),P(w(w(n)),"onMenuMouseMove",function(e){n.blockOptionHover=!1}),P(w(w(n)),"onControlMouseDown",function(e){var t=n.props.openMenuOnClick;n.state.isFocused?n.props.menuIsOpen?"INPUT"!==e.currentTarget.tagName&&n.onMenuClose():t&&n.openMenu("first"):(t&&(n.openAfterFocus=!0),n.focusInput()),"INPUT"!==e.currentTarget.tagName&&e.preventDefault()}),P(w(w(n)),"onDropdownIndicatorMouseDown",function(e){if(!(e&&"mousedown"===e.type&&0!==e.button||n.props.isDisabled)){var t=n.props,r=t.isMulti,o=t.menuIsOpen;n.focusInput(),o?(n.inputIsHiddenAfterUpdate=!r,n.onMenuClose()):n.openMenu("first"),e.preventDefault(),e.stopPropagation()}}),P(w(w(n)),"onClearIndicatorMouseDown",function(e){e&&"mousedown"===e.type&&0!==e.button||(n.clearValue(),e.stopPropagation(),n.openAfterFocus=!1,setTimeout(function(){return n.focusInput()}))}),P(w(w(n)),"onScroll",function(e){"boolean"==typeof n.props.closeMenuOnScroll?e.target instanceof HTMLElement&&(0,c.isDocumentElement)(e.target)&&n.props.onMenuClose():"function"==typeof n.props.closeMenuOnScroll&&n.props.closeMenuOnScroll(e)&&n.props.onMenuClose()}),P(w(w(n)),"onCompositionStart",function(){n.setState({isComposing:!0})}),P(w(w(n)),"onCompositionEnd",function(){n.setState({isComposing:!1})}),P(w(w(n)),"onTouchStart",function(e){var t=e.touches.item(0);t&&(n.initialTouchX=t.clientX,n.initialTouchY=t.clientY,n.userIsDragging=!1)}),P(w(w(n)),"onTouchMove",function(e){var t=e.touches.item(0);if(t){var r=Math.abs(t.clientX-n.initialTouchX),o=Math.abs(t.clientY-n.initialTouchY);n.userIsDragging=r>5||o>5}}),P(w(w(n)),"onTouchEnd",function(e){n.userIsDragging||(n.controlRef&&!n.controlRef.contains(e.target)&&n.menuListRef&&!n.menuListRef.contains(e.target)&&n.blurInput(),n.initialTouchX=0,n.initialTouchY=0)}),P(w(w(n)),"onControlTouchEnd",function(e){n.userIsDragging||n.onControlMouseDown(e)}),P(w(w(n)),"onClearIndicatorTouchEnd",function(e){n.userIsDragging||n.onClearIndicatorMouseDown(e)}),P(w(w(n)),"onDropdownIndicatorTouchEnd",function(e){n.userIsDragging||n.onDropdownIndicatorMouseDown(e)}),P(w(w(n)),"handleInputChange",function(e){var t=e.currentTarget.value;n.inputIsHiddenAfterUpdate=!1,n.onInputChange(t,{action:"input-change"}),n.onMenuOpen()}),P(w(w(n)),"onInputFocus",function(e){var t=n.props,r=t.isSearchable,o=t.isMulti;n.props.onFocus&&n.props.onFocus(e),n.inputIsHiddenAfterUpdate=!1,n.announceAriaLiveContext({event:"input",context:{isSearchable:r,isMulti:o}}),n.setState({isFocused:!0}),(n.openAfterFocus||n.props.openMenuOnFocus)&&n.openMenu("first"),n.openAfterFocus=!1}),P(w(w(n)),"onInputBlur",function(e){n.menuListRef&&n.menuListRef.contains(document.activeElement)?n.inputRef.focus():(n.props.onBlur&&n.props.onBlur(e),n.onInputChange("",{action:"input-blur"}),n.onMenuClose(),n.setState({focusedValue:null,isFocused:!1}))}),P(w(w(n)),"onOptionHover",function(e){n.blockOptionHover||n.state.focusedOption===e||n.setState({focusedOption:e})}),P(w(w(n)),"shouldHideSelectedOptions",function(){var e=n.props,t=e.hideSelectedOptions,r=e.isMulti;return void 0===t?r:t}),P(w(w(n)),"onKeyDown",function(e){var t=n.props,r=t.isMulti,o=t.backspaceRemovesValue,u=t.escapeClearsValue,i=t.inputValue,a=t.isClearable,s=t.isDisabled,l=t.menuIsOpen,c=t.onKeyDown,p=t.tabSelectsValue,f=t.openMenuOnFocus,d=n.state,h=d.isComposing,b=d.focusedOption,m=d.focusedValue,v=d.selectValue;if(!(s||"function"==typeof c&&(c(e),e.defaultPrevented))){switch(n.blockOptionHover=!0,e.key){case"ArrowLeft":if(!r||i)return;n.focusValue("previous");break;case"ArrowRight":if(!r||i)return;n.focusValue("next");break;case"Delete":case"Backspace":if(i)return;if(m)n.removeValue(m);else{if(!o)return;r?n.popValue():a&&n.clearValue()}break;case"Tab":if(h)return;if(e.shiftKey||!l||!p||!b||f&&n.isOptionSelected(b,v))return;n.selectOption(b);break;case"Enter":if(l){if(!b)return;if(h)return;n.selectOption(b);break}return;case"Escape":l?(n.inputIsHiddenAfterUpdate=!1,n.onInputChange("",{action:"menu-close"}),n.onMenuClose()):a&&u&&n.clearValue();break;case" ":if(i)return;if(!l){n.openMenu("first");break}if(!b)return;n.selectOption(b);break;case"ArrowUp":l?n.focusOption("up"):n.openMenu("last");break;case"ArrowDown":l?n.focusOption("down"):n.openMenu("first");break;case"PageUp":if(!l)return;n.focusOption("pageup");break;case"PageDown":if(!l)return;n.focusOption("pagedown");break;case"Home":if(!l)return;n.focusOption("first");break;case"End":if(!l)return;n.focusOption("last");break;default:return}e.preventDefault()}});var a=e.value;n.cacheComponents=(0,o.default)(n.cacheComponents,i.default).bind(w(w(n))),n.cacheComponents(e.components),n.instancePrefix="react-select-"+(n.props.instanceId||++j);var s=(0,c.cleanValue)(a),p=n.buildMenuOptions(e,s);return n.state.menuOptions=p,n.state.selectValue=s,n}var n,a,p;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&C(e,t)}(t,r.Component),n=t,(a=[{key:"componentDidMount",value:function(){this.startListeningComposition(),this.startListeningToTouch(),this.props.closeMenuOnScroll&&document&&document.addEventListener&&document.addEventListener("scroll",this.onScroll,!0),this.props.autoFocus&&this.focusInput()}},{key:"componentWillReceiveProps",value:function(e){var t=this.props,n=t.options,r=t.value,o=t.inputValue;if(this.cacheComponents(e.components),e.value!==r||e.options!==n||e.inputValue!==o){var u=(0,c.cleanValue)(e.value),i=this.buildMenuOptions(e,u),a=this.getNextFocusedValue(u),s=this.getNextFocusedOption(i.focusable);this.setState({menuOptions:i,selectValue:u,focusedOption:s,focusedValue:a})}null!=this.inputIsHiddenAfterUpdate&&(this.setState({inputIsHidden:this.inputIsHiddenAfterUpdate}),delete this.inputIsHiddenAfterUpdate)}},{key:"componentDidUpdate",value:function(e){var t=this.props,n=t.isDisabled,r=t.menuIsOpen,o=this.state.isFocused;(o&&!n&&e.isDisabled||o&&r&&!e.menuIsOpen)&&this.focusInput(),this.menuListRef&&this.focusedOptionRef&&this.scrollToFocusedOptionOnUpdate&&(0,c.scrollIntoView)(this.menuListRef,this.focusedOptionRef),this.scrollToFocusedOptionOnUpdate=!1}},{key:"componentWillUnmount",value:function(){this.stopListeningComposition(),this.stopListeningToTouch(),document.removeEventListener("scroll",this.onScroll,!0)}},{key:"onMenuOpen",value:function(){this.props.onMenuOpen()}},{key:"onMenuClose",value:function(){var e=this.props,t=e.isSearchable,n=e.isMulti;this.announceAriaLiveContext({event:"input",context:{isSearchable:t,isMulti:n}}),this.onInputChange("",{action:"menu-close"}),this.props.onMenuClose()}},{key:"onInputChange",value:function(e,t){this.props.onInputChange(e,t)}},{key:"focusInput",value:function(){this.inputRef&&this.inputRef.focus()}},{key:"blurInput",value:function(){this.inputRef&&this.inputRef.blur()}},{key:"openMenu",value:function(e){var t=this.state,n=t.menuOptions,r=t.selectValue,o=t.isFocused,u=this.props.isMulti,i="first"===e?0:n.focusable.length-1;if(!u){var a=n.focusable.indexOf(r[0]);a>-1&&(i=a)}this.scrollToFocusedOptionOnUpdate=!(o&&this.menuListRef),this.inputIsHiddenAfterUpdate=!1,this.onMenuOpen(),this.setState({focusedValue:null,focusedOption:n.focusable[i]}),this.announceAriaLiveContext({event:"menu"})}},{key:"focusValue",value:function(e){var t=this.props,n=t.isMulti,r=t.isSearchable,o=this.state,u=o.selectValue,i=o.focusedValue;if(n){this.setState({focusedOption:null});var a=u.indexOf(i);i||(a=-1,this.announceAriaLiveContext({event:"value"}));var s=u.length-1,l=-1;if(u.length){switch(e){case"previous":l=0===a?0:-1===a?s:a-1;break;case"next":a>-1&&a<s&&(l=a+1)}-1===l&&this.announceAriaLiveContext({event:"input",context:{isSearchable:r,isMulti:n}}),this.setState({inputIsHidden:-1!==l,focusedValue:u[l]})}}}},{key:"focusOption",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"first",t=this.props.pageSize,n=this.state,r=n.focusedOption,o=n.menuOptions.focusable;if(o.length){var u=0,i=o.indexOf(r);r||(i=-1,this.announceAriaLiveContext({event:"menu"})),"up"===e?u=i>0?i-1:o.length-1:"down"===e?u=(i+1)%o.length:"pageup"===e?(u=i-t)<0&&(u=0):"pagedown"===e?(u=i+t)>o.length-1&&(u=o.length-1):"last"===e&&(u=o.length-1),this.scrollToFocusedOptionOnUpdate=!0,this.setState({focusedOption:o[u],focusedValue:null})}}},{key:"getTheme",value:function(){return this.props.theme?"function"==typeof this.props.theme?this.props.theme(h.defaultTheme):O({},h.defaultTheme,this.props.theme):h.defaultTheme}},{key:"getCommonProps",value:function(){var e=this.clearValue,t=this.getStyles,n=this.setValue,r=this.selectOption,o=this.props,u=o.classNamePrefix,i=o.isMulti,a=o.isRtl,s=o.options,l=this.state.selectValue,p=this.hasValue();return{cx:c.classNames.bind(null,u),clearValue:e,getStyles:t,getValue:function(){return l},hasValue:p,isMulti:i,isRtl:a,options:s,selectOption:r,setValue:n,selectProps:o,theme:this.getTheme()}}},{key:"getNextFocusedValue",value:function(e){if(this.clearFocusValueOnUpdate)return this.clearFocusValueOnUpdate=!1,null;var t=this.state,n=t.focusedValue,r=t.selectValue.indexOf(n);if(r>-1){if(e.indexOf(n)>-1)return n;if(r<e.length)return e[r]}return null}},{key:"getNextFocusedOption",value:function(e){var t=this.state.focusedOption;return t&&e.indexOf(t)>-1?t:e[0]}},{key:"hasValue",value:function(){return this.state.selectValue.length>0}},{key:"hasOptions",value:function(){return!!this.state.menuOptions.render.length}},{key:"countOptions",value:function(){return this.state.menuOptions.focusable.length}},{key:"isClearable",value:function(){var e=this.props,t=e.isClearable,n=e.isMulti;return void 0===t?n:t}},{key:"isOptionDisabled",value:function(e,t){return"function"==typeof this.props.isOptionDisabled&&this.props.isOptionDisabled(e,t)}},{key:"isOptionSelected",value:function(e,t){var n=this;if(t.indexOf(e)>-1)return!0;if("function"==typeof this.props.isOptionSelected)return this.props.isOptionSelected(e,t);var r=this.getOptionValue(e);return t.some(function(e){return n.getOptionValue(e)===r})}},{key:"filterOption",value:function(e,t){return!this.props.filterOption||this.props.filterOption(e,t)}},{key:"formatOptionLabel",value:function(e,t){if("function"==typeof this.props.formatOptionLabel){var n=this.props.inputValue,r=this.state.selectValue;return this.props.formatOptionLabel(e,{context:t,inputValue:n,selectValue:r})}return this.getOptionLabel(e)}},{key:"formatGroupLabel",value:function(e){return this.props.formatGroupLabel(e)}},{key:"startListeningComposition",value:function(){document&&document.addEventListener&&(document.addEventListener("compositionstart",this.onCompositionStart,!1),document.addEventListener("compositionend",this.onCompositionEnd,!1))}},{key:"stopListeningComposition",value:function(){document&&document.removeEventListener&&(document.removeEventListener("compositionstart",this.onCompositionStart),document.removeEventListener("compositionend",this.onCompositionEnd))}},{key:"startListeningToTouch",value:function(){document&&document.addEventListener&&(document.addEventListener("touchstart",this.onTouchStart,!1),document.addEventListener("touchmove",this.onTouchMove,!1),document.addEventListener("touchend",this.onTouchEnd,!1))}},{key:"stopListeningToTouch",value:function(){document&&document.removeEventListener&&(document.removeEventListener("touchstart",this.onTouchStart),document.removeEventListener("touchmove",this.onTouchMove),document.removeEventListener("touchend",this.onTouchEnd))}},{key:"buildMenuOptions",value:function(e,t){var n=this,r=e.inputValue,o=void 0===r?"":r,u=e.options,i=function(e,r){var u=n.isOptionDisabled(e,t),i=n.isOptionSelected(e,t),a=n.getOptionLabel(e),s=n.getOptionValue(e);if(!(n.shouldHideSelectedOptions()&&i||!n.filterOption({label:a,value:s,data:e},o))){var l=u?void 0:function(){return n.onOptionHover(e)},c=u?void 0:function(){return n.selectOption(e)},p="".concat(n.getElementId("option"),"-").concat(r);return{innerProps:{id:p,onClick:c,onMouseMove:l,onMouseOver:l,tabIndex:-1},data:e,isDisabled:u,isSelected:i,key:p,label:a,type:"option",value:s}}};return u.reduce(function(e,t,r){if(t.options){n.hasGroups||(n.hasGroups=!0);var o=t.options.map(function(t,n){var o=i(t,"".concat(r,"-").concat(n));return o&&!o.isDisabled&&e.focusable.push(t),o}).filter(Boolean);if(o.length){var u="".concat(n.getElementId("group"),"-").concat(r);e.render.push({type:"group",key:u,data:t,options:o})}}else{var a=i(t,"".concat(r));a&&(e.render.push(a),a.isDisabled||e.focusable.push(t))}return e},{render:[],focusable:[]})}},{key:"constructAriaLiveMessage",value:function(){var e=this.state,t=e.ariaLiveContext,n=e.selectValue,r=e.focusedValue,o=e.focusedOption,u=this.props,i=u.options,a=u.menuIsOpen,s=u.inputValue,c=u.screenReaderStatus,p=r?(0,l.valueFocusAriaMessage)({focusedValue:r,getOptionLabel:this.getOptionLabel,selectValue:n}):"",f=o&&a?(0,l.optionFocusAriaMessage)({focusedOption:o,getOptionLabel:this.getOptionLabel,options:i}):"",d=(0,l.resultsAriaMessage)({inputValue:s,screenReaderMessage:c({count:this.countOptions()})});return"".concat(p," ").concat(f," ").concat(d," ").concat(t)}},{key:"renderInput",value:function(){var e=this.props,t=e.isDisabled,n=e.isSearchable,o=e.inputId,u=e.inputValue,i=e.tabIndex,a=this.components.Input,l=this.state.inputIsHidden,p=o||this.getElementId("input");if(!n)return r.default.createElement(s.DummyInput,{id:p,innerRef:this.getInputRef,onBlur:this.onInputBlur,onChange:c.noop,onFocus:this.onInputFocus,readOnly:!0,disabled:t,tabIndex:i,value:""});var f={"aria-autocomplete":"list","aria-label":this.props["aria-label"],"aria-labelledby":this.props["aria-labelledby"]},d=this.commonProps,h=d.cx,b=d.theme,m=d.selectProps;return r.default.createElement(a,g({autoCapitalize:"none",autoComplete:"off",autoCorrect:"off",cx:h,getStyles:this.getStyles,id:p,innerRef:this.getInputRef,isDisabled:t,isHidden:l,onBlur:this.onInputBlur,onChange:this.handleInputChange,onFocus:this.onInputFocus,selectProps:m,spellCheck:"false",tabIndex:i,theme:b,type:"text",value:u},f))}},{key:"renderPlaceholderOrValue",value:function(){var e=this,t=this.components,n=t.MultiValue,o=t.MultiValueContainer,u=t.MultiValueLabel,i=t.MultiValueRemove,a=t.SingleValue,s=t.Placeholder,l=this.commonProps,c=this.props,p=c.controlShouldRenderValue,f=c.isDisabled,d=c.isMulti,h=c.inputValue,b=c.placeholder,m=this.state,v=m.selectValue,y=m.focusedValue,O=m.isFocused;if(!this.hasValue()||!p)return h?null:r.default.createElement(s,g({},l,{key:"placeholder",isDisabled:f,isFocused:O}),b);if(d)return v.map(function(t){var a=t===y;return r.default.createElement(n,g({},l,{components:{Container:o,Label:u,Remove:i},isFocused:a,isDisabled:f,key:e.getOptionValue(t),removeProps:{onClick:function(){return e.removeValue(t)},onTouchEnd:function(){return e.removeValue(t)},onMouseDown:function(e){e.preventDefault(),e.stopPropagation()}},data:t}),e.formatOptionLabel(t,"value"))});if(h)return null;var E=v[0];return r.default.createElement(a,g({},l,{data:E,isDisabled:f}),this.formatOptionLabel(E,"value"))}},{key:"renderClearIndicator",value:function(){var e=this.components.ClearIndicator,t=this.commonProps,n=this.props,o=n.isDisabled,u=n.isLoading,i=this.state.isFocused;if(!this.isClearable()||!e||o||!this.hasValue()||u)return null;var a={onMouseDown:this.onClearIndicatorMouseDown,onTouchEnd:this.onClearIndicatorTouchEnd,"aria-hidden":"true"};return r.default.createElement(e,g({},t,{innerProps:a,isFocused:i}))}},{key:"renderLoadingIndicator",value:function(){var e=this.components.LoadingIndicator,t=this.commonProps,n=this.props,o=n.isDisabled,u=n.isLoading,i=this.state.isFocused;if(!e||!u)return null;return r.default.createElement(e,g({},t,{innerProps:{"aria-hidden":"true"},isDisabled:o,isFocused:i}))}},{key:"renderIndicatorSeparator",value:function(){var e=this.components,t=e.DropdownIndicator,n=e.IndicatorSeparator;if(!t||!n)return null;var o=this.commonProps,u=this.props.isDisabled,i=this.state.isFocused;return r.default.createElement(n,g({},o,{isDisabled:u,isFocused:i}))}},{key:"renderDropdownIndicator",value:function(){var e=this.components.DropdownIndicator;if(!e)return null;var t=this.commonProps,n=this.props.isDisabled,o=this.state.isFocused,u={onMouseDown:this.onDropdownIndicatorMouseDown,onTouchEnd:this.onDropdownIndicatorTouchEnd,"aria-hidden":"true"};return r.default.createElement(e,g({},t,{innerProps:u,isDisabled:n,isFocused:o}))}},{key:"renderMenu",value:function(){var e=this,t=this.components,n=t.Group,o=t.GroupHeading,i=t.Menu,a=t.MenuList,l=t.MenuPortal,c=t.LoadingMessage,p=t.NoOptionsMessage,f=t.Option,d=this.commonProps,h=this.state,b=h.focusedOption,m=h.menuOptions,y=this.props,O=y.captureMenuScroll,E=y.inputValue,S=y.isLoading,C=y.loadingMessage,w=y.minMenuHeight,P=y.maxMenuHeight,A=y.menuIsOpen,j=y.menuPlacement,D=y.menuPosition,M=y.menuPortalTarget,k=y.menuShouldBlockScroll,F=y.menuShouldScrollIntoView,x=y.noOptionsMessage,_=y.onMenuScrollToTop,I=y.onMenuScrollToBottom;if(!A)return null;var T,L=function(t){var n=b===t.data;return t.innerRef=n?e.getFocusedOptionRef:void 0,r.default.createElement(f,g({},d,t,{isFocused:n}),e.formatOptionLabel(t.data,"menu"))};if(this.hasOptions())T=m.render.map(function(t){if("group"===t.type){t.type;var u=v(t,["type"]),i="".concat(t.key,"-heading");return r.default.createElement(n,g({},d,u,{Heading:o,headingProps:{id:i},label:e.formatGroupLabel(t.data)}),t.options.map(function(e){return L(e)}))}if("option"===t.type)return L(t)});else if(S){var V=C({inputValue:E});if(null===V)return null;T=r.default.createElement(c,d,V)}else{var R=x({inputValue:E});if(null===R)return null;T=r.default.createElement(p,d,R)}var B={minMenuHeight:w,maxMenuHeight:P,menuPlacement:j,menuPosition:D,menuShouldScrollIntoView:F},H=r.default.createElement(u.MenuPlacer,g({},d,B),function(t){var n=t.ref,o=t.placerProps,u=o.placement,l=o.maxHeight;return r.default.createElement(i,g({},d,B,{innerRef:n,innerProps:{onMouseDown:e.onMenuMouseDown,onMouseMove:e.onMenuMouseMove},isLoading:S,placement:u}),r.default.createElement(s.ScrollCaptor,{isEnabled:O,onTopArrive:_,onBottomArrive:I},r.default.createElement(s.ScrollBlock,{isEnabled:k},r.default.createElement(a,g({},d,{innerRef:e.getMenuListRef,isLoading:S,maxHeight:l}),T))))});return M||"fixed"===D?r.default.createElement(l,g({},d,{appendTo:M,controlElement:this.controlRef,menuPlacement:j,menuPosition:D}),H):H}},{key:"renderFormField",value:function(){var e=this,t=this.props,n=t.delimiter,o=t.isDisabled,u=t.isMulti,i=t.name,a=this.state.selectValue;if(i&&!o){if(u){if(n){var s=a.map(function(t){return e.getOptionValue(t)}).join(n);return r.default.createElement("input",{name:i,type:"hidden",value:s})}var l=a.length>0?a.map(function(t,n){return r.default.createElement("input",{key:"i-".concat(n),name:i,type:"hidden",value:e.getOptionValue(t)})}):r.default.createElement("input",{name:i,type:"hidden"});return r.default.createElement("div",null,l)}var c=a[0]?this.getOptionValue(a[0]):"";return r.default.createElement("input",{name:i,type:"hidden",value:c})}}},{key:"renderLiveRegion",value:function(){return this.state.isFocused?r.default.createElement(s.A11yText,{"aria-live":"assertive"},r.default.createElement("p",{id:"aria-selection-event"},"Â ",this.state.ariaLiveSelection),r.default.createElement("p",{id:"aria-context"},"Â ",this.constructAriaLiveMessage())):null}},{key:"render",value:function(){var e=this.components,t=e.Control,n=e.IndicatorsContainer,o=e.SelectContainer,u=e.ValueContainer,i=this.props,a=i.className,s=i.id,l=i.isDisabled,c=i.menuIsOpen,p=this.state.isFocused,f=this.commonProps=this.getCommonProps();return r.default.createElement(o,g({},f,{className:a,innerProps:{id:s,onKeyDown:this.onKeyDown},isDisabled:l,isFocused:p}),this.renderLiveRegion(),r.default.createElement(t,g({},f,{innerRef:this.getControlRef,innerProps:{onMouseDown:this.onControlMouseDown,onTouchEnd:this.onControlTouchEnd},isDisabled:l,isFocused:p,menuIsOpen:c}),r.default.createElement(u,g({},f,{isDisabled:l}),this.renderPlaceholderOrValue(),this.renderInput()),r.default.createElement(n,g({},f,{isDisabled:l}),this.renderClearIndicator(),this.renderLoadingIndicator(),this.renderIndicatorSeparator(),this.renderDropdownIndicator())),this.renderMenu(),this.renderFormField())}}])&&E(n.prototype,a),p&&E(n,p),t}();t.default=D,P(D,"defaultProps",A)},lQ6M:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.MultiValueRemove=t.MultiValueLabel=t.MultiValueContainer=t.MultiValueGeneric=t.multiValueRemoveCSS=t.multiValueLabelCSS=t.multiValueCSS=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd")),o=n("PAeb"),u=n("+URl");function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){s(e,t,n[t])})}return e}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function c(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function p(e,t,n){return t&&c(e.prototype,t),n&&c(e,n),e}function f(e,t){return!t||"object"!==i(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function d(e){return(d=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function h(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&b(e,t)}function b(e,t){return(b=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}t.multiValueCSS=function(e){var t=e.theme,n=t.spacing,r=t.borderRadius;return{backgroundColor:t.colors.neutral10,borderRadius:r/2,display:"flex",margin:n.baseUnit/2,minWidth:0}};t.multiValueLabelCSS=function(e){var t=e.theme,n=t.borderRadius,r=t.colors,o=e.cropWithEllipsis;return{borderRadius:n/2,color:r.neutral80,fontSize:"85%",overflow:"hidden",padding:3,paddingLeft:6,textOverflow:o?"ellipsis":null,whiteSpace:"nowrap"}};t.multiValueRemoveCSS=function(e){var t=e.theme,n=t.spacing,r=t.borderRadius,o=t.colors;return{alignItems:"center",borderRadius:r/2,backgroundColor:e.isFocused&&o.dangerLight,display:"flex",paddingLeft:n.baseUnit,paddingRight:n.baseUnit,":hover":{backgroundColor:o.dangerLight,color:o.danger}}};var m=function(e){var t=e.children,n=e.innerProps;return r.default.createElement("div",n,t)};t.MultiValueGeneric=m;var v=m;t.MultiValueContainer=v;var g=m;t.MultiValueLabel=g;var y=function(e){function t(){return l(this,t),f(this,d(t).apply(this,arguments))}return h(t,r.Component),p(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.innerProps;return r.default.createElement("div",n,t||r.default.createElement(u.CrossIcon,{size:14}))}}]),t}();t.MultiValueRemove=y;var O=function(e){function t(){return l(this,t),f(this,d(t).apply(this,arguments))}return h(t,r.Component),p(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.className,u=e.components,i=e.cx,s=e.data,l=e.getStyles,c=e.innerProps,p=e.isDisabled,f=e.removeProps,d=e.selectProps,h=u.Container,b=u.Label,m=u.Remove,v=a({className:i((0,o.css)(l("multiValue",this.props)),{"multi-value":!0,"multi-value--is-disabled":p},n)},c),g={className:i((0,o.css)(l("multiValueLabel",this.props)),{"multi-value__label":!0},n)},y=a({className:i((0,o.css)(l("multiValueRemove",this.props)),{"multi-value__remove":!0},n)},f);return r.default.createElement(h,{data:s,innerProps:v,selectProps:d},r.default.createElement(b,{data:s,innerProps:g,selectProps:d},t),r.default.createElement(m,{data:s,innerProps:y,selectProps:d}))}}]),t}();s(O,"defaultProps",{cropWithEllipsis:!0});var E=O;t.default=E},n929:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.GroupHeading=t.groupHeadingCSS=t.groupCSS=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){a(e,t,n[t])})}return e}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function l(){return(l=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.groupCSS=function(e){var t=e.theme.spacing;return{paddingBottom:2*t.baseUnit,paddingTop:2*t.baseUnit}};t.groupHeadingCSS=function(e){var t=e.theme.spacing;return{color:"#999",cursor:"default",display:"block",fontSize:"75%",fontWeight:"500",marginBottom:"0.25em",paddingLeft:3*t.baseUnit,paddingRight:3*t.baseUnit,textTransform:"uppercase"}};t.GroupHeading=function(e){var t=e.className,n=e.cx,r=e.getStyles,a=e.theme,c=(e.selectProps,s(e,["className","cx","getStyles","theme","selectProps"]));return o.default.createElement("div",l({className:n((0,u.css)(r("groupHeading",i({theme:a},c))),{"group-heading":!0},t)},c))};var c=function(e){var t=e.children,n=e.className,r=e.cx,i=e.getStyles,a=e.Heading,s=e.headingProps,c=e.label,p=e.theme,f=e.selectProps;return o.default.createElement("div",{className:r((0,u.css)(i("group",e)),{group:!0},n)},o.default.createElement(a,l({},s,{selectProps:f,theme:p,getStyles:i,cx:r}),c),o.default.createElement("div",null,t))};t.default=c},oUUL:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.defaultProps=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n("cDcd"));function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function u(){return(u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},u=Object.keys(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(r=0;r<u.length;r++)n=u[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function l(e,t){return(l=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function c(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function p(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var f={defaultInputValue:"",defaultMenuIsOpen:!1,defaultValue:null};t.defaultProps=f;var d=function(e){var t,n;return n=t=function(t){function n(){var e,t,r,u;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n);for(var i=arguments.length,a=new Array(i),l=0;l<i;l++)a[l]=arguments[l];return r=this,u=(e=s(n)).call.apply(e,[this].concat(a)),t=!u||"object"!==o(u)&&"function"!=typeof u?c(r):u,p(c(c(t)),"select",void 0),p(c(c(t)),"state",{inputValue:void 0!==t.props.inputValue?t.props.inputValue:t.props.defaultInputValue,menuIsOpen:void 0!==t.props.menuIsOpen?t.props.menuIsOpen:t.props.defaultMenuIsOpen,value:void 0!==t.props.value?t.props.value:t.props.defaultValue}),p(c(c(t)),"onChange",function(e,n){t.callProp("onChange",e,n),t.setState({value:e})}),p(c(c(t)),"onInputChange",function(e,n){var r=t.callProp("onInputChange",e,n);t.setState({inputValue:void 0!==r?r:e})}),p(c(c(t)),"onMenuOpen",function(){t.callProp("onMenuOpen"),t.setState({menuIsOpen:!0})}),p(c(c(t)),"onMenuClose",function(){t.callProp("onMenuClose"),t.setState({menuIsOpen:!1})}),t}var f,d,h;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&l(e,t)}(n,r.Component),f=n,(d=[{key:"focus",value:function(){this.select.focus()}},{key:"blur",value:function(){this.select.blur()}},{key:"getProp",value:function(e){return void 0!==this.props[e]?this.props[e]:this.state[e]}},{key:"callProp",value:function(e){if("function"==typeof this.props[e]){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return(t=this.props)[e].apply(t,r)}}},{key:"render",value:function(){var t=this,n=this.props,o=(n.defaultInputValue,n.defaultMenuIsOpen,n.defaultValue,i(n,["defaultInputValue","defaultMenuIsOpen","defaultValue"]));return r.default.createElement(e,u({},o,{ref:function(e){t.select=e},inputValue:this.getProp("inputValue"),menuIsOpen:this.getProp("menuIsOpen"),onChange:this.onChange,onInputChange:this.onInputChange,onMenuClose:this.onMenuClose,onMenuOpen:this.onMenuOpen,value:this.getProp("value")}))}}])&&a(f.prototype,d),h&&a(f,h),n}(),p(t,"defaultProps",f),n};t.default=d},oZmp:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isOptionDisabled=t.getOptionValue=t.getOptionLabel=t.formatGroupLabel=void 0;t.formatGroupLabel=function(e){return e.label};t.getOptionLabel=function(e){return e.label};t.getOptionValue=function(e){return e.value};t.isOptionDisabled=function(e){return!!e.isDisabled}},oj4i:function(e,t,n){"use strict";var r=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e(n)),t[n]}},o={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};var u=function(e){for(var t,n=e.length,r=n^n,o=0;n>=4;)t=1540483477*(65535&(t=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(t>>>16)&65535)<<16),r=1540483477*(65535&r)+((1540483477*(r>>>16)&65535)<<16)^(t=1540483477*(65535&(t^=t>>>24))+((1540483477*(t>>>16)&65535)<<16)),n-=4,++o;switch(n){case 3:r^=(255&e.charCodeAt(o+2))<<16;case 2:r^=(255&e.charCodeAt(o+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(o)))+((1540483477*(r>>>16)&65535)<<16)}return r=1540483477*(65535&(r^=r>>>13))+((1540483477*(r>>>16)&65535)<<16),((r^=r>>>15)>>>0).toString(36)};var i=function(e){function t(e,t,r){var o=t.trim().split(h);t=o;var u=o.length,i=e.length;switch(i){case 0:case 1:var a=0;for(e=0===i?"":e[0]+" ";a<u;++a)t[a]=n(e,t[a],r).trim();break;default:var s=a=0;for(t=[];a<u;++a)for(var l=0;l<i;++l)t[s++]=n(e[l]+" ",o[a],r).trim()}return t}function n(e,t,n){var r=t.charCodeAt(0);switch(33>r&&(r=(t=t.trim()).charCodeAt(0)),r){case 38:return t.replace(b,"$1"+e.trim());case 58:return e.trim()+t.replace(b,"$1"+e.trim());default:if(0<1*n&&0<t.indexOf("\f"))return t.replace(b,(58===e.charCodeAt(0)?"":"$1")+e.trim())}return e+t}function r(e,t,n,u){var i=e+";",a=2*t+3*n+4*u;if(944===a){e=i.indexOf(":",9)+1;var s=i.substring(e,i.length-1).trim();return s=i.substring(0,e).trim()+s+";",1===M||2===M&&o(s,1)?"-webkit-"+s+s:s}if(0===M||2===M&&!o(i,1))return i;switch(a){case 1015:return 97===i.charCodeAt(10)?"-webkit-"+i+i:i;case 951:return 116===i.charCodeAt(3)?"-webkit-"+i+i:i;case 963:return 110===i.charCodeAt(5)?"-webkit-"+i+i:i;case 1009:if(100!==i.charCodeAt(4))break;case 969:case 942:return"-webkit-"+i+i;case 978:return"-webkit-"+i+"-moz-"+i+i;case 1019:case 983:return"-webkit-"+i+"-moz-"+i+"-ms-"+i+i;case 883:if(45===i.charCodeAt(8))return"-webkit-"+i+i;if(0<i.indexOf("image-set(",11))return i.replace(P,"$1-webkit-$2")+i;break;case 932:if(45===i.charCodeAt(4))switch(i.charCodeAt(5)){case 103:return"-webkit-box-"+i.replace("-grow","")+"-webkit-"+i+"-ms-"+i.replace("grow","positive")+i;case 115:return"-webkit-"+i+"-ms-"+i.replace("shrink","negative")+i;case 98:return"-webkit-"+i+"-ms-"+i.replace("basis","preferred-size")+i}return"-webkit-"+i+"-ms-"+i+i;case 964:return"-webkit-"+i+"-ms-flex-"+i+i;case 1023:if(99!==i.charCodeAt(8))break;return"-webkit-box-pack"+(s=i.substring(i.indexOf(":",15)).replace("flex-","").replace("space-between","justify"))+"-webkit-"+i+"-ms-flex-pack"+s+i;case 1005:return f.test(i)?i.replace(p,":-webkit-")+i.replace(p,":-moz-")+i:i;case 1e3:switch(t=(s=i.substring(13).trim()).indexOf("-")+1,s.charCodeAt(0)+s.charCodeAt(t)){case 226:s=i.replace(y,"tb");break;case 232:s=i.replace(y,"tb-rl");break;case 220:s=i.replace(y,"lr");break;default:return i}return"-webkit-"+i+"-ms-"+s+i;case 1017:if(-1===i.indexOf("sticky",9))break;case 975:switch(t=(i=e).length-10,a=(s=(33===i.charCodeAt(t)?i.substring(0,t):i).substring(e.indexOf(":",7)+1).trim()).charCodeAt(0)+(0|s.charCodeAt(7))){case 203:if(111>s.charCodeAt(8))break;case 115:i=i.replace(s,"-webkit-"+s)+";"+i;break;case 207:case 102:i=i.replace(s,"-webkit-"+(102<a?"inline-":"")+"box")+";"+i.replace(s,"-webkit-"+s)+";"+i.replace(s,"-ms-"+s+"box")+";"+i}return i+";";case 938:if(45===i.charCodeAt(5))switch(i.charCodeAt(6)){case 105:return s=i.replace("-items",""),"-webkit-"+i+"-webkit-box-"+s+"-ms-flex-"+s+i;case 115:return"-webkit-"+i+"-ms-flex-item-"+i.replace(S,"")+i;default:return"-webkit-"+i+"-ms-flex-line-pack"+i.replace("align-content","").replace(S,"")+i}break;case 973:case 989:if(45!==i.charCodeAt(3)||122===i.charCodeAt(4))break;case 931:case 953:if(!0===w.test(e))return 115===(s=e.substring(e.indexOf(":")+1)).charCodeAt(0)?r(e.replace("stretch","fill-available"),t,n,u).replace(":fill-available",":stretch"):i.replace(s,"-webkit-"+s)+i.replace(s,"-moz-"+s.replace("fill-",""))+i;break;case 962:if(i="-webkit-"+i+(102===i.charCodeAt(5)?"-ms-"+i:"")+i,211===n+u&&105===i.charCodeAt(13)&&0<i.indexOf("transform",10))return i.substring(0,i.indexOf(";",27)+1).replace(d,"$1-webkit-$2")+i}return i}function o(e,t){var n=e.indexOf(1===t?":":"{"),r=e.substring(0,3!==t?n:10);return n=e.substring(n+1,e.length-1),_(2!==t?r:r.replace(C,"$1"),n,t)}function u(e,t){var n=r(t,t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2));return n!==t+";"?n.replace(E," or ($1)").substring(4):"("+t+")"}function i(e,t,n,r,o,u,i,a,l,c){for(var p,f=0,d=t;f<x;++f)switch(p=F[f].call(s,e,d,n,r,o,u,i,a,l,c)){case void 0:case!1:case!0:case null:break;default:d=p}if(d!==t)return d}function a(e){return void 0!==(e=e.prefix)&&(_=null,e?"function"!=typeof e?M=1:(M=2,_=e):M=0),a}function s(e,n){var a=e;if(33>a.charCodeAt(0)&&(a=a.trim()),a=[a],0<x){var s=i(-1,n,a,a,j,A,0,0,0,0);void 0!==s&&"string"==typeof s&&(n=s)}var p=function e(n,a,s,p,f){for(var d,h,b,y,E,S=0,C=0,w=0,P=0,F=0,_=0,T=b=d=0,L=0,V=0,R=0,B=0,H=s.length,N=H-1,U="",W="",z="",G="";L<H;){if(h=s.charCodeAt(L),L===N&&0!==C+P+w+S&&(0!==C&&(h=47===C?10:47),P=w=S=0,H++,N++),0===C+P+w+S){if(L===N&&(0<V&&(U=U.replace(c,"")),0<U.trim().length)){switch(h){case 32:case 9:case 59:case 13:case 10:break;default:U+=s.charAt(L)}h=59}switch(h){case 123:for(d=(U=U.trim()).charCodeAt(0),b=1,B=++L;L<H;){switch(h=s.charCodeAt(L)){case 123:b++;break;case 125:b--;break;case 47:switch(h=s.charCodeAt(L+1)){case 42:case 47:e:{for(T=L+1;T<N;++T)switch(s.charCodeAt(T)){case 47:if(42===h&&42===s.charCodeAt(T-1)&&L+2!==T){L=T+1;break e}break;case 10:if(47===h){L=T+1;break e}}L=T}}break;case 91:h++;case 40:h++;case 34:case 39:for(;L++<N&&s.charCodeAt(L)!==h;);}if(0===b)break;L++}switch(b=s.substring(B,L),0===d&&(d=(U=U.replace(l,"").trim()).charCodeAt(0)),d){case 64:switch(0<V&&(U=U.replace(c,"")),h=U.charCodeAt(1)){case 100:case 109:case 115:case 45:V=a;break;default:V=k}if(B=(b=e(a,V,b,h,f+1)).length,0<x&&(E=i(3,b,V=t(k,U,R),a,j,A,B,h,f,p),U=V.join(""),void 0!==E&&0===(B=(b=E.trim()).length)&&(h=0,b="")),0<B)switch(h){case 115:U=U.replace(O,u);case 100:case 109:case 45:b=U+"{"+b+"}";break;case 107:b=(U=U.replace(m,"$1 $2"))+"{"+b+"}",b=1===M||2===M&&o("@"+b,3)?"@-webkit-"+b+"@"+b:"@"+b;break;default:b=U+b,112===p&&(W+=b,b="")}else b="";break;default:b=e(a,t(a,U,R),b,p,f+1)}z+=b,b=R=V=T=d=0,U="",h=s.charCodeAt(++L);break;case 125:case 59:if(1<(B=(U=(0<V?U.replace(c,""):U).trim()).length))switch(0===T&&(d=U.charCodeAt(0),45===d||96<d&&123>d)&&(B=(U=U.replace(" ",":")).length),0<x&&void 0!==(E=i(1,U,a,n,j,A,W.length,p,f,p))&&0===(B=(U=E.trim()).length)&&(U="\0\0"),d=U.charCodeAt(0),h=U.charCodeAt(1),d){case 0:break;case 64:if(105===h||99===h){G+=U+s.charAt(L);break}default:58!==U.charCodeAt(B-1)&&(W+=r(U,d,h,U.charCodeAt(2)))}R=V=T=d=0,U="",h=s.charCodeAt(++L)}}switch(h){case 13:case 10:47===C?C=0:0===1+d&&107!==p&&0<U.length&&(V=1,U+="\0"),0<x*I&&i(0,U,a,n,j,A,W.length,p,f,p),A=1,j++;break;case 59:case 125:if(0===C+P+w+S){A++;break}default:switch(A++,y=s.charAt(L),h){case 9:case 32:if(0===P+S+C)switch(F){case 44:case 58:case 9:case 32:y="";break;default:32!==h&&(y=" ")}break;case 0:y="\\0";break;case 12:y="\\f";break;case 11:y="\\v";break;case 38:0===P+C+S&&(V=R=1,y="\f"+y);break;case 108:if(0===P+C+S+D&&0<T)switch(L-T){case 2:112===F&&58===s.charCodeAt(L-3)&&(D=F);case 8:111===_&&(D=_)}break;case 58:0===P+C+S&&(T=L);break;case 44:0===C+w+P+S&&(V=1,y+="\r");break;case 34:case 39:0===C&&(P=P===h?0:0===P?h:P);break;case 91:0===P+C+w&&S++;break;case 93:0===P+C+w&&S--;break;case 41:0===P+C+S&&w--;break;case 40:if(0===P+C+S){if(0===d)switch(2*F+3*_){case 533:break;default:d=1}w++}break;case 64:0===C+w+P+S+T+b&&(b=1);break;case 42:case 47:if(!(0<P+S+w))switch(C){case 0:switch(2*h+3*s.charCodeAt(L+1)){case 235:C=47;break;case 220:B=L,C=42}break;case 42:47===h&&42===F&&B+2!==L&&(33===s.charCodeAt(B+2)&&(W+=s.substring(B,L+1)),y="",C=0)}}0===C&&(U+=y)}_=F,F=h,L++}if(0<(B=W.length)){if(V=a,0<x&&void 0!==(E=i(2,W,V,n,j,A,B,p,f,p))&&0===(W=E).length)return G+W+z;if(W=V.join(",")+"{"+W+"}",0!=M*D){switch(2!==M||o(W,2)||(D=0),D){case 111:W=W.replace(g,":-moz-$1")+W;break;case 112:W=W.replace(v,"::-webkit-input-$1")+W.replace(v,"::-moz-$1")+W.replace(v,":-ms-input-$1")+W}D=0}}return G+W+z}(k,a,n,0,0);return 0<x&&void 0!==(s=i(-2,p,a,a,j,A,p.length,0,0,0))&&(p=s),D=0,A=j=1,p}var l=/^\0+/g,c=/[\0\r\f]/g,p=/: */g,f=/zoo|gra/,d=/([,: ])(transform)/g,h=/,\r+?/g,b=/([\t\r\n ])*\f?&/g,m=/@(k\w+)\s*(\S*)\s*/,v=/::(place)/g,g=/:(read-only)/g,y=/[svh]\w+-[tblr]{2}/,O=/\(\s*(.*)\s*\)/g,E=/([\s\S]*?);/g,S=/-self|flex-/g,C=/[^]*?(:[rp][el]a[\w-]+)[^]*/,w=/stretch|:\s*\w+\-(?:conte|avail)/,P=/([^-])(image-set\()/,A=1,j=1,D=0,M=1,k=[],F=[],x=0,_=null,I=0;return s.use=function e(t){switch(t){case void 0:case null:x=F.length=0;break;default:switch(t.constructor){case Array:for(var n=0,r=t.length;n<r;++n)e(t[n]);break;case Function:F[x++]=t;break;case Boolean:I=0|!!t}}return e},s.set=a,void 0!==e&&a(e),s},a=n("TAZq"),s=n.n(a),l=/[A-Z]|^ms/g,c=r(function(e){return e.replace(l,"-$&").toLowerCase()}),p=function(e,t){return null==t||"boolean"==typeof t?"":1===o[e]||45===e.charCodeAt(1)||isNaN(t)||0===t?t:t+"px"},f=function e(t){for(var n=t.length,r=0,o="";r<n;r++){var u=t[r];if(null!=u){var i=void 0;switch(typeof u){case"boolean":break;case"function":0,i=e([u()]);break;case"object":if(Array.isArray(u))i=e(u);else for(var a in i="",u)u[a]&&a&&(i&&(i+=" "),i+=a);break;default:i=u}i&&(o&&(o+=" "),o+=i)}}return o},d="undefined"!=typeof document;function h(e){var t=document.createElement("style");return t.setAttribute("data-emotion",e.key||""),void 0!==e.nonce&&t.setAttribute("nonce",e.nonce),t.appendChild(document.createTextNode("")),(void 0!==e.container?e.container:document.head).appendChild(t),t}var b=function(){function e(e){this.isSpeedy=!0,this.tags=[],this.ctr=0,this.opts=e}var t=e.prototype;return t.inject=function(){if(this.injected)throw new Error("already injected!");this.tags[0]=h(this.opts),this.injected=!0},t.speedy=function(e){if(0!==this.ctr)throw new Error("cannot change speedy now");this.isSpeedy=!!e},t.insert=function(e,t){if(this.isSpeedy){var n=function(e){if(e.sheet)return e.sheet;for(var t=0;t<document.styleSheets.length;t++)if(document.styleSheets[t].ownerNode===e)return document.styleSheets[t]}(this.tags[this.tags.length-1]);try{n.insertRule(e,n.cssRules.length)}catch(e){0}}else{var r=h(this.opts);this.tags.push(r),r.appendChild(document.createTextNode(e+(t||"")))}this.ctr++,this.ctr%65e3==0&&this.tags.push(h(this.opts))},t.flush=function(){this.tags.forEach(function(e){return e.parentNode.removeChild(e)}),this.tags=[],this.ctr=0,this.injected=!1},e}();t.a=function(e,t){if(void 0!==e.__SECRET_EMOTION__)return e.__SECRET_EMOTION__;void 0===t&&(t={});var n,r,o=t.key||"css",a=s()(function(e){n+=e,d&&h.insert(e,v)});void 0!==t.prefix&&(r={prefix:t.prefix});var l={registered:{},inserted:{},nonce:t.nonce,key:o},h=new b(t);d&&h.inject();var m=new i(r);m.use(t.stylisPlugins)(a);var v="";function g(e,t){if(null==e)return"";switch(typeof e){case"boolean":return"";case"function":if(void 0!==e.__emotion_styles){var n=e.toString();return n}return g.call(this,void 0===this?e():e(this.mergedProps,this.context),t);case"object":return function(e){if(E.has(e))return E.get(e);var t="";return Array.isArray(e)?e.forEach(function(e){t+=g.call(this,e,!1)},this):Object.keys(e).forEach(function(n){"object"!=typeof e[n]?void 0!==l.registered[e[n]]?t+=n+"{"+l.registered[e[n]]+"}":t+=c(n)+":"+p(n,e[n])+";":Array.isArray(e[n])&&"string"==typeof e[n][0]&&void 0===l.registered[e[n][0]]?e[n].forEach(function(e){t+=c(n)+":"+p(n,e)+";"}):t+=n+"{"+g.call(this,e[n],!1)+"}"},this),E.set(e,t),t}.call(this,e);default:var r=l.registered[e];return!1===t&&void 0!==r?r:e}}var y,O,E=new WeakMap,S=/label:\s*([^\s;\n{]+)\s*;/g,C=function(e){var t=!0,n="",r="";null==e||void 0===e.raw?(t=!1,n+=g.call(this,e,!1)):n+=e[0];for(var o=arguments.length,i=new Array(o>1?o-1:0),a=1;a<o;a++)i[a-1]=arguments[a];return i.forEach(function(r,o){n+=g.call(this,r,46===n.charCodeAt(n.length-1)),!0===t&&void 0!==e[o+1]&&(n+=e[o+1])},this),O=n,n=n.replace(S,function(e,t){return r+="-"+t,""}),y=function(e,t){return u(e+t)+t}(n,r),n};function w(e,t){void 0===l.inserted[y]&&(n="",m(e,t),l.inserted[y]=n)}var P=function(){var e=C.apply(this,arguments),t=o+"-"+y;return void 0===l.registered[t]&&(l.registered[t]=O),w("."+t,e),t};function A(e,t){var n="";return t.split(" ").forEach(function(t){void 0!==l.registered[t]?e.push(t):n+=t+" "}),n}function j(e,t){var n=[],r=A(n,e);return n.length<2?e:r+P(n,t)}function D(e){l.inserted[e]=!0}if(d){var M=document.querySelectorAll("[data-emotion-"+o+"]");Array.prototype.forEach.call(M,function(e){h.tags[0].parentNode.insertBefore(e,h.tags[0]),e.getAttribute("data-emotion-"+o).split(" ").forEach(D)})}var k={flush:function(){d&&(h.flush(),h.inject()),l.inserted={},l.registered={}},hydrate:function(e){e.forEach(D)},cx:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return j(f(t))},merge:j,getRegisteredStyles:A,injectGlobal:function(){w("",C.apply(this,arguments))},keyframes:function(){var e=C.apply(this,arguments),t="animation-"+y;return w("","@keyframes "+t+"{"+e+"}"),t},css:P,sheet:h,caches:l};return e.__SECRET_EMOTION__=k,k}},rc6b:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.css=void 0;var r,o=(r=n("cDcd"))&&r.__esModule?r:{default:r},u=n("PAeb");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}t.css=function(e){var t=e.isDisabled,n=e.isFocused,r=e.theme,o=r.colors,u=r.borderRadius,i=r.spacing;return{alignItems:"center",backgroundColor:t?o.neutral5:o.neutral0,borderColor:t?o.neutral10:n?o.primary:o.neutral20,borderRadius:u,borderStyle:"solid",borderWidth:1,boxShadow:n?"0 0 0 1px ".concat(o.primary):null,cursor:"default",display:"flex",flexWrap:"wrap",justifyContent:"space-between",minHeight:i.controlHeight,outline:"0 !important",position:"relative",transition:"all 100ms","&:hover":{borderColor:n?o.primary:o.neutral30}}};var a=function(e){var t=e.children,n=e.cx,r=e.getStyles,a=e.className,s=e.isDisabled,l=e.isFocused,c=e.innerRef,p=e.innerProps,f=e.menuIsOpen;return o.default.createElement("div",i({ref:c,className:n((0,u.css)(r("control",e)),{control:!0,"control--is-disabled":s,"control--is-focused":l,"control--menu-is-open":f},a)},p),t)};t.default=a},tJT6:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"A11yText",{enumerable:!0,get:function(){return r.default}}),Object.defineProperty(t,"DummyInput",{enumerable:!0,get:function(){return o.default}}),Object.defineProperty(t,"NodeResolver",{enumerable:!0,get:function(){return u.default}}),Object.defineProperty(t,"ScrollBlock",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(t,"ScrollCaptor",{enumerable:!0,get:function(){return a.default}});var r=s(n("/+00")),o=s(n("H6Zs")),u=s(n("N3bB")),i=s(n("QcsS")),a=s(n("d6Hc"));function s(e){return e&&e.__esModule?e:{default:e}}},xEkU:function(e,t,n){(function(t){for(var r=n("bQgK"),o="undefined"==typeof window?t:window,u=["moz","webkit"],i="AnimationFrame",a=o["request"+i],s=o["cancel"+i]||o["cancelRequest"+i],l=0;!a&&l<u.length;l++)a=o[u[l]+"Request"+i],s=o[u[l]+"Cancel"+i]||o[u[l]+"CancelRequest"+i];if(!a||!s){var c=0,p=0,f=[];a=function(e){if(0===f.length){var t=r(),n=Math.max(0,1e3/60-(t-c));c=n+t,setTimeout(function(){var e=f.slice(0);f.length=0;for(var t=0;t<e.length;t++)if(!e[t].cancelled)try{e[t].callback(c)}catch(e){setTimeout(function(){throw e},0)}},Math.round(n))}return f.push({handle:++p,callback:e,cancelled:!1}),p},s=function(e){for(var t=0;t<f.length;t++)f[t].handle===e&&(f[t].cancelled=!0)}}e.exports=function(e){return a.call(o,e)},e.exports.cancel=function(){s.apply(o,arguments)},e.exports.polyfill=function(e){e||(e=o),e.requestAnimationFrame=a,e.cancelAnimationFrame=s}}).call(this,n("yLpj"))},yLpj:function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n}}]);
|
dist/core/admin-notices-api.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
this.itsec=this.itsec||{},this.itsec.core=this.itsec.core||{},this.itsec.core["admin-notices-api"]=function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s="M/oR")}({"1ZqX":function(t,e){!function(){t.exports=this.wp.data}()},"7W2i":function(t,e,n){var r=n("SksO");t.exports=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&r(t,e)}},"92Nh":function(t,e){t.exports=function(t,e,n){if(!e.has(t))throw new TypeError("attempted to set private field on non-instance");var r=e.get(t);if(!r.writable)throw new TypeError("attempted to set read only private field");return r.value=n,n}},Bnag:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},EbDI:function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},Ijbi:function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}},J4zp:function(t,e,n){var r=n("wTVA"),o=n("m0LI"),i=n("wkBT");t.exports=function(t,e){return r(t)||o(t,e)||i()}},"M/oR":function(t,e,n){"use strict";n.r(e);var r={};n.r(r),n.d(r,"receiveNotices",function(){return U}),n.d(r,"startNoticeAction",function(){return C}),n.d(r,"finishNoticeAction",function(){return F}),n.d(r,"failedNoticeAction",function(){return L}),n.d(r,"receiveMutedHighlights",function(){return G}),n.d(r,"startUpdateMutedHighlight",function(){return J}),n.d(r,"finishUpdateMutedHighlight",function(){return V}),n.d(r,"failedUpdateMutedHighlight",function(){return q}),n.d(r,"doNoticeAction",function(){return W}),n.d(r,"updateMutedHighlight",function(){return Z}),n.d(r,"RECEIVE_NOTICES",function(){return B}),n.d(r,"START_NOTICE_ACTION",function(){return Y}),n.d(r,"FINISH_NOTICE_ACTION",function(){return X}),n.d(r,"FAILED_NOTICE_ACTION",function(){return z}),n.d(r,"RECEIVE_MUTED_HIGHLIGHTS",function(){return K}),n.d(r,"START_UPDATE_MUTED_HIGHLIGHT",function(){return Q}),n.d(r,"FINISH_UPDATE_MUTED_HIGHLIGHT",function(){return $}),n.d(r,"FAILED_UPDATE_MUTED_HIGHLIGHT",function(){return tt});var o={};n.r(o),n.d(o,"isResolving",function(){return et}),n.d(o,"isResolved",function(){return nt}),n.d(o,"getNotices",function(){return rt}),n.d(o,"areNoticesLoaded",function(){return ot}),n.d(o,"isDoingAction",function(){return it}),n.d(o,"getInProgressActions",function(){return ct}),n.d(o,"getMutedHighlights",function(){return st}),n.d(o,"getMutedHighlightUpdatesInFlight",function(){return at});var i={};n.r(i),n.d(i,"getNotices",function(){return pt}),n.d(i,"getMutedHighlights",function(){return dt});var u=n("1ZqX"),c=n("RIqP"),s=n.n(c),a=n("MVZn"),f=n.n(a),l=n("YLtl"),p=n("ywyh"),d=n.n(p),h=(n("J4zp"),n("lwsE")),g=n.n(h),y=n("W8MJ"),m=n.n(y),b=n("lSNA"),v=n.n(b),I=(n("92Nh"),n("tmk3"),new WeakMap,new WeakMap,n("a1gu")),T=n.n(I),x=n("Nsbk"),w=n.n(x),E=n("7W2i"),_=n.n(E),O=n("PJYZ"),A=n.n(O),S=n("oShl"),H=n.n(S),N=n("l3Sj"),j=function(t){function e(t){var n,r;g()(this,e);for(var o=arguments.length,i=new Array(o>1?o-1:0),u=1;u<o;u++)i[u-1]=arguments[u];for(var c in r=T()(this,(n=w()(e)).call.apply(n,[this,t.message||Object(N.__)("An unknown error occurred.","better-wp-security")].concat(i))),Error.captureStackTrace&&Error.captureStackTrace(A()(A()(r)),e),r.__response=t,t)t.hasOwnProperty(c)&&Object.defineProperty(A()(A()(r)),c,{value:t[c],configurable:!0,enumerable:!0,writable:!0});return r}return _()(e,t),m()(e,[{key:"toString",value:function(){return this.__response.toString()}},{key:"getResponse",value:function(){return this.__response}}]),e}(H()(Error));function P(t){if(t instanceof Error)throw t;throw new j(t)}function R(t){return{type:"API_FETCH",request:t}}var M={API_FETCH:function(t){var e=t.request;return d()(e).catch(P)},SELECT:function(t){var e,n=t.selectorName,r=t.args;return(e=Object(u.select)("ithemes-security/admin-notices"))[n].apply(e,s()(r))},CREATE_NOTICE:function(t){var e=t.status,n=t.content,r=t.options;r.autoDismiss&&(r.id=r.id||Object(l.uniqueId)("itsec-auto-dismiss-"),setTimeout(function(){return Object(u.dispatch)("core/notices").removeNotice(r.id,r.context)},r.autoDismiss)),Object(u.dispatch)("core/notices").createNotice(e,n,r)}},D=regeneratorRuntime.mark(W),k=regeneratorRuntime.mark(Z);function U(t){return{type:B,notices:t}}function C(t,e){return{type:Y,noticeId:t,actionId:e}}function F(t,e,n){return{type:X,noticeId:t,actionId:e,response:n}}function L(t,e,n){return{type:z,noticeId:t,actionId:e,error:n}}function G(t){return{type:K,mutedHighlights:t}}function J(t,e){return{type:Q,slug:t,mute:e}}function V(t,e){return{type:$,slug:t,mute:e}}function q(t,e,n){return{type:tt,slug:t,mute:e,error:n}}function W(t,e){var n,r,o=arguments;return regeneratorRuntime.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:return n=o.length>2&&void 0!==o[2]?o[2]:{},i.next=3,C(t,e);case 3:return i.prev=3,i.next=6,R({path:"/ithemes-security/v1/admin-notices/".concat(t,"/").concat(e),method:"POST",data:n});case 6:r=i.sent,i.next=14;break;case 9:return i.prev=9,i.t0=i.catch(3),i.next=13,L(t,e,i.t0);case 13:return i.abrupt("return",i.t0);case 14:return i.next=16,F(t,e,r);case 16:return i.abrupt("return",r);case 17:case"end":return i.stop()}},D,this,[[3,9]])}function Z(t,e){var n;return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,J(t,e);case 2:return r.prev=2,r.next=5,R({path:"/ithemes-security/v1/admin-notices/settings",method:"PUT",data:{muted_highlights:v()({},t,e)}});case 5:n=r.sent,r.next=13;break;case 8:return r.prev=8,r.t0=r.catch(2),r.next=12,q(t,e,r.t0);case 12:return r.abrupt("return",r.t0);case 13:return r.next=15,V(t,e);case 15:return r.abrupt("return",n);case 16:case"end":return r.stop()}},k,this,[[2,8]])}var B="RECEIVE_NOTICES",Y="START_NOTICE_ACTION",X="FINISH_NOTICE_ACTION",z="FAILED_NOTICE_ACTION",K="RECEIVE_MUTED_HIGHLIGHTS",Q="START_UPDATE_MUTED_HIGHLIGHT",$="FINISH_UPDATE_MUTED_HIGHLIGHT",tt="FAILED_UPDATE_MUTED_HIGHLIGHT";function et(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r<e;r++)n[r-1]=arguments[r];return Object(u.select)("core/data").isResolving("ithemes-security/admin-notices",t,n)}function nt(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r<e;r++)n[r-1]=arguments[r];return Object(u.select)("core/data").hasFinishedResolution("ithemes-security/admin-notices",t,n)}function rt(t){return t.notices}function ot(){return nt("getNotices")}function it(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return!!t.doingActions[e]&&(""===n||t.doingActions[e].includes(n))}var ut=[];function ct(t,e){return t.doingActions[e]||ut}function st(t){return t.mutedHighlights}function at(t){return t.mutedHighlightUpdatesInFlight}var ft={notices:[],doingActions:{},mutedHighlights:{},mutedHighlightUpdatesInFlight:{}};var lt=regeneratorRuntime.mark(dt),pt={fulfill:regeneratorRuntime.mark(function t(){var e;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,R({path:"/ithemes-security/v1/admin-notices"});case 2:return e=t.sent,t.next=5,U(e);case 5:case"end":return t.stop()}},t,this)}),shouldInvalidate:function(t){return t.type===X||t.type===$}};function dt(){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,R({path:"/ithemes-security/v1/admin-notices/settings"});case 2:return t=e.sent,e.next=5,G(Object(l.isEmpty)(t.muted_highlights)?{}:t.muted_highlights);case 5:case"end":return e.stop()}},lt,this)}Object(u.registerStore)("ithemes-security/admin-notices",{controls:M,actions:r,selectors:o,resolvers:i,reducer:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ft,e=arguments.length>1?arguments[1]:void 0;switch(e.type){case B:return f()({},t,{notices:s()(e.notices)});case Y:return f()({},t,{doingActions:f()({},t.doingActions,v()({},e.noticeId,s()(t.doingActions[e.noticeId]||[]).concat([e.actionId])))});case X:case z:return f()({},t,{doingActions:f()({},t.doingActions,v()({},e.noticeId,(t.doingActions[e.noticeId]||[]).filter(function(t){return t!==e.actionId})))});case K:return f()({},t,{mutedHighlights:e.mutedHighlights});case Q:return f()({},t,{mutedHighlightUpdatesInFlight:f()({},t.mutedHighlightUpdatesInFlight,v()({},e.slug,{mute:e.mute}))});case $:return f()({},t,{mutedHighlightUpdatesInFlight:Object(l.omit)(t.mutedHighlightUpdatesInFlight,e.slug),mutedHighlights:f()({},t.mutedHighlights,v()({},e.slug,e.mute))});case tt:return f()({},t,{mutedHighlightUpdatesInFlight:Object(l.omit)(t.mutedHighlightUpdatesInFlight,e.slug)});default:return t}}});n.p=window.itsecWebpackPublicPath},MVZn:function(t,e,n){var r=n("lSNA");t.exports=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},o=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(n).filter(function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),o.forEach(function(e){r(t,e,n[e])})}return t}},Nsbk:function(t,e){function n(e){return t.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(e)}t.exports=n},PJYZ:function(t,e){t.exports=function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}},RIqP:function(t,e,n){var r=n("Ijbi"),o=n("EbDI"),i=n("Bnag");t.exports=function(t){return r(t)||o(t)||i()}},SksO:function(t,e){function n(e,r){return t.exports=n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(e,r)}t.exports=n},W8MJ:function(t,e){function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}t.exports=function(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),t}},YLtl:function(t,e){!function(){t.exports=this.lodash}()},a1gu:function(t,e,n){var r=n("cDf5"),o=n("PJYZ");t.exports=function(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?o(t):e}},cDf5:function(t,e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(e){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=r=function(t){return n(t)}:t.exports=r=function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},r(e)}t.exports=r},l3Sj:function(t,e){!function(){t.exports=this.wp.i18n}()},lSNA:function(t,e){t.exports=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}},lwsE:function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},m0LI:function(t,e){t.exports=function(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var u,c=t[Symbol.iterator]();!(r=(u=c.next()).done)&&(n.push(u.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{r||null==c.return||c.return()}finally{if(o)throw i}}return n}},oShl:function(t,e,n){var r=n("Nsbk"),o=n("SksO"),i=n("xfeJ"),u=n("sXyB");function c(e){var n="function"==typeof Map?new Map:void 0;return t.exports=c=function(t){if(null===t||!i(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(t))return n.get(t);n.set(t,e)}function e(){return u(t,arguments,r(this).constructor)}return e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),o(e,t)},c(e)}t.exports=c},sXyB:function(t,e,n){var r=n("SksO");function o(e,n,i){return!function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(t){return!1}}()?t.exports=o=function(t,e,n){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return n&&r(i,n.prototype),i}:t.exports=o=Reflect.construct,o.apply(null,arguments)}t.exports=o},tmk3:function(t,e){t.exports=function(t,e){if(!e.has(t))throw new TypeError("attempted to get private field on non-instance");return e.get(t).value}},wTVA:function(t,e){t.exports=function(t){if(Array.isArray(t))return t}},wkBT:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},xfeJ:function(t,e){t.exports=function(t){return-1!==Function.toString.call(t).indexOf("[native code]")}},ywyh:function(t,e){!function(){t.exports=this.wp.apiFetch}()}});
|
1 |
+
this.itsec=this.itsec||{},this.itsec.core=this.itsec.core||{},this.itsec.core["admin-notices-api"]=function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s="M/oR")}({"1ZqX":function(t,e){!function(){t.exports=this.wp.data}()},"7W2i":function(t,e,n){var r=n("SksO");t.exports=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&r(t,e)}},"92Nh":function(t,e){t.exports=function(t,e,n){if(!e.has(t))throw new TypeError("attempted to set private field on non-instance");var r=e.get(t);if(!r.writable)throw new TypeError("attempted to set read only private field");return r.value=n,n}},Bnag:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},EbDI:function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},Ijbi:function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}},J4zp:function(t,e,n){var r=n("wTVA"),o=n("m0LI"),i=n("wkBT");t.exports=function(t,e){return r(t)||o(t,e)||i()}},"M/oR":function(t,e,n){"use strict";n.r(e);var r={};n.r(r),n.d(r,"receiveNotices",function(){return E}),n.d(r,"startNoticeAction",function(){return w}),n.d(r,"finishNoticeAction",function(){return O}),n.d(r,"failedNoticeAction",function(){return T}),n.d(r,"receiveMutedHighlights",function(){return _}),n.d(r,"startUpdateMutedHighlight",function(){return x}),n.d(r,"finishUpdateMutedHighlight",function(){return A}),n.d(r,"failedUpdateMutedHighlight",function(){return S}),n.d(r,"doNoticeAction",function(){return H}),n.d(r,"updateMutedHighlight",function(){return j}),n.d(r,"RECEIVE_NOTICES",function(){return P}),n.d(r,"START_NOTICE_ACTION",function(){return N}),n.d(r,"FINISH_NOTICE_ACTION",function(){return k}),n.d(r,"FAILED_NOTICE_ACTION",function(){return M}),n.d(r,"RECEIVE_MUTED_HIGHLIGHTS",function(){return R}),n.d(r,"START_UPDATE_MUTED_HIGHLIGHT",function(){return C}),n.d(r,"FINISH_UPDATE_MUTED_HIGHLIGHT",function(){return D}),n.d(r,"FAILED_UPDATE_MUTED_HIGHLIGHT",function(){return U});var o={};n.r(o),n.d(o,"isResolving",function(){return F}),n.d(o,"isResolved",function(){return L}),n.d(o,"getNotices",function(){return G}),n.d(o,"areNoticesLoaded",function(){return J}),n.d(o,"isDoingAction",function(){return q}),n.d(o,"getInProgressActions",function(){return W}),n.d(o,"getMutedHighlights",function(){return Z}),n.d(o,"getMutedHighlightUpdatesInFlight",function(){return B});var i={};n.r(i),n.d(i,"getNotices",function(){return z}),n.d(i,"getMutedHighlights",function(){return K});var u=n("1ZqX"),c=n("RIqP"),s=n.n(c),a=n("MVZn"),f=n.n(a),l=n("YLtl"),d=n("ywyh"),p=n.n(d),h=n("Td6G");function g(t){return{type:"API_FETCH",request:t}}var y={API_FETCH:function(t){var e=t.request;return p()(e).catch(h.e)},SELECT:function(t){var e,n=t.selectorName,r=t.args;return(e=Object(u.select)("ithemes-security/admin-notices"))[n].apply(e,s()(r))},CREATE_NOTICE:function(t){var e=t.status,n=t.content,r=t.options;r.autoDismiss&&(r.id=r.id||Object(l.uniqueId)("itsec-auto-dismiss-"),setTimeout(function(){return Object(u.dispatch)("core/notices").removeNotice(r.id,r.context)},r.autoDismiss)),Object(u.dispatch)("core/notices").createNotice(e,n,r)}},v=n("lSNA"),m=n.n(v),b=regeneratorRuntime.mark(H),I=regeneratorRuntime.mark(j);function E(t){return{type:P,notices:t}}function w(t,e){return{type:N,noticeId:t,actionId:e}}function O(t,e,n){return{type:k,noticeId:t,actionId:e,response:n}}function T(t,e,n){return{type:M,noticeId:t,actionId:e,error:n}}function _(t){return{type:R,mutedHighlights:t}}function x(t,e){return{type:C,slug:t,mute:e}}function A(t,e){return{type:D,slug:t,mute:e}}function S(t,e,n){return{type:U,slug:t,mute:e,error:n}}function H(t,e){var n,r,o=arguments;return regeneratorRuntime.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:return n=o.length>2&&void 0!==o[2]?o[2]:{},i.next=3,w(t,e);case 3:return i.prev=3,i.next=6,g({path:"/ithemes-security/v1/admin-notices/".concat(t,"/").concat(e),method:"POST",data:n});case 6:r=i.sent,i.next=14;break;case 9:return i.prev=9,i.t0=i.catch(3),i.next=13,T(t,e,i.t0);case 13:return i.abrupt("return",i.t0);case 14:return i.next=16,O(t,e,r);case 16:return i.abrupt("return",r);case 17:case"end":return i.stop()}},b,this,[[3,9]])}function j(t,e){var n;return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,x(t,e);case 2:return r.prev=2,r.next=5,g({path:"/ithemes-security/v1/admin-notices/settings",method:"PUT",data:{muted_highlights:m()({},t,e)}});case 5:n=r.sent,r.next=13;break;case 8:return r.prev=8,r.t0=r.catch(2),r.next=12,S(t,e,r.t0);case 12:return r.abrupt("return",r.t0);case 13:return r.next=15,A(t,e);case 15:return r.abrupt("return",n);case 16:case"end":return r.stop()}},I,this,[[2,8]])}var P="RECEIVE_NOTICES",N="START_NOTICE_ACTION",k="FINISH_NOTICE_ACTION",M="FAILED_NOTICE_ACTION",R="RECEIVE_MUTED_HIGHLIGHTS",C="START_UPDATE_MUTED_HIGHLIGHT",D="FINISH_UPDATE_MUTED_HIGHLIGHT",U="FAILED_UPDATE_MUTED_HIGHLIGHT";function F(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r<e;r++)n[r-1]=arguments[r];return Object(u.select)("core/data").isResolving("ithemes-security/admin-notices",t,n)}function L(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r<e;r++)n[r-1]=arguments[r];return Object(u.select)("core/data").hasFinishedResolution("ithemes-security/admin-notices",t,n)}function G(t){return t.notices}function J(){return L("getNotices")}function q(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return!!t.doingActions[e]&&(""===n||t.doingActions[e].includes(n))}var V=[];function W(t,e){return t.doingActions[e]||V}function Z(t){return t.mutedHighlights}function B(t){return t.mutedHighlightUpdatesInFlight}var Y={notices:[],doingActions:{},mutedHighlights:{},mutedHighlightUpdatesInFlight:{}};var X=regeneratorRuntime.mark(K),z={fulfill:regeneratorRuntime.mark(function t(){var e;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,g({path:"/ithemes-security/v1/admin-notices"});case 2:return e=t.sent,t.next=5,E(e);case 5:case"end":return t.stop()}},t,this)}),shouldInvalidate:function(t){return t.type===k||t.type===D}};function K(){var t;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,g({path:"/ithemes-security/v1/admin-notices/settings"});case 2:return t=e.sent,e.next=5,_(Object(l.isEmpty)(t.muted_highlights)?{}:t.muted_highlights);case 5:case"end":return e.stop()}},X,this)}Object(u.registerStore)("ithemes-security/admin-notices",{controls:y,actions:r,selectors:o,resolvers:i,reducer:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Y,e=arguments.length>1?arguments[1]:void 0;switch(e.type){case P:return f()({},t,{notices:s()(e.notices)});case N:return f()({},t,{doingActions:f()({},t.doingActions,m()({},e.noticeId,s()(t.doingActions[e.noticeId]||[]).concat([e.actionId])))});case k:case M:return f()({},t,{doingActions:f()({},t.doingActions,m()({},e.noticeId,(t.doingActions[e.noticeId]||[]).filter(function(t){return t!==e.actionId})))});case R:return f()({},t,{mutedHighlights:e.mutedHighlights});case C:return f()({},t,{mutedHighlightUpdatesInFlight:f()({},t.mutedHighlightUpdatesInFlight,m()({},e.slug,{mute:e.mute}))});case D:return f()({},t,{mutedHighlightUpdatesInFlight:Object(l.omit)(t.mutedHighlightUpdatesInFlight,e.slug),mutedHighlights:f()({},t.mutedHighlights,m()({},e.slug,e.mute))});case U:return f()({},t,{mutedHighlightUpdatesInFlight:Object(l.omit)(t.mutedHighlightUpdatesInFlight,e.slug)});default:return t}}});n.p=window.itsecWebpackPublicPath},MVZn:function(t,e,n){var r=n("lSNA");t.exports=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},o=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(n).filter(function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),o.forEach(function(e){r(t,e,n[e])})}return t}},Nsbk:function(t,e){function n(e){return t.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(e)}t.exports=n},PJYZ:function(t,e){t.exports=function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}},RIqP:function(t,e,n){var r=n("Ijbi"),o=n("EbDI"),i=n("Bnag");t.exports=function(t){return r(t)||o(t)||i()}},SksO:function(t,e){function n(e,r){return t.exports=n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(e,r)}t.exports=n},Td6G:function(t,e,n){"use strict";n("J4zp");var r=n("YLtl"),o=n("RIqP"),i=n.n(o),u=n("lwsE"),c=n.n(u),s=n("W8MJ"),a=n.n(s),f=n("lSNA"),l=n.n(f),d=n("92Nh"),p=n.n(d),h=n("tmk3"),g=n.n(h),y=function(){function t(){var e=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;c()(this,t),v.set(this,{writable:!0,value:{}}),m.set(this,{writable:!0,value:{}}),l()(this,"getErrorCodes",function(){return Object.keys(g()(e,v))}),l()(this,"getErrorCode",function(){return e.getErrorCodes()[0]}),l()(this,"getErrorMessages",function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;if(t)return g()(e,v)[t];var n=[];for(var r in g()(e,v))g()(e,v).hasOwnProperty(r)&&n.concat(g()(e,v)[r]);return n}),l()(this,"getErrorMessage",function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return t=t||e.getErrorCode(),e.getErrorMessages(t)[0]}),l()(this,"getErrorData",function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return t=t||e.getErrorCode(),g()(e,m)[t]}),l()(this,"getAllErrorMessages",function(){var t=[];for(var n in g()(e,v))g()(e,v).hasOwnProperty(n)&&t.push.apply(t,i()(g()(e,v)[n]));return t}),n&&(r&&(g()(this,v)[n]=[r]),o&&(g()(this,m)[n]=o))}return a()(t,null,[{key:"fromPHPObject",value:function(e){var n=new t;return p()(n,v,e.errors),p()(n,m,e.error_data),n}},{key:"fromApiError",value:function(e){var n=new t;if(g()(n,v)[e.code]=[e.message],g()(n,m)[e.code]=e.data,e.additional_errors){var r=!0,o=!1,i=void 0;try{for(var u,c=e.additional_errors[Symbol.iterator]();!(r=(u=c.next()).done);r=!0){var s=u.value;g()(n,v)[s.code]=[s.message],g()(n,m)[s.code]=s.data}}catch(t){o=!0,i=t}finally{try{r||null==c.return||c.return()}finally{if(o)throw i}}}return n}}]),t}(),v=new WeakMap,m=new WeakMap,b=n("a1gu"),I=n.n(b),E=n("Nsbk"),w=n.n(E),O=n("7W2i"),T=n.n(O),_=n("PJYZ"),x=n.n(_),A=n("oShl"),S=n.n(A),H=n("l3Sj"),j=function(t){function e(t){var n,r;c()(this,e);for(var o=arguments.length,i=new Array(o>1?o-1:0),u=1;u<o;u++)i[u-1]=arguments[u];for(var s in r=I()(this,(n=w()(e)).call.apply(n,[this,t.message||Object(H.__)("An unknown error occurred.","better-wp-security")].concat(i))),Error.captureStackTrace&&Error.captureStackTrace(x()(x()(r)),e),r.__response=t,t)t.hasOwnProperty(s)&&Object.defineProperty(x()(x()(r)),s,{value:t[s],configurable:!0,enumerable:!0,writable:!0});return r}return T()(e,t),a()(e,[{key:"toString",value:function(){return this.__response.toString()}},{key:"getResponse",value:function(){return this.__response}}]),e}(S()(Error));function P(t){if(!Object(r.isPlainObject)(t))return!1;var e=Object.keys(t);return 2===e.length&&(e.includes("errors")&&e.includes("error_data"))}function N(t){return P(t)?y.fromPHPObject(t):function(t){if(!Object(r.isPlainObject)(t))return!1;var e=Object.keys(t);return(3===e.length||4===e.length)&&!(4===e.length&&!e.includes("additional_errors"))&&e.includes("code")&&e.includes("message")&&e.includes("data")}(t)?y.fromApiError(t):new y}function k(t,e){var n=[[],[]],r=!0,o=!1,i=void 0;try{for(var u,c=t[Symbol.iterator]();!(r=(u=c.next()).done);r=!0){var s=u.value;n[e(s)?0:1].push(s)}}catch(t){o=!0,i=t}finally{try{r||null==c.return||c.return()}finally{if(o)throw i}}return n}function M(t){if(t instanceof Error)throw t;throw new j(t)}n.d(e,"d",function(){return P}),n.d(e,"b",function(){return N}),n.d(e,"a",function(){return k}),n.d(e,"e",function(){return M}),n.d(e,"c",function(){return R});function R(t,e){if(t&&t.links){var n=!0,r=!1,o=void 0;try{for(var i,u=t.links[Symbol.iterator]();!(n=(i=u.next()).done);n=!0){var c=i.value;if(c.rel===e)return c}}catch(t){r=!0,o=t}finally{try{n||null==u.return||u.return()}finally{if(r)throw o}}}}},W8MJ:function(t,e){function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}t.exports=function(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),t}},YLtl:function(t,e){!function(){t.exports=this.lodash}()},a1gu:function(t,e,n){var r=n("cDf5"),o=n("PJYZ");t.exports=function(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?o(t):e}},cDf5:function(t,e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(e){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=r=function(t){return n(t)}:t.exports=r=function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},r(e)}t.exports=r},l3Sj:function(t,e){!function(){t.exports=this.wp.i18n}()},lSNA:function(t,e){t.exports=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}},lwsE:function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},m0LI:function(t,e){t.exports=function(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var u,c=t[Symbol.iterator]();!(r=(u=c.next()).done)&&(n.push(u.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{r||null==c.return||c.return()}finally{if(o)throw i}}return n}},oShl:function(t,e,n){var r=n("Nsbk"),o=n("SksO"),i=n("xfeJ"),u=n("sXyB");function c(e){var n="function"==typeof Map?new Map:void 0;return t.exports=c=function(t){if(null===t||!i(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(t))return n.get(t);n.set(t,e)}function e(){return u(t,arguments,r(this).constructor)}return e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),o(e,t)},c(e)}t.exports=c},sXyB:function(t,e,n){var r=n("SksO");function o(e,n,i){return!function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(t){return!1}}()?t.exports=o=function(t,e,n){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return n&&r(i,n.prototype),i}:t.exports=o=Reflect.construct,o.apply(null,arguments)}t.exports=o},tmk3:function(t,e){t.exports=function(t,e){if(!e.has(t))throw new TypeError("attempted to get private field on non-instance");return e.get(t).value}},wTVA:function(t,e){t.exports=function(t){if(Array.isArray(t))return t}},wkBT:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},xfeJ:function(t,e){t.exports=function(t){return-1!==Function.toString.call(t).indexOf("[native code]")}},ywyh:function(t,e){!function(){t.exports=this.wp.apiFetch}()}});
|
dist/core/admin-notices-dashboard-admin-bar.min.css
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Â
|
5 |
Â
.itsec-admin-notice-list{margin:0}.itsec-admin-notice-list-item-container{display:grid;grid-template:auto / -webkit-min-content 1fr;grid-template:auto / min-content 1fr;grid-gap:1em;margin-bottom:2em}.itsec-admin-notice-list-item-container:last-child{margin-bottom:0}
|
6 |
Â
|
7 |
-
@keyframes itsec-animation-fade-in-constant{from{opacity:0}to{opacity:1}}.itsec-admin-bar-admin-notices__content.components-popover::after{border-color:#E5EAEE !important}.itsec-admin-notice-panel{padding:1em;background:#E5EAEE;width:420px;box-sizing:border-box}.itsec-admin-notice-panel .itsec-admin-notice-panel__header{border-bottom:1px solid #7ABEED;margin-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__header h3{color:#0081E3;text-align:center}.itsec-admin-notice-panel .itsec-admin-notice-panel__header p{text-align:center;font-style:oblique}.is-mobile .itsec-admin-notice-panel{width:100%;overflow-x:auto;height:100%}.is-mobile .itsec-admin-notice-panel header h3{display:none}.is-mobile .itsec-admin-notice-panel header p{margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-
|
8 |
Â
|
9 |
-
.itsec-admin-bar__admin-notices{margin-left:auto}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button{color:#0081E3}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button:hover{color:#4ab1ff}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button svg{margin-right:.5em}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger .components-button{position:relative}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger .components-button::before{content:'';background:#d8514f;height:5px;width:5px;border-radius:5px;vertical-align:middle;border:1px solid #f1f1f1;z-index:1;position:absolute;left:4px;top:3px;opacity:0;transition:opacity 1000ms ease-in-out}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger--has-notices .components-button::before{opacity:1}.itsec-admin-bar-admin-notices__content .components-popover__content{box-shadow:rgba(0,0,0,0.19) 0 4px 5px}@media screen and (max-width: 600px){.itsec-admin-bar .itsec-admin-bar__admin-notices{margin-left:0}}
|
10 |
Â
|
4 |
Â
|
5 |
Â
.itsec-admin-notice-list{margin:0}.itsec-admin-notice-list-item-container{display:grid;grid-template:auto / -webkit-min-content 1fr;grid-template:auto / min-content 1fr;grid-gap:1em;margin-bottom:2em}.itsec-admin-notice-list-item-container:last-child{margin-bottom:0}
|
6 |
Â
|
7 |
+
@keyframes itsec-animation-fade-in-constant{from{opacity:0}to{opacity:1}}.itsec-admin-bar-admin-notices__content.components-popover::after{border-color:#E5EAEE !important}.itsec-admin-notice-panel{padding:1em;background:#E5EAEE;width:420px;box-sizing:border-box}.itsec-admin-notice-panel .itsec-admin-notice-panel__header{border-bottom:1px solid #7ABEED;margin-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__header h3{color:#0081E3;text-align:center}.itsec-admin-notice-panel .itsec-admin-notice-panel__header p{text-align:center;font-style:oblique}.is-mobile .itsec-admin-notice-panel{width:100%;overflow-x:auto;height:100%}.is-mobile .itsec-admin-notice-panel header h3{display:none}.is-mobile .itsec-admin-notice-panel header p{margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-button{padding:5px;height:30px;position:absolute;right:1em;top:1em;transition:opacity 400ms}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-button:hover{opacity:.5;box-shadow:none !important}.itsec-admin-notice-panel.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-button{color:#0081E3}.itsec-admin-notice-panel.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-button:hover{color:#0081E3}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs{border-bottom:1px solid #7ABEED;margin-bottom:1em;padding-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li{display:flex;justify-content:space-between;border-bottom:1px solid #ccc;margin-bottom:1em;padding-bottom:1em;padding-top:0;margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li label{margin-left:calc(24px + 1em);font-size:14px;font-weight:bold}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li .components-form-toggle.is-checked .components-form-toggle__track{background-color:#0081E3;border-color:#0081E3}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li .components-form-toggle__input:disabled+.components-form-toggle__track{opacity:.5}
|
8 |
Â
|
9 |
+
.itsec-admin-bar__admin-notices{margin-left:auto}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button{color:#0081E3;border:none;background:transparent}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button:hover{color:#4ab1ff}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger>.components-button svg{margin-right:.5em}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger .components-button{position:relative}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger .components-button::before{content:'';background:#d8514f;height:5px;width:5px;border-radius:5px;vertical-align:middle;border:1px solid #f1f1f1;z-index:1;position:absolute;left:4px;top:3px;opacity:0;transition:opacity 1000ms ease-in-out}.itsec-admin-bar__admin-notices .itsec-admin-bar-admin-notices__trigger--has-notices .components-button::before{opacity:1}.itsec-admin-bar-admin-notices__content .components-popover__content{box-shadow:rgba(0,0,0,0.19) 0 4px 5px}@media screen and (max-width: 600px){.itsec-admin-bar .itsec-admin-bar__admin-notices{margin-left:0}}
|
10 |
Â
|
dist/core/admin-notices-dashboard-admin-bar.min.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
this.itsec=this.itsec||{},this.itsec.core=this.itsec.core||{},this.itsec.core["admin-notices-dashboard-admin-bar"]=function(e){var t={};function n(i){if(t[i])return t[i].exports;var c=t[i]={i:i,l:!1,exports:{}};return e[i].call(c.exports,c,c.exports,n),c.l=!0,c.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(i,c,function(t){return e[t]}.bind(null,c));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s="Pesb")}({"1ZqX":function(e,t){!function(){e.exports=this.wp.data}()},CDPQ:function(e,t,n){},Ckse:function(e,t,n){},GRId:function(e,t){!function(){e.exports=this.wp.element}()},Hz6T:function(e,t){!function(){e.exports=this.itsec.core["admin-notices-api"]}()},K9lf:function(e,t){!function(){e.exports=this.wp.compose}()},KTI5:function(e,t,n){},Pesb:function(e,t,n){"use strict";n.r(t);var i=n("TvNi"),c=(n("Hz6T"),n("GRId")),r=n("TSYQ"),a=n.n(r),o=n("tI+e"),s=n("l3Sj"),l=n("K9lf"),u=n("1ZqX"),m=n("cruf"),d=n("vYuV"),f=n("rE5z");n("CDPQ");var b=Object(l.compose)([Object(u.withSelect)(function(e){return{notices:e("ithemes-security/admin-notices").getNotices(),noticesLoaded:e("ithemes-security/admin-notices").areNoticesLoaded()}}),Object(l.withState)({isToggled:!1})])(function(e){var t=e.notices,n=e.noticesLoaded,i=e.isToggled,r=e.setState;return Object(c.createElement)(m.AdminBarFill,null,Object(c.createElement)("div",{className:"itsec-admin-bar__admin-notices"},Object(c.createElement)("div",{className:a()("itsec-admin-bar-admin-notices__trigger",{"itsec-admin-bar-admin-notices__trigger--has-notices":t.length>0})},Object(c.createElement)(o.Button,{"aria-expanded":i,onClick:function(){return r({isToggled:!i})}},Object(c.createElement)(o.Dashicon,{icon:"megaphone",size:15}),Object(s.__)("Notifications","better-wp-security")),i&&Object(c.createElement)(o.Popover,{className:"itsec-admin-bar-admin-notices__content",expandOnMobile:!0,focusOnMount:"container",position:"bottom left",headerTitle:Object(s.__)("Notifications","better-wp-security"),onClose:function(){return r({isToggled:!1})},onClickOutside:function(e){"itsec-admin-notices-toolbar-trigger"===e.target.id||"itsec-admin-notices-toolbar-trigger"===e.target.parentNode.id||Object(d.a)(e.target)||r({isToggled:!1})}},Object(c.createElement)(f.a,{notices:t,loaded:n,close:function(){return r({isToggled:!1})}})))))});n.p=window.itsecWebpackPublicPath,Object(i.registerPlugin)("itsec-admin-notices-dashboard-admin-bar",{render:b})},TSYQ:function(e,t,n){
|
2 |
Â
/*!
|
3 |
Â
Copyright (c) 2017 Jed Watson.
|
4 |
Â
Licensed under the MIT License (MIT), see
|
1 |
+
this.itsec=this.itsec||{},this.itsec.core=this.itsec.core||{},this.itsec.core["admin-notices-dashboard-admin-bar"]=function(e){var t={};function n(i){if(t[i])return t[i].exports;var c=t[i]={i:i,l:!1,exports:{}};return e[i].call(c.exports,c,c.exports,n),c.l=!0,c.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(i,c,function(t){return e[t]}.bind(null,c));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s="Pesb")}({"1ZqX":function(e,t){!function(){e.exports=this.wp.data}()},CDPQ:function(e,t,n){},Ckse:function(e,t,n){},GRId:function(e,t){!function(){e.exports=this.wp.element}()},Hz6T:function(e,t){!function(){e.exports=this.itsec.core["admin-notices-api"]}()},K9lf:function(e,t){!function(){e.exports=this.wp.compose}()},KTI5:function(e,t,n){},Pesb:function(e,t,n){"use strict";n.r(t);var i=n("TvNi"),c=(n("Hz6T"),n("GRId")),r=n("TSYQ"),a=n.n(r),o=n("tI+e"),s=n("l3Sj"),l=n("K9lf"),u=n("1ZqX"),m=n("cruf"),d=n("vYuV"),f=n("rE5z");n("CDPQ");var b=Object(l.compose)([Object(u.withSelect)(function(e){return{notices:e("ithemes-security/admin-notices").getNotices(),noticesLoaded:e("ithemes-security/admin-notices").areNoticesLoaded()}}),Object(l.withState)({isToggled:!1})])(function(e){var t=e.notices,n=e.noticesLoaded,i=e.isToggled,r=e.setState;return Object(c.createElement)(m.AdminBarFill,null,Object(c.createElement)("div",{className:"itsec-admin-bar__admin-notices"},Object(c.createElement)("div",{className:a()("itsec-admin-bar-admin-notices__trigger",{"itsec-admin-bar-admin-notices__trigger--has-notices":t.length>0})},Object(c.createElement)(o.Button,{"aria-expanded":i,onClick:function(){return r({isToggled:!i})},isSecondary:!0},Object(c.createElement)(o.Dashicon,{icon:"megaphone",size:15}),Object(s.__)("Notifications","better-wp-security")),i&&Object(c.createElement)(o.Popover,{className:"itsec-admin-bar-admin-notices__content",expandOnMobile:!0,focusOnMount:"container",position:"bottom left",headerTitle:Object(s.__)("Notifications","better-wp-security"),onClose:function(){return r({isToggled:!1})},onClickOutside:function(e){e.target&&("itsec-admin-notices-toolbar-trigger"===e.target.id||"itsec-admin-notices-toolbar-trigger"===e.target.parentNode.id||Object(d.a)(e.target))||r({isToggled:!1})},onFocusOutside:function(){var e=document.activeElement;"itsec-admin-notices-toolbar-trigger"===e.id||e.parentNode&&"itsec-admin-notices-toolbar-trigger"===e.parentNode.id||Object(d.a)(e)||r({isToggled:!1})}},Object(c.createElement)(f.a,{notices:t,loaded:n,close:function(){return r({isToggled:!1})}})))))});n.p=window.itsecWebpackPublicPath,Object(i.registerPlugin)("itsec-admin-notices-dashboard-admin-bar",{render:b})},TSYQ:function(e,t,n){
|
2 |
Â
/*!
|
3 |
Â
Copyright (c) 2017 Jed Watson.
|
4 |
Â
Licensed under the MIT License (MIT), see
|
dist/core/admin-notices.min.css
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Â
|
5 |
Â
.itsec-admin-notice-list{margin:0}.itsec-admin-notice-list-item-container{display:grid;grid-template:auto / -webkit-min-content 1fr;grid-template:auto / min-content 1fr;grid-gap:1em;margin-bottom:2em}.itsec-admin-notice-list-item-container:last-child{margin-bottom:0}
|
6 |
Â
|
7 |
-
@keyframes itsec-animation-fade-in-constant{from{opacity:0}to{opacity:1}}.itsec-admin-bar-admin-notices__content.components-popover::after{border-color:#E5EAEE !important}.itsec-admin-notice-panel{padding:1em;background:#E5EAEE;width:420px;box-sizing:border-box}.itsec-admin-notice-panel .itsec-admin-notice-panel__header{border-bottom:1px solid #7ABEED;margin-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__header h3{color:#0081E3;text-align:center}.itsec-admin-notice-panel .itsec-admin-notice-panel__header p{text-align:center;font-style:oblique}.is-mobile .itsec-admin-notice-panel{width:100%;overflow-x:auto;height:100%}.is-mobile .itsec-admin-notice-panel header h3{display:none}.is-mobile .itsec-admin-notice-panel header p{margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-
|
8 |
Â
|
9 |
Â
#wpadminbar #wp-admin-bar-itsec_admin_bar_menu .ab-sub-wrapper{background:transparent;box-shadow:none}#wpadminbar .itsec-admin-notices-toolbar-bubble{display:inline-block;vertical-align:top;margin:8px 0 0 5px;padding:0 5px;min-width:7px;height:17px;border-radius:11px;font-size:9px;line-height:17px;text-align:center;z-index:26;background-color:#ca4a1f;color:#fff;animation:itsec-admin-notices-toolbar-bubble-fade-in 400ms}#wpadminbar .itsec-admin-notices-toolbar-bubble .itsec-admin-notices-toolbar-bubble__count{line-height:17px;font-size:9px}@keyframes itsec-admin-notices-toolbar-bubble-fade-in{from{opacity:0}to{opacity:1}}#itsec-admin-notices-root .itsec-admin-notice-panel{border:1px solid #e2e4e7;box-shadow:0 3px 30px rgba(25,30,35,0.1)}#itsec-admin-notices-root .components-popover:not(.is-mobile).is-bottom{z-index:99999}#itsec-admin-notices-root .itsec-admin-notices-toolbar__popover .components-popover__content{box-shadow:rgba(0,0,0,0.19) 0 4px 5px}#wp-admin-bar-itsec_admin_bar_menu .components-button{cursor:pointer}#wp-admin-bar-itsec_admin_bar_menu .it-icon-itsec{display:none;margin-top:8px;color:rgba(240,245,250,0.6);height:20px;width:52px;line-height:32px;font-size:32px;text-align:center}@media screen and (max-width: 782px){#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu{display:list-item}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .it-icon-itsec{display:inline-block}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-toolbar-text{display:none}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar-bubble{display:none}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar--has-notices{position:relative}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar--has-notices::before{content:'';background:#d8514f;height:5px;width:5px;border-radius:5px;vertical-align:middle;border:1px solid #23282d;z-index:1;position:absolute;left:4px;top:3px;animation:itsec-admin-notices-toolbar-bubble-fade-in 400ms}}
|
10 |
Â
|
4 |
Â
|
5 |
Â
.itsec-admin-notice-list{margin:0}.itsec-admin-notice-list-item-container{display:grid;grid-template:auto / -webkit-min-content 1fr;grid-template:auto / min-content 1fr;grid-gap:1em;margin-bottom:2em}.itsec-admin-notice-list-item-container:last-child{margin-bottom:0}
|
6 |
Â
|
7 |
+
@keyframes itsec-animation-fade-in-constant{from{opacity:0}to{opacity:1}}.itsec-admin-bar-admin-notices__content.components-popover::after{border-color:#E5EAEE !important}.itsec-admin-notice-panel{padding:1em;background:#E5EAEE;width:420px;box-sizing:border-box}.itsec-admin-notice-panel .itsec-admin-notice-panel__header{border-bottom:1px solid #7ABEED;margin-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__header h3{color:#0081E3;text-align:center}.itsec-admin-notice-panel .itsec-admin-notice-panel__header p{text-align:center;font-style:oblique}.is-mobile .itsec-admin-notice-panel{width:100%;overflow-x:auto;height:100%}.is-mobile .itsec-admin-notice-panel header h3{display:none}.is-mobile .itsec-admin-notice-panel header p{margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-button{padding:5px;height:30px;position:absolute;right:1em;top:1em;transition:opacity 400ms}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-trigger.components-button:hover{opacity:.5;box-shadow:none !important}.itsec-admin-notice-panel.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-button{color:#0081E3}.itsec-admin-notice-panel.itsec-admin-notice-panel--is-configuring .itsec-admin-notice-panel__configure-trigger.components-button:hover{color:#0081E3}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs{border-bottom:1px solid #7ABEED;margin-bottom:1em;padding-bottom:1em}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li{display:flex;justify-content:space-between;border-bottom:1px solid #ccc;margin-bottom:1em;padding-bottom:1em;padding-top:0;margin-top:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li label{margin-left:calc(24px + 1em);font-size:14px;font-weight:bold}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li .components-form-toggle.is-checked .components-form-toggle__track{background-color:#0081E3;border-color:#0081E3}.itsec-admin-notice-panel .itsec-admin-notice-panel__configure-highlighted-logs li .components-form-toggle__input:disabled+.components-form-toggle__track{opacity:.5}
|
8 |
Â
|
9 |
Â
#wpadminbar #wp-admin-bar-itsec_admin_bar_menu .ab-sub-wrapper{background:transparent;box-shadow:none}#wpadminbar .itsec-admin-notices-toolbar-bubble{display:inline-block;vertical-align:top;margin:8px 0 0 5px;padding:0 5px;min-width:7px;height:17px;border-radius:11px;font-size:9px;line-height:17px;text-align:center;z-index:26;background-color:#ca4a1f;color:#fff;animation:itsec-admin-notices-toolbar-bubble-fade-in 400ms}#wpadminbar .itsec-admin-notices-toolbar-bubble .itsec-admin-notices-toolbar-bubble__count{line-height:17px;font-size:9px}@keyframes itsec-admin-notices-toolbar-bubble-fade-in{from{opacity:0}to{opacity:1}}#itsec-admin-notices-root .itsec-admin-notice-panel{border:1px solid #e2e4e7;box-shadow:0 3px 30px rgba(25,30,35,0.1)}#itsec-admin-notices-root .components-popover:not(.is-mobile).is-bottom{z-index:99999}#itsec-admin-notices-root .itsec-admin-notices-toolbar__popover .components-popover__content{box-shadow:rgba(0,0,0,0.19) 0 4px 5px}#wp-admin-bar-itsec_admin_bar_menu .components-button{cursor:pointer}#wp-admin-bar-itsec_admin_bar_menu .it-icon-itsec{display:none;margin-top:8px;color:rgba(240,245,250,0.6);height:20px;width:52px;line-height:32px;font-size:32px;text-align:center}@media screen and (max-width: 782px){#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu{display:list-item}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .it-icon-itsec{display:inline-block}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-toolbar-text{display:none}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar-bubble{display:none}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar--has-notices{position:relative}#wp-toolbar>ul>li#wp-admin-bar-itsec_admin_bar_menu .itsec-admin-notices-toolbar--has-notices::before{content:'';background:#d8514f;height:5px;width:5px;border-radius:5px;vertical-align:middle;border:1px solid #23282d;z-index:1;position:absolute;left:4px;top:3px;animation:itsec-admin-notices-toolbar-bubble-fade-in 400ms}}
|
10 |
Â
|
dist/core/admin-notices.min.js
CHANGED
@@ -4,4 +4,4 @@ this.itsec=this.itsec||{},this.itsec.core=this.itsec.core||{},this.itsec.core["a
|
|
4 |
Â
Licensed under the MIT License (MIT), see
|
5 |
Â
http://jedwatson.github.io/classnames
|
6 |
Â
*/
|
7 |
-
!function(){"use strict";var t={}.hasOwnProperty;function n(){for(var e=[],i=0;i<arguments.length;i++){var c=arguments[i];if(c){var r=typeof c;if("string"===r||"number"===r)e.push(c);else if(Array.isArray(c)&&c.length){var
|
4 |
Â
Licensed under the MIT License (MIT), see
|
5 |
Â
http://jedwatson.github.io/classnames
|
6 |
Â
*/
|
7 |
+
!function(){"use strict";var t={}.hasOwnProperty;function n(){for(var e=[],i=0;i<arguments.length;i++){var c=arguments[i];if(c){var r=typeof c;if("string"===r||"number"===r)e.push(c);else if(Array.isArray(c)&&c.length){var o=n.apply(null,c);o&&e.push(o)}else if("object"===r)for(var a in c)t.call(c,a)&&c[a]&&e.push(a)}}return e.join(" ")}e.exports?(n.default=n,e.exports=n):"function"==typeof define&&"object"==typeof define.amd&&define.amd?define("classnames",[],function(){return n}):window.classNames=n}()},UuzZ:function(e,t){!function(){e.exports=this.wp.autop}()},VwaH:function(e,t,n){},Y8OO:function(e,t){!function(){e.exports=this.wp.domReady}()},YLtl:function(e,t){!function(){e.exports=this.lodash}()},dwGD:function(e,t,n){"use strict";n.r(t);var i=n("GRId"),c=n("l3Sj"),r=n("Y8OO"),o=n.n(r),a=n("tI+e"),s=(n("Hz6T"),n("TSYQ")),l=n.n(s),u=n("K9lf"),m=n("vYuV"),d=n("rE5z"),b=(n("6IbE"),n("1ZqX"));var f=Object(u.compose)([Object(b.withSelect)(function(e){return{notices:e("ithemes-security/admin-notices").getNotices(),noticesLoaded:e("ithemes-security/admin-notices").areNoticesLoaded()}}),Object(u.withState)({isToggled:!1})])(function(e){var t=e.notices,n=e.noticesLoaded,r=e.isToggled,o=e.setState;return Object(i.createElement)(i.Fragment,null,Object(i.createElement)(a.Button,{id:"itsec-admin-notices-toolbar-trigger",className:l()("ab-item ab-empty-item",{"itsec-admin-notices-toolbar--has-notices":t.length>0}),onClick:function(){return o({isToggled:!r})},"aria-expanded":r},Object(i.createElement)("span",{className:"it-icon-itsec"}),Object(i.createElement)("span",{className:"itsec-toolbar-text"},Object(c.__)("Security","better-wp-security")),t.length>0&&Object(i.createElement)("span",{className:"itsec-admin-notices-toolbar-bubble"},Object(i.createElement)("span",{className:"itsec-admin-notices-toolbar-bubble__count"},t.length))),r&&Object(i.createElement)(a.Popover,{className:"itsec-admin-notices-toolbar__popover",noArrow:!0,expandOnMobile:!0,focusOnMount:"container",position:"bottom center",headerTitle:Object(c.__)("Security","better-wp-security"),onClose:function(){return o({isToggled:!1})},onClickOutside:function(e){e.target&&("itsec-admin-notices-toolbar-trigger"===e.target.id||"itsec-admin-notices-toolbar-trigger"===e.target.parentNode.id||Object(m.a)(e.target))||o({isToggled:!1})},onFocusOutside:function(){var e=document.activeElement;"itsec-admin-notices-toolbar-trigger"===e.id||e.parentNode&&"itsec-admin-notices-toolbar-trigger"===e.parentNode.id||Object(m.a)(e)||o({isToggled:!1})}},Object(i.createElement)(d.a,{notices:t,loaded:n,close:function(){return o({isToggled:!1})}})))});n("1Zi1");var p=function(e){var t=e.portalEl;return Object(i.createElement)(a.SlotFillProvider,null,Object(i.createPortal)(Object(i.createElement)(a.Popover.Slot,null),t),Object(i.createElement)(f,null))};n.p=window.itsecWebpackPublicPath,Object(c.setLocaleData)({"":{}},"better-wp-security"),o()(function(){var e=document.getElementById("wp-admin-bar-itsec_admin_bar_menu"),t=document.getElementById("itsec-admin-notices-root");return Object(i.render)(Object(i.createElement)(p,{portalEl:t}),e)})},l3Sj:function(e,t){!function(){e.exports=this.wp.i18n}()},"o/Pk":function(e,t,n){},rE5z:function(e,t,n){"use strict";var i=n("GRId"),c=n("TSYQ"),r=n.n(c),o=n("YLtl"),a=n("l3Sj"),s=n("tI+e"),l=n("K9lf"),u=n("1ZqX"),m=n("UuzZ");n("VwaH");function d(e){var t=e.notice;return Object(i.createElement)("article",{className:"itsec-admin-notice itsec-admin-notice--severity-".concat(t.severity)},Object(i.createElement)("header",{className:"itsec-admin-notice__header"},Object(i.createElement)("div",{className:"itsec-admin-notice__header-inset"},Object(i.createElement)("h4",{dangerouslySetInnerHTML:{__html:t.title||b(t.message,t)}}),Object(o.map)(t.actions,function(e,t){return"primary"===e.style&&Object(i.createElement)(s.Button,{key:t,href:e.uri},e.title)}))),t.title&&t.message&&Object(i.createElement)("section",{className:"itsec-admin-notice__message",dangerouslySetInnerHTML:{__html:Object(m.autop)(b(t.message,t))}}),function(e){if(Object(o.isEmpty)(e.meta))return!1;if(1===Object(o.size)(e.meta)&&e.meta.hasOwnProperty("created_at"))return!1;return!0}(t)&&Object(i.createElement)("dl",{className:"itsec-admin-notice__meta"},Object(o.map)(t.meta,function(e,t){return"created_at"!==t&&Object(i.createElement)(i.Fragment,{key:t},Object(i.createElement)("dt",null,e.label),Object(i.createElement)("dd",null,e.formatted))})),t.meta.created_at&&Object(i.createElement)("footer",{className:"itsec-admin-notice__footer"},Object(i.createElement)("time",{dateTime:t.meta.created_at.value},t.meta.created_at.formatted)))}function b(e,t){for(var n in t.actions)t.actions.hasOwnProperty(n)&&""!==t.actions[n].uri&&(e=e.replace("{{ $"+n+" }}",t.actions[n].uri));return e}n("o/Pk");var f=Object(l.compose)([Object(u.withDispatch)(function(e){return{doAction:e("ithemes-security/admin-notices").doNoticeAction}}),Object(u.withSelect)(function(e,t){return{inProgress:e("ithemes-security/admin-notices").getInProgressActions(t.notice.id)}})])(function(e){var t=e.notice,n=e.doAction,c=e.inProgress,r=[],l=function(e){if(!t.actions.hasOwnProperty(e))return"continue";var o=t.actions[e];"close"===o.style&&r.push(Object(i.createElement)("li",{key:e},Object(i.createElement)(s.IconButton,{icon:"dismiss",label:o.title,onClick:function(){return n(t.id,e)},isBusy:c.includes(e)})))};for(var u in t.actions)l(u);var m=function(e){var t={};for(var n in e.actions)if(e.actions.hasOwnProperty(n)){var i=e.actions[n];"close"!==i.style&&"primary"!==i.style&&(t[n]=i)}return t}(t);return Object(o.isEmpty)(m)||r.push(Object(i.createElement)("li",{key:"more"},Object(i.createElement)(s.Dropdown,{position:"bottom right",className:"itsec-admin-notice-list-actions__more-menu",contentClassName:"itsec-admin-notice-list-actions__more-menu-items",renderToggle:function(e){var t=e.isOpen,n=e.onToggle;return Object(i.createElement)(s.IconButton,{icon:"ellipsis",label:Object(a.__)("More Actions","better-wp-security"),onClick:n,"aria-haspopup":!0,"aria-expanded":t})},renderContent:function(){return Object(i.createElement)(s.NavigableMenu,{role:"menu"},Object(o.map)(m,function(e,r){return e.uri?Object(i.createElement)(s.Button,{key:r,href:e.uri},e.title):Object(i.createElement)(s.Button,{key:r,onClick:function(){return n(t.id,r)},disabled:c.includes(r)},e.title,c.includes(r)&&Object(i.createElement)(s.Spinner,null))}))}}))),Object(i.createElement)("ul",{className:"itsec-admin-notice-list-actions"},r)});n("Ckse");var p=function(e){var t=e.notices;return Object(i.createElement)("ul",{className:"itsec-admin-notice-list"},t.map(function(e){return Object(i.createElement)("li",{className:"itsec-admin-notice-list-item-container",key:e.id},Object(i.createElement)(f,{notice:e}),Object(i.createElement)(d,{notice:e,noticeId:e.id}))}))};n("KTI5");t.a=Object(l.compose)([Object(l.withState)({isConfiguring:!1,checked:{}}),Object(u.withSelect)(function(e){return{mutedHighlights:e("ithemes-security/admin-notices").getMutedHighlights(),mutedHighlightUpdatesInFlight:e("ithemes-security/admin-notices").getMutedHighlightUpdatesInFlight()}}),Object(u.withDispatch)(function(e){return{updateMutedHighlight:e("ithemes-security/admin-notices").updateMutedHighlight}})])(function(e){var t=e.notices,n=e.loaded,c=e.mutedHighlights,l=e.mutedHighlightUpdatesInFlight,u=e.updateMutedHighlight,m=e.isConfiguring,d=e.setState;return Object(i.createElement)("div",{className:r()("itsec-admin-notice-panel",{"itsec-admin-notice-panel--is-configuring":m})},Object(i.createElement)(s.IconButton,{icon:"admin-generic",label:Object(a.__)("Configure","better-wp-security"),className:"itsec-admin-notice-panel__configure-trigger",style:{opacity:Object(o.size)(c)>0?1:0},onClick:function(){return d({isConfiguring:!m})}}),Object(i.createElement)("header",{className:"itsec-admin-notice-panel__header"},Object(i.createElement)("h3",null,Object(a.__)("Security Admin Messages","better-wp-security")),Object(i.createElement)("p",null,Object(a.__)("Important notices from iThemes Security","better-wp-security"))),m&&Object(i.createElement)("ul",{className:"itsec-admin-notice-panel__configure-highlighted-logs"},[{slug:"file-change-report",label:Object(a.__)("File Change Report","better-wp-security")},{slug:"notification-center-send-failed",label:Object(a.__)("Notification Center Errors","better-wp-security")},{slug:"malware-scan-report",label:Object(a.__)("Malware Scan Report","better-wp-security")},{slug:"malware-scan-failed",label:Object(a.__)("Malware Scan Failed","better-wp-security")}].map(function(e){var t=e.slug,r=e.label;return void 0!==c[t]&&Object(i.createElement)("li",null,Object(i.createElement)("label",{htmlFor:"itsec-mute-highlight-".concat(t)},r),Object(i.createElement)(s.FormToggle,{id:"itsec-mute-highlight-".concat(t),disabled:!n||l[t],checked:!Object(o.get)(l,[t,"mute"],c[t]),onChange:function(){return u(t,!c[t])}}))})),t.length>0?Object(i.createElement)(p,{notices:t}):n&&Object(i.createElement)("span",null,Object(a.__)("No notices at the moment.","better-wp-security")))})},"tI+e":function(e,t){!function(){e.exports=this.wp.components}()},vYuV:function(e,t,n){"use strict";function i(e){for(var t=e.parentNode;null!==t;){if(t.classList&&t.classList.contains("itsec-admin-notice-list-actions__more-menu-items"))return!0;t=t.parentNode}return!1}n.d(t,"a",function(){return i})}});
|
dist/manifest.php
CHANGED
@@ -7,11 +7,11 @@
|
|
7 |
Â
0 => 'core/admin-notices.css',
|
8 |
Â
1 => 'core/admin-notices.js',
|
9 |
Â
),
|
10 |
-
'hash' => '
|
11 |
Â
'contentHash' =>
|
12 |
Â
array (
|
13 |
-
'css/mini-extract' => '
|
14 |
-
'javascript' => '
|
15 |
Â
),
|
16 |
Â
'vendors' =>
|
17 |
Â
array (
|
@@ -36,11 +36,11 @@
|
|
36 |
Â
array (
|
37 |
Â
0 => 'core/admin-notices-api.js',
|
38 |
Â
),
|
39 |
-
'hash' => '
|
40 |
Â
'contentHash' =>
|
41 |
Â
array (
|
42 |
Â
'css/mini-extract' => '31d6cfe0d16ae931b73c',
|
43 |
-
'javascript' => '
|
44 |
Â
),
|
45 |
Â
'vendors' =>
|
46 |
Â
array (
|
@@ -61,11 +61,11 @@
|
|
61 |
Â
0 => 'core/admin-notices-dashboard-admin-bar.css',
|
62 |
Â
1 => 'core/admin-notices-dashboard-admin-bar.js',
|
63 |
Â
),
|
64 |
-
'hash' => '
|
65 |
Â
'contentHash' =>
|
66 |
Â
array (
|
67 |
-
'css/mini-extract' => '
|
68 |
-
'javascript' => '
|
69 |
Â
),
|
70 |
Â
'vendors' =>
|
71 |
Â
array (
|
@@ -105,4 +105,106 @@
|
|
105 |
Â
array (
|
106 |
Â
),
|
107 |
Â
),
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
108 |
Â
);
|
7 |
Â
0 => 'core/admin-notices.css',
|
8 |
Â
1 => 'core/admin-notices.js',
|
9 |
Â
),
|
10 |
+
'hash' => '44625005dbb4e6a5d67ec06d66bb6318',
|
11 |
Â
'contentHash' =>
|
12 |
Â
array (
|
13 |
+
'css/mini-extract' => '6fb57999347c20cedea4',
|
14 |
+
'javascript' => 'b7be7e1b3d28502c2bbb',
|
15 |
Â
),
|
16 |
Â
'vendors' =>
|
17 |
Â
array (
|
36 |
Â
array (
|
37 |
Â
0 => 'core/admin-notices-api.js',
|
38 |
Â
),
|
39 |
+
'hash' => '2c3247aed3d49189aa60feffcad7abed',
|
40 |
Â
'contentHash' =>
|
41 |
Â
array (
|
42 |
Â
'css/mini-extract' => '31d6cfe0d16ae931b73c',
|
43 |
+
'javascript' => '1e901721411a447176e1',
|
44 |
Â
),
|
45 |
Â
'vendors' =>
|
46 |
Â
array (
|
61 |
Â
0 => 'core/admin-notices-dashboard-admin-bar.css',
|
62 |
Â
1 => 'core/admin-notices-dashboard-admin-bar.js',
|
63 |
Â
),
|
64 |
+
'hash' => '0cd8b080ffd0f85953652b206e7440c1',
|
65 |
Â
'contentHash' =>
|
66 |
Â
array (
|
67 |
+
'css/mini-extract' => 'fb0322849abdb99593d3',
|
68 |
+
'javascript' => 'd0732cd3721b6c937acc',
|
69 |
Â
),
|
70 |
Â
'vendors' =>
|
71 |
Â
array (
|
105 |
Â
array (
|
106 |
Â
),
|
107 |
Â
),
|
108 |
+
'packages/preload' =>
|
109 |
+
array (
|
110 |
+
'runtime' => true,
|
111 |
+
'files' =>
|
112 |
+
array (
|
113 |
+
0 => 'packages/preload.js',
|
114 |
+
),
|
115 |
+
'hash' => '2c905e0398d2196dc4279540a39e10a8',
|
116 |
+
'contentHash' =>
|
117 |
+
array (
|
118 |
+
'css/mini-extract' => '31d6cfe0d16ae931b73c',
|
119 |
+
'javascript' => '53821da2f6c3984fa5e1',
|
120 |
+
),
|
121 |
+
'vendors' =>
|
122 |
+
array (
|
123 |
+
),
|
124 |
+
'dependencies' =>
|
125 |
+
array (
|
126 |
+
),
|
127 |
+
),
|
128 |
+
'user-groups/api' =>
|
129 |
+
array (
|
130 |
+
'runtime' => true,
|
131 |
+
'files' =>
|
132 |
+
array (
|
133 |
+
0 => 'user-groups/api.js',
|
134 |
+
),
|
135 |
+
'hash' => 'c9198440d6d93418b23f8fc09c747a38',
|
136 |
+
'contentHash' =>
|
137 |
+
array (
|
138 |
+
'css/mini-extract' => '31d6cfe0d16ae931b73c',
|
139 |
+
'javascript' => '4f635c3e11bebc2913be',
|
140 |
+
),
|
141 |
+
'vendors' =>
|
142 |
+
array (
|
143 |
+
0 => 'vendors/user-groups/api',
|
144 |
+
),
|
145 |
+
'dependencies' =>
|
146 |
+
array (
|
147 |
+
0 => 'lodash',
|
148 |
+
1 => 'wp-api-fetch',
|
149 |
+
2 => 'wp-data',
|
150 |
+
3 => 'wp-i18n',
|
151 |
+
4 => 'wp-url',
|
152 |
+
),
|
153 |
+
),
|
154 |
+
'user-groups/settings' =>
|
155 |
+
array (
|
156 |
+
'runtime' => true,
|
157 |
+
'files' =>
|
158 |
+
array (
|
159 |
+
0 => 'user-groups/settings.css',
|
160 |
+
1 => 'user-groups/settings.js',
|
161 |
+
),
|
162 |
+
'hash' => '305ce83e45716bef87675e4537acb854',
|
163 |
+
'contentHash' =>
|
164 |
+
array (
|
165 |
+
'css/mini-extract' => '59a0798149a770d90ff7',
|
166 |
+
'javascript' => '91ae72c9f77f23fe2c64',
|
167 |
+
),
|
168 |
+
'vendors' =>
|
169 |
+
array (
|
170 |
+
),
|
171 |
+
'dependencies' =>
|
172 |
+
array (
|
173 |
+
0 => '@ithemes/security.user-groups.api',
|
174 |
+
1 => 'lodash',
|
175 |
+
2 => 'react',
|
176 |
+
3 => 'react-dom',
|
177 |
+
4 => 'wp-api-fetch',
|
178 |
+
5 => 'wp-components',
|
179 |
+
6 => 'wp-compose',
|
180 |
+
7 => 'wp-data',
|
181 |
+
8 => 'wp-dom-ready',
|
182 |
+
9 => 'wp-element',
|
183 |
+
10 => 'wp-html-entities',
|
184 |
+
11 => 'wp-i18n',
|
185 |
+
12 => 'wp-is-shallow-equal',
|
186 |
+
13 => 'wp-notices',
|
187 |
+
14 => 'wp-url',
|
188 |
+
),
|
189 |
+
),
|
190 |
+
'vendors/user-groups/api' =>
|
191 |
+
array (
|
192 |
+
'runtime' => false,
|
193 |
+
'files' =>
|
194 |
+
array (
|
195 |
+
0 => 'vendors/user-groups/api.js',
|
196 |
+
),
|
197 |
+
'hash' => '6e34397d56216708356fb62fb92c1b6c',
|
198 |
+
'contentHash' =>
|
199 |
+
array (
|
200 |
+
'css/mini-extract' => '31d6cfe0d16ae931b73c',
|
201 |
+
'javascript' => 'a4cac444b9ecf3c4bda3',
|
202 |
+
),
|
203 |
+
'vendors' =>
|
204 |
+
array (
|
205 |
+
),
|
206 |
+
'dependencies' =>
|
207 |
+
array (
|
208 |
+
),
|
209 |
+
),
|
210 |
Â
);
|
dist/packages/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
dist/packages/preload.min.js
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
this.itsec=this.itsec||{},this.itsec.packages=this.itsec.packages||{},this.itsec.packages.preload=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s="aJ6B")}({aJ6B:function(e,t,r){"use strict";r.r(t),r.d(t,"getStablePath",function(){return o}),r.d(t,"createMiddleware",function(){return i}),r.d(t,"invalidatePreload",function(){return u}),r.d(t,"CONTROL",function(){return a}),r.d(t,"invalidatePreloadControl",function(){return c}),r.p=window.itsecWebpackPublicPath;var n={};function o(e){var t=e.split("?"),r=t[1],n=t[0];return r?n+"?"+r.split("&").map(function(e){return e.split("=")}).sort(function(e,t){return e[0].localeCompare(t[0])}).map(function(e){return e.join("=")}).join("&"):n}function i(e){return Object.keys(e).reduce(function(t,r){return t[o(r)]=e[r],t},n),function(e,t){var r=e.parse,i=void 0===r||r;if("string"==typeof e.path){var u=e.method||"GET",a=o(e.path);if(i&&"GET"===u&&n[a])return Promise.resolve(n[a].body);if("OPTIONS"===u&&n[u]&&n[u][a])return Promise.resolve(n[u][a])}return t(e)}}function u(e){var t=e.path;delete n[o(t)]}var a="INVALIDATE_API_FETCH_PRELOAD";function c(e){return{type:a,path:e}}}});
|
dist/user-groups/api.min.js
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
this.itsec=this.itsec||{},this.itsec["user-groups"]=this.itsec["user-groups"]||{},this.itsec["user-groups"].api=function(e){function t(t){for(var n,a,c=t[0],s=t[1],o=t[2],f=0,p=[];f<c.length;f++)a=c[f],u[a]&&p.push(u[a][0]),u[a]=0;for(n in s)Object.prototype.hasOwnProperty.call(s,n)&&(e[n]=s[n]);for(d&&d(t);p.length;)p.shift()();return i.push.apply(i,o||[]),r()}function r(){for(var e,t=0;t<i.length;t++){for(var r=i[t],n=!0,c=1;c<r.length;c++){var s=r[c];0!==u[s]&&(n=!1)}n&&(i.splice(t--,1),e=a(a.s=r[0]))}return e}var n={},u={5:0},i=[];function a(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,a),r.l=!0,r.exports}a.m=e,a.c=n,a.d=function(e,t,r){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(a.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(r,n,function(t){return e[t]}.bind(null,n));return r},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="";var c=window.itsecWebpackJsonP=window.itsecWebpackJsonP||[],s=c.push.bind(c);c.push=t,c=c.slice();for(var o=0;o<c.length;o++)t(c[o]);var d=s;return i.push(["Ntz8",7]),r()}({"1ZqX":function(e,t){!function(){e.exports=this.wp.data}()},Mmq9:function(e,t){!function(){e.exports=this.wp.url}()},Ntz8:function(e,t,r){"use strict";r.r(t);var n={};r.r(n),r.d(n,"path",function(){return G}),r.d(n,"query",function(){return R}),r.d(n,"appendToQuery",function(){return k}),r.d(n,"receiveQuery",function(){return U}),r.d(n,"processItem",function(){return A}),r.d(n,"receiveGroup",function(){return w}),r.d(n,"receiveMatchables",function(){return j}),r.d(n,"startCreateGroup",function(){return N}),r.d(n,"failedCreateGroup",function(){return C}),r.d(n,"finishCreateGroup",function(){return D}),r.d(n,"startUpdateGroup",function(){return F}),r.d(n,"failedUpdateGroup",function(){return H}),r.d(n,"finishUpdateGroup",function(){return L}),r.d(n,"startDeleteGroup",function(){return B}),r.d(n,"failedDeleteGroup",function(){return q}),r.d(n,"finishDeleteGroup",function(){return M}),r.d(n,"receiveGroupSettings",function(){return Y}),r.d(n,"startUpdateGroupSettings",function(){return Q}),r.d(n,"failedUpdateGroupSettings",function(){return K}),r.d(n,"finishUpdateGroupSettings",function(){return V}),r.d(n,"createGroup",function(){return W}),r.d(n,"updateGroup",function(){return J}),r.d(n,"deleteGroup",function(){return Z}),r.d(n,"updateGroupSettings",function(){return z}),r.d(n,"fetchGroupsSettings",function(){return X}),r.d(n,"startFetchGroupsSettings",function(){return $}),r.d(n,"finishFetchGroupsSettings",function(){return ee}),r.d(n,"failedFetchGroupsSettings",function(){return te}),r.d(n,"patchBulkGroupSettings",function(){return re}),r.d(n,"startPatchBulkGroupSettings",function(){return ne}),r.d(n,"finishPatchBulkGroupSettings",function(){return ue}),r.d(n,"failedPatchBulkGroupSettings",function(){return ie}),r.d(n,"RECEIVE_QUERY",function(){return ae}),r.d(n,"APPEND_TO_QUERY",function(){return ce}),r.d(n,"RECEIVE_MATCHABLES",function(){return se}),r.d(n,"START_CREATE_GROUP",function(){return oe}),r.d(n,"FINISH_CREATE_GROUP",function(){return de}),r.d(n,"FAILED_CREATE_GROUP",function(){return fe}),r.d(n,"RECEIVE_GROUP",function(){return pe}),r.d(n,"START_UPDATE_GROUP",function(){return le}),r.d(n,"FINISH_UPDATE_GROUP",function(){return ge}),r.d(n,"FAILED_UPDATE_GROUP",function(){return he}),r.d(n,"START_DELETE_GROUP",function(){return be}),r.d(n,"FINISH_DELETE_GROUP",function(){return ve}),r.d(n,"FAILED_DELETE_GROUP",function(){return ye}),r.d(n,"RECEIVE_GROUP_SETTINGS",function(){return me}),r.d(n,"START_UPDATE_GROUP_SETTINGS",function(){return _e}),r.d(n,"FINISH_UPDATE_GROUP_SETTINGS",function(){return Ee}),r.d(n,"FAILED_UPDATE_GROUP_SETTINGS",function(){return Se}),r.d(n,"START_FETCH_GROUPS_SETTINGS",function(){return Ie}),r.d(n,"FINISH_FETCH_GROUPS_SETTINGS",function(){return Te}),r.d(n,"FAILED_FETCH_GROUPS_SETTINGS",function(){return Pe}),r.d(n,"START_PATCH_BULK_GROUP_SETTINGS",function(){return Oe}),r.d(n,"FINISH_PATCH_BULK_GROUP_SETTINGS",function(){return xe}),r.d(n,"FAILED_PATCH_BULK_GROUP_SETTINGS",function(){return Ge});var u={};r.r(u),r.d(u,"getMatchables",function(){return ke}),r.d(u,"getMatchableType",function(){return Ue}),r.d(u,"getMatchableLabel",function(){return Ae}),r.d(u,"getGroups",function(){return we}),r.d(u,"getQueriedObjectIds",function(){return Ne}),r.d(u,"getGroup",function(){return Ce}),r.d(u,"getGroupAttribute",function(){return De}),r.d(u,"isUpdating",function(){return Fe}),r.d(u,"isDeleting",function(){return He}),r.d(u,"getGroupSettings",function(){return Le}),r.d(u,"getGroupSetting",function(){return Be}),r.d(u,"isUpdatingSettings",function(){return qe}),r.d(u,"isBulkPatchingSettings",function(){return Me}),r.d(u,"getGroupsBySetting",function(){return Ye});var i={};r.r(i),r.d(i,"getGroup",function(){return Ze}),r.d(i,"getMatchables",function(){return ze}),r.d(i,"getGroupSettings",function(){return Xe});var a=r("1ZqX"),c=r("RIqP"),s=r.n(c),o=r("ywyh"),d=r.n(o),f=r("Td6G");function p(e){return{type:"API_FETCH",request:e}}function l(e,t){for(var r=arguments.length,n=new Array(r>2?r-2:0),u=2;u<r;u++)n[u-2]=arguments[u];return{type:"DISPATCH",storeKey:e,actionName:t,args:n}}var g={API_FETCH:function(e){var t=e.request;return d()(t).catch(f.e)},SELECT:function(e){var t,r=e.storeKey,n=e.selectorName,u=e.args;return(t=Object(a.select)(r))[n].apply(t,s()(u))},DISPATCH:function(e){var t,r=e.storeKey,n=e.actionName,u=e.args;return(t=Object(a.dispatch)(r))[n].apply(t,s()(u))}},h=r("YLtl"),b=r("qPad"),v=r.n(b),y=r("Mmq9"),m=regeneratorRuntime.mark(R),_=regeneratorRuntime.mark(k),E=regeneratorRuntime.mark(A),S=regeneratorRuntime.mark(W),I=regeneratorRuntime.mark(J),T=regeneratorRuntime.mark(Z),P=regeneratorRuntime.mark(z),O=regeneratorRuntime.mark(X),x=regeneratorRuntime.mark(re),G="/ithemes-security/v1/user-groups";function R(e,t){var r,n,u,i,a,c,s;return regeneratorRuntime.wrap(function(o){for(;;)switch(o.prev=o.next){case 0:return o.next=2,p({path:Object(y.addQueryArgs)(G,t)});case 2:return r=o.sent,o.next=5,U(e,r);case 5:n=!0,u=!1,i=void 0,o.prev=8,a=r[Symbol.iterator]();case 10:if(n=(c=a.next()).done){o.next=16;break}return s=c.value,o.delegateYield(A(s),"t0",13);case 13:n=!0,o.next=10;break;case 16:o.next=22;break;case 18:o.prev=18,o.t1=o.catch(8),u=!0,i=o.t1;case 22:o.prev=22,o.prev=23,n||null==a.return||a.return();case 25:if(o.prev=25,!u){o.next=28;break}throw i;case 28:return o.finish(25);case 29:return o.finish(22);case 30:return o.abrupt("return",r);case 31:case"end":return o.stop()}},m,this,[[8,18,22,30],[23,,25,29]])}function k(e,t){return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,{type:ce,queryId:e,item:t};case 2:return r.delegateYield(A(t),"t0",3);case 3:case"end":return r.stop()}},_,this)}function U(e,t){return{type:ae,queryId:e,items:t}}function A(e){var t,r,n,u,i,a,c,s;return regeneratorRuntime.wrap(function(o){for(;;)switch(o.prev=o.next){case 0:t=Object(h.get)(e,["_embedded","ithemes-security:user-group-member"],[]),r=Object(h.get)(e,["_embedded","ithemes-security:user-matchable-settings",0]),n=!0,u=!1,i=void 0,o.prev=5,a=t[Symbol.iterator]();case 7:if(n=(c=a.next()).done){o.next=14;break}return s=c.value,o.next=11,l("ithemes-security/core","receiveUser",s);case 11:n=!0,o.next=7;break;case 14:o.next=20;break;case 16:o.prev=16,o.t0=o.catch(5),u=!0,i=o.t0;case 20:o.prev=20,o.prev=21,n||null==a.return||a.return();case 23:if(o.prev=23,!u){o.next=26;break}throw i;case 26:return o.finish(23);case 27:return o.finish(20);case 28:if(!r){o.next=31;break}return o.next=31,Y(e.id,r);case 31:case"end":return o.stop()}},E,this,[[5,16,20,28],[21,,23,27]])}function w(e){return{type:pe,group:e}}function j(e){return{type:se,matchables:e}}function N(e){return{type:oe,group:e}}function C(e,t){return{type:fe,group:e,error:t}}function D(e,t){return{type:de,group:e,response:t}}function F(e,t){return{type:le,id:e,group:t}}function H(e,t){return{type:he,id:e,error:t}}function L(e,t){return{type:ge,id:e,response:t}}function B(e){return{type:be,id:e}}function q(e,t){return{type:ye,id:e,error:t}}function M(e){return{type:ve,id:e}}function Y(e,t){return{type:me,id:e,settings:t}}function Q(e,t){return{type:_e,id:e,settings:t}}function K(e,t){return{type:Se,id:e,error:t}}function V(e,t){return{type:Ee,id:e,response:t}}function W(e){var t;return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,N(e);case 2:return r.prev=2,r.next=5,p({path:Object(y.addQueryArgs)(G,{_embed:1}),method:"POST",data:e});case 5:t=r.sent,r.next=13;break;case 8:return r.prev=8,r.t0=r.catch(2),r.next=12,C(e,r.t0);case 12:return r.abrupt("return",r.t0);case 13:return r.next=15,D(e,t);case 15:return r.next=17,w(t);case 17:return r.delegateYield(A(t),"t1",18);case 18:return r.abrupt("return",t);case 19:case"end":return r.stop()}},S,this,[[2,8]])}function J(e,t){var r;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,F(e,t);case 2:return n.prev=2,n.next=5,p({path:G+"/"+e,method:"PUT",data:t});case 5:r=n.sent,n.next=13;break;case 8:return n.prev=8,n.t0=n.catch(2),n.next=12,H(e,n.t0);case 12:return n.abrupt("return",n.t0);case 13:return n.next=15,L(e,r);case 15:return n.next=17,w(r);case 17:return n.abrupt("return",r);case 18:case"end":return n.stop()}},I,this,[[2,8]])}function Z(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,B(e);case 2:return t.prev=2,t.next=5,p({path:"".concat(G,"/").concat(e),method:"DELETE"});case 5:t.next=12;break;case 7:return t.prev=7,t.t0=t.catch(2),t.next=11,q(e,t.t0);case 11:return t.abrupt("return",t.t0);case 12:return t.next=14,M(e);case 14:return t.abrupt("return",null);case 15:case"end":return t.stop()}},T,this,[[2,7]])}function z(e,t){var r;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,Q(e,t);case 2:return n.prev=2,n.next=5,p({path:"ithemes-security/v1/user-matchable-settings/".concat(e),method:"PUT",data:t});case 5:r=n.sent,n.next=13;break;case 8:return n.prev=8,n.t0=n.catch(2),n.next=12,K(e,n.t0);case 12:return n.abrupt("return",n.t0);case 13:return n.next=15,V(e,r);case 15:return n.next=17,Y(e,r);case 17:return n.abrupt("return",r);case 18:case"end":return n.stop()}},P,this,[[2,8]])}function X(){var e,t,r,n,u=arguments;return regeneratorRuntime.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:return e=u.length>0&&void 0!==u[0]?u[0]:[],i.next=3,$(e);case 3:return i.prev=3,r="ithemes-security/v1/user-matchable-settings",e.length>0&&(r=Object(y.addQueryArgs)(r,{include:e})),i.next=8,p({path:r});case 8:t=i.sent,i.next=16;break;case 11:return i.prev=11,i.t0=i.catch(3),i.next=15,te(e,i.t0);case 15:return i.abrupt("return",i.t0);case 16:return i.next=18,ee(e,t);case 18:i.t1=regeneratorRuntime.keys(t);case 19:if((i.t2=i.t1()).done){i.next=27;break}if(n=i.t2.value,t.hasOwnProperty(n)){i.next=23;break}return i.abrupt("continue",19);case 23:return i.next=25,Y(n,t[n]);case 25:i.next=19;break;case 27:return i.abrupt("return",t);case 28:case"end":return i.stop()}},O,this,[[3,11]])}function $(e){return{type:Ie,groupIds:e}}function ee(e,t){return{type:Te,groupIds:e,response:t}}function te(e,t){return{type:Pe,groupIds:e,error:t}}function re(e,t){var r,n,u,i,c,s,o,d,l,g,h;return regeneratorRuntime.wrap(function(b){for(;;)switch(b.prev=b.next){case 0:return b.next=2,ne(e,t);case 2:return b.prev=2,b.next=5,p({path:Object(y.addQueryArgs)("ithemes-security/v1/user-matchable-settings",{include:e}),method:"PATCH",data:t});case 5:r=b.sent,b.next=13;break;case 8:return b.prev=8,b.t0=b.catch(2),b.next=12,ie(e,t,b.t0);case 12:return b.abrupt("return",b.t0);case 13:return b.next=15,ue(e,t,r);case 15:if(n=Object(a.select)("ithemes-security/core").getSchema("ithemes-security-user-group-settings"),u=Object(f.c)(n,"self")){b.next=19;break}return b.abrupt("return",r);case 19:i=new v.a(u.href),c=!0,s=!1,o=void 0,b.prev=23,d=r[Symbol.iterator]();case 25:if(c=(l=d.next()).done){b.next=37;break}if(200===(g=l.value).status){b.next=29;break}return b.abrupt("continue",34);case 29:if((h=i.fromUri(g.href)).id){b.next=32;break}return b.abrupt("continue",34);case 32:return b.next=34,Y(h.id,g.response);case 34:c=!0,b.next=25;break;case 37:b.next=43;break;case 39:b.prev=39,b.t1=b.catch(23),s=!0,o=b.t1;case 43:b.prev=43,b.prev=44,c||null==d.return||d.return();case 46:if(b.prev=46,!s){b.next=49;break}throw o;case 49:return b.finish(46);case 50:return b.finish(43);case 51:return b.abrupt("return",r);case 52:case"end":return b.stop()}},x,this,[[2,8],[23,39,43,51],[44,,46,50]])}function ne(e,t){return{type:Oe,groupIds:e,patch:t}}function ue(e,t,r){return{type:xe,groupIds:e,patch:t,response:r}}function ie(e,t,r){return{type:Ge,groupIds:e,patch:t,error:r}}var ae="RECEIVE_QUERY",ce="APPEND_TO_QUERY",se="RECEIVE_MATCHABLES",oe="START_CREATE_GROUP",de="FINISH_CREATE_GROUP",fe="FAILED_CREATE_GROUP",pe="RECEIVE_GROUP",le="START_UPDATE_GROUP",ge="FINISH_UPDATE_GROUP",he="FAILED_UPDATE_GROUP",be="START_DELETE_GROUP",ve="FINISH_DELETE_GROUP",ye="FAILED_DELETE_GROUP",me="RECEIVE_GROUP_SETTINGS",_e="START_UPDATE_GROUP_SETTINGS",Ee="FINISH_UPDATE_GROUP_SETTINGS",Se="FAILED_UPDATE_GROUP_SETTINGS",Ie="START_FETCH_GROUPS_SETTINGS",Te="FINISH_FETCH_GROUPS_SETTINGS",Pe="FAILED_FETCH_GROUPS_SETTINGS",Oe="START_PATCH_BULK_GROUP_SETTINGS",xe="FINISH_PATCH_BULK_GROUP_SETTINGS",Ge="FAILED_PATCH_BULK_GROUP_SETTINGS",Re=r("pPDe"),ke=Object(Re.a)(function(e){return Object(h.filter)(Object(h.map)(e.matchableIds,function(t){return e.matchablesById[t]}),h.isObject)},function(e){return[e.matchablesById,e.matchableIds]});function Ue(e,t){return(e.matchablesById[t]||{}).type}function Ae(e,t){return(e.matchablesById[t]||{}).label}var we=Object(Re.a)(function(e,t){return Object(h.filter)(Object(h.map)(e.queries[t],function(t){return e.byId[t]}),h.isObject)},function(e,t){return[e.queries[t],e.byId]}),je=[];function Ne(e,t){return e.queries[t]||je}function Ce(e,t){return e.byId[t]}function De(e,t,r){var n=Object(a.select)("ithemes-security/user-groups").getGroup(t);return n?n[r]:void 0}function Fe(e,t){return e.updating.includes(t)}function He(e,t){return e.deleting.includes(t)}function Le(e,t){return e.settings[t]}function Be(e,t,r,n){var u=Object(a.select)("ithemes-security/user-groups").getGroupSettings(t);return Object(h.get)(u,[r,n])}function qe(e,t){return e.updatingSettings.includes(t)}function Me(e,t,r){var n=t.join("_");return e.bulkPatchingSettings[n]===r}function Ye(e){var t={};for(var r in e.settings)if(e.settings.hasOwnProperty(r))for(var n in e.settings[r])if(e.settings[r].hasOwnProperty(n))for(var u in e.settings[r][n])e.settings[r][n].hasOwnProperty(u)&&(t[n]||(t[n]={}),t[n][u]||(t[n][u]=[]),e.settings[r][n][u]&&t[n][u].push(r));return t}var Qe=r("lSNA"),Ke=r.n(Qe),Ve=r("MVZn"),We=r.n(Ve),Je={matchablesById:{},matchableIds:[],byId:{},queries:{},creating:[],updating:[],deleting:[],settings:{},updatingSettings:[],bulkPatchingSettings:{}};var Ze={fulfill:regeneratorRuntime.mark(function e(t){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,p({path:"".concat(G,"/").concat(t,"?_embed=1")});case 2:return r=e.sent,e.next=5,w(r);case 5:return e.delegateYield(A(r),"t0",6);case 6:case"end":return e.stop()}},e,this)}),isFulfilled:function(e,t){return e.byId.hasOwnProperty(t)}},ze={fulfill:regeneratorRuntime.mark(function e(){var t,r,n,u,i,a,c,s,o;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,p({path:"/ithemes-security/v1/user-matchables?_embed=1"});case 2:return t=e.sent,e.next=5,j(t);case 5:r=!0,n=!1,u=void 0,e.prev=8,i=t[Symbol.iterator]();case 10:if(r=(a=i.next()).done){e.next=23;break}if(c=a.value,s=Object(h.get)(c,["_embedded","self",0]),o=Object(h.get)(c,["_embedded","ithemes-security:user-matchable-settings",0]),!s){e.next=17;break}return e.next=17,w(s);case 17:if(!o){e.next=20;break}return e.next=20,Y(c.id,o);case 20:r=!0,e.next=10;break;case 23:e.next=29;break;case 25:e.prev=25,e.t0=e.catch(8),n=!0,u=e.t0;case 29:e.prev=29,e.prev=30,r||null==i.return||i.return();case 32:if(e.prev=32,!n){e.next=35;break}throw u;case 35:return e.finish(32);case 36:return e.finish(29);case 37:case"end":return e.stop()}},e,this,[[8,25,29,37],[30,,32,36]])}),isFulfilled:function(e){return!Object(h.isEmpty)(e.matchablesById)}},Xe={fulfill:regeneratorRuntime.mark(function e(t){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,p({path:"ithemes-security/v1/user-matchable-settings/".concat(t)});case 2:return r=e.sent,e.next=5,Y(t,r);case 5:case"end":return e.stop()}},e,this)}),isFulfilled:function(e,t){return e.settings.hasOwnProperty(t)}},$e=Object(a.registerStore)("ithemes-security/user-groups",{controls:g,actions:n,selectors:u,resolvers:i,reducer:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Je,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case se:return We()({},e,{matchableIds:Object(h.map)(t.matchables,"id"),matchablesById:Object(h.keyBy)(t.matchables,"id")});case ae:return We()({},e,{byId:We()({},e.byId,Object(h.keyBy)(t.items,"id")),queries:We()({},e.queries,Ke()({},t.queryId,Object(h.map)(t.items,"id")))});case ce:return We()({},e,{byId:We()({},e.byId,Ke()({},t.item.id,t.item)),queries:We()({},e.queries,Ke()({},t.queryId,s()(e.queries[t.queryId]||[]).concat([t.item.id])))});case pe:return We()({},e,{byId:We()({},e.byId,Ke()({},t.group.id,t.group)),matchablesById:e.matchablesById[t.group.id]?We()({},e.matchablesById,Ke()({},t.group.id,We()({},e.matchablesById[t.group.id],{label:t.group.label}))):e.matchablesById});case oe:return We()({},e,{creating:s()(e.creating).concat([t.group])});case de:return We()({},e,{creating:e.creating.filter(function(e){return e!==t.group}),matchablesById:We()({},e.matchablesById,Ke()({},t.response.id,{id:t.response.id,label:t.response.label,type:"user-group"})),matchableIds:s()(e.matchableIds).concat([[t.response.id]])});case fe:return We()({},e,{creating:e.creating.filter(function(e){return e!==t.group})});case le:return We()({},e,{updating:s()(e.updating).concat([t.id])});case ge:case he:return We()({},e,{updating:e.updating.filter(function(e){return e!==t.id})});case be:return We()({},e,{deleting:s()(e.deleting).concat([t.id])});case ve:return We()({},e,{deleting:e.deleting.filter(function(e){return e!==t.id}),byId:Object(h.omit)(e.byId,[t.id]),matchablesById:Object(h.omit)(e.matchablesById,[t.id]),matchableIds:e.matchableIds.filter(function(e){return e!==t.id}),settings:Object(h.omit)(e.settings,[t.id])});case ye:return We()({},e,{deleting:e.deleting.filter(function(e){return e!==t.id})});case me:return We()({},e,{settings:We()({},e.settings,Ke()({},t.id,t.settings))});case _e:return We()({},e,{updatingSettings:s()(e.updatingSettings).concat([t.id])});case Ee:case Se:return We()({},e,{updatingSettings:e.updatingSettings.filter(function(e){return e!==t.id})});case Oe:return We()({},e,{bulkPatchingSettings:We()({},e.bulkPatchingSettings,Ke()({},t.groupIds.join("_"),t.patch))});case xe:case Ge:return We()({},e,{bulkPatchingSettings:Object(h.omit)(e.bulkPatchingSettings,[t.groupIds.join("_")])});default:return e}}});r.d(t,"store",function(){return $e}),r.p=window.itsecWebpackPublicPath},Td6G:function(e,t,r){"use strict";r("J4zp");var n=r("YLtl"),u=r("RIqP"),i=r.n(u),a=r("lwsE"),c=r.n(a),s=r("W8MJ"),o=r.n(s),d=r("lSNA"),f=r.n(d),p=r("92Nh"),l=r.n(p),g=r("tmk3"),h=r.n(g),b=function(){function e(){var t=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,u=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;c()(this,e),v.set(this,{writable:!0,value:{}}),y.set(this,{writable:!0,value:{}}),f()(this,"getErrorCodes",function(){return Object.keys(h()(t,v))}),f()(this,"getErrorCode",function(){return t.getErrorCodes()[0]}),f()(this,"getErrorMessages",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;if(e)return h()(t,v)[e];var r=[];for(var n in h()(t,v))h()(t,v).hasOwnProperty(n)&&r.concat(h()(t,v)[n]);return r}),f()(this,"getErrorMessage",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return e=e||t.getErrorCode(),t.getErrorMessages(e)[0]}),f()(this,"getErrorData",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return e=e||t.getErrorCode(),h()(t,y)[e]}),f()(this,"getAllErrorMessages",function(){var e=[];for(var r in h()(t,v))h()(t,v).hasOwnProperty(r)&&e.push.apply(e,i()(h()(t,v)[r]));return e}),r&&(n&&(h()(this,v)[r]=[n]),u&&(h()(this,y)[r]=u))}return o()(e,null,[{key:"fromPHPObject",value:function(t){var r=new e;return l()(r,v,t.errors),l()(r,y,t.error_data),r}},{key:"fromApiError",value:function(t){var r=new e;if(h()(r,v)[t.code]=[t.message],h()(r,y)[t.code]=t.data,t.additional_errors){var n=!0,u=!1,i=void 0;try{for(var a,c=t.additional_errors[Symbol.iterator]();!(n=(a=c.next()).done);n=!0){var s=a.value;h()(r,v)[s.code]=[s.message],h()(r,y)[s.code]=s.data}}catch(e){u=!0,i=e}finally{try{n||null==c.return||c.return()}finally{if(u)throw i}}}return r}}]),e}(),v=new WeakMap,y=new WeakMap,m=r("a1gu"),_=r.n(m),E=r("Nsbk"),S=r.n(E),I=r("7W2i"),T=r.n(I),P=r("PJYZ"),O=r.n(P),x=r("oShl"),G=r.n(x),R=r("l3Sj"),k=function(e){function t(e){var r,n;c()(this,t);for(var u=arguments.length,i=new Array(u>1?u-1:0),a=1;a<u;a++)i[a-1]=arguments[a];for(var s in n=_()(this,(r=S()(t)).call.apply(r,[this,e.message||Object(R.__)("An unknown error occurred.","better-wp-security")].concat(i))),Error.captureStackTrace&&Error.captureStackTrace(O()(O()(n)),t),n.__response=e,e)e.hasOwnProperty(s)&&Object.defineProperty(O()(O()(n)),s,{value:e[s],configurable:!0,enumerable:!0,writable:!0});return n}return T()(t,e),o()(t,[{key:"toString",value:function(){return this.__response.toString()}},{key:"getResponse",value:function(){return this.__response}}]),t}(G()(Error));function U(e){if(!Object(n.isPlainObject)(e))return!1;var t=Object.keys(e);return 2===t.length&&(t.includes("errors")&&t.includes("error_data"))}function A(e){return U(e)?b.fromPHPObject(e):function(e){if(!Object(n.isPlainObject)(e))return!1;var t=Object.keys(e);return(3===t.length||4===t.length)&&!(4===t.length&&!t.includes("additional_errors"))&&t.includes("code")&&t.includes("message")&&t.includes("data")}(e)?b.fromApiError(e):new b}function w(e,t){var r=[[],[]],n=!0,u=!1,i=void 0;try{for(var a,c=e[Symbol.iterator]();!(n=(a=c.next()).done);n=!0){var s=a.value;r[t(s)?0:1].push(s)}}catch(e){u=!0,i=e}finally{try{n||null==c.return||c.return()}finally{if(u)throw i}}return r}function j(e){if(e instanceof Error)throw e;throw new k(e)}r.d(t,"d",function(){return U}),r.d(t,"b",function(){return A}),r.d(t,"a",function(){return w}),r.d(t,"e",function(){return j}),r.d(t,"c",function(){return N});function N(e,t){if(e&&e.links){var r=!0,n=!1,u=void 0;try{for(var i,a=e.links[Symbol.iterator]();!(r=(i=a.next()).done);r=!0){var c=i.value;if(c.rel===t)return c}}catch(e){n=!0,u=e}finally{try{r||null==a.return||a.return()}finally{if(n)throw u}}}}},YLtl:function(e,t){!function(){e.exports=this.lodash}()},l3Sj:function(e,t){!function(){e.exports=this.wp.i18n}()},ywyh:function(e,t){!function(){e.exports=this.wp.apiFetch}()}});
|
dist/user-groups/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
dist/user-groups/settings.min.css
ADDED
@@ -0,0 +1,37 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.itsec-log-modal .components-modal__frame{min-width:80%;height:100%}.itsec-log-modal .itsec-log-modal__content{margin:2em 1em}.itsec-log-modal .itsec-log-modal__content .itsec-log-raw-details-toggle{display:none}.itsec-log-modal .itsec-log-modal__content tr:first-child th,.itsec-log-modal .itsec-log-modal__content tr:first-child td{margin-top:0;padding-top:0}
|
2 |
+
|
3 |
+
.itsec-malware-scan-results h4{margin-top:5px}.itsec-malware-scan-results ul{margin-left:20px}.itsec-malware-scan-results ul li{line-height:16px;list-style:outside none disc}.itsec-malware-scan-results .itsec-malware-scan-details pre{background-color:#eaeaea;padding:1em;white-space:pre-wrap}.itsec-malware-scan-results .itsec-malware-scan-results-section{border:1px solid #ddd;border-bottom-color:transparent;padding:0 1em}.itsec-malware-scan-results .itsec-malware-scan-results-section:last-child{border-bottom-color:#ddd}.itsec-malware-scan-results .itsec-malware-scan-clean,.itsec-malware-scan-results .itsec-malware-scan-warn,.itsec-malware-scan-results .itsec-malware-scan-error{padding:2px 6px;color:#fff;margin-right:1em;width:60px;text-align:center}.itsec-malware-scan-results span.itsec-malware-scan-clean,.itsec-malware-scan-results span.itsec-malware-scan-warn,.itsec-malware-scan-results span.itsec-malware-scan-error{display:inline-block}.itsec-malware-scan-results .itsec-malware-scan-clean{background:#7ad03a}.itsec-malware-scan-results .itsec-malware-scan-warn,.itsec-malware-scan-results .itsec-malware-scan-error{background:#dd3d36}.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-warn,.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-error,.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-clean{background:none;padding:0;color:inherit;margin:0;width:100%;text-align:left}.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-warn,.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-error{color:#dd3d36}.itsec-malware-scan-results .itsec-malware-scan-details .itsec-malware-scan-clean{color:#7ad03a}.itsec-malware-scan-results .itsec-malware-scan-results-section .itsec-malware-scan-details li{margin-bottom:.25em;padding-bottom:.5em;border-bottom:1px solid #ddd}.itsec-malware-scan-results .itsec-malware-scan-results-section .itsec-malware-scan-details li:last-child{border:none}.itsec-malware-scan-results .itsec-malware-scan-results-section .itsec-malware-scan-details li span{color:#444}.itsec-malware-scan-results .itsec-malware-scan-toggle-details{margin-left:1em}
|
4 |
+
|
5 |
+
.itsec-site-scan-results h4{margin-top:5px}.itsec-site-scan-results .itsec-site-scan-details pre{background-color:#eaeaea;padding:1em;white-space:pre-wrap}.itsec-site-scan-results .itsec-site-scan-results-section{border:1px solid #ddd;border-bottom-color:transparent;padding:1em}.itsec-site-scan-results .itsec-site-scan-results-section>p{margin:0}.itsec-site-scan-results .itsec-site-scan-results-section:last-child{border-bottom-color:#ddd}.itsec-site-scan-results .itsec-site-scan__status{display:inline-block;padding:2px 6px;color:#fff;margin-right:1em;width:60px;text-align:center}.itsec-site-scan-results .itsec-site-scan__status.itsec-site-scan__status--clean{background:#7ad03a}.itsec-site-scan-results .itsec-site-scan__status.itsec-site-scan__status--warn{background:#dd3d36}.itsec-site-scan-results .itsec-site-scan__status.itsec-site-scan__status--error{background:#dd3d36}.itsec-site-scan-results .itsec-site-scan__details ul{margin-left:2.5em;list-style:disc outside}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail{width:100%;margin-bottom:.25em;padding-bottom:.5em;color:inherit;border-bottom:1px solid #ddd}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail:last-child{border:none}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail.itsec-site-scan__detail--warn{color:#dd3d36}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail.itsec-site-scan__detail--error{color:#dd3d36}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail.itsec-site-scan__detail--clean{color:#7ad03a}.itsec-site-scan-results .itsec-site-scan__details .itsec-site-scan__detail span{color:#444}.itsec-site-scan-results .itsec-site-scan-toggle-details{margin-left:1em}
|
6 |
+
|
7 |
+
.itsec-component-print-r{background:#f1f1f1;overflow:scroll;padding:1em;color:black;font-family:"Courier New", Courier, monospace;font-size:12px;white-space:pre-wrap;text-align:left;max-width:100%}
|
8 |
+
|
9 |
+
.itsec-close-button.components-icon-button{padding:0;height:20px;position:absolute;right:1em;top:1em}.itsec-close-button.components-icon-button:hover{opacity:.5;box-shadow:none !important}.components-popover.is-mobile .itsec-close-button.components-icon-button{display:none}
|
10 |
+
|
11 |
+
.itsec-loader{margin:0 auto;display:flex;align-items:center;justify-content:center;height:100%}.itsec-loader svg{animation:itsec-loader__grow 3.0s infinite ease-in}@keyframes itsec-loader__grow{0%{transform:scale(0)}100%{transform:scale(1);opacity:0}}
|
12 |
+
|
13 |
+
.components-base-control>ul.components-hierarchical-checkbox-control__group{padding-left:0}ul.components-hierarchical-checkbox-control__group{padding-left:1em}.components-hierarchical-checkbox-control__group .components-hierarchical-checkbox-control__option{list-style-type:none}.components-hierarchical-checkbox-control__option--has-children{margin-bottom:1em}.components-hierarchical-checkbox-control__option--has-children>.components-base-control{font-weight:bold}
|
14 |
+
|
15 |
+
.itsec-module-settings-notice-list .notice .notice__action{margin-left:.5em}.itsec-module-settings-notice-list{position:relative;padding-bottom:1em;font-size:13px}.itsec-module-settings-notice-list:empty{display:none}.itsec-module-settings-content .components-editor-notices__snackbar{position:fixed;bottom:100px;padding-left:16px;padding-right:16px;width:-webkit-max-content;width:-moz-max-content;width:max-content}.itsec-module-settings-content .components-snackbar{width:-webkit-max-content;width:-moz-max-content;width:max-content}
|
16 |
+
|
17 |
+
.components-form-toggle__input:disabled+.components-form-toggle__track{opacity:.5}
|
18 |
+
|
19 |
+
.components-checkbox-control__input[type="checkbox"]{border:1px solid #b4b9be;background:#fff;color:#555;clear:none;cursor:pointer;display:inline-block;line-height:0;margin:0 4px 0 0;outline:0;padding:0 !important;text-align:center;vertical-align:top;width:25px;height:25px;-webkit-appearance:none;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);transition:0.05s border-color ease-in-out}@media (min-width: 600px){.components-checkbox-control__input[type="checkbox"]{height:16px;width:16px}}.components-checkbox-control__input[type="checkbox"]:focus{border-color:#5b9dd9;box-shadow:0 0 2px rgba(30,140,190,0.8);outline:2px solid transparent}.components-checkbox-control__input[type="checkbox"]:checked{background:#11a0d2;border-color:#11a0d2}.components-checkbox-control__input[type="checkbox"]:checked::-ms-check{opacity:0}.components-checkbox-control__input[type="checkbox"]:focus:checked{border:none}.components-checkbox-control__input[type="checkbox"]:checked::before{content:none}.components-checkbox-control__input-container{position:relative;display:inline-block;margin-right:12px;vertical-align:middle;width:25px;height:25px}@media (min-width: 600px){.components-checkbox-control__input-container{width:16px;height:16px}}svg.dashicon.components-checkbox-control__checked{fill:#fff;cursor:pointer;position:absolute;left:-4px;top:-2px;width:31px;height:31px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}@media (min-width: 600px){svg.dashicon.components-checkbox-control__checked{width:21px;height:21px;left:-3px}}.components-checkbox-control__input[type="checkbox"]:indeterminate{background:#11a0d2;border-color:#11a0d2}.components-checkbox-control__input[type="checkbox"]:indeterminate::-ms-check{opacity:0}.components-checkbox-control__input[type="checkbox"]:focus:checked,.components-checkbox-control__input[type="checkbox"]:focus:indeterminate{border:none}.components-checkbox-control__input[type="checkbox"]:checked::before,.components-checkbox-control__input[type="checkbox"]:indeterminate::before{content:none}svg.dashicon.components-checkbox-control__checked.components-checkbox-control__checked--indeterminate{width:16px;left:0}
|
20 |
+
|
21 |
+
.itsec-user-groups-list{display:grid;grid-template-columns:200px minmax(0, auto);grid-gap:1.25em;padding-bottom:2em}.itsec-user-groups-list>.components-tab-panel__tabs{display:flex;flex-direction:column;margin-top:2.2em}.itsec-user-groups-list__item{padding:1em .5em;margin:1.25em 0 0;border:1px solid #7e8993;border-radius:4px;text-align:left;height:auto}.itsec-user-groups-list__item.is-active{border-color:#007cba;box-shadow:0 0 0 1px #007cba;outline:2px solid transparent}.itsec-user-groups-list__item:first-child{margin-top:0}.itsec-user-groups-list__item:last-child{margin-bottom:0}.itsec-user-groups-list__item--new{justify-content:center;align-items:center}.itsec-user-groups-list__item--new .dashicon{margin-right:10px}
|
22 |
+
|
23 |
+
.itsec-manage-user-group-tabs{border:1px solid #7e8993;border-radius:4px}.itsec-manage-user-group-tabs .components-tab-panel__tabs{background:#f3f4f5;border-radius:4px 4px 0 0;display:flex;flex-basis:0}.itsec-manage-user-group-tabs__tab.components-button{flex-grow:1;flex-basis:0;height:40px;padding:3px 15px 0;border-bottom:1px solid #7e8993;border-right:1px solid #7e8993;cursor:pointer;font-weight:400;justify-content:center;align-items:center;text-transform:uppercase;outline-offset:-1px;border-radius:0}.itsec-manage-user-group-tabs__tab.components-button:hover{box-shadow:none !important}.itsec-manage-user-group-tabs__tab.components-button:first-child{border-top-left-radius:3px}.itsec-manage-user-group-tabs__tab.components-button:last-child{border-top-right-radius:3px;border-right:none}.itsec-manage-user-group-tabs__tab.components-button.is-active{padding-top:0;background:white;border-top:3px solid #0081E3;border-bottom-color:transparent;font-weight:600;outline:none}
|
24 |
+
|
25 |
+
.itsec-user-group-label h4{margin-top:0}
|
26 |
+
|
27 |
+
.itsec-user-groups-group-tab__row{padding:1em}.itsec-user-groups-group-tab__row--save{border-top:1px solid #7e8993;text-align:right}.itsec-user-groups-group-tab--is-loading{opacity:.5;pointer-events:none}
|
28 |
+
|
29 |
+
.itsec-user-groups-group-tab--settings .itsec-user-groups-group-tab__modules-list{padding-left:0}.itsec-user-groups-group-tab--settings ul{list-style-type:none}.itsec-user-groups-group-tab--settings legend{font-weight:600;margin-bottom:1em;font-size:1.2em}
|
30 |
+
|
31 |
+
.itsec-user-group-panel-users__selected span{padding-right:.5em}.components-itsec-async-select-control__input input{min-height:0}.components-itsec-async-select-control__input input:focus{box-shadow:none}
|
32 |
+
|
33 |
+
.itsec-user-group-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1em;height:1.2em}.itsec-user-group-header__label{margin:0 .5em 0 0;font-size:1.2em;line-height:1.2em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.itsec-user-group-header .components-button{flex-shrink:0}
|
34 |
+
|
35 |
+
.itsec-user-groups-group-tab__row--edit-fields>.components-base-control:first-child{margin-bottom:16px}.itsec-user-groups-group-tab__row--edit-fields .components-base-control__label{font-weight:600;margin-bottom:1em;font-size:1.2em}
|
36 |
+
|
37 |
+
|
dist/user-groups/settings.min.js
ADDED
@@ -0,0 +1,7 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
this.itsec=this.itsec||{},this.itsec["user-groups"]=this.itsec["user-groups"]||{},this.itsec["user-groups"].settings=function(e){function t(t){for(var n,i,o=t[0],s=t[1],c=0,u=[];c<o.length;c++)i=o[c],r[i]&&u.push(r[i][0]),r[i]=0;for(n in s)Object.prototype.hasOwnProperty.call(s,n)&&(e[n]=s[n]);for(a&&a(t);u.length;)u.shift()()}var n={},r={6:0,3:0};function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.e=function(e){var t=[],n=r[e];if(0!==n)if(n)t.push(n[2]);else{var o=new Promise(function(t,i){n=r[e]=[t,i]});t.push(n[2]=o);var s,c=document.createElement("script");c.charset="utf-8",c.timeout=120,i.nc&&c.setAttribute("nonce",i.nc),c.src=function(e){return i.p+""+({}[e]||e)+".min.js"}(e),s=function(t){c.onerror=c.onload=null,clearTimeout(a);var n=r[e];if(0!==n){if(n){var i=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src,s=new Error("Loading chunk "+e+" failed.\n("+i+": "+o+")");s.type=i,s.request=o,n[1](s)}r[e]=void 0}};var a=setTimeout(function(){s({type:"timeout",target:c})},12e4);c.onerror=c.onload=s,document.head.appendChild(c)}return Promise.all(t)},i.m=e,i.c=n,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var o=window.itsecWebpackJsonP=window.itsecWebpackJsonP||[],s=o.push.bind(o);o.push=t,o=o.slice();for(var c=0;c<o.length;c++)t(o[c]);var a=s;return i(i.s="epig")}({"+VN0":function(e,t,n){},"16Al":function(e,t,n){"use strict";var r=n("WbBG");function i(){}e.exports=function(){function e(e,t,n,i,o,s){if(s!==r){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return n.checkPropTypes=i,n.PropTypes=n,n}},"17x9":function(e,t,n){e.exports=n("16Al")()},"1ZqX":function(e,t){!function(){e.exports=this.wp.data}()},"31KZ":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.withErrorBoundary=void 0;var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=n("cDcd"),o=c(i),s=c(n("Xvx9"));function c(e){return e&&e.__esModule?e:{default:e}}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}var u=n("cDcd").babelPluginFlowReactPropTypes_proptype_ComponentType||n("17x9").any,l=function(e){function t(){var e,n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);for(var i=arguments.length,o=Array(i),s=0;s<i;s++)o[s]=arguments[s];return n=r=a(this,(e=t.__proto__||Object.getPrototypeOf(t)).call.apply(e,[this].concat(o))),r.state={error:null,info:null},a(r,n)}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,i.Component),r(t,[{key:"componentDidCatch",value:function(e,t){var n=this.props.onError;if("function"==typeof n)try{n.call(this,e,t?t.componentStack:"")}catch(e){}this.setState({error:e,info:t})}},{key:"render",value:function(){var e=this.props,t=e.children,n=e.FallbackComponent,r=this.state,i=r.error,s=r.info;return null!==i?o.default.createElement(n,{componentStack:s?s.componentStack:"",error:i}):t}}]),t}();l.defaultProps={FallbackComponent:s.default},l.propTypes={error:"function"==typeof Error?n("17x9").instanceOf(Error):n("17x9").any,info:n("17x9").shape({componentStack:n("17x9").string.isRequired})},(t.withErrorBoundary=function(e,t,n){return function(r){return o.default.createElement(l,{FallbackComponent:t,onError:n},o.default.createElement(e,r))}}).propTypes=u===n("17x9").any?{}:u,t.default=l},"4eJC":function(e,t,n){e.exports=function(e,t){var n,r,i,o=0;function s(){var t,s,c=r,a=arguments.length;e:for(;c;){if(c.args.length===arguments.length){for(s=0;s<a;s++)if(c.args[s]!==arguments[s]){c=c.next;continue e}return c!==r&&(c===i&&(i=c.prev),c.prev.next=c.next,c.next&&(c.next.prev=c.prev),c.next=r,c.prev=null,r.prev=c,r=c),c.val}c=c.next}for(t=new Array(a),s=0;s<a;s++)t[s]=arguments[s];return c={args:t,val:e.apply(null,t)},r?(r.prev=c,c.next=r):i=c,o===n?(i=i.prev).next=null:o++,r=c,c.val}return t&&t.maxSize&&(n=t.maxSize),s.clear=function(){r=null,i=null,o=0},s}},"6ECA":function(e,t,n){},"7W2i":function(e,t,n){var r=n("SksO");e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}},"8OQS":function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(i[n]=e[n]);return i}},"92Nh":function(e,t){e.exports=function(e,t,n){if(!t.has(e))throw new TypeError("attempted to set private field on non-instance");var r=t.get(e);if(!r.writable)throw new TypeError("attempted to set read only private field");return r.value=n,n}},A6yB:function(e,t,n){},Bnag:function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},DfSy:function(e,t,n){},Dfre:function(e,t,n){},ELjz:function(e,t,n){},EbDI:function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},GRId:function(e,t){!function(){e.exports=this.wp.element}()},"GjY+":function(e,t,n){},GrEf:function(e,t,n){},IXp0:function(e,t,n){},Ijbi:function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},J4zp:function(e,t,n){var r=n("wTVA"),i=n("m0LI"),o=n("wkBT");e.exports=function(e,t){return r(e)||i(e,t)||o()}},JVTk:function(e,t,n){var r=n("cDcd");function i(e){return r.createElement("svg",e,[r.createElement("defs",{key:0},r.createElement("style",null,".itsec-icon-logo-12f8d__path{fill:#1072ba;}.itsec-icon-logo-12f8d__path{fill:#69c;}")),r.createElement("g",{key:1},r.createElement("g",null,[r.createElement("path",{className:"itsec-icon-logo-12f8d__path",d:"M203.28,95V14.26a1.73,1.73,0,0,0-1.11-1.55c-4.38-1.44-21.5-6.6-46.22-8a1.1,1.1,0,0,0-1.17,1.11V20.1a1,1,0,0,1-1.16,1c-8-1.24-16.88-2.29-26.39-3a1.27,1.27,0,0,1-1.17-1.25V3a1.37,1.37,0,0,0-1.16-1.32A211.61,211.61,0,0,0,101,0,178.14,178.14,0,0,0,78.51,1.87a1.4,1.4,0,0,0-1.16,1.35V16.91a1.28,1.28,0,0,1-1.16,1.26c-9.51.72-18.34,1.78-26.38,3a1,1,0,0,1-1.16-1V5.79a1.1,1.1,0,0,0-1.17-1.11c-24.74,1.43-41.94,6.59-46.34,8A1.73,1.73,0,0,0,0,14.26V95s-2.3,54.32,34.61,97.07c32.69,37.86,60,46.91,65.84,48.5a5.16,5.16,0,0,0,2.28,0c5.82-1.58,33.16-10.63,65.83-48.5C205.51,149.35,203.28,95,203.28,95Z",key:0}),r.createElement("path",{className:"itsec-icon-logo-12f8d__path",d:"M101.38,68.5a21.75,21.75,0,1,0,21.7,21.81A21.77,21.77,0,0,0,101.38,68.5Z",key:1}),r.createElement("path",{className:"itsec-icon-logo-12f8d__path",d:"M182.44,87V42.75A1.92,1.92,0,0,0,181,41a385.2,385.2,0,0,0-78.26-8.05h-1.66a398.43,398.43,0,0,0-78.71,8.21,1.9,1.9,0,0,0-1.45,1.78l0,44.2v.24c0,3.27.09,54.82,33.38,93.35,18.71,21.67,35,33.81,46.15,40.44a2.79,2.79,0,0,0,2.56,0c11.14-6.61,27.36-18.74,46.12-40.45C183.22,141.12,182.46,87.63,182.44,87Zm-50.57,79.1c-2.69,3.13-5.32,6-7.87,8.69-.59.61-1.07.41-1.07-.44V155.78c0-14.05,13.64-21.19,18.14-23.17a2.49,2.49,0,0,0,1.42-2.11V116.39a1,1,0,0,0-1.41-.94c-37.93,15.49-72.25,3-79.51,0a.93.93,0,0,0-1.41.91V130.5a2.37,2.37,0,0,0,1.44,2.06c14.94,5.72,18,15.46,18,23.4v18.25c0,.85-.48,1-1.06.43-2.51-2.63-5.09-5.46-7.76-8.53-28.11-32.58-27.95-78.24-27.93-78.7V61.47a1.86,1.86,0,0,1,1.51-1.77,374.15,374.15,0,0,1,56.51-4.51h1.69a364.08,364.08,0,0,1,55.75,4.32,1.86,1.86,0,0,1,1.52,1.78v25.3C159.83,87.44,160.12,133.44,131.87,166.11Z",key:2})]))])}i.defaultProps={width:"200px",viewBox:"0 0 203.31 240.72"},e.exports=i,i.default=i},K9lf:function(e,t){!function(){e.exports=this.wp.compose}()},MVZn:function(e,t,n){var r=n("lSNA");e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),i.forEach(function(t){r(e,t,n[t])})}return e}},Mmq9:function(e,t){!function(){e.exports=this.wp.url}()},Nsbk:function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},PJYZ:function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},QILm:function(e,t,n){var r=n("8OQS");e.exports=function(e,t){if(null==e)return{};var n,i,o=r(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(i=0;i<s.length;i++)n=s[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}},QmYb:function(e,t,n){},QxRw:function(e,t,n){},RIqP:function(e,t,n){var r=n("Ijbi"),i=n("EbDI"),o=n("Bnag");e.exports=function(e){return r(e)||i(e)||o()}},SksO:function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},TSYQ:function(e,t,n){
|
2 |
+
/*!
|
3 |
+
Copyright (c) 2017 Jed Watson.
|
4 |
+
Licensed under the MIT License (MIT), see
|
5 |
+
http://jedwatson.github.io/classnames
|
6 |
+
*/
|
7 |
+
!function(){"use strict";var t={}.hasOwnProperty;function n(){for(var e=[],r=0;r<arguments.length;r++){var i=arguments[r];if(i){var o=typeof i;if("string"===o||"number"===o)e.push(i);else if(Array.isArray(i)&&i.length){var s=n.apply(null,i);s&&e.push(s)}else if("object"===o)for(var c in i)t.call(i,c)&&i[c]&&e.push(c)}}return e.join(" ")}e.exports?(n.default=n,e.exports=n):"function"==typeof define&&"object"==typeof define.amd&&define.amd?define("classnames",[],function(){return n}):window.classNames=n}()},Td6G:function(e,t,n){"use strict";n("J4zp");var r=n("YLtl"),i=n("RIqP"),o=n.n(i),s=n("lwsE"),c=n.n(s),a=n("W8MJ"),u=n.n(a),l=n("lSNA"),d=n.n(l),p=n("92Nh"),f=n.n(p),h=n("tmk3"),b=n.n(h),m=function(){function e(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;c()(this,e),v.set(this,{writable:!0,value:{}}),g.set(this,{writable:!0,value:{}}),d()(this,"getErrorCodes",function(){return Object.keys(b()(t,v))}),d()(this,"getErrorCode",function(){return t.getErrorCodes()[0]}),d()(this,"getErrorMessages",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;if(e)return b()(t,v)[e];var n=[];for(var r in b()(t,v))b()(t,v).hasOwnProperty(r)&&n.concat(b()(t,v)[r]);return n}),d()(this,"getErrorMessage",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return e=e||t.getErrorCode(),t.getErrorMessages(e)[0]}),d()(this,"getErrorData",function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0;return e=e||t.getErrorCode(),b()(t,g)[e]}),d()(this,"getAllErrorMessages",function(){var e=[];for(var n in b()(t,v))b()(t,v).hasOwnProperty(n)&&e.push.apply(e,o()(b()(t,v)[n]));return e}),n&&(r&&(b()(this,v)[n]=[r]),i&&(b()(this,g)[n]=i))}return u()(e,null,[{key:"fromPHPObject",value:function(t){var n=new e;return f()(n,v,t.errors),f()(n,g,t.error_data),n}},{key:"fromApiError",value:function(t){var n=new e;if(b()(n,v)[t.code]=[t.message],b()(n,g)[t.code]=t.data,t.additional_errors){var r=!0,i=!1,o=void 0;try{for(var s,c=t.additional_errors[Symbol.iterator]();!(r=(s=c.next()).done);r=!0){var a=s.value;b()(n,v)[a.code]=[a.message],b()(n,g)[a.code]=a.data}}catch(e){i=!0,o=e}finally{try{r||null==c.return||c.return()}finally{if(i)throw o}}}return n}}]),e}(),v=new WeakMap,g=new WeakMap,y=n("a1gu"),O=n.n(y),E=n("Nsbk"),j=n.n(E),_=n("7W2i"),w=n.n(_),S=n("PJYZ"),k=n.n(S),I=n("oShl"),x=n.n(I),N=n("l3Sj"),C=function(e){function t(e){var n,r;c()(this,t);for(var i=arguments.length,o=new Array(i>1?i-1:0),s=1;s<i;s++)o[s-1]=arguments[s];for(var a in r=O()(this,(n=j()(t)).call.apply(n,[this,e.message||Object(N.__)("An unknown error occurred.","better-wp-security")].concat(o))),Error.captureStackTrace&&Error.captureStackTrace(k()(k()(r)),t),r.__response=e,e)e.hasOwnProperty(a)&&Object.defineProperty(k()(k()(r)),a,{value:e[a],configurable:!0,enumerable:!0,writable:!0});return r}return w()(t,e),u()(t,[{key:"toString",value:function(){return this.__response.toString()}},{key:"getResponse",value:function(){return this.__response}}]),t}(x()(Error));function T(e){if(!Object(r.isPlainObject)(e))return!1;var t=Object.keys(e);return 2===t.length&&(t.includes("errors")&&t.includes("error_data"))}function R(e){return T(e)?m.fromPHPObject(e):function(e){if(!Object(r.isPlainObject)(e))return!1;var t=Object.keys(e);return(3===t.length||4===t.length)&&!(4===t.length&&!t.includes("additional_errors"))&&t.includes("code")&&t.includes("message")&&t.includes("data")}(e)?m.fromApiError(e):new m}function L(e,t){var n=[[],[]],r=!0,i=!1,o=void 0;try{for(var s,c=e[Symbol.iterator]();!(r=(s=c.next()).done);r=!0){var a=s.value;n[t(a)?0:1].push(a)}}catch(e){i=!0,o=e}finally{try{r||null==c.return||c.return()}finally{if(i)throw o}}return n}function P(e){if(e instanceof Error)throw e;throw new C(e)}n.d(t,"d",function(){return T}),n.d(t,"b",function(){return R}),n.d(t,"a",function(){return L}),n.d(t,"e",function(){return P}),n.d(t,"c",function(){return G});function G(e,t){if(e&&e.links){var n=!0,r=!1,i=void 0;try{for(var o,s=e.links[Symbol.iterator]();!(n=(o=s.next()).done);n=!0){var c=o.value;if(c.rel===t)return c}}catch(e){r=!0,i=e}finally{try{n||null==s.return||s.return()}finally{if(r)throw i}}}}},W8MJ:function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}},WbBG:function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},XO7p:function(e,t,n){},Xvx9:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,i=n("cDcd"),o=(r=i)&&r.__esModule?r:{default:r};var s=function(e,t){return e.toString()+"\n\nThis is located at:"+t},c=function(e){var t=e.componentStack,n=e.error;return o.default.createElement("div",{style:a,title:s(n,t)},o.default.createElement("svg",{style:u,viewBox:"0 0 24 24",preserveAspectRatio:"xMidYMid"},o.default.createElement("path",{d:"M20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,\n 12M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,\n 12M15.5,8C16.3,8 17,8.7 17,9.5C17,10.3 16.3,11 15.5,11C14.7,11 14,10.3 14,\n 9.5C14,8.7 14.7,8 15.5,8M10,9.5C10,10.3 9.3,11 8.5,11C7.7,11 7,10.3 7,9.5C7,\n 8.7 7.7,8 8.5,8C9.3,8 10,8.7 10,9.5M12,14C13.75,14 15.29,14.72 16.19,\n 15.81L14.77,17.23C14.32,16.5 13.25,16 12,16C10.75,16 9.68,16.5 9.23,\n 17.23L7.81,15.81C8.71,14.72 10.25,14 12,14Z"})))};c.propTypes={componentStack:n("17x9").string.isRequired,error:"function"==typeof Error?n("17x9").instanceOf(Error).isRequired:n("17x9").any.isRequired};var a={height:"100%",maxHeight:"100vh",width:"100%",maxWidth:"100vw",display:"flex",flexDirection:"column",alignItems:"center",textAlign:"center",backgroundColor:"#C00",color:"#FFF",boxSizing:"border-box",cursor:"help"},u={fill:"currentColor",flex:"1 1 auto"};t.default=c},Y0od:function(e,t,n){},Y8OO:function(e,t){!function(){e.exports=this.wp.domReady}()},YLtl:function(e,t){!function(){e.exports=this.lodash}()},ZRc3:function(e,t,n){},a1gu:function(e,t,n){var r=n("cDf5"),i=n("PJYZ");e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?i(e):t}},"bJT+":function(e,t,n){},cDcd:function(e,t){!function(){e.exports=this.React}()},cDf5:function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(t){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?e.exports=r=function(e){return n(e)}:e.exports=r=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":n(e)},r(t)}e.exports=r},epig:function(e,t,n){"use strict";n.r(t);var r={};n.r(r),n.d(r,"getUser",function(){return w}),n.d(r,"getIndex",function(){return S}),n.d(r,"getSchema",function(){return k}),n.d(r,"getRoles",function(){return I});var i={};n.r(i),n.d(i,"fetchIndex",function(){return N}),n.d(i,"receiveIndex",function(){return C}),n.d(i,"receiveUser",function(){return T}),n.d(i,"RECEIVE_INDEX",function(){return R}),n.d(i,"RECEIVE_USER",function(){return L});var o={};n.r(o),n.d(o,"getIndex",function(){return G}),n.d(o,"getUser",function(){return A});var s={};n.r(s),n.d(s,"selectGroup",function(){return ze}),n.d(s,"editGroup",function(){return Je}),n.d(s,"saveGroup",function(){return Ye}),n.d(s,"resetEdits",function(){return Ze}),n.d(s,"createGroup",function(){return Xe}),n.d(s,"editGroupSetting",function(){return Qe}),n.d(s,"saveGroupSettings",function(){return et}),n.d(s,"bulkEditGroupSetting",function(){return tt}),n.d(s,"resetBulkGroupSettingEdit",function(){return nt}),n.d(s,"resetBulkGroupSettingEdits",function(){return rt}),n.d(s,"saveBulkEdits",function(){return it}),n.d(s,"SELECT_GROUP",function(){return ot}),n.d(s,"EDIT_GROUP",function(){return st}),n.d(s,"RESET_EDITS",function(){return ct}),n.d(s,"START_SAVE_GROUP",function(){return at}),n.d(s,"FINISH_SAVE_GROUP",function(){return ut}),n.d(s,"FAILED_SAVE_GROUP",function(){return lt}),n.d(s,"START_CREATE_GROUP",function(){return dt}),n.d(s,"FINISH_CREATE_GROUP",function(){return pt}),n.d(s,"FAILED_CREATE_GROUP",function(){return ft}),n.d(s,"EDIT_GROUP_SETTING",function(){return ht}),n.d(s,"START_SAVE_GROUP_SETTINGS",function(){return bt}),n.d(s,"FINISH_SAVE_GROUP_SETTINGS",function(){return mt}),n.d(s,"FAILED_SAVE_GROUP_SETTINGS",function(){return vt}),n.d(s,"BULK_EDIT_GROUP_SETTING",function(){return gt}),n.d(s,"RESET_BULK_GROUP_SETTING_EDIT",function(){return yt}),n.d(s,"RESET_BULK_GROUP_SETTING_EDITS",function(){return Ot});var c={};n.r(c),n.d(c,"getSelectedGroup",function(){return Et}),n.d(c,"isCreating",function(){return jt}),n.d(c,"getEditedGroup",function(){return _t}),n.d(c,"getEditedGroupAttribute",function(){return wt}),n.d(c,"hasEdits",function(){return St}),n.d(c,"settingHasEdits",function(){return kt}),n.d(c,"getEditedGroupSettings",function(){return It}),n.d(c,"getEditedGroupSetting",function(){return xt}),n.d(c,"hasBulkSettingEdits",function(){return Nt}),n.d(c,"getBulkSettingEdits",function(){return Ct}),n.d(c,"getBulkSettingEdit",function(){return Tt}),n.d(c,"getBulkSettingValue",function(){return Rt}),n.d(c,"isSavingBulkEdits",function(){return Lt}),n.d(c,"getAvailableGroups",function(){return Pt});var a={};n.r(a),n.d(a,"getAvailableGroups",function(){return At});var u=n("GRId"),l=n("l3Sj"),d=n("Y8OO"),p=n.n(d),f=(n("onLe"),n("1ZqX")),h=n("RIqP"),b=n.n(h),m=n("MVZn"),v=n.n(m),g=n("YLtl"),y=n("ywyh"),O=n.n(y),E=n("Td6G");function j(e){return{type:"API_FETCH",request:e}}var _={API_FETCH:function(e){var t=e.request;return O()(t).catch(E.e)},SELECT:function(e){var t=e.storeKey,n=e.selectorName,r=e.args,i=Object(f.select)(t)[n];return i.hasResolver?function(e){var t=e.storeKey,n=e.selectorName,r=e.args;return new Promise(function(e){var i=function(){return Object(f.select)("core/data").hasFinishedResolution(t,n,r)},o=function(){return Object(f.select)(t)[n].apply(null,r)},s=o();if(i())return e(s);var c=Object(f.subscribe)(function(){i()&&(c(),e(o()))})})}({storeKey:t,selectorName:n,args:r}):i.apply(void 0,b()(r))},DISPATCH:function(e){var t,n=e.storeKey,r=e.actionName,i=e.args;return(t=Object(f.dispatch)(n))[r].apply(t,b()(i))},CREATE_NOTICE:function(e){var t=e.status,n=e.content,r=e.options;r.autoDismiss&&(r.id=r.id||Object(g.uniqueId)("itsec-auto-dismiss-"),setTimeout(function(){return Object(f.dispatch)("core/notices").removeNotice(r.id,r.context)},r.autoDismiss)),Object(f.dispatch)("core/notices").createNotice(t,n,r)}};function w(e,t){return e.users.byId[t]}function S(e){return e.index}function k(e,t){var n=Object(f.select)("ithemes-security/core").getIndex();if(!n)return null;for(var r in n.routes)if(n.routes.hasOwnProperty(r)){var i=n.routes[r].schema;if(i&&i.title===t)return i}return null}function I(){var e=Object(f.select)("ithemes-security/core").getIndex();return e?e.roles:null}var x=regeneratorRuntime.mark(N);function N(){var e,t,n,r=arguments;return regeneratorRuntime.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:return e=r.length>0&&void 0!==r[0]&&r[0],t="/ithemes-security/v1?context=help",e&&(t+="&_="+Date.now()),i.next=5,j({path:t});case 5:return n=i.sent,i.next=8,C(n);case 8:return i.abrupt("return",n);case 9:case"end":return i.stop()}},x,this)}function C(e){return{type:R,index:e}}function T(e){return{type:L,user:e}}var R="RECEIVE_INDEX",L="RECEIVE_USER",P=regeneratorRuntime.mark(G);function G(){var e;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,j({path:"/ithemes-security/v1?context=help"});case 2:return e=t.sent,t.next=5,C(e);case 5:case"end":return t.stop()}},P,this)}var A={fulfill:regeneratorRuntime.mark(function e(t){var n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,j({path:"/wp/v2/users/".concat(t)});case 2:return n=e.sent,e.next=5,T(n);case 5:case"end":return e.stop()}},e,this)}),isFulfilled:function(e,t){return!!e.users.byId[t]}},D=n("lSNA"),M=n.n(D),B={users:{byId:{}},index:null};Object(f.registerStore)("ithemes-security/core",{controls:_,selectors:r,resolvers:o,actions:i,reducer:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:B,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case R:return v()({},e,{index:t.index});case L:return v()({},e,{users:v()({},e.users,{byId:v()({},e.users.byId,M()({},t.user.id,t.user))})});default:return e}}});n("sPxh");var U=n("lwsE"),H=n.n(U),V=n("W8MJ"),F=n.n(V),K=n("a1gu"),W=n.n(K),$=n("Nsbk"),q=n.n($),z=n("7W2i"),J=n.n(z),Y=n("PJYZ"),Z=n.n(Y),X=n("tI+e");n("6ECA");function Q(e,t,n){if(e!==t)throw new TypeError("Private static access of wrong provenance");return n.value}u.Component;var ee={writable:!0,value:{}},te=n("TSYQ"),ne=n.n(te),re=n("K9lf");Object(re.compose)([Object(re.withState)({isShowing:!1}),re.withInstanceId])(function(e){var t,n=e.type,r=e.status,i=e.description,o=e.isShowing,s=e.setState,c=e.instanceId,a=e.children;switch(r){case"clean":t=Object(l.__)("Clean","better-wp-security");break;case"warn":t=Object(l.__)("Warn","better-wp-security");break;case"error":t=Object(l.__)("Error","better-wp-security");break;default:t=r}var d=Object(u.createElement)("span",{className:"itsec-malware-scan-".concat(r)},t);return Object(u.createElement)("div",{className:ne()("itsec-malware-scan-results-section","itsec-malware-scan-results-".concat(n,"-section"))},Object(g.isEmpty)(a)?Object(u.createElement)("p",null,d," ",i):Object(u.createElement)(u.Fragment,null,Object(u.createElement)("p",null,d,i,Object(u.createElement)(X.Button,{isLink:!0,className:"itsec-malware-scan-toggle-details",onClick:function(){return s({isShowing:!o})},"aria-expanded":o,"aria-controls":"itsec-malware-scan-details--".concat(c)},o?Object(l.__)("Hide Details","better-wp-security"):Object(l.__)("Show Details","better-wp-security"))),Object(u.createElement)("div",{className:"itsec-malware-scan-details",id:"itsec-malware-scan-details--".concat(c),style:{display:o?"block":"none"}},a)))});var ie=n("J4zp"),oe=n.n(ie);n("rmEH");n("A6yB");function se(e){var t=e.id,n=e.isVisible,r=e.children;return Object(u.createElement)("div",{className:"itsec-site-scan__details",id:t,style:{display:n?"block":"none"}},Object(u.createElement)("ul",null,r))}Object(re.compose)([Object(re.withState)({isShowing:!1}),re.withInstanceId])(function(e){var t,n=e.type,r=e.status,i=e.description,o=e.isShowing,s=e.setState,c=e.instanceId,a=e.children;switch(r){case"clean":t=Object(l.__)("Clean","better-wp-security");break;case"warn":t=Object(l.__)("Warn","better-wp-security");break;case"error":t=Object(l.__)("Error","better-wp-security");break;default:t=r}var d=Object(u.createElement)("span",{className:"itsec-site-scan__status itsec-site-scan__status--".concat(r)},t);return Object(u.createElement)("div",{className:ne()("itsec-site-scan-results-section","itsec-site-scan-results-".concat(n,"-section"))},Object(g.isEmpty)(a)?Object(u.createElement)("p",null,d," ",i):Object(u.createElement)(u.Fragment,null,Object(u.createElement)("p",null,d,i,Object(u.createElement)(X.Button,{isLink:!0,className:"itsec-site-scan-toggle-details",onClick:function(){return s({isShowing:!o})},"aria-expanded":o,"aria-controls":"itsec-site-scan__details--".concat(c)},o?Object(l.__)("Hide Details","better-wp-security"):Object(l.__)("Show Details","better-wp-security"))),Object(u.createElement)(se,{id:"itsec-site-scan__details--".concat(c),isVisible:o},a)))});var ce=n("4eJC"),ae=n.n(ce);ae()(function(e){return b()(e).sort(function(e,t){return"blacklisted"===e.status&&"blacklisted"!==t.status?-1:"blacklisted"!==e.status&&"blacklisted"===t.status?1:0})});n("oaS/");n("bJT+");var ue=n("QILm"),le=n.n(ue),de=n("cDcd"),pe=n("urxu"),fe=n.n(pe),he=Object(de.lazy)(function(){return n.e(8).then(n.t.bind(null,"H0AD",7))});function be(){return Object(u.createElement)("span",null,Object(l.__)("Error when loading. Please refresh.","better-wp-security"))}function me(e){var t=e.addErrorBoundary,n=void 0===t||t,r=le()(e,["addErrorBoundary"]),i=Object(u.createElement)(de.Suspense,{fallback:Object(u.createElement)(X.Spinner,null)},Object(u.createElement)(he,r));return n?Object(u.createElement)(fe.a,{FallbackComponent:be},i):i}var ve=function(){},ge=function(e){function t(e){var n;return H()(this,t),(n=W()(this,q()(t).call(this,e))).state={isHovering:!1},n.onMouseEnter=n.onMouseEnter.bind(Z()(Z()(n))),n.onMouseLeave=n.onMouseLeave.bind(Z()(Z()(n))),n.onMouseOver=n.onMouseOver.bind(Z()(Z()(n))),n.onMouseOut=n.onMouseOut.bind(Z()(Z()(n))),n.setIsHovering=n.setIsHovering.bind(Z()(Z()(n))),n.unsetIsHovering=n.unsetIsHovering.bind(Z()(Z()(n))),n.componentWillUnmount=n.componentWillUnmount.bind(Z()(Z()(n))),n.timerIds=[],n}return J()(t,e),F()(t,[{key:"onMouseEnter",value:function(e){this.props.onMouseEnter({e:e,setIsHovering:this.setIsHovering,unsetIsHovering:this.unsetIsHovering})}},{key:"onMouseLeave",value:function(e){this.props.onMouseLeave({e:e,setIsHovering:this.setIsHovering,unsetIsHovering:this.unsetIsHovering})}},{key:"onMouseOver",value:function(e){this.props.onMouseOver({e:e,setIsHovering:this.setIsHovering,unsetIsHovering:this.unsetIsHovering})}},{key:"onMouseOut",value:function(e){this.props.onMouseOut({e:e,setIsHovering:this.setIsHovering,unsetIsHovering:this.unsetIsHovering})}},{key:"componentWillUnmount",value:function(){this.clearTimers()}},{key:"setIsHovering",value:function(){var e=this;this.clearTimers();var t=setTimeout(function(){var t={isHovering:!0};e.setState(t,function(){e.props.onHoverChanged(t)})},this.props.hoverDelayInMs);this.timerIds.push(t)}},{key:"unsetIsHovering",value:function(){var e=this;this.clearTimers();var t=setTimeout(function(){var t={isHovering:!1};e.setState(t,function(){e.props.onHoverChanged(t)})},this.props.hoverOffDelayInMs);this.timerIds.push(t)}},{key:"clearTimers",value:function(){for(var e=this.timerIds;e.length;)clearTimeout(e.pop())}},{key:"render",value:function(){var e=this.props,t=e.children,n=e.className;return Object(u.createElement)("div",{className:n,onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave,onMouseOver:this.onMouseOver,onMouseOut:this.onMouseOut},t)}}]),t}(u.Component);M()(ge,"displayName","HoverDetector"),M()(ge,"defaultProps",{hoverDelayInMs:0,hoverOffDelayInMs:0,onHoverChanged:ve,onMouseEnter:function(e){return(0,e.setIsHovering)()},onMouseLeave:function(e){return(0,e.unsetIsHovering)()},onMouseOver:ve,onMouseOut:ve,shouldDecorateChildren:!0});n("QxRw");n("JVTk"),n("lSb6");var ye=n("pVnL"),Oe=n.n(ye);n("Dfre");var Ee=Symbol.iterator,je=function(){function e(t,n,r){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:[];H()(this,e),M()(this,"tree",void 0),M()(this,"name",void 0),M()(this,"data",void 0),M()(this,"parent",void 0),M()(this,"children",void 0),this.tree=t,this.name=n,this.data=r,this.parent=i,this.children=o}return F()(e,[{key:"getParent",value:function(){return this.parent?this.tree.nodes[this.parent]:null}},{key:"getAllParents",value:function(){for(var e=[],t=this.getParent();t;)e.push(t.name),t=t.getParent();return e}},{key:"hasChildren",value:function(){return this.children.length>0}},{key:"getAllChildren",value:function(){var e=[];if(!this.hasChildren())return e;var t=!0,n=!1,r=void 0;try{for(var i,o=this[Symbol.iterator]();!(t=(i=o.next()).done);t=!0){var s=i.value;e.push.apply(e,[s.name].concat(b()(s.getAllChildren())))}}catch(e){n=!0,r=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw r}}return e}},{key:Ee,value:regeneratorRuntime.mark(function e(){var t,n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:t=0;case 1:if(!(t<this.children.length)){e.next=8;break}return n=this.children[t],e.next=5,this.tree.nodes[n];case 5:t++,e.next=1;break;case 8:case"end":return e.stop()}},e,this)})}]),e}(),_e=Symbol.iterator,we=function(){function e(){H()(this,e),M()(this,"nodes",{}),M()(this,"ordered",[])}return F()(e,[{key:"add",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;this.ordered.push(e),this.nodes[e]?(this.nodes[e].data=t,this.nodes[e].parent=n):this.nodes[e]=new je(this,e,t,n),n&&(this.nodes[n]?this.nodes[n].children.push(e):this.nodes[n]=new je(this,n))}},{key:_e,value:regeneratorRuntime.mark(function e(){var t,n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:t=0;case 1:if(!(t<this.ordered.length)){e.next=9;break}if(n=this.ordered[t],this.nodes[n].parent){e.next=6;break}return e.next=6,this.nodes[n];case 6:t++,e.next=1;break;case 9:case"end":return e.stop()}},e,this)})}]),e}(),Se=ae()(function(e){var t=new we,n=!0,r=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(n=(o=s.next()).done);n=!0){var c=o.value;t.add(c.value,c,c.parent)}}catch(e){r=!0,i=e}finally{try{n||null==s.return||s.return()}finally{if(r)throw i}}return t}),ke=function(e){function t(){var e;return H()(this,t),e=W()(this,q()(t).apply(this,arguments)),M()(Z()(Z()(e)),"props",void 0),e.renderOption=e.renderOption.bind(Z()(Z()(e))),e.isChecked=e.isChecked.bind(Z()(Z()(e))),e.isIndeterminate=e.isIndeterminate.bind(Z()(Z()(e))),e.onChange=e.onChange.bind(Z()(Z()(e))),e}return J()(t,e),F()(t,[{key:"indeterminate",value:function(e){e.indeterminate=!0}},{key:"isChecked",value:function(e){return!!e&&(Object(g.isArray)(this.props.value)?this.props.value.includes(e.name)||this.isChecked(e.getParent()):this.props.value[e.name]||this.isChecked(e.getParent()))}},{key:"isIndeterminate",value:function(e){if(!e.hasChildren())return!1;var t=!0,n=!1,r=void 0;try{for(var i,o=e[Symbol.iterator]();!(t=(i=o.next()).done);t=!0){var s=i.value;if(this.isChecked(s))return!0;if(this.isIndeterminate(s))return!0}}catch(e){n=!0,r=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw r}}return!1}},{key:"onChange",value:function(e,t){var n,r=[e.name].concat(b()(e.getAllChildren())),i=t?[]:e.getAllParents();Object(g.isArray)(this.props.value)?(n=t?b()(this.props.value).concat(b()(r)):this.props.value.filter(function(e){return!r.includes(e)&&!i.includes(e)}),this.props.onChange(n)):this.props.onChange(v()({},this.props.value,r.reduce(function(e,n){return e[n]=t},{}),i.reduce(function(e,t){return e[t]=!1},{})))}},{key:"render",value:function(){var e=this.props,t=e.label,n=e.help,r=e.options,i=Se(r);return Object(u.createElement)("fieldset",{className:"components-base-control"},Object(u.createElement)("div",{className:"components-base-control__field"},Object(u.createElement)("legend",{className:"components-base-control__label"},t),n&&Object(u.createElement)("p",{className:"components-base-control__help"},n)),Object(u.createElement)("ul",{className:"components-hierarchical-checkbox-control__group"},Array.from(i,this.renderOption)))}},{key:"renderOption",value:function(e){var t=this,n=e.data,r=n.value,i=n.selectable,o=void 0===i||i,s=le()(n,["value","selectable"]),c=this.isChecked(e),a=!c&&this.isIndeterminate(e);return Object(u.createElement)("li",{key:r,className:ne()("components-hierarchical-checkbox-control__option",{"components-hierarchical-checkbox-control__option--has-children":e.hasChildren()})},Object(u.createElement)(Ce,Oe()({},s,{checked:!!o&&c,disabled:!o||this.props.disabled,indeterminate:a,onChange:function(n){return t.onChange(e,n)}})),e.hasChildren()&&Object(u.createElement)("ul",{className:"components-hierarchical-checkbox-control__group"},Array.from(e,this.renderOption)))}}]),t}(u.Component);Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.context,r=void 0===n?"ithemes-security":n;return{notices:e("core/notices").getNotices(r)}}),Object(f.withDispatch)(function(e,t){var n=t.context,r=void 0===n?"ithemes-security":n;return{onRemove:function(t){return e("core/notices").removeNotice(t,r)}}})])(function(e){var t=e.notices,n=e.onRemove,r=Object(g.filter)(t,function(e){return e.isDismissible&&(!e.type||"default"===e.type)}),i=Object(g.filter)(t,function(e){return!(e.isDismissible||e.type&&"default"!==e.type)}),o=X.SnackbarList?Object(g.filter)(t,{type:"snackbar"}):[];return Object(u.createElement)(u.Fragment,null,Object(u.createElement)(X.NoticeList,{notices:i,className:"components-editor-notices__pinned"}),Object(u.createElement)(X.NoticeList,{notices:r,className:"components-editor-notices__dismissible",onRemove:n}),X.SnackbarList&&Object(u.createElement)(X.SnackbarList,{notices:o,className:"components-editor-notices__snackbar",onRemove:n}))});var Ie=function(e){var t=e.className,n=e.status,r=e.children,i=e.onRemove,o=void 0===i?g.noop:i,s=e.isDismissible,c=void 0===s||s,a=e.actions,d=void 0===a?[]:a,p=ne()(t,"notice","notice-alt","notice-"+n,{"is-dismissible":c});return Object(u.createElement)("div",{className:p},Object(u.createElement)("p",null,r,d.map(function(e,t){var n=e.className,r=e.label,i=e.onClick,s=e.url,c=e.isLink,a=void 0!==c&&c;return Object(u.createElement)(X.Button,{key:t,href:s,isSmall:!a&&!s,isLink:a||s,onClick:s?void 0:function(){o(),i()},className:ne()("notice__action",n)},r)})),c&&Object(u.createElement)("button",{type:"button",className:"notice-dismiss",onClick:o},Object(u.createElement)("span",{className:"screen-reader-text"},Object(l.__)("Dismiss this notice","better-wp-security"))))};n("+VN0");var xe=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.context,r=void 0===n?"ithemes-security":n;return{notices:e("core/notices").getNotices(r)}}),Object(f.withDispatch)(function(e,t){var n=t.context,r=void 0===n?"ithemes-security":n;return{onRemove:function(t){return e("core/notices").removeNotice(t,r)}}})])(function(e){var t,n,r=e.notices,i=e.onRemove,o=function(e){if(!X.SnackbarList)return e.length;var t=0,n=!0,r=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(n=(o=s.next()).done);n=!0)"snackbar"!==o.value.type&&t++}catch(e){r=!0,i=e}finally{try{n||null==s.return||s.return()}finally{if(r)throw i}}return t}(r),s=(t=o,n=Object(u.useRef)(),Object(u.useEffect)(function(){n.current=t}),n.current);Object(u.useEffect)(function(){o>s&&window.itsecSettingsPage&&window.itsecSettingsPage.scrollTop()},[o,s]);var c=X.SnackbarList?Object(g.filter)(r,{type:"snackbar"}):[];return Object(u.createElement)(u.Fragment,null,Object(u.createElement)("div",{className:"itsec-module-settings-notice-list"},r.map(function(e){return"snackbar"===e.type&&X.SnackbarList?null:Object(u.createElement)(Ie,Oe()({},Object(g.omit)(e,["content"]),{key:e.id,onRemove:(t=e.id,function(){return i(t)})}),e.content);var t})),X.SnackbarList&&Object(u.createElement)(X.SnackbarList,{notices:c,className:"components-editor-notices__snackbar",onRemove:i}))}),Ne=(n("DfSy"),function(e){function t(){var e;return H()(this,t),(e=W()(this,q()(t).apply(this,arguments))).onChange=e.onChange.bind(Z()(Z()(e))),e}return J()(t,e),F()(t,[{key:"onChange",value:function(e){this.props.onChange&&this.props.onChange(e.target.checked)}},{key:"render",value:function(){var e,t,n=this.props,r=n.label,i=n.checked,o=n.help,s=n.instanceId,c=le()(n,["label","checked","help","instanceId"]),a="inspector-toggle-control-".concat(s);return o&&(e=a+"__help",t=Object(g.isFunction)(o)?o(i):o),Object(u.createElement)(X.BaseControl,{id:a,help:t,className:"components-toggle-control"},Object(u.createElement)(X.FormToggle,Oe()({},c,{id:a,checked:i,onChange:this.onChange,"aria-describedby":e})),Object(u.createElement)("label",{htmlFor:a,className:"components-toggle-control__label"},r))}}]),t}(u.Component));Object(re.withInstanceId)(Ne),n("IXp0");var Ce=Object(re.withInstanceId)(function(e){var t=e.label,n=e.className,r=e.heading,i=e.checked,o=e.help,s=e.instanceId,c=e.onChange,a=e.indeterminate,l=le()(e,["label","className","heading","checked","help","instanceId","onChange","indeterminate"]),d="inspector-checkbox-control-".concat(s);return Object(u.createElement)(X.BaseControl,{label:r,id:d,help:o,className:n},Object(u.createElement)("span",{className:"components-checkbox-control__input-container"},Object(u.createElement)("input",Oe()({id:d,className:"components-checkbox-control__input",type:"checkbox",value:"1",onChange:function(e){return c(e.target.checked)},checked:i,"aria-describedby":o?d+"__help":void 0,ref:function(e){e&&(e.indeterminate=a)}},l)),i?Object(u.createElement)(X.Dashicon,{icon:"yes",className:"components-checkbox-control__checked",role:"presentation"}):null,a?Object(u.createElement)(X.Dashicon,{icon:"minus",className:"components-checkbox-control__checked components-checkbox-control__checked--indeterminate",role:"presentation"}):null),Object(u.createElement)("label",{className:"components-checkbox-control__label",htmlFor:d},t))});function Te(e){var t=e.tabId,n=e.onClick,r=e.children,i=e.selected,o=le()(e,["tabId","onClick","children","selected"]);return Object(u.createElement)(X.Button,Oe()({role:"tab",tabIndex:i?null:-1,"aria-selected":i,id:t,onClick:n},o),r)}var Re=function(e){function t(){var e;return H()(this,t),(e=W()(this,q()(t).apply(this,arguments))).handleClick=e.handleClick.bind(Z()(Z()(e))),e.onNavigate=e.onNavigate.bind(Z()(Z()(e))),e.onKeyDown=e.onKeyDown.bind(Z()(Z()(e))),e}return J()(t,e),F()(t,[{key:"handleClick",value:function(e){var t=this.props.onSelect;(void 0===t?g.noop:t)(e)}},{key:"onNavigate",value:function(e,t){var n=this.event;n&&"tab"===n.target.getAttribute("role")&&n.preventDefault(),t.click()}},{key:"onKeyDown",value:function(e){this.event=e}},{key:"render",value:function(){var e=this,t=this.props,n=t.activeClass,r=void 0===n?"is-active":n,i=t.className,o=t.instanceId,s=t.orientation,c=void 0===s?"horizontal":s,a=t.tabs,l=t.selected,d=Object(g.find)(a,{name:l})||a[0],p=o+"-"+d.name;return Object(u.createElement)("div",{className:i},Object(u.createElement)(X.NavigableMenu,{role:"tablist",orientation:c,onNavigate:this.onNavigate,onKeyDown:this.onKeyDown,className:"components-tab-panel__tabs"},a.map(function(t){return Object(u.createElement)(Te,{className:ne()(t.className,M()({},r,t.name===d.name)),tabId:o+"-"+t.name,"aria-controls":o+"-"+t.name+"-view",selected:t.name===d.name,key:t.name,onClick:Object(g.partial)(e.handleClick,t.name)},t.title)})),d&&Object(u.createElement)("div",{"aria-labelledby":p,role:"tabpanel",id:p+"-view",className:"components-tab-panel__tab-content",tabIndex:"0"},this.props.children(d)))}}]),t}(u.Component),Le=Object(re.withInstanceId)(Re),Pe=n("rl8x"),Ge=n.n(Pe);Object(re.createHigherOrderComponent)(function(e){var t,n;return n=t=function(t){function n(){var e,t;H()(this,n);for(var r=arguments.length,i=new Array(r),o=0;o<r;o++)i[o]=arguments[o];return t=W()(this,(e=q()(n)).call.apply(e,[this].concat(i))),M()(Z()(Z()(t)),"state",{width:1280}),M()(Z()(Z()(t)),"mounted",!1),M()(Z()(Z()(t)),"ref",null),M()(Z()(Z()(t)),"onWindowResize",function(){if(t.mounted){var e=Object(u.findDOMNode)(Z()(Z()(t)));if(e instanceof window.HTMLElement){var n=e.offsetWidth;t.setState({width:n})}}}),t}return J()(n,t),F()(n,[{key:"componentDidMount",value:function(){this.mounted=!0,window.addEventListener("resize",this.onWindowResize),document.getElementById("collapse-button").addEventListener("click",this.onWindowResize),this.onWindowResize()}},{key:"componentWillUnmount",value:function(){this.mounted=!1,window.removeEventListener("resize",this.onWindowResize),document.getElementById("collapse-button").removeEventListener("click",this.onWindowResize)}},{key:"render",value:function(){var t=this.props,n=t.measureBeforeMount,r=le()(t,["measureBeforeMount"]);return n&&!this.mounted?Object(u.createElement)("div",{className:this.props.className,style:this.props.style}):Object(u.createElement)(e,Oe()({},r,{width:this.state.width+20}))}}]),n}(u.Component),M()(t,"defaultProps",{measureBeforeMount:!1}),n},"withWidth");var Ae=Object(re.createHigherOrderComponent)(function(e){return function(t){function n(){var e;return H()(this,n),e=W()(this,q()(n).apply(this,arguments)),M()(Z()(Z()(e)),"state",{pressed:{shift:!1,ctrl:!1,meta:!1,alt:!1}}),M()(Z()(Z()(e)),"mounted",!1),e.listener=e.listener.bind(Z()(Z()(e))),e.onBlur=e.onBlur.bind(Z()(Z()(e))),e}return J()(n,t),F()(n,[{key:"componentDidMount",value:function(){this.mounted=!0,window.addEventListener("keydown",this.listener),window.addEventListener("keyup",this.listener),window.addEventListener("click",this.listener),window.addEventListener("blur",this.onBlur)}},{key:"componentWillUnmount",value:function(){this.mounted=!1,window.removeEventListener("keydown",this.listener),window.removeEventListener("keyup",this.listener),window.removeEventListener("click",this.listener),window.removeEventListener("blur",this.onBlur)}},{key:"listener",value:function(e){this.mounted&&this.setState({pressed:{shift:e.shiftKey,ctrl:e.ctrlKey,meta:e.metaKey,alt:e.altKey}})}},{key:"onBlur",value:function(){this.setState({pressed:{shift:!1,ctrl:!1,meta:!1,alt:!1}})}},{key:"render",value:function(){return Object(u.createElement)(e,Oe()({pressedModifierKeys:this.state.pressed},this.props))}}]),n}(u.Component)},"withPressedModifierKeys"),De=function(e){function t(){var e;return H()(this,t),(e=W()(this,q()(t).apply(this,arguments))).handleClick=e.handleClick.bind(Z()(Z()(e))),e.onNavigate=e.onNavigate.bind(Z()(Z()(e))),e.onKeyDown=e.onKeyDown.bind(Z()(Z()(e))),e.toggleTab=e.toggleTab.bind(Z()(Z()(e))),e.getSelectedTabs=e.getSelectedTabs.bind(Z()(Z()(e))),e.isSelected=e.isSelected.bind(Z()(Z()(e))),e.getSelectedId=e.getSelectedId.bind(Z()(Z()(e))),e.getLabelledBy=e.getLabelledBy.bind(Z()(Z()(e))),e.getTabId=e.getTabId.bind(Z()(Z()(e))),e.getTabPanelId=e.getTabPanelId.bind(Z()(Z()(e))),e.isTabDisabled=e.isTabDisabled.bind(Z()(Z()(e))),e.isNonMultiSelectableTabSelected=e.isNonMultiSelectableTabSelected.bind(Z()(Z()(e))),e}return J()(t,e),F()(t,[{key:"handleClick",value:function(e,t){t.metaKey||t.ctrlKey?this.toggleTab(e):this.props.onSelect([e])}},{key:"onNavigate",value:function(e,t){var n=this.event;if(n){if("tab"===n.target.getAttribute("role")&&n.preventDefault(),n.ctrlKey)return;if(n.shiftKey){if(this.isTabDisabled(this.props.tabs[e]))return;var r=this.props.tabs[e].name;return void this.toggleTab(r)}}t.click()}},{key:"onKeyDown",value:function(e){if(!e.nativeEvent&&(this.event=e,e.ctrlKey&&("Space"===e.code||32===e.keyCode))){e.preventDefault();var t=e.target.dataset.tabname;t&&this.toggleTab(t)}}},{key:"toggleTab",value:function(e){var t=Object(g.find)(this.props.tabs,{name:e});t&&!1===t.allowMultiple||(this.props.selected.includes(e)?this.props.onSelect(this.props.selected.filter(function(t){return t!==e})):this.props.onSelect(b()(this.props.selected).concat([e])))}},{key:"getSelectedTabs",value:function(){var e=this,t=this.props.selected;!t.length&&this.props.initialTab&&t.push(this.props.initialTab);var n=[];return this.props.tabs.forEach(function(t){e.props.selected.includes(t.name)&&n.push(t)}),n}},{key:"isSelected",value:function(e,t){return e.some(function(e){return e.name===t.name})}},{key:"isTabDisabled",value:function(e){var t=this.props.pressedModifierKeys;if(this.props.selected.includes(e.name))return!1;if(!1!==e.allowMultiple&&!this.isNonMultiSelectableTabSelected())return!1;if(t.meta||t.ctrl)return!0;if(t.shift){var n=document.activeElement;if(n.parentElement&&n.parentElement.id==="components-tab-panel__tabs-".concat(this.props.instanceId))return!0}return!1}},{key:"isNonMultiSelectableTabSelected",value:function(){if(1!==this.props.selected.length)return!1;var e=Object(g.find)(this.props.tabs,{name:this.props.selected[0]});return e&&!1===e.allowMultiple}},{key:"getSelectedId",value:function(e){return 1===e.length?this.getTabPanelId(e[0].name):"components-tab-panel__panel-".concat(this.props.instanceId,"-").concat(Object(g.map)(e,"name").join("-"))}},{key:"getLabelledBy",value:function(e){var t=this;return e.map(function(e){return t.getTabId(e.name)}).join(",")}},{key:"getTabId",value:function(e){return"components-tab-panel__tab-".concat(this.props.instanceId,"-").concat(e)}},{key:"getTabPanelId",value:function(e){return"components-tab-panel__panel-".concat(this.props.instanceId,"-").concat(e)}},{key:"componentDidUpdate",value:function(e){if(1===this.props.selected.length&&Ge()(this.props.selected,e.selected)){var t=this.props.selected[0];if(!Object(g.find)(this.props.tabs,{name:t})){var n=Object(g.findIndex)(e.tabs,{name:t});if(-1!==n){var r=Math.max(n-1,0),i=this.props.tabs[r];i&&this.props.onSelect([i.name])}}}}},{key:"render",value:function(){var e=this,t=this.props,n=t.tabs,r=t.className,i=t.activeClass,o=void 0===i?"is-active":i,s=t.orientation,c=void 0===s?"horizontal":s,a=this.getSelectedTabs(),l=this.getSelectedId(a);return Object(u.createElement)("div",{className:r},Object(u.createElement)(X.NavigableMenu,{role:"tablist","aria-multiselectable":!0,orientation:c,onNavigate:this.onNavigate,onKeyDown:this.onKeyDown,className:"components-tab-panel__tabs",id:"components-tab-panel__tabs-".concat(this.props.instanceId)},n.map(function(t){var n=e.isSelected(a,t),r=n&&a.length>1?l:e.getTabPanelId(t.name);return Object(u.createElement)(Te,{className:ne()(t.className,M()({},o,n)),tabId:e.getTabId(t.name),"aria-controls":r,selected:n,disabled:e.isTabDisabled(t),key:t.name,onClick:Object(g.partial)(e.handleClick,t.name),"data-tabname":t.name},t.title)})),a.length>0&&Object(u.createElement)("div",{"aria-labelledby":this.getLabelledBy(a),role:"tabpanel",id:l,className:"components-tab-panel__tab-content",tabIndex:"0"},this.props.children(a)))}}]),t}(u.Component),Me=Object(re.compose)([re.withInstanceId,Ae])(De),Be=function(e){function t(){var e;return H()(this,t),e=W()(this,q()(t).apply(this,arguments)),M()(Z()(Z()(e)),"onSelect",function(t){e.setState({selected:t})}),e.state={selected:e.props.initialTab||""},e}return J()(t,e),F()(t,[{key:"render",value:function(){return Object(u.createElement)(Le,Oe()({},this.props,{selected:this.state.selected,onSelect:this.onSelect}))}}]),t}(u.Component);function Ue(e,t){for(var n=arguments.length,r=new Array(n>2?n-2:0),i=2;i<n;i++)r[i-2]=arguments[i];return{type:"SELECT",storeKey:e,selectorName:t,args:r}}function He(e,t){for(var n=arguments.length,r=new Array(n>2?n-2:0),i=2;i<n;i++)r[i-2]=arguments[i];return{type:"DISPATCH",storeKey:e,actionName:t,args:r}}function Ve(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"info",t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return{type:"CREATE_NOTICE",status:e,content:t,options:v()({context:"ithemes-security"},n)}}var Fe={API_FETCH:function(e){var t=e.request;return O()(t).catch(E.e)},SELECT:function(e){var t,n=e.storeKey,r=e.selectorName,i=e.args;return(t=Object(f.select)(n))[r].apply(t,b()(i))},DISPATCH:function(e){var t,n=e.storeKey,r=e.actionName,i=e.args;return(t=Object(f.dispatch)(n))[r].apply(t,b()(i))},CREATE_NOTICE:function(e){var t=e.status,n=e.content,r=e.options;r.autoDismiss&&(r.id=r.id||Object(g.uniqueId)("itsec-auto-dismiss-"),setTimeout(function(){return Object(f.dispatch)("core/notices").removeNotice(r.id,r.context)},r.autoDismiss)),Object(f.dispatch)("core/notices").createNotice(t,n,r)}},Ke=regeneratorRuntime.mark(Ye),We=regeneratorRuntime.mark(Xe),$e=regeneratorRuntime.mark(et),qe=regeneratorRuntime.mark(it);function ze(e){return{type:ot,ids:e}}function Je(e,t){return{type:st,id:e,edit:t}}function Ye(e){var t,n;return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,Ue("ithemes-security/user-groups-editor","getEditedGroup",e);case 2:if(t=r.sent){r.next=5;break}return r.abrupt("return");case 5:return r.next=7,{type:at,id:e};case 7:return r.next=9,He("ithemes-security/user-groups","updateGroup",e,t);case 9:if(!((n=r.sent)instanceof Error)){r.next=17;break}return r.next=13,Ve("error",n.message);case 13:return r.next=15,{type:lt,id:e,error:n};case 15:r.next=21;break;case 17:return r.next=19,{type:ut,id:e,updated:n};case 19:return r.next=21,Ve("success",Object(l.__)("Updated group.","better-wp-security"),{type:"snackbar"});case 21:return r.abrupt("return",n);case 22:case"end":return r.stop()}},Ke,this)}function Ze(e){return{type:ct,id:e}}function Xe(){var e,t,n,r=arguments;return regeneratorRuntime.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:return e=r.length>0&&void 0!==r[0]?r[0]:{},i.next=3,Ue("ithemes-security/user-groups-editor","getEditedGroup","new");case 3:if(t=i.sent){i.next=6;break}return i.abrupt("return");case 6:return i.next=8,{type:dt};case 8:return i.next=10,He("ithemes-security/user-groups","createGroup",v()({},t,e));case 10:if(!((n=i.sent)instanceof Error)){i.next=23;break}if("rest_duplicate_user_group"!==n.code){i.next=17;break}return i.next=15,Ve("error",n.message,{actions:[{label:Object(l.__)("View Duplicate","better-wp-security"),isLink:!0,onClick:function(){var e=Object(g.get)(n,["_links","duplicate",0,"href"]).split("/").pop();Object(f.dispatch)("ithemes-security/user-groups-editor").selectGroup([e])}},{label:Object(l.__)("Create Anyway","better-wp-security"),onClick:function(){Object(f.dispatch)("ithemes-security/user-groups-editor").createGroup({ignore_duplicate:!0})}}]});case 15:i.next=19;break;case 17:return i.next=19,Ve("error",n.message);case 19:return i.next=21,{type:ft,error:n};case 21:i.next=31;break;case 23:return i.next=25,Ze("new");case 25:return i.next=27,{type:pt,created:n};case 27:return i.next=29,He("ithemes-security/user-groups-editor","selectGroup",n.id);case 29:return i.next=31,Ve("success",Object(l.__)("Created group.","better-wp-security"),{type:"snackbar"});case 31:return i.abrupt("return",n);case 32:case"end":return i.stop()}},We,this)}function Qe(e,t,n,r){return{type:ht,id:e,module:t,setting:n,value:r}}function et(e){var t,n;return regeneratorRuntime.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,Ue("ithemes-security/user-groups-editor","getEditedGroupSettings",e);case 2:if(t=r.sent){r.next=5;break}return r.abrupt("return");case 5:return r.next=7,{type:bt,id:e};case 7:return r.next=9,He("ithemes-security/user-groups","updateGroupSettings",e,t);case 9:if(!((n=r.sent)instanceof Error)){r.next=17;break}return r.next=13,Ve("error",n.message);case 13:return r.next=15,{type:vt,id:e,error:n};case 15:r.next=21;break;case 17:return r.next=19,{type:mt,id:e,updated:n};case 19:return r.next=21,Ve("success",Object(l.__)("Updated group settings.","better-wp-security"),{type:"snackbar"});case 21:return r.abrupt("return",n);case 22:case"end":return r.stop()}},$e,this)}function tt(e,t,n){return{type:gt,module:e,setting:t,value:n}}function nt(e,t){return{type:yt,module:e,setting:t}}function rt(){return{type:Ot}}function it(e){var t,n,r,i;return regeneratorRuntime.wrap(function(o){for(;;)switch(o.prev=o.next){case 0:return o.next=2,Ue("ithemes-security/user-groups-editor","getBulkSettingEdits");case 2:return t=o.sent,o.next=5,He("ithemes-security/user-groups","patchBulkGroupSettings",e,t);case 5:if(!((n=o.sent)instanceof Error)){o.next=11;break}return o.next=9,Ve("error",n.message);case 9:o.next=25;break;case 11:if(!Object(g.map)(n,"status").every(function(e){return 200===e})){o.next=16;break}return o.next=14,Ve("success",Object(l.__)("Updated group settings.","better-wp-security"),{type:"snackbar"});case 14:o.next=25;break;case 16:if(r=n.filter(function(e){return 200!==e.status}).map(function(e){var t=e.error;return Object(E.b)(t)}),i=r.map(function(e){return e.getAllErrorMessages().join(" ")}).join(" "),r.length!==n.length){o.next=23;break}return o.next=21,Ve("error",i);case 21:o.next=25;break;case 23:return o.next=25,Ve("warning",Object(l.sprintf)(Object(l._n)("%1$d group was not updated: %2$s","%1$d groups were not updated: %2$s",r.length,"better-wp-security"),r.length,i));case 25:return o.next=27,rt();case 27:return o.abrupt("return",n);case 28:case"end":return o.stop()}},qe,this)}var ot="SELECT_GROUP",st="EDIT_GROUP",ct="RESET_EDITS",at="START_SAVE_GROUP",ut="FINISH_SAVE_GROUP",lt="FAILED_SAVE_GROUP",dt="START_CREATE_GROUP",pt="FINISH_CREATE_GROUP",ft="FAILED_CREATE_GROUP",ht="EDIT_GROUP_SETTING",bt="START_SAVE_GROUP_SETTINGS",mt="FINISH_SAVE_GROUP_SETTINGS",vt="FAILED_SAVE_GROUP_SETTINGS",gt="BULK_EDIT_GROUP_SETTING",yt="RESET_BULK_GROUP_SETTING_EDIT",Ot="RESET_BULK_GROUP_SETTING_EDITS";function Et(e){return e.selectedGroup}function jt(e){return e.creating}function _t(e,t){return e.edits[t]}function wt(e,t,n){var r=Object(g.get)(e,["edits",t,n]);return void 0!==r?r:"new"!==t?Object(f.select)("ithemes-security/user-groups").getGroupAttribute(t,n):void 0}function St(e,t){return!!e.edits[t]}function kt(e,t){return!!e.settingEdits[t]}function It(e,t){return e.settingEdits[t]}function xt(e,t,n,r){var i=Object(g.get)(e,["settingEdits",t,n,r]);return void 0!==i?i:Object(f.select)("ithemes-security/user-groups").getGroupSetting(t,n,r)}function Nt(e){return!Object(g.isEmpty)(e.bulkSettingEdits)}function Ct(e){return e.bulkSettingEdits}function Tt(e,t,n){return Object(g.get)(e,["bulkSettingEdits",t,n])}function Rt(e,t,n,r){var i=Tt(e,n,r);if(void 0!==i)return i;var o=function(e){return Object(f.select)("ithemes-security/user-groups").getGroupSetting(e,n,r)},s=o(t[0]);return t.every(function(e){return o(e)===s})?s:null}function Lt(e,t){var n=Ct(e);return Object(f.select)("ithemes-security/user-groups").isBulkPatchingSettings(t,n)}function Pt(){return Object(f.select)("ithemes-security/user-groups").getGroups("available")}var Gt=regeneratorRuntime.mark(At);function At(){var e;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,He("ithemes-security/user-groups","query","available",{_embed:1});case 2:if(!((e=t.sent).length>0)){t.next=6;break}return t.next=6,He("ithemes-security/user-groups-editor","selectGroup",[e[0].id]);case 6:return t.abrupt("return",e);case 7:case"end":return t.stop()}},Gt,this)}var Dt={edits:{},settingEdits:{},bulkSettingEdits:{},creating:!1,selectedGroup:[]};Object(f.registerStore)("ithemes-security/user-groups-editor",{controls:Fe,actions:s,selectors:c,resolvers:a,reducer:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Dt,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case ot:return v()({},e,{selectedGroup:t.ids});case st:return v()({},e,{edits:v()({},e.edits,M()({},t.id,v()({},e.edits[t.id]||{},t.edit)))});case ut:return v()({},e,{edits:Object(g.omit)(e.edits,[t.id])});case ht:return v()({},e,{settingEdits:v()({},e.settingEdits,M()({},t.id,v()({},Object(g.get)(e,["settingEdits",t.id],{}),M()({},t.module,v()({},Object(g.get)(e,["settingEdits",t.id,t.module],{}),M()({},t.setting,t.value))))))});case mt:return v()({},e,{settingEdits:Object(g.omit)(e.settingEdits,[t.id])});case dt:return v()({},e,{creating:!0});case ft:case pt:return v()({},e,{creating:!1});case ct:return v()({},e,{edits:Object(g.omit)(e.edits,[t.id])});case gt:return v()({},e,{bulkSettingEdits:v()({},e.bulkSettingEdits,M()({},t.module,v()({},e.bulkSettingEdits[t.module]||{},M()({},t.setting,t.value))))});case yt:return v()({},e,{bulkSettingEdits:Object(g.omit)(e.bulkSettingEdits,"".concat(t.module,".").concat(t.setting))});case Ot:return v()({},e,{bulkSettingEdits:{}});default:return e}}});function Mt(){return Object(u.createElement)("div",null,Object(u.createElement)(Ut,null))}n("GjY+");var Bt=ae()(function(e){return e.sort(function(e,t){return e.type===t.type?0:"user-group"===e.type?-1:"user-group"===t.type?1:0}).map(function(e){return{name:e.id,title:e.label,className:"itsec-user-groups-list__item",group:e}}).concat({name:"new",title:Object(u.createElement)(u.Fragment,null,Object(u.createElement)(X.Icon,{icon:"plus"}),Object(l.__)("New Group","better-wp-security")),className:"itsec-user-groups-list__item itsec-user-groups-list__item--new",allowMultiple:!1})});var Ut=Object(re.compose)([Object(f.withSelect)(function(e){return{matchables:e("ithemes-security/user-groups").getMatchables(),resolvingMatchables:e("core/data").isResolving("ithemes-security/user-groups","getMatchables"),selectedGroup:e("ithemes-security/user-groups-editor").getSelectedGroup()}}),Object(f.withDispatch)(function(e){return{selectGroup:e("ithemes-security/user-groups-editor").selectGroup}})])(function(e){var t=e.matchables,n=e.resolvingMatchables,r=e.selectedGroup,i=e.selectGroup;if(Object(u.useEffect)(function(){!n&&t.length&&0===r.length&&i([t[0].id])},[n]),n&&!t.length)return null;var o=Bt(t);return Object(u.createElement)(Me,{tabs:o,selected:r,onSelect:i,allowMultiple:!0,orientation:"vertical",className:"itsec-user-groups-list"},function(e){if(e.length>1){var t=Object(g.filter)(e.map(function(e){var t=e.group;return t&&t.id}));return Object(u.createElement)(Kt,{groupIds:t})}return e[0]?Object(u.createElement)(Vt,{groupId:e[0].name,isNew:"new"===e[0].name}):null})}),Ht=(n("Y0od"),ae()(function(e,t){if("new"===e)return[{name:"create",title:Object(l.__)("Edit Group","better-wp-security"),className:"itsec-manage-user-group-tabs__tab",Component:qt}];var n=[{name:"settings",title:Object(l.__)("Features","better-wp-security"),className:"itsec-manage-user-group-tabs__tab",Component:Yt}];return"user-group"===t&&n.push({name:"edit",title:Object(l.__)("Edit Group","better-wp-security"),className:"itsec-manage-user-group-tabs__tab",Component:zt}),n}));var Vt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{type:e("ithemes-security/user-groups").getMatchableType(n)}})])(function(e){var t=e.groupId,n=e.type,r=e.isNew;return Object(u.createElement)("div",{className:"itsec-manage-user-group"},r?Object(u.createElement)(cn,null):Object(u.createElement)(sn,{groupId:t}),Object(u.createElement)(Be,{tabs:Ht(t,n),className:"itsec-manage-user-group-tabs"},function(e){var n=e.Component;return Object(u.createElement)(n,{groupId:t})}))}),Ft=ae()(function(){return[{name:"settings",title:Object(l.__)("Features","better-wp-security"),className:"itsec-manage-user-group-tabs__tab",Component:Xt}]});var Kt=function(e){var t=e.groupIds;return Object(u.createElement)("div",{className:"itsec-manage-multiple-user-groups"},Object(u.createElement)(an,{groupIds:t}),Object(u.createElement)(Be,{tabs:Ft(),className:"itsec-manage-user-group-tabs"},function(e){var n=e.Component;return Object(u.createElement)(n,{groupIds:t})}))};n("QmYb");var Wt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{label:e("ithemes-security/user-groups-editor").getEditedGroupAttribute(n,"label")||""}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{edit:function(t){return e("ithemes-security/user-groups-editor").editGroup(n,t)}}})])(function(e){var t=e.label,n=e.edit,r=e.disabled,i=void 0!==r&&r;return Object(u.createElement)(X.TextControl,{label:Object(l.__)("Group Name","better-wp-security"),value:t,maxLength:50,disabled:i,onChange:function(e){return n({label:e})}})});n("ZRc3");function $t(e){var t,n=e.name,r=e.isLoading,i=e.children,o=ne()("itsec-user-groups-group-tab",(t={},M()(t,"itsec-user-groups-group-tab--".concat(n),n),M()(t,"itsec-user-groups-group-tab--is-loading",r),t));return Object(u.createElement)("div",{className:o},i)}$t.Row=function(e){var t=e.name,n=e.children;return Object(u.createElement)("div",{className:"itsec-user-groups-group-tab__row itsec-user-groups-group-tab__row--".concat(t)},n)};var qt=Object(re.compose)([Object(f.withSelect)(function(e){return{hasEdits:e("ithemes-security/user-groups-editor").hasEdits("new"),isSaving:e("ithemes-security/user-groups-editor").isCreating("new")}}),Object(f.withDispatch)(function(e){return{save:function(){e("ithemes-security/user-groups-editor").createGroup()}}})])(function(e){var t=e.hasEdits,n=e.save,r=e.isSaving;return Object(u.createElement)($t,{name:"create-group"},Object(u.createElement)(ln,{groupId:"new"}),Object(u.createElement)($t.Row,{name:"save"},Object(u.createElement)(X.Button,{disabled:!t,isPrimary:!0,onClick:n,isBusy:r},Object(l.__)("Create","better-wp-security"))))});var zt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{isLoading:e("core/data").isResolving("ithemes-security/user-groups","getGroup",[n])||e("core/data").isResolving("ithemes-security/core","getIndex"),hasEdits:e("ithemes-security/user-groups-editor").hasEdits(n),isSaving:e("ithemes-security/user-groups").isUpdating(n)}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{save:function(){return e("ithemes-security/user-groups-editor").saveGroup(n)}}})])(function(e){var t=e.groupId,n=e.hasEdits,r=e.save,i=e.isSaving,o=e.isLoading;return Object(u.createElement)($t,{name:"edit-group",isLoading:o},Object(u.createElement)(ln,{groupId:t,disabled:o}),Object(u.createElement)($t.Row,{name:"save"},Object(u.createElement)(X.Button,{disabled:!n,isPrimary:!0,onClick:r,isBusy:i},Object(l.__)("Save","better-wp-security"))))});var Jt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId,r=t.module,i=t.setting;return{value:e("ithemes-security/user-groups-editor").getEditedGroupSetting(n,r,i)}}),Object(f.withDispatch)(function(e,t){var n=t.groupId,r=t.module,i=t.setting;return{edit:function(t){return e("ithemes-security/user-groups-editor").editGroupSetting(n,r,i,t)}}})])(function(e){var t=e.schema,n=e.value,r=e.edit,i=e.disabled,o=void 0!==i&&i;return Object(u.createElement)(X.ToggleControl,{checked:!0===n,label:t.title,help:t.description,disabled:o,onChange:function(e){return r(e)}})});n("GrEf");var Yt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{groupSettings:e("ithemes-security/user-groups").getGroupSettings(n),isLoading:e("core/data").isResolving("ithemes-security/user-groups","getGroupSettings",[n]),schema:e("ithemes-security/core").getSchema("ithemes-security-user-group-settings"),hasEdits:e("ithemes-security/user-groups-editor").settingHasEdits(n),isSaving:e("ithemes-security/user-groups").isUpdatingSettings(n)}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{save:function(){return e("ithemes-security/user-groups-editor").saveGroupSettings(n)}}})])(function(e){var t=e.schema,n=e.groupId,r=e.hasEdits,i=e.save,o=e.isSaving,s=e.isLoading;return t?Object(u.createElement)($t,{name:"settings",isLoading:s},Object(u.createElement)($t.Row,null,Object(u.createElement)(dn,{schema:t,settingComponent:Jt,groupId:n,disabled:s})),Object(u.createElement)($t.Row,{name:"save"},Object(u.createElement)(X.Button,{disabled:!r,isPrimary:!0,onClick:i,isBusy:o},Object(l.__)("Save","better-wp-security")))):null});var Zt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.module,r=t.setting,i=t.groupIds;return{value:e("ithemes-security/user-groups-editor").getBulkSettingValue(i,n,r)}}),Object(f.withDispatch)(function(e,t){var n=t.module,r=t.setting;return{edit:function(t){return e("ithemes-security/user-groups-editor").bulkEditGroupSetting(n,r,t)}}})])(function(e){var t=e.schema,n=e.value,r=e.edit,i=e.disabled,o=void 0!==i&&i;return Object(u.createElement)(Ce,{checked:!0===n,indeterminate:null==n,label:t.title,help:t.description,disabled:o,onChange:function(e){return r(e)}})});var Xt=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupIds;return{schema:e("ithemes-security/core").getSchema("ithemes-security-user-group-settings"),hasEdits:e("ithemes-security/user-groups-editor").hasBulkSettingEdits(),isSaving:e("ithemes-security/user-groups-editor").isSavingBulkEdits(n)}}),Object(f.withDispatch)(function(e,t){var n=t.groupIds;return{save:function(){return e("ithemes-security/user-groups-editor").saveBulkEdits(n)}}})])(function(e){var t=e.schema,n=e.hasEdits,r=e.save,i=e.isSaving,o=e.groupIds;return t?Object(u.createElement)($t,{name:"settings"},Object(u.createElement)($t.Row,null,Object(u.createElement)(dn,{schema:t,settingComponent:Zt,groupIds:o})),Object(u.createElement)($t.Row,{name:"save"},Object(u.createElement)(X.Button,{disabled:!n,isPrimary:!0,onClick:r,isBusy:i},Object(l.__)("Save","better-wp-security")))):null});Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{minRole:e("ithemes-security/user-groups-editor").getEditedGroupAttribute(n,"min_role")}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{onChange:function(t){return e("ithemes-security/user-groups-editor").editGroup(n,t)}}})])(function(e){var t=e.minRole,n=e.onChange;return Object(u.createElement)("div",null,Object(u.createElement)(X.SelectControl,{options:[{value:"administrator",label:Object(l._x)("Administrator","User role","default")},{value:"editor",label:Object(l._x)("Editor","User role","default")},{value:"author",label:Object(l._x)("Author","User role","default")},{value:"contributor",label:Object(l._x)("Contributor","User role","default")},{value:"subscriber",label:Object(l._x)("Subscriber","User role","default")}],label:Object(l.__)("Minimum Role","better-wp-security"),value:t,onChange:function(e){return n({min_role:e})},help:Object(l.__)("Add users with the selected minimum role to this group. To edit roles, go to Users in your WordPress Dashboard.","better-wp-security")}))});var Qt=ae()(function(e,t){var n=[{value:"$administrator$",label:Object(l.__)("Administrator Capabilities","better-wp-security")},{value:"$editor$",label:Object(l.__)("Editor Capabilities","better-wp-security")},{value:"$author$",label:Object(l.__)("Author Capabilities","better-wp-security")},{value:"$contributor$",label:Object(l.__)("Contributor Capabilities","better-wp-security")},{value:"$subscriber$",label:Object(l.__)("Subscriber Capabilities","better-wp-security")}];for(var r in t&&n.unshift({value:"$super-admin$",label:Object(l.__)("Super Admin","better-wp-security")}),Object(g.some)(e,function(e){return""===e.canonical})&&n.push({value:"$other$",label:Object(l.__)("Other","better-wp-security"),selectable:!1}),e)if(e.hasOwnProperty(r)){var i=e[r],o=i.canonical,s=i.label;n.push({value:r,parent:o.length>0?"$".concat(o,"$"):"$other$",label:s})}return Object.values(n)});var en=Object(re.compose)([Object(f.withSelect)(function(e,t){var n=t.groupId;return{roles:e("ithemes-security/user-groups-editor").getEditedGroupAttribute(n,"roles")||[],canonical:e("ithemes-security/user-groups-editor").getEditedGroupAttribute(n,"canonical")||[],available:e("ithemes-security/core").getRoles(),schema:e("ithemes-security/core").getSchema("ithemes-security-user-group")}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{onChange:function(t){return e("ithemes-security/user-groups-editor").editGroup(n,t)}}})])(function(e){var t=e.canonical,n=e.roles,r=e.onChange,i=e.available,o=e.schema,s=e.disabled,c=void 0!==s&&s,a=Object(g.get)(o,["properties","canonical","items","enum"],[]).includes("super-admin"),d=b()(n).concat(b()(t.map(function(e){return"$".concat(e,"$")})));return Object(u.createElement)(ke,{label:Object(l.__)("Select Roles","better-wp-security"),help:Object(l.__)("Add users with the selected roles to this group.","better-wp-security"),value:d,disabled:c,options:Qt(i,a),onChange:function(e){var t=Object(E.a)(e,function(e){return e.startsWith("$")&&e.endsWith("$")}),n=oe()(t,2),i=n[0],o=n[1];r({roles:o,canonical:Object(g.without)(i.map(function(e){return e.slice(1,-1)}),"other")})}})}),tn=n("Mmq9");n("ELjz");function nn(e){return{value:e.id,label:e.name,user:e}}var rn=function(e){return new Promise(function(t,n){O()({path:Object(tn.addQueryArgs)("/wp/v2/users",{search:e,per_page:100,context:"embed",itsec_global:!0})}).then(function(e){return e.forEach(Object(f.dispatch)("ithemes-security/core").receiveUser),e}).then(function(e){return t(e.map(nn))}).catch(n)})};var on=Object(re.compose)([Object(re.withState)({selectSearch:""}),Object(f.withSelect)(function(e,t){var n=t.groupId,r=e("ithemes-security/user-groups-editor").getEditedGroupAttribute(n,"users")||[],i=[],o=!1;return r.forEach(function(t){var n=e("ithemes-security/core").getUser(t);n?i.push(n):e("core/data").isResolving("ithemes-security/core","getUser",[t])&&(o=!0)}),{users:i,userIds:r,loading:o}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{receiveUser:e("ithemes-security/core").receiveUser,onChange:function(t){return e("ithemes-security/user-groups-editor").editGroup(n,t)}}}),re.withInstanceId])(function(e){var t=e.instanceId,n=e.users,r=e.loading,i=e.onChange,o=e.disabled,s=void 0!==o&&o,c=e.selectSearch,a=e.setState,d="itsec-user-group-panel-users__select-".concat(t),p=r?[]:n.map(nn);return Object(u.createElement)(X.BaseControl,{className:"itsec-user-group-panel-users__select-control",label:Object(l.__)("Select Users","better-wp-security"),help:Object(l.__)("Select specific users to add to this group.","better-wp-security"),id:d},Object(u.createElement)(me,{classNamePrefix:"components-itsec-async-select-control",inputId:d,isDisabled:s||r,isLoading:r,isMulti:!0,cacheOptions:!0,defaultOptions:!0,loadOptions:rn,value:p,onChange:function(e){return i({users:Object(g.map)(e,"value")})},inputValue:c,onInputChange:function(e){return a({selectSearch:e})}}))});n("mzAq");var sn=Object(re.compose)([Object(f.withSelect)(function(e,t){var n,r=t.groupId,i=e("ithemes-security/user-groups").getMatchableType(r),o="user-group"===i&&e("ithemes-security/user-groups").isDeleting(r);return"user-group"===i&&(n=e("ithemes-security/user-groups-editor").getEditedGroupAttribute(r,"label")),void 0===n&&(n=e("ithemes-security/user-groups").getMatchableLabel(r)),{type:i,label:n,isDeleting:o}}),Object(f.withDispatch)(function(e,t){var n=t.groupId;return{deleteGroup:function(){return e("ithemes-security/user-groups").deleteGroup(n)}}})])(function(e){var t=e.type,n=e.label,r=e.isDeleting,i=e.deleteGroup,o="user-group"===t;return n&&n.length||(n=Object(l.__)("Untitled","better-wp-security")),Object(u.createElement)(un,{label:n},o&&Object(u.createElement)(X.Button,{onClick:i,isBusy:r,isLink:!0,isDestructive:!0},Object(l.__)("Delete Group","better-wp-security")))});var cn=Object(re.compose)([Object(f.withSelect)(function(e){return{label:e("ithemes-security/user-groups-editor").getEditedGroupAttribute("new","label")}})])(function(e){var t=e.label;return t&&t.length||(t=Object(l.__)("New Group","better-wp-security")),Object(u.createElement)(un,{label:t})});var an=Object(re.compose)([Object(f.withSelect)(function(e,t){return{label:t.groupIds.map(e("ithemes-security/user-groups").getMatchableLabel).join(", ")}})])(function(e){var t=e.label;return Object(u.createElement)(un,{label:t})});function un(e){var t=e.label,n=e.children;return Object(u.createElement)("div",{className:"itsec-user-group-header"},Object(u.createElement)("h4",{className:"itsec-user-group-header__label"},t),n)}n("XO7p");var ln=function(e){var t=e.groupId,n=e.disabled;return Object(u.createElement)($t.Row,{name:"edit-fields"},Object(u.createElement)(Wt,{groupId:t,disabled:n}),Object(u.createElement)(en,{groupId:t,disabled:n}),Object(u.createElement)(on,{groupId:t,disabled:n}))};function dn(e){var t=e.schema,n=e.settingComponent,r=le()(e,["schema","settingComponent"]);return Object(u.createElement)("ul",{className:"itsec-user-groups-group-tab__modules-list"},Object(g.map)(t.properties,function(e,t){return Object(u.createElement)("li",{key:t},Object(u.createElement)("fieldset",null,Object(u.createElement)("legend",null,e.title),Object(u.createElement)("ul",null,Object(g.map)(e.properties,function(e,i){return Object(u.createElement)("li",{key:i},Object(u.createElement)(n,Oe()({schema:e,module:t,setting:i},r)))}))))}))}n("wM0a");var pn=function(e){var t=e.noticeEl;return Object(u.createElement)("div",{className:"itsec-user-groups-app"},Object(u.createPortal)(Object(u.createElement)(xe,null),t),Object(u.createElement)(Mt,null))};function fn(){var e=document.getElementById("itsec-user-groups-settings-root"),t=document.getElementById("itsec-module-messages-container-user-groups");return Object(u.render)(Object(u.createElement)(pn,{noticeEl:t}),e)}n.p=window.itsecWebpackPublicPath,Object(l.setLocaleData)({"":{}},"ithemes-security-pro"),p()(function(){fn(),window.itsecSettingsPage&&(window.itsecSettingsPage.events.on("modulesReloaded",fn),window.itsecSettingsPage.events.on("moduleReloaded",function(e,t){"user-groups"===t&&fn()}))})},faye:function(e,t){!function(){e.exports=this.ReactDOM}()},l3Sj:function(e,t){!function(){e.exports=this.wp.i18n}()},lSNA:function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},lSb6:function(e,t,n){},lwsE:function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},m0LI:function(e,t){e.exports=function(e,t){var n=[],r=!0,i=!1,o=void 0;try{for(var s,c=e[Symbol.iterator]();!(r=(s=c.next()).done)&&(n.push(s.value),!t||n.length!==t);r=!0);}catch(e){i=!0,o=e}finally{try{r||null==c.return||c.return()}finally{if(i)throw o}}return n}},mzAq:function(e,t,n){},oShl:function(e,t,n){var r=n("Nsbk"),i=n("SksO"),o=n("xfeJ"),s=n("sXyB");function c(t){var n="function"==typeof Map?new Map:void 0;return e.exports=c=function(e){if(null===e||!o(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(e))return n.get(e);n.set(e,t)}function t(){return s(e,arguments,r(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),i(t,e)},c(t)}e.exports=c},"oaS/":function(e,t,n){},onLe:function(e,t){!function(){e.exports=this.wp.notices}()},pVnL:function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},n.apply(this,arguments)}e.exports=n},rl8x:function(e,t){!function(){e.exports=this.wp.isShallowEqual}()},rmEH:function(e,t){!function(){e.exports=this.wp.htmlEntities}()},sPxh:function(e,t){!function(){e.exports=this.itsec["user-groups"].api}()},sXyB:function(e,t,n){var r=n("SksO");function i(t,n,o){return!function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}()?e.exports=i=function(e,t,n){var i=[null];i.push.apply(i,t);var o=new(Function.bind.apply(e,i));return n&&r(o,n.prototype),o}:e.exports=i=Reflect.construct,i.apply(null,arguments)}e.exports=i},"tI+e":function(e,t){!function(){e.exports=this.wp.components}()},tmk3:function(e,t){e.exports=function(e,t){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return t.get(e).value}},urxu:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ErrorBoundaryFallbackComponent=t.withErrorBoundary=t.ErrorBoundary=void 0;var r=s(n("Xvx9")),i=n("31KZ"),o=s(i);function s(e){return e&&e.__esModule?e:{default:e}}t.default=o.default,t.ErrorBoundary=o.default,t.withErrorBoundary=i.withErrorBoundary,t.ErrorBoundaryFallbackComponent=r.default},wM0a:function(e,t,n){},wTVA:function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},wkBT:function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},xfeJ:function(e,t){e.exports=function(e){return-1!==Function.toString.call(e).indexOf("[native code]")}},ywyh:function(e,t){!function(){e.exports=this.wp.apiFetch}()}});
|
dist/vendors/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
dist/vendors/user-groups/api.min.js
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
(window.itsecWebpackJsonP=window.itsecWebpackJsonP||[]).push([[7],{"7W2i":function(t,e,n){var r=n("SksO");t.exports=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&r(t,e)}},"92Nh":function(t,e){t.exports=function(t,e,n){if(!e.has(t))throw new TypeError("attempted to set private field on non-instance");var r=e.get(t);if(!r.writable)throw new TypeError("attempted to set read only private field");return r.value=n,n}},Bnag:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},EbDI:function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},Ijbi:function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}},J4zp:function(t,e,n){var r=n("wTVA"),o=n("m0LI"),i=n("wkBT");t.exports=function(t,e){return r(t)||o(t,e)||i()}},MVZn:function(t,e,n){var r=n("lSNA");t.exports=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},o=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(n).filter(function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),o.forEach(function(e){r(t,e,n[e])})}return t}},Nsbk:function(t,e){function n(e){return t.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(e)}t.exports=n},PJYZ:function(t,e){t.exports=function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}},RIqP:function(t,e,n){var r=n("Ijbi"),o=n("EbDI"),i=n("Bnag");t.exports=function(t){return r(t)||o(t)||i()}},SksO:function(t,e){function n(e,r){return t.exports=n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(e,r)}t.exports=n},W8MJ:function(t,e){function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}t.exports=function(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),t}},a1gu:function(t,e,n){var r=n("cDf5"),o=n("PJYZ");t.exports=function(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?o(t):e}},cDf5:function(t,e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(e){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=r=function(t){return n(t)}:t.exports=r=function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},r(e)}t.exports=r},lSNA:function(t,e){t.exports=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}},lwsE:function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},m0LI:function(t,e){t.exports=function(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var u,f=t[Symbol.iterator]();!(r=(u=f.next()).done)&&(n.push(u.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{r||null==f.return||f.return()}finally{if(o)throw i}}return n}},oShl:function(t,e,n){var r=n("Nsbk"),o=n("SksO"),i=n("xfeJ"),u=n("sXyB");function f(e){var n="function"==typeof Map?new Map:void 0;return t.exports=f=function(t){if(null===t||!i(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(t))return n.get(t);n.set(t,e)}function e(){return u(t,arguments,r(this).constructor)}return e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),o(e,t)},f(e)}t.exports=f},pPDe:function(t,e,n){"use strict";var r,o;function i(t){return[t]}function u(){var t={clear:function(){t.head=null}};return t}function f(t,e,n){var r;if(t.length!==e.length)return!1;for(r=n;r<t.length;r++)if(t[r]!==e[r])return!1;return!0}r={},o="undefined"!=typeof WeakMap,e.a=function(t,e){var n,s;function a(){n=o?new WeakMap:u()}function c(){var n,r,o,i,u,a=arguments.length;for(i=new Array(a),o=0;o<a;o++)i[o]=arguments[o];for(u=e.apply(null,i),(n=s(u)).isUniqueByDependants||(n.lastDependants&&!f(u,n.lastDependants,0)&&n.clear(),n.lastDependants=u),r=n.head;r;){if(f(r.args,i,1))return r!==n.head&&(r.prev.next=r.next,r.next&&(r.next.prev=r.prev),r.next=n.head,r.prev=null,n.head.prev=r,n.head=r),r.val;r=r.next}return r={val:t.apply(null,i)},i[0]=null,r.args=i,n.head&&(n.head.prev=r,r.next=n.head),n.head=r,r.val}return e||(e=i),s=o?function(t){var e,o,i,f,s,a=n,c=!0;for(e=0;e<t.length;e++){if(o=t[e],!(s=o)||"object"!=typeof s){c=!1;break}a.has(o)?a=a.get(o):(i=new WeakMap,a.set(o,i),a=i)}return a.has(r)||((f=u()).isUniqueByDependants=c,a.set(r,f)),a.get(r)}:function(){return n},c.getDependants=e,c.clear=a,a(),c}},qPad:function(t,e,n){var r,o;r=this,o=function(){var t={"+":!0,"#":!0,".":!0,"/":!0,";":!0,"?":!0,"&":!0},e={"*":!0};function n(t){return encodeURI(t).replace(/%25[0-9][0-9]/g,function(t){return"%"+t.substring(3)})}function r(t){return t=t.replace(/%../g,""),encodeURIComponent(t)===t}function o(o){var i="";t[o.charAt(0)]&&(i=o.charAt(0),o=o.substring(1));var u="",f="",s=!0,a=!1,c=!1;"+"==i?s=!1:"."==i?(f=".",u="."):"/"==i?(f="/",u="/"):"#"==i?(f="#",s=!1):";"==i?(f=";",u=";",a=!0,c=!0):"?"==i?(f="?",u="&",a=!0):"&"==i&&(f="&",u="&",a=!0);for(var l=[],p=o.split(","),h=[],g={},y=0;y<p.length;y++){var b=p[y],v=null;if(-1!=b.indexOf(":")){var d=b.split(":");b=d[0],v=parseInt(d[1])}for(var m={};e[b.charAt(b.length-1)];)m[b.charAt(b.length-1)]=!0,b=b.substring(0,b.length-1);var x={truncate:v,name:b,suffices:m};h.push(x),g[b]=x,l.push(b)}return{varNames:l,prefix:f,substitution:function(t){for(var e="",r=0,o=0;o<h.length;o++){var i=h[o],l=t(i.name);if(null==l||Array.isArray(l)&&0==l.length||"object"==typeof l&&0==Object.keys(l).length)r++;else if(e+=o==r?f:u||",",Array.isArray(l)){a&&(e+=i.name+"=");for(var p=0;p<l.length;p++)p>0&&(e+=i.suffices["*"]&&u||",",i.suffices["*"]&&a&&(e+=i.name+"=")),e+=s?encodeURIComponent(l[p]).replace(/!/g,"%21"):n(l[p])}else if("object"==typeof l){a&&!i.suffices["*"]&&(e+=i.name+"=");var g=!0;for(var y in l)g||(e+=i.suffices["*"]&&u||","),g=!1,e+=s?encodeURIComponent(y).replace(/!/g,"%21"):n(y),e+=i.suffices["*"]?"=":",",e+=s?encodeURIComponent(l[y]).replace(/!/g,"%21"):n(l[y])}else a&&(e+=i.name,c&&""==l||(e+="=")),null!=i.truncate&&(l=l.substring(0,i.truncate)),e+=s?encodeURIComponent(l).replace(/!/g,"%21"):n(l)}return e},unSubstitution:function(t,e,n){if(f&&(t=t.substring(f.length)),1==h.length&&h[0].suffices["*"]){for(var o=(S=h[0]).name,i=S.suffices["*"]?t.split(u||","):[t],c=s&&-1!=t.indexOf("="),l=1;l<i.length;l++)t=i[l],c&&-1==t.indexOf("=")&&(i[l-1]+=(u||",")+t,i.splice(l,1),l--);for(l=0;l<i.length;l++)t=i[l],s&&-1!=t.indexOf("=")&&(c=!0),1==(d=t.split(",")).length?i[l]=d[0]:i[l]=d;if(a||c){for(var p=e[o]||{},y=0;y<i.length;y++){var b=t;if(!a||b){if("string"==typeof i[y]){var v=(t=i[y]).split("=",1)[0];if(t=t.substring(v.length+1),s){if(n&&!r(t))return;t=decodeURIComponent(t)}b=t}else{if(v=(t=i[y][0]).split("=",1)[0],t=t.substring(v.length+1),s){if(n&&!r(t))return;t=decodeURIComponent(t)}i[y][0]=t,b=i[y]}if(s){if(n&&!r(v))return;v=decodeURIComponent(v)}void 0!==p[v]?Array.isArray(p[v])?p[v].push(b):p[v]=[p[v],b]:p[v]=b}}1==Object.keys(p).length&&void 0!==p[o]?e[o]=p[o]:e[o]=p}else{if(s)for(y=0;y<i.length;y++){var d=i[y];if(Array.isArray(d))for(var m=0;m<d.length;m++){if(n&&!r(d[m]))return;d[m]=decodeURIComponent(d[m])}else{if(n&&!r(d))return;i[y]=decodeURIComponent(d)}}void 0!==e[o]?Array.isArray(e[o])?e[o]=e[o].concat(i):e[o]=[e[o]].concat(i):1!=i.length||S.suffices["*"]?e[o]=i:e[o]=i[0]}}else{i=1==h.length?[t]:t.split(u||",");var x={};for(l=0;l<i.length;l++){for(var w=0;w<h.length-1&&w<l&&!h[w].suffices["*"];w++);if(w!=l){for(var O=h.length-1;O>0&&h.length-O<i.length-l&&!h[O].suffices["*"];O--);h.length-O!=i.length-l?x[l]=w:x[l]=O}else x[l]=l}for(l=0;l<i.length;l++)if((t=i[l])||!a){if(d=t.split(","),c=!1,a){o=(t=d[0]).split("=",1)[0],t=t.substring(o.length+1),d[0]=t;var S=g[o]||h[0]}else o=(S=h[x[l]]).name;for(y=0;y<d.length;y++)if(s){if(n&&!r(d[y]))return;d[y]=decodeURIComponent(d[y])}(a||S.suffices["*"])&&void 0!==e[o]?Array.isArray(e[o])?e[o]=e[o].concat(d):e[o]=[e[o]].concat(d):1!=d.length||S.suffices["*"]?e[o]=d:e[o]=d[0]}}return 1}}}function i(t){if(!(this instanceof i))return new i(t);for(var e=t.split("{"),n=[e.shift()],r=[],u=[],f=[],s=[];e.length>0;){var a=e.shift(),c=a.split("}")[0],l=a.substring(c.length+1),p=o(c);u.push(p.substitution),f.push(p.unSubstitution),r.push(p.prefix),n.push(l),s=s.concat(p.varNames)}this.fill=function(t){if(t&&"function"!=typeof t){var e=t;t=function(t){return e[t]}}for(var r=n[0],o=0;o<u.length;o++){r+=(0,u[o])(t),r+=n[o+1]}return r},this.fromUri=function(t,e){e=e||{};for(var o={},i=0;i<n.length;i++){var u=n[i];if(t.substring(0,u.length)!==u)return;if(t=t.substring(u.length),i>=n.length-1){if(""==t)break;return}var s=r[i];if(!s||t.substring(0,s.length)===s){for(var a=n[i+1],c=i;;){if(c==n.length-2){var l=t.substring(t.length-a.length);if(l!==a)return;var p=t.substring(0,t.length-a.length);t=l}else if(a){var h=t.indexOf(a);p=t.substring(0,h);t=t.substring(h)}else if(r[c+1]){-1===(h=t.indexOf(r[c+1]))&&(h=t.length);p=t.substring(0,h);t=t.substring(h)}else{if(n.length>c+2){a=n[++c+1];continue}p=t;t=""}break}if(!f[i](p,o,e.strict))return}}return o},this.varNames=s,this.template=t}return i.prototype={toString:function(){return this.template},fillFromObject:function(t){return this.fill(t)},test:function(t,e){return!!this.fromUri(t,e)}},i},"function"==typeof define&&define.amd?define("uri-templates",[],o):t.exports?t.exports=o():r.UriTemplate=o()},sXyB:function(t,e,n){var r=n("SksO");function o(e,n,i){return!function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(t){return!1}}()?t.exports=o=function(t,e,n){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return n&&r(i,n.prototype),i}:t.exports=o=Reflect.construct,o.apply(null,arguments)}t.exports=o},tmk3:function(t,e){t.exports=function(t,e){if(!e.has(t))throw new TypeError("attempted to get private field on non-instance");return e.get(t).value}},wTVA:function(t,e){t.exports=function(t){if(Array.isArray(t))return t}},wkBT:function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},xfeJ:function(t,e){t.exports=function(t){return-1!==Function.toString.call(t).indexOf("[native code]")}}}]);
|
dist/vendors/user-groups/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
history.txt
CHANGED
@@ -864,5 +864,23 @@
|
|
864 |
Â
New Feature: iThemes Security now includes Security Check Pro to automatically and correctly determine your visitors IP addresses. Enable this scan by running Security Check and opting in to Security Check Pro or activate the Security Check Pro module in Advanced Modules. H/t Jeremy Voisin
|
865 |
Â
Enhancement: Run Security Check Pro IP Detection automatically once a day.
|
866 |
Â
Enhancement: Manually re-run Security Check Pro IP Detection from the Global Settings page.
|
867 |
-
7.
|
868 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
864 |
Â
New Feature: iThemes Security now includes Security Check Pro to automatically and correctly determine your visitors IP addresses. Enable this scan by running Security Check and opting in to Security Check Pro or activate the Security Check Pro module in Advanced Modules. H/t Jeremy Voisin
|
865 |
Â
Enhancement: Run Security Check Pro IP Detection automatically once a day.
|
866 |
Â
Enhancement: Manually re-run Security Check Pro IP Detection from the Global Settings page.
|
867 |
+
7.7.0 - 2020-04-15 - Timothy Jacobs, Josh Oakes
|
868 |
+
Important: iThemes Security requires PHP 5.6 or greater and WordPress 5.2 or greater.
|
869 |
+
New Feature: Save Time Securing WordPress With User Groups!
|
870 |
+
New Feature: Simplified connection flow when setting up iThemes Sync.
|
871 |
+
Enhancement: Add a warning if a WordPress Salt is set to an invalid value.
|
872 |
+
Enhancement: Include child log items in the logs list table. These are helpful for debugging issues.
|
873 |
+
Enhancement: Improve performance of the logs page on sites with large number of log items.
|
874 |
+
Enhancement: Check tables exist after completing a DB upgrade.
|
875 |
+
Tweak: When logging $_SERVER, only log a snapshot of available properties.
|
876 |
+
Bug Fix: The "Mulisite Tweaks -> Hide Updates" setting prevented auto-updates from running with WP Cron.
|
877 |
+
Bug Fix: Backup event was not added when the WP Cron Scheduler was reset manually.
|
878 |
+
Bug Fix: Admin Notices Popover was not being hidden when clicking outside the Popover on WP 5.3.
|
879 |
+
Bug Fix: New Password Requirements for already created accounts were not enforced until the second login.
|
880 |
+
Bug Fix: Update admin notices styling to be compatible with WordPress 5.4.
|
881 |
+
Bug Fix: Periodically clear expired opaque tokens.
|
882 |
+
Bug Fix: Don't block registration page when "wp-signup.php" is the Hide Backend register slug.
|
883 |
+
Bug Fix: Users with weak passwords would not be forced to change their password if the strong password requirement had been enabled after their password strength was checked.
|
884 |
+
Bug Fix: Remove "get_magic_quotes()" call that existed for backwards compatibility with PHP versions 5.3 and earlier. This function call was causing a warning on PHP 7.4.
|
885 |
+
Bug Fix: Warning when loading the settings page on PHP 7.4.
|
886 |
+
Bug Fix: Warning when loading the debug page on PHP 7.4.
|
package.json
CHANGED
@@ -9,28 +9,28 @@
|
|
9 |
Â
"dependencies": {
|
10 |
Â
"@wordpress/a11y": "*",
|
11 |
Â
"@wordpress/api-fetch": "*",
|
12 |
-
"@wordpress/autop": "
|
13 |
-
"@wordpress/components": "
|
14 |
-
"@wordpress/compose": "
|
15 |
-
"@wordpress/data": "
|
16 |
-
"@wordpress/date": "
|
17 |
Â
"@wordpress/dom-ready": "*",
|
18 |
Â
"@wordpress/element": "*",
|
19 |
Â
"@wordpress/hooks": "*",
|
20 |
Â
"@wordpress/html-entities": "*",
|
21 |
Â
"@wordpress/i18n": "*",
|
22 |
Â
"@wordpress/is-shallow-equal": "*",
|
23 |
-
"@wordpress/keycodes": "
|
24 |
Â
"@wordpress/notices": "*",
|
25 |
-
"@wordpress/plugins": "
|
26 |
Â
"@wordpress/redux-routine": "*",
|
27 |
-
"@wordpress/rich-text": "
|
28 |
Â
"@wordpress/url": "*",
|
29 |
Â
"@wordpress/viewport": "*",
|
30 |
Â
"classnames": "^2.2.6",
|
31 |
Â
"contrast": "^1.0.1",
|
32 |
Â
"li": "^1.3.0",
|
33 |
-
"lodash": "^4.17.
|
34 |
Â
"memize": "^1.0.5",
|
35 |
Â
"react": "^16.6.3",
|
36 |
Â
"react-error-boundary": "^1.2.3",
|
@@ -38,11 +38,14 @@
|
|
38 |
Â
"react-select": "^2.4.1",
|
39 |
Â
"react-transition-group": "^2.0.0",
|
40 |
Â
"recharts": "^1.5.0",
|
41 |
-
"rememo": "^3.0.0"
|
Â
|
|
Â
|
|
42 |
Â
},
|
43 |
Â
"devDependencies": {
|
44 |
Â
"@babel/core": "^7.3.3",
|
45 |
Â
"@babel/plugin-proposal-class-properties": "^7.3.3",
|
Â
|
|
46 |
Â
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
47 |
Â
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
48 |
Â
"@babel/runtime-corejs2": "^7.3.1",
|
@@ -110,8 +113,11 @@
|
|
110 |
Â
"test-unit:update": "npm run test-unit -- --updateSnapshot",
|
111 |
Â
"test-unit:watch": "npm run test-unit -- --watch",
|
112 |
Â
"watch": "./node_modules/.bin/webpack --watch",
|
Â
|
|
113 |
Â
"test-wpunit": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpunit",
|
114 |
Â
"test-acceptance": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run acceptance",
|
115 |
-
"test-
|
Â
|
|
Â
|
|
116 |
Â
}
|
117 |
Â
}
|
9 |
Â
"dependencies": {
|
10 |
Â
"@wordpress/a11y": "*",
|
11 |
Â
"@wordpress/api-fetch": "*",
|
12 |
+
"@wordpress/autop": "*",
|
13 |
+
"@wordpress/components": "*",
|
14 |
+
"@wordpress/compose": "*",
|
15 |
+
"@wordpress/data": "*",
|
16 |
+
"@wordpress/date": "*",
|
17 |
Â
"@wordpress/dom-ready": "*",
|
18 |
Â
"@wordpress/element": "*",
|
19 |
Â
"@wordpress/hooks": "*",
|
20 |
Â
"@wordpress/html-entities": "*",
|
21 |
Â
"@wordpress/i18n": "*",
|
22 |
Â
"@wordpress/is-shallow-equal": "*",
|
23 |
+
"@wordpress/keycodes": "*",
|
24 |
Â
"@wordpress/notices": "*",
|
25 |
+
"@wordpress/plugins": "*",
|
26 |
Â
"@wordpress/redux-routine": "*",
|
27 |
+
"@wordpress/rich-text": "*",
|
28 |
Â
"@wordpress/url": "*",
|
29 |
Â
"@wordpress/viewport": "*",
|
30 |
Â
"classnames": "^2.2.6",
|
31 |
Â
"contrast": "^1.0.1",
|
32 |
Â
"li": "^1.3.0",
|
33 |
+
"lodash": "^4.17.15",
|
34 |
Â
"memize": "^1.0.5",
|
35 |
Â
"react": "^16.6.3",
|
36 |
Â
"react-error-boundary": "^1.2.3",
|
38 |
Â
"react-select": "^2.4.1",
|
39 |
Â
"react-transition-group": "^2.0.0",
|
40 |
Â
"recharts": "^1.5.0",
|
41 |
+
"rememo": "^3.0.0",
|
42 |
+
"uri-templates": "^0.2.0",
|
43 |
+
"uuid": "^3.3.3"
|
44 |
Â
},
|
45 |
Â
"devDependencies": {
|
46 |
Â
"@babel/core": "^7.3.3",
|
47 |
Â
"@babel/plugin-proposal-class-properties": "^7.3.3",
|
48 |
+
"@babel/plugin-proposal-export-default-from": "^7.8.3",
|
49 |
Â
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
50 |
Â
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
51 |
Â
"@babel/runtime-corejs2": "^7.3.1",
|
113 |
Â
"test-unit:update": "npm run test-unit -- --updateSnapshot",
|
114 |
Â
"test-unit:watch": "npm run test-unit -- --watch",
|
115 |
Â
"watch": "./node_modules/.bin/webpack --watch",
|
116 |
+
"test-up": "./bin/test-up.sh",
|
117 |
Â
"test-wpunit": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpunit",
|
118 |
Â
"test-acceptance": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run acceptance",
|
119 |
+
"test-cli": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run wpcli",
|
120 |
+
"test-upgrade": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept run upgrade",
|
121 |
+
"test-build": "docker-compose exec -T -w /var/www/html/wp-content/plugins/ithemes-security-pro wordpress ./vendor/bin/codecept build"
|
122 |
Â
}
|
123 |
Â
}
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
Â
=== iThemes Security (formerly Better WP Security) ===
|
2 |
Â
Contributors: ithemes, chrisjean, mattdanner, timothyblynjacobs
|
3 |
Â
Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
|
4 |
-
Requires at least:
|
5 |
-
Tested up to: 5.
|
6 |
-
Stable tag: 7.
|
7 |
-
Requires PHP: 5.
|
8 |
Â
License: GPLv2 or later
|
9 |
Â
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
Â
|
@@ -189,6 +189,27 @@ Free support may be available with the help of the community in the <a href="htt
|
|
189 |
Â
|
190 |
Â
== Changelog ==
|
191 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
192 |
Â
= 7.6.1 =
|
193 |
Â
* Bug Fix: Properly notate that iThemes Security requires PHP 5.5 or greater.
|
194 |
Â
|
@@ -569,5 +590,5 @@ Free support may be available with the help of the community in the <a href="htt
|
|
569 |
Â
|
570 |
Â
== Upgrade Notice ==
|
571 |
Â
|
572 |
-
= 7.
|
573 |
-
Version 7.
|
1 |
Â
=== iThemes Security (formerly Better WP Security) ===
|
2 |
Â
Contributors: ithemes, chrisjean, mattdanner, timothyblynjacobs
|
3 |
Â
Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
|
4 |
+
Requires at least: 5.2
|
5 |
+
Tested up to: 5.4
|
6 |
+
Stable tag: 7.7.0
|
7 |
+
Requires PHP: 5.6
|
8 |
Â
License: GPLv2 or later
|
9 |
Â
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
Â
|
189 |
Â
|
190 |
Â
== Changelog ==
|
191 |
Â
|
192 |
+
= 7.7.0 =
|
193 |
+
* Important: iThemes Security requires PHP 5.6 or greater and WordPress 5.2 or greater.
|
194 |
+
* New Feature: Save Time Securing WordPress With User Groups!
|
195 |
+
* New Feature: Simplified connection flow when setting up iThemes Sync.
|
196 |
+
* Enhancement: Add a warning if a WordPress Salt is set to an invalid value.
|
197 |
+
* Enhancement: Include child log items in the logs list table. These are helpful for debugging issues.
|
198 |
+
* Enhancement: Improve performance of the logs page on sites with large number of log items.
|
199 |
+
* Enhancement: Check tables exist after completing a DB upgrade.
|
200 |
+
* Tweak: When logging $_SERVER, only log a snapshot of available properties.
|
201 |
+
* Bug Fix: The "Mulisite Tweaks -> Hide Updates" setting prevented auto-updates from running with WP Cron.
|
202 |
+
* Bug Fix: Backup event was not added when the WP Cron Scheduler was reset manually.
|
203 |
+
* Bug Fix: Admin Notices Popover was not being hidden when clicking outside the Popover on WP 5.3.
|
204 |
+
* Bug Fix: New Password Requirements for already created accounts were not enforced until the second login.
|
205 |
+
* Bug Fix: Update admin notices styling to be compatible with WordPress 5.4.
|
206 |
+
* Bug Fix: Periodically clear expired opaque tokens.
|
207 |
+
* Bug Fix: Don't block registration page when "wp-signup.php" is the Hide Backend register slug.
|
208 |
+
* Bug Fix: Users with weak passwords would not be forced to change their password if the strong password requirement had been enabled after their password strength was checked.
|
209 |
+
* Bug Fix: Remove "get_magic_quotes()" call that existed for backwards compatibility with PHP versions 5.3 and earlier. This function call was causing a warning on PHP 7.4.
|
210 |
+
* Bug Fix: Warning when loading the settings page on PHP 7.4.
|
211 |
+
* Bug Fix: Warning when loading the debug page on PHP 7.4.
|
212 |
+
|
213 |
Â
= 7.6.1 =
|
214 |
Â
* Bug Fix: Properly notate that iThemes Security requires PHP 5.5 or greater.
|
215 |
Â
|
590 |
Â
|
591 |
Â
== Upgrade Notice ==
|
592 |
Â
|
593 |
+
= 7.7.0 =
|
594 |
+
Version 7.7.0 contains new features and bug fixes. It is recommended for all users.
|
vendor-prod/autoload.php
ADDED
@@ -0,0 +1,7 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload.php @generated by Composer
|
4 |
+
|
5 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
+
|
7 |
+
return ComposerAutoloaderInit35a2bd4feb347da0d3ea2d8ef023082f::getLoader();
|
vendor-prod/composer/ClassLoader.php
ADDED
@@ -0,0 +1,445 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Composer.
|
5 |
+
*
|
6 |
+
* (c) Nils Adermann <naderman@naderman.de>
|
7 |
+
* Jordi Boggiano <j.boggiano@seld.be>
|
8 |
+
*
|
9 |
+
* For the full copyright and license information, please view the LICENSE
|
10 |
+
* file that was distributed with this source code.
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace Composer\Autoload;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
17 |
+
*
|
18 |
+
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
+
*
|
20 |
+
* // register classes with namespaces
|
21 |
+
* $loader->add('Symfony\Component', __DIR__.'/component');
|
22 |
+
* $loader->add('Symfony', __DIR__.'/framework');
|
23 |
+
*
|
24 |
+
* // activate the autoloader
|
25 |
+
* $loader->register();
|
26 |
+
*
|
27 |
+
* // to enable searching the include path (eg. for PEAR packages)
|
28 |
+
* $loader->setUseIncludePath(true);
|
29 |
+
*
|
30 |
+
* In this example, if you try to use a class in the Symfony\Component
|
31 |
+
* namespace or one of its children (Symfony\Component\Console for instance),
|
32 |
+
* the autoloader will first look for the class under the component/
|
33 |
+
* directory, and it will then fallback to the framework/ directory if not
|
34 |
+
* found before giving up.
|
35 |
+
*
|
36 |
+
* This class is loosely based on the Symfony UniversalClassLoader.
|
37 |
+
*
|
38 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see http://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see http://www.php-fig.org/psr/psr-4/
|
42 |
+
*/
|
43 |
+
class ClassLoader
|
44 |
+
{
|
45 |
+
// PSR-4
|
46 |
+
private $prefixLengthsPsr4 = array();
|
47 |
+
private $prefixDirsPsr4 = array();
|
48 |
+
private $fallbackDirsPsr4 = array();
|
49 |
+
|
50 |
+
// PSR-0
|
51 |
+
private $prefixesPsr0 = array();
|
52 |
+
private $fallbackDirsPsr0 = array();
|
53 |
+
|
54 |
+
private $useIncludePath = false;
|
55 |
+
private $classMap = array();
|
56 |
+
private $classMapAuthoritative = false;
|
57 |
+
private $missingClasses = array();
|
58 |
+
private $apcuPrefix;
|
59 |
+
|
60 |
+
public function getPrefixes()
|
61 |
+
{
|
62 |
+
if (!empty($this->prefixesPsr0)) {
|
63 |
+
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
64 |
+
}
|
65 |
+
|
66 |
+
return array();
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getPrefixesPsr4()
|
70 |
+
{
|
71 |
+
return $this->prefixDirsPsr4;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function getFallbackDirs()
|
75 |
+
{
|
76 |
+
return $this->fallbackDirsPsr0;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function getFallbackDirsPsr4()
|
80 |
+
{
|
81 |
+
return $this->fallbackDirsPsr4;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function getClassMap()
|
85 |
+
{
|
86 |
+
return $this->classMap;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @param array $classMap Class to filename map
|
91 |
+
*/
|
92 |
+
public function addClassMap(array $classMap)
|
93 |
+
{
|
94 |
+
if ($this->classMap) {
|
95 |
+
$this->classMap = array_merge($this->classMap, $classMap);
|
96 |
+
} else {
|
97 |
+
$this->classMap = $classMap;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Registers a set of PSR-0 directories for a given prefix, either
|
103 |
+
* appending or prepending to the ones previously set for this prefix.
|
104 |
+
*
|
105 |
+
* @param string $prefix The prefix
|
106 |
+
* @param array|string $paths The PSR-0 root directories
|
107 |
+
* @param bool $prepend Whether to prepend the directories
|
108 |
+
*/
|
109 |
+
public function add($prefix, $paths, $prepend = false)
|
110 |
+
{
|
111 |
+
if (!$prefix) {
|
112 |
+
if ($prepend) {
|
113 |
+
$this->fallbackDirsPsr0 = array_merge(
|
114 |
+
(array) $paths,
|
115 |
+
$this->fallbackDirsPsr0
|
116 |
+
);
|
117 |
+
} else {
|
118 |
+
$this->fallbackDirsPsr0 = array_merge(
|
119 |
+
$this->fallbackDirsPsr0,
|
120 |
+
(array) $paths
|
121 |
+
);
|
122 |
+
}
|
123 |
+
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
|
127 |
+
$first = $prefix[0];
|
128 |
+
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
129 |
+
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
130 |
+
|
131 |
+
return;
|
132 |
+
}
|
133 |
+
if ($prepend) {
|
134 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
135 |
+
(array) $paths,
|
136 |
+
$this->prefixesPsr0[$first][$prefix]
|
137 |
+
);
|
138 |
+
} else {
|
139 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
140 |
+
$this->prefixesPsr0[$first][$prefix],
|
141 |
+
(array) $paths
|
142 |
+
);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Registers a set of PSR-4 directories for a given namespace, either
|
148 |
+
* appending or prepending to the ones previously set for this namespace.
|
149 |
+
*
|
150 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
151 |
+
* @param array|string $paths The PSR-4 base directories
|
152 |
+
* @param bool $prepend Whether to prepend the directories
|
153 |
+
*
|
154 |
+
* @throws \InvalidArgumentException
|
155 |
+
*/
|
156 |
+
public function addPsr4($prefix, $paths, $prepend = false)
|
157 |
+
{
|
158 |
+
if (!$prefix) {
|
159 |
+
// Register directories for the root namespace.
|
160 |
+
if ($prepend) {
|
161 |
+
$this->fallbackDirsPsr4 = array_merge(
|
162 |
+
(array) $paths,
|
163 |
+
$this->fallbackDirsPsr4
|
164 |
+
);
|
165 |
+
} else {
|
166 |
+
$this->fallbackDirsPsr4 = array_merge(
|
167 |
+
$this->fallbackDirsPsr4,
|
168 |
+
(array) $paths
|
169 |
+
);
|
170 |
+
}
|
171 |
+
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
172 |
+
// Register directories for a new namespace.
|
173 |
+
$length = strlen($prefix);
|
174 |
+
if ('\\' !== $prefix[$length - 1]) {
|
175 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
176 |
+
}
|
177 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
178 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
179 |
+
} elseif ($prepend) {
|
180 |
+
// Prepend directories for an already registered namespace.
|
181 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
182 |
+
(array) $paths,
|
183 |
+
$this->prefixDirsPsr4[$prefix]
|
184 |
+
);
|
185 |
+
} else {
|
186 |
+
// Append directories for an already registered namespace.
|
187 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
188 |
+
$this->prefixDirsPsr4[$prefix],
|
189 |
+
(array) $paths
|
190 |
+
);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Registers a set of PSR-0 directories for a given prefix,
|
196 |
+
* replacing any others previously set for this prefix.
|
197 |
+
*
|
198 |
+
* @param string $prefix The prefix
|
199 |
+
* @param array|string $paths The PSR-0 base directories
|
200 |
+
*/
|
201 |
+
public function set($prefix, $paths)
|
202 |
+
{
|
203 |
+
if (!$prefix) {
|
204 |
+
$this->fallbackDirsPsr0 = (array) $paths;
|
205 |
+
} else {
|
206 |
+
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Registers a set of PSR-4 directories for a given namespace,
|
212 |
+
* replacing any others previously set for this namespace.
|
213 |
+
*
|
214 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
215 |
+
* @param array|string $paths The PSR-4 base directories
|
216 |
+
*
|
217 |
+
* @throws \InvalidArgumentException
|
218 |
+
*/
|
219 |
+
public function setPsr4($prefix, $paths)
|
220 |
+
{
|
221 |
+
if (!$prefix) {
|
222 |
+
$this->fallbackDirsPsr4 = (array) $paths;
|
223 |
+
} else {
|
224 |
+
$length = strlen($prefix);
|
225 |
+
if ('\\' !== $prefix[$length - 1]) {
|
226 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
227 |
+
}
|
228 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
229 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Turns on searching the include path for class files.
|
235 |
+
*
|
236 |
+
* @param bool $useIncludePath
|
237 |
+
*/
|
238 |
+
public function setUseIncludePath($useIncludePath)
|
239 |
+
{
|
240 |
+
$this->useIncludePath = $useIncludePath;
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Can be used to check if the autoloader uses the include path to check
|
245 |
+
* for classes.
|
246 |
+
*
|
247 |
+
* @return bool
|
248 |
+
*/
|
249 |
+
public function getUseIncludePath()
|
250 |
+
{
|
251 |
+
return $this->useIncludePath;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Turns off searching the prefix and fallback directories for classes
|
256 |
+
* that have not been registered with the class map.
|
257 |
+
*
|
258 |
+
* @param bool $classMapAuthoritative
|
259 |
+
*/
|
260 |
+
public function setClassMapAuthoritative($classMapAuthoritative)
|
261 |
+
{
|
262 |
+
$this->classMapAuthoritative = $classMapAuthoritative;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Should class lookup fail if not found in the current class map?
|
267 |
+
*
|
268 |
+
* @return bool
|
269 |
+
*/
|
270 |
+
public function isClassMapAuthoritative()
|
271 |
+
{
|
272 |
+
return $this->classMapAuthoritative;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
277 |
+
*
|
278 |
+
* @param string|null $apcuPrefix
|
279 |
+
*/
|
280 |
+
public function setApcuPrefix($apcuPrefix)
|
281 |
+
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* The APCu prefix in use, or null if APCu caching is not enabled.
|
287 |
+
*
|
288 |
+
* @return string|null
|
289 |
+
*/
|
290 |
+
public function getApcuPrefix()
|
291 |
+
{
|
292 |
+
return $this->apcuPrefix;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Registers this instance as an autoloader.
|
297 |
+
*
|
298 |
+
* @param bool $prepend Whether to prepend the autoloader or not
|
299 |
+
*/
|
300 |
+
public function register($prepend = false)
|
301 |
+
{
|
302 |
+
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Unregisters this instance as an autoloader.
|
307 |
+
*/
|
308 |
+
public function unregister()
|
309 |
+
{
|
310 |
+
spl_autoload_unregister(array($this, 'loadClass'));
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Loads the given class or interface.
|
315 |
+
*
|
316 |
+
* @param string $class The name of the class
|
317 |
+
* @return bool|null True if loaded, null otherwise
|
318 |
+
*/
|
319 |
+
public function loadClass($class)
|
320 |
+
{
|
321 |
+
if ($file = $this->findFile($class)) {
|
322 |
+
includeFile($file);
|
323 |
+
|
324 |
+
return true;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Finds the path to the file where the class is defined.
|
330 |
+
*
|
331 |
+
* @param string $class The name of the class
|
332 |
+
*
|
333 |
+
* @return string|false The path if found, false otherwise
|
334 |
+
*/
|
335 |
+
public function findFile($class)
|
336 |
+
{
|
337 |
+
// class map lookup
|
338 |
+
if (isset($this->classMap[$class])) {
|
339 |
+
return $this->classMap[$class];
|
340 |
+
}
|
341 |
+
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
342 |
+
return false;
|
343 |
+
}
|
344 |
+
if (null !== $this->apcuPrefix) {
|
345 |
+
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
346 |
+
if ($hit) {
|
347 |
+
return $file;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
$file = $this->findFileWithExtension($class, '.php');
|
352 |
+
|
353 |
+
// Search for Hack files if we are running on HHVM
|
354 |
+
if (false === $file && defined('HHVM_VERSION')) {
|
355 |
+
$file = $this->findFileWithExtension($class, '.hh');
|
356 |
+
}
|
357 |
+
|
358 |
+
if (null !== $this->apcuPrefix) {
|
359 |
+
apcu_add($this->apcuPrefix.$class, $file);
|
360 |
+
}
|
361 |
+
|
362 |
+
if (false === $file) {
|
363 |
+
// Remember that this class does not exist.
|
364 |
+
$this->missingClasses[$class] = true;
|
365 |
+
}
|
366 |
+
|
367 |
+
return $file;
|
368 |
+
}
|
369 |
+
|
370 |
+
private function findFileWithExtension($class, $ext)
|
371 |
+
{
|
372 |
+
// PSR-4 lookup
|
373 |
+
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
374 |
+
|
375 |
+
$first = $class[0];
|
376 |
+
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
+
$subPath = $class;
|
378 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
+
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath . '\\';
|
381 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
+
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
384 |
+
if (file_exists($file = $dir . $pathEnd)) {
|
385 |
+
return $file;
|
386 |
+
}
|
387 |
+
}
|
388 |
+
}
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
// PSR-4 fallback dirs
|
393 |
+
foreach ($this->fallbackDirsPsr4 as $dir) {
|
394 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
395 |
+
return $file;
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
// PSR-0 lookup
|
400 |
+
if (false !== $pos = strrpos($class, '\\')) {
|
401 |
+
// namespaced class name
|
402 |
+
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
403 |
+
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
404 |
+
} else {
|
405 |
+
// PEAR-like class name
|
406 |
+
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
407 |
+
}
|
408 |
+
|
409 |
+
if (isset($this->prefixesPsr0[$first])) {
|
410 |
+
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
411 |
+
if (0 === strpos($class, $prefix)) {
|
412 |
+
foreach ($dirs as $dir) {
|
413 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
414 |
+
return $file;
|
415 |
+
}
|
416 |
+
}
|
417 |
+
}
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
// PSR-0 fallback dirs
|
422 |
+
foreach ($this->fallbackDirsPsr0 as $dir) {
|
423 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
424 |
+
return $file;
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
// PSR-0 include paths.
|
429 |
+
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
430 |
+
return $file;
|
431 |
+
}
|
432 |
+
|
433 |
+
return false;
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Scope isolated include.
|
439 |
+
*
|
440 |
+
* Prevents access to $this/self from included files.
|
441 |
+
*/
|
442 |
+
function includeFile($file)
|
443 |
+
{
|
444 |
+
include $file;
|
445 |
+
}
|
vendor-prod/composer/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
+
|
4 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
+
of this software and associated documentation files (the "Software"), to deal
|
6 |
+
in the Software without restriction, including without limitation the rights
|
7 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
9 |
+
to do so, subject to the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included in all
|
12 |
+
copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 |
+
THE SOFTWARE.
|
21 |
+
|
vendor-prod/composer/autoload_classmap.php
ADDED
@@ -0,0 +1,327 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_classmap.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'ITSEC_404_Detection_Settings_Page' => $baseDir . '/core/modules/404-detection/settings-page.php',
|
10 |
+
'ITSEC_Admin_Notice' => $baseDir . '/core/lib/admin-notices/interface-itsec-admin-notice.php',
|
11 |
+
'ITSEC_Admin_Notice_Action' => $baseDir . '/core/lib/admin-notices/actions/interface-itsec-admin-notice-action.php',
|
12 |
+
'ITSEC_Admin_Notice_Action_Callback' => $baseDir . '/core/lib/admin-notices/actions/class-itsec-admin-notice-action-callback.php',
|
13 |
+
'ITSEC_Admin_Notice_Action_Link' => $baseDir . '/core/lib/admin-notices/actions/class-itsec-admin-notice-action-link.php',
|
14 |
+
'ITSEC_Admin_Notice_Callback' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-callback.php',
|
15 |
+
'ITSEC_Admin_Notice_Context' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-context.php',
|
16 |
+
'ITSEC_Admin_Notice_Globally_Dismissible' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-globally-dismissible.php',
|
17 |
+
'ITSEC_Admin_Notice_Highlighted_Log' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-highlighted-log.php',
|
18 |
+
'ITSEC_Admin_Notice_Managers_Only' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-managers-only.php',
|
19 |
+
'ITSEC_Admin_Notice_Network_Brute_Force_Promo' => $baseDir . '/core/modules/global/notices.php',
|
20 |
+
'ITSEC_Admin_Notice_New_Feature_Core' => $baseDir . '/core/modules/core/notices.php',
|
21 |
+
'ITSEC_Admin_Notice_Remind_Me' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-remind-me.php',
|
22 |
+
'ITSEC_Admin_Notice_Screen_Blacklist' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-screen-blacklist.php',
|
23 |
+
'ITSEC_Admin_Notice_Static' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-static.php',
|
24 |
+
'ITSEC_Admin_Notice_User_Dismissible' => $baseDir . '/core/lib/admin-notices/class-itsec-admin-notice-user-dismissible.php',
|
25 |
+
'ITSEC_Admin_Notices' => $baseDir . '/core/modules/core/class-itsec-admin-notices.php',
|
26 |
+
'ITSEC_Admin_User_Settings' => $baseDir . '/core/modules/admin-user/settings.php',
|
27 |
+
'ITSEC_Admin_User_Settings_Page' => $baseDir . '/core/modules/admin-user/settings-page.php',
|
28 |
+
'ITSEC_Admin_User_Validator' => $baseDir . '/core/modules/admin-user/validator.php',
|
29 |
+
'ITSEC_Away_Mode' => $baseDir . '/core/modules/away-mode/class-itsec-away-mode.php',
|
30 |
+
'ITSEC_Away_Mode_Logs' => $baseDir . '/core/modules/away-mode/logs.php',
|
31 |
+
'ITSEC_Away_Mode_Settings' => $baseDir . '/core/modules/away-mode/settings.php',
|
32 |
+
'ITSEC_Away_Mode_Settings_Page' => $baseDir . '/core/modules/away-mode/settings-page.php',
|
33 |
+
'ITSEC_Away_Mode_Setup' => $baseDir . '/core/modules/away-mode/setup.php',
|
34 |
+
'ITSEC_Away_Mode_Utilities' => $baseDir . '/core/modules/away-mode/utilities.php',
|
35 |
+
'ITSEC_Away_Mode_Validator' => $baseDir . '/core/modules/away-mode/validator.php',
|
36 |
+
'ITSEC_Backup' => $baseDir . '/core/modules/backup/class-itsec-backup.php',
|
37 |
+
'ITSEC_Backup_Logs' => $baseDir . '/core/modules/backup/logs.php',
|
38 |
+
'ITSEC_Backup_Privacy' => $baseDir . '/core/modules/backup/privacy.php',
|
39 |
+
'ITSEC_Backup_Settings' => $baseDir . '/core/modules/backup/settings.php',
|
40 |
+
'ITSEC_Backup_Settings_Page' => $baseDir . '/core/modules/backup/settings-page.php',
|
41 |
+
'ITSEC_Backup_Setup' => $baseDir . '/core/modules/backup/setup.php',
|
42 |
+
'ITSEC_Backup_Validator' => $baseDir . '/core/modules/backup/validator.php',
|
43 |
+
'ITSEC_Ban_Users' => $baseDir . '/core/modules/ban-users/class-itsec-ban-users.php',
|
44 |
+
'ITSEC_Ban_Users_Config_Generators' => $baseDir . '/core/modules/ban-users/config-generators.php',
|
45 |
+
'ITSEC_Ban_Users_Settings' => $baseDir . '/core/modules/ban-users/settings.php',
|
46 |
+
'ITSEC_Ban_Users_Settings_Page' => $baseDir . '/core/modules/ban-users/settings-page.php',
|
47 |
+
'ITSEC_Ban_Users_Setup' => $baseDir . '/core/modules/ban-users/setup.php',
|
48 |
+
'ITSEC_Ban_Users_Validator' => $baseDir . '/core/modules/ban-users/validator.php',
|
49 |
+
'ITSEC_Brute_Force' => $baseDir . '/core/modules/brute-force/class-itsec-brute-force.php',
|
50 |
+
'ITSEC_Brute_Force_Logs' => $baseDir . '/core/modules/brute-force/logs.php',
|
51 |
+
'ITSEC_Brute_Force_Settings' => $baseDir . '/core/modules/brute-force/settings.php',
|
52 |
+
'ITSEC_Brute_Force_Settings_Page' => $baseDir . '/core/modules/brute-force/settings-page.php',
|
53 |
+
'ITSEC_Brute_Force_Setup' => $baseDir . '/core/modules/brute-force/setup.php',
|
54 |
+
'ITSEC_Brute_Force_Validator' => $baseDir . '/core/modules/brute-force/validator.php',
|
55 |
+
'ITSEC_Content_Directory_Settings_Page' => $baseDir . '/core/modules/content-directory/settings-page.php',
|
56 |
+
'ITSEC_Content_Directory_Utility' => $baseDir . '/core/modules/content-directory/utility.php',
|
57 |
+
'ITSEC_Core_Active' => $baseDir . '/core/modules/core/class-itsec-core-active.php',
|
58 |
+
'ITSEC_Core_Admin' => $baseDir . '/core/modules/core/class-itsec-core-admin.php',
|
59 |
+
'ITSEC_Core_Server_Config_Rules_Settings_Page' => $baseDir . '/core/modules/file-writing/settings-page.php',
|
60 |
+
'ITSEC_Core_WPConfig_File_Settings_Page' => $baseDir . '/core/modules/file-writing/settings-page.php',
|
61 |
+
'ITSEC_Database_Prefix_Settings_Page' => $baseDir . '/core/modules/database-prefix/settings-page.php',
|
62 |
+
'ITSEC_Database_Prefix_Utility' => $baseDir . '/core/modules/database-prefix/utility.php',
|
63 |
+
'ITSEC_Debug' => $baseDir . '/core/lib/debug.php',
|
64 |
+
'ITSEC_Email_Confirmation' => $baseDir . '/core/modules/email-confirmation/class-itsec-email-confirmation.php',
|
65 |
+
'ITSEC_Feature_Flags_Settings_Page' => $baseDir . '/core/modules/feature-flags/settings-page.php',
|
66 |
+
'ITSEC_File_Change' => $baseDir . '/core/modules/file-change/class-itsec-file-change.php',
|
67 |
+
'ITSEC_File_Change_Admin' => $baseDir . '/core/modules/file-change/admin.php',
|
68 |
+
'ITSEC_File_Change_Chunk_Scanner' => $baseDir . '/core/modules/file-change/lib/chunk-scanner.php',
|
69 |
+
'ITSEC_File_Change_Hash_Comparator' => $baseDir . '/core/modules/file-change/lib/hash-comparator.php',
|
70 |
+
'ITSEC_File_Change_Hash_Comparator_Chain' => $baseDir . '/core/modules/file-change/lib/hash-comparator-chain.php',
|
71 |
+
'ITSEC_File_Change_Hash_Comparator_Loadable' => $baseDir . '/core/modules/file-change/lib/hash-comparator-loadable.php',
|
72 |
+
'ITSEC_File_Change_Hash_Comparator_Managed_Files' => $baseDir . '/core/modules/file-change/lib/hash-comparator-managed-files.php',
|
73 |
+
'ITSEC_File_Change_Hash_Loading_Failed_Exception' => $baseDir . '/core/modules/file-change/lib/hash-loading-failed-exception.php',
|
74 |
+
'ITSEC_File_Change_Logs' => $baseDir . '/core/modules/file-change/logs.php',
|
75 |
+
'ITSEC_File_Change_Package' => $baseDir . '/core/modules/file-change/lib/package.php',
|
76 |
+
'ITSEC_File_Change_Package_Core' => $baseDir . '/core/modules/file-change/lib/package-core.php',
|
77 |
+
'ITSEC_File_Change_Package_Factory' => $baseDir . '/core/modules/file-change/lib/package-factory.php',
|
78 |
+
'ITSEC_File_Change_Package_Plugin' => $baseDir . '/core/modules/file-change/lib/package-plugin.php',
|
79 |
+
'ITSEC_File_Change_Package_System' => $baseDir . '/core/modules/file-change/lib/package-system.php',
|
80 |
+
'ITSEC_File_Change_Package_Theme' => $baseDir . '/core/modules/file-change/lib/package-theme.php',
|
81 |
+
'ITSEC_File_Change_Package_Unknown' => $baseDir . '/core/modules/file-change/lib/package-unknown.php',
|
82 |
+
'ITSEC_File_Change_Scanner' => $baseDir . '/core/modules/file-change/scanner.php',
|
83 |
+
'ITSEC_File_Change_Settings' => $baseDir . '/core/modules/file-change/settings.php',
|
84 |
+
'ITSEC_File_Change_Settings_Page' => $baseDir . '/core/modules/file-change/settings-page.php',
|
85 |
+
'ITSEC_File_Change_Setup' => $baseDir . '/core/modules/file-change/setup.php',
|
86 |
+
'ITSEC_File_Change_Validator' => $baseDir . '/core/modules/file-change/validator.php',
|
87 |
+
'ITSEC_File_Permissions_Settings_Page' => $baseDir . '/core/modules/file-permissions/settings-page.php',
|
88 |
+
'ITSEC_Fingerprint' => $baseDir . '/core/lib/fingerprinting/class-itsec-fingerprint.php',
|
89 |
+
'ITSEC_Fingerprint_Comparison' => $baseDir . '/core/lib/fingerprinting/class-itsec-fingerprint-comparison.php',
|
90 |
+
'ITSEC_Fingerprint_Source' => $baseDir . '/core/lib/fingerprinting/interface-itsec-fingerprint-source.php',
|
91 |
+
'ITSEC_Fingerprint_Value' => $baseDir . '/core/lib/fingerprinting/class-itsec-fingerprint-value.php',
|
92 |
+
'ITSEC_Form' => $baseDir . '/core/lib/form.php',
|
93 |
+
'ITSEC_Four_Oh_Four' => $baseDir . '/core/modules/404-detection/class-itsec-four-oh-four.php',
|
94 |
+
'ITSEC_Four_Oh_Four_Logs' => $baseDir . '/core/modules/404-detection/logs.php',
|
95 |
+
'ITSEC_Four_Oh_Four_Settings' => $baseDir . '/core/modules/404-detection/settings.php',
|
96 |
+
'ITSEC_Four_Oh_Four_Setup' => $baseDir . '/core/modules/404-detection/setup.php',
|
97 |
+
'ITSEC_Four_Oh_Four_Validator' => $baseDir . '/core/modules/404-detection/validator.php',
|
98 |
+
'ITSEC_Geolocator' => $baseDir . '/core/lib/geolocation/interface-itsec-geolocator.php',
|
99 |
+
'ITSEC_Geolocator_Chain' => $baseDir . '/core/lib/geolocation/class-itsec-geolocator-chain.php',
|
100 |
+
'ITSEC_Geolocator_Page_Cache' => $baseDir . '/core/lib/geolocation/class-itsec-geolocator-page-cache.php',
|
101 |
+
'ITSEC_Global_Logs' => $baseDir . '/core/modules/global/logs.php',
|
102 |
+
'ITSEC_Global_Privacy' => $baseDir . '/core/modules/global/privacy.php',
|
103 |
+
'ITSEC_Global_Settings_New' => $baseDir . '/core/modules/global/settings.php',
|
104 |
+
'ITSEC_Global_Settings_Page' => $baseDir . '/core/modules/global/settings-page.php',
|
105 |
+
'ITSEC_Global_Setup' => $baseDir . '/core/modules/global/setup.php',
|
106 |
+
'ITSEC_Global_Validator' => $baseDir . '/core/modules/global/validator.php',
|
107 |
+
'ITSEC_Hide_Backend' => $baseDir . '/core/modules/hide-backend/class-itsec-hide-backend.php',
|
108 |
+
'ITSEC_Hide_Backend_Privacy' => $baseDir . '/core/modules/hide-backend/privacy.php',
|
109 |
+
'ITSEC_Hide_Backend_Settings' => $baseDir . '/core/modules/hide-backend/settings.php',
|
110 |
+
'ITSEC_Hide_Backend_Settings_Page' => $baseDir . '/core/modules/hide-backend/settings-page.php',
|
111 |
+
'ITSEC_Hide_Backend_Setup' => $baseDir . '/core/modules/hide-backend/setup.php',
|
112 |
+
'ITSEC_Hide_Backend_Validator' => $baseDir . '/core/modules/hide-backend/validator.php',
|
113 |
+
'ITSEC_IPCheck' => $baseDir . '/core/modules/ipcheck/class-itsec-ipcheck.php',
|
114 |
+
'ITSEC_IPCheck_Logs' => $baseDir . '/core/modules/ipcheck/logs.php',
|
115 |
+
'ITSEC_IPCheck_Setup' => $baseDir . '/core/modules/ipcheck/setup.php',
|
116 |
+
'ITSEC_IP_Detector' => $baseDir . '/core/lib/class-itsec-ip-detector.php',
|
117 |
+
'ITSEC_Import_Export_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
118 |
+
'ITSEC_Ithemes_Sync_Upgrader_Skin' => $baseDir . '/core/modules/sync-connect/includes/upgrader-skin.php',
|
119 |
+
'ITSEC_Job' => $baseDir . '/core/lib/class-itsec-job.php',
|
120 |
+
'ITSEC_Lib_Admin_Notices' => $baseDir . '/core/lib/class-itsec-lib-admin-notices.php',
|
121 |
+
'ITSEC_Lib_Browser' => $baseDir . '/core/lib/class-itsec-lib-browser.php',
|
122 |
+
'ITSEC_Lib_Canonical_Roles' => $baseDir . '/core/lib/class-itsec-lib-canonical-roles.php',
|
123 |
+
'ITSEC_Lib_Config_File' => $baseDir . '/core/lib/class-itsec-lib-config-file.php',
|
124 |
+
'ITSEC_Lib_Directory' => $baseDir . '/core/lib/class-itsec-lib-directory.php',
|
125 |
+
'ITSEC_Lib_Distributed_Storage' => $baseDir . '/core/lib/class-itsec-lib-distributed-storage.php',
|
126 |
+
'ITSEC_Lib_Distributed_Storage_Cursor' => $baseDir . '/core/lib/class-itsec-lib-distributed-storage.php',
|
127 |
+
'ITSEC_Lib_Email_Confirmation' => $baseDir . '/core/lib/class-itsec-lib-email-confirmation.php',
|
128 |
+
'ITSEC_Lib_Feature_Flags' => $baseDir . '/core/lib/class-itsec-lib-feature-flags.php',
|
129 |
+
'ITSEC_Lib_File' => $baseDir . '/core/lib/class-itsec-lib-file.php',
|
130 |
+
'ITSEC_Lib_Fingerprinting' => $baseDir . '/core/lib/class-itsec-lib-fingerprinting.php',
|
131 |
+
'ITSEC_Lib_Geolocation' => $baseDir . '/core/lib/class-itsec-lib-geolocation.php',
|
132 |
+
'ITSEC_Lib_Highlighted_Logs' => $baseDir . '/core/lib/class-itsec-lib-highlighted-logs.php',
|
133 |
+
'ITSEC_Lib_IP_Detector' => $baseDir . '/core/lib/class-itsec-lib-ip-detector.php',
|
134 |
+
'ITSEC_Lib_IP_Tools' => $baseDir . '/core/lib/class-itsec-lib-ip-tools.php',
|
135 |
+
'ITSEC_Lib_Login' => $baseDir . '/core/lib/class-itsec-lib-login.php',
|
136 |
+
'ITSEC_Lib_Login_Interstitial' => $baseDir . '/core/lib/class-itsec-lib-login-interstitial.php',
|
137 |
+
'ITSEC_Lib_Opaque_Tokens' => $baseDir . '/core/lib/class-itsec-lib-opaque-tokens.php',
|
138 |
+
'ITSEC_Lib_Password_Requirements' => $baseDir . '/core/lib/class-itsec-lib-password-requirements.php',
|
139 |
+
'ITSEC_Lib_REST' => $baseDir . '/core/lib/class-itsec-lib-rest.php',
|
140 |
+
'ITSEC_Lib_Remote_Messages' => $baseDir . '/core/lib/class-itsec-lib-remote-messages.php',
|
141 |
+
'ITSEC_Lib_Static_Map_API' => $baseDir . '/core/lib/class-itsec-lib-static-map-api.php',
|
142 |
+
'ITSEC_Lib_User_Activity' => $baseDir . '/core/lib/class-itsec-lib-user-activity.php',
|
143 |
+
'ITSEC_Lib_Utility' => $baseDir . '/core/lib/class-itsec-lib-utility.php',
|
144 |
+
'ITSEC_Log' => $baseDir . '/core/lib/log.php',
|
145 |
+
'ITSEC_Log_Util' => $baseDir . '/core/lib/log-util.php',
|
146 |
+
'ITSEC_Login_Interstitial' => $baseDir . '/core/lib/login-interstitial/abstract-itsec-login-interstitial.php',
|
147 |
+
'ITSEC_Login_Interstitial_Config_Driven' => $baseDir . '/core/lib/login-interstitial/class-itsec-login-interstitial-config-driven.php',
|
148 |
+
'ITSEC_Login_Interstitial_Session' => $baseDir . '/core/lib/login-interstitial/class-itsec-login-interstitial-session.php',
|
149 |
+
'ITSEC_Magic_Links_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
150 |
+
'ITSEC_Mail' => $baseDir . '/core/lib/class-itsec-mail.php',
|
151 |
+
'ITSEC_Malware' => $baseDir . '/core/modules/malware/class-itsec-malware.php',
|
152 |
+
'ITSEC_Malware_Logs' => $baseDir . '/core/modules/malware/logs.php',
|
153 |
+
'ITSEC_Malware_Privacy' => $baseDir . '/core/modules/malware/privacy.php',
|
154 |
+
'ITSEC_Malware_Scan_Results_Template' => $baseDir . '/core/modules/malware/class-itsec-malware-scan-results-template.php',
|
155 |
+
'ITSEC_Malware_Scanner' => $baseDir . '/core/modules/malware/class-itsec-malware-scanner.php',
|
156 |
+
'ITSEC_Malware_Scheduling_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
157 |
+
'ITSEC_Malware_Setup' => $baseDir . '/core/modules/malware/setup.php',
|
158 |
+
'ITSEC_Multisite_Tweaks' => $baseDir . '/core/modules/multisite-tweaks/class-itsec-multisite-tweaks.php',
|
159 |
+
'ITSEC_Multisite_Tweaks_Settings' => $baseDir . '/core/modules/multisite-tweaks/settings.php',
|
160 |
+
'ITSEC_Multisite_Tweaks_Settings_Page' => $baseDir . '/core/modules/multisite-tweaks/settings-page.php',
|
161 |
+
'ITSEC_Multisite_Tweaks_Setup' => $baseDir . '/core/modules/multisite-tweaks/setup.php',
|
162 |
+
'ITSEC_Multisite_Tweaks_Validator' => $baseDir . '/core/modules/multisite-tweaks/validator.php',
|
163 |
+
'ITSEC_Mutex' => $baseDir . '/core/lib/class-itsec-mutex.php',
|
164 |
+
'ITSEC_Network_Brute_Force_Settings' => $baseDir . '/core/modules/ipcheck/settings.php',
|
165 |
+
'ITSEC_Network_Brute_Force_Settings_Page' => $baseDir . '/core/modules/ipcheck/settings-page.php',
|
166 |
+
'ITSEC_Network_Brute_Force_Utilities' => $baseDir . '/core/modules/ipcheck/utilities.php',
|
167 |
+
'ITSEC_Network_Brute_Force_Validator' => $baseDir . '/core/modules/ipcheck/validator.php',
|
168 |
+
'ITSEC_Network_Bruteforce_Privacy' => $baseDir . '/core/modules/ipcheck/privacy.php',
|
169 |
+
'ITSEC_Notification_Center' => $baseDir . '/core/modules/notification-center/class-notification-center.php',
|
170 |
+
'ITSEC_Notification_Center_Debug' => $baseDir . '/core/modules/notification-center/debug.php',
|
171 |
+
'ITSEC_Notification_Center_Logs' => $baseDir . '/core/modules/notification-center/logs.php',
|
172 |
+
'ITSEC_Notification_Center_Settings' => $baseDir . '/core/modules/notification-center/settings.php',
|
173 |
+
'ITSEC_Notification_Center_Settings_Page' => $baseDir . '/core/modules/notification-center/settings-page.php',
|
174 |
+
'ITSEC_Notification_Center_Setup' => $baseDir . '/core/modules/notification-center/setup.php',
|
175 |
+
'ITSEC_Notification_Center_Validator' => $baseDir . '/core/modules/notification-center/validator.php',
|
176 |
+
'ITSEC_Password_Requirements' => $baseDir . '/core/modules/password-requirements/class-itsec-password-requirements.php',
|
177 |
+
'ITSEC_Password_Requirements_Settings' => $baseDir . '/core/modules/password-requirements/settings.php',
|
178 |
+
'ITSEC_Password_Requirements_Settings_Page' => $baseDir . '/core/modules/password-requirements/settings-page.php',
|
179 |
+
'ITSEC_Password_Requirements_Validator' => $baseDir . '/core/modules/password-requirements/validator.php',
|
180 |
+
'ITSEC_Passwordless_Login_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
181 |
+
'ITSEC_Privacy' => $baseDir . '/core/modules/privacy/class-itsec-privacy.php',
|
182 |
+
'ITSEC_Privacy_Util' => $baseDir . '/core/modules/privacy/util.php',
|
183 |
+
'ITSEC_Privilege_Escalation_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
184 |
+
'ITSEC_Pro_Setup' => $baseDir . '/core/modules/pro/setup.php',
|
185 |
+
'ITSEC_REST_Core_Admin_Notices_Controller' => $baseDir . '/core/modules/core/class-rest-core-admin-notices-controller.php',
|
186 |
+
'ITSEC_Recaptcha_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
187 |
+
'ITSEC_SSL' => $baseDir . '/core/modules/ssl/class-itsec-ssl.php',
|
188 |
+
'ITSEC_SSL_Admin' => $baseDir . '/core/modules/ssl/class-itsec-ssl-admin.php',
|
189 |
+
'ITSEC_SSL_Settings' => $baseDir . '/core/modules/ssl/settings.php',
|
190 |
+
'ITSEC_SSL_Settings_Page' => $baseDir . '/core/modules/ssl/settings-page.php',
|
191 |
+
'ITSEC_SSL_Setup' => $baseDir . '/core/modules/ssl/setup.php',
|
192 |
+
'ITSEC_SSL_Validator' => $baseDir . '/core/modules/ssl/validator.php',
|
193 |
+
'ITSEC_Salts_Setup' => $baseDir . '/core/modules/salts/setup.php',
|
194 |
+
'ITSEC_Scheduler' => $baseDir . '/core/lib/class-itsec-scheduler.php',
|
195 |
+
'ITSEC_Scheduler_Cron' => $baseDir . '/core/lib/class-itsec-scheduler-cron.php',
|
196 |
+
'ITSEC_Scheduler_Page_Load' => $baseDir . '/core/lib/class-itsec-scheduler-page-load.php',
|
197 |
+
'ITSEC_Schema' => $baseDir . '/core/lib/schema.php',
|
198 |
+
'ITSEC_Security_Check_Feedback' => $baseDir . '/core/modules/security-check/feedback.php',
|
199 |
+
'ITSEC_Security_Check_Feedback_Renderer' => $baseDir . '/core/modules/security-check/feedback-renderer.php',
|
200 |
+
'ITSEC_Security_Check_Pro' => $baseDir . '/core/modules/security-check-pro/class-itsec-security-check-pro.php',
|
201 |
+
'ITSEC_Security_Check_Pro_Debug' => $baseDir . '/core/modules/security-check-pro/debug.php',
|
202 |
+
'ITSEC_Security_Check_Pro_Privacy' => $baseDir . '/core/modules/security-check-pro/privacy.php',
|
203 |
+
'ITSEC_Security_Check_Pro_Settings' => $baseDir . '/core/modules/security-check-pro/settings.php',
|
204 |
+
'ITSEC_Security_Check_Pro_Settings_Page' => $baseDir . '/core/modules/security-check-pro/settings-page.php',
|
205 |
+
'ITSEC_Security_Check_Pro_Utility' => $baseDir . '/core/modules/security-check-pro/utility.php',
|
206 |
+
'ITSEC_Security_Check_Pro_Validator' => $baseDir . '/core/modules/security-check-pro/validator.php',
|
207 |
+
'ITSEC_Security_Check_Scanner' => $baseDir . '/core/modules/security-check/scanner.php',
|
208 |
+
'ITSEC_Security_Check_Settings_Page' => $baseDir . '/core/modules/security-check/settings-page.php',
|
209 |
+
'ITSEC_Settings' => $baseDir . '/core/lib/settings.php',
|
210 |
+
'ITSEC_Settings_Page_Sidebar_Widget_BackupBuddy_Cross_Promo' => $baseDir . '/core/modules/core/sidebar-widget-backupbuddy-cross-promo.php',
|
211 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Free_Support' => $baseDir . '/core/modules/core/sidebar-widget-support.php',
|
212 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Mail_List_Signup' => $baseDir . '/core/modules/core/sidebar-widget-mail-list-signup.php',
|
213 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan' => $baseDir . '/core/modules/malware/settings-page.php',
|
214 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Pro_Upsell' => $baseDir . '/core/modules/core/sidebar-widget-pro-upsell.php',
|
215 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Sync_Cross_Promo' => $baseDir . '/core/modules/core/sidebar-widget-sync-cross-promo.php',
|
216 |
+
'ITSEC_Static_Map_API' => $baseDir . '/core/lib/static-map-api/interface-itsec-static-map-api.php',
|
217 |
+
'ITSEC_Storage' => $baseDir . '/core/lib/storage.php',
|
218 |
+
'ITSEC_Strong_Passwords' => $baseDir . '/core/modules/strong-passwords/class-itsec-strong-passwords.php',
|
219 |
+
'ITSEC_Strong_Passwords_Settings' => $baseDir . '/core/modules/strong-passwords/settings.php',
|
220 |
+
'ITSEC_Strong_Passwords_Setup' => $baseDir . '/core/modules/strong-passwords/setup.php',
|
221 |
+
'ITSEC_Strong_Passwords_Validator' => $baseDir . '/core/modules/strong-passwords/validator.php',
|
222 |
+
'ITSEC_Sync_Connect' => $baseDir . '/core/modules/sync-connect/class-itsec-sync-connect.php',
|
223 |
+
'ITSEC_Sync_Connect_Interstitial' => $baseDir . '/core/modules/sync-connect/class-itsec-sync-connect-interstitial.php',
|
224 |
+
'ITSEC_System_Tweaks' => $baseDir . '/core/modules/system-tweaks/class-itsec-system-tweaks.php',
|
225 |
+
'ITSEC_System_Tweaks_Config_Generators' => $baseDir . '/core/modules/system-tweaks/config-generators.php',
|
226 |
+
'ITSEC_System_Tweaks_Settings' => $baseDir . '/core/modules/system-tweaks/settings.php',
|
227 |
+
'ITSEC_System_Tweaks_Settings_Page' => $baseDir . '/core/modules/system-tweaks/settings-page.php',
|
228 |
+
'ITSEC_System_Tweaks_Setup' => $baseDir . '/core/modules/system-tweaks/setup.php',
|
229 |
+
'ITSEC_System_Tweaks_Validator' => $baseDir . '/core/modules/system-tweaks/validator.php',
|
230 |
+
'ITSEC_Two_Factor_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
231 |
+
'ITSEC_User_Logging_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
232 |
+
'ITSEC_User_Security_Check_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
233 |
+
'ITSEC_Validator' => $baseDir . '/core/lib/validator.php',
|
234 |
+
'ITSEC_Version_Management_Settings_Page' => $baseDir . '/core/modules/pro/settings-page.php',
|
235 |
+
'ITSEC_WP_List_Table' => $baseDir . '/core/lib/class-itsec-wp-list-table.php',
|
236 |
+
'ITSEC_WordPress_Salts_Settings' => $baseDir . '/core/modules/salts/settings.php',
|
237 |
+
'ITSEC_WordPress_Salts_Settings_Page' => $baseDir . '/core/modules/salts/settings-page.php',
|
238 |
+
'ITSEC_WordPress_Salts_Utilities' => $baseDir . '/core/modules/salts/utilities.php',
|
239 |
+
'ITSEC_WordPress_Salts_Validator' => $baseDir . '/core/modules/salts/validator.php',
|
240 |
+
'ITSEC_WordPress_Tweaks' => $baseDir . '/core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php',
|
241 |
+
'ITSEC_WordPress_Tweaks_Config_Generators' => $baseDir . '/core/modules/wordpress-tweaks/config-generators.php',
|
242 |
+
'ITSEC_WordPress_Tweaks_Settings_Page' => $baseDir . '/core/modules/wordpress-tweaks/settings-page.php',
|
243 |
+
'ITSEC_WordPress_Tweaks_Setup' => $baseDir . '/core/modules/wordpress-tweaks/setup.php',
|
244 |
+
'ITSEC_WordPress_Tweaks_Validator' => $baseDir . '/core/modules/wordpress-tweaks/validator.php',
|
245 |
+
'ITSEC_Wordpress_Tweaks_Settings' => $baseDir . '/core/modules/wordpress-tweaks/settings.php',
|
246 |
+
'Ithemes_Sync_Verb_ITSEC_Do_Security_Check' => $baseDir . '/core/modules/security-check/sync-verbs/itsec-do-security-check.php',
|
247 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Away_Mode' => $baseDir . '/core/modules/away-mode/sync-verbs/itsec-get-away-mode.php',
|
248 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log' => $baseDir . '/core/modules/malware/sync-verbs/itsec-get-malware-scan-log.php',
|
249 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Security_Check_Feedback_Response' => $baseDir . '/core/modules/security-check/sync-verbs/itsec-get-security-check-feedback-response.php',
|
250 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Security_Check_Modules' => $baseDir . '/core/modules/security-check/sync-verbs/itsec-get-security-check-modules.php',
|
251 |
+
'Ithemes_Sync_Verb_ITSEC_Latest_File_Scan' => $baseDir . '/core/modules/file-change/sync-verbs/itsec-latest-file-scan.php',
|
252 |
+
'Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan' => $baseDir . '/core/modules/malware/sync-verbs/itsec-do-malware-scan.php',
|
253 |
+
'Ithemes_Sync_Verb_ITSEC_Override_Away_Mode' => $baseDir . '/core/modules/away-mode/sync-verbs/itsec-override-away-mode.php',
|
254 |
+
'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php',
|
255 |
+
'Pimple\\Exception\\ExpectedInvokableException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
256 |
+
'Pimple\\Exception\\FrozenServiceException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
257 |
+
'Pimple\\Exception\\InvalidServiceIdentifierException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php',
|
258 |
+
'Pimple\\Exception\\UnknownIdentifierException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php',
|
259 |
+
'Pimple\\Psr11\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Psr11/Container.php',
|
260 |
+
'Pimple\\Psr11\\ServiceLocator' => $vendorDir . '/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php',
|
261 |
+
'Pimple\\ServiceIterator' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceIterator.php',
|
262 |
+
'Pimple\\ServiceProviderInterface' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php',
|
263 |
+
'Pimple\\Tests\\Fixtures\\Invokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php',
|
264 |
+
'Pimple\\Tests\\Fixtures\\NonInvokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php',
|
265 |
+
'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php',
|
266 |
+
'Pimple\\Tests\\Fixtures\\Service' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php',
|
267 |
+
'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php',
|
268 |
+
'Pimple\\Tests\\PimpleTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php',
|
269 |
+
'Pimple\\Tests\\Psr11\\ContainerTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php',
|
270 |
+
'Pimple\\Tests\\Psr11\\ServiceLocatorTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php',
|
271 |
+
'Pimple\\Tests\\ServiceIteratorTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php',
|
272 |
+
'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
|
273 |
+
'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
|
274 |
+
'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
|
275 |
+
'Wikimedia\\Composer\\Logger' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Logger.php',
|
276 |
+
'Wikimedia\\Composer\\MergePlugin' => $vendorDir . '/wikimedia/composer-merge-plugin/src/MergePlugin.php',
|
277 |
+
'Wikimedia\\Composer\\Merge\\ExtraPackage' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Merge/ExtraPackage.php',
|
278 |
+
'Wikimedia\\Composer\\Merge\\MissingFileException' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Merge/MissingFileException.php',
|
279 |
+
'Wikimedia\\Composer\\Merge\\NestedArray' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Merge/NestedArray.php',
|
280 |
+
'Wikimedia\\Composer\\Merge\\PluginState' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Merge/PluginState.php',
|
281 |
+
'Wikimedia\\Composer\\Merge\\StabilityFlags' => $vendorDir . '/wikimedia/composer-merge-plugin/src/Merge/StabilityFlags.php',
|
282 |
+
'iThemesSecurity\\Contracts\\Runnable' => $baseDir . '/core/Contracts/Runnable.php',
|
283 |
+
'iThemesSecurity\\Exception\\Exception' => $baseDir . '/core/Exception/Exception.php',
|
284 |
+
'iThemesSecurity\\Exception\\Invalid_Argument_Exception' => $baseDir . '/core/Exception/Invalid_Argument_Exception.php',
|
285 |
+
'iThemesSecurity\\Exception\\Unsatisfied_Module_Dependencies_Exception' => $baseDir . '/core/Exception/Unsatisfied_Module_Dependencies_Exception.php',
|
286 |
+
'iThemesSecurity\\Exception\\WP_Error' => $baseDir . '/core/Exception/WP_Error.php',
|
287 |
+
'iThemesSecurity\\Lib\\Lockout\\Context' => $baseDir . '/core/lib/lockout/abstract-context.php',
|
288 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Context' => $baseDir . '/core/lib/lockout/execute-lock/abstract-context.php',
|
289 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Host_Context' => $baseDir . '/core/lib/lockout/execute-lock/class-host-context.php',
|
290 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Configurable' => $baseDir . '/core/lib/lockout/execute-lock/source/class-configurable.php',
|
291 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Lockout_Module' => $baseDir . '/core/lib/lockout/execute-lock/source/class-lockout-module.php',
|
292 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Source' => $baseDir . '/core/lib/lockout/execute-lock/source/interface-source.php',
|
293 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\User_Context' => $baseDir . '/core/lib/lockout/execute-lock/class-user-context.php',
|
294 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Username_Context' => $baseDir . '/core/lib/lockout/execute-lock/class-username-context.php',
|
295 |
+
'iThemesSecurity\\Lib\\Lockout\\Host_Context' => $baseDir . '/core/lib/lockout/class-host-context.php',
|
296 |
+
'iThemesSecurity\\Lib\\Lockout\\Lockout' => $baseDir . '/core/lib/lockout/class-lockout.php',
|
297 |
+
'iThemesSecurity\\Lib\\Lockout\\User_Context' => $baseDir . '/core/lib/lockout/class-user-context.php',
|
298 |
+
'iThemesSecurity\\Lib\\Lockout\\Username_Context' => $baseDir . '/core/lib/lockout/class-username-context.php',
|
299 |
+
'iThemesSecurity\\User_Groups\\All_Users' => $baseDir . '/core/modules/user-groups/All_Users.php',
|
300 |
+
'iThemesSecurity\\User_Groups\\Default_Matcher' => $baseDir . '/core/modules/user-groups/Match/Default_Matcher.php',
|
301 |
+
'iThemesSecurity\\User_Groups\\Everybody_Else' => $baseDir . '/core/modules/user-groups/Everybody_Else.php',
|
302 |
+
'iThemesSecurity\\User_Groups\\Match_Target' => $baseDir . '/core/modules/user-groups/Match/Match_Target.php',
|
303 |
+
'iThemesSecurity\\User_Groups\\Matchable' => $baseDir . '/core/modules/user-groups/Matchable.php',
|
304 |
+
'iThemesSecurity\\User_Groups\\Matchable_Not_Found' => $baseDir . '/core/modules/user-groups/Match/Matchable_Not_Found.php',
|
305 |
+
'iThemesSecurity\\User_Groups\\Matchables_Source' => $baseDir . '/core/modules/user-groups/Matchables_Source.php',
|
306 |
+
'iThemesSecurity\\User_Groups\\Matcher' => $baseDir . '/core/modules/user-groups/Match/Matcher.php',
|
307 |
+
'iThemesSecurity\\User_Groups\\Module\\Module' => $baseDir . '/core/modules/user-groups/Module/Module.php',
|
308 |
+
'iThemesSecurity\\User_Groups\\Module\\Settings' => $baseDir . '/core/modules/user-groups/Module/Settings.php',
|
309 |
+
'iThemesSecurity\\User_Groups\\Module\\Validator' => $baseDir . '/core/modules/user-groups/Module/Validator.php',
|
310 |
+
'iThemesSecurity\\User_Groups\\REST\\Matchables' => $baseDir . '/core/modules/user-groups/REST/Matchables.php',
|
311 |
+
'iThemesSecurity\\User_Groups\\REST\\REST' => $baseDir . '/core/modules/user-groups/REST/REST.php',
|
312 |
+
'iThemesSecurity\\User_Groups\\REST\\Settings' => $baseDir . '/core/modules/user-groups/REST/Settings.php',
|
313 |
+
'iThemesSecurity\\User_Groups\\REST\\User_Groups' => $baseDir . '/core/modules/user-groups/REST/User_Groups.php',
|
314 |
+
'iThemesSecurity\\User_Groups\\Repository\\DB_Repository' => $baseDir . '/core/modules/user-groups/Repository/DB_Repository.php',
|
315 |
+
'iThemesSecurity\\User_Groups\\Repository\\Decorator' => $baseDir . '/core/modules/user-groups/Repository/Decorator.php',
|
316 |
+
'iThemesSecurity\\User_Groups\\Repository\\Eager_Loading_Decorator' => $baseDir . '/core/modules/user-groups/Repository/Eager_Loading_Decorator.php',
|
317 |
+
'iThemesSecurity\\User_Groups\\Repository\\In_Memory_Repository' => $baseDir . '/core/modules/user-groups/Repository/In_Memory_Repository.php',
|
318 |
+
'iThemesSecurity\\User_Groups\\Repository\\Object_Caching_Decorator' => $baseDir . '/core/modules/user-groups/Repository/Object_Caching_Decorator.php',
|
319 |
+
'iThemesSecurity\\User_Groups\\Repository\\Repository' => $baseDir . '/core/modules/user-groups/Repository/Repository.php',
|
320 |
+
'iThemesSecurity\\User_Groups\\Repository\\User_Group_Not_Found' => $baseDir . '/core/modules/user-groups/Repository/User_Group_Not_Found.php',
|
321 |
+
'iThemesSecurity\\User_Groups\\Settings_Page' => $baseDir . '/core/modules/user-groups/settings-page.php',
|
322 |
+
'iThemesSecurity\\User_Groups\\Settings_Proxy' => $baseDir . '/core/modules/user-groups/Settings/Settings_Proxy.php',
|
323 |
+
'iThemesSecurity\\User_Groups\\Settings_Registration' => $baseDir . '/core/modules/user-groups/Settings/Settings_Registration.php',
|
324 |
+
'iThemesSecurity\\User_Groups\\Settings_Registry' => $baseDir . '/core/modules/user-groups/Settings/Settings_Registry.php',
|
325 |
+
'iThemesSecurity\\User_Groups\\Upgrader' => $baseDir . '/core/modules/user-groups/Upgrader.php',
|
326 |
+
'iThemesSecurity\\User_Groups\\User_Group' => $baseDir . '/core/modules/user-groups/User_Group.php',
|
327 |
+
);
|
vendor-prod/composer/autoload_namespaces.php
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_namespaces.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
|
10 |
+
);
|
vendor-prod/composer/autoload_psr4.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_psr4.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'Wikimedia\\Composer\\' => array($vendorDir . '/wikimedia/composer-merge-plugin/src'),
|
10 |
+
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
11 |
+
);
|
vendor-prod/composer/autoload_real.php
ADDED
@@ -0,0 +1,52 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_real.php @generated by Composer
|
4 |
+
|
5 |
+
class ComposerAutoloaderInit35a2bd4feb347da0d3ea2d8ef023082f
|
6 |
+
{
|
7 |
+
private static $loader;
|
8 |
+
|
9 |
+
public static function loadClassLoader($class)
|
10 |
+
{
|
11 |
+
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
+
require __DIR__ . '/ClassLoader.php';
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
public static function getLoader()
|
17 |
+
{
|
18 |
+
if (null !== self::$loader) {
|
19 |
+
return self::$loader;
|
20 |
+
}
|
21 |
+
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit35a2bd4feb347da0d3ea2d8ef023082f', 'loadClassLoader'), true, true);
|
23 |
+
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit35a2bd4feb347da0d3ea2d8ef023082f', 'loadClassLoader'));
|
25 |
+
|
26 |
+
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
+
if ($useStaticLoader) {
|
28 |
+
require_once __DIR__ . '/autoload_static.php';
|
29 |
+
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f::getInitializer($loader));
|
31 |
+
} else {
|
32 |
+
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
+
foreach ($map as $namespace => $path) {
|
34 |
+
$loader->set($namespace, $path);
|
35 |
+
}
|
36 |
+
|
37 |
+
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
+
foreach ($map as $namespace => $path) {
|
39 |
+
$loader->setPsr4($namespace, $path);
|
40 |
+
}
|
41 |
+
|
42 |
+
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
+
if ($classMap) {
|
44 |
+
$loader->addClassMap($classMap);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
$loader->register(true);
|
49 |
+
|
50 |
+
return $loader;
|
51 |
+
}
|
52 |
+
}
|
vendor-prod/composer/autoload_static.php
ADDED
@@ -0,0 +1,372 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_static.php @generated by Composer
|
4 |
+
|
5 |
+
namespace Composer\Autoload;
|
6 |
+
|
7 |
+
class ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f
|
8 |
+
{
|
9 |
+
public static $prefixLengthsPsr4 = array (
|
10 |
+
'W' =>
|
11 |
+
array (
|
12 |
+
'Wikimedia\\Composer\\' => 19,
|
13 |
+
),
|
14 |
+
'P' =>
|
15 |
+
array (
|
16 |
+
'Psr\\Container\\' => 14,
|
17 |
+
),
|
18 |
+
);
|
19 |
+
|
20 |
+
public static $prefixDirsPsr4 = array (
|
21 |
+
'Wikimedia\\Composer\\' =>
|
22 |
+
array (
|
23 |
+
0 => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src',
|
24 |
+
),
|
25 |
+
'Psr\\Container\\' =>
|
26 |
+
array (
|
27 |
+
0 => __DIR__ . '/..' . '/psr/container/src',
|
28 |
+
),
|
29 |
+
);
|
30 |
+
|
31 |
+
public static $prefixesPsr0 = array (
|
32 |
+
'P' =>
|
33 |
+
array (
|
34 |
+
'Pimple' =>
|
35 |
+
array (
|
36 |
+
0 => __DIR__ . '/..' . '/pimple/pimple/src',
|
37 |
+
),
|
38 |
+
),
|
39 |
+
);
|
40 |
+
|
41 |
+
public static $classMap = array (
|
42 |
+
'ITSEC_404_Detection_Settings_Page' => __DIR__ . '/../..' . '/core/modules/404-detection/settings-page.php',
|
43 |
+
'ITSEC_Admin_Notice' => __DIR__ . '/../..' . '/core/lib/admin-notices/interface-itsec-admin-notice.php',
|
44 |
+
'ITSEC_Admin_Notice_Action' => __DIR__ . '/../..' . '/core/lib/admin-notices/actions/interface-itsec-admin-notice-action.php',
|
45 |
+
'ITSEC_Admin_Notice_Action_Callback' => __DIR__ . '/../..' . '/core/lib/admin-notices/actions/class-itsec-admin-notice-action-callback.php',
|
46 |
+
'ITSEC_Admin_Notice_Action_Link' => __DIR__ . '/../..' . '/core/lib/admin-notices/actions/class-itsec-admin-notice-action-link.php',
|
47 |
+
'ITSEC_Admin_Notice_Callback' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-callback.php',
|
48 |
+
'ITSEC_Admin_Notice_Context' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-context.php',
|
49 |
+
'ITSEC_Admin_Notice_Globally_Dismissible' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-globally-dismissible.php',
|
50 |
+
'ITSEC_Admin_Notice_Highlighted_Log' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-highlighted-log.php',
|
51 |
+
'ITSEC_Admin_Notice_Managers_Only' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-managers-only.php',
|
52 |
+
'ITSEC_Admin_Notice_Network_Brute_Force_Promo' => __DIR__ . '/../..' . '/core/modules/global/notices.php',
|
53 |
+
'ITSEC_Admin_Notice_New_Feature_Core' => __DIR__ . '/../..' . '/core/modules/core/notices.php',
|
54 |
+
'ITSEC_Admin_Notice_Remind_Me' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-remind-me.php',
|
55 |
+
'ITSEC_Admin_Notice_Screen_Blacklist' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-screen-blacklist.php',
|
56 |
+
'ITSEC_Admin_Notice_Static' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-static.php',
|
57 |
+
'ITSEC_Admin_Notice_User_Dismissible' => __DIR__ . '/../..' . '/core/lib/admin-notices/class-itsec-admin-notice-user-dismissible.php',
|
58 |
+
'ITSEC_Admin_Notices' => __DIR__ . '/../..' . '/core/modules/core/class-itsec-admin-notices.php',
|
59 |
+
'ITSEC_Admin_User_Settings' => __DIR__ . '/../..' . '/core/modules/admin-user/settings.php',
|
60 |
+
'ITSEC_Admin_User_Settings_Page' => __DIR__ . '/../..' . '/core/modules/admin-user/settings-page.php',
|
61 |
+
'ITSEC_Admin_User_Validator' => __DIR__ . '/../..' . '/core/modules/admin-user/validator.php',
|
62 |
+
'ITSEC_Away_Mode' => __DIR__ . '/../..' . '/core/modules/away-mode/class-itsec-away-mode.php',
|
63 |
+
'ITSEC_Away_Mode_Logs' => __DIR__ . '/../..' . '/core/modules/away-mode/logs.php',
|
64 |
+
'ITSEC_Away_Mode_Settings' => __DIR__ . '/../..' . '/core/modules/away-mode/settings.php',
|
65 |
+
'ITSEC_Away_Mode_Settings_Page' => __DIR__ . '/../..' . '/core/modules/away-mode/settings-page.php',
|
66 |
+
'ITSEC_Away_Mode_Setup' => __DIR__ . '/../..' . '/core/modules/away-mode/setup.php',
|
67 |
+
'ITSEC_Away_Mode_Utilities' => __DIR__ . '/../..' . '/core/modules/away-mode/utilities.php',
|
68 |
+
'ITSEC_Away_Mode_Validator' => __DIR__ . '/../..' . '/core/modules/away-mode/validator.php',
|
69 |
+
'ITSEC_Backup' => __DIR__ . '/../..' . '/core/modules/backup/class-itsec-backup.php',
|
70 |
+
'ITSEC_Backup_Logs' => __DIR__ . '/../..' . '/core/modules/backup/logs.php',
|
71 |
+
'ITSEC_Backup_Privacy' => __DIR__ . '/../..' . '/core/modules/backup/privacy.php',
|
72 |
+
'ITSEC_Backup_Settings' => __DIR__ . '/../..' . '/core/modules/backup/settings.php',
|
73 |
+
'ITSEC_Backup_Settings_Page' => __DIR__ . '/../..' . '/core/modules/backup/settings-page.php',
|
74 |
+
'ITSEC_Backup_Setup' => __DIR__ . '/../..' . '/core/modules/backup/setup.php',
|
75 |
+
'ITSEC_Backup_Validator' => __DIR__ . '/../..' . '/core/modules/backup/validator.php',
|
76 |
+
'ITSEC_Ban_Users' => __DIR__ . '/../..' . '/core/modules/ban-users/class-itsec-ban-users.php',
|
77 |
+
'ITSEC_Ban_Users_Config_Generators' => __DIR__ . '/../..' . '/core/modules/ban-users/config-generators.php',
|
78 |
+
'ITSEC_Ban_Users_Settings' => __DIR__ . '/../..' . '/core/modules/ban-users/settings.php',
|
79 |
+
'ITSEC_Ban_Users_Settings_Page' => __DIR__ . '/../..' . '/core/modules/ban-users/settings-page.php',
|
80 |
+
'ITSEC_Ban_Users_Setup' => __DIR__ . '/../..' . '/core/modules/ban-users/setup.php',
|
81 |
+
'ITSEC_Ban_Users_Validator' => __DIR__ . '/../..' . '/core/modules/ban-users/validator.php',
|
82 |
+
'ITSEC_Brute_Force' => __DIR__ . '/../..' . '/core/modules/brute-force/class-itsec-brute-force.php',
|
83 |
+
'ITSEC_Brute_Force_Logs' => __DIR__ . '/../..' . '/core/modules/brute-force/logs.php',
|
84 |
+
'ITSEC_Brute_Force_Settings' => __DIR__ . '/../..' . '/core/modules/brute-force/settings.php',
|
85 |
+
'ITSEC_Brute_Force_Settings_Page' => __DIR__ . '/../..' . '/core/modules/brute-force/settings-page.php',
|
86 |
+
'ITSEC_Brute_Force_Setup' => __DIR__ . '/../..' . '/core/modules/brute-force/setup.php',
|
87 |
+
'ITSEC_Brute_Force_Validator' => __DIR__ . '/../..' . '/core/modules/brute-force/validator.php',
|
88 |
+
'ITSEC_Content_Directory_Settings_Page' => __DIR__ . '/../..' . '/core/modules/content-directory/settings-page.php',
|
89 |
+
'ITSEC_Content_Directory_Utility' => __DIR__ . '/../..' . '/core/modules/content-directory/utility.php',
|
90 |
+
'ITSEC_Core_Active' => __DIR__ . '/../..' . '/core/modules/core/class-itsec-core-active.php',
|
91 |
+
'ITSEC_Core_Admin' => __DIR__ . '/../..' . '/core/modules/core/class-itsec-core-admin.php',
|
92 |
+
'ITSEC_Core_Server_Config_Rules_Settings_Page' => __DIR__ . '/../..' . '/core/modules/file-writing/settings-page.php',
|
93 |
+
'ITSEC_Core_WPConfig_File_Settings_Page' => __DIR__ . '/../..' . '/core/modules/file-writing/settings-page.php',
|
94 |
+
'ITSEC_Database_Prefix_Settings_Page' => __DIR__ . '/../..' . '/core/modules/database-prefix/settings-page.php',
|
95 |
+
'ITSEC_Database_Prefix_Utility' => __DIR__ . '/../..' . '/core/modules/database-prefix/utility.php',
|
96 |
+
'ITSEC_Debug' => __DIR__ . '/../..' . '/core/lib/debug.php',
|
97 |
+
'ITSEC_Email_Confirmation' => __DIR__ . '/../..' . '/core/modules/email-confirmation/class-itsec-email-confirmation.php',
|
98 |
+
'ITSEC_Feature_Flags_Settings_Page' => __DIR__ . '/../..' . '/core/modules/feature-flags/settings-page.php',
|
99 |
+
'ITSEC_File_Change' => __DIR__ . '/../..' . '/core/modules/file-change/class-itsec-file-change.php',
|
100 |
+
'ITSEC_File_Change_Admin' => __DIR__ . '/../..' . '/core/modules/file-change/admin.php',
|
101 |
+
'ITSEC_File_Change_Chunk_Scanner' => __DIR__ . '/../..' . '/core/modules/file-change/lib/chunk-scanner.php',
|
102 |
+
'ITSEC_File_Change_Hash_Comparator' => __DIR__ . '/../..' . '/core/modules/file-change/lib/hash-comparator.php',
|
103 |
+
'ITSEC_File_Change_Hash_Comparator_Chain' => __DIR__ . '/../..' . '/core/modules/file-change/lib/hash-comparator-chain.php',
|
104 |
+
'ITSEC_File_Change_Hash_Comparator_Loadable' => __DIR__ . '/../..' . '/core/modules/file-change/lib/hash-comparator-loadable.php',
|
105 |
+
'ITSEC_File_Change_Hash_Comparator_Managed_Files' => __DIR__ . '/../..' . '/core/modules/file-change/lib/hash-comparator-managed-files.php',
|
106 |
+
'ITSEC_File_Change_Hash_Loading_Failed_Exception' => __DIR__ . '/../..' . '/core/modules/file-change/lib/hash-loading-failed-exception.php',
|
107 |
+
'ITSEC_File_Change_Logs' => __DIR__ . '/../..' . '/core/modules/file-change/logs.php',
|
108 |
+
'ITSEC_File_Change_Package' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package.php',
|
109 |
+
'ITSEC_File_Change_Package_Core' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-core.php',
|
110 |
+
'ITSEC_File_Change_Package_Factory' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-factory.php',
|
111 |
+
'ITSEC_File_Change_Package_Plugin' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-plugin.php',
|
112 |
+
'ITSEC_File_Change_Package_System' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-system.php',
|
113 |
+
'ITSEC_File_Change_Package_Theme' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-theme.php',
|
114 |
+
'ITSEC_File_Change_Package_Unknown' => __DIR__ . '/../..' . '/core/modules/file-change/lib/package-unknown.php',
|
115 |
+
'ITSEC_File_Change_Scanner' => __DIR__ . '/../..' . '/core/modules/file-change/scanner.php',
|
116 |
+
'ITSEC_File_Change_Settings' => __DIR__ . '/../..' . '/core/modules/file-change/settings.php',
|
117 |
+
'ITSEC_File_Change_Settings_Page' => __DIR__ . '/../..' . '/core/modules/file-change/settings-page.php',
|
118 |
+
'ITSEC_File_Change_Setup' => __DIR__ . '/../..' . '/core/modules/file-change/setup.php',
|
119 |
+
'ITSEC_File_Change_Validator' => __DIR__ . '/../..' . '/core/modules/file-change/validator.php',
|
120 |
+
'ITSEC_File_Permissions_Settings_Page' => __DIR__ . '/../..' . '/core/modules/file-permissions/settings-page.php',
|
121 |
+
'ITSEC_Fingerprint' => __DIR__ . '/../..' . '/core/lib/fingerprinting/class-itsec-fingerprint.php',
|
122 |
+
'ITSEC_Fingerprint_Comparison' => __DIR__ . '/../..' . '/core/lib/fingerprinting/class-itsec-fingerprint-comparison.php',
|
123 |
+
'ITSEC_Fingerprint_Source' => __DIR__ . '/../..' . '/core/lib/fingerprinting/interface-itsec-fingerprint-source.php',
|
124 |
+
'ITSEC_Fingerprint_Value' => __DIR__ . '/../..' . '/core/lib/fingerprinting/class-itsec-fingerprint-value.php',
|
125 |
+
'ITSEC_Form' => __DIR__ . '/../..' . '/core/lib/form.php',
|
126 |
+
'ITSEC_Four_Oh_Four' => __DIR__ . '/../..' . '/core/modules/404-detection/class-itsec-four-oh-four.php',
|
127 |
+
'ITSEC_Four_Oh_Four_Logs' => __DIR__ . '/../..' . '/core/modules/404-detection/logs.php',
|
128 |
+
'ITSEC_Four_Oh_Four_Settings' => __DIR__ . '/../..' . '/core/modules/404-detection/settings.php',
|
129 |
+
'ITSEC_Four_Oh_Four_Setup' => __DIR__ . '/../..' . '/core/modules/404-detection/setup.php',
|
130 |
+
'ITSEC_Four_Oh_Four_Validator' => __DIR__ . '/../..' . '/core/modules/404-detection/validator.php',
|
131 |
+
'ITSEC_Geolocator' => __DIR__ . '/../..' . '/core/lib/geolocation/interface-itsec-geolocator.php',
|
132 |
+
'ITSEC_Geolocator_Chain' => __DIR__ . '/../..' . '/core/lib/geolocation/class-itsec-geolocator-chain.php',
|
133 |
+
'ITSEC_Geolocator_Page_Cache' => __DIR__ . '/../..' . '/core/lib/geolocation/class-itsec-geolocator-page-cache.php',
|
134 |
+
'ITSEC_Global_Logs' => __DIR__ . '/../..' . '/core/modules/global/logs.php',
|
135 |
+
'ITSEC_Global_Privacy' => __DIR__ . '/../..' . '/core/modules/global/privacy.php',
|
136 |
+
'ITSEC_Global_Settings_New' => __DIR__ . '/../..' . '/core/modules/global/settings.php',
|
137 |
+
'ITSEC_Global_Settings_Page' => __DIR__ . '/../..' . '/core/modules/global/settings-page.php',
|
138 |
+
'ITSEC_Global_Setup' => __DIR__ . '/../..' . '/core/modules/global/setup.php',
|
139 |
+
'ITSEC_Global_Validator' => __DIR__ . '/../..' . '/core/modules/global/validator.php',
|
140 |
+
'ITSEC_Hide_Backend' => __DIR__ . '/../..' . '/core/modules/hide-backend/class-itsec-hide-backend.php',
|
141 |
+
'ITSEC_Hide_Backend_Privacy' => __DIR__ . '/../..' . '/core/modules/hide-backend/privacy.php',
|
142 |
+
'ITSEC_Hide_Backend_Settings' => __DIR__ . '/../..' . '/core/modules/hide-backend/settings.php',
|
143 |
+
'ITSEC_Hide_Backend_Settings_Page' => __DIR__ . '/../..' . '/core/modules/hide-backend/settings-page.php',
|
144 |
+
'ITSEC_Hide_Backend_Setup' => __DIR__ . '/../..' . '/core/modules/hide-backend/setup.php',
|
145 |
+
'ITSEC_Hide_Backend_Validator' => __DIR__ . '/../..' . '/core/modules/hide-backend/validator.php',
|
146 |
+
'ITSEC_IPCheck' => __DIR__ . '/../..' . '/core/modules/ipcheck/class-itsec-ipcheck.php',
|
147 |
+
'ITSEC_IPCheck_Logs' => __DIR__ . '/../..' . '/core/modules/ipcheck/logs.php',
|
148 |
+
'ITSEC_IPCheck_Setup' => __DIR__ . '/../..' . '/core/modules/ipcheck/setup.php',
|
149 |
+
'ITSEC_IP_Detector' => __DIR__ . '/../..' . '/core/lib/class-itsec-ip-detector.php',
|
150 |
+
'ITSEC_Import_Export_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
151 |
+
'ITSEC_Ithemes_Sync_Upgrader_Skin' => __DIR__ . '/../..' . '/core/modules/sync-connect/includes/upgrader-skin.php',
|
152 |
+
'ITSEC_Job' => __DIR__ . '/../..' . '/core/lib/class-itsec-job.php',
|
153 |
+
'ITSEC_Lib_Admin_Notices' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-admin-notices.php',
|
154 |
+
'ITSEC_Lib_Browser' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-browser.php',
|
155 |
+
'ITSEC_Lib_Canonical_Roles' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-canonical-roles.php',
|
156 |
+
'ITSEC_Lib_Config_File' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-config-file.php',
|
157 |
+
'ITSEC_Lib_Directory' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-directory.php',
|
158 |
+
'ITSEC_Lib_Distributed_Storage' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-distributed-storage.php',
|
159 |
+
'ITSEC_Lib_Distributed_Storage_Cursor' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-distributed-storage.php',
|
160 |
+
'ITSEC_Lib_Email_Confirmation' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-email-confirmation.php',
|
161 |
+
'ITSEC_Lib_Feature_Flags' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-feature-flags.php',
|
162 |
+
'ITSEC_Lib_File' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-file.php',
|
163 |
+
'ITSEC_Lib_Fingerprinting' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-fingerprinting.php',
|
164 |
+
'ITSEC_Lib_Geolocation' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-geolocation.php',
|
165 |
+
'ITSEC_Lib_Highlighted_Logs' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-highlighted-logs.php',
|
166 |
+
'ITSEC_Lib_IP_Detector' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-ip-detector.php',
|
167 |
+
'ITSEC_Lib_IP_Tools' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-ip-tools.php',
|
168 |
+
'ITSEC_Lib_Login' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-login.php',
|
169 |
+
'ITSEC_Lib_Login_Interstitial' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-login-interstitial.php',
|
170 |
+
'ITSEC_Lib_Opaque_Tokens' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-opaque-tokens.php',
|
171 |
+
'ITSEC_Lib_Password_Requirements' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-password-requirements.php',
|
172 |
+
'ITSEC_Lib_REST' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-rest.php',
|
173 |
+
'ITSEC_Lib_Remote_Messages' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-remote-messages.php',
|
174 |
+
'ITSEC_Lib_Static_Map_API' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-static-map-api.php',
|
175 |
+
'ITSEC_Lib_User_Activity' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-user-activity.php',
|
176 |
+
'ITSEC_Lib_Utility' => __DIR__ . '/../..' . '/core/lib/class-itsec-lib-utility.php',
|
177 |
+
'ITSEC_Log' => __DIR__ . '/../..' . '/core/lib/log.php',
|
178 |
+
'ITSEC_Log_Util' => __DIR__ . '/../..' . '/core/lib/log-util.php',
|
179 |
+
'ITSEC_Login_Interstitial' => __DIR__ . '/../..' . '/core/lib/login-interstitial/abstract-itsec-login-interstitial.php',
|
180 |
+
'ITSEC_Login_Interstitial_Config_Driven' => __DIR__ . '/../..' . '/core/lib/login-interstitial/class-itsec-login-interstitial-config-driven.php',
|
181 |
+
'ITSEC_Login_Interstitial_Session' => __DIR__ . '/../..' . '/core/lib/login-interstitial/class-itsec-login-interstitial-session.php',
|
182 |
+
'ITSEC_Magic_Links_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
183 |
+
'ITSEC_Mail' => __DIR__ . '/../..' . '/core/lib/class-itsec-mail.php',
|
184 |
+
'ITSEC_Malware' => __DIR__ . '/../..' . '/core/modules/malware/class-itsec-malware.php',
|
185 |
+
'ITSEC_Malware_Logs' => __DIR__ . '/../..' . '/core/modules/malware/logs.php',
|
186 |
+
'ITSEC_Malware_Privacy' => __DIR__ . '/../..' . '/core/modules/malware/privacy.php',
|
187 |
+
'ITSEC_Malware_Scan_Results_Template' => __DIR__ . '/../..' . '/core/modules/malware/class-itsec-malware-scan-results-template.php',
|
188 |
+
'ITSEC_Malware_Scanner' => __DIR__ . '/../..' . '/core/modules/malware/class-itsec-malware-scanner.php',
|
189 |
+
'ITSEC_Malware_Scheduling_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
190 |
+
'ITSEC_Malware_Setup' => __DIR__ . '/../..' . '/core/modules/malware/setup.php',
|
191 |
+
'ITSEC_Multisite_Tweaks' => __DIR__ . '/../..' . '/core/modules/multisite-tweaks/class-itsec-multisite-tweaks.php',
|
192 |
+
'ITSEC_Multisite_Tweaks_Settings' => __DIR__ . '/../..' . '/core/modules/multisite-tweaks/settings.php',
|
193 |
+
'ITSEC_Multisite_Tweaks_Settings_Page' => __DIR__ . '/../..' . '/core/modules/multisite-tweaks/settings-page.php',
|
194 |
+
'ITSEC_Multisite_Tweaks_Setup' => __DIR__ . '/../..' . '/core/modules/multisite-tweaks/setup.php',
|
195 |
+
'ITSEC_Multisite_Tweaks_Validator' => __DIR__ . '/../..' . '/core/modules/multisite-tweaks/validator.php',
|
196 |
+
'ITSEC_Mutex' => __DIR__ . '/../..' . '/core/lib/class-itsec-mutex.php',
|
197 |
+
'ITSEC_Network_Brute_Force_Settings' => __DIR__ . '/../..' . '/core/modules/ipcheck/settings.php',
|
198 |
+
'ITSEC_Network_Brute_Force_Settings_Page' => __DIR__ . '/../..' . '/core/modules/ipcheck/settings-page.php',
|
199 |
+
'ITSEC_Network_Brute_Force_Utilities' => __DIR__ . '/../..' . '/core/modules/ipcheck/utilities.php',
|
200 |
+
'ITSEC_Network_Brute_Force_Validator' => __DIR__ . '/../..' . '/core/modules/ipcheck/validator.php',
|
201 |
+
'ITSEC_Network_Bruteforce_Privacy' => __DIR__ . '/../..' . '/core/modules/ipcheck/privacy.php',
|
202 |
+
'ITSEC_Notification_Center' => __DIR__ . '/../..' . '/core/modules/notification-center/class-notification-center.php',
|
203 |
+
'ITSEC_Notification_Center_Debug' => __DIR__ . '/../..' . '/core/modules/notification-center/debug.php',
|
204 |
+
'ITSEC_Notification_Center_Logs' => __DIR__ . '/../..' . '/core/modules/notification-center/logs.php',
|
205 |
+
'ITSEC_Notification_Center_Settings' => __DIR__ . '/../..' . '/core/modules/notification-center/settings.php',
|
206 |
+
'ITSEC_Notification_Center_Settings_Page' => __DIR__ . '/../..' . '/core/modules/notification-center/settings-page.php',
|
207 |
+
'ITSEC_Notification_Center_Setup' => __DIR__ . '/../..' . '/core/modules/notification-center/setup.php',
|
208 |
+
'ITSEC_Notification_Center_Validator' => __DIR__ . '/../..' . '/core/modules/notification-center/validator.php',
|
209 |
+
'ITSEC_Password_Requirements' => __DIR__ . '/../..' . '/core/modules/password-requirements/class-itsec-password-requirements.php',
|
210 |
+
'ITSEC_Password_Requirements_Settings' => __DIR__ . '/../..' . '/core/modules/password-requirements/settings.php',
|
211 |
+
'ITSEC_Password_Requirements_Settings_Page' => __DIR__ . '/../..' . '/core/modules/password-requirements/settings-page.php',
|
212 |
+
'ITSEC_Password_Requirements_Validator' => __DIR__ . '/../..' . '/core/modules/password-requirements/validator.php',
|
213 |
+
'ITSEC_Passwordless_Login_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
214 |
+
'ITSEC_Privacy' => __DIR__ . '/../..' . '/core/modules/privacy/class-itsec-privacy.php',
|
215 |
+
'ITSEC_Privacy_Util' => __DIR__ . '/../..' . '/core/modules/privacy/util.php',
|
216 |
+
'ITSEC_Privilege_Escalation_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
217 |
+
'ITSEC_Pro_Setup' => __DIR__ . '/../..' . '/core/modules/pro/setup.php',
|
218 |
+
'ITSEC_REST_Core_Admin_Notices_Controller' => __DIR__ . '/../..' . '/core/modules/core/class-rest-core-admin-notices-controller.php',
|
219 |
+
'ITSEC_Recaptcha_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
220 |
+
'ITSEC_SSL' => __DIR__ . '/../..' . '/core/modules/ssl/class-itsec-ssl.php',
|
221 |
+
'ITSEC_SSL_Admin' => __DIR__ . '/../..' . '/core/modules/ssl/class-itsec-ssl-admin.php',
|
222 |
+
'ITSEC_SSL_Settings' => __DIR__ . '/../..' . '/core/modules/ssl/settings.php',
|
223 |
+
'ITSEC_SSL_Settings_Page' => __DIR__ . '/../..' . '/core/modules/ssl/settings-page.php',
|
224 |
+
'ITSEC_SSL_Setup' => __DIR__ . '/../..' . '/core/modules/ssl/setup.php',
|
225 |
+
'ITSEC_SSL_Validator' => __DIR__ . '/../..' . '/core/modules/ssl/validator.php',
|
226 |
+
'ITSEC_Salts_Setup' => __DIR__ . '/../..' . '/core/modules/salts/setup.php',
|
227 |
+
'ITSEC_Scheduler' => __DIR__ . '/../..' . '/core/lib/class-itsec-scheduler.php',
|
228 |
+
'ITSEC_Scheduler_Cron' => __DIR__ . '/../..' . '/core/lib/class-itsec-scheduler-cron.php',
|
229 |
+
'ITSEC_Scheduler_Page_Load' => __DIR__ . '/../..' . '/core/lib/class-itsec-scheduler-page-load.php',
|
230 |
+
'ITSEC_Schema' => __DIR__ . '/../..' . '/core/lib/schema.php',
|
231 |
+
'ITSEC_Security_Check_Feedback' => __DIR__ . '/../..' . '/core/modules/security-check/feedback.php',
|
232 |
+
'ITSEC_Security_Check_Feedback_Renderer' => __DIR__ . '/../..' . '/core/modules/security-check/feedback-renderer.php',
|
233 |
+
'ITSEC_Security_Check_Pro' => __DIR__ . '/../..' . '/core/modules/security-check-pro/class-itsec-security-check-pro.php',
|
234 |
+
'ITSEC_Security_Check_Pro_Debug' => __DIR__ . '/../..' . '/core/modules/security-check-pro/debug.php',
|
235 |
+
'ITSEC_Security_Check_Pro_Privacy' => __DIR__ . '/../..' . '/core/modules/security-check-pro/privacy.php',
|
236 |
+
'ITSEC_Security_Check_Pro_Settings' => __DIR__ . '/../..' . '/core/modules/security-check-pro/settings.php',
|
237 |
+
'ITSEC_Security_Check_Pro_Settings_Page' => __DIR__ . '/../..' . '/core/modules/security-check-pro/settings-page.php',
|
238 |
+
'ITSEC_Security_Check_Pro_Utility' => __DIR__ . '/../..' . '/core/modules/security-check-pro/utility.php',
|
239 |
+
'ITSEC_Security_Check_Pro_Validator' => __DIR__ . '/../..' . '/core/modules/security-check-pro/validator.php',
|
240 |
+
'ITSEC_Security_Check_Scanner' => __DIR__ . '/../..' . '/core/modules/security-check/scanner.php',
|
241 |
+
'ITSEC_Security_Check_Settings_Page' => __DIR__ . '/../..' . '/core/modules/security-check/settings-page.php',
|
242 |
+
'ITSEC_Settings' => __DIR__ . '/../..' . '/core/lib/settings.php',
|
243 |
+
'ITSEC_Settings_Page_Sidebar_Widget_BackupBuddy_Cross_Promo' => __DIR__ . '/../..' . '/core/modules/core/sidebar-widget-backupbuddy-cross-promo.php',
|
244 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Free_Support' => __DIR__ . '/../..' . '/core/modules/core/sidebar-widget-support.php',
|
245 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Mail_List_Signup' => __DIR__ . '/../..' . '/core/modules/core/sidebar-widget-mail-list-signup.php',
|
246 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Malware_Scan' => __DIR__ . '/../..' . '/core/modules/malware/settings-page.php',
|
247 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Pro_Upsell' => __DIR__ . '/../..' . '/core/modules/core/sidebar-widget-pro-upsell.php',
|
248 |
+
'ITSEC_Settings_Page_Sidebar_Widget_Sync_Cross_Promo' => __DIR__ . '/../..' . '/core/modules/core/sidebar-widget-sync-cross-promo.php',
|
249 |
+
'ITSEC_Static_Map_API' => __DIR__ . '/../..' . '/core/lib/static-map-api/interface-itsec-static-map-api.php',
|
250 |
+
'ITSEC_Storage' => __DIR__ . '/../..' . '/core/lib/storage.php',
|
251 |
+
'ITSEC_Strong_Passwords' => __DIR__ . '/../..' . '/core/modules/strong-passwords/class-itsec-strong-passwords.php',
|
252 |
+
'ITSEC_Strong_Passwords_Settings' => __DIR__ . '/../..' . '/core/modules/strong-passwords/settings.php',
|
253 |
+
'ITSEC_Strong_Passwords_Setup' => __DIR__ . '/../..' . '/core/modules/strong-passwords/setup.php',
|
254 |
+
'ITSEC_Strong_Passwords_Validator' => __DIR__ . '/../..' . '/core/modules/strong-passwords/validator.php',
|
255 |
+
'ITSEC_Sync_Connect' => __DIR__ . '/../..' . '/core/modules/sync-connect/class-itsec-sync-connect.php',
|
256 |
+
'ITSEC_Sync_Connect_Interstitial' => __DIR__ . '/../..' . '/core/modules/sync-connect/class-itsec-sync-connect-interstitial.php',
|
257 |
+
'ITSEC_System_Tweaks' => __DIR__ . '/../..' . '/core/modules/system-tweaks/class-itsec-system-tweaks.php',
|
258 |
+
'ITSEC_System_Tweaks_Config_Generators' => __DIR__ . '/../..' . '/core/modules/system-tweaks/config-generators.php',
|
259 |
+
'ITSEC_System_Tweaks_Settings' => __DIR__ . '/../..' . '/core/modules/system-tweaks/settings.php',
|
260 |
+
'ITSEC_System_Tweaks_Settings_Page' => __DIR__ . '/../..' . '/core/modules/system-tweaks/settings-page.php',
|
261 |
+
'ITSEC_System_Tweaks_Setup' => __DIR__ . '/../..' . '/core/modules/system-tweaks/setup.php',
|
262 |
+
'ITSEC_System_Tweaks_Validator' => __DIR__ . '/../..' . '/core/modules/system-tweaks/validator.php',
|
263 |
+
'ITSEC_Two_Factor_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
264 |
+
'ITSEC_User_Logging_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
265 |
+
'ITSEC_User_Security_Check_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
266 |
+
'ITSEC_Validator' => __DIR__ . '/../..' . '/core/lib/validator.php',
|
267 |
+
'ITSEC_Version_Management_Settings_Page' => __DIR__ . '/../..' . '/core/modules/pro/settings-page.php',
|
268 |
+
'ITSEC_WP_List_Table' => __DIR__ . '/../..' . '/core/lib/class-itsec-wp-list-table.php',
|
269 |
+
'ITSEC_WordPress_Salts_Settings' => __DIR__ . '/../..' . '/core/modules/salts/settings.php',
|
270 |
+
'ITSEC_WordPress_Salts_Settings_Page' => __DIR__ . '/../..' . '/core/modules/salts/settings-page.php',
|
271 |
+
'ITSEC_WordPress_Salts_Utilities' => __DIR__ . '/../..' . '/core/modules/salts/utilities.php',
|
272 |
+
'ITSEC_WordPress_Salts_Validator' => __DIR__ . '/../..' . '/core/modules/salts/validator.php',
|
273 |
+
'ITSEC_WordPress_Tweaks' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php',
|
274 |
+
'ITSEC_WordPress_Tweaks_Config_Generators' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/config-generators.php',
|
275 |
+
'ITSEC_WordPress_Tweaks_Settings_Page' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/settings-page.php',
|
276 |
+
'ITSEC_WordPress_Tweaks_Setup' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/setup.php',
|
277 |
+
'ITSEC_WordPress_Tweaks_Validator' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/validator.php',
|
278 |
+
'ITSEC_Wordpress_Tweaks_Settings' => __DIR__ . '/../..' . '/core/modules/wordpress-tweaks/settings.php',
|
279 |
+
'Ithemes_Sync_Verb_ITSEC_Do_Security_Check' => __DIR__ . '/../..' . '/core/modules/security-check/sync-verbs/itsec-do-security-check.php',
|
280 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Away_Mode' => __DIR__ . '/../..' . '/core/modules/away-mode/sync-verbs/itsec-get-away-mode.php',
|
281 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log' => __DIR__ . '/../..' . '/core/modules/malware/sync-verbs/itsec-get-malware-scan-log.php',
|
282 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Security_Check_Feedback_Response' => __DIR__ . '/../..' . '/core/modules/security-check/sync-verbs/itsec-get-security-check-feedback-response.php',
|
283 |
+
'Ithemes_Sync_Verb_ITSEC_Get_Security_Check_Modules' => __DIR__ . '/../..' . '/core/modules/security-check/sync-verbs/itsec-get-security-check-modules.php',
|
284 |
+
'Ithemes_Sync_Verb_ITSEC_Latest_File_Scan' => __DIR__ . '/../..' . '/core/modules/file-change/sync-verbs/itsec-latest-file-scan.php',
|
285 |
+
'Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan' => __DIR__ . '/../..' . '/core/modules/malware/sync-verbs/itsec-do-malware-scan.php',
|
286 |
+
'Ithemes_Sync_Verb_ITSEC_Override_Away_Mode' => __DIR__ . '/../..' . '/core/modules/away-mode/sync-verbs/itsec-override-away-mode.php',
|
287 |
+
'Pimple\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Container.php',
|
288 |
+
'Pimple\\Exception\\ExpectedInvokableException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
289 |
+
'Pimple\\Exception\\FrozenServiceException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
290 |
+
'Pimple\\Exception\\InvalidServiceIdentifierException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php',
|
291 |
+
'Pimple\\Exception\\UnknownIdentifierException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php',
|
292 |
+
'Pimple\\Psr11\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Psr11/Container.php',
|
293 |
+
'Pimple\\Psr11\\ServiceLocator' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php',
|
294 |
+
'Pimple\\ServiceIterator' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/ServiceIterator.php',
|
295 |
+
'Pimple\\ServiceProviderInterface' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php',
|
296 |
+
'Pimple\\Tests\\Fixtures\\Invokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php',
|
297 |
+
'Pimple\\Tests\\Fixtures\\NonInvokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php',
|
298 |
+
'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php',
|
299 |
+
'Pimple\\Tests\\Fixtures\\Service' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php',
|
300 |
+
'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php',
|
301 |
+
'Pimple\\Tests\\PimpleTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php',
|
302 |
+
'Pimple\\Tests\\Psr11\\ContainerTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php',
|
303 |
+
'Pimple\\Tests\\Psr11\\ServiceLocatorTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php',
|
304 |
+
'Pimple\\Tests\\ServiceIteratorTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php',
|
305 |
+
'Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php',
|
306 |
+
'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php',
|
307 |
+
'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php',
|
308 |
+
'Wikimedia\\Composer\\Logger' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Logger.php',
|
309 |
+
'Wikimedia\\Composer\\MergePlugin' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/MergePlugin.php',
|
310 |
+
'Wikimedia\\Composer\\Merge\\ExtraPackage' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Merge/ExtraPackage.php',
|
311 |
+
'Wikimedia\\Composer\\Merge\\MissingFileException' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Merge/MissingFileException.php',
|
312 |
+
'Wikimedia\\Composer\\Merge\\NestedArray' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Merge/NestedArray.php',
|
313 |
+
'Wikimedia\\Composer\\Merge\\PluginState' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Merge/PluginState.php',
|
314 |
+
'Wikimedia\\Composer\\Merge\\StabilityFlags' => __DIR__ . '/..' . '/wikimedia/composer-merge-plugin/src/Merge/StabilityFlags.php',
|
315 |
+
'iThemesSecurity\\Contracts\\Runnable' => __DIR__ . '/../..' . '/core/Contracts/Runnable.php',
|
316 |
+
'iThemesSecurity\\Exception\\Exception' => __DIR__ . '/../..' . '/core/Exception/Exception.php',
|
317 |
+
'iThemesSecurity\\Exception\\Invalid_Argument_Exception' => __DIR__ . '/../..' . '/core/Exception/Invalid_Argument_Exception.php',
|
318 |
+
'iThemesSecurity\\Exception\\Unsatisfied_Module_Dependencies_Exception' => __DIR__ . '/../..' . '/core/Exception/Unsatisfied_Module_Dependencies_Exception.php',
|
319 |
+
'iThemesSecurity\\Exception\\WP_Error' => __DIR__ . '/../..' . '/core/Exception/WP_Error.php',
|
320 |
+
'iThemesSecurity\\Lib\\Lockout\\Context' => __DIR__ . '/../..' . '/core/lib/lockout/abstract-context.php',
|
321 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Context' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/abstract-context.php',
|
322 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Host_Context' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/class-host-context.php',
|
323 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Configurable' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/source/class-configurable.php',
|
324 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Lockout_Module' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/source/class-lockout-module.php',
|
325 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Source\\Source' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/source/interface-source.php',
|
326 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\User_Context' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/class-user-context.php',
|
327 |
+
'iThemesSecurity\\Lib\\Lockout\\Execute_Lock\\Username_Context' => __DIR__ . '/../..' . '/core/lib/lockout/execute-lock/class-username-context.php',
|
328 |
+
'iThemesSecurity\\Lib\\Lockout\\Host_Context' => __DIR__ . '/../..' . '/core/lib/lockout/class-host-context.php',
|
329 |
+
'iThemesSecurity\\Lib\\Lockout\\Lockout' => __DIR__ . '/../..' . '/core/lib/lockout/class-lockout.php',
|
330 |
+
'iThemesSecurity\\Lib\\Lockout\\User_Context' => __DIR__ . '/../..' . '/core/lib/lockout/class-user-context.php',
|
331 |
+
'iThemesSecurity\\Lib\\Lockout\\Username_Context' => __DIR__ . '/../..' . '/core/lib/lockout/class-username-context.php',
|
332 |
+
'iThemesSecurity\\User_Groups\\All_Users' => __DIR__ . '/../..' . '/core/modules/user-groups/All_Users.php',
|
333 |
+
'iThemesSecurity\\User_Groups\\Default_Matcher' => __DIR__ . '/../..' . '/core/modules/user-groups/Match/Default_Matcher.php',
|
334 |
+
'iThemesSecurity\\User_Groups\\Everybody_Else' => __DIR__ . '/../..' . '/core/modules/user-groups/Everybody_Else.php',
|
335 |
+
'iThemesSecurity\\User_Groups\\Match_Target' => __DIR__ . '/../..' . '/core/modules/user-groups/Match/Match_Target.php',
|
336 |
+
'iThemesSecurity\\User_Groups\\Matchable' => __DIR__ . '/../..' . '/core/modules/user-groups/Matchable.php',
|
337 |
+
'iThemesSecurity\\User_Groups\\Matchable_Not_Found' => __DIR__ . '/../..' . '/core/modules/user-groups/Match/Matchable_Not_Found.php',
|
338 |
+
'iThemesSecurity\\User_Groups\\Matchables_Source' => __DIR__ . '/../..' . '/core/modules/user-groups/Matchables_Source.php',
|
339 |
+
'iThemesSecurity\\User_Groups\\Matcher' => __DIR__ . '/../..' . '/core/modules/user-groups/Match/Matcher.php',
|
340 |
+
'iThemesSecurity\\User_Groups\\Module\\Module' => __DIR__ . '/../..' . '/core/modules/user-groups/Module/Module.php',
|
341 |
+
'iThemesSecurity\\User_Groups\\Module\\Settings' => __DIR__ . '/../..' . '/core/modules/user-groups/Module/Settings.php',
|
342 |
+
'iThemesSecurity\\User_Groups\\Module\\Validator' => __DIR__ . '/../..' . '/core/modules/user-groups/Module/Validator.php',
|
343 |
+
'iThemesSecurity\\User_Groups\\REST\\Matchables' => __DIR__ . '/../..' . '/core/modules/user-groups/REST/Matchables.php',
|
344 |
+
'iThemesSecurity\\User_Groups\\REST\\REST' => __DIR__ . '/../..' . '/core/modules/user-groups/REST/REST.php',
|
345 |
+
'iThemesSecurity\\User_Groups\\REST\\Settings' => __DIR__ . '/../..' . '/core/modules/user-groups/REST/Settings.php',
|
346 |
+
'iThemesSecurity\\User_Groups\\REST\\User_Groups' => __DIR__ . '/../..' . '/core/modules/user-groups/REST/User_Groups.php',
|
347 |
+
'iThemesSecurity\\User_Groups\\Repository\\DB_Repository' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/DB_Repository.php',
|
348 |
+
'iThemesSecurity\\User_Groups\\Repository\\Decorator' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/Decorator.php',
|
349 |
+
'iThemesSecurity\\User_Groups\\Repository\\Eager_Loading_Decorator' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/Eager_Loading_Decorator.php',
|
350 |
+
'iThemesSecurity\\User_Groups\\Repository\\In_Memory_Repository' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/In_Memory_Repository.php',
|
351 |
+
'iThemesSecurity\\User_Groups\\Repository\\Object_Caching_Decorator' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/Object_Caching_Decorator.php',
|
352 |
+
'iThemesSecurity\\User_Groups\\Repository\\Repository' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/Repository.php',
|
353 |
+
'iThemesSecurity\\User_Groups\\Repository\\User_Group_Not_Found' => __DIR__ . '/../..' . '/core/modules/user-groups/Repository/User_Group_Not_Found.php',
|
354 |
+
'iThemesSecurity\\User_Groups\\Settings_Page' => __DIR__ . '/../..' . '/core/modules/user-groups/settings-page.php',
|
355 |
+
'iThemesSecurity\\User_Groups\\Settings_Proxy' => __DIR__ . '/../..' . '/core/modules/user-groups/Settings/Settings_Proxy.php',
|
356 |
+
'iThemesSecurity\\User_Groups\\Settings_Registration' => __DIR__ . '/../..' . '/core/modules/user-groups/Settings/Settings_Registration.php',
|
357 |
+
'iThemesSecurity\\User_Groups\\Settings_Registry' => __DIR__ . '/../..' . '/core/modules/user-groups/Settings/Settings_Registry.php',
|
358 |
+
'iThemesSecurity\\User_Groups\\Upgrader' => __DIR__ . '/../..' . '/core/modules/user-groups/Upgrader.php',
|
359 |
+
'iThemesSecurity\\User_Groups\\User_Group' => __DIR__ . '/../..' . '/core/modules/user-groups/User_Group.php',
|
360 |
+
);
|
361 |
+
|
362 |
+
public static function getInitializer(ClassLoader $loader)
|
363 |
+
{
|
364 |
+
return \Closure::bind(function () use ($loader) {
|
365 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f::$prefixLengthsPsr4;
|
366 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f::$prefixDirsPsr4;
|
367 |
+
$loader->prefixesPsr0 = ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f::$prefixesPsr0;
|
368 |
+
$loader->classMap = ComposerStaticInit35a2bd4feb347da0d3ea2d8ef023082f::$classMap;
|
369 |
+
|
370 |
+
}, null, ClassLoader::class);
|
371 |
+
}
|
372 |
+
}
|
vendor-prod/composer/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
vendor-prod/composer/installed.json
ADDED
@@ -0,0 +1,156 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"name": "pimple/pimple",
|
4 |
+
"version": "v3.2.3",
|
5 |
+
"version_normalized": "3.2.3.0",
|
6 |
+
"source": {
|
7 |
+
"type": "git",
|
8 |
+
"url": "https://github.com/silexphp/Pimple.git",
|
9 |
+
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
|
10 |
+
},
|
11 |
+
"dist": {
|
12 |
+
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
|
14 |
+
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
|
15 |
+
"shasum": ""
|
16 |
+
},
|
17 |
+
"require": {
|
18 |
+
"php": ">=5.3.0",
|
19 |
+
"psr/container": "^1.0"
|
20 |
+
},
|
21 |
+
"require-dev": {
|
22 |
+
"symfony/phpunit-bridge": "^3.2"
|
23 |
+
},
|
24 |
+
"time": "2018-01-21T07:42:36+00:00",
|
25 |
+
"type": "library",
|
26 |
+
"extra": {
|
27 |
+
"branch-alias": {
|
28 |
+
"dev-master": "3.2.x-dev"
|
29 |
+
}
|
30 |
+
},
|
31 |
+
"installation-source": "dist",
|
32 |
+
"autoload": {
|
33 |
+
"psr-0": {
|
34 |
+
"Pimple": "src/"
|
35 |
+
}
|
36 |
+
},
|
37 |
+
"notification-url": "https://packagist.org/downloads/",
|
38 |
+
"license": [
|
39 |
+
"MIT"
|
40 |
+
],
|
41 |
+
"authors": [
|
42 |
+
{
|
43 |
+
"name": "Fabien Potencier",
|
44 |
+
"email": "fabien@symfony.com"
|
45 |
+
}
|
46 |
+
],
|
47 |
+
"description": "Pimple, a simple Dependency Injection Container",
|
48 |
+
"homepage": "http://pimple.sensiolabs.org",
|
49 |
+
"keywords": [
|
50 |
+
"container",
|
51 |
+
"dependency injection"
|
52 |
+
]
|
53 |
+
},
|
54 |
+
{
|
55 |
+
"name": "psr/container",
|
56 |
+
"version": "1.0.0",
|
57 |
+
"version_normalized": "1.0.0.0",
|
58 |
+
"source": {
|
59 |
+
"type": "git",
|
60 |
+
"url": "https://github.com/php-fig/container.git",
|
61 |
+
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
|
62 |
+
},
|
63 |
+
"dist": {
|
64 |
+
"type": "zip",
|
65 |
+
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
66 |
+
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
67 |
+
"shasum": ""
|
68 |
+
},
|
69 |
+
"require": {
|
70 |
+
"php": ">=5.3.0"
|
71 |
+
},
|
72 |
+
"time": "2017-02-14T16:28:37+00:00",
|
73 |
+
"type": "library",
|
74 |
+
"extra": {
|
75 |
+
"branch-alias": {
|
76 |
+
"dev-master": "1.0.x-dev"
|
77 |
+
}
|
78 |
+
},
|
79 |
+
"installation-source": "dist",
|
80 |
+
"autoload": {
|
81 |
+
"psr-4": {
|
82 |
+
"Psr\\Container\\": "src/"
|
83 |
+
}
|
84 |
+
},
|
85 |
+
"notification-url": "https://packagist.org/downloads/",
|
86 |
+
"license": [
|
87 |
+
"MIT"
|
88 |
+
],
|
89 |
+
"authors": [
|
90 |
+
{
|
91 |
+
"name": "PHP-FIG",
|
92 |
+
"homepage": "http://www.php-fig.org/"
|
93 |
+
}
|
94 |
+
],
|
95 |
+
"description": "Common Container Interface (PHP FIG PSR-11)",
|
96 |
+
"homepage": "https://github.com/php-fig/container",
|
97 |
+
"keywords": [
|
98 |
+
"PSR-11",
|
99 |
+
"container",
|
100 |
+
"container-interface",
|
101 |
+
"container-interop",
|
102 |
+
"psr"
|
103 |
+
]
|
104 |
+
},
|
105 |
+
{
|
106 |
+
"name": "wikimedia/composer-merge-plugin",
|
107 |
+
"version": "v1.4.1",
|
108 |
+
"version_normalized": "1.4.1.0",
|
109 |
+
"source": {
|
110 |
+
"type": "git",
|
111 |
+
"url": "https://github.com/wikimedia/composer-merge-plugin.git",
|
112 |
+
"reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100"
|
113 |
+
},
|
114 |
+
"dist": {
|
115 |
+
"type": "zip",
|
116 |
+
"url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/81c6ac72a24a67383419c7eb9aa2b3437f2ab100",
|
117 |
+
"reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100",
|
118 |
+
"shasum": ""
|
119 |
+
},
|
120 |
+
"require": {
|
121 |
+
"composer-plugin-api": "^1.0",
|
122 |
+
"php": ">=5.3.2"
|
123 |
+
},
|
124 |
+
"require-dev": {
|
125 |
+
"composer/composer": "~1.0.0",
|
126 |
+
"jakub-onderka/php-parallel-lint": "~0.8",
|
127 |
+
"phpunit/phpunit": "~4.8|~5.0",
|
128 |
+
"squizlabs/php_codesniffer": "~2.1.0"
|
129 |
+
},
|
130 |
+
"time": "2017-04-25T02:31:25+00:00",
|
131 |
+
"type": "composer-plugin",
|
132 |
+
"extra": {
|
133 |
+
"branch-alias": {
|
134 |
+
"dev-master": "1.3.x-dev"
|
135 |
+
},
|
136 |
+
"class": "Wikimedia\\Composer\\MergePlugin"
|
137 |
+
},
|
138 |
+
"installation-source": "dist",
|
139 |
+
"autoload": {
|
140 |
+
"psr-4": {
|
141 |
+
"Wikimedia\\Composer\\": "src/"
|
142 |
+
}
|
143 |
+
},
|
144 |
+
"notification-url": "https://packagist.org/downloads/",
|
145 |
+
"license": [
|
146 |
+
"MIT"
|
147 |
+
],
|
148 |
+
"authors": [
|
149 |
+
{
|
150 |
+
"name": "Bryan Davis",
|
151 |
+
"email": "bd808@wikimedia.org"
|
152 |
+
}
|
153 |
+
],
|
154 |
+
"description": "Composer plugin to merge multiple composer.json files"
|
155 |
+
}
|
156 |
+
]
|
vendor-prod/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
vendor-prod/pimple/index.php
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
<?php // Silence is golden.
|
vendor-prod/pimple/pimple/CHANGELOG
ADDED
@@ -0,0 +1,59 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
* 3.2.3 (2017-XX-XX)
|
2 |
+
|
3 |
+
* n/a
|
4 |
+
|
5 |
+
* 3.2.2 (2017-07-23)
|
6 |
+
|
7 |
+
* reverted extending a protected closure throws an exception (deprecated it instead)
|
8 |
+
|
9 |
+
* 3.2.1 (2017-07-17)
|
10 |
+
|
11 |
+
* fixed PHP error
|
12 |
+
|
13 |
+
* 3.2.0 (2017-07-17)
|
14 |
+
|
15 |
+
* added a PSR-11 service locator
|
16 |
+
* added a PSR-11 wrapper
|
17 |
+
* added ServiceIterator
|
18 |
+
* fixed extending a protected closure (now throws InvalidServiceIdentifierException)
|
19 |
+
|
20 |
+
* 3.1.0 (2017-07-03)
|
21 |
+
|
22 |
+
* deprecated the C extension
|
23 |
+
* added support for PSR-11 exceptions
|
24 |
+
|
25 |
+
* 3.0.2 (2015-09-11)
|
26 |
+
|
27 |
+
* refactored the C extension
|
28 |
+
* minor non-significant changes
|
29 |
+
|
30 |
+
* 3.0.1 (2015-07-30)
|
31 |
+
|
32 |
+
* simplified some code
|
33 |
+
* fixed a segfault in the C extension
|
34 |
+
|
35 |
+
* 3.0.0 (2014-07-24)
|
36 |
+
|
37 |
+
* removed the Pimple class alias (use Pimple\Container instead)
|
38 |
+
|
39 |
+
* 2.1.1 (2014-07-24)
|
40 |
+
|
41 |
+
* fixed compiler warnings for the C extension
|
42 |
+
* fixed code when dealing with circular references
|
43 |
+
|
44 |
+
* 2.1.0 (2014-06-24)
|
45 |
+
|
46 |
+
* moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a
|
47 |
+
deprecated alias which will be removed in Pimple 3.0)
|
48 |
+
* added Pimple\ServiceProviderInterface (and Pimple::register())
|
49 |
+
|
50 |
+
* 2.0.0 (2014-02-10)
|
51 |
+
|
52 |
+
* changed extend to automatically re-assign the extended service and keep it as shared or factory
|
53 |
+
(to keep BC, extend still returns the extended service)
|
54 |
+
* changed services to be shared by default (use factory() for factory
|
55 |
+
services)
|
56 |
+
|
57 |
+
* 1.0.0
|
58 |
+
|
59 |
+
* initial version
|
vendor-prod/pimple/pimple/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
Copyright (c) 2009-2017 Fabien Potencier
|
2 |
+
|
3 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4 |
+
of this software and associated documentation files (the "Software"), to deal
|
5 |
+
in the Software without restriction, including without limitation the rights
|
6 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
8 |
+
to do so, subject to the following conditions:
|
9 |
+
|
10 |
+
The above copyright notice and this permission notice shall be included in all
|
11 |
+
copies or substantial portions of the Software.
|
12 |
+
|
13 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19 |
+
THE SOFTWARE.
|
vendor-prod/pimple/pimple/README.rst
ADDED
@@ -0,0 +1,326 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
Pimple
|
2 |
+
======
|
3 |
+
|
4 |
+
.. caution::
|
5 |
+
|
6 |
+
This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read
|
7 |
+
the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good
|
8 |
+
way to learn more about how to create a simple Dependency Injection
|
9 |
+
Container (recent versions of Pimple are more focused on performance).
|
10 |
+
|
11 |
+
Pimple is a small Dependency Injection Container for PHP.
|
12 |
+
|
13 |
+
Installation
|
14 |
+
------------
|
15 |
+
|
16 |
+
Before using Pimple in your project, add it to your ``composer.json`` file:
|
17 |
+
|
18 |
+
.. code-block:: bash
|
19 |
+
|
20 |
+
$ ./composer.phar require pimple/pimple "^3.0"
|
21 |
+
|
22 |
+
Usage
|
23 |
+
-----
|
24 |
+
|
25 |
+
Creating a container is a matter of creating a ``Container`` instance:
|
26 |
+
|
27 |
+
.. code-block:: php
|
28 |
+
|
29 |
+
use Pimple\Container;
|
30 |
+
|
31 |
+
$container = new Container();
|
32 |
+
|
33 |
+
As many other dependency injection containers, Pimple manages two different
|
34 |
+
kind of data: **services** and **parameters**.
|
35 |
+
|
36 |
+
Defining Services
|
37 |
+
~~~~~~~~~~~~~~~~~
|
38 |
+
|
39 |
+
A service is an object that does something as part of a larger system. Examples
|
40 |
+
of services: a database connection, a templating engine, or a mailer. Almost
|
41 |
+
any **global** object can be a service.
|
42 |
+
|
43 |
+
Services are defined by **anonymous functions** that return an instance of an
|
44 |
+
object:
|
45 |
+
|
46 |
+
.. code-block:: php
|
47 |
+
|
48 |
+
// define some services
|
49 |
+
$container['session_storage'] = function ($c) {
|
50 |
+
return new SessionStorage('SESSION_ID');
|
51 |
+
};
|
52 |
+
|
53 |
+
$container['session'] = function ($c) {
|
54 |
+
return new Session($c['session_storage']);
|
55 |
+
};
|
56 |
+
|
57 |
+
Notice that the anonymous function has access to the current container
|
58 |
+
instance, allowing references to other services or parameters.
|
59 |
+
|
60 |
+
As objects are only created when you get them, the order of the definitions
|
61 |
+
does not matter.
|
62 |
+
|
63 |
+
Using the defined services is also very easy:
|
64 |
+
|
65 |
+
.. code-block:: php
|
66 |
+
|
67 |
+
// get the session object
|
68 |
+
$session = $container['session'];
|
69 |
+
|
70 |
+
// the above call is roughly equivalent to the following code:
|
71 |
+
// $storage = new SessionStorage('SESSION_ID');
|
72 |
+
// $session = new Session($storage);
|
73 |
+
|
74 |
+
Defining Factory Services
|
75 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
76 |
+
|
77 |
+
By default, each time you get a service, Pimple returns the **same instance**
|
78 |
+
of it. If you want a different instance to be returned for all calls, wrap your
|
79 |
+
anonymous function with the ``factory()`` method
|
80 |
+
|
81 |
+
.. code-block:: php
|
82 |
+
|
83 |
+
$container['session'] = $container->factory(function ($c) {
|
84 |
+
return new Session($c['session_storage']);
|
85 |
+
});
|
86 |
+
|
87 |
+
Now, each call to ``$container['session']`` returns a new instance of the
|
88 |
+
session.
|
89 |
+
|
90 |
+
Defining Parameters
|
91 |
+
~~~~~~~~~~~~~~~~~~~
|
92 |
+
|
93 |
+
Defining a parameter allows to ease the configuration of your container from
|
94 |
+
the outside and to store global values:
|
95 |
+
|
96 |
+
.. code-block:: php
|
97 |
+
|
98 |
+
// define some parameters
|
99 |
+
$container['cookie_name'] = 'SESSION_ID';
|
100 |
+
$container['session_storage_class'] = 'SessionStorage';
|
101 |
+
|
102 |
+
If you change the ``session_storage`` service definition like below:
|
103 |
+
|
104 |
+
.. code-block:: php
|
105 |
+
|
106 |
+
$container['session_storage'] = function ($c) {
|
107 |
+
return new $c['session_storage_class']($c['cookie_name']);
|
108 |
+
};
|
109 |
+
|
110 |
+
You can now easily change the cookie name by overriding the
|
111 |
+
``cookie_name`` parameter instead of redefining the service
|
112 |
+
definition.
|
113 |
+
|
114 |
+
Protecting Parameters
|
115 |
+
~~~~~~~~~~~~~~~~~~~~~
|
116 |
+
|
117 |
+
Because Pimple sees anonymous functions as service definitions, you need to
|
118 |
+
wrap anonymous functions with the ``protect()`` method to store them as
|
119 |
+
parameters:
|
120 |
+
|
121 |
+
.. code-block:: php
|
122 |
+
|
123 |
+
$container['random_func'] = $container->protect(function () {
|
124 |
+
return rand();
|
125 |
+
});
|
126 |
+
|
127 |
+
Modifying Services after Definition
|
128 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
129 |
+
|
130 |
+
In some cases you may want to modify a service definition after it has been
|
131 |
+
defined. You can use the ``extend()`` method to define additional code to be
|
132 |
+
run on your service just after it is created:
|
133 |
+
|
134 |
+
.. code-block:: php
|
135 |
+
|
136 |
+
$container['session_storage'] = function ($c) {
|
137 |
+
return new $c['session_storage_class']($c['cookie_name']);
|
138 |
+
};
|
139 |
+
|
140 |
+
$container->extend('session_storage', function ($storage, $c) {
|
141 |
+
$storage->...();
|
142 |
+
|
143 |
+
return $storage;
|
144 |
+
});
|
145 |
+
|
146 |
+
The first argument is the name of the service to extend, the second a function
|
147 |
+
that gets access to the object instance and the container.
|
148 |
+
|
149 |
+
Extending a Container
|
150 |
+
~~~~~~~~~~~~~~~~~~~~~
|
151 |
+
|
152 |
+
If you use the same libraries over and over, you might want to reuse some
|
153 |
+
services from one project to the next one; package your services into a
|
154 |
+
**provider** by implementing ``Pimple\ServiceProviderInterface``:
|
155 |
+
|
156 |
+
.. code-block:: php
|
157 |
+
|
158 |
+
use Pimple\Container;
|
159 |
+
|
160 |
+
class FooProvider implements Pimple\ServiceProviderInterface
|
161 |
+
{
|
162 |
+
public function register(Container $pimple)
|
163 |
+
{
|
164 |
+
// register some services and parameters
|
165 |
+
// on $pimple
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
Then, register the provider on a Container:
|
170 |
+
|
171 |
+
.. code-block:: php
|
172 |
+
|
173 |
+
$pimple->register(new FooProvider());
|
174 |
+
|
175 |
+
Fetching the Service Creation Function
|
176 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
177 |
+
|
178 |
+
When you access an object, Pimple automatically calls the anonymous function
|
179 |
+
that you defined, which creates the service object for you. If you want to get
|
180 |
+
raw access to this function, you can use the ``raw()`` method:
|
181 |
+
|
182 |
+
.. code-block:: php
|
183 |
+
|
184 |
+
$container['session'] = function ($c) {
|
185 |
+
return new Session($c['session_storage']);
|
186 |
+
};
|
187 |
+
|
188 |
+
$sessionFunction = $container->raw('session');
|
189 |
+
|
190 |
+
PSR-11 compatibility
|
191 |
+
--------------------
|
192 |
+
|
193 |
+
For historical reasons, the ``Container`` class does not implement the PSR-11
|
194 |
+
``ContainerInterface``. However, Pimple provides a helper class that will let
|
195 |
+
you decouple your code from the Pimple container class.
|
196 |
+
|
197 |
+
The PSR-11 container class
|
198 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
199 |
+
|
200 |
+
The ``Pimple\Psr11\Container`` class lets you access the content of an
|
201 |
+
underlying Pimple container using ``Psr\Container\ContainerInterface``
|
202 |
+
methods:
|
203 |
+
|
204 |
+
.. code-block:: php
|
205 |
+
|
206 |
+
use Pimple\Container;
|
207 |
+
use Pimple\Psr11\Container as PsrContainer;
|
208 |
+
|
209 |
+
$container = new Container();
|
210 |
+
$container['service'] = function ($c) {
|
211 |
+
return new Service();
|
212 |
+
};
|
213 |
+
$psr11 = new PsrContainer($container);
|
214 |
+
|
215 |
+
$controller = function (PsrContainer $container) {
|
216 |
+
$service = $container->get('service');
|
217 |
+
};
|
218 |
+
$controller($psr11);
|
219 |
+
|
220 |
+
Using the PSR-11 ServiceLocator
|
221 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
222 |
+
|
223 |
+
Sometimes, a service needs access to several other services without being sure
|
224 |
+
that all of them will actually be used. In those cases, you may want the
|
225 |
+
instantiation of the services to be lazy.
|
226 |
+
|
227 |
+
The traditional solution is to inject the entire service container to get only
|
228 |
+
the services really needed. However, this is not recommended because it gives
|
229 |
+
services a too broad access to the rest of the application and it hides their
|
230 |
+
actual dependencies.
|
231 |
+
|
232 |
+
The ``ServiceLocator`` is intended to solve this problem by giving access to a
|
233 |
+
set of predefined services while instantiating them only when actually needed.
|
234 |
+
|
235 |
+
It also allows you to make your services available under a different name than
|
236 |
+
the one used to register them. For instance, you may want to use an object
|
237 |
+
that expects an instance of ``EventDispatcherInterface`` to be available under
|
238 |
+
the name ``event_dispatcher`` while your event dispatcher has been
|
239 |
+
registered under the name ``dispatcher``:
|
240 |
+
|
241 |
+
.. code-block:: php
|
242 |
+
|
243 |
+
use Monolog\Logger;
|
244 |
+
use Pimple\Psr11\ServiceLocator;
|
245 |
+
use Psr\Container\ContainerInterface;
|
246 |
+
use Symfony\Component\EventDispatcher\EventDispatcher;
|
247 |
+
|
248 |
+
class MyService
|
249 |
+
{
|
250 |
+
/**
|
251 |
+
* "logger" must be an instance of Psr\Log\LoggerInterface
|
252 |
+
* "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface
|
253 |
+
*/
|
254 |
+
private $services;
|
255 |
+
|
256 |
+
public function __construct(ContainerInterface $services)
|
257 |
+
{
|
258 |
+
$this->services = $services;
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
$container['logger'] = function ($c) {
|
263 |
+
return new Monolog\Logger();
|
264 |
+
};
|
265 |
+
$container['dispatcher'] = function () {
|
266 |
+
return new EventDispatcher();
|
267 |
+
};
|
268 |
+
|
269 |
+
$container['service'] = function ($c) {
|
270 |
+
$locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher'));
|
271 |
+
|
272 |
+
return new MyService($locator);
|
273 |
+
};
|
274 |
+
|
275 |
+
Referencing a Collection of Services Lazily
|
276 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
277 |
+
|
278 |
+
Passing a collection of services instances in an array may prove inefficient
|
279 |
+
if the class that consumes the collection only needs to iterate over it at a
|
280 |
+
later stage, when one of its method is called. It can also lead to problems
|
281 |
+
if there is a circular dependency between one of the services stored in the
|
282 |
+
collection and the class that consumes it.
|
283 |
+
|
284 |
+
The ``ServiceIterator`` class helps you solve these issues. It receives a
|
285 |
+
list of service names during instantiation and will retrieve the services
|
286 |
+
when iterated over:
|
287 |
+
|
288 |
+
.. code-block:: php
|
289 |
+
|
290 |
+
use Pimple\Container;
|
291 |
+
use Pimple\ServiceIterator;
|
292 |
+
|
293 |
+
class AuthorizationService
|
294 |
+
{
|
295 |
+
private $voters;
|
296 |
+
|
297 |
+
public function __construct($voters)
|
298 |
+
{
|
299 |
+
$this->voters = $voters;
|
300 |
+
}
|
301 |
+
|
302 |
+
public function canAccess($resource)
|
303 |
+
{
|
304 |
+
foreach ($this->voters as $voter) {
|
305 |
+
if (true === $voter->canAccess($resource) {
|
306 |
+
return true;
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
return false;
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
$container = new Container();
|
315 |
+
|