25 Commits

Author SHA1 Message Date
075441d6f3 Bump version to 1.4.4 2018-05-19 14:36:23 +02:00
92f8496926 Fix #12: do not skip filter chain on non-matching regex filter
Corrected the regular expression methods and unit-tested combined filters.
2018-05-19 14:22:15 +02:00
66ddada63e Updated deprecated SPDX license code and removed PHP from require-dev
[ci skip]
2018-03-08 19:45:51 +01:00
fcba292698 Fixed README deploy path in Robo script [ci skip] 2018-03-08 17:21:18 +01:00
1e811957f8 Minor correction in required Statify version
'Tested up to' no longer holds with 1.6.0 now released, so now the
minimum version required is named instead of updating the maximum.
2018-03-08 17:15:50 +01:00
b9017a7b8d Update License file
Hopefully GitHub now recognizes the GPL license again...
2018-02-04 12:00:29 +01:00
7329574d09 Contributing ++ 2018-01-20 12:38:20 +01:00
b8b1dc83de Prepare release 1.4.3 2018-01-09 20:16:17 +01:00
5956059327 Cleaned up option handling for multisite
Multisite detection has been executed multiple times while the status is present in class variable after initialization.
2018-01-07 16:17:27 +01:00
c2ad908481 Fixed menu page for multisite activation 2018-01-07 16:16:01 +01:00
9e3dc8fb86 Parameter sanitization on config update reworked
Verify that checkbox value is actually present in POST value and fallback to 0.
2018-01-07 16:15:46 +01:00
8b9ce4c570 Fixed issues with multisite installation (#11) 2018-01-07 14:14:48 +01:00
8a35182d81 Added SVN deployment tasks 2017-12-29 14:07:43 +01:00
0b7c9c07e2 Added Robo build script
Created tasks for building and testing using Robo build environment, installed via Composer. This is supposed to replace Gulp as default build tool and makes NPM obsolete.
2017-12-29 11:43:30 +01:00
d82de3547b Update Composer and Travis config
PHPUnit and PHPCS test execution is now available using Composer.
2017-12-03 12:49:41 +01:00
012b9a0189 Release 1.4.2 2017-11-12 12:12:52 +01:00
eb63299dfc Minor code styling.
* Added some equals-alignments and removed require_once paranthesis.
* Notice: _add_menu_page() has been renamed to add_menu_page()
2017-11-12 12:12:51 +01:00
637d5f482c Preparations for 1.4.2
Supported WP version is 4.9, updated WPCS definitions.
2017-11-12 12:12:51 +01:00
f061b4c194 _add_menu_page in admin class made static
This method has been non-static for not reason which lead to reasonable warning. Simply declared static now, as there are no instance dependencies.
2017-11-12 12:12:51 +01:00
7962d4dbc9 Add required PHP version to ReadMe
This field is now parsed and displayed on WP plugin page.
2017-09-06 21:12:51 +02:00
aa40945ebd Replaced superfluous instantiation of Object with static init() method 2017-08-20 11:22:39 +02:00
12a7959982 Add PHP 7.2 build to Travis config 2017-08-17 20:02:47 +02:00
58ac6e36f1 Bump required WordPress version to 4.4 (#10) 2017-08-17 19:58:12 +02:00
bc32bd66db Minor dist bundle adjustments
The Gulp task now creates a ZIP file with the plugin-dir as root, instead of directly adding the files.
2017-08-02 13:55:50 +02:00
2b6f892b18 Contribution guidelines 2017-07-16 18:09:38 +02:00
17 changed files with 794 additions and 77 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@ composer.lock
/node_modules/
/dist/
.idea
tests-clover.xml
tests-junit.xml

View File

@ -5,10 +5,8 @@ php:
- '5.6'
- '7.0'
- '7.1'
- '7.2'
before_script:
- composer install --no-interaction
- vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs
- composer install
script:
- vendor/bin/phpunit ./test/statifyblacklist-test.php
- vendor/bin/phpcs statify-blacklist.php --standard=phpcs.xml
- vendor/bin/phpcs ./inc/ --standard=phpcs.xml --extensions=php
- composer test-all

130
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,130 @@
# How to contribute
As for all great Open Source projects, contributions in form of bug reports and code are welcome and important to keep the project alive.
In general, this project follows the [GitHub Flow](https://guides.github.com/introduction/flow/).
Fork the project, commit your changes to your branch, open a pull request and it will probably be merged.
However, to ensure maintainability and quality of the code, there are some guidelines you might be more or less familiar with.
For that purpose, this document describes the important points.
## Opening an Issue
If you experience any issues with the plugin or the code, don't hesitate to file an issue.
### Bug Reports
Think you found a bug?
Please clearly state what happens and describe your environment to help tracking down the issue.
* Which version of the plugin are you running?
* Which version of WordPress?
* Which version(s) of related plugin(s) (e.g. Statify)?
* Which version of PHP and - if of interest - which webserver are you running?
### Feature Requests
Missing a feature or like to have certain functionality enhanced?
No problem, please open an issue and describe what and why you think this change is required.
## Pull Requests
If you want to contribute your code to solve an issue or implement a desired feature yourself, you might open a pull request.
If the changes introduce new functionality or affect major parts of existing code, please consider opening an issue for discussion first.
For adding new functionality a new test case the corresponding PHPUnit test would be nice (no hard criterion though).
### Branches
The `master` branch represents the current state of development.
Please ensure your initial code is up to date with it at the time you start development.
The `master` should also be target for most pull requests.
In addition, this project features a `develop` branch, which holds bleeding edge developments, not necessarily considered stable or even compatible.
Do not expect this code to run smoothly, but you might have a look into the history to see if some work on an issue has already been started there.
For fixes and features, there might be additional branches, likely prefixed by `ft-` (feature) or `hf-` (hotfix) followed by an issue number (if applicable) and/or a title.
Feel free to adapt these naming scheme to your forks.
### Merge Requirements
To be merged into the master branch, your code has to pass the automated continuous integration tests, to ensure compatibility.
In Addition your code has to be approved by a project member.
#### What if my code fails the tests?
Don't worry, you can submit your PR anyway.
The reviewing process might help you to solve remaining issues.
### Commit messages
Please use speaking titles and messages for your commits, to ensure a transparent history.
If your patch fixes an issue, reference the ID in the first line.
If you feel like you have to _briefly_ explain your changes, do it (for long explanations and discussion, consider opening an issue or describe in the PR).
**Example commit:**
```text
Fix nasty bug from #1337
This example commit fixes the issue that some people write non-speaking commit messages like 'done magic'.
A short description is helpful sometimes.
```
You might sign your work, although that's no must.
### When will it be merged?
Short answer: When it makes sense.
Bugfixes should be merged in time - assuming they pass the above criteria.
New features might be assigned to a certain milestone and as a result of this be scheduled according to the planned release cycle.
## Compatibility
To ensure usability for a wide range of users, please take note on the software requirements stated in the `README`.
This includes especially the minimum PHP version and also the minimum version of WordPress.
If you are unsure if your code matches these versions, the test will probably tell you.
In case you think, your change is more important than maintaining backwards compatibility, please start a discussion to see,
if we might increase the minimum version or find a workaround for legacy systems.
## Build Environment
All you need to start off - besides your favorite IDE of course - is [Composer](https://getcomposer.org).
Running `composer install` will fetch all dependencies and build tools required.
You might have noticed that this project contains a [Robo](http://robo.li) build script.
Running the _build_-task (`./vendor/bin/robo build`) executes the full chain from cleanup over test to bundling the final product in the `dist` directory.
A complete list of the available tasks and options can be shown by running `robo list`.
## Unit Tests
The PHP code is tested by a PHPUnit tests.
All test files are located in the `test` directory.
Files ending with `-test.php` will be automatically included into the test suite.
The coverage is not yet perfect, but be invited to write tests for methods not yet covered or newly introduced by your patch.
## Code Style
This project, as part of the WordPress ecosystem adheres to the [WordPress Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards).
Please make sure that you are at least roughly familiar with those guidelines.
The code style is automatically checked for commits (including pull requests) using [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer).
You can check your code against the configured ruleset yourself by running
`./vendor/bin/phpcs --standard=phpcs.xml your-edited-file.php` (assuming `composer install` has been executed) or the Robo task `robo test:cs` for a complete scan.
Please see these standards as guidelines.
If code style this is the only test that fails and your code's semantics are fine, don't hesitate to submit your pull request anyway.
We probably find a solution for that.
## Continuous Integration
Automated tests are run using [Travis CI](https://travis-ci.org/stklcode/statify-blacklist) for every commit including pull requests.
They ensure compatibility with the supported PHP versions and the WP Coding Standards.
There is also a semi-automated code quality analysis pushing results to [SonarCloud](https://sonarcloud.io/dashboard?id=de.stklcode.web.wordpress.plugins%3Astatify-blacklist).
Keep in mind that the ruleset is not yet perfect, so not every minor issue has to be fixed immediately.
## Still Open Questions?
If anything is still left unanswered and you're unsure if you got it right, don't hesitate to contact a team member.
in any case you might submit your request/issue anyway, we won't refuse good code only for formal reasons.

View File

@ -30,11 +30,15 @@ gulp.task('test', ['compose'], function () {
// Execute PHP Code Sniffer.
gulp.task('test-cs', function (cb) {
return exec('./vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs', function (err, stdout, stderr) {
return exec('./vendor/bin/phpcs --config-set installed_paths vendor/wimg/php-compatibility,vendor/wp-coding-standards/wpcs', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
if (null === err) {
console.log('Running PHP Code Sniffer tests ...');
// exec('./vendor/bin/phpcs --standard=phpcs.xml', function(err, stdout, stderr) {
// console.log(stdout);
// console.log(stderr);
// });
gulp.src(['statify-blacklist.php', 'inc/**/*.php'])
.pipe(phpcs({bin: './vendor/bin/phpcs', standard: 'phpcs.xml'}))
.pipe(phpcs.reporter('log'));
@ -46,8 +50,8 @@ gulp.task('test-cs', function (cb) {
// Bundle files as required for plugin distribution..
gulp.task('bundle', ['clean'], function () {
console.log('Collecting files for package dist/' + config.name + config.version + ' ...');
return gulp.src(['**/*.php', '!test/**', '!vendor/**', 'README.md', 'LICENSE.md'], {base: './'})
.pipe(copy('./dist/' + config.name + '.' + config.version));
return gulp.src(['**/*.php', '!RoboFile.php', '!test/**', '!vendor/**', 'README.md', 'LICENSE.md'], {base: './'})
.pipe(copy('./dist/' + config.name + '.' + config.version + '/' + config.name));
});
// Create a ZIP package of the relevant files for plugin distribution.

View File

@ -358,4 +358,4 @@ you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
[GNU Lesser General Public
License](http://www.gnu.org/licenses/lgpl.html) instead of this
License.
License.

View File

@ -1,8 +1,9 @@
# Statify Blacklist #
* Contributors: Stefan Kalscheuer
* Requires at least: 3.9
* Tested up to: 4.8
* Stable tag: 1.4.1
* Requires at least: 4.4
* Tested up to: 4.9
* Requires PHP: 5.5
* Stable tag: 1.4.4
* License: GPLv2 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -45,8 +46,8 @@ The plugin is capable of handling multisite installations.
### Requirements ###
* PHP 5.5 or above
* WordPress 3.9 or above
* Statify plugin installed and activated (tested up to 1.5.1)
* WordPress 4.4 or above
* Statify plugin installed and activated (1.5.0 or above)
## Frequently Asked Questions ##
@ -81,11 +82,21 @@ Because of this, an IP blacklist can only be applied while processing the reques
## Changelog ##
### 1.4.4 / 19.05.2018 ###
* Fix live filter chain when regular expressions are active (#12)
### 1.4.3 / 09.01.2018 ###
* Fix issues with multisite installation (#11)
### 1.4.2 / 12.11.2017 ###
* Minor code fixes
### 1.4.1 / 16.07.2017 ###
* Relicensed to GPLv2 or later
* Fix filter hook if referer is disabled (#9)
* Fix problem with faulty IPv6 netmask in IP blacklist
* Minor changes for WP Coding Standard
* Minimum required WordPress version is 4.4 (#10)
### 1.4.0 / 10.06.2017 ###
* IP blacklist implemented (#7)

388
RoboFile.php Normal file
View File

@ -0,0 +1,388 @@
<?php
/**
* Statify Blacklist Robo build script.
*
* This file contains the Robo tasks for building a distributable plugin package.
* Should not be included in final package.
*
* @author Stefan Kalscheuer <stefan@stklcode.de>
*
* @package Statify_Blacklist
* @version 1.4.4
*/
use Robo\Exception\TaskException;
use Robo\Tasks;
/**
* Class RoboFile
*/
class RoboFile extends Tasks {
const PROJECT_NAME = 'statify-blacklist';
const SVN_URL = 'https://plugins.svn.wordpress.org/statify-blacklist';
const OPT_TARGET = 'target';
const OPT_SKIPTEST = 'skipTests';
const OPT_SKIPSTYLE = 'skipStyle';
/**
* Version tag (read from composer.json).
*
* @var string
*/
private $version;
/**
* Target directory path.
*
* @var string
*/
private $target_dir;
/**
* Final package name.
*
* @var string
*/
private $final_name;
/**
* RoboFile constructor
*
* @param array $opts Options.
*
* @return void
*/
public function __construct( $opts = [ self::OPT_TARGET => 'dist' ] ) {
// Read composer configuration and extract version number..
$composer = json_decode( file_get_contents( __DIR__ . '/composer.json' ) );
// Extract parameter from options.
$this->version = $composer->version;
$this->target_dir = $opts[ self::OPT_TARGET ];
$this->final_name = self::PROJECT_NAME . '.' . $this->version;
}
/**
* Clean up target directory
*
* @param array $opts Options.
*
* @return void
*/
public function clean( $opts = [ self::OPT_TARGET => 'dist' ] ) {
$this->say( 'Cleaning target directory...' );
if ( is_dir( $this->target_dir . '/' . $this->final_name ) ) {
$this->_deleteDir( [ $this->target_dir . '/' . $this->final_name ] );
}
if ( is_file( $this->target_dir . '/' . $this->final_name . '.zip' ) ) {
$this->_remove( $this->target_dir . '/' . $this->final_name . '.zip' );
}
}
/**
* Run PHPUnit tests
*
* @return void
*/
public function test() {
$this->say( 'Executing PHPUnit tests...' );
$this->taskPhpUnit()->configFile( __DIR__ . '/phpunit.xml' )->run();
}
/**
* Run code style tests
*
* @return void
*/
public function testCS() {
$this->say( 'Executing PHPCS tests...' );
$this->_exec( __DIR__ . '/vendor/bin/phpcs --standard=phpcs.xml -s' );
}
/**
* Build a distributable bundle.
*
* @param array $opts Options.
*
* @return void
*/
public function build(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
$this->clean( $opts );
if ( isset( $opts[ self::OPT_SKIPTEST ] ) && true === $opts[ self::OPT_SKIPTEST ] ) {
$this->say( 'Tests skipped' );
} else {
$this->test();
}
if ( isset( $opts[ self::OPT_SKIPSTYLE ] ) && true === $opts[ self::OPT_SKIPSTYLE ] ) {
$this->say( 'Style checks skipped' );
} else {
$this->testCS();
}
$this->bundle();
}
/**
* Bundle global resources.
*
* @return void
*/
private function bundle() {
$this->say( 'Bundling resources...' );
$this->taskCopyDir( [
'inc' => $this->target_dir . '/' . $this->final_name . '/inc',
'views' => $this->target_dir . '/' . $this->final_name . '/views',
] )->run();
$this->_copy( 'statify-blacklist.php', $this->target_dir . '/' . $this->final_name . '/statify-blacklist.php' );
$this->_copy( 'README.md', $this->target_dir . '/' . $this->final_name . '/README.md' );
$this->_copy( 'LICENSE.md', $this->target_dir . '/' . $this->final_name . '/LICENSE.md' );
}
/**
* Create ZIP package from distribution bundle.
*
* @param array $opts Options.
*
* @return void
*/
public function package(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
$this->build( $opts );
$this->say( 'Packaging...' );
$this->taskPack( $this->target_dir . '/' . $this->final_name . '.zip' )
->addDir( '', $this->target_dir . '/' . $this->final_name )
->run();
}
/**
* Deploy development version (trunk).
*
* @param array $opts Options.
*
* @return void
* @throws TaskException On errors.
*/
public function deployTrunk(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
// First execute build job.
$this->build( $opts );
// Prepare VCS, either checkout or update local copy.
$this->prepareVCS();
$this->say( 'Preparing deployment directory...' );
$this->updateVCStrunk();
// Update remote repository.
$this->say( 'Deploying...' );
$this->commitVCS(
'--force trunk/*',
'Updated ' . self::PROJECT_NAME . ' trunk'
);
}
/**
* Deploy current version tag.
*
* @param array $opts Options.
*
* @return void
* @throws TaskException On errors.
*/
public function deployTag(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
// First execute build job.
$this->build( $opts );
// Prepare VCS, either checkout or update local copy.
$this->prepareVCS();
$this->say( 'Preparing deployment directory...' );
$this->updateVCStag();
// Update remote repository.
$this->say( 'Deploying...' );
$this->commitVCS(
'tags/' . $this->version,
'Updated ' . self::PROJECT_NAME . ' v' . $this->version
);
}
/**
* Deploy current version tag.
*
* @param array $opts Options.
*
* @return void
* @throws TaskException On errors.
*/
public function deployReadme(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
// First execute build job.
$this->build( $opts );
// Prepare VCS, either checkout or update local copy.
$this->prepareVCS();
$this->updateVCSreadme();
// Update remote repository.
$this->say( 'Deploying...' );
$this->commitVCS(
'--force trunk/README.md',
'Updated ' . self::PROJECT_NAME . ' ReadMe'
);
}
/**
* Deploy current version tag and trunk.
*
* @param array $opts Options.
*
* @return void
* @throws TaskException On errors.
*/
public function deployAll(
$opts = [
self::OPT_TARGET => 'dist',
self::OPT_SKIPTEST => false,
self::OPT_SKIPSTYLE => false,
]
) {
// First execute build job.
$this->build( $opts );
// Prepare VCS, either checkout or update local copy.
$this->prepareVCS();
$this->say( 'Preparing deployment directory...' );
$this->updateVCStrunk();
$this->updateVCStag();
// Update remote repository.
$this->say( 'Deploying...' );
$this->commitVCS(
[
'--force trunk/*',
'--force tags/' . $this->version,
],
'Updated ' . self::PROJECT_NAME . ' v' . $this->version
);
}
/**
* Prepare VCS direcory.
*
* Checkout or update local copy of SVN repository.
*
* @return void
* @throws TaskException On errors.
*/
private function prepareVCS() {
if ( is_dir( $this->target_dir . '/svn' ) ) {
$this->taskSvnStack()
->stopOnFail()
->dir( $this->target_dir . '/svn/statify-blacklist' )
->update()
->run();
} else {
$this->_mkdir( $this->target_dir . '/svn' );
$this->taskSvnStack()
->dir( $this->target_dir . '/svn' )
->checkout( self::SVN_URL )
->run();
}
}
/**
* Commit VCS changes
*
* @param string|array $to_add Files to add.
* @param string $msg Commit message.
*
* @return void
* @throws TaskException On errors.
*/
private function commitVCS( $to_add, $msg ) {
$task = $this->taskSvnStack()
->stopOnFail()
->dir( $this->target_dir . '/svn/statify-blacklist' );
if ( is_array( $to_add ) ) {
foreach ( $to_add as $ta ) {
$task = $task->add( $ta );
}
} else {
$task = $task->add( $to_add );
}
$task->commit( $msg )->run();
}
/**
* Update SVN readme file.
*
* @return void
*/
private function updateVCSreadme() {
$trunk_dir = $this->target_dir . '/svn/statify-blacklist/trunk';
$this->_copy( $this->target_dir . '/' . $this->final_name . '/README.md', $trunk_dir . '/README.md' );
}
/**
* Update SVN development version (trunk).
*
* @return void
*/
private function updateVCStrunk() {
// Clean trunk directory.
$trunk_dir = $this->target_dir . '/svn/statify-blacklist/trunk';
$this->taskCleanDir( $trunk_dir )->run();
// Copy built bundle to trunk.
$this->taskCopyDir( [ $this->target_dir . '/' . $this->final_name => $trunk_dir ] )->run();
}
/**
* Update current SVN version tag.
*
* @return void
*/
private function updateVCStag() {
// Clean tag directory if it exists.
$tag_dir = $this->target_dir . '/svn/statify-blacklist/tags/' . $this->version;
if ( is_dir( $tag_dir ) ) {
$this->taskCleanDir( $this->target_dir . '/svn/statify-blacklist/tags/' . $this->version )->run();
} else {
$this->_mkdir( $tag_dir );
}
// Copy built bundle to trunk.
$this->taskCopyDir( [ $this->target_dir . '/' . $this->final_name => $tag_dir ] )->run();
}
}

View File

@ -1,6 +1,6 @@
{
"name": "stklcode/statify-blacklist",
"version": "1.4.1",
"version": "1.4.4",
"description": "A blacklist extension for the famous Statify WordPress plugin",
"keywords": [
"wordpress",
@ -8,7 +8,7 @@
"statistics",
"blacklist"
],
"license": "GPL-2.0+",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Stefan Kalscheuer",
@ -22,8 +22,37 @@
"composer/installers": "~1.0"
},
"require-dev": {
"php": ">=5.5",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4",
"consolidation/robo": "^1.0.0",
"phpunit/phpunit": "*",
"wp-coding-standards/wpcs": "~0.11.0"
"phpunit/php-code-coverage": "*",
"slowprog/composer-copy-file": "~0.2",
"squizlabs/php_codesniffer": "^3.1",
"wimg/php-compatibility": "^8.0",
"wp-coding-standards/wpcs": "~0.14"
},
"scripts": {
"build": [
"robo build"
],
"package": [
"robo package"
],
"deploy": [
"robo deploy:all"
],
"test-all": [
"@test",
"@test-cs"
],
"test": [
"phpunit"
],
"test-cs": [
"phpcs --standard=phpcs.xml -s"
],
"fix-cs": [
"phpcbf --standard=phpcs.xml"
]
}
}

View File

@ -48,11 +48,11 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
} elseif ( ! empty( array_diff( $given_ip, $sanitized_ip ) ) ) {
return array(
'ip' => array_diff( $given_ip, $sanitized_ip ),
);
);
}
// Update database on success.
if ( ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) ) {
if ( self::$multisite ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );
@ -70,7 +70,7 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
*
* @since 1.0.0
*/
public function _add_menu_page() {
public static function add_menu_page() {
$title = __( 'Statify Blacklist', 'statify-blacklist' );
if ( self::$multisite ) {
add_submenu_page(

View File

@ -28,7 +28,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
*/
public static function install( $network_wide = false ) {
// Create tables for each site in a network.
if ( is_multisite() && $network_wide ) {
if ( $network_wide && is_multisite() ) {
if ( function_exists( 'get_sites' ) ) {
$sites = get_sites();
} elseif ( function_exists( 'wp_get_sites' ) ) {
@ -39,11 +39,12 @@ class StatifyBlacklist_System extends StatifyBlacklist {
}
foreach ( $sites as $site ) {
switch_to_blog( $site['blog_id'] );
add_option(
'statify-blacklist',
self::default_options()
);
if ( is_array( $site ) ) {
$site_id = $site['blog_id'];
} else {
$site_id = $site->blog_id;
}
self::install_site( $site_id );
}
restore_current_blog();
@ -55,6 +56,22 @@ class StatifyBlacklist_System extends StatifyBlacklist {
}
}
/**
* Set up the plugin for a single site on Multisite.
*
* @since 1.4.3
*
* @param integer $site_id Site ID.
*/
public static function install_site( $site_id ) {
switch_to_blog( (int) $site_id );
add_option(
'statify-blacklist',
self::default_options()
);
restore_current_blog();
}
/**
* Plugin uninstall handler.
@ -75,8 +92,12 @@ class StatifyBlacklist_System extends StatifyBlacklist {
}
foreach ( $sites as $site ) {
switch_to_blog( $site['blog_id'] );
delete_option( 'statify-blacklist' );
if ( is_array( $site ) ) {
$site_id = $site['blog_id'];
} else {
$site_id = $site->blog_id;
}
self::uninstall_site( $site_id );
}
switch_to_blog( $old );
@ -85,6 +106,19 @@ class StatifyBlacklist_System extends StatifyBlacklist {
delete_option( 'statify-blacklist' );
}
/**
* Remove the plugin for a single site on Multisite.
*
* @since 1.4.3
*
* @param integer $site_id Site ID.
*/
public static function uninstall_site( $site_id ) {
$old = get_current_blog_id();
switch_to_blog( (int) $site_id );
delete_option( 'statify-blacklist' );
switch_to_blog( $old );
}
/**
* Upgrade plugin options.
@ -98,7 +132,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
// Flip referer array to make domains keys.
$options = self::$_options;
$options['referer'] = array_flip( self::$_options['referer'] );
if ( ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) ) {
if ( self::$multisite ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );
@ -127,7 +161,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
),
'version' => 1.4,
);
if ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) {
if ( self::$multisite ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );
@ -140,7 +174,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
// Merge default options with current config, assuming only additive changes.
$options = array_merge_recursive( self::default_options(), self::$_options );
$options['version'] = self::VERSION_MAIN;
if ( ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) ) {
if ( self::$multisite ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );

View File

@ -46,28 +46,39 @@ class StatifyBlacklist {
* Class self initialize.
*
* @since 1.0.0
* @deprecated 1.4.2 Replaced by init().
*/
public static function instance() {
new self();
self::init();
}
/**
* Class constructor.
*
* @since 1.0.0
* @deprecated 1.4.2 Replaced by init().
*/
public function __construct() {
self::init();
}
/**
* Plugin initialization.
*
* @since 1.4.2
*/
public static function init() {
// Skip on autosave or AJAX.
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
return;
}
// Plugin options.
self::update_options();
// Get multisite status.
self::$multisite = ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) );
// Plugin options.
self::update_options();
// Add Filter to statify hook if enabled.
if ( 0 !== self::$_options['referer']['active'] || 0 !== self::$_options['target']['active'] || 0 !== self::$_options['ip']['active'] ) {
add_filter( 'statify__skip_tracking', array( 'StatifyBlacklist', 'apply_blacklist_filter' ) );
@ -79,12 +90,12 @@ class StatifyBlacklist {
load_plugin_textdomain( 'statifyblacklist', false, STATIFYBLACKLIST_DIR . '/lang/' );
// Add actions.
add_action( 'wpmu_new_blog', array( 'StatifyBlacklist_Install', 'init_site' ) );
add_action( 'delete_blog', array( 'StatifyBlacklist_System', 'init_site' ) );
add_action( 'wpmu_new_blog', array( 'StatifyBlacklist_System', 'install_site' ) );
add_action( 'delete_blog', array( 'StatifyBlacklist_System', 'uninstall_site' ) );
add_filter( 'plugin_row_meta', array( 'StatifyBlacklist_Admin', 'plugin_meta_link' ), 10, 2 );
if ( is_multisite() ) {
add_action( 'network_admin_menu', array( 'StatifyBlacklist_Admin', '_add_menu_page' ) );
if ( self::$multisite ) {
add_action( 'network_admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
add_filter(
'network_admin_plugin_action_links', array(
'StatifyBlacklist_Admin',
@ -94,7 +105,7 @@ class StatifyBlacklist {
2
);
} else {
add_action( 'admin_menu', array( 'StatifyBlacklist_Admin', '_add_menu_page' ) );
add_action( 'admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
add_filter( 'plugin_action_links', array( 'StatifyBlacklist_Admin', 'plugin_actions_links' ), 10, 2 );
}
}
@ -116,10 +127,12 @@ class StatifyBlacklist {
* @param array $options Optional. New options to save.
*/
public static function update_options( $options = null ) {
self::$_options = wp_parse_args(
get_option( 'statify-blacklist' ),
self::default_options()
);
if ( self::$multisite ) {
$o = get_site_option( 'statify-blacklist' );
} else {
$o = get_option( 'statify-blacklist' );
}
self::$_options = wp_parse_args( $o, self::default_options() );
}
/**
@ -174,8 +187,10 @@ class StatifyBlacklist {
$regexp .= 'i';
}
// Check blacklist (return NULL to continue filtering).
return ( 1 === preg_match( $regexp, $referer ) ) ? true : null;
// Check blacklist (no return to continue filtering #12).
if ( 1 === preg_match( $regexp, $referer ) ) {
return true;
}
} else {
// Extract relevant domain parts.
$referer = wp_parse_url( wp_get_raw_referer() );
@ -205,8 +220,10 @@ class StatifyBlacklist {
$regexp .= 'i';
}
// Check blacklist (return NULL to continue filtering).
return ( 1 === preg_match( $regexp, $target ) ) ? true : null;
// Check blacklist (no return to continue filtering #12).
if ( 1 === preg_match( $regexp, $target ) ) {
return true;
}
} else {
// Extract target page.
// @codingStandardsIgnoreStart The globals are checked.
@ -306,7 +323,7 @@ class StatifyBlacklist {
}
$bytes_addr = unpack( 'n*', inet_pton( $base ) );
$bytes_est = unpack( 'n*', inet_pton( $ip ) );
$bytes_est = unpack( 'n*', inet_pton( $ip ) );
if ( ! $bytes_addr || ! $bytes_est ) {
return false;
@ -314,8 +331,8 @@ class StatifyBlacklist {
$ceil = ceil( $mask / 16 );
for ( $i = 1; $i <= $ceil; ++ $i ) {
$left = $mask - 16 * ( $i - 1 );
$left = ( $left <= 16 ) ? $left : 16;
$left = $mask - 16 * ( $i - 1 );
$left = ( $left <= 16 ) ? $left : 16;
$mask_b = ~( 0xffff >> $left ) & 0xffff;
if ( ( $bytes_addr[ $i ] & $mask_b ) !== ( $bytes_est[ $i ] & $mask_b ) ) {
return false;

View File

@ -1,17 +1,17 @@
{
"name": "statify-blacklist",
"version": "1.4.1",
"version": "1.4.4",
"description": "A blacklist extension for the famous Statify WordPress plugin",
"author": "Stefan Kalscheuer",
"license": "GPLv2 or later",
"license": "GPL-2.0+",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-clean": "^0.3.2",
"gulp-copy": "^1.0.0",
"gulp-copy": "^1.0.1",
"gulp-zip": "^4.0.0",
"gulp-composer": "^0.4.0",
"gulp-phpunit": "^0.23.0",
"gulp-phpcs": "^2.0.0",
"gulp-composer": "^0.4.4",
"gulp-phpunit": "^0.24.1",
"gulp-phpcs": "^2.1.0",
"child_process": "^1.0.2"
}
}

View File

@ -2,10 +2,16 @@
<ruleset name="StatifyBlacklist">
<description>Derived from WordPress Coding Standard</description>
<rule ref="WordPress">
<!-- Type hint checks mess up PHP 7 checks, while this plugin has compatibility level 5.5 and above. -->
<exclude name="Squiz.Commenting.FunctionComment.ScalarTypeHintMissing"/>
<arg value="psvn"/>
<arg name="colors"/>
<!-- Files to sniff -->
<file>inc</file>
<file>statify-blacklist.php</file>
<!-- Compliance with WordPress Coding Standard -->
<config name="minimum_supported_wp_version" value="4.4"/>
<rule ref="WordPress">
<!-- The plugin uses switch_to_blog for multisite handling. -->
<exclude name="WordPress.VIP.RestrictedFunctions.switch_to_blog"/>
<exclude name="WordPress.VIP.RestrictedFunctions.switch_to_blog_switch_to_blog"/>
@ -14,4 +20,8 @@
<exclude name="WordPress.VIP.DirectDatabaseQuery.DirectQuery"/>
<exclude name="WordPress.VIP.DirectDatabaseQuery.NoCaching"/>
</rule>
<!-- PHP compatibility level -->
<config name="testVersion" value="5.5-"/>
<rule ref="PHPCompatibility"/>
</ruleset>

View File

@ -5,4 +5,13 @@
<directory suffix="-test.php">./test/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./inc/</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="tests-clover.xml"/>
<log type="junit" target="tests-junit.xml" logIncompleteSkipped="false"/>
</logging>
</phpunit>

View File

@ -10,7 +10,7 @@
* Plugin Name: Statify Blacklist
* Plugin URI: https://wordpress.org/plugins/statify-blacklist/
* Description: Extension for the Statify plugin to add a customizable blacklists.
* Version: 1.4.1
* Version: 1.4.4
* Author: Stefan Kalscheuer (@stklcode)
* Author URI: https://www.stklcode.de
* Text Domain: statify-blacklist
@ -40,7 +40,7 @@ define( 'STATIFYBLACKLIST_DIR', dirname( __FILE__ ) );
define( 'STATIFYBLACKLIST_BASE', plugin_basename( __FILE__ ) );
// System Hooks.
add_action( 'plugins_loaded', array( 'StatifyBlacklist', 'instance' ) );
add_action( 'plugins_loaded', array( 'StatifyBlacklist', 'init' ) );
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'install' ) );
@ -67,12 +67,10 @@ function statify_blacklist_autoload( $class ) {
);
if ( in_array( $class, $plugin_classes, true ) ) {
require_once(
sprintf(
'%s/inc/class-%s.php',
STATIFYBLACKLIST_DIR,
strtolower( str_replace( '_', '-', $class ) )
)
require_once sprintf(
'%s/inc/class-%s.php',
STATIFYBLACKLIST_DIR,
strtolower( str_replace( '_', '-', $class ) )
);
}
}

View File

@ -472,6 +472,86 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
}
// TODO: Test target regex filter.
/**
* Test combined filters.
*
* @since 1.4.4
*
* @return void
*/
public function test_combined_filters() {
// Prepare Options: simple referer + simple target + ip.
StatifyBlacklist::$_options = array(
'referer' => array(
'active' => 1,
'cron' => 0,
'regexp' => 0,
'blacklist' => array(
'example.com' => 0,
),
),
'target' => array(
'active' => 1,
'cron' => 0,
'regexp' => 0,
'blacklist' => array(
'/excluded/page/' => 0
),
),
'ip' => array(
'active' => 1,
'blacklist' => array(
'192.0.2.123'
),
),
'version' => StatifyBlacklist::VERSION_MAIN,
);
// No multisite.
StatifyBlacklist::$multisite = false;
// No match.
$_SERVER['HTTP_REFERER'] = 'https://example.net';
$_SERVER['REQUEST_URI'] = '/normal/page/';
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
unset( $_SERVER['HTTP_X_FORWARDED_FOR'] );
unset( $_SERVER['HTTP_X_REAL_IP'] );
// Matching Referer.
$_SERVER['HTTP_REFERER'] = 'https://example.com';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
// Matching target.
$_SERVER['HTTP_REFERER'] = 'https://example.net';
$_SERVER['REQUEST_URI'] = '/excluded/page/';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
// Matching IP.
$_SERVER['REQUEST_URI'] = '/normal/page/';
$_SERVER['REMOTE_ADDR'] = '192.0.2.123';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
// Same for RegExp filters.
StatifyBlacklist::$_options['referer']['regexp'] = 1;
StatifyBlacklist::$_options['referer']['blacklist'] = array( 'example\.com' => 0 );
StatifyBlacklist::$_options['target']['regexp'] = 1;
StatifyBlacklist::$_options['target']['blacklist'] = array( '\/excluded\/.*' => 0 );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_REFERER'] = 'https://example.com';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_REFERER'] = 'https://example.net';
$_SERVER['REQUEST_URI'] = '/excluded/page/';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/normal/page/';
$_SERVER['REMOTE_ADDR'] = '192.0.2.123';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
}
}

View File

@ -51,19 +51,26 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
$statifyblacklist_update_result = StatifyBlacklist_Admin::update_options(
array(
'referer' => array(
'active' => (int) $_POST['statifyblacklist']['referer']['active'],
'cron' => (int) $_POST['statifyblacklist']['referer']['cron'],
'regexp' => (int) $_POST['statifyblacklist']['referer']['regexp'],
'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' => (int) $_POST['statifyblacklist']['target']['active'],
'cron' => (int) $_POST['statifyblacklist']['target']['cron'],
'regexp' => (int) $_POST['statifyblacklist']['target']['regexp'],
'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' => (int) $_POST['statifyblacklist']['ip']['active'],
'active' => isset( $_POST['statifyblacklist']['ip']['active'] )
? (int) $_POST['statifyblacklist']['ip']['active'] : 0,
'blacklist' => $ip,
),
'version' => StatifyBlacklist::VERSION_MAIN,
@ -90,7 +97,7 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
<?php
if ( is_plugin_inactive( 'statify/statify.php' ) ) {
print '<div class="notice notice-warning"><p>';
esc_html( 'Statify plugin is not active.' );
esc_html_e( 'Statify plugin is not active.', 'statify-blacklist' );
print '</p></div>';
}
if ( isset( $statifyblacklist_post_warning ) ) {