From fa38e10049fabcdb321e9b79618897aaa0950a7e Mon Sep 17 00:00:00 2001 From: Renato Alves <19148962+renatonascalves@users.noreply.github.com> Date: Thu, 9 Nov 2023 21:56:50 -0300 Subject: [PATCH 1/4] Misc: several updates to the plugin --- .editorconfig | 18 ++++++++ .github/workflows/unit-test.yml | 2 +- CHANGELOG.md | 17 +++++++ archiveless.php | 15 ++++-- composer.json | 81 ++++++++++++++++++--------------- inc/assets.php | 37 +++++++-------- inc/class-archiveless.php | 78 ++++++++++++++++--------------- phpstan.neon | 10 ++++ tests/bootstrap.php | 4 +- 9 files changed, 164 insertions(+), 98 deletions(-) create mode 100644 .editorconfig create mode 100644 phpstan.neon diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..3f81e6e6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tab +indent_size = 4 + +[*.{ts,tsx,js,jsx,scss,css,json,yaml,yml,feature,xml}] +indent_style = space +indent_size = 2 + +# Dotfiles +[.*] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c01f03f6..e784ff48 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -12,7 +12,7 @@ jobs: php-tests: strategy: matrix: - php: [8.0] + php: [8.0, 8.1, 8.2] wordpress: ["latest"] uses: alleyinteractive/.github/.github/workflows/php-tests.yml@main with: diff --git a/CHANGELOG.md b/CHANGELOG.md index dc3785c5..ee8f57d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this plugin will be documented in this file. +## 1.1.2 + +- Github Action: Updated matrix to test the following PHP versions: 8.0, 8.1, and 8.2; +- Added `.editorconfig`; +- Composer: upgraded packages; +- PHPStan: added support; +- Bumped the plugin version from `0.2` to `1.1.2`; +- Tested the plugin with the WordPress 6.4. + +## 1.1.1 + +- See + +### 1.1.0 + +- See + ## 1.0.1 - Bug fix from previous use of the archiveless plugin that broke backwards diff --git a/archiveless.php b/archiveless.php index 1ecab71c..9c364534 100644 --- a/archiveless.php +++ b/archiveless.php @@ -3,12 +3,12 @@ * Plugin Name: Archiveless * Plugin URI: https://github.com/alleyinteractive/archiveless * Description: Hide posts from archives performantly - * Version: 0.2 + * Version: 1.1.2 * Author: Alley Interactive - * Author URI: https://alley.co/ + * Author URI: https://alley.com * License: GPL-2.0-or-later * License URI: https://www.gnu.org/licenses/gpl-2.0.html - * Tested up to: 6.2 + * Tested up to: 6.4 * Requires PHP: 8.0 * * @package Archiveless @@ -32,5 +32,10 @@ require_once __DIR__ . '/inc/assets.php'; require_once __DIR__ . '/inc/class-archiveless.php'; -// Add action hook to initialize the plugin. -add_action( 'after_setup_theme', [ 'Archiveless', 'instance' ] ); +// Initialize Archiveless. +add_action( + 'after_setup_theme', + function (): void { + Archiveless::instance(); + } +); diff --git a/composer.json b/composer.json index 9145f00a..0eb5cfec 100644 --- a/composer.json +++ b/composer.json @@ -1,39 +1,48 @@ { - "name": "alleyinteractive/archiveless", - "description": "WordPress plugin to hide posts from archives (lists)", - "homepage": "https://github.com/alleyinteractive/archiveless", - "type": "wordpress-plugin", - "license": "GPL-3.0-or-later", - "authors": [ - { - "name": "Alley", - "email": "info@alley.co" - } - ], - "support": { - "issues": "https://github.com/alleyinteractive/archiveless/issues", - "source": "https://github.com/alleyinteractive/archiveless" - }, - "require-dev": { - "alleyinteractive/alley-coding-standards": "^1.0", - "mantle-framework/testkit": "^0.10" - }, - "config": { - "allow-plugins": { - "alleyinteractive/composer-wordpress-autoloader": true, - "dealerdirect/phpcodesniffer-composer-installer": true - }, - "sort-packages": true - }, - "minimum-stability": "dev", - "prefer-stable": true, - "scripts": { - "phpcbf": "phpcbf .", - "phpcs": "phpcs .", - "phpunit": "phpunit", - "test": [ - "@phpcs", - "@phpunit" - ] + "name": "alleyinteractive/archiveless", + "description": "WordPress plugin to hide posts from archives (lists)", + "keywords": [ + "alleyinteractive", + "archive", + "archiveless" + ], + "homepage": "https://github.com/alleyinteractive/archiveless", + "type": "wordpress-plugin", + "license": "GPL-3.0-or-later", + "authors": [ + { + "name": "Alley Interactive", + "email": "info@alley.com" } + ], + "support": { + "issues": "https://github.com/alleyinteractive/archiveless/issues", + "source": "https://github.com/alleyinteractive/archiveless" + }, + "require-dev": { + "php": "^8.0", + "alleyinteractive/alley-coding-standards": "^2.0", + "mantle-framework/testkit": "^0.12", + "szepeviktor/phpstan-wordpress": "^1.1" + }, + "config": { + "allow-plugins": { + "alleyinteractive/composer-wordpress-autoloader": true, + "dealerdirect/phpcodesniffer-composer-installer": true + }, + "sort-packages": true + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + "phpcbf": "phpcbf .", + "phpcs": "phpcs .", + "phpunit": "phpunit", + "phpstan": "phpstan --memory-limit=512M", + "test": [ + "@phpcs", + "@phpstan", + "@phpunit" + ] + } } diff --git a/inc/assets.php b/inc/assets.php index 0727dd5c..77adf60c 100644 --- a/inc/assets.php +++ b/inc/assets.php @@ -5,6 +5,8 @@ * @package Archiveless */ +declare(strict_types=1); + namespace Archiveless; use Archiveless; @@ -21,7 +23,7 @@ /** * A callback for the enqueue_block_editor_assets action hook. */ -function action_enqueue_block_editor_assets() { +function action_enqueue_block_editor_assets(): void { if ( ! Archiveless::instance()->is_block_editor() ) { return; } @@ -40,10 +42,9 @@ function action_enqueue_block_editor_assets() { * Gets asset dependencies from the generated asset manifest. * * @param string $asset Entry point and asset type separated by a '.'. - * - * @return array An array of dependencies for this asset. + * @return array An array of dependencies for this asset. */ -function get_asset_dependencies( string $asset ) : array { +function get_asset_dependencies( string $asset ): array { // Get the path to the PHP file containing the dependencies. $dependency_file = get_asset_path( $asset, true ); if ( empty( $dependency_file ) ) { @@ -58,6 +59,7 @@ function get_asset_dependencies( string $asset ) : array { // Try to load the dependencies. // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable $dependencies = require $dependency_file; + if ( empty( $dependencies['dependencies'] ) || ! is_array( $dependencies['dependencies'] ) ) { return []; } @@ -69,10 +71,9 @@ function get_asset_dependencies( string $asset ) : array { * Get the contentHash for a given asset. * * @param string $asset Entry point and asset type separated by a '.'. - * * @return string The asset's hash. */ -function get_asset_hash( string $asset ) : string { +function get_asset_hash( string $asset ): string { return get_asset_property( $asset, 'hash' ) ?? ARCHIVELESS_ASSET_MAP['hash'] ?? '1.0.0'; @@ -83,10 +84,9 @@ function get_asset_hash( string $asset ) : string { * * @param string $asset Entry point and asset type separated by a '.'. * @param boolean $dir Optional. Whether to return the directory path or the plugin URL path. Defaults to false (returns URL). - * * @return string The asset URL. */ -function get_asset_path( string $asset, bool $dir = false ) : string { +function get_asset_path( string $asset, bool $dir = false ): string { // Try to get the relative path. $relative_path = get_asset_property( $asset, 'path' ); if ( empty( $relative_path ) ) { @@ -106,19 +106,16 @@ function get_asset_path( string $asset, bool $dir = false ) : string { * * @param string $asset Entry point and asset type separated by a '.'. * @param string $prop The property to get from the entry object. - * * @return string|null The asset property based on entry and type. */ -function get_asset_property( string $asset, string $prop ) : ?string { +function get_asset_property( string $asset, string $prop ): ?string { /* * Appending a '.' ensures the explode() doesn't generate a notice while * allowing the variable names to be more readable via list(). */ list( $entrypoint, $type ) = explode( '.', "$asset." ); - $asset_property = ARCHIVELESS_ASSET_MAP[ $entrypoint ][ $type ][ $prop ] ?? null; - - return $asset_property ? $asset_property : null; + return ARCHIVELESS_ASSET_MAP[ $entrypoint ][ $type ][ $prop ] ?? null; } /** @@ -126,7 +123,7 @@ function get_asset_property( string $asset, string $prop ) : ?string { * * @param string $to_handle The script handle to attach the inline script to. */ -function inline_locale_data( string $to_handle ) { +function inline_locale_data( string $to_handle ): void { // Define locale data for Jed. $locale_data = [ '' => [ @@ -146,14 +143,18 @@ function inline_locale_data( string $to_handle ) { * Decode the asset map at the given file path. * * @param string $path File path. - * - * @return array The asset map. + * @return array The asset map. */ -function read_asset_map( string $path ) : array { +function read_asset_map( string $path ): array { if ( file_exists( $path ) && 0 === validate_file( $path ) ) { ob_start(); include $path; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.IncludingFile, WordPressVIPMinimum.Files.IncludingFile.UsingVariable - return json_decode( ob_get_clean(), true ); + + $retval = json_decode( (string) ob_get_clean(), true ); + + if ( is_array( $retval ) ) { + return $retval; + } } return []; diff --git a/inc/class-archiveless.php b/inc/class-archiveless.php index 7bb35d3c..b6b846b1 100644 --- a/inc/class-archiveless.php +++ b/inc/class-archiveless.php @@ -5,6 +5,8 @@ * @package Archiveless */ +declare(strict_types=1); + /** * The main class for the Archiveless plugin. */ @@ -79,8 +81,8 @@ protected function __construct() { * * @return Archiveless The active instance of the class. */ - public static function instance() { - if ( ! isset( self::$instance ) ) { + public static function instance(): Archiveless { + if ( ! self::$instance instanceof Archiveless ) { self::$instance = new Archiveless(); } return self::$instance; @@ -90,7 +92,7 @@ public static function instance() { * Determine if gutenberg editor exists and * the post type has support for the `custom-fields`. * - * @return boolean + * @return bool */ public function is_block_editor(): bool { $is_block_editor = false; @@ -113,35 +115,36 @@ public function is_block_editor(): bool { /** * Register the custom post status. + * + * @see register_post_status(). */ - public function register_post_status() { + public function register_post_status(): void { /** * Filters the arguments passed to `register_post_status()`. * - * @see register_post_status(). + * @param array $args The arguments passed to `register_post_status()`. */ - register_post_status( - self::$status, - apply_filters( - 'archiveless_post_status_args', - [ - 'label' => __( 'Hidden from Archives', 'archiveless' ), - // translators: post count. - 'label_count' => _n_noop( 'Hidden from Archives (%s)', 'Hidden from Archives (%s)', 'archiveless' ), - 'exclude_from_search' => true, - 'public' => true, - 'publicly_queryable' => true, - 'show_in_admin_status_list' => true, - 'show_in_admin_all_list' => true, - ] - ) + $args = apply_filters( + 'archiveless_post_status_args', + [ + 'label' => __( 'Hidden from Archives', 'archiveless' ), + // translators: post count. + 'label_count' => _n_noop( 'Hidden from Archives (%s)', 'Hidden from Archives (%s)', 'archiveless' ), + 'exclude_from_search' => true, + 'public' => true, + 'publicly_queryable' => true, + 'show_in_admin_status_list' => true, + 'show_in_admin_all_list' => true, + ] ); + + register_post_status( self::$status, $args ); } /** * Register the custom post meta. */ - public function register_post_meta() { + public function register_post_meta(): void { register_post_meta( '', self::$meta_key, @@ -157,8 +160,10 @@ public function register_post_meta() { /** * Add the checkbox to the post edit screen to give the option to hide a * post from archives. + * + * @global WP_Post $post The current post object. */ - public function add_ui() { + public function add_ui(): void { global $post; // Ensure there is a post ID before attempting to look up postmeta. @@ -186,7 +191,7 @@ public function add_ui() { * @param string $meta_key Metadata key. * @param mixed $meta_value Metadata value. Serialized if non-scalar. */ - public function updated_post_meta( $meta_id, $object_id, $meta_key, $meta_value ) { + public function updated_post_meta( $meta_id, $object_id, $meta_key, $meta_value ): void { // Only handle updates to this plugin's meta key. if ( self::$meta_key !== $meta_key ) { return; @@ -225,10 +230,8 @@ public function updated_post_meta( $meta_id, $object_id, $meta_key, $meta_value /** * Add a filter to all post types for REST response modification. - * - * @return void */ - public function filter_rest_response() { + public function filter_rest_response(): void { // Override the post status in the REST response to avoid Gutenbugs. foreach ( get_post_types() as $allowed_post_type ) { add_filter( 'rest_prepare_' . $allowed_post_type, [ $this, 'rest_prepare_post_data' ] ); @@ -241,7 +244,7 @@ public function filter_rest_response() { * @param WP_REST_Response $response The response object. * @return WP_REST_Response The modified response. */ - public function rest_prepare_post_data( $response ) { + public function rest_prepare_post_data( $response ): WP_REST_Response { // Override the post status if it is 'archiveless'. if ( ! empty( $response->data['status'] ) && self::$status === $response->data['status'] ) { $response->data['status'] = 'publish'; @@ -257,7 +260,7 @@ public function rest_prepare_post_data( $response ) { * @param string $old_status Old post status. * @param WP_Post $post Post object. */ - public function transition_post_status( $new_status, $old_status, $post ) { + public function transition_post_status( $new_status, $old_status, $post ): void { // Only fire if transitioning to publish. if ( 'publish' !== $new_status || $new_status === $old_status ) { return; @@ -270,15 +273,16 @@ public function transition_post_status( $new_status, $old_status, $post ) { // Change the post status to `archiveless` and update. $post->post_status = self::$status; + wp_update_post( $post ); } /** * Store the value of the "Hide form Archives" checkbox to post meta. * - * @param int $post_id Post ID. + * @param int $post_id Post ID. */ - public function save_post( $post_id ) { + public function save_post( $post_id ): void { // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( isset( $_POST[ self::$meta_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing @@ -290,8 +294,10 @@ public function save_post( $post_id ) { * Fool the edit screen into thinking that an archiveless post status is * actually 'publish'. This lets WordPress use its hard-coded post statuses * seamlessly. + * + * @global WP_Post $post The current post object. */ - public function fool_edit_form() { + public function fool_edit_form(): void { global $post; // Ensure there is a post status before attempting to set it. @@ -310,9 +316,9 @@ public function fool_edit_form() { * Optionally allow archiveless posts to be hidden for other queries by * passing 'exclude_archiveless'. * - * @param \WP_Query $query Current WP_Query object. + * @param WP_Query $query Current WP_Query object. */ - public function on_pre_get_posts( $query ) { + public function on_pre_get_posts( $query ): void { // Ignore all post previews. if ( $query->is_preview() || $query->get( 'p' ) ) { return; @@ -376,10 +382,10 @@ public function on_pre_get_posts( $query ) { * Retrieve the default post statuses to show for a request. * Imitates the default behavior of WP_Query. * - * @param \WP_Query $query Current WP_Query object. + * @param WP_Query $query Current WP_Query object. * @return string[] */ - public function get_default_post_statuses( $query ) { + public function get_default_post_statuses( $query ): array { $post_statuses = $query->get( 'post_status', [] ); if ( ! is_array( $post_statuses ) ) { @@ -404,7 +410,7 @@ public function get_default_post_statuses( $query ) { * Output noindex meta tag to prevent search engines from indexing archiveless * posts. */ - public function on_wp_head() { + public function on_wp_head(): void { if ( ! is_singular() || ! static::is() ) { return; } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..070c6f3b --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,10 @@ +includes: + - vendor/szepeviktor/phpstan-wordpress/extension.neon + +parameters: + # Level 9 is the highest level + level: max + + paths: + - inc/ + - archiveless.php diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f032e583..011f29dd 100755 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -9,10 +9,10 @@ ->maybe_rsync_plugin() ->loaded( function () { - require_once __DIR__ . '/../archiveless.php'; - // switch_theme( 'twentytwentytwo' ); // Set the permalink structure. update_option( 'permalink_structure', '/%year%/%monthnum%/%day%/%postname%/' ); + + require_once __DIR__ . '/../archiveless.php'; } ) ->install(); From 59001e87c48254a698f19fa849b19d1b049673c8 Mon Sep 17 00:00:00 2001 From: Renato Alves <19148962+renatonascalves@users.noreply.github.com> Date: Thu, 9 Nov 2023 21:59:17 -0300 Subject: [PATCH 2/4] Misc: more changelog updates --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8f57d5..a96347e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,10 @@ All notable changes to this plugin will be documented in this file. - Composer: upgraded packages; - PHPStan: added support; - Bumped the plugin version from `0.2` to `1.1.2`; -- Tested the plugin with the WordPress 6.4. +- Tested the plugin with the WordPress 6.4; +- Use `declare(strict_types=1);`, when possible; +- Update Alley domain to `https://alley.com`; + ## 1.1.1 From db508861e8065eb3fafba1c86ac54b9408a54403 Mon Sep 17 00:00:00 2001 From: Benjamin Bolton <7146063+benpbolton@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:46:33 -0700 Subject: [PATCH 3/4] Attempt to trigger github workflow From cac3e30a3e373c7ca2dad110c7776b1e17ef5b3e Mon Sep 17 00:00:00 2001 From: Benjamin Bolton <7146063+benpbolton@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:00:22 -0700 Subject: [PATCH 4/4] Attempt to trigger github workflow