diff --git a/.github/workflows/php-tests.yml b/.github/workflows/php-tests.yml index 650c1c30..0077d875 100644 --- a/.github/workflows/php-tests.yml +++ b/.github/workflows/php-tests.yml @@ -49,12 +49,11 @@ jobs: env: WP_ENV_CORE: WordPress/WordPress#${{ matrix.wp }} + - name: Run PHPCS diff tests + run: bash bin/phpcs-diff.sh + - name: Run PHPUnit tests (single site) run: composer integration - name: Run PHPUnit tests (multisite) run: composer integration-ms - - # (previously before "Run PHPUnit tests (single site)") - - name: Run PHPCS diff tests - run: bash bin/phpcs-diff.sh diff --git a/README.md b/README.md index 35543bb1..d344e6be 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,9 @@ For support questions, feedback and ideas, please use the [WordPress.org forums] ## Upgrade Notice +**0.9.9** +Bump minimum PHP supported version to 8.0, WordPress minimum supported version to 6.0. + **0.9.8** PHP 8.2 compatible with various bug fixes @@ -128,6 +131,16 @@ New features, including story budget and editorial metadata, a completely rewrit ## Changelog +**0.9.9 (May 24, 2024)** +* Enhancements: bump lowest supported PHP version to 8.0 and lowest WordPress version to 6.0 (https://github.com/Automattic/Edit-Flow/pull/727) +* Test fix: Update ESLint configuration and format JS files (https://github.com/Automattic/Edit-Flow/pull/723) +* Enhancements: Move JS environment to node 20, upgrade packages (https://github.com/Automattic/Edit-Flow/pull/725) + +**0.9.8 (April 10, 2024)** +* Fix WP 5.9 deprecation notice with `who` in `WP_User_Query` (https://github.com/Automattic/Edit-Flow/pull/701) +* Add PHP 8.2 fixes (https://github.com/Automattic/Edit-Flow/pull/700) +* Bump @babel/traverse from 7.1.6 to 7.23.2 (https://github.com/Automattic/Edit-Flow/pull/714) + **0.9.7 (August 26, 2022)** * Bug fix: Allow scheduled posts to be shifted around on calendar (https://github.com/Automattic/Edit-Flow/pull/614) * Bug fix: Add back unpublish status, small css tweak for statuses (https://github.com/Automattic/Edit-Flow/pull/613) diff --git a/edit_flow.php b/edit_flow.php index 52c7d1ca..eda4fe38 100644 --- a/edit_flow.php +++ b/edit_flow.php @@ -32,19 +32,19 @@ function _ef_print_php_version_admin_notice() { } // Define contants -define( 'EDIT_FLOW_VERSION' , '0.9.8' ); -define( 'EDIT_FLOW_ROOT' , dirname(__FILE__) ); -define( 'EDIT_FLOW_FILE_PATH' , EDIT_FLOW_ROOT . '/' . basename(__FILE__) ); -define( 'EDIT_FLOW_URL' , plugins_url( '/', __FILE__ ) ); -define( 'EDIT_FLOW_SETTINGS_PAGE' , add_query_arg( 'page', 'ef-settings', get_admin_url( null, 'admin.php' ) ) ); +define( 'EDIT_FLOW_VERSION', '0.9.9' ); +define( 'EDIT_FLOW_ROOT', __DIR__ ); +define( 'EDIT_FLOW_FILE_PATH', EDIT_FLOW_ROOT . '/' . basename( __FILE__ ) ); +define( 'EDIT_FLOW_URL', plugins_url( '/', __FILE__ ) ); +define( 'EDIT_FLOW_SETTINGS_PAGE', add_query_arg( 'page', 'ef-settings', get_admin_url( null, 'admin.php' ) ) ); // Core class #[\AllowDynamicProperties] class edit_flow { // Unique identified added as a prefix to all options - var $options_group = 'edit_flow_'; - var $options_group_name = 'edit_flow_options'; + public $options_group = 'edit_flow_'; + public $options_group_name = 'edit_flow_options'; /** * @var EditFlow The one true EditFlow @@ -86,7 +86,7 @@ class edit_flow { */ public static function instance() { if ( ! isset( self::$instance ) ) { - self::$instance = new edit_flow; + self::$instance = new edit_flow(); self::$instance->setup_globals(); self::$instance->setup_actions(); // Backwards compat for when we promoted use of the $edit_flow global @@ -101,7 +101,7 @@ private function __construct() { } private function setup_globals() { - $this->modules = new stdClass(); + $this->modules = new stdClass(); $this->modules_count = 0; } @@ -111,32 +111,33 @@ private function setup_globals() { private function load_modules() { // We use the WP_List_Table API for some of the table gen - if ( !class_exists( 'WP_List_Table' ) ) - require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); + if ( ! class_exists( 'WP_List_Table' ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; + } // Edit Flow base module - require_once( EDIT_FLOW_ROOT . '/common/php/class-module.php' ); + require_once EDIT_FLOW_ROOT . '/common/php/class-module.php'; // Edit Flow Block Editor Compat trait - require_once( EDIT_FLOW_ROOT . '/common/php/trait-block-editor-compatible.php' ); + require_once EDIT_FLOW_ROOT . '/common/php/trait-block-editor-compatible.php'; // Scan the modules directory and include any modules that exist there $module_dirs = scandir( EDIT_FLOW_ROOT . '/modules/' ); $class_names = array(); - foreach( $module_dirs as $module_dir ) { + foreach ( $module_dirs as $module_dir ) { if ( file_exists( EDIT_FLOW_ROOT . "/modules/{$module_dir}/$module_dir.php" ) ) { - include_once( EDIT_FLOW_ROOT . "/modules/{$module_dir}/$module_dir.php" ); + include_once EDIT_FLOW_ROOT . "/modules/{$module_dir}/$module_dir.php"; // Prepare the class name because it should be standardized - $tmp = explode( '-', $module_dir ); + $tmp = explode( '-', $module_dir ); $class_name = ''; - $slug_name = ''; - foreach( $tmp as $word ) { + $slug_name = ''; + foreach ( $tmp as $word ) { $class_name .= ucfirst( $word ) . '_'; - $slug_name .= $word . '_'; + $slug_name .= $word . '_'; } - $slug_name = rtrim( $slug_name, '_' ); - $class_names[$slug_name] = 'EF_' . rtrim( $class_name, '_' ); + $slug_name = rtrim( $slug_name, '_' ); + $class_names[ $slug_name ] = 'EF_' . rtrim( $class_name, '_' ); } } @@ -145,11 +146,11 @@ private function load_modules() { $this->helpers = new EF_Module(); // Other utils - require_once( EDIT_FLOW_ROOT . '/common/php/util.php' ); + require_once EDIT_FLOW_ROOT . '/common/php/util.php'; // Instantiate all of our classes onto the Edit Flow object // but make sure they exist too - foreach( $class_names as $slug => $class_name ) { + foreach ( $class_names as $slug => $class_name ) { if ( class_exists( $class_name ) ) { $this->$slug = new $class_name(); } @@ -162,7 +163,6 @@ private function load_modules() { * */ do_action( 'ef_modules_loaded' ); - } /** @@ -203,9 +203,11 @@ function action_init() { // Load all of the modules that are enabled. // Modules won't have an options value if they aren't enabled - foreach ( $this->modules as $mod_name => $mod_data ) - if ( isset( $mod_data->options->enabled ) && $mod_data->options->enabled == 'on' ) + foreach ( $this->modules as $mod_name => $mod_data ) { + if ( isset( $mod_data->options->enabled ) && 'on' == $mod_data->options->enabled ) { $this->$mod_name->init(); + } + } /** * Fires after edit_flow has loaded all modules and module options. @@ -225,26 +227,27 @@ function action_admin_init() { $previous_version = get_option( $this->options_group . 'version' ); if ( $previous_version && version_compare( $previous_version, EDIT_FLOW_VERSION, '<' ) ) { foreach ( $this->modules as $mod_name => $mod_data ) { - if ( method_exists( $this->$mod_name, 'upgrade' ) ) + if ( method_exists( $this->$mod_name, 'upgrade' ) ) { $this->$mod_name->upgrade( $previous_version ); + } } update_option( $this->options_group . 'version', EDIT_FLOW_VERSION ); - } else if ( !$previous_version ) { + } elseif ( ! $previous_version ) { update_option( $this->options_group . 'version', EDIT_FLOW_VERSION ); } // For each module that's been loaded, auto-load data if it's never been run before foreach ( $this->modules as $mod_name => $mod_data ) { // If the module has never been loaded before, run the install method if there is one - if ( !isset( $mod_data->options->loaded_once ) || !$mod_data->options->loaded_once ) { - if ( method_exists( $this->$mod_name, 'install' ) ) + if ( ! isset( $mod_data->options->loaded_once ) || ! $mod_data->options->loaded_once ) { + if ( method_exists( $this->$mod_name, 'install' ) ) { $this->$mod_name->install(); + } $this->update_module_option( $mod_name, 'loaded_once', true ); } } $this->register_scripts_and_styles(); - } /** @@ -253,47 +256,52 @@ function action_admin_init() { public function register_module( $name, $args = array() ) { // A title and name is required for every module - if ( !isset( $args['title'], $name ) ) + if ( ! isset( $args['title'], $name ) ) { return false; + } $defaults = array( - 'title' => '', - 'short_description' => '', + 'title' => '', + 'short_description' => '', 'extended_description' => '', - 'img_url' => false, - 'slug' => '', - 'post_type_support' => '', - 'default_options' => array(), - 'options' => false, - 'configure_page_cb' => false, - 'configure_link_text' => __( 'Configure', 'edit-flow' ), + 'img_url' => false, + 'slug' => '', + 'post_type_support' => '', + 'default_options' => array(), + 'options' => false, + 'configure_page_cb' => false, + 'configure_link_text' => __( 'Configure', 'edit-flow' ), // These messages are applied to modules and can be overridden if custom messages are needed - 'messages' => array( - 'settings-updated' => __( 'Settings updated.', 'edit-flow' ), - 'form-error' => __( 'Please correct your form errors below and try again.', 'edit-flow' ), - 'nonce-failed' => __( 'Cheatin’ uh?', 'edit-flow' ), + 'messages' => array( + 'settings-updated' => __( 'Settings updated.', 'edit-flow' ), + 'form-error' => __( 'Please correct your form errors below and try again.', 'edit-flow' ), + 'nonce-failed' => __( 'Cheatin’ uh?', 'edit-flow' ), 'invalid-permissions' => __( 'You do not have necessary permissions to complete this action.', 'edit-flow' ), - 'missing-post' => __( 'Post does not exist', 'edit-flow' ), + 'missing-post' => __( 'Post does not exist', 'edit-flow' ), ), - 'autoload' => false, // autoloading a module will remove the ability to enable or disable it + 'autoload' => false, // autoloading a module will remove the ability to enable or disable it ); - if ( isset( $args['messages'] ) ) - $args['messages'] = array_merge( (array)$args['messages'], $defaults['messages'] ); - $args = array_merge( $defaults, $args ); - $args['name'] = $name; + if ( isset( $args['messages'] ) ) { + $args['messages'] = array_merge( (array) $args['messages'], $defaults['messages'] ); + } + $args = array_merge( $defaults, $args ); + $args['name'] = $name; $args['options_group_name'] = $this->options_group . $name . '_options'; - if ( !isset( $args['settings_slug'] ) ) + if ( ! isset( $args['settings_slug'] ) ) { $args['settings_slug'] = 'ef-' . $args['slug'] . '-settings'; - if ( empty( $args['post_type_support'] ) ) + } + if ( empty( $args['post_type_support'] ) ) { $args['post_type_support'] = 'ef_' . $name; + } // If there's a Help Screen registered for the module, make sure we // auto-load it - if ( !empty( $args['settings_help_tab'] ) ) + if ( ! empty( $args['settings_help_tab'] ) ) { add_action( 'load-edit-flow_page_' . $args['settings_slug'], array( &$this->$name, 'action_settings_help_menu' ) ); + } $this->modules->$name = (object) $args; - $this->modules_count++; + ++$this->modules_count; /** * Fires after edit_flow has registered a module. @@ -314,10 +322,11 @@ function load_module_options() { foreach ( $this->modules as $mod_name => $mod_data ) { - $this->modules->$mod_name->options = get_option( $this->options_group . $mod_name . '_options', new stdClass ); + $this->modules->$mod_name->options = get_option( $this->options_group . $mod_name . '_options', new stdClass() ); foreach ( $mod_data->default_options as $default_key => $default_value ) { - if ( !isset( $this->modules->$mod_name->options->$default_key ) ) + if ( ! isset( $this->modules->$mod_name->options->$default_key ) ) { $this->modules->$mod_name->options->$default_key = $default_value; + } } $this->$mod_name->module = $this->modules->$mod_name; @@ -340,8 +349,9 @@ function load_module_options() { function action_init_after() { foreach ( $this->modules as $mod_name => $mod_data ) { - if ( isset( $this->modules->$mod_name->options->post_types ) ) + if ( isset( $this->modules->$mod_name->options->post_types ) ) { $this->modules->$mod_name->options->post_types = $this->helpers->clean_post_type_options( $this->modules->$mod_name->options->post_types, $mod_data->post_type_support ); + } $this->$mod_name->module = $this->modules->$mod_name; } @@ -358,11 +368,12 @@ function get_module_by( $key, $value ) { foreach ( $this->modules as $mod_name => $mod_data ) { if ( $key == 'name' && $value == $mod_name ) { - $module = $this->modules->$mod_name; + $module = $this->modules->$mod_name; } else { - foreach( $mod_data as $mod_data_key => $mod_data_value ) { - if ( $mod_data_key == $key && $mod_data_value == $value ) + foreach ( $mod_data as $mod_data_key => $mod_data_value ) { + if ( $mod_data_key == $key && $mod_data_value == $value ) { $module = $this->modules->$mod_name; + } } } } @@ -374,15 +385,16 @@ function get_module_by( $key, $value ) { */ function update_module_option( $mod_name, $key, $value ) { $this->modules->$mod_name->options->$key = $value; - $this->$mod_name->module = $this->modules->$mod_name; + $this->$mod_name->module = $this->modules->$mod_name; return update_option( $this->options_group . $mod_name . '_options', $this->modules->$mod_name->options ); } function update_all_module_options( $mod_name, $new_options ) { - if ( is_array( $new_options ) ) - $new_options = (object)$new_options; + if ( is_array( $new_options ) ) { + $new_options = (object) $new_options; + } $this->modules->$mod_name->options = $new_options; - $this->$mod_name->module = $this->modules->$mod_name; + $this->$mod_name->module = $this->modules->$mod_name; return update_option( $this->options_group . $mod_name . '_options', $this->modules->$mod_name->options ); } @@ -396,17 +408,17 @@ function register_scripts_and_styles() { wp_register_style( 'jquery-listfilterizer', EDIT_FLOW_URL . 'common/css/jquery.listfilterizer.css', false, EDIT_FLOW_VERSION, 'all' ); - wp_localize_script( 'jquery-listfilterizer', - '__i18n_jquery_filterizer', - array( - 'all' => esc_html__( 'All', 'edit-flow' ), - 'selected' => esc_html__( 'Selected', 'edit-flow' ), - ) ); + wp_localize_script( + 'jquery-listfilterizer', + '__i18n_jquery_filterizer', + array( + 'all' => esc_html__( 'All', 'edit-flow' ), + 'selected' => esc_html__( 'Selected', 'edit-flow' ), + ) + ); wp_register_script( 'jquery-quicksearch', EDIT_FLOW_URL . 'common/js/jquery.quicksearch.js', array( 'jquery' ), EDIT_FLOW_VERSION, true ); - } - } function EditFlow() { diff --git a/package-lock.json b/package-lock.json index 579f68a9..211c1637 100644 --- a/package-lock.json +++ b/package-lock.json @@ -485,9 +485,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", - "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", + "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", "engines": { "node": ">=6.9.0" } @@ -577,9 +577,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", "engines": { "node": ">=6.9.0" } @@ -788,13 +788,13 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", - "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.6.tgz", + "integrity": "sha512-gNkksSdV8RbsCoHF9sjVYrHfYACMl/8U32UfUhJ9+84/ASXw8dlx+eHyyF0m6ncQJ9IBSxfuCkB36GJqYdXTOA==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.6" }, "engines": { "node": ">=6.9.0" diff --git a/readme.txt b/readme.txt index 7a460613..195de676 100644 --- a/readme.txt +++ b/readme.txt @@ -2,10 +2,10 @@ Contributors: batmoo, danielbachhuber, sbressler, automattic Donate link: http://editflow.org/contribute/ Tags: edit flow, workflow, editorial, newsroom, management, journalism, post status, custom status, notifications, email, comments, editorial comments, usergroups, calendars, editorial calendar, story budget -Requires at least: 5.2 -Requires PHP: 5.6 -Tested up to: 5.8 -Stable tag: 0.9.8 +Requires at least: 6.0 +Requires PHP: 8.0 +Tested up to: 6.5 +Stable tag: 0.9.9 Redefining your editorial workflow. @@ -57,6 +57,12 @@ For support questions, feedback and ideas, please use the [WordPress.org forums] == Upgrade Notice == += 0.9.9 = +Bump minimum PHP supported version to 8.0, WordPress minimum supported version to 6.0. + += 0.9.8 = +PHP 8.2 compatible with various bug fixes + = 0.9.7 = PHP 8 compatible now with various bug fixes @@ -131,6 +137,16 @@ New features, including story budget and editorial metadata, a completely rewrit == Changelog == += 0.9.9 (May 24, 2024) = +* Enhancements: bump lowest supported PHP version to 8.0 and lowest WordPress version to 6.0 (https://github.com/Automattic/Edit-Flow/pull/727) +* Test fix: Update ESLint configuration and format JS files (https://github.com/Automattic/Edit-Flow/pull/723) +* Enhancements: Move JS environment to node 20, upgrade packages (https://github.com/Automattic/Edit-Flow/pull/725) + += 0.9.8 (April 10, 2024) = +* Fix WP 5.9 deprecation notice with `who` in `WP_User_Query` (https://github.com/Automattic/Edit-Flow/pull/701) +* Add PHP 8.2 fixes (https://github.com/Automattic/Edit-Flow/pull/700) +* Bump @babel/traverse from 7.1.6 to 7.23.2 (https://github.com/Automattic/Edit-Flow/pull/714) + = 0.9.7 (Aug 26, 2022) = * Bug fix: Allow scheduled posts to be shifted around on calendar (https://github.com/Automattic/Edit-Flow/pull/614) * Bug fix: Add back unpublish status, small css tweak for statuses (https://github.com/Automattic/Edit-Flow/pull/613) diff --git a/tests/e2e/utils/index.js b/tests/e2e/utils/index.js index f41755a2..5838fd45 100644 --- a/tests/e2e/utils/index.js +++ b/tests/e2e/utils/index.js @@ -1,4 +1,5 @@ const addCategoryToPost = async (categoryName) => { + await ensureSidebarOpened(); await page.waitForXPath('//button[text()="Categories"]'); await page.$$eval( @@ -6,7 +7,7 @@ const addCategoryToPost = async (categoryName) => { ( sidebarButtons ) => { const categoriesButton = sidebarButtons.filter( el => el.textContent === 'Categories' ); - if ( categoriesButton.length === 1 ) { + if ( categoriesButton.length === 1 && categoriesButton[ 0 ].getAttribute( 'aria-expanded' ) !== true ) { categoriesButton[ 0 ].scrollIntoView(); categoriesButton[ 0 ].click(); } @@ -89,7 +90,19 @@ const schedulePost = async() => { await yearInput.type( year ); await publishPost(); +} +const ensureSidebarOpened = async() => { + const toggleSidebarButton = await page.$( + '.edit-post-header__settings [aria-label="Settings"][aria-expanded="false"],' + + '.edit-site-header__actions [aria-label="Settings"][aria-expanded="false"],' + + '.edit-widgets-header__actions [aria-label="Settings"][aria-expanded="false"],' + + '.edit-site-header-edit-mode__actions [aria-label="Settings"][aria-expanded="false"]' + ); + + if ( toggleSidebarButton ) { + await toggleSidebarButton.click(); + } } export { addCategoryToPost, publishPost, schedulePost };