From 6ac4e60b71289c212d1cf80e22c5c2b500d16e5b Mon Sep 17 00:00:00 2001 From: Dyszczo <krzysztof.dyszczyk@gmail.com> Date: Mon, 25 May 2020 09:47:39 +0000 Subject: [PATCH] Feature/init --- .gitattributes | 15 +++ .gitignore | 5 + .gitlab-ci.yml | 9 ++ README.md | 54 +++++++++ changelog.txt | 1 + composer.json | 34 ++++++ phpunit-integration.xml | 28 +++++ phpunit-unit.xml | 21 ++++ src/GetStrategy.php | 44 +++++++ src/PostTypeStrategy.php | 39 +++++++ src/ShouldShowStrategy.php | 13 +++ tests/docker-compose.yaml | 172 ++++++++++++++++++++++++++++ tests/integration/bootstrap.php | 28 +++++ tests/unit/Stub/WP_Post.php | 6 + tests/unit/TestGetStrategy.php | 83 ++++++++++++++ tests/unit/TestPostTypeStrategy.php | 55 +++++++++ tests/unit/bootstrap.php | 9 ++ 17 files changed, 616 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 changelog.txt create mode 100644 composer.json create mode 100644 phpunit-integration.xml create mode 100644 phpunit-unit.xml create mode 100644 src/GetStrategy.php create mode 100644 src/PostTypeStrategy.php create mode 100644 src/ShouldShowStrategy.php create mode 100644 tests/docker-compose.yaml create mode 100644 tests/integration/bootstrap.php create mode 100644 tests/unit/Stub/WP_Post.php create mode 100644 tests/unit/TestGetStrategy.php create mode 100644 tests/unit/TestPostTypeStrategy.php create mode 100644 tests/unit/bootstrap.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a612c0c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +tests/ export-ignore +vendor/ export-ignore +.editorconfig export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.git/ export-ignore +.gitlab-ci.yml export-ignore +.idea export-ignore +apigen.neon export-ignore +build-coverage/ export-ignore +docs/ export-ignore +LICENSE.md export-ignore +phpcs.xml.dist export-ignore +phpunit-integration.xml export-ignore +phpunit-unit.xml export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b86223 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/vendor/ +.idea +composer.lock +build-coverage +swagger \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..38447e9 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,9 @@ +variables: + DISABLE_FUNCTIONAL: 1 + DISABLE_ACCEPTANCE: 1 + DISABLE_PHP_5_5: 1 + DISABLE_CODECEPTION: 1 + DISABLE_INTEGRATION_TESTS: 1 + IS_LIBRARY: 1 + +include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml' diff --git a/README.md b/README.md index e69de29..2afdc49 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,54 @@ +[](https://gitlab.com/wpdesk/wp-show-decision/pipelines) +[](https://gitlab.com/wpdesk/wp-show-decision/commits/master) +[](https://packagist.org/packages/wpdesk/wp-show-decision) +[](https://packagist.org/packages/wpdesk/wp-show-decision) +[](https://packagist.org/packages/wpdesk/wp-show-decision) +[](https://packagist.org/packages/wpdesk/wp-show-decision) + +WordPress Library for Decision whether to show something. +=================================================== +Idea is that you have ShouldShowStrategy interface with one bool method. Thanks to this you can create a class that +delegates decision whether to show something. Your class does not have to hardcode that decision. + +## Requirements + +PHP 5.6 or later. + +## Composer + +You can install the bindings via [Composer](http://getcomposer.org/). Run the following command: + +```bash +composer require --dev wpdesk/wp-show-decision +``` + +To use the bindings, use Composer's [autoload](https://getcomposer.org/doc/01-basic-usage.md#autoloading): + +```php +require_once 'vendor/autoload.php'; +``` + +## Usage + +```php + new Beacon( + '6057086f-4b25-4e12-8735-fbc556d2dc01', + new PostTypeStrategy('automation'), + $this->get_plugin_assets_url() +``` + +```php + if ( is_admin() ) { + ( new RateNotices( + [ new TwoWeeksNotice( $this->plugin_url . '/assets', new PostTypeStrategy([ + [ 'page' => 'x', 'name' => 'stefan' ], // show when page = x and name = stefan + [ 'page' => 'y' ] // OR when page = y + ] ) ) ] + ) )->hooks(); + } +``` + + +## Project documentation + +PHPDoc: https://wpdesk.gitlab.io/wp-show-decision/index.html \ No newline at end of file diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..8531c03 --- /dev/null +++ b/changelog.txt @@ -0,0 +1 @@ +* First release diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..667851a --- /dev/null +++ b/composer.json @@ -0,0 +1,34 @@ +{ + "name": "wpdesk/wp-show-decision", + "authors": [ + { + "name": "Krzysiek", + "email": "krzysiek@wpdesk.pl" + } + ], + "require": { + "php": ">=5.6", + "ext-curl": "*", + "ext-json": "*" + }, + "require-dev": { + "phpunit/phpunit": "<7", + "wp-coding-standards/wpcs": "^0.14.1", + "squizlabs/php_codesniffer": "^3.0.2", + "mockery/mockery": "*", + "10up/wp_mock": "*" + }, + "autoload": { + "psr-4": { + "WPDesk\\ShowDecision\\": "src/" + } + }, + "autoload-dev": { + }, + "scripts": { + "phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never", + "phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage", + "phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never", + "phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage" + } +} diff --git a/phpunit-integration.xml b/phpunit-integration.xml new file mode 100644 index 0000000..4a342ab --- /dev/null +++ b/phpunit-integration.xml @@ -0,0 +1,28 @@ +<phpunit bootstrap="tests/integration/bootstrap.php" + backupGlobals="false" + > + <testsuites> + <testsuite> + <directory prefix="Test" suffix=".php">./tests/integration</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory suffix=".php">src</directory> + </whitelist> + </filter> + + <logging> + <log type="junit" target="build-coverage/report.junit.xml"/> + <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/> + <log type="coverage-text" target="build-coverage/coverage.txt"/> + <log type="coverage-clover" target="build-coverage/clover.xml"/> + </logging> + + <php> + <env name="WP_DEVELOP_DIR" value="/tmp/wordpress-develop"/> + <env name="WC_DEVELOP_DIR" value="/tmp/woocommerce"/> + </php> + +</phpunit> \ No newline at end of file diff --git a/phpunit-unit.xml b/phpunit-unit.xml new file mode 100644 index 0000000..31e5c9f --- /dev/null +++ b/phpunit-unit.xml @@ -0,0 +1,21 @@ +<phpunit bootstrap="tests/unit/bootstrap.php"> + <testsuites> + <testsuite> + <directory prefix="Test" suffix=".php">./tests/unit/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory suffix=".php">src</directory> + </whitelist> + </filter> + + <logging> + <log type="junit" target="build-coverage/report.junit.xml"/> + <log type="coverage-html" target="build-coverage/coverage" charset="UTF-8" yui="true" highlight="true"/> + <log type="coverage-text" target="build-coverage/coverage.txt"/> + <log type="coverage-clover" target="build-coverage/clover.xml"/> + </logging> + +</phpunit> diff --git a/src/GetStrategy.php b/src/GetStrategy.php new file mode 100644 index 0000000..b22ac92 --- /dev/null +++ b/src/GetStrategy.php @@ -0,0 +1,44 @@ +<?php + +namespace WPDesk\ShowDecision; + +/** + * Show when some conditions with $_GET are meet. + */ +class GetStrategy implements ShouldShowStrategy { + /** + * @var array + */ + private $conditions; + + /** + * @param array $conditions Whether to show on the page or not. Array of arrays with condition for _GET. + * + * Inner arrays mean AND, outer arrays mean OR conditions. + * + * ie. [ [ .. and .. and ..] or [ .. and .. and ..] or .. ] + * + */ + public function __construct( array $conditions ) { + $this->conditions = $conditions; + } + + /** + * @return bool + */ + public function shouldDisplay() { + foreach ( $this->conditions as $or_conditions ) { + $display = true; + foreach ( $or_conditions as $parameter => $value ) { + if ( ! isset( $_GET[ $parameter ] ) || $_GET[ $parameter ] !== $value ) { + $display = false; + } + } + if ( $display ) { + return $display; + } + } + + return false; + } +} diff --git a/src/PostTypeStrategy.php b/src/PostTypeStrategy.php new file mode 100644 index 0000000..fe768f1 --- /dev/null +++ b/src/PostTypeStrategy.php @@ -0,0 +1,39 @@ +<?php + +namespace WPDesk\ShowDecision; + +/** + * Show when pages associated with given post type is displayed. + */ +class PostTypeStrategy implements ShouldShowStrategy { + /** @var string */ + private $post_type; + + public function __construct( $post_type ) { + $this->post_type = $post_type; + } + + /** + * Should Beacon be visible? + * + * @return bool + */ + public function shouldDisplay() { + return $this->is_current_post_type_automation() || + ( isset( $_GET['post_type'] ) && $_GET['post_type'] === $this->post_type ); + } + + /** + * @return bool + */ + private function is_current_post_type_automation() { + if ( isset( $_GET['post'] ) ) { + $post = get_post( (int) $_GET['post'] ); + if ( $post instanceof \WP_Post ) { + return $post->post_type === $this->post_type; + } + } + + return false; + } +} diff --git a/src/ShouldShowStrategy.php b/src/ShouldShowStrategy.php new file mode 100644 index 0000000..c957cd0 --- /dev/null +++ b/src/ShouldShowStrategy.php @@ -0,0 +1,13 @@ +<?php + +namespace WPDesk\ShowDecision; + +/** + * Should something be shown? + */ +interface ShouldShowStrategy { + /** + * @return bool + */ + public function shouldDisplay(); +} diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml new file mode 100644 index 0000000..2a86b03 --- /dev/null +++ b/tests/docker-compose.yaml @@ -0,0 +1,172 @@ +version: '2.0' + +services: + + wordpress: + image: wpdesknet/phpunit-woocommerce:0-0 + volumes: + - .././:/opt/project + depends_on: + - mysql0 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql0 + + wordpress-0-1: + image: wpdesknet/phpunit-woocommerce:0-1 + volumes: + - .././:/opt/project + depends_on: + - mysql1 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql1 + + wordpress-0-2: + image: wpdesknet/phpunit-woocommerce:0-2 + volumes: + - .././:/opt/project + depends_on: + - mysql2 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql2 + + wordpress-0-3: + image: wpdesknet/phpunit-woocommerce:0-3 + volumes: + - .././:/opt/project + depends_on: + - mysql3 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql3 + + wordpress-0-4: + image: wpdesknet/phpunit-woocommerce:0-4 + volumes: + - .././:/opt/project + depends_on: + - mysql4 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql4 + + wordpress-0-5: + image: wpdesknet/phpunit-woocommerce:0-5 + volumes: + - .././:/opt/project + depends_on: + - mysql5 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql5 + + wordpress-1-0: + image: wpdesknet/phpunit-woocommerce:1-0 + volumes: + - .././:/opt/project + depends_on: + - mysql0 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql0 + + wordpress-2-0: + image: wpdesknet/phpunit-woocommerce:2-0 + volumes: + - .././:/opt/project + depends_on: + - mysql0 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql0 + + wordpress-3-0: + image: wpdesknet/phpunit-woocommerce:3-0 + volumes: + - .././:/opt/project + depends_on: + - mysql0 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql0 + + wordpress-4-0: + image: wpdesknet/phpunit-woocommerce:4-0 + volumes: + - .././:/opt/project + depends_on: + - mysql0 + environment: + WORDPRESS_DB_NAME: wptest + WORDPRESS_DB_USER: mysql + WORDPRESS_DB_PASSWORD: mysql + WORDPRESS_DB_HOST: mysql0 + + mysql0: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + + mysql1: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + + mysql2: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + + mysql3: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + + mysql4: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + + mysql5: + image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: mysql + MYSQL_DATABASE: wptest + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php new file mode 100644 index 0000000..a422fd9 --- /dev/null +++ b/tests/integration/bootstrap.php @@ -0,0 +1,28 @@ +<?php + +ini_set('error_reporting', E_ALL); // or error_reporting(E_ALL); +ini_set('display_errors', '1'); +ini_set('display_startup_errors', '1'); + +require_once __DIR__ . '/../../vendor/autoload.php'; + +// disable xdebug backtrace +if ( function_exists( 'xdebug_disable' ) ) { + xdebug_disable(); +} + +if ( getenv( 'PLUGIN_PATH' ) !== false ) { + define( 'PLUGIN_PATH', getenv( 'PLUGIN_PATH' ) ); +} else { + define( 'PLUGIN_PATH', __DIR__ . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR ); +} + +require_once( getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit/includes/functions.php' ); + +tests_add_filter( 'muplugins_loaded', function () { +}, 100 ); + +putenv('WP_TESTS_DIR=' . getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit'); +require_once( getenv( 'WC_DEVELOP_DIR' ) . '/tests/bootstrap.php' ); + +do_action('plugins_loaded'); \ No newline at end of file diff --git a/tests/unit/Stub/WP_Post.php b/tests/unit/Stub/WP_Post.php new file mode 100644 index 0000000..bba4f36 --- /dev/null +++ b/tests/unit/Stub/WP_Post.php @@ -0,0 +1,6 @@ +<?php + +class WP_Post { + public $ID; + public $post_type; +} \ No newline at end of file diff --git a/tests/unit/TestGetStrategy.php b/tests/unit/TestGetStrategy.php new file mode 100644 index 0000000..7da82b5 --- /dev/null +++ b/tests/unit/TestGetStrategy.php @@ -0,0 +1,83 @@ +<?php + +namespace unit; + +use PHPUnit\Framework\TestCase; +use WPDesk\ShowDecision\GetStrategy; + +class TestGetStrategy extends TestCase { + const true_1 = [ 'a' => '1' ]; + const true_2 = [ 'b' => '2' ]; + const true_3 = [ 'c' => '3' ]; + + const false_1 = [ 'x' => '1' ]; + const false_2 = [ 'y' => '2' ]; + + /** + * Prepares $_GET with true clauses + */ + private function prepare_get() { + $_GET = [ + self::true_1, + self::true_2, + self::true_3 + ]; + } + + protected function setUp() { + parent::setUp(); + $this->prepare_get(); + } + + public function testAndClausesFailure() { + $strategy = new GetStrategy( [ + [ + self::true_1, + self::false_1 + ] + ] ); + $this->assertFalse( $strategy->shouldDisplay() ); + } + + public function testAndClausesSuccess() { + $strategy = new GetStrategy( [ + [ + self::true_1, + self::true_2, + self::true_3 + ] + ] ); + $this->assertTrue( $strategy->shouldDisplay() ); + } + + public function testOrClausesSuccess() { + $strategy = new GetStrategy( [ + [ + self::true_1, + self::false_1 + ], + [ + self::true_1, + self::true_2 + ] + ] ); + $this->assertTrue( $strategy->shouldDisplay() ); + } + + public function testOrClausesFailure() { + $strategy = new GetStrategy( [ + [ + self::true_1, + self::false_1 + ], + [ + self::true_1, + self::true_2, + self::true_3, + self::false_1 + ] + ] ); + $this->assertFalse( $strategy->shouldDisplay() ); + } + +} diff --git a/tests/unit/TestPostTypeStrategy.php b/tests/unit/TestPostTypeStrategy.php new file mode 100644 index 0000000..31eb4ca --- /dev/null +++ b/tests/unit/TestPostTypeStrategy.php @@ -0,0 +1,55 @@ +<?php + +namespace unit; + +use PHPUnit\Framework\TestCase; +use WPDesk\ShowDecision\PostTypeStrategy; + + +class TestPostTypeStrategy extends TestCase { + const valid_post_type = 'test_post_type'; + const invalid_post_type = 'invalid'; + + protected function setUp() { + require_once __DIR__ . DIRECTORY_SEPARATOR . 'Stub' . DIRECTORY_SEPARATOR . 'WP_Post.php'; + parent::setUp(); + \WP_Mock::setUp(); + } + + protected function tearDown() { + parent::tearDown(); + \WP_Mock::tearDown(); + } + + public function testFailureWhenTriesUseInvalidPostType() { + $strategy = new PostTypeStrategy( self::invalid_post_type ); + $this->assertFalse( $strategy->shouldDisplay() ); + } + + public function testValidPostTypeUsingGetSuccess() { + $_GET = [ 'post_type' => self::valid_post_type ]; + $strategy = new PostTypeStrategy( self::valid_post_type ); + $this->assertTrue( $strategy->shouldDisplay() ); + } + + public function testValidPostTypeUsingPostIdSuccess() { + $post_id = 123; + $_GET = [ + 'post' => $post_id + ]; + \WP_Mock::userFunction( 'get_post', [ + 'times' => 1, + 'return' => function () use ( $post_id ) { + $post = new \WP_Post(); + $post->ID = $post_id; + $post->post_type = self::valid_post_type; + + return $post; + } + ] ); + + $strategy = new PostTypeStrategy( self::valid_post_type ); + $this->assertTrue( $strategy->shouldDisplay() ); + } + +} diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php new file mode 100644 index 0000000..76b8109 --- /dev/null +++ b/tests/unit/bootstrap.php @@ -0,0 +1,9 @@ +<?php +/** + * PHPUnit bootstrap file + */ + +require_once __DIR__ . '/../../vendor/autoload.php'; + +WP_Mock::setUsePatchwork( true ); +WP_Mock::bootstrap(); -- GitLab