diff --git a/.editorconfig b/.editorconfig index bb112e1..c8561cc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,4 +13,4 @@ insert_final_newline = true trim_trailing_whitespace = false [*.php] -indent_style = tab +indent_size = 4 diff --git a/composer.json b/composer.json index da68da2..6b7679a 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,6 @@ }, "require-dev": { "squizlabs/php_codesniffer": "^3.4", - "wp-coding-standards/wpcs": "^2.1", "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "szepeviktor/phpstan-wordpress": "^1.1", "php-stubs/wordpress-stubs": "^5.5", @@ -29,9 +28,17 @@ ] }, "scripts": { - "phpcs": "phpcs -s --colors --standard=./phpcs.xml", - "phpstan": "phpstan analyse --memory-limit=512M", - "phpunit": "phpunit" + "lint": [ + "@lint:style", + "@lint:static" + ], + "lint:style": "phpcs", + "lint:static": "phpstan analyse --memory-limit=512M", + "fix": [ + "@fix:style" + ], + "fix:style": "phpcbf", + "test": "phpunit" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/composer.lock b/composer.lock index d3e54f9..405f3e3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "58321d066b07ecb11928cd5e68e5d563", + "content-hash": "f46208b8750d1d7d0f6a899a2cf219b8", "packages": [ { "name": "anahkiasen/html-object", @@ -2975,57 +2975,6 @@ ], "time": "2024-03-03T12:36:25+00:00" }, - { - "name": "wp-coding-standards/wpcs", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "7da1894633f168fe244afc6de00d141f27517b62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", - "reference": "7da1894633f168fe244afc6de00d141f27517b62", - "shasum": "" - }, - "require": { - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.3.1" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", - "phpcompatibility/php-compatibility": "^9.0", - "phpcsstandards/phpcsdevtools": "^1.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Contributors", - "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", - "keywords": [ - "phpcs", - "standards", - "wordpress" - ], - "support": { - "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", - "source": "https://github.com/WordPress/WordPress-Coding-Standards", - "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" - }, - "time": "2020-05-13T23:57:56+00:00" - }, { "name": "yoast/phpunit-polyfills", "version": "1.1.0", diff --git a/phpcs.xml b/phpcs.xml index d2926a8..4f907dd 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,5 +1,10 @@ + + + + + ./src/ ./tests/ @@ -7,33 +12,17 @@ /vendor/ - - - - - - + - - - - - - - - - - */tests/* + + - + */tests/* - + */tests/* diff --git a/phpstan.neon b/phpstan.neon index a027ab3..e94f403 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,6 +3,8 @@ includes: parameters: level: max + cache: + nodesByStringCountMax: 512 inferPrivatePropertyTypeFromConstructor: true checkMissingIterableValueType: false reportUnmatchedIgnoredErrors: false diff --git a/src/Builders/Builder.php b/src/Builders/Builder.php index fdc5580..0e78715 100644 --- a/src/Builders/Builder.php +++ b/src/Builders/Builder.php @@ -15,127 +15,136 @@ /** * Cleanup a WordPress project for security and performance. */ -abstract class Builder { - /** - * The post type key. - * - * @var string - */ - private $type; - - /** - * The post type configuration. - * - * @var array - */ - private $config = array(); - - /** - * The post type configuration. - * - * @var array - */ - public $default_config = array(); - - /** - * The method used to register the builder. - * - * @var string - */ - public $register_method = ''; - - /** - * The key for the register method arguments. - * - * @var array - */ - public $register_method_args = array(); - - /** - * __construct - * - * @param string $type The post type key. - * @param array $config A config for the builder. - */ - public function __construct( string $type, array $config = array() ) { - $this->type = $type; - - if ( is_array( $this->default_config ) ) { - $this->update_config( $this->default_config ); - } - - $this->update_config( $config ); - } - - /** - * Build the post type configuration. - * - * @return array The post type configuration. - */ - public function get_config():array { - return $this->config; - } - - /** - * Set a config key -> value pair. - * - * @param string $key The key to set. - * @param mixed $value The value to set. - * @return $this - */ - public function set_config( string $key, $value ) { - return $this->update_config( array( $key => $value ) ); - } - - /** - * Update multiple config values. - * - * @param array $config The config to merge. - * @return $this - */ - public function update_config( $config ) { - $this->config = array_merge( $this->config, $config ); - return $this; - } - - /** - * Get the register method name. - * - * @return string The register method name. - */ - private function get_register_method():string { - return $this->register_method; - } - - /** - * Get the register method argument names. - * - * @return array The register method name. - */ - private function get_register_method_args():array { - return $this->register_method_args; - } - - /** - * Get an instance property value. - * - * @param string $key The property to get. - * @return mixed The property value. - */ - private function get( string $key ) { - return $this->{$key}; - } - - /** - * Register the post type. - * - * @return void - */ - public function register():void { - $register_method = $this->get_register_method(); - if ( $register_method && is_callable( $register_method ) ) { - $args = array_map( array( $this, 'get' ), $this->get_register_method_args() ); - $register_method( ...$args ); - } - } +abstract class Builder +{ + /** + * The post type key. + * + * @var string + */ + private $type; + + /** + * The post type configuration. + * + * @var array + */ + private $config = array(); + + /** + * The post type configuration. + * + * @var array + */ + public $default_config = array(); + + /** + * The method used to register the builder. + * + * @var string + */ + public $register_method = ''; + + /** + * The key for the register method arguments. + * + * @var array + */ + public $register_method_args = array(); + + /** + * __construct + * + * @param string $type The post type key. + * @param array $config A config for the builder. + */ + public function __construct(string $type, array $config = array()) + { + $this->type = $type; + + if (is_array($this->default_config)) { + $this->update_config($this->default_config); + } + + $this->update_config($config); + } + + /** + * Build the post type configuration. + * + * @return array The post type configuration. + */ + public function get_config():array + { + return $this->config; + } + + /** + * Set a config key -> value pair. + * + * @param string $key The key to set. + * @param mixed $value The value to set. + * @return $this + */ + public function set_config(string $key, $value) + { + return $this->update_config(array( $key => $value )); + } + + /** + * Update multiple config values. + * + * @param array $config The config to merge. + * @return $this + */ + public function update_config($config) + { + $this->config = array_merge($this->config, $config); + return $this; + } + + /** + * Get the register method name. + * + * @return string The register method name. + */ + private function get_register_method():string + { + return $this->register_method; + } + + /** + * Get the register method argument names. + * + * @return array The register method name. + */ + private function get_register_method_args():array + { + return $this->register_method_args; + } + + /** + * Get an instance property value. + * + * @param string $key The property to get. + * @return mixed The property value. + */ + private function get(string $key) + { + return $this->{$key}; + } + + /** + * Register the post type. + * + * @return void + */ + public function register():void + { + $register_method = $this->get_register_method(); + if ($register_method && is_callable($register_method)) { + $args = array_map(array( $this, 'get' ), $this->get_register_method_args()); + $register_method(...$args); + } + } } diff --git a/src/Builders/PostTypeBuilder.php b/src/Builders/PostTypeBuilder.php index 8e66a6a..dd66e95 100644 --- a/src/Builders/PostTypeBuilder.php +++ b/src/Builders/PostTypeBuilder.php @@ -15,351 +15,386 @@ /** * Build a custom post type. */ -class PostTypeBuilder extends Builder { - /** - * The post type configuration. - * - * @var array - */ - public $default_config = array( - 'public' => true, - 'show_in_rest' => false, - 'menu_position' => null, - 'has_archive' => false, - 'supports' => array( 'title', 'editor', 'thumbnail' ), - 'can_export' => true, - 'delete_with_user' => null, - ); +class PostTypeBuilder extends Builder +{ + /** + * The post type configuration. + * + * @var array + */ + public $default_config = array( + 'public' => true, + 'show_in_rest' => false, + 'menu_position' => null, + 'has_archive' => false, + 'supports' => array( 'title', 'editor', 'thumbnail' ), + 'can_export' => true, + 'delete_with_user' => null, + ); - /** - * The register method name. - * - * @var string - */ - public $register_method = 'register_post_type'; + /** + * The register method name. + * + * @var string + */ + public $register_method = 'register_post_type'; - /** - * The register method args. - * - * @var array - */ - public $register_method_args = array( 'type', 'config' ); + /** + * The register method args. + * + * @var array + */ + public $register_method_args = array( 'type', 'config' ); - /** - * Name of the post type shown in the menu. Usually plural. Default is value of $labels['name']. - * - * @param string $label The post type label. - */ - public function set_label( string $label ):self { - return $this->set_config( 'label', $label ); - } + /** + * Name of the post type shown in the menu. Usually plural. Default is value of $labels['name']. + * + * @param string $label The post type label. + */ + public function set_label(string $label):self + { + return $this->set_config('label', $label); + } - /** - * An array of labels for this post type. If not set, post labels are inherited for non-hierarchical types and page - * labels for hierarchical ones. - * - * @param string $singular The singular label. - * @param string $plural The plural label. - */ - public function set_labels( string $singular, string $plural ):self { - return $this->set_config( 'labels', $this->generate_labels( $singular, $plural ) ); - } + /** + * An array of labels for this post type. If not set, post labels are inherited for non-hierarchical types and page + * labels for hierarchical ones. + * + * @param string $singular The singular label. + * @param string $plural The plural label. + */ + public function set_labels(string $singular, string $plural):self + { + return $this->set_config('labels', $this->generate_labels($singular, $plural)); + } - /** - * Generate labels. - * - * @param string $singular Singular name. - * @param string $plural Plural name. - * @return array Labels. - */ - private function generate_labels( string $singular, string $plural ):array { + /** + * Generate labels. + * + * @param string $singular Singular name. + * @param string $plural Plural name. + * @return array Labels. + */ + private function generate_labels(string $singular, string $plural):array + { // phpcs:disable WordPress.WP.I18n - $labels = array( - 'name' => $plural, - 'singular_name' => $singular, - 'add_new' => sprintf( __( 'Add New %s', 'studiometa' ), $singular ), - 'add_new_item' => sprintf( __( 'Add New %s', 'studiometa' ), $singular ), - 'edit_item' => sprintf( __( 'Edit %s', 'studiometa' ), $singular ), - 'new_item' => sprintf( __( 'New %s', 'studiometa' ), $singular ), - 'all_items' => sprintf( __( 'All %s', 'studiometa' ), $plural ), - 'view_item' => sprintf( __( 'View %s', 'studiometa' ), $singular ), - 'search_items' => sprintf( __( 'Search %s', 'studiometa' ), $plural ), - 'not_found' => sprintf( __( 'No %s', 'studiometa' ), $plural ), - 'not_found_in_trash' => sprintf( __( 'No %s found in Trash', 'studiometa' ), $plural ), - 'parent_item_colon' => isset( $this->get_config()['hierarchical'] ) && $this->get_config()['hierarchical'] ? sprintf( __( 'Parent %s:', 'studiometa' ), $singular ) : null, - 'menu_name' => $plural, - 'insert_into_item' => sprintf( __( 'Insert into %s', 'studiometa' ), strtolower( $singular ) ), - 'uploaded_to_this_item' => sprintf( __( 'Uploaded to this %s', 'studiometa' ), strtolower( $singular ) ), - 'items_list' => sprintf( __( '%s list', 'studiometa' ), $plural ), - 'items_list_navigation' => sprintf( __( '%s list navigation', 'studiometa' ), $plural ), - 'filter_items_list' => sprintf( __( 'Filter %s list', 'studiometa' ), strtolower( $plural ) ), - ); + $labels = array( + 'name' => $plural, + 'singular_name' => $singular, + 'add_new' => sprintf(__('Add New %s', 'studiometa'), $singular), + 'add_new_item' => sprintf(__('Add New %s', 'studiometa'), $singular), + 'edit_item' => sprintf(__('Edit %s', 'studiometa'), $singular), + 'new_item' => sprintf(__('New %s', 'studiometa'), $singular), + 'all_items' => sprintf(__('All %s', 'studiometa'), $plural), + 'view_item' => sprintf(__('View %s', 'studiometa'), $singular), + 'search_items' => sprintf(__('Search %s', 'studiometa'), $plural), + 'not_found' => sprintf(__('No %s', 'studiometa'), $plural), + 'not_found_in_trash' => sprintf(__('No %s found in Trash', 'studiometa'), $plural), + 'parent_item_colon' => isset($this->get_config()['hierarchical']) && $this->get_config()['hierarchical'] + ? sprintf(__('Parent %s:', 'studiometa'), $singular) + : null, + 'menu_name' => $plural, + 'insert_into_item' => sprintf(__('Insert into %s', 'studiometa'), strtolower($singular)), + 'uploaded_to_this_item' => sprintf(__('Uploaded to this %s', 'studiometa'), strtolower($singular)), + 'items_list' => sprintf(__('%s list', 'studiometa'), $plural), + 'items_list_navigation' => sprintf(__('%s list navigation', 'studiometa'), $plural), + 'filter_items_list' => sprintf(__('Filter %s list', 'studiometa'), strtolower($plural)), + ); // phpcs:enable - return $labels; - } + return $labels; + } - /** - * A short descriptive summary of what the post type is. - * - * @param string $description The description. - * @return PostTypeBuilder - */ - public function set_description( string $description ) { - return $this->set_config( 'description', $description ); - } + /** + * A short descriptive summary of what the post type is. + * + * @param string $description The description. + * @return PostTypeBuilder + */ + public function set_description(string $description) + { + return $this->set_config('description', $description); + } - /** - * Whether a post type is intended for use publicly either via the admin interface or by front-end users. While the - * default settings of $exclude_from_search, $publicly_queryable, $show_ui, and $show_in_nav_menus are inherited from - * public, each does not rely on this relationship and controls a very specific intention. Default false. - * - * @param bool $is_public Is it public or not. - * @return PostTypeBuilder - */ - public function set_public( bool $is_public ) { - return $this->set_config( 'public', $is_public ); - } + /** + * Whether a post type is intended for use publicly either via the admin interface or by front-end users. While the + * default settings of $exclude_from_search, $publicly_queryable, $show_ui, and $show_in_nav_menus are inherited + * from public, each does not rely on this relationship and controls a very specific intention. Default false. + * + * @param bool $is_public Is it public or not. + * @return PostTypeBuilder + */ + public function set_public(bool $is_public) + { + return $this->set_config('public', $is_public); + } - /** - * Whether the post type is hierarchical (e.g. page). Default false. - * - * @param bool $is_hierarchical Is it hierarchical or not. - * @return PostTypeBuilder - */ - public function set_hierarchical( bool $is_hierarchical ) { - return $this->set_config( 'hierarchical', $is_hierarchical ); - } + /** + * Whether the post type is hierarchical (e.g. page). Default false. + * + * @param bool $is_hierarchical Is it hierarchical or not. + * @return PostTypeBuilder + */ + public function set_hierarchical(bool $is_hierarchical) + { + return $this->set_config('hierarchical', $is_hierarchical); + } - /** - * Whether to exclude posts with this post type from front end search results. - * Default is the opposite value of $public. - * - * @param bool $exclude_from_search Exclude this CPT from search or not. - * @return PostTypeBuilder - */ - public function set_exclude_from_search( bool $exclude_from_search ) { - return $this->set_config( 'exclude_from_search', $exclude_from_search ); - } + /** + * Whether to exclude posts with this post type from front end search results. + * Default is the opposite value of $public. + * + * @param bool $exclude_from_search Exclude this CPT from search or not. + * @return PostTypeBuilder + */ + public function set_exclude_from_search(bool $exclude_from_search) + { + return $this->set_config('exclude_from_search', $exclude_from_search); + } - /** - * Whether queries can be performed on the front end for the post type as part of parse_request(). - * Endpoints would include: - * - * - ?post_type={post_type_key} - * - ?{post_type_key}={single_post_slug} - * - ?{post_type_query_var}={single_post_slug} - * - * If not set, the default is inherited from $public. - * - * @param bool $is_publicly_queryable Is it publicly queryable or not. - * @return PostTypeBuilder - */ - public function set_publicly_queryable( bool $is_publicly_queryable ) { - return $this->set_config( 'publicly_queryable', $is_publicly_queryable ); - } + /** + * Whether queries can be performed on the front end for the post type as part of parse_request(). + * Endpoints would include: + * + * - ?post_type={post_type_key} + * - ?{post_type_key}={single_post_slug} + * - ?{post_type_query_var}={single_post_slug} + * + * If not set, the default is inherited from $public. + * + * @param bool $is_publicly_queryable Is it publicly queryable or not. + * @return PostTypeBuilder + */ + public function set_publicly_queryable(bool $is_publicly_queryable) + { + return $this->set_config('publicly_queryable', $is_publicly_queryable); + } - /** - * Whether to generate and allow a UI for managing this post type in the admin. Default is value of $public. - * - * @param bool $show_ui Show this CPT in the administration or not. - * @return PostTypeBuilder UI? - */ - public function set_show_ui( bool $show_ui ) { - return $this->set_config( 'show_ui', $show_ui ); - } + /** + * Whether to generate and allow a UI for managing this post type in the admin. Default is value of $public. + * + * @param bool $show_ui Show this CPT in the administration or not. + * @return PostTypeBuilder UI? + */ + public function set_show_ui(bool $show_ui) + { + return $this->set_config('show_ui', $show_ui); + } - /** - * Where to show the post type in the admin menu. To work, $show_ui must be true. If true, the post type is shown in - * its own top level menu. If false, no menu is shown. If a string of an existing top level menu (eg. 'tools.php' or - * 'edit.php?post_type=page'), the post type will be placed as a sub-menu of that. Default is value of $show_ui. - * - * @param bool|string $show_in_menu Show this CPT in menu. - * @return PostTypeBuilder in menu? - */ - public function set_show_in_menu( $show_in_menu ) { - return $this->set_config( 'show_in_menu', $show_in_menu ); - } + /** + * Where to show the post type in the admin menu. To work, $show_ui must be true. If true, the post type is shown in + * its own top level menu. If false, no menu is shown. If a string of an existing top level menu (eg. 'tools.php' or + * 'edit.php?post_type=page'), the post type will be placed as a sub-menu of that. Default is value of $show_ui. + * + * @param bool|string $show_in_menu Show this CPT in menu. + * @return PostTypeBuilder in menu? + */ + public function set_show_in_menu($show_in_menu) + { + return $this->set_config('show_in_menu', $show_in_menu); + } - /** - * Makes this post type available for selection in navigation menus. Default is value of $public. - * - * @param bool $show_in_nav_menus Is selectable in navigation menu or not. - * @return PostTypeBuilder - */ - public function set_show_in_nav_menus( bool $show_in_nav_menus ) { - return $this->set_config( 'show_in_nav_menus', $show_in_nav_menus ); - } + /** + * Makes this post type available for selection in navigation menus. Default is value of $public. + * + * @param bool $show_in_nav_menus Is selectable in navigation menu or not. + * @return PostTypeBuilder + */ + public function set_show_in_nav_menus(bool $show_in_nav_menus) + { + return $this->set_config('show_in_nav_menus', $show_in_nav_menus); + } - /** - * Makes this post type available via the admin bar. Default is value of $show_in_menu. - * - * @param bool $show_in_admin_bar Show in admin bar or not. - * @return PostTypeBuilder - */ - public function set_show_in_admin_bar( bool $show_in_admin_bar ) { - return $this->set_config( 'show_in_admin_bar', $show_in_admin_bar ); - } - /** - * Whether to include the post type in the REST API. Set this to true for the post type to be available in the block editor. - * - * @param bool $show_in_rest Show in rest or not. - * @return PostTypeBuilder - */ - public function set_show_in_rest( bool $show_in_rest ) { - return $this->set_config( 'show_in_rest', $show_in_rest ); - } + /** + * Makes this post type available via the admin bar. Default is value of $show_in_menu. + * + * @param bool $show_in_admin_bar Show in admin bar or not. + * @return PostTypeBuilder + */ + public function set_show_in_admin_bar(bool $show_in_admin_bar) + { + return $this->set_config('show_in_admin_bar', $show_in_admin_bar); + } + /** + * Whether to include the post type in the REST API. Set this to true for the post type to be available in the block + * editor. + * + * @param bool $show_in_rest Show in rest or not. + * @return PostTypeBuilder + */ + public function set_show_in_rest(bool $show_in_rest) + { + return $this->set_config('show_in_rest', $show_in_rest); + } - /** - * To change the base url of REST API route. Default is $post_type. - * - * @param string $rest_base The base url of the REST API route. - * @return PostTypeBuilder - */ - public function set_rest_base( string $rest_base ) { - return $this->set_config( 'rest_base', $rest_base ); - } + /** + * To change the base url of REST API route. Default is $post_type. + * + * @param string $rest_base The base url of the REST API route. + * @return PostTypeBuilder + */ + public function set_rest_base(string $rest_base) + { + return $this->set_config('rest_base', $rest_base); + } - /** - * REST API Controller class name. Default is 'WP_REST_Posts_Controller'. - * - * @param string $rest_controller_class The REST API Controller class name. - * @return PostTypeBuilder - */ - public function set_rest_controller_class( string $rest_controller_class ) { - return $this->set_config( 'rest_controller_class', $rest_controller_class ); - } + /** + * REST API Controller class name. Default is 'WP_REST_Posts_Controller'. + * + * @param string $rest_controller_class The REST API Controller class name. + * @return PostTypeBuilder + */ + public function set_rest_controller_class(string $rest_controller_class) + { + return $this->set_config('rest_controller_class', $rest_controller_class); + } - /** - * The position in the menu order the post type should appear. To work, $show_in_menu must be true. - * Default null (at the bottom). - * - * @param int $menu_position The menu position. - * @return PostTypeBuilder - */ - public function set_menu_position( int $menu_position ) { - return $this->set_config( 'menu_position', $menu_position ); - } + /** + * The position in the menu order the post type should appear. To work, $show_in_menu must be true. + * Default null (at the bottom). + * + * @param int $menu_position The menu position. + * @return PostTypeBuilder + */ + public function set_menu_position(int $menu_position) + { + return $this->set_config('menu_position', $menu_position); + } - /** - * The url to the icon to be used for this menu. Pass a base64-encoded SVG using a data URI, which will be colored to - * match the color scheme -- this should begin with 'data:image/svg+xml;base64,'. Pass the name of a Dashicons helper - * class to use a font icon, e.g. 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty so an icon can - * be added via CSS. Defaults to use the posts icon. - * - * @param string $menu_icon The menu icon. - * @return PostTypeBuilder - */ - public function set_menu_icon( string $menu_icon ) { - return $this->set_config( 'menu_icon', $menu_icon ); - } + /** + * The url to the icon to be used for this menu. Pass a base64-encoded SVG using a data URI, which will be colored + * to match the color scheme -- this should begin with 'data:image/svg+xml;base64,'. Pass the name of a Dashicons + * helper class to use a font icon, e.g. 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty so an + * icon can be added via CSS. Defaults to use the posts icon. + * + * @param string $menu_icon The menu icon. + * @return PostTypeBuilder + */ + public function set_menu_icon(string $menu_icon) + { + return $this->set_config('menu_icon', $menu_icon); + } - /** - * The string to use to build the read, edit & delete capabilities. May be passed as an array to allow for alternative - * plurals when using this argument as a base to construct the capabilities, e.g. array('story', 'stories'). - * Default 'post'. - * - * @param string $capability_type The capability type of the CPT. - * @return PostTypeBuilder - */ - public function set_capability_type( string $capability_type ) { - return $this->set_config( 'capability_type', $capability_type ); - } + /** + * The string to use to build the read, edit & delete capabilities. May be passed as an array to allow for + * alternative plurals when using this argument as a base to construct the capabilities, + * e.g. array('story', 'stories'). + * Default 'post'. + * + * @param string $capability_type The capability type of the CPT. + * @return PostTypeBuilder + */ + public function set_capability_type(string $capability_type) + { + return $this->set_config('capability_type', $capability_type); + } - /** - * Array of capabilities for this post type. $capability_type is used as a base to construct capabilities by default. - * See get_post_type_capabilities(). - * - * @param array $capabilities List of capabilities. - * @return PostTypeBuilder - */ - public function set_capabilities( array $capabilities ) { - return $this->set_config( 'capabilities', $capabilities ); - } + /** + * Array of capabilities for this post type. $capability_type is used as a base to construct capabilities by + * default. + * See get_post_type_capabilities(). + * + * @param array $capabilities List of capabilities. + * @return PostTypeBuilder + */ + public function set_capabilities(array $capabilities) + { + return $this->set_config('capabilities', $capabilities); + } - /** - * Core feature(s) the post type supports. Serves as an alias for calling add_post_type_support() directly. Core - * features include 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', - * 'thumbnail', 'custom-fields', and 'post-formats'. Additionally, the 'revisions' feature dictates whether the post - * type will store revisions, and the 'comments' feature dictates whether the comments count will show on the edit - * screen. A feature can also be specified as an array of arguments to provide additional information about supporting - * that feature. Example: array( 'my_feature', array( 'field' => 'value' ) ). Default is an array containing 'title' - * and 'editor'. - * - * @param array $supports List of features this CPT should support. - * @return PostTypeBuilder - */ - public function set_supports( array $supports ) { - return $this->set_config( 'supports', $supports ); - } + /** + * Core feature(s) the post type supports. Serves as an alias for calling add_post_type_support() directly. Core + * features include 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', + * 'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'. Additionally, the 'revisions' feature + * dictates whether the post type will store revisions, and the 'comments' feature dictates whether the comments + * count will show on the edit screen. A feature can also be specified as an array of arguments to provide + * additional information about supporting that feature. + * + * Example: array( 'my_feature', array( 'field' => 'value' ) ). + * + * Default is an array containing 'title' and 'editor'. + * + * @param array $supports List of features this CPT should support. + * @return PostTypeBuilder + */ + public function set_supports(array $supports) + { + return $this->set_config('supports', $supports); + } - /** - * An array of taxonomy identifiers that will be registered for the post type. Taxonomies can be registered later with - * register_taxonomy() or register_taxonomy_for_object_type(). - * - * @param array $taxonomies List of taxonomy identifiers. - * @return PostTypeBuilder - */ - public function set_taxonomies( array $taxonomies ) { - return $this->set_config( 'taxonomies', $taxonomies ); - } + /** + * An array of taxonomy identifiers that will be registered for the post type. Taxonomies can be registered later + * with register_taxonomy() or register_taxonomy_for_object_type(). + * + * @param array $taxonomies List of taxonomy identifiers. + * @return PostTypeBuilder + */ + public function set_taxonomies(array $taxonomies) + { + return $this->set_config('taxonomies', $taxonomies); + } - /** - * Whether there should be post type archives, or if a string, the archive slug to use. Will generate the proper - * rewrite rules if $rewrite is enabled. Default false. - * - * @param bool|string $has_archive Whether this CPT has archive or not. - * @return PostTypeBuilder - */ - public function set_has_archive( $has_archive ) { - return $this->set_config( 'has_archive', $has_archive ); - } + /** + * Whether there should be post type archives, or if a string, the archive slug to use. Will generate the proper + * rewrite rules if $rewrite is enabled. Default false. + * + * @param bool|string $has_archive Whether this CPT has archive or not. + * @return PostTypeBuilder + */ + public function set_has_archive($has_archive) + { + return $this->set_config('has_archive', $has_archive); + } - /** - * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. Defaults to true, using - * $post_type as slug. - * - * Prefer using https://github.com/Upstatement/routes. - * - * @param bool|array $rewrite Rewrite rules for this CPT. - * @return PostTypeBuilder - */ - public function set_rewrite( $rewrite ) { - return $this->set_config( 'rewrite', $rewrite ); - } + /** + * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. Defaults to true, using + * $post_type as slug. + * + * Prefer using https://github.com/Upstatement/routes. + * + * @param bool|array $rewrite Rewrite rules for this CPT. + * @return PostTypeBuilder + */ + public function set_rewrite($rewrite) + { + return $this->set_config('rewrite', $rewrite); + } - /** - * Sets the query_var key for this post type. Defaults to $post_type key. If false, a post type cannot be loaded at - * ?{query_var}={post_slug}. If specified as a string, the query ?{query_var_string}={post_slug} will be valid. - * - * @param string|bool $query_var The query var key. - * @return PostTypeBuilder - */ - public function set_query_var( $query_var ) { - return $this->set_config( 'query_var', $query_var ); - } + /** + * Sets the query_var key for this post type. Defaults to $post_type key. If false, a post type cannot be loaded at + * ?{query_var}={post_slug}. If specified as a string, the query ?{query_var_string}={post_slug} will be valid. + * + * @param string|bool $query_var The query var key. + * @return PostTypeBuilder + */ + public function set_query_var($query_var) + { + return $this->set_config('query_var', $query_var); + } - /** - * Whether to allow this post type to be exported. Default true. - * - * @param bool $can_export Wether to allow export or not. - * @return PostTypeBuilder - */ - public function set_can_export( bool $can_export ) { - return $this->set_config( 'can_export', $can_export ); - } + /** + * Whether to allow this post type to be exported. Default true. + * + * @param bool $can_export Wether to allow export or not. + * @return PostTypeBuilder + */ + public function set_can_export(bool $can_export) + { + return $this->set_config('can_export', $can_export); + } - /** - * Whether to delete posts of this type when deleting a user. If true, posts of this type belonging to the user will - * be moved to Trash when then user is deleted. If false, posts of this type belonging to the user will *not* be - * trashed or deleted. If not set (the default), posts are trashed if post_type_supports('author'). Otherwise posts - * are not trashed or deleted. Default null. - * - * @param bool $delete_with_user Wether to delete posts when their author is deleted or not. - * @return PostTypeBuilder - */ - public function set_delete_with_user( bool $delete_with_user ) { - return $this->set_config( 'delete_with_user', $delete_with_user ); - } + /** + * Whether to delete posts of this type when deleting a user. If true, posts of this type belonging to the user will + * be moved to Trash when then user is deleted. If false, posts of this type belonging to the user will *not* be + * trashed or deleted. If not set (the default), posts are trashed if post_type_supports('author'). Otherwise posts + * are not trashed or deleted. Default null. + * + * @param bool $delete_with_user Wether to delete posts when their author is deleted or not. + * @return PostTypeBuilder + */ + public function set_delete_with_user(bool $delete_with_user) + { + return $this->set_config('delete_with_user', $delete_with_user); + } } diff --git a/src/Builders/TaxonomyBuilder.php b/src/Builders/TaxonomyBuilder.php index 2c9c0a1..9fa185d 100644 --- a/src/Builders/TaxonomyBuilder.php +++ b/src/Builders/TaxonomyBuilder.php @@ -15,325 +15,356 @@ /** * Build a custom post type. */ -class TaxonomyBuilder extends Builder { - /** - * The post type configuration. - * - * @var array - */ - public $default_config = array( - 'query_var' => true, - 'show_ui' => true, - 'show_admin_column' => true, - 'show_in_nav_menus' => true, - 'show_tagcloud' => true, - ); +class TaxonomyBuilder extends Builder +{ + /** + * The post type configuration. + * + * @var array + */ + public $default_config = array( + 'query_var' => true, + 'show_ui' => true, + 'show_admin_column' => true, + 'show_in_nav_menus' => true, + 'show_tagcloud' => true, + ); - /** - * The register method name. - * - * @var string - */ - public $register_method = 'register_taxonomy'; + /** + * The register method name. + * + * @var string + */ + public $register_method = 'register_taxonomy'; - /** - * The register method args. - * - * @var array - */ - public $register_method_args = array( 'type', 'post_types', 'config' ); + /** + * The register method args. + * + * @var array + */ + public $register_method_args = array( 'type', 'post_types', 'config' ); - /** - * The post types which associated to this taxonomy. - * - * @var string|array - */ - protected $post_types = array(); + /** + * The post types which associated to this taxonomy. + * + * @var string|array + */ + protected $post_types = array(); - /** - * Set the taxonomy post types. - * - * @param string|array $post_types Object type or array of object types with which the taxonomy should be associated. - * @return $this; - */ - public function set_post_types( $post_types ):self { - $this->post_types = $post_types; - return $this; - } + /** + * Set the taxonomy post types. + * + * @param string|array $post_types Object or array of objects with which the taxonomy should be associated. + * @return $this; + */ + public function set_post_types($post_types):self + { + $this->post_types = $post_types; + return $this; + } - /** - * Get the associated post types. - * - * @return string|array The name or a list of names of post types. - */ - public function get_post_types() { - return $this->post_types; - } + /** + * Get the associated post types. + * + * @return string|array The name or a list of names of post types. + */ + public function get_post_types() + { + return $this->post_types; + } - /** - * An array of labels for this post type. If not set, post labels are inherited for non-hierarchical types and page - * labels for hierarchical ones. - * - * @param string $singular The singular label. - * @param string $plural The plural label. - */ - public function set_labels( string $singular, string $plural ):self { - return $this->set_config( 'labels', $this->generate_labels( $singular, $plural ) ); - } + /** + * An array of labels for this post type. If not set, post labels are inherited for non-hierarchical types and page + * labels for hierarchical ones. + * + * @param string $singular The singular label. + * @param string $plural The plural label. + */ + public function set_labels(string $singular, string $plural):self + { + return $this->set_config('labels', $this->generate_labels($singular, $plural)); + } - /** - * Generate labels. - * - * @param string $singular Singular name. - * @param string $plural Plural name. - * @return array Labels. - */ - private function generate_labels( string $singular, string $plural ):array { + /** + * Generate labels. + * + * @param string $singular Singular name. + * @param string $plural Plural name. + * @return array Labels. + */ + private function generate_labels(string $singular, string $plural):array + { // phpcs:disable WordPress.WP.I18n - $labels = array( - 'name' => $plural, - 'singular_name' => $singular, - 'add_new_item' => sprintf( __( 'Add New %s', 'studiometa' ), $singular ), - 'all_items' => sprintf( __( 'All %s', 'studiometa' ), $plural ), - 'choose_from_most_used' => __( 'Most used', 'studiometa' ), - 'edit_item' => sprintf( __( 'Edit %s', 'studiometa' ), $singular ), - 'items_list' => sprintf( __( '%s list', 'studiometa' ), $plural ), - 'items_list_navigation' => sprintf( __( '%s list navigation', 'studiometa' ), $plural ), - 'menu_name' => $plural, - 'new_item_name' => sprintf( __( 'New %s', 'studiometa' ), $singular ), - 'no_terms' => sprintf( __( 'No %s', 'studiometa' ), $singular ), - 'parent_item' => sprintf( __( '%s parent', 'studiometa' ), $singular ), - 'parent_item_colon' => isset( $this->get_config()['hierarchical'] ) && $this->get_config()['hierarchical'] ? sprintf( __( '%s parent:', 'studiometa' ), $singular ) : null, - 'popular_items' => sprintf( __( 'Popular %s', 'studiometa' ), $singular ), - 'search_items' => sprintf( __( 'Search %s', 'studiometa' ), $plural ), - 'update_item' => sprintf( __( 'Update the %s', 'studiometa' ), $singular ), - 'view_item' => sprintf( __( 'View %s', 'studiometa' ), $singular ), - ); + $labels = array( + 'name' => $plural, + 'singular_name' => $singular, + 'add_new_item' => sprintf(__('Add New %s', 'studiometa'), $singular), + 'all_items' => sprintf(__('All %s', 'studiometa'), $plural), + 'choose_from_most_used' => __('Most used', 'studiometa'), + 'edit_item' => sprintf(__('Edit %s', 'studiometa'), $singular), + 'items_list' => sprintf(__('%s list', 'studiometa'), $plural), + 'items_list_navigation' => sprintf(__('%s list navigation', 'studiometa'), $plural), + 'menu_name' => $plural, + 'new_item_name' => sprintf(__('New %s', 'studiometa'), $singular), + 'no_terms' => sprintf(__('No %s', 'studiometa'), $singular), + 'parent_item' => sprintf(__('%s parent', 'studiometa'), $singular), + 'parent_item_colon' => isset($this->get_config()['hierarchical']) && $this->get_config()['hierarchical'] + ? sprintf(__('%s parent:', 'studiometa'), $singular) + : null, + 'popular_items' => sprintf(__('Popular %s', 'studiometa'), $singular), + 'search_items' => sprintf(__('Search %s', 'studiometa'), $plural), + 'update_item' => sprintf(__('Update the %s', 'studiometa'), $singular), + 'view_item' => sprintf(__('View %s', 'studiometa'), $singular), + ); // phpcs:enable - return $labels; - } + return $labels; + } - /** - * A short descriptive summary of what the taxonomy is for. - * - * @param string $description The description. - * @return $this - */ - public function set_description( string $description ):self { - return $this->set_config( 'description', $description ); - } + /** + * A short descriptive summary of what the taxonomy is for. + * + * @param string $description The description. + * @return $this + */ + public function set_description(string $description):self + { + return $this->set_config('description', $description); + } - /** - * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users. The default - * settings of $publicly_queryable, $show_ui, and $show_in_nav_menus are inherited from $public. - * - * @param bool $public Public or not. - * @return $this - */ - public function set_public( bool $public ):self { - return $this->set_config( 'public', $public ); - } + /** + * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users. The default + * settings of $publicly_queryable, $show_ui, and $show_in_nav_menus are inherited from $public. + * + * @param bool $public Public or not. + * @return $this + */ + public function set_public(bool $public):self + { + return $this->set_config('public', $public); + } - /** - * Whether the taxonomy is publicly queryable. If not set, the default is inherited from $public. - * - * @param bool $publicly_queryable Is publicly queryable or not. - * @return $this - */ - public function set_publicly_queryable( bool $publicly_queryable ):self { - return $this->set_config( 'publicly_queryable', $publicly_queryable ); - } + /** + * Whether the taxonomy is publicly queryable. If not set, the default is inherited from $public. + * + * @param bool $publicly_queryable Is publicly queryable or not. + * @return $this + */ + public function set_publicly_queryable(bool $publicly_queryable):self + { + return $this->set_config('publicly_queryable', $publicly_queryable); + } - /** - * Whether the taxonomy is hierarchical. Default false. - * - * @param bool $hierarchical Hierarchical or not. - * @return $this - */ - public function set_hierarchical( bool $hierarchical ):self { - return $this->set_config( 'hierarchical', $hierarchical ); - } + /** + * Whether the taxonomy is hierarchical. Default false. + * + * @param bool $hierarchical Hierarchical or not. + * @return $this + */ + public function set_hierarchical(bool $hierarchical):self + { + return $this->set_config('hierarchical', $hierarchical); + } - /** - * Whether to generate and allow a UI for managing terms in this taxonomy in the admin. If not set, the default is - * inherited from $public. Default to true. - * - * @param bool $show_ui Show the UI or not. - * @return $this - */ - public function set_show_ui( bool $show_ui ):self { - return $this->set_config( 'show_ui', $show_ui ); - } + /** + * Whether to generate and allow a UI for managing terms in this taxonomy in the admin. If not set, the default is + * inherited from $public. Default to true. + * + * @param bool $show_ui Show the UI or not. + * @return $this + */ + public function set_show_ui(bool $show_ui):self + { + return $this->set_config('show_ui', $show_ui); + } - /** - * Whether to show the taxonomy in the admin menu or not. If true, the taxonomy is shown as a submenu of the object - * type menu. If false, no menu is shown. $show_ui must be true. If not set, default is inherited from $show_ui. - * Default to true. - * - * @param bool $show_in_menu Show in menu or not. - * @return $this - */ - public function set_show_in_menu( bool $show_in_menu ):self { - return $this->set_config( 'show_in_menu', $show_in_menu ); - } + /** + * Whether to show the taxonomy in the admin menu or not. If true, the taxonomy is shown as a submenu of the object + * type menu. If false, no menu is shown. $show_ui must be true. If not set, default is inherited from $show_ui. + * Default to true. + * + * @param bool $show_in_menu Show in menu or not. + * @return $this + */ + public function set_show_in_menu(bool $show_in_menu):self + { + return $this->set_config('show_in_menu', $show_in_menu); + } - /** - * Makes this taxonomy available for selection in navigation menus. If not set, the default is inherited from $public. - * Default to true. - * - * @param bool $show_in_nav_menus Show in nav menus or not. - * @return $this - */ - public function set_show_in_nav_menus( bool $show_in_nav_menus ):self { - return $this->set_config( 'show_in_nav_menus', $show_in_nav_menus ); - } + /** + * Makes this taxonomy available for selection in navigation menus. If not set, the default is inherited from + * $public. + * + * Default to true. + * + * @param bool $show_in_nav_menus Show in nav menus or not. + * @return $this + */ + public function set_show_in_nav_menus(bool $show_in_nav_menus):self + { + return $this->set_config('show_in_nav_menus', $show_in_nav_menus); + } - /** - * Whether to include the taxonomy in the REST API. Set this to true for the taxonomy to be available in the - * block editor. - * - * @param bool $show_in_rest Show in taxonomy or not. - * @return $this - */ - public function set_show_in_rest( bool $show_in_rest ):self { - return $this->set_config( 'show_in_rest', $show_in_rest ); - } + /** + * Whether to include the taxonomy in the REST API. Set this to true for the taxonomy to be available in the + * block editor. + * + * @param bool $show_in_rest Show in taxonomy or not. + * @return $this + */ + public function set_show_in_rest(bool $show_in_rest):self + { + return $this->set_config('show_in_rest', $show_in_rest); + } - /** - * To change the base url of REST API route. Default is $taxonomy. - * - * @param string $rest_base The REST API base route value. - * @return $this - */ - public function set_rest_base( string $rest_base ):self { - return $this->set_config( 'rest_base', $rest_base ); - } + /** + * To change the base url of REST API route. Default is $taxonomy. + * + * @param string $rest_base The REST API base route value. + * @return $this + */ + public function set_rest_base(string $rest_base):self + { + return $this->set_config('rest_base', $rest_base); + } - /** - * REST API Controller class name. Default is 'WP_REST_Terms_Controller'. - * - * @param string $rest_controller_class The REST API Controller class name. - * @return $this - */ - public function set_rest_controller_class( string $rest_controller_class ):self { - return $this->set_config( 'rest_controller_class', $rest_controller_class ); - } + /** + * REST API Controller class name. Default is 'WP_REST_Terms_Controller'. + * + * @param string $rest_controller_class The REST API Controller class name. + * @return $this + */ + public function set_rest_controller_class(string $rest_controller_class):self + { + return $this->set_config('rest_controller_class', $rest_controller_class); + } - /** - * Whether to list the taxonomy in the Tag Cloud Widget controls. If not set, the default is inherited from $show_ui. - * Default to true. - * - * @param bool $show_tagcloud Show in tag cloud or not. - * @return $this - */ - public function set_show_tagcloud( bool $show_tagcloud ):self { - return $this->set_config( 'show_tagcloud', $show_tagcloud ); - } + /** + * Whether to list the taxonomy in the Tag Cloud Widget controls. If not set, the default is inherited from + * $show_ui. + * + * Default to true. + * + * @param bool $show_tagcloud Show in tag cloud or not. + * @return $this + */ + public function set_show_tagcloud(bool $show_tagcloud):self + { + return $this->set_config('show_tagcloud', $show_tagcloud); + } - /** - * Whether to show the taxonomy in the quick/bulk edit panel. It not set, the default is inherited from $show_ui. - * Default to true. - * - * @param bool $show_in_quick_edit Show in quick edit or not. - * @return $this - */ - public function set_show_in_quick_edit( bool $show_in_quick_edit ):self { - return $this->set_config( 'show_in_quick_edit', $show_in_quick_edit ); - } + /** + * Whether to show the taxonomy in the quick/bulk edit panel. It not set, the default is inherited from $show_ui. + * Default to true. + * + * @param bool $show_in_quick_edit Show in quick edit or not. + * @return $this + */ + public function set_show_in_quick_edit(bool $show_in_quick_edit):self + { + return $this->set_config('show_in_quick_edit', $show_in_quick_edit); + } - /** - * Whether to display a column for the taxonomy on its post type listing screens. Default false. - * - * @param bool $show_admin_column Show or column or not. - * @return $this - */ - public function set_show_admin_column( bool $show_admin_column ):self { - return $this->set_config( 'show_admin_column', $show_admin_column ); - } + /** + * Whether to display a column for the taxonomy on its post type listing screens. Default false. + * + * @param bool $show_admin_column Show or column or not. + * @return $this + */ + public function set_show_admin_column(bool $show_admin_column):self + { + return $this->set_config('show_admin_column', $show_admin_column); + } - /** - * Provide a callback function for the meta box display. If not set, post_categories_meta_box() is used for - * hierarchical taxonomies, and post_tags_meta_box() is used for non-hierarchical. If false, no meta box is shown. - * - * @param bool|callable $meta_box_cb The callback function. - * @return $this - */ - public function set_meta_box_cb( $meta_box_cb ):self { - return $this->set_config( 'meta_box_cb', $meta_box_cb ); - } + /** + * Provide a callback function for the meta box display. If not set, post_categories_meta_box() is used for + * hierarchical taxonomies, and post_tags_meta_box() is used for non-hierarchical. If false, no meta box is shown. + * + * @param bool|callable $meta_box_cb The callback function. + * @return $this + */ + public function set_meta_box_cb($meta_box_cb):self + { + return $this->set_config('meta_box_cb', $meta_box_cb); + } - /** - * Callback function for sanitizing taxonomy data saved from a meta box. If no callback is defined, an appropriate one - * is determined based on the value of $meta_box_cb. - * - * @param callable $meta_box_sanitize_cb The callback function. - * @return $this - */ - public function set_meta_box_sanitize_cb( $meta_box_sanitize_cb ):self { - return $this->set_config( 'meta_box_sanitize_cb', $meta_box_sanitize_cb ); - } + /** + * Callback function for sanitizing taxonomy data saved from a meta box. If no callback is defined, an appropriate + * one is determined based on the value of $meta_box_cb. + * + * @param callable $meta_box_sanitize_cb The callback function. + * @return $this + */ + public function set_meta_box_sanitize_cb($meta_box_sanitize_cb):self + { + return $this->set_config('meta_box_sanitize_cb', $meta_box_sanitize_cb); + } - /** - * Array of capabilities for this taxonomy. - * - * @param array $capabilities Array of capabilities for this taxonomy. - * @return $this - */ - public function set_capabilities( array $capabilities ):self { - return $this->set_config( 'capabilities', $capabilities ); - } + /** + * Array of capabilities for this taxonomy. + * + * @param array $capabilities Array of capabilities for this taxonomy. + * @return $this + */ + public function set_capabilities(array $capabilities):self + { + return $this->set_config('capabilities', $capabilities); + } - /** - * Triggers the handling of rewrites for this taxonomy. Default true, using $taxonomy as slug. To prevent rewrite, set - * to false. To specify rewrite rules, an array can be passed with any of these keys: - * - * - `slug` (string) Customize the permastruct slug. Default $taxonomy key. - * - `with_front` (bool) Should the permastruct be prepended with WP_Rewrite::$front. Default true. - * - `hierarchical` (bool) Either hierarchical rewrite tag or not. Default false. - * - `ep_mask` (int) Assign an endpoint mask. Default EP_NONE. - * - * @param bool|array $rewrite The rewrite configuration. - * @return $this - */ - public function set_rewrite( $rewrite ):self { - return $this->set_config( 'rewrite', $rewrite ); - } + /** + * Triggers the handling of rewrites for this taxonomy. Default true, using $taxonomy as slug. To prevent rewrite, + * set to false. To specify rewrite rules, an array can be passed with any of these keys: + * + * - `slug` (string) Customize the permastruct slug. Default $taxonomy key. + * - `with_front` (bool) Should the permastruct be prepended with WP_Rewrite::$front. Default true. + * - `hierarchical` (bool) Either hierarchical rewrite tag or not. Default false. + * - `ep_mask` (int) Assign an endpoint mask. Default EP_NONE. + * + * @param bool|array $rewrite The rewrite configuration. + * @return $this + */ + public function set_rewrite($rewrite):self + { + return $this->set_config('rewrite', $rewrite); + } - /** - * Sets the query var key for this taxonomy. Default $taxonomy key. If false, a taxonomy cannot be loaded at - * ?{query_var}={term_slug}. If a string, the query ?{query_var}={term_slug} will be valid. - * - * @param string|bool $query_var The query var value. - * @return $this - */ - public function set_query_var( $query_var ):self { - return $this->set_config( 'query_var', $query_var ); - } + /** + * Sets the query var key for this taxonomy. Default $taxonomy key. If false, a taxonomy cannot be loaded at + * ?{query_var}={term_slug}. If a string, the query ?{query_var}={term_slug} will be valid. + * + * @param string|bool $query_var The query var value. + * @return $this + */ + public function set_query_var($query_var):self + { + return $this->set_config('query_var', $query_var); + } - /** - * Works much like a hook, in that it will be called when the count is updated. Default _update_post_term_count() for - * taxonomies attached to post types, which confirms that the objects are published before counting them. Default - * _update_generic_term_count() for taxonomies attached to other object types, such as users. - * - * @param callable $update_count_callback The callback function. - * @return $this - */ - public function set_update_count_callback( $update_count_callback ):self { - return $this->set_config( 'update_count_callback', $update_count_callback ); - } + /** + * Works much like a hook, in that it will be called when the count is updated. Default _update_post_term_count() + * for taxonomies attached to post types, which confirms that the objects are published before counting them. + * Default _update_generic_term_count() for taxonomies attached to other object types, such as users. + * + * @param callable $update_count_callback The callback function. + * @return $this + */ + public function set_update_count_callback($update_count_callback):self + { + return $this->set_config('update_count_callback', $update_count_callback); + } - /** - * Default term to be used for the taxonomy. If an array, it can have the following keys: - * - * - `name` (string) Name of default term. - * - `slug` (string) Slug for default term. - * - `description` (string) Description for default term. - * - * @param string|array $default_term The default term value. - * @return $this - */ - public function set_default_term( $default_term ):self { - return $this->set_config( 'default_term', $default_term ); - } + /** + * Default term to be used for the taxonomy. If an array, it can have the following keys: + * + * - `name` (string) Name of default term. + * - `slug` (string) Slug for default term. + * - `description` (string) Description for default term. + * + * @param string|array $default_term The default term value. + * @return $this + */ + public function set_default_term($default_term):self + { + return $this->set_config('default_term', $default_term); + } } diff --git a/src/Helpers/Env.php b/src/Helpers/Env.php index 78876b6..5f92efe 100644 --- a/src/Helpers/Env.php +++ b/src/Helpers/Env.php @@ -2,19 +2,21 @@ namespace Studiometa\WPToolkit\Helpers; -class Env { - /** - * Get an environment variable value. - * - * @param string $key The variable name. - * @return string - */ - public static function get( string $key ): string { +class Env +{ + /** + * Get an environment variable value. + * + * @param string $key The variable name. + * @return string + */ + public static function get(string $key): string + { // phpcs:ignore /** @var array Good type. */ - $env = $_ENV; - // In some environment, values are not available in the `$_ENV` variables, - // so we use `getenv` as a fallback to try and get the value. - return $env[ $key ] ?? (string) getenv( $key ); - } + $env = $_ENV; + // In some environment, values are not available in the `$_ENV` variables, + // so we use `getenv` as a fallback to try and get the value. + return $env[ $key ] ?? (string) getenv($key); + } } diff --git a/src/Helpers/Plugin.php b/src/Helpers/Plugin.php index 49cdcb9..e2f6bc3 100644 --- a/src/Helpers/Plugin.php +++ b/src/Helpers/Plugin.php @@ -19,112 +19,118 @@ /** * Plugins class. */ -class Plugin { - - /** - * Disabled plugins. - * - * @var string[] - */ - private static $disabled_plugins = array(); - - /** - * Class instance. - * @var self - */ - private static $instance = null; - - /** - * Hook into the activation filters on construction. - */ - private function __construct( ) { - early_add_filter( - 'option_active_plugins', - function( array $plugins ) { - return self::do_disabling( $plugins ); - } - ); - early_add_filter( - 'site_option_active_sitewide_plugins', - function( array $plugins ) { - return self::do_network_disabling( $plugins ); - } - ); - } - - /** - * Hooks in to the option_active_plugins filter and does the disabling - * - * @param string[] $plugins WP-provided list of plugin filenames. - * - * @return string[] The filtered array of plugin filenames - */ - private static function do_disabling( array $plugins ): array { - if ( count( self::$disabled_plugins ) ) { - foreach ( self::$disabled_plugins as $disabled_plugin ) { - $key = array_search( $disabled_plugin, $plugins, true ); - if ( false !== $key ) { - unset( $plugins[ $key ] ); - } - } - } - - return $plugins; - } - - /** - * Hooks in to the site_option_active_sitewide_plugins filter and does the disabling - * - * @param string[] $plugins Plugins. - * - * @return string[] - */ - private static function do_network_disabling( $plugins ) { - if ( count( self::$disabled_plugins ) ) { - foreach ( (array) self::$disabled_plugins as $plugin ) { - if ( isset( $plugins[ $plugin ] ) ) { - unset( $plugins[ $plugin ] ); - } - } - } - - return $plugins; - } - - /** - * Disable a list of plugins. - * - * @param string[] $plugins The list of plugins to disable. - */ - public static function disable( array $plugins ): void { - self::$disabled_plugins = self::$disabled_plugins + $plugins; - - if ( is_null( self::$instance) ) { - self::$instance = new self(); - } - } - - /** - * Test if plugin is enabled. - * - * @param string $filepath Plugin filepath (relative to plugins folder). - * - * @codeCoverageIgnore - * - * @return boolean Is the plugin enabled? - */ - public static function is_plugin_enabled( string $filepath ):bool { - $cache_key = __FUNCTION__ . md5( $filepath ); - $cached_results = wp_cache_get( $cache_key, __CLASS__ ); - - if ( false !== $cached_results ) { - return (bool) $cached_results; - } - - $is_enabled = is_plugin_active( $filepath ); - - wp_cache_set( $cache_key, (int) $is_enabled, __CLASS__ ); - - return $is_enabled; - } +class Plugin +{ + + /** + * Disabled plugins. + * + * @var string[] + */ + private static $disabled_plugins = array(); + + /** + * Class instance. + * @var self|null + */ + private static $instance = null; + + /** + * Hook into the activation filters on construction. + */ + private function __construct() + { + early_add_filter( + 'option_active_plugins', + function (array $plugins) { + return self::do_disabling($plugins); + } + ); + early_add_filter( + 'site_option_active_sitewide_plugins', + function (array $plugins) { + return self::do_network_disabling($plugins); + } + ); + } + + /** + * Hooks in to the option_active_plugins filter and does the disabling + * + * @param string[] $plugins WP-provided list of plugin filenames. + * + * @return string[] The filtered array of plugin filenames + */ + private static function do_disabling(array $plugins): array + { + if (count(self::$disabled_plugins)) { + foreach (self::$disabled_plugins as $disabled_plugin) { + $key = array_search($disabled_plugin, $plugins, true); + if (false !== $key) { + unset($plugins[ $key ]); + } + } + } + + return $plugins; + } + + /** + * Hooks in to the site_option_active_sitewide_plugins filter and does the disabling + * + * @param string[] $plugins Plugins. + * + * @return string[] + */ + private static function do_network_disabling($plugins) + { + if (count(self::$disabled_plugins)) { + foreach ((array) self::$disabled_plugins as $plugin) { + if (isset($plugins[ $plugin ])) { + unset($plugins[ $plugin ]); + } + } + } + + return $plugins; + } + + /** + * Disable a list of plugins. + * + * @param string[] $plugins The list of plugins to disable. + */ + public static function disable(array $plugins): void + { + self::$disabled_plugins = self::$disabled_plugins + $plugins; + + if (is_null(self::$instance)) { + self::$instance = new self(); + } + } + + /** + * Test if plugin is enabled. + * + * @param string $filepath Plugin filepath (relative to plugins folder). + * + * @codeCoverageIgnore + * + * @return boolean Is the plugin enabled? + */ + public static function is_plugin_enabled(string $filepath):bool + { + $cache_key = __FUNCTION__ . md5($filepath); + $cached_results = wp_cache_get($cache_key, __CLASS__); + + if (false !== $cached_results) { + return (bool) $cached_results; + } + + $is_enabled = is_plugin_active($filepath); + + wp_cache_set($cache_key, (int) $is_enabled, __CLASS__); + + return $is_enabled; + } } diff --git a/src/Helpers/Request.php b/src/Helpers/Request.php index 3dc3eaa..199ef1f 100644 --- a/src/Helpers/Request.php +++ b/src/Helpers/Request.php @@ -4,47 +4,51 @@ use Symfony\Component\HttpFoundation\Request as SymfonyRequest; -class Request { - /** - * Private variable to hold the helpers instance. - * - * @var ?Request - */ - private static $instance = null; - - /** - * Private variables to hold the current request instance. - * - * @var SymfonyRequest - */ - private SymfonyRequest $request; - - /** - * Private constructor. - */ - private function __construct() { - $this->request = SymfonyRequest::createFromGlobals(); - } - - /** - * Get singleton instance. - * - * @return Request - */ - private static function get_instance() { - if ( is_null( self::$instance ) ) { - self::$instance = new self(); - } - - return self::$instance; - } - - /** - * Work with the current HTTP request. - * - * @return SymfonyRequest - */ - public static function request(): SymfonyRequest { - return self::get_instance()->request; - } +class Request +{ + /** + * Private variable to hold the helpers instance. + * + * @var ?Request + */ + private static $instance = null; + + /** + * Private variables to hold the current request instance. + * + * @var SymfonyRequest + */ + private SymfonyRequest $request; + + /** + * Private constructor. + */ + private function __construct() + { + $this->request = SymfonyRequest::createFromGlobals(); + } + + /** + * Get singleton instance. + * + * @return Request + */ + private static function get_instance() + { + if (is_null(self::$instance)) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * Work with the current HTTP request. + * + * @return SymfonyRequest + */ + public static function request(): SymfonyRequest + { + return self::get_instance()->request; + } } diff --git a/src/Managers/AssetsManager.php b/src/Managers/AssetsManager.php index 3c337a8..050892a 100644 --- a/src/Managers/AssetsManager.php +++ b/src/Managers/AssetsManager.php @@ -19,334 +19,344 @@ /** * Helper class to manage a theme's assets. */ -class AssetsManager implements ManagerInterface { - /** - * The parsed configuration. - * - * @var array - */ - public $config; - - /** - * The parsed Webpack manifest. - * - * @var Manifest - */ - public $webpack_manifest; - - /** - * Configuration filepath. - * - * @var string - */ - private $configuration_filepath; - - /** - * Webpack manifest filepath. - * - * @var string - */ - private $webpack_manifest_filepath; - - /** - * Constructor. - * - * @param string|null $configuration_filepath Configuration filepath. - * @param string|null $webpack_manifest_filepath Webpack manifest filepath. - */ - public function __construct( ?string $configuration_filepath = null, ?string $webpack_manifest_filepath = null ) { - $this->configuration_filepath = get_template_directory() . '/config/assets.yml'; - $this->webpack_manifest_filepath = get_template_directory() . '/dist/assets-manifest.json'; - - if ( isset( $configuration_filepath ) ) { - $this->configuration_filepath = $configuration_filepath; - } - - if ( isset( $webpack_manifest_filepath ) ) { - $this->webpack_manifest_filepath = $webpack_manifest_filepath; - } - } +class AssetsManager implements ManagerInterface +{ + /** + * The parsed configuration. + * + * @var array + */ + public $config; + + /** + * The parsed Webpack manifest. + * + * @var Manifest + */ + public $webpack_manifest; + + /** + * Configuration filepath. + * + * @var string + */ + private $configuration_filepath; + + /** + * Webpack manifest filepath. + * + * @var string + */ + private $webpack_manifest_filepath; + + /** + * Constructor. + * + * @param string|null $configuration_filepath Configuration filepath. + * @param string|null $webpack_manifest_filepath Webpack manifest filepath. + */ + public function __construct(?string $configuration_filepath = null, ?string $webpack_manifest_filepath = null) + { + $this->configuration_filepath = get_template_directory() . '/config/assets.yml'; + $this->webpack_manifest_filepath = get_template_directory() . '/dist/assets-manifest.json'; + + if (isset($configuration_filepath)) { + $this->configuration_filepath = $configuration_filepath; + } + + if (isset($webpack_manifest_filepath)) { + $this->webpack_manifest_filepath = $webpack_manifest_filepath; + } + } // phpcs:ignore Generic.Commenting.DocComment.MissingShort - /** - * @inheritdoc - */ - public function run() { - if ( ! file_exists( $this->configuration_filepath ) ) { - $msg = 'No assets configuration file found.'; + /** + * @inheritdoc + */ + public function run() + { + if (! file_exists($this->configuration_filepath)) { + $msg = 'No assets configuration file found.'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error - trigger_error( esc_html( $msg ), E_USER_NOTICE ); - return; - } + trigger_error(esc_html($msg), E_USER_NOTICE); + return; + } - // @phpstan-ignore-next-line - $this->config = Yaml::parseFile( $this->configuration_filepath ); + // @phpstan-ignore-next-line + $this->config = Yaml::parseFile($this->configuration_filepath); - if ( $this->webpack_manifest_filepath ) { - if ( ! file_exists( $this->webpack_manifest_filepath ) ) { - $msg = sprintf( 'No webpack manifest file found in `%s`.', $this->webpack_manifest_filepath ); + if ($this->webpack_manifest_filepath) { + if (! file_exists($this->webpack_manifest_filepath)) { + $msg = sprintf('No webpack manifest file found in `%s`.', $this->webpack_manifest_filepath); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error - trigger_error( esc_html( $msg ), E_USER_NOTICE ); - return; - } - - $this->webpack_manifest = new Manifest( - $this->webpack_manifest_filepath, - $this->get_webpack_public_path_relative_to_theme() - ); - } - - add_action( 'wp_enqueue_scripts', array( $this, 'register_all' ) ); - add_filter( 'template_include', array( $this, 'enqueue_all' ) ); - } - - /** - * Get Webpack dist folder relative to the theme. - * - * @returns string - */ - private function get_webpack_public_path_relative_to_theme():string { - return trim( str_replace( get_template_directory(), '', dirname( $this->webpack_manifest_filepath ) ), '/' ) . '/'; - } - - /** - * Register all defined JS and CSS assets with automatic - * versioning based on their content's MD5 hash. - * - * @return void - */ - public function register_all() { - foreach ( $this->config as $name => $config ) { - if ( isset( $config['entries'] ) && is_array( $config['entries'] ) ) { - foreach ( $config['entries'] as $entry ) { - $pathinfo = pathinfo( $entry ); - $entry = implode( - DIRECTORY_SEPARATOR, - array( $pathinfo['dirname'] ?? '', $pathinfo['filename'] ) - ); - - $webpack_entry = $this->webpack_manifest->entry( $entry ); - - if ( ! $webpack_entry ) { - continue; - } - - $webpack_entry->styles->each( - function ( $style, $handle ) { - $this->register( 'style', $handle, $style->getAttribute( 'href' ) ); - } - ); - - $webpack_entry->scripts->each( - function ( $script, $handle ) { - $this->register( 'script', $handle, $script->getAttribute( 'src' ) ); - } - ); - } - } - - if ( isset( $config['css'] ) ) { - foreach ( $config['css'] as $handle => $path ) { - $this->register( 'style', $handle, $path ); - - // Enqueue directly if the name of the config is 'all'. - if ( 'all' === $name ) { - wp_enqueue_style( $handle ); - } - } - } - - if ( isset( $config['js'] ) ) { - foreach ( $config['js'] as $handle => $path ) { - $this->register( 'script', $handle, $path ); - - // Enqueue directly if the name of the config is 'all'. - if ( 'all' === $name ) { - wp_enqueue_script( $handle ); - } - } - } - } - } - - /** - * Enqueue CSS and JS files based on the WordPress template. - * - * @param string $template The template path. - * @return string The template path. - */ - public function enqueue_all( $template ) { - $potential_names = array( 'all' ) + $this->get_potential_names( $template ); - - foreach ( $potential_names as $potential_name ) { - foreach ( $this->config as $name => $config ) { - if ( (string) $name !== $potential_name ) { - continue; - } - - if ( isset( $config['entries'] ) && is_array( $config['entries'] ) ) { - foreach ( $config['entries'] as $entry ) { - $pathinfo = pathinfo( $entry ); - $entry = implode( - DIRECTORY_SEPARATOR, - array( $pathinfo['dirname'] ?? '', $pathinfo['filename'] ) - ); - - $webpack_entry = $this->webpack_manifest->entry( $entry ); - - if ( ! $webpack_entry ) { - continue; - } - - $webpack_entry->styles->keys()->each( - function ( $handle ) { - $this->enqueue( 'style', $handle ); - } - ); - - $webpack_entry->scripts->keys()->each( - function ( $handle ) { - $this->enqueue( 'script', $handle ); - } - ); - } - } - - if ( isset( $config['css'] ) ) { - foreach ( $config['css'] as $handle => $path ) { - $this->enqueue( 'style', $handle ); - } - } - - if ( isset( $config['js'] ) ) { - foreach ( $config['js'] as $handle => $path ) { - $this->enqueue( 'script', $handle ); - } - } - } - } - - return $template; - } - - /** - * Get all the potential assets group name. - * For a template file `single-post-hello.php`, the following group names - * will be returned: - * - * - single - * - single-post - * - single-post-hello - * - * @param string $template The full template path. - * @return array A list of potential assets name. - */ - protected function get_potential_names( string $template ):array { - $pathinfo = pathinfo( $template ); - $parts = explode( '-', $pathinfo['filename'] ); - - return array_reduce( - $parts, - function ( $acc, $part ) { - if ( empty( $acc ) ) { - return array( $part ); - } - - $previous_part = $acc[ count( $acc ) - 1 ]; - $acc[] = $previous_part . '-' . $part; - - return $acc; - }, - array() - ); - } - - - /** - * Register a single asset. - * - * @param string $type The type of the asset: 'style' or 'script'. - * @param string $handle The asset's handle. - * @param string|array $path The asset's path in the theme. - * @return void - */ - protected function register( string $type, string $handle, $path ):void { - $handle = $this->format_handle( $handle ); - - if ( is_array( $path ) ) { - $_path = $path; - $path = $_path['path']; - $media = $_path['media'] ?? 'all'; - $in_footer = $_path['footer'] ?? true; - } else { - $media = 'all'; - $in_footer = true; - } - - $webpack_path = str_replace( $this->get_webpack_public_path_relative_to_theme(), '', $path ); - - // Read path from Webpack manifest if it exists. - if ( $this->webpack_manifest instanceof Manifest && $this->webpack_manifest->asset( $webpack_path ) ) { - $path = $this->webpack_manifest->asset( $webpack_path ); - } - - $path = trim( $path, '/' ); - $full_path = get_template_directory() . '/' . $path; - $public_uri = get_template_directory_uri() . '/' . $path; - - $hash = null; - if ( file_exists( $full_path ) ) { - $hash = md5_file( $full_path ); - } - - if ( 'style' === $type ) { - wp_register_style( - $handle, - $public_uri, - array(), - $hash, - $media - ); - } else { - wp_register_script( - $handle, - $public_uri, - array(), - $hash, - $in_footer - ); - } - } - - /** - * Enqueue an asset given its handle. - * - * @param string $type The type of the asset: 'style' or 'script'. - * @param string $handle The asset's handle. - * @return void - */ - protected function enqueue( $type, $handle ) { - $handle = $this->format_handle( $handle ); - - add_action( - 'wp_enqueue_scripts', - function () use ( $type, $handle ) { - if ( 'style' === $type ) { - wp_enqueue_style( $handle ); - } else { - wp_enqueue_script( $handle ); - } - } - ); - } - - /** - * Prefix all handles with `theme-`. - * - * @param string $handle The handle to format. - * @return string - */ - protected function format_handle( string $handle ):string { - return 'theme-' . str_replace( '.', '-', $handle ); - } + trigger_error(esc_html($msg), E_USER_NOTICE); + return; + } + + $this->webpack_manifest = new Manifest( + $this->webpack_manifest_filepath, + $this->get_webpack_public_path_relative_to_theme() + ); + } + + add_action('wp_enqueue_scripts', array( $this, 'register_all' )); + add_filter('template_include', array( $this, 'enqueue_all' )); + } + + /** + * Get Webpack dist folder relative to the theme. + * + * @returns string + */ + private function get_webpack_public_path_relative_to_theme():string + { + return trim(str_replace(get_template_directory(), '', dirname($this->webpack_manifest_filepath)), '/') . '/'; + } + + /** + * Register all defined JS and CSS assets with automatic + * versioning based on their content's MD5 hash. + * + * @return void + */ + public function register_all() + { + foreach ($this->config as $name => $config) { + if (isset($config['entries']) && is_array($config['entries'])) { + foreach ($config['entries'] as $entry) { + $pathinfo = pathinfo($entry); + $entry = implode( + DIRECTORY_SEPARATOR, + array( $pathinfo['dirname'] ?? '', $pathinfo['filename'] ) + ); + + $webpack_entry = $this->webpack_manifest->entry($entry); + + if (! $webpack_entry) { + continue; + } + + $webpack_entry->styles->each( + function ($style, $handle) { + $this->register('style', $handle, $style->getAttribute('href')); + } + ); + + $webpack_entry->scripts->each( + function ($script, $handle) { + $this->register('script', $handle, $script->getAttribute('src')); + } + ); + } + } + + if (isset($config['css'])) { + foreach ($config['css'] as $handle => $path) { + $this->register('style', $handle, $path); + + // Enqueue directly if the name of the config is 'all'. + if ('all' === $name) { + wp_enqueue_style($handle); + } + } + } + + if (isset($config['js'])) { + foreach ($config['js'] as $handle => $path) { + $this->register('script', $handle, $path); + + // Enqueue directly if the name of the config is 'all'. + if ('all' === $name) { + wp_enqueue_script($handle); + } + } + } + } + } + + /** + * Enqueue CSS and JS files based on the WordPress template. + * + * @param string $template The template path. + * @return string The template path. + */ + public function enqueue_all($template) + { + $potential_names = array( 'all' ) + $this->get_potential_names($template); + + foreach ($potential_names as $potential_name) { + foreach ($this->config as $name => $config) { + if ((string) $name !== $potential_name) { + continue; + } + + if (isset($config['entries']) && is_array($config['entries'])) { + foreach ($config['entries'] as $entry) { + $pathinfo = pathinfo($entry); + $entry = implode( + DIRECTORY_SEPARATOR, + array( $pathinfo['dirname'] ?? '', $pathinfo['filename'] ) + ); + + $webpack_entry = $this->webpack_manifest->entry($entry); + + if (! $webpack_entry) { + continue; + } + + $webpack_entry->styles->keys()->each( + function ($handle) { + $this->enqueue('style', $handle); + } + ); + + $webpack_entry->scripts->keys()->each( + function ($handle) { + $this->enqueue('script', $handle); + } + ); + } + } + + if (isset($config['css'])) { + foreach ($config['css'] as $handle => $path) { + $this->enqueue('style', $handle); + } + } + + if (isset($config['js'])) { + foreach ($config['js'] as $handle => $path) { + $this->enqueue('script', $handle); + } + } + } + } + + return $template; + } + + /** + * Get all the potential assets group name. + * For a template file `single-post-hello.php`, the following group names + * will be returned: + * + * - single + * - single-post + * - single-post-hello + * + * @param string $template The full template path. + * @return array A list of potential assets name. + */ + protected function get_potential_names(string $template):array + { + $pathinfo = pathinfo($template); + $parts = explode('-', $pathinfo['filename']); + + return array_reduce( + $parts, + function ($acc, $part) { + if (empty($acc)) { + return array( $part ); + } + + $previous_part = $acc[ count($acc) - 1 ]; + $acc[] = $previous_part . '-' . $part; + + return $acc; + }, + array() + ); + } + + + /** + * Register a single asset. + * + * @param string $type The type of the asset: 'style' or 'script'. + * @param string $handle The asset's handle. + * @param string|array $path The asset's path in the theme. + * @return void + */ + protected function register(string $type, string $handle, $path):void + { + $handle = $this->format_handle($handle); + + if (is_array($path)) { + $_path = $path; + $path = $_path['path']; + $media = $_path['media'] ?? 'all'; + $in_footer = $_path['footer'] ?? true; + } else { + $media = 'all'; + $in_footer = true; + } + + $webpack_path = str_replace($this->get_webpack_public_path_relative_to_theme(), '', $path); + + // Read path from Webpack manifest if it exists. + if ($this->webpack_manifest instanceof Manifest && $this->webpack_manifest->asset($webpack_path)) { + $path = $this->webpack_manifest->asset($webpack_path); + } + + $path = trim($path, '/'); + $full_path = get_template_directory() . '/' . $path; + $public_uri = get_template_directory_uri() . '/' . $path; + + $hash = null; + if (file_exists($full_path)) { + $hash = md5_file($full_path); + } + + if ('style' === $type) { + wp_register_style( + $handle, + $public_uri, + array(), + $hash, + $media + ); + } else { + wp_register_script( + $handle, + $public_uri, + array(), + $hash, + $in_footer + ); + } + } + + /** + * Enqueue an asset given its handle. + * + * @param string $type The type of the asset: 'style' or 'script'. + * @param string $handle The asset's handle. + * @return void + */ + protected function enqueue($type, $handle) + { + $handle = $this->format_handle($handle); + + add_action( + 'wp_enqueue_scripts', + function () use ($type, $handle) { + if ('style' === $type) { + wp_enqueue_style($handle); + } else { + wp_enqueue_script($handle); + } + } + ); + } + + /** + * Prefix all handles with `theme-`. + * + * @param string $handle The handle to format. + * @return string + */ + protected function format_handle(string $handle):string + { + return 'theme-' . str_replace('.', '-', $handle); + } } diff --git a/src/Managers/CleanupManager.php b/src/Managers/CleanupManager.php index e29d52a..0236221 100644 --- a/src/Managers/CleanupManager.php +++ b/src/Managers/CleanupManager.php @@ -17,163 +17,175 @@ /** * Cleanup a WordPress project for security and performance. */ -class CleanupManager implements ManagerInterface { - /** - * Wether to enable XML RPC endpoint or not. - * - * @var bool - */ - protected $xml_rpc; - - /** - * Constructor. - * - * @param bool $xml_rpc Enable or disable XML RPC. - */ - public function __construct( bool $xml_rpc = false ) { - $this->xml_rpc = $xml_rpc; - } - - /** - * {@inheritdoc} - */ - public function run() { - // Clean up . - add_action( 'init', array( $this, 'cleanup_head' ) ); - - // Remove WP version from RSS. - add_filter( 'the_generator', array( $this, 'remove_version' ) ); - - // Remove WordPress version from js & css enqueued files. - add_filter( 'style_loader_src', array( $this, 'remove_version_css_js' ), 9999 ); - add_filter( 'script_loader_src', array( $this, 'remove_version_css_js' ), 9999 ); - - // Make login error message the same. - add_filter( 'login_errors', array( $this, 'simple_wordpress_errors' ) ); - - // Remove emojis related files. - add_action( 'init', array( $this, 'disable_emojis' ) ); - - // Remove useless widgets from the dashboard. - add_action( 'wp_dashboard_setup', array( $this, 'remove_dashboard_widgets' ) ); - - // Remove comments from the admin bar. - add_action( 'wp_before_admin_bar_render', array( $this, 'remove_comments_from_admin_bar' ) ); - - // Remove comments from the admin menu. - add_action( 'admin_menu', array( $this, 'remove_comments_from_admin_menu' ) ); - - add_filter( 'xmlrpc_enabled', array( $this, 'xmlrpc_enabled' ) ); - } - - /** - * Remove a lot of useless stuff added by default in WordPress - */ - public function cleanup_head():void { - // EditURI link. - remove_action( 'wp_head', 'rsd_link' ); - // Category feed links. - remove_action( 'wp_head', 'feed_links_extra', 3 ); - // Post and comment feed links. - remove_action( 'wp_head', 'feed_links', 2 ); - // Windows Live Writer. - remove_action( 'wp_head', 'wlwmanifest_link' ); - // Index link. - remove_action( 'wp_head', 'index_rel_link' ); - // Previous link. - remove_action( 'wp_head', 'parent_post_rel_link', 10 ); - // Start link. - remove_action( 'wp_head', 'start_post_rel_link', 10 ); - // Canonical. - remove_action( 'wp_head', 'rel_canonical', 10 ); - // Shortlink. - remove_action( 'wp_head', 'wp_shortlink_wp_head', 10 ); - // Links for adjacent posts. - remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 ); - // WP version. - remove_action( 'wp_head', 'wp_generator' ); - } - - /** - * Remove WordPress version number in meta tags - * - * @return String - */ - public function remove_version() { - return ''; - } - - /** - * Suppress version number in enqued css & js files. - * Except for themes assets where version isn't a security breach. - * - * @see Studiometa\WP\Assets::register() - * - * @param string $src The source path of the asset. - * @return string - */ - public function remove_version_css_js( string $src ):string { - if ( strpos( $src, 'ver=' ) && false === strpos( $src, content_url( 'themes' ) ) ) { - $src = remove_query_arg( 'ver', $src ); - } - - return $src; - } - - /** - * Make all login faillure message the same - * - * @return string Basic login error message - */ - public function simple_wordpress_errors():string { - return __( 'Login credentials are incorrect', 'studio-meta-cleaner' ); - } - - /** - * Remove all occurence of Emoji's in WordPress - */ - public function disable_emojis():void { - remove_action( 'admin_print_styles', 'print_emoji_styles' ); - remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); - remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); - remove_action( 'wp_print_styles', 'print_emoji_styles' ); - remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' ); - remove_filter( 'the_content_feed', 'wp_staticize_emoji' ); - remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); - } - - /** - * Remove useless widgets from the dashboard - */ - public function remove_dashboard_widgets():void { - // Remove WordPress activities. - remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' ); - // Remove WordPress events. - remove_meta_box( 'dashboard_primary', 'dashboard', 'side' ); - // Remove WordPress welcome board. - remove_action( 'welcome_panel', 'wp_welcome_panel' ); - } - - /** - * Remove comments from admin Bar - */ - public function remove_comments_from_admin_bar():void { - global $wp_admin_bar; - $wp_admin_bar->remove_menu( 'comments' ); - } - - /** - * Remove comments from admin menu - */ - public function remove_comments_from_admin_menu():void { - // Remove comments admin menu item. - remove_menu_page( 'edit-comments.php' ); - } - - /** - * Enable or disable XML RPC endpoint. - */ - public function xmlrpc_enabled():bool { - return $this->xml_rpc; - } +class CleanupManager implements ManagerInterface +{ + /** + * Wether to enable XML RPC endpoint or not. + * + * @var bool + */ + protected $xml_rpc; + + /** + * Constructor. + * + * @param bool $xml_rpc Enable or disable XML RPC. + */ + public function __construct(bool $xml_rpc = false) + { + $this->xml_rpc = $xml_rpc; + } + + /** + * {@inheritdoc} + */ + public function run() + { + // Clean up . + add_action('init', array( $this, 'cleanup_head' )); + + // Remove WP version from RSS. + add_filter('the_generator', array( $this, 'remove_version' )); + + // Remove WordPress version from js & css enqueued files. + add_filter('style_loader_src', array( $this, 'remove_version_css_js' ), 9999); + add_filter('script_loader_src', array( $this, 'remove_version_css_js' ), 9999); + + // Make login error message the same. + add_filter('login_errors', array( $this, 'simple_wordpress_errors' )); + + // Remove emojis related files. + add_action('init', array( $this, 'disable_emojis' )); + + // Remove useless widgets from the dashboard. + add_action('wp_dashboard_setup', array( $this, 'remove_dashboard_widgets' )); + + // Remove comments from the admin bar. + add_action('wp_before_admin_bar_render', array( $this, 'remove_comments_from_admin_bar' )); + + // Remove comments from the admin menu. + add_action('admin_menu', array( $this, 'remove_comments_from_admin_menu' )); + + add_filter('xmlrpc_enabled', array( $this, 'xmlrpc_enabled' )); + } + + /** + * Remove a lot of useless stuff added by default in WordPress + */ + public function cleanup_head():void + { + // EditURI link. + remove_action('wp_head', 'rsd_link'); + // Category feed links. + remove_action('wp_head', 'feed_links_extra', 3); + // Post and comment feed links. + remove_action('wp_head', 'feed_links', 2); + // Windows Live Writer. + remove_action('wp_head', 'wlwmanifest_link'); + // Index link. + remove_action('wp_head', 'index_rel_link'); + // Previous link. + remove_action('wp_head', 'parent_post_rel_link', 10); + // Start link. + remove_action('wp_head', 'start_post_rel_link', 10); + // Canonical. + remove_action('wp_head', 'rel_canonical', 10); + // Shortlink. + remove_action('wp_head', 'wp_shortlink_wp_head', 10); + // Links for adjacent posts. + remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10); + // WP version. + remove_action('wp_head', 'wp_generator'); + } + + /** + * Remove WordPress version number in meta tags + * + * @return String + */ + public function remove_version() + { + return ''; + } + + /** + * Suppress version number in enqued css & js files. + * Except for themes assets where version isn't a security breach. + * + * @see Studiometa\WP\Assets::register() + * + * @param string $src The source path of the asset. + * @return string + */ + public function remove_version_css_js(string $src):string + { + if (strpos($src, 'ver=') && false === strpos($src, content_url('themes'))) { + $src = remove_query_arg('ver', $src); + } + + return $src; + } + + /** + * Make all login faillure message the same + * + * @return string Basic login error message + */ + public function simple_wordpress_errors():string + { + return __('Login credentials are incorrect', 'studio-meta-cleaner'); + } + + /** + * Remove all occurence of Emoji's in WordPress + */ + public function disable_emojis():void + { + remove_action('admin_print_styles', 'print_emoji_styles'); + remove_action('wp_head', 'print_emoji_detection_script', 7); + remove_action('admin_print_scripts', 'print_emoji_detection_script'); + remove_action('wp_print_styles', 'print_emoji_styles'); + remove_filter('wp_mail', 'wp_staticize_emoji_for_email'); + remove_filter('the_content_feed', 'wp_staticize_emoji'); + remove_filter('comment_text_rss', 'wp_staticize_emoji'); + } + + /** + * Remove useless widgets from the dashboard + */ + public function remove_dashboard_widgets():void + { + // Remove WordPress activities. + remove_meta_box('dashboard_activity', 'dashboard', 'normal'); + // Remove WordPress events. + remove_meta_box('dashboard_primary', 'dashboard', 'side'); + // Remove WordPress welcome board. + remove_action('welcome_panel', 'wp_welcome_panel'); + } + + /** + * Remove comments from admin Bar + */ + public function remove_comments_from_admin_bar():void + { + global $wp_admin_bar; + $wp_admin_bar->remove_menu('comments'); + } + + /** + * Remove comments from admin menu + */ + public function remove_comments_from_admin_menu():void + { + // Remove comments admin menu item. + remove_menu_page('edit-comments.php'); + } + + /** + * Enable or disable XML RPC endpoint. + */ + public function xmlrpc_enabled():bool + { + return $this->xml_rpc; + } } diff --git a/src/Managers/ManagerFactory.php b/src/Managers/ManagerFactory.php index ce0efad..51711fc 100644 --- a/src/Managers/ManagerFactory.php +++ b/src/Managers/ManagerFactory.php @@ -15,16 +15,18 @@ /** * Manager factory class. */ -class ManagerFactory { - /** - * Run the given managers. - * - * @param ManagerInterface[] $managers A list of manager instances. - * @return void - */ - public static function init( array $managers ):void { - foreach ( $managers as $manager ) { - $manager->run(); - } - } +class ManagerFactory +{ + /** + * Run the given managers. + * + * @param ManagerInterface[] $managers A list of manager instances. + * @return void + */ + public static function init(array $managers):void + { + foreach ($managers as $manager) { + $manager->run(); + } + } } diff --git a/src/Managers/ManagerInterface.php b/src/Managers/ManagerInterface.php index 2b6c786..5761b79 100644 --- a/src/Managers/ManagerInterface.php +++ b/src/Managers/ManagerInterface.php @@ -15,11 +15,12 @@ /** * Manager interface. */ -interface ManagerInterface { - /** - * Runs initialization tasks. - * - * @return void - */ - public function run(); +interface ManagerInterface +{ + /** + * Runs initialization tasks. + * + * @return void + */ + public function run(); } diff --git a/src/TransientCleaner.php b/src/TransientCleaner.php index 2fb80d6..1ddbf76 100644 --- a/src/TransientCleaner.php +++ b/src/TransientCleaner.php @@ -15,301 +15,319 @@ /** * TransientCleaner class. */ -class TransientCleaner { - const PREFIX = 'wp_toolkit_transient_cleaner_'; - const OPTION_STORED_TRANSIENTS = self::PREFIX . 'stored_transients'; +class TransientCleaner +{ + const PREFIX = 'wp_toolkit_transient_cleaner_'; + const OPTION_STORED_TRANSIENTS = self::PREFIX . 'stored_transients'; - /** - * Class instance - * - * @var TransientCleaner|null - */ - private static $instance = null; + /** + * Class instance + * + * @var TransientCleaner|null + */ + private static $instance = null; - /** - * Transients configuration. - * - * @var array - */ - private $config = array(); + /** + * Transients configuration. + * + * @var array + */ + private $config = array(); - /** - * Stored transients. - * - * @var array|bool - */ - private $stored_transients; + /** + * Stored transients. + * + * @var array|bool + */ + private $stored_transients; - /** - * Constructor. - * - * @param array $config Configuration. - */ - public function __construct( array $config = array() ) { - // @phpstan-ignore-next-line - $this->set_stored_transients( get_option( self::OPTION_STORED_TRANSIENTS ) ); - $this->set_config( $config ); - $this->define_public_hooks(); - } + /** + * Constructor. + * + * @param array $config Configuration. + */ + public function __construct(array $config = array()) + { + // @phpstan-ignore-next-line + $this->set_stored_transients(get_option(self::OPTION_STORED_TRANSIENTS)); + $this->set_config($config); + $this->define_public_hooks(); + } - /** - * Get class instance. - * - * {@example} - * ```php - * TransientCleaner::get_instance( - * array( - * 'post' => array( - * 'all' => array( - * TransientCleaner::PREFIX . 'transient_key', - * ), - * 'post_type_key' => array( - * TransientCleaner::PREFIX . 'transient_key', - * TransientCleaner::PREFIX . 'transient_key_1', - * ) - * ), - * 'term' => array( - * 'all' => array(), - * 'your_taxonomy_type_key' => array(), - * 'category' => array(), - * ), - * 'option' => array( - * 'all' => array(), - * 'option_key' => array(), - * 'blogdescription' => array(), - * ), - * ) - * ); - * ``` - * - * @param array $config Configuration. - * - * @return TransientCleaner Class instance - */ - public static function get_instance( array $config = array() ) : TransientCleaner { - if ( is_null( self::$instance ) ) { - self::$instance = new TransientCleaner( $config ); - } + /** + * Get class instance. + * + * {@example} + * ```php + * TransientCleaner::get_instance( + * array( + * 'post' => array( + * 'all' => array( + * TransientCleaner::PREFIX . 'transient_key', + * ), + * 'post_type_key' => array( + * TransientCleaner::PREFIX . 'transient_key', + * TransientCleaner::PREFIX . 'transient_key_1', + * ) + * ), + * 'term' => array( + * 'all' => array(), + * 'your_taxonomy_type_key' => array(), + * 'category' => array(), + * ), + * 'option' => array( + * 'all' => array(), + * 'option_key' => array(), + * 'blogdescription' => array(), + * ), + * ) + * ); + * ``` + * + * @param array $config Configuration. + * + * @return TransientCleaner Class instance + */ + public static function get_instance(array $config = array()) : TransientCleaner + { + if (is_null(self::$instance)) { + self::$instance = new TransientCleaner($config); + } - return self::$instance; - } + return self::$instance; + } - /** - * Initialize hooks and filters. - * - * @return void - */ - public function define_public_hooks() { - add_action( 'save_post', array( $this, 'post_transient_cleaner' ), 10, 2 ); - add_action( 'edit_term', array( $this, 'term_transient_cleaner' ), 10, 3 ); - add_action( 'updated_option', array( $this, 'option_transient_cleaner' ), 10, 2 ); - add_action( 'setted_transient', array( $this, 'store_transient_key' ) ); - add_filter( 'pre_update_option_' . self::OPTION_STORED_TRANSIENTS, array( $this, 'merge_stored_transients_option_values' ), 10, 3 ); - add_filter( 'update_option_' . self::OPTION_STORED_TRANSIENTS, array( $this, 'set_stored_transients' ), 20, 1 ); - } + /** + * Initialize hooks and filters. + * + * @return void + */ + public function define_public_hooks() + { + add_action('save_post', array( $this, 'post_transient_cleaner' ), 10, 2); + add_action('edit_term', array( $this, 'term_transient_cleaner' ), 10, 3); + add_action('updated_option', array( $this, 'option_transient_cleaner' ), 10, 2); + add_action('setted_transient', array( $this, 'store_transient_key' )); + add_filter( + 'pre_update_option_' . self::OPTION_STORED_TRANSIENTS, + array( $this, 'merge_stored_transients_option_values' ), + 10, + 3 + ); + add_filter('update_option_' . self::OPTION_STORED_TRANSIENTS, array( $this, 'set_stored_transients' ), 20, 1); + } - /** - * Get config. - * - * @return array - */ - public function get_config() : array { - return $this->config; - } + /** + * Get config. + * + * @return array + */ + public function get_config() : array + { + return $this->config; + } - /** - * Set config. - * - * {@example} - * ```php - * TransientCleaner::get_instance() - * ->set_config( - * array( - * 'post' => array( - * 'all' => array( - * TransientCleaner::PREFIX . 'transient_key', - * ), - * 'post_type_key' => array( - * TransientCleaner::PREFIX . 'transient_key', - * TransientCleaner::PREFIX . 'transient_key_1', - * ) - * ), - * 'term' => array( - * 'all' => array(), - * 'your_taxonomy_type_key' => array(), - * 'category' => array(), - * ), - * 'option' => array( - * 'all' => array(), - * 'option_key' => array(), - * 'blogdescription' => array(), - * ), - * ) - * ); - * ``` - * - * @param array $config Configuration. - * - * @return TransientCleaner - */ - public function set_config( array $config ) : TransientCleaner { - $this->config = $config; + /** + * Set config. + * + * {@example} + * ```php + * TransientCleaner::get_instance() + * ->set_config( + * array( + * 'post' => array( + * 'all' => array( + * TransientCleaner::PREFIX . 'transient_key', + * ), + * 'post_type_key' => array( + * TransientCleaner::PREFIX . 'transient_key', + * TransientCleaner::PREFIX . 'transient_key_1', + * ) + * ), + * 'term' => array( + * 'all' => array(), + * 'your_taxonomy_type_key' => array(), + * 'category' => array(), + * ), + * 'option' => array( + * 'all' => array(), + * 'option_key' => array(), + * 'blogdescription' => array(), + * ), + * ) + * ); + * ``` + * + * @param array $config Configuration. + * + * @return TransientCleaner + */ + public function set_config(array $config) : TransientCleaner + { + $this->config = $config; - return $this; - } + return $this; + } - /** - * Get stored_transients. - * - * @return array|bool - */ - public function get_stored_transients() { - return $this->stored_transients; - } + /** + * Get stored_transients. + * + * @return array|bool + */ + public function get_stored_transients() + { + return $this->stored_transients; + } - /** - * Set stored_transients. - * - * @param array|bool $value New value. - * - * @return TransientCleaner - */ - public function set_stored_transients( $value ) : TransientCleaner { - $this->stored_transients = $value; + /** + * Set stored_transients. + * + * @param array|bool $value New value. + * + * @return TransientCleaner + */ + public function set_stored_transients($value) : TransientCleaner + { + $this->stored_transients = $value; - return $this; - } + return $this; + } - /** - * Merge new stored transient key with others if exists. - * - * @param array|bool $value New value. - * @param array|bool $old_value Old value. - * - * @return array|bool New value - */ - public function merge_stored_transients_option_values( $value, $old_value ) { - // Return `$value` if no previous value. - if ( false === $old_value ) { - return $value; - } + /** + * Merge new stored transient key with others if exists. + * + * @param array|bool $value New value. + * @param array|bool $old_value Old value. + * + * @return array|bool New value + */ + public function merge_stored_transients_option_values($value, $old_value) + { + // Return `$value` if no previous value. + if (false === $old_value) { + return $value; + } - // Do nothing if transient key already exists in stored transients. - if ( is_array( $value ) && is_array( $old_value ) ) { - if ( isset( $value[0] ) && true === in_array( $value[0], $old_value, true ) ) { - return $old_value; - } + // Do nothing if transient key already exists in stored transients. + if (is_array($value) && is_array($old_value)) { + if (isset($value[0]) && true === in_array($value[0], $old_value, true)) { + return $old_value; + } - // Merge old and new values. - return array_merge( $old_value, $value ); - } + // Merge old and new values. + return array_merge($old_value, $value); + } - return $old_value; - } + return $old_value; + } - /** - * Store transient key in option on save. - * - * @param string $transient_key Transient key. - * - * @see self::merge_stored_transients_option_values - * - * @return bool - */ - public function store_transient_key( string $transient_key ) : bool { - if ( - false === strpos( $transient_key, self::PREFIX ) - || false !== strpos( $transient_key, '_lock' ) - ) { - return false; - } + /** + * Store transient key in option on save. + * + * @param string $transient_key Transient key. + * + * @see self::merge_stored_transients_option_values + * + * @return bool + */ + public function store_transient_key(string $transient_key) : bool + { + if (false === strpos($transient_key, self::PREFIX) + || false !== strpos($transient_key, '_lock') + ) { + return false; + } - return update_option( - self::OPTION_STORED_TRANSIENTS, - array( $transient_key ) - ); - } + return update_option( + self::OPTION_STORED_TRANSIENTS, + array( $transient_key ) + ); + } - /** - * Delete transient based on current content and transient key. - * - * @param string $type Content type. - * @param callable $validator Function who control if the transient must be validate or no (must return boolean). - * - * @return bool - */ - protected function object_transient_cleaner( string $type, callable $validator ) : bool { - if ( ! is_array( $this->stored_transients ) || empty( $this->config[ $type ] ) ) { - return false; - } + /** + * Delete transient based on current content and transient key. + * + * @param string $type Content type. + * @param callable $validator Function who control if the transient must be validate or no (must return boolean). + * + * @return bool + */ + protected function object_transient_cleaner(string $type, callable $validator) : bool + { + if (! is_array($this->stored_transients) || empty($this->config[ $type ])) { + return false; + } - foreach ( $this->config[ $type ] as $type_key => $type_values ) { - if ( 'all' !== $type_key && false === call_user_func( $validator, $type_key ) ) { - continue; - } + foreach ($this->config[ $type ] as $type_key => $type_values) { + if ('all' !== $type_key && false === call_user_func($validator, $type_key)) { + continue; + } - foreach ( $type_values as $transient_key ) { - foreach ( $this->stored_transients as $stored_transient ) { - if ( false === strpos( $stored_transient, $transient_key ) ) { - continue; - } + foreach ($type_values as $transient_key) { + foreach ($this->stored_transients as $stored_transient) { + if (false === strpos($stored_transient, $transient_key)) { + continue; + } - delete_transient( $stored_transient ); - } - } - } + delete_transient($stored_transient); + } + } + } - return true; - } + return true; + } - /** - * Clear transient on post save. - * - * @param mixed $post_id post id. - * @param \WP_Post $post post. - * - * @return bool - */ - public function post_transient_cleaner( $post_id, \WP_Post $post ) : bool { - return $this->object_transient_cleaner( - 'post', - function( $key ) use ( $post ) { - return $key === $post->post_type; - } - ); - } + /** + * Clear transient on post save. + * + * @param mixed $post_id post id. + * @param \WP_Post $post post. + * + * @return bool + */ + public function post_transient_cleaner($post_id, \WP_Post $post) : bool + { + return $this->object_transient_cleaner( + 'post', + function ($key) use ($post) { + return $key === $post->post_type; + } + ); + } - /** - * Clear transient on term save. - * - * @param int $term_id Term ID. - * @param int $tt_id Term taxonomy ID. - * @param string $taxonomy Taxonomy. - * - * @return bool - */ - public function term_transient_cleaner( int $term_id, int $tt_id, string $taxonomy ) : bool { - return $this->object_transient_cleaner( - 'term', - function( $key ) use ( $taxonomy ) { - return $key === $taxonomy; - } - ); - } + /** + * Clear transient on term save. + * + * @param int $term_id Term ID. + * @param int $tt_id Term taxonomy ID. + * @param string $taxonomy Taxonomy. + * + * @return bool + */ + public function term_transient_cleaner(int $term_id, int $tt_id, string $taxonomy) : bool + { + return $this->object_transient_cleaner( + 'term', + function ($key) use ($taxonomy) { + return $key === $taxonomy; + } + ); + } - /** - * Clear transient on option save. - * - * @param string $option Option key. - * - * @return bool - */ - public function option_transient_cleaner( string $option ) : bool { - return $this->object_transient_cleaner( - 'option', - function( $key ) use ( $option ) { - return strpos( $option, $key ); - } - ); - } + /** + * Clear transient on option save. + * + * @param string $option Option key. + * + * @return bool + */ + public function option_transient_cleaner(string $option) : bool + { + return $this->object_transient_cleaner( + 'option', + function ($key) use ($option) { + return strpos($option, $key); + } + ); + } } diff --git a/src/helpers.php b/src/helpers.php index dc3fc66..72c6bd4 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -17,8 +17,9 @@ * @param string $key The variable name. * @return string */ -function env( string $key ): string { - return Env::get( $key ); +function env(string $key): string +{ + return Env::get($key); } /** @@ -28,6 +29,7 @@ function env( string $key ): string { * * @return SymfonyRequest */ -function request(): SymfonyRequest { - return Request::request(); +function request(): SymfonyRequest +{ + return Request::request(); } diff --git a/tests/Builder/PostTypeBuilderTest.php b/tests/Builder/PostTypeBuilderTest.php index 651968f..b7ce983 100644 --- a/tests/Builder/PostTypeBuilderTest.php +++ b/tests/Builder/PostTypeBuilderTest.php @@ -1,43 +1,50 @@ post_type_builder = new PostTypeBuilder( 'product' ); - } - - /** - * Test register function. - * - * @return void - */ - public function test_post_type_builder_register() { - $this->post_type_builder->register(); - - $this->assertTrue( post_type_exists( 'product' ) ); - } - - /** - * Test set_labels function. - * - * @return void - */ - public function test_post_type_builder_set_labels() { - $this->post_type_builder->set_labels( 'Product', 'Products' ); - - $config = $this->post_type_builder->get_config(); - - $this->assertTrue( isset( $config['labels'] ) ); - $this->assertEquals( 'Product', $config['labels']['singular_name'] ); - $this->assertEquals( 'Products', $config['labels']['menu_name'] ); - } +class PostTypeBuilderTest extends WP_UnitTestCase +{ + /** + * Store a PostTypeBuilder instance. + */ + public function setUp():void + { + parent::setUp(); + + $this->post_type_builder = new PostTypeBuilder('product'); + } + + /** + * Test register function. + * + * @return void + */ + public function test_post_type_builder_register() + { + $this->post_type_builder->register(); + + $this->assertTrue(post_type_exists('product')); + } + + /** + * Test set_labels function. + * + * @return void + */ + public function test_post_type_builder_set_labels() + { + $this->post_type_builder->set_labels('Product', 'Products'); + + $config = $this->post_type_builder->get_config(); + + $this->assertTrue(isset($config['labels'])); + $this->assertEquals('Product', $config['labels']['singular_name']); + $this->assertEquals('Products', $config['labels']['menu_name']); + } } diff --git a/tests/Builder/TaxonomyBuilderTest.php b/tests/Builder/TaxonomyBuilderTest.php index 1b09795..462dfdc 100644 --- a/tests/Builder/TaxonomyBuilderTest.php +++ b/tests/Builder/TaxonomyBuilderTest.php @@ -1,56 +1,64 @@ taxonomy_builder = new TaxonomyBuilder( 'category' ); - } - - /** - * Test register function. - * - * @return void - */ - public function test_taxonomy_builder_register() { - $this->taxonomy_builder->register(); - - $this->assertTrue( taxonomy_exists( 'category' ) ); - } - - /** - * Test set_labels function. - * - * @return void - */ - public function test_taxonomy_builder_set_labels() { - $this->taxonomy_builder->set_labels( 'Category', 'Categories' ); - - $config = $this->taxonomy_builder->get_config(); - - $this->assertTrue( isset( $config['labels'] ) ); - $this->assertEquals( 'Category', $config['labels']['singular_name'] ); - $this->assertEquals( 'Categories', $config['labels']['menu_name'] ); - } - - /** - * Test set_post_types function. - * - * @return void - */ - public function test_taxonomy_builder_set_post_types() { - $this->taxonomy_builder->set_post_types( 'tag' ); - - $post_types = $this->taxonomy_builder->get_post_types(); - - $this->assertEquals( 'tag', $post_types ); - } +class TaxonomyBuilderTest extends WP_UnitTestCase +{ + /** + * Store a TaxonomyBuilder instance. + */ + public function setUp():void + { + parent::setUp(); + + $this->taxonomy_builder = new TaxonomyBuilder('category'); + } + + /** + * Test register function. + * + * @return void + */ + public function test_taxonomy_builder_register() + { + $this->taxonomy_builder->register(); + + $this->assertTrue(taxonomy_exists('category')); + } + + /** + * Test set_labels function. + * + * @return void + */ + public function test_taxonomy_builder_set_labels() + { + $this->taxonomy_builder->set_labels('Category', 'Categories'); + + $config = $this->taxonomy_builder->get_config(); + + $this->assertTrue(isset($config['labels'])); + $this->assertEquals('Category', $config['labels']['singular_name']); + $this->assertEquals('Categories', $config['labels']['menu_name']); + } + + /** + * Test set_post_types function. + * + * @return void + */ + public function test_taxonomy_builder_set_post_types() + { + $this->taxonomy_builder->set_post_types('tag'); + + $post_types = $this->taxonomy_builder->get_post_types(); + + $this->assertEquals('tag', $post_types); + } } diff --git a/tests/Helpers/EnvTest.php b/tests/Helpers/EnvTest.php index 5a8e7c7..a986ecc 100644 --- a/tests/Helpers/EnvTest.php +++ b/tests/Helpers/EnvTest.php @@ -1,20 +1,25 @@ assertTrue(is_string(env('missing'))); - $this->assertTrue(is_string(EnvClass::get('missing'))); - } + /** + * Test the request() function + * + * @return void + */ + public function test_type_of_request_function_helper() + { + $this->assertTrue(is_string(env('missing'))); + $this->assertTrue(is_string(EnvClass::get('missing'))); + } } diff --git a/tests/Helpers/PluginTest.php b/tests/Helpers/PluginTest.php index 22be2ac..0a32b82 100644 --- a/tests/Helpers/PluginTest.php +++ b/tests/Helpers/PluginTest.php @@ -1,36 +1,43 @@ assertTrue( - is_bool( Plugin::is_plugin_enabled( 'my-plugin/my-plugin.php' ) ) - ); - } + /** + * Test `is_plugin_enabled` function. + * + * @return void + */ + public function test_is_plugin_enabled() + { + $this->assertTrue( + is_bool(Plugin::is_plugin_enabled('my-plugin/my-plugin.php')) + ); + } - /** - * Test the `disable` method. - * - * @return void - */ - public function test_plugins_have_been_disabled() { - $this->assertTrue( is_plugin_active( 'akismet/akismet.php' ) ); - Plugin::disable( array( 'akismet/akismet.php' ) ); - $this->assertFalse( is_plugin_active( 'akismet/akismet.php' ) ); - } + /** + * Test the `disable` method. + * + * @return void + */ + public function test_plugins_have_been_disabled() + { + $this->assertTrue(is_plugin_active('akismet/akismet.php')); + Plugin::disable(array( 'akismet/akismet.php' )); + $this->assertFalse(is_plugin_active('akismet/akismet.php')); + } } diff --git a/tests/Helpers/RequestTest.php b/tests/Helpers/RequestTest.php index 0b39486..efd2691 100644 --- a/tests/Helpers/RequestTest.php +++ b/tests/Helpers/RequestTest.php @@ -1,5 +1,8 @@ assertTrue($request1 instanceof SymfonyRequest); - $this->assertTrue($request2 instanceof SymfonyRequest); - $this->assertTrue($request1 === $request2); - } + /** + * Test the request() function + * + * @return void + */ + public function test_type_of_request_function_helper() + { + $request1 = RequestClass::request(); + $request2 = request(); + $this->assertTrue($request1 instanceof SymfonyRequest); + $this->assertTrue($request2 instanceof SymfonyRequest); + $this->assertTrue($request1 === $request2); + } } diff --git a/tests/Managers/AssetsManagerTest.php b/tests/Managers/AssetsManagerTest.php index b2d15c4..a23cc4b 100644 --- a/tests/Managers/AssetsManagerTest.php +++ b/tests/Managers/AssetsManagerTest.php @@ -1,88 +1,97 @@ assets_manager = new AssetsManager(); + $this->assets_manager = new AssetsManager(); - // @todo put stubs file in current theme folder for tests - $this->theme_path = realpath( get_template_directory() ); - $this->stubs_path = realpath( __DIR__ . '/__stubs__/theme/' ); + // @todo put stubs file in current theme folder for tests + $this->theme_path = realpath(get_template_directory()); + $this->stubs_path = realpath(__DIR__ . '/__stubs__/theme/'); // phpcs:ignore exec( sprintf( 'rsync -avh %s %s', $this->stubs_path . '/', $this->theme_path . '/' ) ); - $this->assets_manager->run(); - } - - /** - * Test remove css and js version. - * - * @return void - */ - public function test_configs_are_read() { - $this->assertEqualSets( - $this->assets_manager->config, - array( - 'all' => array( - 'entries' => array( - 'css/app.scss', - 'js/app.js', - ), - 'css' => array( - 'editor' => 'dist/editor.css', - ), - ), - 'post' => array( - 'css' => array( - 'post' => 'dist/post.css', - ), - ), - ) - ); - - $this->assertTrue( - $this->assets_manager->webpack_manifest instanceof \Studiometa\WebpackConfig\Manifest - ); - - $this->assertTrue( - $this->assets_manager->webpack_manifest->entry( 'css/app' ) instanceof \Studiometa\WebpackConfig\Entry - ); - - $this->assertTrue( - $this->assets_manager->webpack_manifest->entry( 'js/app' ) instanceof \Studiometa\WebpackConfig\Entry - ); - } - - public function test_assets_are_registered() { - do_action( 'wp_enqueue_scripts' ); - $this->assertTrue( isset( wp_styles()->registered['theme-styles-1234-css'] ) ); - $this->assertTrue( isset( wp_styles()->registered['theme-editor'] ) ); - $this->assertTrue( isset( wp_scripts()->registered['theme-app-1234-js'] ) ); - } - - public function test_entries_are_enqueued() { - apply_filters( 'template_include', 'frontpage' ); - do_action( 'wp_enqueue_scripts' ); - - $this->assertTrue( in_array( 'theme-styles-1234-css', wp_styles()->queue, true ) ); - $this->assertTrue( in_array( 'theme-editor', wp_styles()->queue, true ) ); - $this->assertFalse( in_array( 'theme-post', wp_styles()->queue, true ) ); - - $this->assertTrue( in_array( 'theme-app-1234-js', wp_scripts()->queue, true ) ); - } - - public function test_entries_are_enqueued_by_template() { - apply_filters( 'template_include', 'single-post.php' ); - do_action( 'wp_enqueue_scripts' ); - - $this->assertTrue( in_array( 'theme-styles-1234-css', wp_styles()->queue, true ) ); - $this->assertTrue( in_array( 'theme-editor', wp_styles()->queue, true ) ); - $this->assertTrue( in_array( 'theme-post', wp_styles()->queue, true ) ); - } + $this->assets_manager->run(); + } + + /** + * Test remove css and js version. + * + * @return void + */ + public function test_configs_are_read() + { + $this->assertEqualSets( + $this->assets_manager->config, + array( + 'all' => array( + 'entries' => array( + 'css/app.scss', + 'js/app.js', + ), + 'css' => array( + 'editor' => 'dist/editor.css', + ), + ), + 'post' => array( + 'css' => array( + 'post' => 'dist/post.css', + ), + ), + ) + ); + + $this->assertTrue( + $this->assets_manager->webpack_manifest instanceof \Studiometa\WebpackConfig\Manifest + ); + + $this->assertTrue( + $this->assets_manager->webpack_manifest->entry('css/app') instanceof \Studiometa\WebpackConfig\Entry + ); + + $this->assertTrue( + $this->assets_manager->webpack_manifest->entry('js/app') instanceof \Studiometa\WebpackConfig\Entry + ); + } + + public function test_assets_are_registered() + { + do_action('wp_enqueue_scripts'); + $this->assertTrue(isset(wp_styles()->registered['theme-styles-1234-css'])); + $this->assertTrue(isset(wp_styles()->registered['theme-editor'])); + $this->assertTrue(isset(wp_scripts()->registered['theme-app-1234-js'])); + } + + public function test_entries_are_enqueued() + { + apply_filters('template_include', 'frontpage'); + do_action('wp_enqueue_scripts'); + + $this->assertTrue(in_array('theme-styles-1234-css', wp_styles()->queue, true)); + $this->assertTrue(in_array('theme-editor', wp_styles()->queue, true)); + $this->assertFalse(in_array('theme-post', wp_styles()->queue, true)); + + $this->assertTrue(in_array('theme-app-1234-js', wp_scripts()->queue, true)); + } + + public function test_entries_are_enqueued_by_template() + { + apply_filters('template_include', 'single-post.php'); + do_action('wp_enqueue_scripts'); + + $this->assertTrue(in_array('theme-styles-1234-css', wp_styles()->queue, true)); + $this->assertTrue(in_array('theme-editor', wp_styles()->queue, true)); + $this->assertTrue(in_array('theme-post', wp_styles()->queue, true)); + } } diff --git a/tests/Managers/CleanupManagerTest.php b/tests/Managers/CleanupManagerTest.php index 88d43da..9010fff 100644 --- a/tests/Managers/CleanupManagerTest.php +++ b/tests/Managers/CleanupManagerTest.php @@ -1,49 +1,56 @@ cleanup_manager = new CleanupManager(); - } - - /** - * Test remove css and js version. - * - * @return void - */ - public function test_remove_version_css_js() { - $themes_uri = content_url( 'themes' ); - $theme_src = $themes_uri . '/example/example.js?ver=2.0.0'; - $other_src = 'https://example.org/example.js?ver=2.0.0'; - - $updated_theme_src = $this->cleanup_manager->remove_version_css_js( $theme_src ); - $updated_other_src = $this->cleanup_manager->remove_version_css_js( $other_src ); - - $this->assertFalse( strpos( $updated_other_src, 'ver=' ) ); - $this->assertNotFalse( strpos( $updated_theme_src, 'ver=' ) ); - } - - /** - * Test disable XML RPC. - * - * @return void - */ - public function test_xml_rpc_disabled() { - $this->cleanup_manager->run(); - $this->assertFalse( apply_filters( 'xmlrpc_enabled', true ) ); - } +class CleanupManagerTest extends WP_UnitTestCase +{ + + /** + * CleanupManager. + * + * @var CleanupManager + */ + public $cleanup_manager; + + public function setUp():void + { + parent::setUp(); + + $this->cleanup_manager = new CleanupManager(); + } + + /** + * Test remove css and js version. + * + * @return void + */ + public function test_remove_version_css_js() + { + $themes_uri = content_url('themes'); + $theme_src = $themes_uri . '/example/example.js?ver=2.0.0'; + $other_src = 'https://example.org/example.js?ver=2.0.0'; + + $updated_theme_src = $this->cleanup_manager->remove_version_css_js($theme_src); + $updated_other_src = $this->cleanup_manager->remove_version_css_js($other_src); + + $this->assertFalse(strpos($updated_other_src, 'ver=')); + $this->assertNotFalse(strpos($updated_theme_src, 'ver=')); + } + + /** + * Test disable XML RPC. + * + * @return void + */ + public function test_xml_rpc_disabled() + { + $this->cleanup_manager->run(); + $this->assertFalse(apply_filters('xmlrpc_enabled', true)); + } } diff --git a/tests/Managers/ManagerFactoryTest.php b/tests/Managers/ManagerFactoryTest.php index 9810e13..64d7a4c 100644 --- a/tests/Managers/ManagerFactoryTest.php +++ b/tests/Managers/ManagerFactoryTest.php @@ -1,41 +1,48 @@ assertFalse( self::$has_run ); + /** + * Test init method. + * Should trigger the manager instances `run` method. + * + * @return void + */ + public function test_init() + { + $this->assertFalse(self::$has_run); - ManagerFactory::init( - array( new Manager() ) - ); + ManagerFactory::init( + array( new Manager() ) + ); - $this->assertTrue( self::$has_run ); - } + $this->assertTrue(self::$has_run); + } } diff --git a/tests/TransientCleanerTest.php b/tests/TransientCleanerTest.php index 913111f..6d98266 100644 --- a/tests/TransientCleanerTest.php +++ b/tests/TransientCleanerTest.php @@ -1,174 +1,195 @@ config = array( - 'post' => array( - 'post' => array( - self::POST_TRANSIENT_KEY, - ), - ), - 'term' => array( - 'post_tag' => array( - self::TERM_TRANSIENT_KEY, - ), - ), - 'option' => array( - 'baz_option' => array( - self::OPTION_TRANSIENT_KEY, - ), - ), - ); - - $this->transient_cleaner = TransientCleaner::get_instance( $this->config ); - - set_transient( self::POST_TRANSIENT_KEY, 'foo' ); - set_transient( self::TERM_TRANSIENT_KEY, 'bar' ); - set_transient( self::OPTION_TRANSIENT_KEY, 'baz' ); - - // Mock stored transient because WordPress `update_option` don't work in tests. - $this->transient_cleaner->set_stored_transients( - array( - self::POST_TRANSIENT_KEY, - self::TERM_TRANSIENT_KEY, - self::OPTION_TRANSIENT_KEY, - ) - ); - } - - /** - * Test set/get config. - * - * @return void - */ - public function test_set_get_config() { - $config_1 = $this->transient_cleaner->get_config(); - $this->transient_cleaner->set_config( - array_merge( - $config_1, - array( 'foo' => array() ) - ) - ); - $config_2 = $this->transient_cleaner->get_config(); - - $this->assertIsArray( $config_2 ); - $this->assertNotEmpty( $config_2 ); - $this->assertEquals( count( $config_1 ), count( $config_2 ) - 1 ); - } - - /** - * Test set/get stored_transients. - * - * @return void - */ - public function test_set_get_stored_transients() { - $stored_transients_1 = $this->transient_cleaner->get_stored_transients(); - $this->transient_cleaner->set_stored_transients( - array( 'foo' ) - ); - $stored_transients_2 = $this->transient_cleaner->get_stored_transients(); - - $this->assertEquals( array( 'foo' ), $stored_transients_2 ); - } - - /** - * Test merge_stored_transients_option_values. - * - * @return void - */ - public function test_merge_stored_transients_option_values() { - $test_no_old_value = $this->transient_cleaner->merge_stored_transients_option_values( 'foo', false ); - $test_old_value = $this->transient_cleaner->merge_stored_transients_option_values( 'foo', 'foo_old' ); - $test_merge_values = $this->transient_cleaner->merge_stored_transients_option_values( array( 'foo' ), array( 'foo_old' ) ); - $test_merge_values_already_exists = $this->transient_cleaner->merge_stored_transients_option_values( array( 'foo' ), array( 'foo_old', 'foo' ) ); - - $this->assertEquals( 'foo', $test_no_old_value ); - $this->assertEquals( 'foo_old', $test_old_value ); - $this->assertEquals( array( 'foo_old', 'foo' ), $test_merge_values ); - $this->assertEquals( array( 'foo_old', 'foo' ), $test_merge_values_already_exists ); - } - - /** - * Test store transient. - * - * @return void - */ - public function test_store_transient_key() { - $test_fail = $this->transient_cleaner->store_transient_key( 'foo' ); - $test_success = $this->transient_cleaner->store_transient_key( TransientCleaner::PREFIX . 'foo' ); - - $this->assertFalse( $test_fail ); - $this->assertTrue( $test_success ); - } - - /** - * Test post transient cleaner. - * - * @return void - */ - public function test_post_transient_cleaner() { - $post = $this->factory->post->create_and_get(); - $test_success = $this->transient_cleaner->post_transient_cleaner( 1, $post ); - - $config_1 = $this->transient_cleaner->get_config(); - unset( $config_1['post'] ); - $this->transient_cleaner->set_config( $config_1 ); - - $test_fail = $this->transient_cleaner->post_transient_cleaner( 1, $post ); - - $this->assertTrue( $test_success ); - $this->assertFalse( $test_fail ); - } - - /** - * Test term transient cleaner. - * - * @return void - */ - public function test_term_transient_cleaner() { - $taxonomy = 'post_tag'; - $test_success = $this->transient_cleaner->term_transient_cleaner( 1, 1, $taxonomy ); - - $config_1 = $this->transient_cleaner->get_config(); - unset( $config_1['term'] ); - $this->transient_cleaner->set_config( $config_1 ); - - $test_fail = $this->transient_cleaner->term_transient_cleaner( 1, 1, $taxonomy ); - - $this->assertTrue( $test_success ); - $this->assertFalse( $test_fail ); - } - - /** - * Test option transient cleaner. - * - * @return void - */ - public function test_option_transient_cleaner() { - $option = 'baz_option'; - $test_success = $this->transient_cleaner->option_transient_cleaner( $option ); - - $config_1 = $this->transient_cleaner->get_config(); - unset( $config_1['option'] ); - $this->transient_cleaner->set_config( $config_1 ); - - $test_fail = $this->transient_cleaner->option_transient_cleaner( $option ); - - $this->assertTrue( $test_success ); - $this->assertFalse( $test_fail ); - } +class TransientCleanerTest extends WP_UnitTestCase +{ + const POST_TRANSIENT_KEY = TransientCleaner::PREFIX . 'transient_cleaner_post'; + const TERM_TRANSIENT_KEY = TransientCleaner::PREFIX . 'transient_cleaner_term'; + const OPTION_TRANSIENT_KEY = TransientCleaner::PREFIX . 'transient_cleaner_option'; + + public $transient_cleaner; + + /** + * Initialize transient cleaner based on config. + */ + public function setUp():void + { + parent::setUp(); + + $this->config = array( + 'post' => array( + 'post' => array( + self::POST_TRANSIENT_KEY, + ), + ), + 'term' => array( + 'post_tag' => array( + self::TERM_TRANSIENT_KEY, + ), + ), + 'option' => array( + 'baz_option' => array( + self::OPTION_TRANSIENT_KEY, + ), + ), + ); + + $this->transient_cleaner = TransientCleaner::get_instance($this->config); + + set_transient(self::POST_TRANSIENT_KEY, 'foo'); + set_transient(self::TERM_TRANSIENT_KEY, 'bar'); + set_transient(self::OPTION_TRANSIENT_KEY, 'baz'); + + // Mock stored transient because WordPress `update_option` don't work in tests. + $this->transient_cleaner->set_stored_transients( + array( + self::POST_TRANSIENT_KEY, + self::TERM_TRANSIENT_KEY, + self::OPTION_TRANSIENT_KEY, + ) + ); + } + + /** + * Test set/get config. + * + * @return void + */ + public function test_set_get_config() + { + $config_1 = $this->transient_cleaner->get_config(); + $this->transient_cleaner->set_config( + array_merge( + $config_1, + array( 'foo' => array() ) + ) + ); + $config_2 = $this->transient_cleaner->get_config(); + + $this->assertIsArray($config_2); + $this->assertNotEmpty($config_2); + $this->assertEquals(count($config_1), count($config_2) - 1); + } + + /** + * Test set/get stored_transients. + * + * @return void + */ + public function test_set_get_stored_transients() + { + $stored_transients_1 = $this->transient_cleaner->get_stored_transients(); + $this->transient_cleaner->set_stored_transients( + array( 'foo' ) + ); + $stored_transients_2 = $this->transient_cleaner->get_stored_transients(); + + $this->assertEquals(array( 'foo' ), $stored_transients_2); + } + + /** + * Test merge_stored_transients_option_values. + * + * @return void + */ + public function test_merge_stored_transients_option_values() + { + $test_no_old_value = $this->transient_cleaner->merge_stored_transients_option_values('foo', false); + $test_old_value = $this->transient_cleaner->merge_stored_transients_option_values('foo', 'foo_old'); + + $test_merge_values = $this->transient_cleaner->merge_stored_transients_option_values( + array( 'foo' ), + array( 'foo_old' ) + ); + $test_merge_values_already_exists = $this->transient_cleaner->merge_stored_transients_option_values( + array( 'foo' ), + array( 'foo_old', 'foo' ) + ); + + $this->assertEquals('foo', $test_no_old_value); + $this->assertEquals('foo_old', $test_old_value); + $this->assertEquals(array( 'foo_old', 'foo' ), $test_merge_values); + $this->assertEquals(array( 'foo_old', 'foo' ), $test_merge_values_already_exists); + } + + /** + * Test store transient. + * + * @return void + */ + public function test_store_transient_key() + { + $test_fail = $this->transient_cleaner->store_transient_key('foo'); + $test_success = $this->transient_cleaner->store_transient_key(TransientCleaner::PREFIX . 'foo'); + + $this->assertFalse($test_fail); + $this->assertTrue($test_success); + } + + /** + * Test post transient cleaner. + * + * @return void + */ + public function test_post_transient_cleaner() + { + $post = $this->factory->post->create_and_get(); + $test_success = $this->transient_cleaner->post_transient_cleaner(1, $post); + + $config_1 = $this->transient_cleaner->get_config(); + unset($config_1['post']); + $this->transient_cleaner->set_config($config_1); + + $test_fail = $this->transient_cleaner->post_transient_cleaner(1, $post); + + $this->assertTrue($test_success); + $this->assertFalse($test_fail); + } + + /** + * Test term transient cleaner. + * + * @return void + */ + public function test_term_transient_cleaner() + { + $taxonomy = 'post_tag'; + $test_success = $this->transient_cleaner->term_transient_cleaner(1, 1, $taxonomy); + + $config_1 = $this->transient_cleaner->get_config(); + unset($config_1['term']); + $this->transient_cleaner->set_config($config_1); + + $test_fail = $this->transient_cleaner->term_transient_cleaner(1, 1, $taxonomy); + + $this->assertTrue($test_success); + $this->assertFalse($test_fail); + } + + /** + * Test option transient cleaner. + * + * @return void + */ + public function test_option_transient_cleaner() + { + $option = 'baz_option'; + $test_success = $this->transient_cleaner->option_transient_cleaner($option); + + $config_1 = $this->transient_cleaner->get_config(); + unset($config_1['option']); + $this->transient_cleaner->set_config($config_1); + + $test_fail = $this->transient_cleaner->option_transient_cleaner($option); + + $this->assertTrue($test_success); + $this->assertFalse($test_fail); + } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 30ef095..2b45e25 100755 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -5,18 +5,16 @@ * @package studiometa/wp-toolkit */ -$_tests_dir = getenv( 'WP_TESTS_DIR' ); +$_tests_dir = getenv('WP_TESTS_DIR'); -if ( ! $_tests_dir ) { - $_tests_dir = rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib'; +if (! $_tests_dir) { + $_tests_dir = rtrim(sys_get_temp_dir(), '/\\') . '/wordpress-tests-lib'; } -if ( ! file_exists( $_tests_dir . '/includes/functions.php' ) ) { - echo "Could not find $_tests_dir/includes/functions.php, have you run bin/install-wp-tests.sh ?" . PHP_EOL; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - exit( 1 ); +if (! file_exists($_tests_dir . '/includes/functions.php')) { + echo "Could not find $_tests_dir/includes/functions.php, have you run bin/install-wp-tests.sh ?" . PHP_EOL; + exit(1); } // Start up the WP testing environment. require $_tests_dir . '/includes/bootstrap.php'; - -