diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4ed72b0..0f8436c 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -32,7 +32,7 @@ jobs:
args: >
-Dsonar.organization=stklcode-github
-Dsonar.projectKey=stklcode:statify-blacklist
- -Dsonar.sources=inc,views,statify-blacklist.php
+ -Dsonar.sources=inc,statify-blacklist.php
-Dsonar.tests=test
-Dsonar.php.tests.reportPath=tests-junit.xml
-Dsonar.php.coverage.reportPaths=tests-clover.xml
diff --git a/inc/class-statifyblacklist-admin.php b/inc/class-statifyblacklist-admin.php
index 7151940..023321b 100644
--- a/inc/class-statifyblacklist-admin.php
+++ b/inc/class-statifyblacklist-admin.php
@@ -16,17 +16,15 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Statify Filter admin configuration.
- *
- * @since 1.0.0
*/
class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Initialize admin-only components of the plugin.
*
- * @since 1.5.0
- *
* @return void
+ *
+ * @since 1.5.0
*/
public static function init() {
// Add actions.
@@ -46,91 +44,12 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
2
);
} else {
+ add_action( 'admin_init', array( 'StatifyBlacklist_Settings', 'register_settings' ) );
add_action( 'admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
add_filter( 'plugin_action_links', array( 'StatifyBlacklist_Admin', 'plugin_actions_links' ), 10, 2 );
}
}
- /**
- * Update options.
- *
- * @since 1.1.1
- *
- * @param array $options Optional. New options to save.
- *
- * @return array|bool array of sanitized array on errors, FALSE if there were none.
- */
- public static function update_options( $options = null ) {
- if ( isset( $options ) && current_user_can( 'manage_options' ) ) {
-
- // Sanitize referer list.
- $given_referer = $options['referer']['blacklist'];
- $invalid_referer = array();
- if ( self::MODE_NORMAL === $options['referer']['regexp'] ) {
- // Sanitize URLs and remove empty inputs.
- $sanitized_referer = self::sanitize_urls( $given_referer );
- } elseif ( self::MODE_REGEX === $options['referer']['regexp'] || self::MODE_REGEX_CI === $options['referer']['regexp'] ) {
- $sanitized_referer = $given_referer;
- // Check regular expressions.
- $invalid_referer = self::sanitize_regex( $given_referer );
- } else {
- $sanitized_referer = $given_referer;
- }
-
- // Sanitize target list.
- $given_target = $options['target']['blacklist'];
- $invalid_target = array();
- if ( self::MODE_REGEX === $options['target']['regexp'] || self::MODE_REGEX_CI === $options['target']['regexp'] ) {
- $sanitized_target = $given_target;
- // Check regular expressions.
- $invalid_target = self::sanitize_regex( $given_target );
- } else {
- $sanitized_target = $given_target;
- }
-
- // Sanitize IPs and subnets and remove empty inputs.
- $given_ip = $options['ip']['blacklist'];
- $sanitized_ip = self::sanitize_ips( $given_ip );
-
- // Abort on errors.
- $errors = array(
- 'referer' => array(
- 'sanitized' => $sanitized_referer,
- 'diff' => array_diff( $given_referer, $sanitized_referer ),
- 'invalid' => $invalid_referer,
- ),
- 'target' => array(
- 'sanitized' => $sanitized_target,
- 'diff' => array_diff( $given_target, $sanitized_target ),
- 'invalid' => $invalid_target,
- ),
- 'ip' => array(
- 'sanitized' => $sanitized_ip,
- 'diff' => array_diff( $given_ip, $sanitized_ip ),
- ),
- );
- if ( ! empty( $errors['referer']['diff'] )
- || ! empty( $errors['referer']['invalid'] )
- || ! empty( $errors['target']['diff'] )
- || ! empty( $errors['target']['invalid'] )
- || ! empty( $errors['ip']['diff'] ) ) {
- return $errors;
- }
-
- // Update database on success.
- if ( self::$multisite ) {
- update_site_option( 'statify-blacklist', $options );
- } else {
- update_option( 'statify-blacklist', $options );
- }
- }
-
- // Refresh options.
- parent::update_options( $options );
-
- return false;
- }
-
/**
* Add configuration page to admin menu.
*
@@ -139,50 +58,33 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
public static function add_menu_page() {
$title = __( 'Statify Filter', 'statify-blacklist' );
if ( self::$multisite ) {
- add_submenu_page(
- 'settings.php',
+ add_options_page(
$title,
$title,
'manage_network_plugins',
- 'statify-blacklist-settings',
- array(
- 'StatifyBlacklist_Admin',
- 'settings_page',
- )
+ 'statify-blacklist',
+ array( 'StatifyBlacklist_Settings', 'create_settings_page' )
);
} else {
- add_submenu_page(
- 'options-general.php',
+ add_options_page(
$title,
$title,
'manage_options',
'statify-blacklist',
- array(
- 'StatifyBlacklist_Admin',
- 'settings_page',
- )
+ array( 'StatifyBlacklist_Settings', 'create_settings_page' )
);
}
}
- /**
- * Include the Statify-Blacklist settings page.
- *
- * @since 1.0.0
- */
- public static function settings_page() {
- include STATIFYBLACKLIST_DIR . '/views/settings-page.php';
- }
-
/**
* Add plugin meta links
*
- * @since 1.0.0
- *
* @param array $links Registered links.
* @param string $file The filename.
*
* @return array Merged links.
+ *
+ * @since 1.0.0
*/
public static function plugin_meta_link( $links, $file ) {
if ( STATIFYBLACKLIST_BASE === $file ) {
@@ -195,12 +97,12 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Add plugin action links.
*
- * @since 1.0.0
- *
* @param array $links Registered links.
* @param string $file The filename.
*
* @return array Merged links.
+ *
+ * @since 1.0.0
*/
public static function plugin_actions_links( $links, $file ) {
$base = self::$multisite ? network_admin_url( 'settings.php' ) : admin_url( 'options-general.php' );
@@ -298,11 +200,11 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Sanitize URLs and remove empty results.
*
- * @since 1.1.1
- *
* @param array $urls given array of URLs.
*
* @return array sanitized array.
+ *
+ * @since 1.1.1
*/
private static function sanitize_urls( $urls ) {
return array_flip(
@@ -316,56 +218,4 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
)
);
}
-
- /**
- * Sanitize IP addresses with optional CIDR notation and remove empty results.
- *
- * @since 1.4.0
- *
- * @param array $ips given array of URLs.
- *
- * @return array sanitized array.
- */
- private static function sanitize_ips( $ips ) {
- return array_filter(
- array_map( 'strtolower', $ips ),
- function ( $ip ) {
- return preg_match(
- '/^((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])(\/([0-9]|[1-2][0-9]|3[0-2]))?$/',
- $ip
- ) ||
- preg_match(
- '/^(([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,7}:|([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}' .
- '|([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}' .
- '|([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}' .
- '|[0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|:((:[0-9a-f]{1,4}){1,7}|:)' .
- '|fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]' .
- '|1?[0-9])?[0-9])|([0-9a-f]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))' .
- '(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/i',
- $ip
- );
- }
- );
- }
-
- /**
- * Validate regular expressions, i.e. remove duplicates and empty values and validate others.
- *
- * @since 1.5.0 #13
- *
- * @param array $expressions Given pre-sanitized array of regular expressions.
- *
- * @return array Array of invalid expressions.
- */
- private static function sanitize_regex( $expressions ) {
- return array_filter(
- array_flip( $expressions ),
- function ( $re ) {
- // Check of preg_match() fails (warnings suppressed).
-
- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
- return false === @preg_match( StatifyBlacklist::regex( $re, false ), null );
- }
- );
- }
}
diff --git a/inc/class-statifyblacklist-settings.php b/inc/class-statifyblacklist-settings.php
new file mode 100644
index 0000000..2d5ff26
--- /dev/null
+++ b/inc/class-statifyblacklist-settings.php
@@ -0,0 +1,727 @@
+
+ array( __CLASS__, 'sanitize_options' ),
+ )
+ );
+
+ // Referer filter.
+ add_settings_section(
+ 'statifyblacklist-referer',
+ __( 'Referer filter', 'statify-blacklist' ),
+ null,
+ 'statify-blacklist'
+ );
+ add_settings_field(
+ 'statifyblacklist-referer-active',
+ __( 'Activate live filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_referer_active' ),
+ 'statify-blacklist',
+ 'statifyblacklist-referer'
+ );
+ add_settings_field(
+ 'statifyblacklist-referer-cron',
+ __( 'CronJob execution', 'statify-blacklist' ),
+ array( __CLASS__, 'option_referer_cron' ),
+ 'statify-blacklist',
+ 'statifyblacklist-referer'
+ );
+ add_settings_field(
+ 'statifyblacklist-referer-regexp',
+ __( 'Matching method', 'statify-blacklist' ),
+ array( __CLASS__, 'option_referer_regexp' ),
+ 'statify-blacklist',
+ 'statifyblacklist-referer',
+ array( 'label_for' => 'statifyblacklist-referer-regexp' )
+ );
+ add_settings_field(
+ 'statifyblacklist-referer-blacklist',
+ __( 'Referer filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_referer_blacklist' ),
+ 'statify-blacklist',
+ 'statifyblacklist-referer',
+ array( 'label_for' => 'statifyblacklist-referer-blacklist' )
+ );
+
+ // Target filter.
+ add_settings_section(
+ 'statifyblacklist-target',
+ __( 'Target filter', 'statify-blacklist' ),
+ null,
+ 'statify-blacklist'
+ );
+ add_settings_field(
+ 'statifyblacklist-target-active',
+ __( 'Activate live filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_target_active' ),
+ 'statify-blacklist',
+ 'statifyblacklist-target'
+ );
+ add_settings_field(
+ 'statifyblacklist-target-cron',
+ __( 'CronJob execution', 'statify-blacklist' ),
+ array( __CLASS__, 'option_target_cron' ),
+ 'statify-blacklist',
+ 'statifyblacklist-target'
+ );
+ add_settings_field(
+ 'statifyblacklist-target-regexp',
+ __( 'Matching method', 'statify-blacklist' ),
+ array( __CLASS__, 'option_target_regexp' ),
+ 'statify-blacklist',
+ 'statifyblacklist-target',
+ array( 'label_for' => 'statifyblacklist-target-regexp' )
+ );
+ add_settings_field(
+ 'statifyblacklist-target-blacklist',
+ __( 'Target filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_target_blacklist' ),
+ 'statify-blacklist',
+ 'statifyblacklist-target',
+ array( 'label_for' => 'statifyblacklist-target-blacklist' )
+ );
+
+ // IP filter.
+ add_settings_section(
+ 'statifyblacklist-ip',
+ __( 'IP filter', 'statify-blacklist' ),
+ null,
+ 'statify-blacklist'
+ );
+ add_settings_field(
+ 'statifyblacklist-ip-active',
+ __( 'Activate live filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_ip_active' ),
+ 'statify-blacklist',
+ 'statifyblacklist-ip'
+ );
+ add_settings_field(
+ 'statifyblacklist-ip-blacklist',
+ __( 'IP filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_ip_blacklist' ),
+ 'statify-blacklist',
+ 'statifyblacklist-ip',
+ array( 'label_for' => 'statifyblacklist-ip-blacklist' )
+ );
+
+ // User agent filter.
+ add_settings_section(
+ 'statifyblacklist-ua',
+ __( 'User agent filter', 'statify-blacklist' ),
+ null,
+ 'statify-blacklist'
+ );
+ add_settings_field(
+ 'statifyblacklist-ua-active',
+ __( 'Activate live filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_ua_active' ),
+ 'statify-blacklist',
+ 'statifyblacklist-ua'
+ );
+ add_settings_field(
+ 'statifyblacklist-ua-regexp',
+ __( 'Matching method', 'statify-blacklist' ),
+ array( __CLASS__, 'option_ua_regexp' ),
+ 'statify-blacklist',
+ 'statifyblacklist-ua',
+ array( 'label_for' => 'statifyblacklist-ua-regexp' )
+ );
+ add_settings_field(
+ 'statifyblacklist-ua-blacklist',
+ __( 'User agent filter', 'statify-blacklist' ),
+ array( __CLASS__, 'option_ua_blacklist' ),
+ 'statify-blacklist',
+ 'statifyblacklist-ua',
+ array( 'label_for' => 'statifyblacklist-ua-blacklist' )
+ );
+ }
+
+ /**
+ * Creates the settings pages.
+ *
+ * @return void
+ */
+ public static function create_settings_page() {
+ ?>
+
+
+
+
+
+
+
+
+
+ -
+
+ -
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ -
+
+
+
+
+ /, /test/page/, /?page_id=123
+
+
+
+
+
+
+
+ 127.0.0.1, 192.168.123.0/24, 2001:db8:a0b:12f0::1/64
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ -
+
+ -
+
+
+
+
+
+ MyBot/1.23
+
+ array(
+ 'active' => isset( $options['referer']['active'] ) ? (int) $options['referer']['active'] : 0,
+ 'cron' => isset( $options['referer']['cron'] ) ? (int) $options['referer']['cron'] : 0,
+ 'regexp' => isset( $options['referer']['regexp'] ) ? (int) $options['referer']['regexp'] : 0,
+ 'blacklist' => array_flip( $referer ),
+ ),
+ 'target' => array(
+ 'active' => isset( $options['target']['active'] ) ? (int) $options['target']['active'] : 0,
+ 'cron' => isset( $options['target']['cron'] ) ? (int) $options['target']['cron'] : 0,
+ 'regexp' => isset( $options['target']['regexp'] ) ? (int) $options['target']['regexp'] : 0,
+ 'blacklist' => array_flip( $target ),
+ ),
+ 'ip' => array(
+ 'active' => isset( $options['ip']['active'] ) ? (int) $options['ip']['active'] : 0,
+ 'blacklist' => $ip,
+ ),
+ 'ua' => array(
+ 'active' => isset( $options['ua']['active'] ) ? (int) $options['ua']['active'] : 0,
+ 'regexp' => isset( $options['ua']['regexp'] ) ? (int) $options['ua']['regexp'] : 0,
+ 'blacklist' => array_flip( $ua ),
+ ),
+ 'version' => StatifyBlacklist::VERSION_MAIN,
+ );
+
+ // Apply sanitizations.
+ self::sanitize_referer_options( $res['referer'] );
+ self::sanitize_target_options( $res['target'] );
+ self::sanitize_ip_options( $res['ip'] );
+
+ return $res;
+ }
+
+ /**
+ * Sanitize referer options.
+ *
+ * @param array $options Original referer options.
+ *
+ * @return void
+ *
+ * @since 1.7.0
+ */
+ private static function sanitize_referer_options( &$options ) {
+ $referer_given = $options['blacklist'];
+ $referer_invalid = array();
+ if ( StatifyBlacklist::MODE_NORMAL === $options['regexp'] ) {
+ // Sanitize URLs and remove empty inputs.
+ $referer_sanitized = self::sanitize_urls( $referer_given );
+ } elseif ( StatifyBlacklist::MODE_REGEX === $options['regexp'] || StatifyBlacklist::MODE_REGEX_CI === $options['regexp'] ) {
+ $referer_sanitized = $referer_given;
+ // Check regular expressions.
+ $referer_invalid = self::sanitize_regex( $referer_given );
+ } else {
+ $referer_sanitized = $referer_given;
+ }
+ $referer_diff = array_diff_key( $referer_given, $referer_sanitized );
+ $options['blacklist'] = $referer_sanitized;
+
+ // Generate messages.
+ if ( ! empty( $referer_diff ) ) {
+ add_settings_error(
+ 'statify-blacklist',
+ 'referer-diff',
+ __( 'Some URLs are invalid and have been sanitized.', 'statify-blacklist' ),
+ 'warning'
+ );
+ }
+ if ( ! empty( $referer_invalid ) ) {
+ add_settings_error(
+ 'statify-blacklist',
+ 'referer-invalid',
+ __( 'Some regular expressions for referrers are invalid:', 'statify-blacklist' ) . '
' . implode( '
', $referer_invalid )
+ );
+ }
+ }
+
+ /**
+ * Sanitize target options.
+ *
+ * @param array $options Original target options.
+ *
+ * @return void
+ *
+ * @since 1.7.0
+ */
+ private static function sanitize_target_options( &$options ) {
+ $target_given = $options['blacklist'];
+ $target_invalid = array();
+ if ( StatifyBlacklist::MODE_REGEX === $options['regexp'] || StatifyBlacklist::MODE_REGEX_CI === $options['regexp'] ) {
+ $target_sanitized = $target_given;
+ // Check regular expressions.
+ $target_invalid = self::sanitize_regex( $target_given );
+ } else {
+ $target_sanitized = $target_given;
+ }
+ $options['blacklist'] = $target_sanitized;
+
+ // Generate messages.
+ if ( ! empty( $target_invalid ) ) {
+ add_settings_error(
+ 'statify-blacklist',
+ 'target-invalid',
+ __( 'Some regular expressions for targets are invalid:', 'statify-blacklist' ) . '
' . implode( '
', $target_invalid )
+ );
+ }
+ }
+
+ /**
+ * Sanitize IPs and subnets and remove empty inputs.
+ *
+ * @param array $options Original IP options.
+ *
+ * @return void
+ *
+ * @since 1.7.0
+ */
+ private static function sanitize_ip_options( &$options ) {
+ $given_ip = $options['blacklist'];
+ $sanitized_ip = self::sanitize_ips( $given_ip );
+ $ip_diff = array_diff( $given_ip, $sanitized_ip );
+ $options['blacklist'] = $sanitized_ip;
+
+ // Generate messages.
+ if ( ! empty( $ip_diff ) ) {
+ add_settings_error(
+ 'statify-blacklist',
+ 'ip-diff',
+ // translators: List of invalid IP addresses (comma separated).
+ sprintf( __( 'Some IPs are invalid: %s', 'statify-blacklist' ), implode( ', ', $ip_diff ) ),
+ 'warning'
+ );
+ }
+ }
+
+ /**
+ * Sanitize URLs and remove empty results.
+ *
+ * @param array $urls given array of URLs.
+ *
+ * @return array sanitized array.
+ *
+ * @since 1.1.1
+ * @since 1.7.0 moved from StatifyBlacklist_Admin to StatifyBlacklist_Settings.
+ */
+ private static function sanitize_urls( $urls ) {
+ return array_flip(
+ array_filter(
+ array_map(
+ function ( $r ) {
+ return preg_replace( '/[^\da-z\.-]/i', '', filter_var( $r, FILTER_SANITIZE_URL ) );
+ },
+ array_flip( $urls )
+ )
+ )
+ );
+ }
+
+ /**
+ * Sanitize IP addresses with optional CIDR notation and remove empty results.
+ *
+ * @param array $ips given array of URLs.
+ *
+ * @return array sanitized array.
+ *
+ * @since 1.4.0
+ * @since 1.7.0 moved from StatifyBlacklist_Admin to StatifyBlacklist_Settings.
+ */
+ private static function sanitize_ips( $ips ) {
+ return array_filter(
+ array_map( 'strtolower', $ips ),
+ function ( $ip ) {
+ return preg_match(
+ '/^((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])(\/([0-9]|[1-2][0-9]|3[0-2]))?$/',
+ $ip
+ ) ||
+ preg_match(
+ '/^(([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,7}:|([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}' .
+ '|([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}' .
+ '|([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}' .
+ '|[0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|:((:[0-9a-f]{1,4}){1,7}|:)' .
+ '|fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]' .
+ '|1?[0-9])?[0-9])|([0-9a-f]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))' .
+ '(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/',
+ $ip
+ );
+ }
+ );
+ }
+
+ /**
+ * Validate regular expressions, i.e. remove duplicates and empty values and validate others.
+ *
+ * @param array $expressions Given pre-sanitized array of regular expressions.
+ *
+ * @return array Array of invalid expressions.
+ *
+ * @since 1.5.0 #13
+ * @since 1.7.0 moved from StatifyBlacklist_Admin to StatifyBlacklist_Settings.
+ */
+ private static function sanitize_regex( $expressions ) {
+ return array_filter(
+ array_flip( $expressions ),
+ function ( $re ) {
+ // Check of preg_match() fails (warnings suppressed).
+
+ // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
+ return false === @preg_match( StatifyBlacklist::regex( $re, false ), null );
+ }
+ );
+ }
+
+ /**
+ * Parse multi-line option string.
+ *
+ * @param string $raw Input string.
+ *
+ * @return array Parsed options.
+ */
+ private static function parse_multiline_option( $raw ) {
+ if ( empty( trim( $raw ) ) ) {
+ return array();
+ } else {
+ return array_filter(
+ array_map(
+ function ( $a ) {
+ return trim( $a );
+ },
+ explode( "\r\n", str_replace( '\\\\', '\\', $raw ) )
+ ),
+ function ( $a ) {
+ return ! empty( $a );
+ }
+ );
+ }
+ }
+}
diff --git a/phpcs.xml b/phpcs.xml
index a4ff01e..1e0c607 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -8,7 +8,6 @@
statify-blacklist.php
inc
- views
diff --git a/statify-blacklist.php b/statify-blacklist.php
index 240d86b..1f25d37 100644
--- a/statify-blacklist.php
+++ b/statify-blacklist.php
@@ -70,6 +70,7 @@ function statify_blacklist_autoload( $class ) {
$plugin_classes = array(
'StatifyBlacklist',
'StatifyBlacklist_Admin',
+ 'StatifyBlacklist_Settings',
'StatifyBlacklist_System',
);
diff --git a/test/StatifyBlacklist_Admin_Test.php b/test/StatifyBlacklist_Admin_Test.php
deleted file mode 100644
index 3ad9f20..0000000
--- a/test/StatifyBlacklist_Admin_Test.php
+++ /dev/null
@@ -1,67 +0,0 @@
-assertNotFalse( $result );
-
- /*
- * Unfortunately this is necessary as long as we run PHP 5 tests, because "assertInternalType" is deprecated
- * as of PHPUnit 8, but "assertIsArray" has been introduces in PHPUnit 7.5 which requires PHP >= 7.1.
- */
- if ( method_exists( $this, 'assertIsArray' ) ) {
- $this->assertIsArray( $result );
- } else {
- $this->assertInternalType( 'array', $result );
- }
- $this->assertEquals( $valid, $result );
-
- // IPv6 tests.
- $valid = array(
- '2001:db8:a0b:12f0::',
- '2001:db8:a0b:12f0::1',
- '2001:db8:a0b:12f0::1/128',
- '2001:DB8:A0B:12F0::/64',
- 'fe80::7645:6de2:ff:1',
- '::ffff:192.0.2.123',
- );
- $invalid = array(
- '2001:db8:a0b:12f0::x',
- '2001:db8:a0b:12f0:::',
- '2001:fffff:a0b:12f0::1',
- '2001:DB8:A0B:12F0::/129',
- '1:2:3:4:5:6:7:8:9',
- '::ffff:12.34.56.789',
- );
- $result = invoke_static( StatifyBlacklist_Admin::class, 'sanitize_ips', array( array_merge( $valid, $invalid ) ) );
- $this->assertNotFalse( $result );
- if ( method_exists( $this, 'assertIsArray' ) ) {
- $this->assertIsArray( $result );
- } else {
- $this->assertInternalType( 'array', $result );
- }
- $this->assertEquals( array_map( 'strtolower', $valid ), $result );
- }
-}
diff --git a/test/StatifyBlacklist_Settings_Test.php b/test/StatifyBlacklist_Settings_Test.php
new file mode 100644
index 0000000..16e7620
--- /dev/null
+++ b/test/StatifyBlacklist_Settings_Test.php
@@ -0,0 +1,329 @@
+ array(
+ 'blacklist' => '',
+ 'regexp' => '0',
+ ),
+ 'target' => array(
+ 'blacklist' => '',
+ 'regexp' => '0',
+ ),
+ 'ip' => array( 'blacklist' => '' ),
+ 'ua' => array(
+ 'blacklist' => '',
+ 'regexp' => '0',
+ ),
+ );
+
+ $sanitized = StatifyBlacklist_Settings::sanitize_options( $raw );
+
+ self::assertEmpty( $settings_error );
+ self::assertEquals(
+ array(
+ 'referer' => array(
+ 'active' => 0,
+ 'cron' => 0,
+ 'blacklist' => array(),
+ 'regexp' => StatifyBlacklist::MODE_NORMAL,
+ ),
+ 'target' => array(
+ 'active' => 0,
+ 'cron' => 0,
+ 'blacklist' => array(),
+ 'regexp' => StatifyBlacklist::MODE_NORMAL,
+ ),
+ 'ip' => array(
+ 'active' => 0,
+ 'blacklist' => array(),
+ ),
+ 'ua' => array(
+ 'active' => 0,
+ 'regexp' => StatifyBlacklist::MODE_NORMAL,
+ 'blacklist' => array(),
+ ),
+ 'version' => StatifyBlacklist::VERSION_MAIN,
+ ),
+ $sanitized
+ );
+
+ // Some checked options and some valid entries.
+ $raw = array(
+ 'referer' => array(
+ 'cron' => '1',
+ 'blacklist' => "example.com\r\nexample.net\r\nexample.org",
+ 'regexp' => '0',
+ ),
+ 'target' => array(
+ 'active' => '1',
+ 'blacklist' => "foo\r\nbar\r\ntest",
+ 'regexp' => '3',
+ ),
+ 'ip' => array(
+ 'active' => '1',
+ 'blacklist' => "127.0.0.1/8\r\n::1",
+ ),
+ 'ua' => array(
+ 'blacklist' => 'MyBot/1.23',
+ 'regexp' => '1',
+ ),
+ );
+
+ $sanitized = StatifyBlacklist_Settings::sanitize_options( $raw );
+
+ self::assertEmpty( $settings_error );
+ self::assertEquals(
+ array(
+ 'referer' => array(
+ 'active' => 0,
+ 'cron' => 1,
+ 'blacklist' => array(
+ 'example.com' => 0,
+ 'example.net' => 1,
+ 'example.org' => 2,
+ ),
+ 'regexp' => StatifyBlacklist::MODE_NORMAL,
+ ),
+ 'target' => array(
+ 'active' => 1,
+ 'cron' => 0,
+ 'blacklist' => array(
+ 'foo' => 0,
+ 'bar' => 1,
+ 'test' => 2,
+ ),
+ 'regexp' => StatifyBlacklist::MODE_KEYWORD,
+ ),
+ 'ip' => array(
+ 'active' => 1,
+ 'blacklist' => array(
+ '127.0.0.1/8',
+ '::1',
+ ),
+ ),
+ 'ua' => array(
+ 'active' => 0,
+ 'regexp' => StatifyBlacklist::MODE_REGEX,
+ 'blacklist' => array(
+ 'MyBot/1.23' => 0,
+ ),
+ ),
+ 'version' => StatifyBlacklist::VERSION_MAIN,
+ ),
+ $sanitized
+ );
+
+ // Now we have some additional nonsense fields and invalid entries.
+ $raw = array(
+ 'testme ' => 'whatever',
+ 'referer' => array(
+ 'cron' => '1',
+ 'blacklist' => " example\\.com \r\nexample(\\.net\r\nexample\\.com",
+ 'regexp' => '1',
+ ),
+ 'target' => array(
+ 'active' => '1',
+ 'blacklist' => "fo.\r\n[bar\r\n*test",
+ 'regexp' => '2',
+ ),
+ 'ip' => array(
+ 'active' => '1',
+ 'blacklist' => "127.0.0.1/8\r\nthisisnotanip",
+ ),
+ 'ua' => array(
+ 'blacklist' => 'MyBot/1.23',
+ 'regexp' => '1',
+ ),
+ );
+
+ $sanitized = StatifyBlacklist_Settings::sanitize_options( $raw );
+
+ self::assertEquals(
+ array(
+ 'referer' => array(
+ 'active' => 0,
+ 'cron' => 1,
+ 'blacklist' => array(
+ 'example\.com' => 2,
+ 'example(\.net' => 1,
+ ),
+ 'regexp' => StatifyBlacklist::MODE_REGEX,
+ ),
+ 'target' => array(
+ 'active' => 1,
+ 'cron' => 0,
+ 'blacklist' => array(
+ 'fo.' => 0,
+ '[bar' => 1,
+ '*test' => 2,
+ ),
+ 'regexp' => StatifyBlacklist::MODE_REGEX_CI,
+ ),
+ 'ip' => array(
+ 'active' => 1,
+ 'blacklist' => array(
+ '127.0.0.1/8',
+ ),
+ ),
+ 'ua' => array(
+ 'active' => 0,
+ 'regexp' => StatifyBlacklist::MODE_REGEX,
+ 'blacklist' => array(
+ 'MyBot/1.23' => 0,
+ ),
+ ),
+ 'version' => StatifyBlacklist::VERSION_MAIN,
+ ),
+ $sanitized
+ );
+
+ self::assertEquals(
+ array(
+ array( 'statify-blacklist', 'referer-invalid', 'Some regular expressions for referrers are invalid:
example(\.net', 'error' ),
+ array( 'statify-blacklist', 'target-invalid', 'Some regular expressions for targets are invalid:
[bar
*test', 'error' ),
+ array( 'statify-blacklist', 'ip-diff', 'Some IPs are invalid: thisisnotanip', 'warning' ),
+ ),
+ $settings_error
+ );
+ }
+
+ /**
+ * Test sanitization of IP addresses.
+ *
+ * @return void
+ */
+ public function test_sanitize_ips() {
+ // IPv4 tests.
+ $valid = array( '192.0.2.123', '192.0.2.123/32', '192.0.2.0/24', '192.0.2.128/25' );
+ $invalid = array( '12.34.56.789', '192.0.2.123/33', '192.0.2.123/-1' );
+ $result = invoke_static( StatifyBlacklist_Settings::class, 'sanitize_ips', array( array_merge( $valid, $invalid ) ) );
+ $this->assertNotFalse( $result );
+
+ /*
+ * Unfortunately this is necessary as long as we run PHP 5 tests, because "assertInternalType" is deprecated
+ * as of PHPUnit 8, but "assertIsArray" has been introduces in PHPUnit 7.5 which requires PHP >= 7.1.
+ */
+ if ( method_exists( $this, 'assertIsArray' ) ) {
+ $this->assertIsArray( $result );
+ } else {
+ $this->assertInternalType( 'array', $result );
+ }
+ $this->assertEquals( $valid, $result );
+
+ // IPv6 tests.
+ $valid = array(
+ '2001:db8:a0b:12f0::',
+ '2001:db8:a0b:12f0::1',
+ '2001:db8:a0b:12f0::1/128',
+ '2001:DB8:A0B:12F0::/64',
+ 'fe80::7645:6de2:ff:1',
+ '::ffff:192.0.2.123',
+ );
+ $invalid = array(
+ '2001:db8:a0b:12f0::x',
+ '2001:db8:a0b:12f0:::',
+ '2001:fffff:a0b:12f0::1',
+ '2001:DB8:A0B:12F0::/129',
+ '1:2:3:4:5:6:7:8:9',
+ '::ffff:12.34.56.789',
+ );
+ $result = invoke_static( StatifyBlacklist_Settings::class, 'sanitize_ips', array( array_merge( $valid, $invalid ) ) );
+ $this->assertNotFalse( $result );
+ if ( method_exists( $this, 'assertIsArray' ) ) {
+ $this->assertIsArray( $result );
+ } else {
+ $this->assertInternalType( 'array', $result );
+ }
+ $this->assertEquals(
+ array(
+ '2001:db8:a0b:12f0::',
+ '2001:db8:a0b:12f0::1',
+ '2001:db8:a0b:12f0::1/128',
+ '2001:db8:a0b:12f0::/64',
+ 'fe80::7645:6de2:ff:1',
+ '::ffff:192.0.2.123',
+ ),
+ array_values( $result )
+ );
+ }
+
+ /**
+ * Test settings registration.
+ *
+ * @return void
+ */
+ public function test_register_settings() {
+ global $settings;
+ $settings = array();
+
+ StatifyBlacklist_Settings::register_settings();
+ $this->assertEquals( array( 'statify-blacklist' ), array_keys( $settings ), 'unexpected settings pages' );
+ $this->assertEquals(
+ array(
+ 'statifyblacklist-referer',
+ 'statifyblacklist-target',
+ 'statifyblacklist-ip',
+ 'statifyblacklist-ua',
+ ),
+ array_keys( $settings['statify-blacklist']['sections'] ),
+ 'unexpected settings sections'
+ );
+ $this->assertEquals(
+ array(
+ 'statifyblacklist-referer-active',
+ 'statifyblacklist-referer-cron',
+ 'statifyblacklist-referer-regexp',
+ 'statifyblacklist-referer-blacklist',
+ ),
+ array_keys( $settings['statify-blacklist']['sections']['statifyblacklist-referer']['fields'] ),
+ 'unexpected fields in referrer section'
+ );
+ $this->assertEquals(
+ array(
+ 'statifyblacklist-target-active',
+ 'statifyblacklist-target-cron',
+ 'statifyblacklist-target-regexp',
+ 'statifyblacklist-target-blacklist',
+ ),
+ array_keys( $settings['statify-blacklist']['sections']['statifyblacklist-target']['fields'] ),
+ 'unexpected fields in target section'
+ );
+ $this->assertEquals(
+ array( 'statifyblacklist-ip-active', 'statifyblacklist-ip-blacklist' ),
+ array_keys( $settings['statify-blacklist']['sections']['statifyblacklist-ip']['fields'] ),
+ 'unexpected fields in ip section'
+ );
+ $this->assertEquals(
+ array(
+ 'statifyblacklist-ua-active',
+ 'statifyblacklist-ua-regexp',
+ 'statifyblacklist-ua-blacklist',
+ ),
+ array_keys( $settings['statify-blacklist']['sections']['statifyblacklist-ua']['fields'] ),
+ 'unexpected fields in user agent section'
+ );
+ }
+}
diff --git a/test/bootstrap.php b/test/bootstrap.php
index 6a3796e..97228e7 100644
--- a/test/bootstrap.php
+++ b/test/bootstrap.php
@@ -17,6 +17,7 @@ const ABSPATH = false;
*/
require_once __DIR__ . '/../inc/class-statifyblacklist.php';
require_once __DIR__ . '/../inc/class-statifyblacklist-admin.php';
+require_once __DIR__ . '/../inc/class-statifyblacklist-settings.php';
require_once __DIR__ . '/../inc/class-statifyblacklist-system.php';
// Include Composer autoloader.
@@ -36,6 +37,8 @@ function invoke_static( $class, $method_name, $parameters = array() ) {
// Some mocked WP functions.
$mock_options = array();
$mock_multisite = false;
+$settings_error = array();
+$settings = array();
/** @ignore */
function is_multisite() {
@@ -87,3 +90,45 @@ function wp_parse_url( $value ) {
function wp_unslash( $value ) {
return is_string( $value ) ? stripslashes( $value ) : $value;
}
+
+/** @ignore */
+function __( $text, $domain = 'default' ) {
+ return $text;
+}
+
+/** @ignore */
+function add_settings_error( $setting, $code, $message, $type = 'error' ) {
+ global $settings_error;
+ $settings_error[] = array( $setting, $code, $message, $type );
+}
+
+/** @ignore */
+function register_setting( $option_group, $option_name, $args = array() ) {
+ global $settings;
+ $settings[ $option_name ] = array(
+ 'group' => $option_group,
+ 'args' => $args,
+ 'sections' => array(),
+ );
+}
+
+/** @ignore */
+function add_settings_section( $id, $title, $callback, $page, $args = array() ) {
+ global $settings;
+ $settings[ $page ]['sections'][ $id ] = array(
+ 'title' => $title,
+ 'callback' => $callback,
+ 'args' => $args,
+ 'fields' => array(),
+ );
+}
+
+/** @ignore */
+function add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() ) {
+ global $settings;
+ $settings[ $page ]['sections'][ $section ]['fields'][ $id ] = array(
+ 'title' => $title,
+ 'callback' => $callback,
+ 'args' => $args,
+ );
+}
diff --git a/views/settings-page.php b/views/settings-page.php
deleted file mode 100755
index 3c082cd..0000000
--- a/views/settings-page.php
+++ /dev/null
@@ -1,488 +0,0 @@
- array(
- 'active' => isset( $_POST['statifyblacklist']['referer']['active'] )
- ? (int) $_POST['statifyblacklist']['referer']['active'] : 0,
- 'cron' => isset( $_POST['statifyblacklist']['referer']['cron'] )
- ? (int) $_POST['statifyblacklist']['referer']['cron'] : 0,
- 'regexp' => isset( $_POST['statifyblacklist']['referer']['regexp'] )
- ? (int) $_POST['statifyblacklist']['referer']['regexp'] : 0,
- 'blacklist' => array_flip( $referer ),
- ),
- 'target' => array(
- 'active' => isset( $_POST['statifyblacklist']['target']['active'] )
- ? (int) $_POST['statifyblacklist']['target']['active'] : 0,
- 'cron' => isset( $_POST['statifyblacklist']['target']['cron'] )
- ? (int) $_POST['statifyblacklist']['target']['cron'] : 0,
- 'regexp' => isset( $_POST['statifyblacklist']['target']['regexp'] )
- ? (int) $_POST['statifyblacklist']['target']['regexp'] : 0,
- 'blacklist' => array_flip( $target ),
- ),
- 'ip' => array(
- 'active' => isset( $_POST['statifyblacklist']['ip']['active'] )
- ? (int) $_POST['statifyblacklist']['ip']['active'] : 0,
- 'blacklist' => $ip,
- ),
- 'ua' => array(
- 'active' => isset( $_POST['statifyblacklist']['ua']['active'] )
- ? (int) $_POST['statifyblacklist']['ua']['active'] : 0,
- 'regexp' => isset( $_POST['statifyblacklist']['ua']['regexp'] )
- ? (int) $_POST['statifyblacklist']['ua']['regexp'] : 0,
- 'blacklist' => array_flip( $ua ),
- ),
- 'version' => StatifyBlacklist::VERSION_MAIN,
- )
- );
-
- // Generate messages.
- if ( false !== $statifyblacklist_update_result ) {
- $statifyblacklist_post_warning = array();
- if ( ! empty( $statifyblacklist_update_result['referer']['diff'] ) ) {
- $statifyblacklist_post_warning[] = __( 'Some URLs are invalid and have been sanitized.', 'statify-blacklist' );
- }
- if ( ! empty( $statifyblacklist_update_result['referer']['invalid'] ) ) {
- $statifyblacklist_post_warning[] = __( 'Some regular expressions are invalid:', 'statify-blacklist' ) . '
' . implode( '
', $statifyblacklist_update_result['referer']['invalid'] );
- }
- if ( ! empty( $statifyblacklist_update_result['ip']['diff'] ) ) {
- // translators: List of invalid IP addresses (comma separated).
- $statifyblacklist_post_warning[] = sprintf( __( 'Some IPs are invalid: %s', 'statify-blacklist' ), implode( ', ', $statifyblacklist_update_result['ip']['diff'] ) );
- }
- } else {
- $statifyblacklist_post_success = __( 'Settings updated successfully.', 'statify-blacklist' );
- }
- }
-}
-
-/*
- * Disable some code style rules that are impractical for textarea content:
- *
- * phpcs:disable Squiz.PHP.EmbeddedPhp.ContentBeforeOpen
- * phpcs:disable Squiz.PHP.EmbeddedPhp.ContentAfterEnd
- */
-?>
-
-
-
-
';
- esc_html_e( 'Statify plugin is not active.', 'statify-blacklist' );
- print '
';
- }
- if ( isset( $statifyblacklist_post_warning ) ) {
- foreach ( $statifyblacklist_post_warning as $w ) {
- print '' .
- wp_kses( $w, array( 'br' => array() ) ) .
- '
';
- }
- print '' . esc_html__( 'Settings have not been saved yet.', 'statify-blacklist' ) . '
';
- }
- if ( isset( $statifyblacklist_post_success ) ) {
- print '' .
- esc_html( $statifyblacklist_post_success ) .
- '
';
- }
- ?>
-
-