diff --git a/.drone.yml b/.drone.yml index a9e824b..4cac679 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,24 +1,17 @@ kind: pipeline name: default - -clone: - disable: true +type: docker steps: -- name: clone - image: plugins/git - settings: - depth: 10 - skip_verify: true -- name: pre-build - image: composer - commands: - - composer install -- name: test - image: composer - commands: - - ./vendor/bin/robo test -- name: test-style - image: composer - commands: - - ./vendor/bin/robo test:cs + - name: pre-build + image: composer + commands: + - composer install + - name: test + image: composer + commands: + - composer test + - name: lint + image: composer + commands: + - composer lint-php diff --git a/.eslintrc.json b/.eslintrc.json index 88304e7..95e51b8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,25 @@ { - "extends": "./vendor/npm-asset/eslint-config-wordpress/index.js" + "env": { + "es6": false, + "browser": true + }, + "globals": { + "sclivetickerAjax": "readonly", + "wp": "readonly" + }, + "extends": [ + "plugin:@wordpress/eslint-plugin/recommended", + "plugin:@wordpress/eslint-plugin/es5" + ], + "overrides": [ + { + "files": [ + "*" + ], + "rules": { + "no-var": "off", + "object-shorthand": "off" + } + } + ] } diff --git a/.gitignore b/.gitignore index 1ba8b01..2502359 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ composer.lock +package-lock.json /vendor/ /node_modules/ /dist/ .idea +.phpunit.result.cache **/*.min.css **/*.min.js diff --git a/.travis.yml b/.travis.yml index ac604a3..ec2cff1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,14 @@ language: php -dist: trusty php: -- '5.5' -- '5.6' -- '7.0' -- '7.1' - '7.2' - '7.3' +- '7.4' before_script: - composer install +- npm install script: -- composer test-all +- composer test +- composer lint-all notifications: slack: secure: "R40BhRCETuDule7lz4oGN+qyLvd7dBmuEu6hVELNhWg3DgCgYOXyrWR2dgxsWsAZ3sldpWGfTJKzSShdDanGCpygpYzuvXxjt23YYJ2ihrohYJwiGIhkR9c24LF2yvWBQDBNZaeLBQ3o6FSnbkTBsmRy5ShgKehfKCOQTKmI1yWHi3fvkMElTorrJc710O41yy/bRKBnoIYd4ZfpLMSSVGCPzR5lZPZy3EiGWXPgYdY7jGMI7ADsy+T5VWHyFqgSSJz/U2bcryKzF08FAry8pyu9lN3r61kXHfVCCJX+kcsFxW9yCfuPLnLu14O776y3U6zrX9is+8mEfkMuTXFaL5o8+iq32AmFjTIDQn6o9BKHsknfmppjwZiLgFTp1T7Z/XR6I4nyK9Z5HXDU2HS0eCUknbgXlMLhxWpKhkyx4rQELuvVlgD+u7yRYraawc3v1ycqaPj0S0G5QBFljSuxsZgNnX1hs8VmgafIvOq5qm4ZVVBhhbz+LgvW1m9COr8DDPVhWWdpcWzF8jtkqC3m4Q/1Ssc6T/MbJMgcXRq/C4DlfEs4aYGYfSl7gLtF2PwlEQCppKJwx0fEPkcbZZ1PjpzF+JMwwRmWS88R0oRyThOyCwlG50c+ktB94pJC+sP1aQZrLAd4WDKUPD9vJTas86V3XBjTUJPs8HQaBDFqFdg=" diff --git a/README.md b/README.md index 0e5d07b..34edf67 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [](https://travis-ci.org/stklcode/wp-liveticker) [](https://sonarcloud.io/dashboard?id=de.stklcode.web.wordpress.plugins%3Awp-liveticker) +[](https://wordpress.org/plugins/stklcode-liveticker/) [](https://packagist.org/packages/stklcode/stklcode-liveticker) [](https://github.com/stklcode/wp-liveticker/blob/master/LICENSE.md) @@ -8,8 +9,8 @@ * Contributors: Stefan Kalscheuer * Tags: liveticker, feed, rss * Requires at least: 4.0 -* Tested up to: 5.3 -* Requires PHP: 5.2 +* Tested up to: 5.4 +* Requires PHP: 5.6 * Stable tag: 1.0.0 * License: GPLv2 or later * License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -26,9 +27,9 @@ Easily add multiple livetickers, add them to posts with shortcode or use them as * Handle multiple Tickers * Automatic update via AJAX * RSS feed capability -* Shortcode to display liveticker +* Gutenberg block and shortcode to display liveticker * Add ticker to sidebar widgets -* Ability to customise through CSS +* Ability to customize through CSS * Localization support @@ -47,7 +48,9 @@ Easily add multiple livetickers, add them to posts with shortcode or use them as ### How do I display a liveticker on my post/page? -Use the shortcode `[liveticker ticker="my-ticker"]`. +On WordPress 5 sites there is a Gutenberg Block available to embed a liveticker in your post. + +You can also use the shortcode `[liveticker ticker="my-ticker"]` on WordPress 4 or classic-mode sites. If you want to define a custom tick limit, you might also add a limit with `[liveticker ticker="my-ticker" limit="10"]`. ### Can I use my own styles? @@ -57,9 +60,11 @@ You can deactivate the default stylesheet on the settings page and include your ### Does the liveticker work with caching? -It strongly depends on the use case. -If you update your ticker every 5 minutes, a caching time of 12 hours obviously makes no sense. -However the AJAX update will fetch the latest ticks and update cached tickers depending on the configured interval. +If you activate AJAX updates (enabled by default), the JavaScript will automatically update the content, even when the +page is loaded from cached. + +If AJAX is disabled, it depends on your update and caching intervals. If you update your ticker every 5 minutes, a +caching time of 12 hours obviously makes no sense. ## Screenshots @@ -68,11 +73,18 @@ However the AJAX update will fetch the latest ticks and update cached tickers d 2. Tick management 3. Ticker configuration. 4. Settings page -5. Example shortcode -6. Example widget +5. Gutenberg block +6. Example shortcode +7. Example widget ## Changelog +### 1.1.0 - unreleased + +* Requires PHP 5.6 or above +* Use GMT for automatic updates +* Gutenberg Block available + ### 1.0.0 - 2018-11-02 * Initial release diff --git a/RoboFile.php b/RoboFile.php index ddce5a9..36929f6 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -26,6 +26,7 @@ class RoboFile extends Tasks { const OPT_SKIPTEST = 'skipTests'; const OPT_SKIPSTYLE = 'skipStyle'; const OPT_MINIFY = 'minify'; + const OPT_NODE = 'node'; /** * Version tag (read from composer.json). @@ -94,11 +95,31 @@ class RoboFile extends Tasks { /** * Run code style tests * + * @param array $opts Options. + * * @return void */ - public function testCS() { - $this->say( 'Executing PHPCS tests...' ); + public function testCS( + $opts = array( + self::OPT_TARGET => 'dist', + self::OPT_SKIPTEST => false, + self::OPT_SKIPSTYLE => false, + self::OPT_MINIFY => true, + self::OPT_NODE => false, + ) + ) { + $this->say( 'Executing PHPCS...' ); $this->_exec( __DIR__ . '/vendor/bin/phpcs --standard=phpcs.xml -s' ); + + if ( $opts[ self::OPT_NODE ] ) { + $this->say( 'Executing ESLint...' ); + $this->_exec( __DIR__ . '/node_modules/eslint/bin/eslint.js ' . __DIR__ . '/scripts/block.js' ); + $this->_exec( __DIR__ . '/node_modules/eslint/bin/eslint.js ' . __DIR__ . '/scripts/liveticker.js' ); + + $this->say( 'Executing StyleLint...' ); + $this->_exec( __DIR__ . '/node_modules/stylelint/bin/stylelint.js ' . __DIR__ . '/styles/block.css' ); + $this->_exec( __DIR__ . '/node_modules/stylelint/bin/stylelint.js ' . __DIR__ . '/styles/liveticker.css' ); + } } /** @@ -114,6 +135,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { $this->clean( $opts ); @@ -125,7 +147,7 @@ class RoboFile extends Tasks { if ( isset( $opts[ self::OPT_SKIPSTYLE ] ) && true === $opts[ self::OPT_SKIPSTYLE ] ) { $this->say( 'Style checks skipped' ); } else { - $this->testCS(); + $this->testCS( $opts ); } $this->bundle(); } @@ -137,21 +159,23 @@ class RoboFile extends Tasks { */ private function bundle() { $this->say( 'Bundling resources...' ); - $this->taskCopyDir( array( - 'includes' => $this->target_dir . '/' . $this->final_name . '/includes', - 'scripts' => $this->target_dir . '/' . $this->final_name . '/scripts', - 'styles' => $this->target_dir . '/' . $this->final_name . '/styles', - 'views' => $this->target_dir . '/' . $this->final_name . '/views', - ) )->run(); + $this->taskCopyDir( + array( + 'includes' => $this->target_dir . '/' . $this->final_name . '/includes', + 'scripts' => $this->target_dir . '/' . $this->final_name . '/scripts', + 'styles' => $this->target_dir . '/' . $this->final_name . '/styles', + 'views' => $this->target_dir . '/' . $this->final_name . '/views', + ) + )->run(); $this->_copy( 'stklcode-liveticker.php', $this->target_dir . '/' . $this->final_name . '/stklcode-liveticker.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' ); // Remove content before title (e.g. badges) from README file. $this->taskReplaceInFile( $this->target_dir . '/' . $this->final_name . '/README.md' ) - ->regex( '/^[^\\#]*/' ) - ->to( '' ) - ->run(); + ->regex( '/^[^\\#]*/' ) + ->to( '' ) + ->run(); } /** @@ -190,6 +214,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { if ( ! isset( $opts[ self::OPT_MINIFY ] ) ) { @@ -224,6 +249,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { if ( ! isset( $opts[ self::OPT_MINIFY ] ) ) { @@ -259,6 +285,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { $this->build( $opts ); @@ -282,6 +309,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { // First execute build job. @@ -315,6 +343,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { // First execute build job. @@ -348,6 +377,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { // First execute build job. @@ -380,6 +410,7 @@ class RoboFile extends Tasks { self::OPT_SKIPTEST => false, self::OPT_SKIPSTYLE => false, self::OPT_MINIFY => true, + self::OPT_NODE => false, ) ) { // First execute build job. diff --git a/assets/screenshot-2.png b/assets/screenshot-2.png index 4ec4d01..5bf1394 100644 Binary files a/assets/screenshot-2.png and b/assets/screenshot-2.png differ diff --git a/assets/screenshot-3.png b/assets/screenshot-3.png index fa10f08..6343231 100644 Binary files a/assets/screenshot-3.png and b/assets/screenshot-3.png differ diff --git a/assets/screenshot-4.png b/assets/screenshot-4.png index 03ceded..bfe643e 100644 Binary files a/assets/screenshot-4.png and b/assets/screenshot-4.png differ diff --git a/assets/screenshot-5.png b/assets/screenshot-5.png index d64e7ef..4f6ddaf 100644 Binary files a/assets/screenshot-5.png and b/assets/screenshot-5.png differ diff --git a/assets/screenshot-6.png b/assets/screenshot-6.png index 445dfd8..d64e7ef 100644 Binary files a/assets/screenshot-6.png and b/assets/screenshot-6.png differ diff --git a/assets/screenshot-7.png b/assets/screenshot-7.png new file mode 100644 index 0000000..445dfd8 Binary files /dev/null and b/assets/screenshot-7.png differ diff --git a/composer.json b/composer.json index e2f9550..03e6b8a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "stklcode/stklcode-liveticker", - "version": "1.0.0", + "version": "1.1.0-alpha", "description": "A simple Liveticker for Wordpress.", "keywords": [ "wordpress", @@ -17,23 +17,22 @@ ], "type": "wordpress-plugin", "require": { - "php": ">=5.2", + "php": ">=5.6", "composer/installers": "~1.7" }, "require-dev": { - "php": ">=5.2", - "consolidation/robo": "^1.4", - "phpunit/phpunit": "*", - "phpunit/php-code-coverage": "*", - "dealerdirect/phpcodesniffer-composer-installer": "^0.5", + "php": ">=7", + "consolidation/robo": "^2", + "phpunit/phpunit": "^8", + "phpunit/php-code-coverage": "^7", + "dealerdirect/phpcodesniffer-composer-installer": "^0.6", "slowprog/composer-copy-file": "~0.3", - "squizlabs/php_codesniffer": "^3.4", - "phpcompatibility/php-compatibility": "^9.2", - "wp-coding-standards/wpcs": "^2.1", + "squizlabs/php_codesniffer": "^3.5", + "phpcompatibility/php-compatibility": "^9.3", + "wp-coding-standards/wpcs": "^2.2", "patchwork/jsqueeze": "^2.0", "natxet/cssmin": "^3.0", - "matthiasmullie/minify": "^1.3", - "npm-asset/eslint-config-wordpress": "^2.0" + "matthiasmullie/minify": "^1.3" }, "scripts": { "post-install-cmd": [ @@ -54,28 +53,30 @@ "@minify", "robo deploy:all" ], - "test-all": [ - "@test", - "@test-cs" - ], "test": [ "phpunit" ], - "test-cs": [ + "lint-all": [ + "@lint-php", + "@lint-css", + "@lint-js" + ], + "lint-php": [ "phpcs --standard=phpcs.xml -s" ], - "fix-cs": [ - "phpcbf --standard=phpcs.xml" + "lint-css": [ + "./node_modules/stylelint/bin/stylelint.js styles/block.css", + "./node_modules/stylelint/bin/stylelint.js styles/liveticker.css" + ], + "lint-js": [ + "./node_modules/eslint/bin/eslint.js scripts/block.js", + "./node_modules/eslint/bin/eslint.js scripts/liveticker.js" ], "minify": [ + "minifycss styles/block.css > styles/block.min.css", "minifycss styles/liveticker.css > styles/liveticker.min.css", + "minifyjs scripts/block.js > scripts/block.min.js", "minifyjs scripts/liveticker.js > scripts/liveticker.min.js" ] - }, - "repositories": [ - { - "type": "composer", - "url": "https://asset-packagist.org" - } - ] + } } diff --git a/includes/class-scliveticker-admin.php b/includes/class-admin.php similarity index 89% rename from includes/class-scliveticker-admin.php rename to includes/class-admin.php index 4a56989..3d89bfd 100644 --- a/includes/class-scliveticker-admin.php +++ b/includes/class-admin.php @@ -4,9 +4,11 @@ * * This file contains the derived class for the plugin's administration features. * - * @package Liveticker + * @package SCLiveticker */ +namespace SCLiveticker; + // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; @@ -15,7 +17,7 @@ if ( ! defined( 'ABSPATH' ) ) { /** * Liveticker admin configuration. */ -class SCLiveticker_Admin extends SCLiveticker { +class Admin extends SCLiveticker { /** * Add to Right Now Widget * @@ -202,4 +204,35 @@ class SCLiveticker_Admin extends SCLiveticker { return $result; } + + /** + * Register custom Gutenberg block type. + * + * @return void + * @since 1.1 + */ + public static function register_block() { + wp_register_script( + 'scliveticker-editor', + SCLIVETICKER_BASE . 'scripts/block.min.js', + array( 'wp-blocks', 'wp-element' ), + self::VERSION, + true + ); + + wp_register_style( + 'scliveticker-editor', + SCLIVETICKER_BASE . 'styles/block.min.css', + array(), + self::VERSION + ); + + register_block_type( + 'scliveticker-block/liveticker', + array( + 'editor_script' => 'scliveticker-editor', + 'editor_style' => 'scliveticker-editor', + ) + ); + } } diff --git a/includes/class-scliveticker.php b/includes/class-scliveticker.php index d97b6d8..b398c12 100644 --- a/includes/class-scliveticker.php +++ b/includes/class-scliveticker.php @@ -4,14 +4,19 @@ * * This file contains the plugin's base class. * - * @package Liveticker + * @package SCLiveticker */ +namespace SCLiveticker; + +use WP_Query; + // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } + /** * Liveticker. */ @@ -21,7 +26,7 @@ class SCLiveticker { * * @var string OPTIONS */ - const VERSION = '1.0.0'; + const VERSION = '1.1.0-alpha'; /** * Options tag. @@ -80,11 +85,8 @@ class SCLiveticker { // Add shortcode. add_shortcode( 'liveticker', array( __CLASS__, 'shortcode_ticker_show' ) ); - // Enqueue styles. - add_action( 'wp_footer', array( __CLASS__, 'enqueue_styles' ) ); - - // Enqueue JavaScript. - add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts' ) ); + // Enqueue styles and JavaScript. + add_action( 'wp_footer', array( __CLASS__, 'enqueue_resources' ) ); // Add AJAX hook if configured. if ( 1 === self::$options['enable_ajax'] ) { @@ -95,11 +97,11 @@ class SCLiveticker { // Admin only actions. if ( is_admin() ) { // Add dashboard "right now" functionality. - add_action( 'right_now_content_table_end', array( 'SCLiveticker_Admin', 'dashboard_right_now' ) ); + add_action( 'right_now_content_table_end', array( 'SCLiveticker\\Admin', 'dashboard_right_now' ) ); // Settings. - add_action( 'admin_init', array( 'SCLiveticker_Admin', 'register_settings' ) ); - add_action( 'admin_menu', array( 'SCLiveticker_Admin', 'register_settings_page' ) ); + add_action( 'admin_init', array( 'SCLiveticker\\Admin', 'register_settings' ) ); + add_action( 'admin_menu', array( 'SCLiveticker\\Admin', 'register_settings_page' ) ); } } @@ -133,6 +135,7 @@ class SCLiveticker { 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, + 'show_in_rest' => true, ) ); @@ -198,14 +201,14 @@ class SCLiveticker { $show_feed = 1 === self::$options['show_feed']; } - $output = '