diff --git a/.github/actions/code-quality/action.yml b/.github/actions/code-quality/action.yml new file mode 100644 index 00000000..d67ff17e --- /dev/null +++ b/.github/actions/code-quality/action.yml @@ -0,0 +1,36 @@ +name: 'PHP Code Quality' +description: 'Sets up PHP and runs code quality tools' +inputs: + working-directory: + description: 'Directory to run composer and quality tools in' + required: true +runs: + using: "composite" + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + tools: composer:v2 + coverage: none + + - name: Install dependencies + uses: ramsey/composer-install@v2 + with: + working-directory: ${{ inputs.working-directory }} + composer-options: "--no-progress" + + - name: Run PHPStan + working-directory: ${{ inputs.working-directory }} + run: composer run-script phpstan + shell: bash + + - name: Run Psalm + working-directory: ${{ inputs.working-directory }} + run: composer run-script php:psalm + shell: bash + + - name: Run PHP CodeSniffer + working-directory: ${{ inputs.working-directory }} + run: composer run-script check-cs + shell: bash \ No newline at end of file diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 00000000..80275d2d --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,27 @@ +name: Code Quality + +on: + pull_request: + paths: + - 'plugins/**' + +jobs: + run: + runs-on: ubuntu-latest + name: Check code quality + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get changed plugin directory + id: plugin + run: | + git fetch --prune --unshallow + plugin=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep '^plugins/' | head -1 | cut -d/ -f2) + echo "slug=$plugin" >> $GITHUB_OUTPUT + + - name: PHP Code Quality + uses: ./.github/actions/code-quality + with: + working-directory: plugins/${{ steps.plugin.outputs.slug }} \ No newline at end of file diff --git a/plugins/hwp-previews/ACTIONS_AND_FILTERS.md b/plugins/hwp-previews/ACTIONS_AND_FILTERS.md index 134fbcbf..492fc9e0 100644 --- a/plugins/hwp-previews/ACTIONS_AND_FILTERS.md +++ b/plugins/hwp-previews/ACTIONS_AND_FILTERS.md @@ -16,7 +16,7 @@ - `hwp_previews_settings_group_settings_group` - Filter to modify the settings group name. Default is HWP_PREVIEWS_SETTINGS_GROUP - `hwp_previews_settings_group_settings_config` - Filter to modify the settings array. See `Settings_Group` - `hwp_previews_settings_group_cache_groups` - Filter to modify cache groups for `Settings_Group` -- `hwp_preview_get_post_types_config` - Filter for generating the instance of `Post_Types_Config_Interface` +- `hwp_previews_get_post_types_config` - Filter for generating the instance of `Post_Types_Config_Interface` - `hwp_previews_hooks_post_type_config` - Filter for post type config service for the Hook class - `hwp_previews_hooks_post_status_config` - Filter for post status config service for the Hook class - `hwp_previews_hooks_preview_link_service` - Filter for preview link service for the Hook class diff --git a/plugins/hwp-previews/composer.json b/plugins/hwp-previews/composer.json index 993d4d80..801bc2bf 100644 --- a/plugins/hwp-previews/composer.json +++ b/plugins/hwp-previews/composer.json @@ -50,7 +50,7 @@ } }, "archive": { - "name": "hwp-previews", + "name": "hwp-previews", "exclude": [ "/.*", "bin", @@ -100,9 +100,9 @@ "phpstan": [ "vendor/bin/phpstan analyze --ansi --memory-limit=1G" ], - "psalm": [ - "vendor/bin/psalm --no-progress --show-info=false" - ] + "php:psalm": "psalm", + "php:psalm:info": "psalm --show-info=true", + "php:psalm:fix": "psalm --alter" }, "scripts-descriptions": { }, diff --git a/plugins/hwp-previews/composer.lock b/plugins/hwp-previews/composer.lock index 2aae8e21..bc8be856 100644 --- a/plugins/hwp-previews/composer.lock +++ b/plugins/hwp-previews/composer.lock @@ -1031,16 +1031,16 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.8.0", + "version": "v6.8.1", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "1824db4d1d00d32c0119175d2369d9425dbc4953" + "reference": "92e444847d94f7c30f88c60004648f507688acd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/1824db4d1d00d32c0119175d2369d9425dbc4953", - "reference": "1824db4d1d00d32c0119175d2369d9425dbc4953", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/92e444847d94f7c30f88c60004648f507688acd5", + "reference": "92e444847d94f7c30f88c60004648f507688acd5", "shasum": "" }, "conflict": { @@ -1048,7 +1048,7 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "nikic/php-parser": "^4.13", + "nikic/php-parser": "^5.4", "php": "^7.4 || ^8.0", "php-stubs/generator": "^0.8.3", "phpdocumentor/reflection-docblock": "^5.4.1", @@ -1076,9 +1076,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.0" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.1" }, - "time": "2025-04-17T15:13:53+00:00" + "time": "2025-05-02T12:33:34+00:00" }, { "name": "php-stubs/wp-cli-stubs", diff --git a/plugins/hwp-previews/hwp-previews.php b/plugins/hwp-previews/hwp-previews.php index f4f16fae..f1a428e8 100644 --- a/plugins/hwp-previews/hwp-previews.php +++ b/plugins/hwp-previews/hwp-previews.php @@ -19,8 +19,9 @@ * @package HWP\Previews */ -declare( strict_types=1 ); +declare(strict_types=1); +use HWP\Previews\Autoloader; use HWP\Previews\Plugin; if ( ! defined( 'ABSPATH' ) ) { @@ -29,17 +30,19 @@ // Load the autoloader. require_once __DIR__ . '/src/Autoloader.php'; -if ( ! \HWP\Previews\Autoloader::autoload() ) { +if ( ! Autoloader::autoload() ) { return; } if ( file_exists( __DIR__ . '/activation.php' ) ) { require_once __DIR__ . '/activation.php'; + // @phpstan-ignore-next-line register_activation_hook( __FILE__, 'hwp_previews_activation_callback' ); } if ( file_exists( __DIR__ . '/deactivation.php' ) ) { require_once __DIR__ . '/deactivation.php'; + // @phpstan-ignore-next-line register_deactivation_hook( __FILE__, 'hwp_previews_deactivation_callback' ); } @@ -47,44 +50,23 @@ * Define plugin constants. */ function hwp_previews_constants(): void { - // Plugin version. - if ( ! defined( 'HWP_PREVIEWS_VERSION' ) ) { - define( 'HWP_PREVIEWS_VERSION', '0.0.1' ); - } - - // Plugin Folder Path. - if ( ! defined( 'HWP_PREVIEWS_PLUGIN_DIR' ) ) { - define( 'HWP_PREVIEWS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); - } - - // Plugin Folder URL. - if ( ! defined( 'HWP_PREVIEWS_PLUGIN_URL' ) ) { - define( 'HWP_PREVIEWS_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); - } - - // Plugin Root File. - if ( ! defined( 'HWP_PREVIEWS_PLUGIN_FILE' ) ) { - define( 'HWP_PREVIEWS_PLUGIN_FILE', __FILE__ ); - } - - // Whether to autoload the files or not. - if ( ! defined( 'HWP_PREVIEWS_AUTOLOAD' ) ) { - define( 'HWP_PREVIEWS_AUTOLOAD', true ); - } - - // Text Domain - if ( ! defined( 'HWP_PREVIEWS_TEXT_DOMAIN' ) ) { - define( 'HWP_PREVIEWS_TEXT_DOMAIN', 'hwp-previews' ); - } - - // Plugin config settings group - if ( ! defined( 'HWP_PREVIEWS_SETTINGS_GROUP' ) ) { - define( 'HWP_PREVIEWS_SETTINGS_GROUP', 'hwp_previews_settings_group' ); - } - - // Plugin config settings key. - if ( ! defined( 'HWP_PREVIEWS_SETTINGS_KEY' ) ) { - define( 'HWP_PREVIEWS_SETTINGS_KEY', 'hwp_previews_settings' ); + $constants = [ + 'HWP_PREVIEWS_VERSION' => '0.0.1', + 'HWP_PREVIEWS_PLUGIN_DIR' => plugin_dir_path( __FILE__ ), + 'HWP_PREVIEWS_PLUGIN_URL' => plugin_dir_url( __FILE__ ), + 'HWP_PREVIEWS_PLUGIN_FILE' => __FILE__, + 'HWP_PREVIEWS_AUTOLOAD' => true, + 'HWP_PREVIEWS_SETTINGS_GROUP' => 'hwp_previews_settings_group', + 'HWP_PREVIEWS_SETTINGS_KEY' => 'hwp_previews_settings', + 'HWP_PREVIEWS_TEXT_DOMAIN' => 'hwp-previews', + ]; + + foreach ( $constants as $name => $value ) { + if ( ! defined( $name ) ) { + // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound + define( $name, $value ); + // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound + } } // Plugin Template Directory. @@ -99,7 +81,6 @@ function hwp_previews_constants(): void { function hwp_previews_init(): void { hwp_previews_constants(); - if ( defined( 'HWP_PREVIEWS_PLUGIN_DIR' ) ) { require_once HWP_PREVIEWS_PLUGIN_DIR . 'src/Plugin.php'; Plugin::instance(); @@ -110,14 +91,12 @@ function hwp_previews_init(): void { add_action( 'admin_notices', - static function () { + static function (): void { ?>

@@ -128,5 +107,14 @@ static function () { ); } +/** + * Load plugin textdomain. + */ +function hwp_previews_load_textdomain(): void { + load_plugin_textdomain( 'hwp-previews', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); +} + +add_action( 'init', 'hwp_previews_load_textdomain', 1, 0 ); + /** @psalm-suppress HookNotFound */ -add_action( 'plugins_loaded', 'hwp_previews_init', 15 ); +add_action( 'plugins_loaded', 'hwp_previews_init', 15, 0 ); diff --git a/plugins/hwp-previews/phpstan.neon.dist b/plugins/hwp-previews/phpstan.neon.dist index a14601d5..5681561c 100644 --- a/plugins/hwp-previews/phpstan.neon.dist +++ b/plugins/hwp-previews/phpstan.neon.dist @@ -29,8 +29,9 @@ parameters: max: 80400 paths: - hwp-previews.php - - vendor/autoload.php - src/ ignoreErrors: + - identifier: empty.notAllowed - - identifier: empty.notAllowed + message: '#Constant HWP_PREVIEWS.* not found\.#' + diff --git a/plugins/hwp-previews/psalm.xml b/plugins/hwp-previews/psalm.xml index 97817e2e..3405dd85 100644 --- a/plugins/hwp-previews/psalm.xml +++ b/plugins/hwp-previews/psalm.xml @@ -9,12 +9,26 @@ findUnusedCode="false" > - - - + + + - + + + + + + + + + + + + + + + diff --git a/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Group.php b/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Group.php index 0ec93dbf..8cbd36c8 100644 --- a/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Group.php +++ b/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Group.php @@ -1,22 +1,40 @@ + */ protected array $settings_config = []; + /** + * The settings helper instance. + * + * @var \HWP\Previews\Admin\Settings\Helper\Settings_Group|null + */ + protected static $instance = null; + + /** + * Class initializer. + */ public function __construct() { $this->option_key = $this->get_option_key(); $this->settings_group = $this->get_settings_group(); @@ -24,64 +42,72 @@ public function __construct() { $this->set_cache_group(); } - protected function get_option_key(): string { - return apply_filters( 'hwp_previews_settings_group_option_key', HWP_PREVIEWS_SETTINGS_KEY ); - } + /** + * Get Singleton instance of the Settings_Group class. + */ + public static function get_instance(): self { - protected function get_settings_group(): string { - return apply_filters( 'hwp_previews_settings_group_settings_group', HWP_PREVIEWS_SETTINGS_GROUP ); - } + $instance = self::$instance; + + if ( $instance instanceof self ) { + return $instance; + } + + self::$instance = new self(); + return self::$instance; + } + /** + * Setting key for the enabled status. + */ public function get_settings_key_enabled(): string { return 'enabled'; } + /** + * Setting key for unique post slugs. + */ public function get_settings_key_unique_post_slugs(): string { return 'unique_post_slugs'; } + /** + * Setting key for post-statuses as parent. + */ public function get_settings_key_post_statuses_as_parent(): string { return 'post_statuses_as_parent'; } + /** + * Setting key for the preview URL. + */ public function get_settings_key_preview_url(): string { return 'preview_url'; } + /** + * Setting key for is the preview in an iframe. + */ public function get_settings_key_in_iframe(): string { return 'in_iframe'; } + /** + * Gets the settings configuration for the settings group. + * + * @return array The settings configuration. + */ public function get_settings_config(): array { return apply_filters( 'hwp_previews_settings_group_settings_config', [ - $this->get_settings_key_enabled() => 'bool', - $this->get_settings_key_unique_post_slugs() => 'bool', + $this->get_settings_key_enabled() => 'bool', + $this->get_settings_key_unique_post_slugs() => 'bool', $this->get_settings_key_post_statuses_as_parent() => 'bool', - $this->get_settings_key_preview_url() => 'string', - $this->get_settings_key_in_iframe() => 'bool', + $this->get_settings_key_preview_url() => 'string', + $this->get_settings_key_in_iframe() => 'bool', ] ); } - protected function set_cache_group(): void { - $groups = apply_filters( 'hwp_previews_settings_group_cache_groups', [ $this->settings_group ] ); - wp_cache_add_non_persistent_groups( $groups ); - } - - - public static function get_instance(): self { - - $instance = self::$instance; - - if ( $instance instanceof self ) { - return $instance; - } - - self::$instance = new self(); - - return self::$instance; - } - /** * Gets settings from the cache or database. * @@ -105,14 +131,12 @@ public function get_cached_settings(): array { * * @param string $name The setting name. * @param string $post_type The post type slug. - * @param bool $default_value The default value to return if the setting is not found. - * - * @return bool + * @param bool $default_value The default value to return if the setting is not found. */ public function get_post_type_boolean_value( string $name, string $post_type, bool $default_value = false ): bool { $settings = $this->get_cached_settings(); $type = $this->settings_config[ $name ] ?? null; - if ( $type === 'bool' && isset( $settings[ $post_type ][ $name ] ) ) { + if ( 'bool' === $type && isset( $settings[ $post_type ][ $name ] ) ) { return (bool) $settings[ $post_type ][ $name ]; } @@ -125,17 +149,36 @@ public function get_post_type_boolean_value( string $name, string $post_type, bo * @param string $name The setting name. * @param string $post_type The post type slug. * @param string $default_value The default value to return if the setting is not found. - * - * @return string */ public function get_post_type_string_value( string $name, string $post_type, string $default_value = '' ): string { $settings = $this->get_cached_settings(); $type = $this->settings_config[ $name ] ?? null; - if ( $type === 'string' && isset( $settings[ $post_type ][ $name ] ) ) { + if ( 'string' === $type && isset( $settings[ $post_type ][ $name ] ) ) { return (string) $settings[ $post_type ][ $name ]; } return $default_value; } + /** + * Gets the option key for the settings group. + */ + protected function get_option_key(): string { + return apply_filters( 'hwp_previews_settings_group_option_key', HWP_PREVIEWS_SETTINGS_KEY ); + } + + /** + * Gets the settings group name. + */ + protected function get_settings_group(): string { + return apply_filters( 'hwp_previews_settings_group_settings_group', HWP_PREVIEWS_SETTINGS_GROUP ); + } + + /** + * Sets the cache group for the settings. + */ + protected function set_cache_group(): void { + $groups = apply_filters( 'hwp_previews_settings_group_cache_groups', [ $this->settings_group ] ); + wp_cache_add_non_persistent_groups( $groups ); + } } diff --git a/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Helper.php b/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Helper.php index e71ec308..086f729b 100644 --- a/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Helper.php +++ b/plugins/hwp-previews/src/Admin/Settings/Helper/Settings_Helper.php @@ -1,26 +1,36 @@ settings_group = $settings_group; } + /** + * Get an instance of the Settings_Helper class. + * + * @return \HWP\Previews\Admin\Settings\Helper\Settings_Helper + */ public static function get_instance(): self { $instance = self::$instance; @@ -34,7 +44,12 @@ public static function get_instance(): self { return self::$instance; } - public function get_settings_config() : array { + /** + * Get the settings group. + * + * @return array + */ + public function get_settings_config(): array { return $this->settings_group->get_settings_config(); } @@ -52,19 +67,22 @@ public function post_types_enabled( array $default_value = [] ): array { $enabled_post_types = []; foreach ( $settings as $key => $item ) { - if ( $item[ $enabled_key ] ?? false ) { + if ( (bool) ( $item[ $enabled_key ] ?? false ) ) { $enabled_post_types[] = $key; } } - return $enabled_post_types ?: $default_value; + if ( ! empty( $enabled_post_types ) ) { + return $enabled_post_types; + } + return $default_value; } /** * Get Unique Post Slugs setting value for the given post type. * * @param string $post_type The post type to get the setting for. - * @param bool $default_value The default value to return if the setting is not set. + * @param bool $default_value The default value to return if the setting is not set. */ public function unique_post_slugs( string $post_type, bool $default_value = false ): bool { @@ -77,7 +95,7 @@ public function unique_post_slugs( string $post_type, bool $default_value = fals * Get Post Statuses as Parent setting value for the given post type. * * @param string $post_type The post type to get the setting for. - * @param bool $default_value The default value to return if the setting is not set. + * @param bool $default_value The default value to return if the setting is not set. */ public function post_statuses_as_parent( string $post_type, bool $default_value = false ): bool { $key = $this->settings_group->get_settings_key_post_statuses_as_parent(); @@ -89,7 +107,7 @@ public function post_statuses_as_parent( string $post_type, bool $default_value * Show In iframe value for the given post type. * * @param string $post_type The post type to get the setting for. - * @param bool $default_value The default value to return if the setting is not set. + * @param bool $default_value The default value to return if the setting is not set. */ public function in_iframe( string $post_type, bool $default_value = false ): bool { @@ -109,5 +127,4 @@ public function url_template( string $post_type, string $default_value = '' ): s return $this->settings_group->get_post_type_string_value( $key, $post_type, $default_value ); } - } diff --git a/plugins/hwp-previews/src/Admin/Settings/Menu/Menu_Page.php b/plugins/hwp-previews/src/Admin/Settings/Menu/Menu_Page.php index 68fe515f..b8167c9f 100644 --- a/plugins/hwp-previews/src/Admin/Settings/Menu/Menu_Page.php +++ b/plugins/hwp-previews/src/Admin/Settings/Menu/Menu_Page.php @@ -83,7 +83,7 @@ public function register_page(): void { add_submenu_page( 'options-general.php', $this->page_title, - __($this->menu_title, HWP_PREVIEWS_TEXT_DOMAIN), + $this->menu_title, 'manage_options', $this->menu_slug, [ $this, 'registration_callback' ], diff --git a/plugins/hwp-previews/src/Admin/Settings/Settings_Section.php b/plugins/hwp-previews/src/Admin/Settings/Settings_Section.php index e2a144f5..41f49897 100644 --- a/plugins/hwp-previews/src/Admin/Settings/Settings_Section.php +++ b/plugins/hwp-previews/src/Admin/Settings/Settings_Section.php @@ -36,9 +36,9 @@ class Settings_Section { /** * Constructor. * - * @param string $id Page slug. - * @param string $title Settings section title. - * @param string $page The slug of the settings page. + * @param string $id Page slug. + * @param string $title Settings section title. + * @param string $page The slug of the settings page. * @param array<\HWP\Previews\Admin\Settings\Fields\Abstract_Settings_Field> $fields Array of fields to be registered in the section. */ public function __construct( diff --git a/plugins/hwp-previews/src/Admin/Settings/Templates/settings-page-main.php b/plugins/hwp-previews/src/Admin/Settings/Templates/settings-page-main.php index 5c26957d..ab59c525 100644 --- a/plugins/hwp-previews/src/Admin/Settings/Templates/settings-page-main.php +++ b/plugins/hwp-previews/src/Admin/Settings/Templates/settings-page-main.php @@ -1,6 +1,6 @@ get_public_post_types(); + /** * Array of post types where key is the post type slug and value is the label. * * @var array $post_types */ - $post_types = apply_filters( 'hwp_previews_filter_post_type_setting', self::$types_config->get_public_post_types() ); + $post_types = apply_filters( 'hwp_previews_filter_post_type_setting', $post_types ); self::create_settings_page( $post_types )->register_page(); - } ); } + /** + * Registers the settings fields for each post type. + */ public static function register_settings_fields(): void { - add_action( 'admin_init', function (): void { + add_action( 'admin_init', static function (): void { + + $post_types = ( null === self::$types_config ) ? [] : self::$types_config->get_public_post_types(); /** * Array of post types where key is the post type slug and value is the label. * * @var array $post_types */ - $post_types = apply_filters( 'hwp_previews_filter_post_type_setting', self::$types_config->get_public_post_types() ); + $post_types = apply_filters( 'hwp_previews_filter_post_type_setting', $post_types ); /** * Register setting itself. @@ -74,7 +100,7 @@ public static function register_settings_fields(): void { * Enqueues the JavaScript and the CSS file for the plugin admin area. */ public static function load_scripts_styles(): void { - add_action( 'admin_enqueue_scripts', function ( string $hook ): void { + add_action( 'admin_enqueue_scripts', static function ( string $hook ): void { if ( 'settings_page_' . self::PLUGIN_MENU_SLUG !== $hook ) { return; @@ -103,8 +129,12 @@ public static function load_scripts_styles(): void { * @param array $post_types The post types to be used in the settings page. */ public static function create_settings_page( array $post_types ): Menu_Page { + + $descriptions = ( null === self::$parameters ) ? [] : self::$parameters->get_descriptions(); + + return new Menu_Page( - __( 'HWP Previews Settings', HWP_PREVIEWS_TEXT_DOMAIN ), + __( 'HWP Previews Settings', 'hwp-previews' ), 'HWP Previews', self::PLUGIN_MENU_SLUG, trailingslashit( HWP_PREVIEWS_TEMPLATE_DIR ) . 'settings-page-main.php', @@ -112,10 +142,9 @@ public static function create_settings_page( array $post_types ): Menu_Page { 'hwp_previews_main_page_config' => [ 'tabs' => $post_types, 'current_tab' => self::get_current_tab( $post_types ), - 'params' => self::$parameters->get_descriptions(), + 'params' => $descriptions, ], ], - 'dashicons-welcome-view-site' ); } @@ -139,7 +168,7 @@ public static function create_setting_section( string $post_type, string $label * * @param string $post_type The post type slug. * @param string $label The label for the post type. - * @param bool $is_hierarchical Whether the post type is hierarchical. + * @param bool $is_hierarchical Whether the post type is hierarchical. * * @return array<\HWP\Previews\Admin\Settings\Fields\Abstract_Settings_Field> */ @@ -148,33 +177,33 @@ public static function create_settings_fields( string $post_type, string $label, $fields[] = new Checkbox_Field( 'enabled', // translators: %s is the label of the post type. - sprintf( __( 'Enable HWP Previews for %s', HWP_PREVIEWS_TEXT_DOMAIN ), $label ), - __( 'Turn preview functionality on or off for this public post type.', HWP_PREVIEWS_TEXT_DOMAIN ) + sprintf( __( 'Enable HWP Previews for %s', 'hwp-previews' ), $label ), + __( 'Turn preview functionality on or off for this public post type.', 'hwp-previews' ) ); $fields[] = new Checkbox_Field( 'unique_post_slugs', - __( 'Enable unique post slugs for all post statuses', HWP_PREVIEWS_TEXT_DOMAIN ), - __( 'By default WordPress adds unique post slugs to the published posts. This option enforces unique slugs for all post statuses.', HWP_PREVIEWS_TEXT_DOMAIN ) + __( 'Enable unique post slugs for all post statuses', 'hwp-previews' ), + __( 'By default WordPress adds unique post slugs to the published posts. This option enforces unique slugs for all post statuses.', 'hwp-previews' ) ); if ( $is_hierarchical ) { $fields[] = new Checkbox_Field( 'post_statuses_as_parent', - __( 'Allow all post statuses in parents option', HWP_PREVIEWS_TEXT_DOMAIN ), - __( 'By default WordPress only allows published posts to be parents. This option allows posts of all statuses to be used as parent within hierarchical post types.', HWP_PREVIEWS_TEXT_DOMAIN ) + __( 'Allow all post statuses in parents option', 'hwp-previews' ), + __( 'By default WordPress only allows published posts to be parents. This option allows posts of all statuses to be used as parent within hierarchical post types.', 'hwp-previews' ) ); } $fields[] = new Checkbox_Field( 'in_iframe', - sprintf( __( 'Load previews in iframe', HWP_PREVIEWS_TEXT_DOMAIN ), $label ), - __( 'With this option enabled, headless previews will be displayed inside an iframe on the preview page, without leaving WordPress.', HWP_PREVIEWS_TEXT_DOMAIN ) + sprintf( __( 'Load previews in iframe', 'hwp-previews' ), $label ), + __( 'With this option enabled, headless previews will be displayed inside an iframe on the preview page, without leaving WordPress.', 'hwp-previews' ) ); $fields[] = new Text_Input_Field( 'preview_url', // translators: %s is the label of the post type. - sprintf( __( 'Preview URL for %s', HWP_PREVIEWS_TEXT_DOMAIN ), $label ), - __( 'Construct your preview URL using the tags on the right. You can add any parameters needed to support headless previews.', HWP_PREVIEWS_TEXT_DOMAIN ), + sprintf( __( 'Preview URL for %s', 'hwp-previews' ), $label ), + __( 'Construct your preview URL using the tags on the right. You can add any parameters needed to support headless previews.', 'hwp-previews' ), "https://localhost:3000/{$post_type}?preview=true&post_id={ID}&name={slug}", 'code hwp-previews-url' // The class is being used as a query for the JS. ); @@ -202,7 +231,7 @@ public static function create_tabbed_settings( array $post_types ): Tabbed_Setti * Get the current tab for the settings page. * * @param array $post_types The post types to be used in the settings page. - * @param string $tab The name of the tab. + * @param string $tab The name of the tab. */ public static function get_current_tab( $post_types, string $tab = 'tab' ): string { // phpcs:disable WordPress.Security.NonceVerification.Recommended diff --git a/plugins/hwp-previews/src/Autoloader.php b/plugins/hwp-previews/src/Autoloader.php index 7847d037..056b1a0a 100644 --- a/plugins/hwp-previews/src/Autoloader.php +++ b/plugins/hwp-previews/src/Autoloader.php @@ -3,17 +3,16 @@ * Includes the composer Autoloader used for packages and classes in the src/ directory. * * @package HWP\Previews + * * @since 0.0.1 */ -declare( strict_types = 1 ); +declare(strict_types=1); namespace HWP\Previews; /** * Class - Autoloader - * - * @internal */ class Autoloader { /** @@ -60,7 +59,7 @@ protected static function require_autoloader( string $autoloader_file ): bool { * Displays a notice if the autoloader is missing. */ protected static function missing_autoloader_notice(): void { - $error_message = __( 'HWP Previews: The Composer autoloader was not found. If you installed the plugin from the GitHub source, make sure to run `composer install`.', 'hwp-previews' ); + $error_message = 'HWP Previews: The Composer autoloader was not found. If you installed the plugin from the GitHub source, make sure to run `composer install`.'; if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( esc_html( $error_message ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- This is a development notice. @@ -75,7 +74,7 @@ protected static function missing_autoloader_notice(): void { /** @psalm-suppress HookNotFound */ add_action( $hook, - static function () use ( $error_message ) { + static function () use ( $error_message ): void { ?>

diff --git a/plugins/hwp-previews/src/Hooks/Preview_Hooks.php b/plugins/hwp-previews/src/Hooks/Preview_Hooks.php index 7a7c0fcd..c508b114 100644 --- a/plugins/hwp-previews/src/Hooks/Preview_Hooks.php +++ b/plugins/hwp-previews/src/Hooks/Preview_Hooks.php @@ -1,5 +1,7 @@ + */ public static function get_post_statuses(): array { $post_statuses = [ 'publish', @@ -123,7 +139,7 @@ public static function get_post_statuses(): array { 'draft', 'pending', 'private', - 'auto-draft' + 'auto-draft', ]; return apply_filters( 'hwp_previews_hooks_post_statuses', $post_statuses ); @@ -134,14 +150,18 @@ public static function get_post_statuses(): array { * * @link https://developer.wordpress.org/reference/hooks/wp_insert_post_data/ * - * @param array $data - * @param array $postarr + * @param array $data + * @param array $postarr * - * @return array + * @return array */ public static function enable_unique_post_slug( array $data, array $postarr ): array { $post = new WP_Post( new Post_Data_Model( $data, (int) ( $postarr['ID'] ?? 0 ) ) ); + if ( null === self::$settings_helper || null === self::$types_config || null === self::$statuses_config ) { + return $data; + } + // Check if the correspondent setting is enabled. if ( ! self::$settings_helper->unique_post_slugs( $post->post_type ) ) { return $data; @@ -160,18 +180,23 @@ public static function enable_unique_post_slug( array $data, array $postarr ): a return $data; } - /** * Enable post statuses as parent for the post types specified in the post types config. * - * @param array $args The arguments for the dropdown pages + * @param array $args The arguments for the dropdown pages. + * + * @return array The modified dropdown arguments with post statuses as parent if applicable. * - * @return array The modified dropdown arguments with post statuses as parent if applicable. * @link https://developer.wordpress.org/reference/hooks/page_attributes_dropdown_pages_args/. * * @link https://developer.wordpress.org/reference/hooks/quick_edit_dropdown_pages_args/ */ public static function enable_post_statuses_as_parent( array $args ): array { + + if ( null === self::$settings_helper || null === self::$types_config || null === self::$statuses_config ) { + return $args; + } + $post_parent_manager = new Post_Parent_Manager( self::$types_config, self::$statuses_config ); if ( empty( $args['post_type'] ) ) { @@ -195,11 +220,12 @@ public static function enable_post_statuses_as_parent( array $args ): array { /** * Replace the preview link in the REST response. - * - * @param \WP_REST_Response $response The REST response object. - * @param \WP_Post $post The post object. */ public static function filter_rest_prepare_link( WP_REST_Response $response, WP_Post $post ): WP_REST_Response { + if ( null === self::$settings_helper ) { + return $response; + } + if ( self::$settings_helper->in_iframe( $post->post_type ) ) { return $response; } @@ -216,6 +242,12 @@ public static function filter_rest_prepare_link( WP_REST_Response $response, WP_ * Enable preview functionality in iframe. */ public static function add_iframe_preview_template( string $template ): string { + + // Bail out if class not initialized or settings helper and link service are not set. + if ( null === self::$settings_helper || null === self::$link_service || null === self::$types_config || null === self::$statuses_config ) { + return $template; + } + if ( ! is_preview() ) { return $template; } @@ -244,8 +276,6 @@ public static function add_iframe_preview_template( string $template ): string { $preview_template = $template_resolver->resolve_template_path( $post, $template_dir_path ); if ( empty( $preview_template ) ) { - error_log( 'Preview template not found for post type' . (string) $post->post_type ); - return $template; } @@ -258,11 +288,14 @@ public static function add_iframe_preview_template( string $template ): string { * Enables preview functionality when iframe option is disabled. * * @link https://developer.wordpress.org/reference/hooks/preview_post_link/ - * - * @return void */ public static function update_preview_post_link( string $preview_link, WP_Post $post ): string { + // Bail out if class not initialized or settings helper and link service are not set. + if ( null === self::$settings_helper || null === self::$link_service ) { + return $preview_link; + } + // @TODO - Need to do more testing and add e2e tests for this filter. // If iframe option is enabled, we need to resolve preview on the template redirect level. @@ -286,10 +319,14 @@ public static function update_preview_post_link( string $preview_link, WP_Post $ * @return string The generated preview URL. */ public static function generate_preview_url( WP_Post $post ): string { + if ( null === self::$settings_helper ) { + return ''; + } + // Check if the correspondent setting is enabled. $url = self::$settings_helper->url_template( $post->post_type ); - if ( empty( $url ) ) { + if ( empty( $url ) || null === self::$link_service ) { return ''; } diff --git a/plugins/hwp-previews/src/Plugin.php b/plugins/hwp-previews/src/Plugin.php index ad4da209..3bdd7e99 100644 --- a/plugins/hwp-previews/src/Plugin.php +++ b/plugins/hwp-previews/src/Plugin.php @@ -1,13 +1,12 @@ get_var( // phpcs:ignore WordPress.DB $wpdb->prepare( + // @phpstan-ignore-next-line "SELECT post_name FROM {$wpdb->posts} WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1", $slug, $post_type, diff --git a/plugins/hwp-previews/src/Post/Type/Post_Types_Config_Registry.php b/plugins/hwp-previews/src/Post/Type/Post_Types_Config_Registry.php index f63f7ac8..2eacf296 100644 --- a/plugins/hwp-previews/src/Post/Type/Post_Types_Config_Registry.php +++ b/plugins/hwp-previews/src/Post/Type/Post_Types_Config_Registry.php @@ -1,6 +1,6 @@ set_post_types( Settings_Helper::get_instance()->post_types_enabled() ); - $instance = apply_filters( 'hwp_preview_get_post_types_config', $instance ); + $instance = apply_filters( 'hwp_previews_get_post_types_config', $instance ); self::$instance = $instance; return $instance; } - } diff --git a/plugins/hwp-previews/src/Preview/Parameter/Preview_Parameter_Registry.php b/plugins/hwp-previews/src/Preview/Parameter/Preview_Parameter_Registry.php index 6488b28d..08305b42 100644 --- a/plugins/hwp-previews/src/Preview/Parameter/Preview_Parameter_Registry.php +++ b/plugins/hwp-previews/src/Preview/Parameter/Preview_Parameter_Registry.php @@ -1,6 +1,6 @@ register( - new Preview_Parameter( 'ID', static fn( WP_Post $post ) => (string) $post->ID, __( 'Post ID.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'ID', static fn( WP_Post $post ) => (string) $post->ID, 'Post ID.' ) )->register( - new Preview_Parameter( 'author_ID', static fn( WP_Post $post ) => $post->post_author, __( 'ID of post author..', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'author_ID', static fn( WP_Post $post ) => $post->post_author, 'ID of post author.' ) )->register( - new Preview_Parameter( 'status', static fn( WP_Post $post ) => $post->post_status, __( 'The post\'s status..', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'status', static fn( WP_Post $post ) => $post->post_status, 'The post status.' ) )->register( - new Preview_Parameter( 'slug', static fn( WP_Post $post ) => $post->post_name, __( 'The post\'s slug.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'slug', static fn( WP_Post $post ) => $post->post_name, 'The post slug.' ) )->register( - new Preview_Parameter( 'parent_ID', static fn( WP_Post $post ) => (string) $post->post_parent, __( 'ID of a post\'s parent post.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'parent_ID', static fn( WP_Post $post ) => (string) $post->post_parent, 'ID of a post parent post.' ) )->register( - new Preview_Parameter( 'type', static fn( WP_Post $post ) => $post->post_type, __( 'The post\'s type, like post or page.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'type', static fn( WP_Post $post ) => $post->post_type, 'The post type, like post or page.' ) )->register( - new Preview_Parameter( 'uri', static fn( WP_Post $post ) => (string) get_page_uri( $post ), __( 'The URI path for a page.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'uri', static fn( WP_Post $post ) => (string) get_page_uri( $post ), 'The URI path for a page.' ) )->register( - new Preview_Parameter( 'template', static fn( WP_Post $post ) => (string) get_page_template_slug( $post ), __( 'Specific template filename for a given post.', HWP_PREVIEWS_TEXT_DOMAIN ) ) + new Preview_Parameter( 'template', static fn( WP_Post $post ) => (string) get_page_template_slug( $post ), 'Specific template filename for a given post.' ) ); // Allow users to register/unregister parameters.