Skip to content

Conversation

@ingeniumed
Copy link
Contributor

@ingeniumed ingeniumed commented Sep 26, 2024

Description

  • Migrate custom status to use term_meta, similar to Migrate EM to use term_meta #41
  • Change the taxonomy used by custom status to be unique, so it won't interfere with Edit Flow. The slug has been left as is, just to not make it a minefield of bugs. This should be fine for now imo.
  • Add in support for storing editorial metadata fields on a status so we can make that required in another PR
  • Update the frontend of a status to show this new restriction.

Testing

  • Remove your custom status options as the taxonomy is different, so that should be sufficient.
  • Ensure normal CRUD operations against a status works fine
  • Ensure CRUD operations against an EM on a status works fine as well

@ingeniumed ingeniumed self-assigned this Sep 26, 2024

// This is taxonomy name used to store all our custom statuses
const TAXONOMY_KEY = 'post_status';
const TAXONOMY_KEY = 'vw_post_status';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the taxonomy so it won't interfere with Edit Flow. I left the slug as is as that would create more problems imo, since we have some statuses that cannot be deleted and their slug matches core slugs. We would need to add in branching logic to tackle that. This keeps it a bit simpler.


// The metadata keys for the custom status term
const METADATA_POSITION_KEY = 'position';
const METADATA_REQ_EDITORIAL_FIELDS_KEY = 'required_metadata_fields';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went back and forth on calling this ID or fields. I left it as fields to mark the purpose of this field. Unlike the users field, there are no full EM objects being given back.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about required_metadata_field_ids?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had that, but it became such a mouthful that I reverted it. I'll change the fields to ids


wp_localize_script( 'vip-workflow-custom-status-configure', 'VW_CUSTOM_STATUS_CONFIGURE', [
'custom_statuses' => $this->get_custom_statuses(),
'editorial_metadatas' => EditorialMetadata::get_editorial_metadata_terms(),
Copy link
Contributor Author

@ingeniumed ingeniumed Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's taxonomy conflicts that happen due to the different inits calling get_terms/get_term. As a result, this is way safer to do so the client can handle the mapping. We could do some mapping but I didn't want more conflicts happening here to.

Perhaps after custom status is migrated, we can revisit this. I don't feel like the refactor would fix this but I could be wrong.

<script type="text/javascript">
var custom_statuses = <?php echo json_encode( $all_statuses ); ?>;
var current_status = '<?php echo esc_js( $selected ); ?>';
var current_status_name = '<?php echo esc_js( $selected_name ); ?>';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused field

$required_metadata_fields = $args['required_metadata_fields'] ?? [];
$required_user_ids = $args['required_user_ids'] ?? [];

// In case of failure, data cleanup happens which includes the term and the meta keys.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures we don't have bad data sitting around that we need to handle.

Ideally, once all our features are clean we should have a regular cron job that goes in and deletes all the bad data that could exist.

return $allcaps;
}

// ToDo: Once custom status has been refactored, the below CRUD methods should be unified with the
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was my little todo to create a generic DB utility class that could handle CRUD operations rather than us repeating the code everywhere.

Copy link
Contributor

@alecgeatches alecgeatches Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! This would be a great way to pull EM and custom-status meta getters and setters into per-datum classes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, let's create a separate issue for this ToDo and ideally remove all of the ToDos in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yip, I was gonna do that before a merge just so all the issues are made in one go. 100% agreed though

$field = 'term_id';
$custom_status = get_term( $value, self::TAXONOMY_KEY );
} else {
$custom_status = get_term_by( $field, $value, self::TAXONOMY_KEY );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much faster imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me!

const [ requiredUsers, setRequiredUsers ] = useState( customStatus?.meta?.required_users || [] );

// Taxonomy conflicts arise if this is done server side, so this transient field is only set here.
const [ requiredMetadatas, setRequiredMetadatas ] = useState( () => {
Copy link
Contributor Author

@ingeniumed ingeniumed Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the taxonomy problems, this is needed. I noticed I had some bad data sitting around so this helps to clean it up whenever an update happens. It's fine if its silent right now, but ideally we should handle this on the backend with a cron cleanup job that has proper logging.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "taxonomy problems"/"taxonomy conflicts" here? I'm not sure what problem this is solving.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I originally had:

  • Filter against get_term and get_terms in EM that used it's taxonomy to populate each term with the necessary term_meta.
  • Filter against get_term and get_terms in CS that used it's taxonomy to populate each term with the necessary term_meta.

What ended up happening was related to init problems:

  • Within EM, CS taxonomy was given back. That was rejected because we only target the EM taxonomy so no term_meta was populated.
  • Within CS, EM taxonomy was given back. That was rejected because we only target the CS taxonomy so no term_meta was populated.

So the safest option to me was:

Just do this on the client side for now.

What I'd like to do ideally:

Add a GET api to CS and EM endpoints and add this functionality there. Ideally that's how all this data massaging is done and it should hopefully not have as many conflicts.

use VIPWorkflow\Modules\Custom_Status;
use VIPWorkflow\VIP_Workflow;

class RequiredFieldsCronCleaner {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Common utility class that handles the cleanup of the required fields without needing to duplicate the code everytime. This would be an ideal candidate for a cron cleaner as well imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the use of Cron in the name here, which I would take to mean there's scheduled cron calls. I'm not seeing anything cron-related though, am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it on purpose because we can add cron to this down the line, to handle data cleanup. I meant for this to be a central cleaner of data I suppose.

return true;
}

private static function is_valid_user_ids( $user_ids ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the user lookup a lot faster by making it a simple batch SQL query.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool solution!

}

// ToDo: Optimize this to batch fetch metadata terms, and only include the ID field.
foreach ( $metadata_ids as $metadata_id ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing as below needs to happen here, I've punted it for later as that's a new method that needs to go into EM.

public static function insert_editorial_metadata_term( array $args ): WP_Term|WP_Error {
$term_to_save = [
'slug' => $args['slug'] ?? '',
'slug' => $args['slug'] ?? sanitize_title( $args['name'] ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed via tests that this wasn't being set properly if it wasn't passed in.

@ingeniumed ingeniumed marked this pull request as ready for review September 30, 2024 03:12
@ingeniumed ingeniumed requested a review from a team as a code owner September 30, 2024 03:12
add_action( 'admin_menu', [ $this, 'add_admin_menu' ], 6 /* Prior to default registration of sub-pages */ );

// These seven-ish methods are hacks for fixing bugs in WordPress core
add_action( 'admin_init', [ $this, 'check_timestamp_on_publish' ] );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up using the chance to clear our this core hack that was in place. Essentially, by adding date_floaing to our custom statuses it's able to get pulled into any of the get_post_stati calls as they check if the date_floaing is true or not. This allows the timestamp to get set correctly. To test this, you have to ensure your timezone offset is set correctly. Before I added the date_floating, if you took out the hacks you'd see the GMT time only be set even if your timezone was set correctly. Also, the exact time of publishing was off a bit.

With this, we should be down 2 core hacks which is nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@alecgeatches
Copy link
Contributor

Taking a look at this PR! From initial testing I'm unable to get editorial metadata to register correctly. I tried deleting the vip_workflow_editorial_metadata_options option to get it to initialize correctly:

$ vip dev-env shell -- wp option delete vip_workflow_editorial_metadata_options

[30-Sep-2024 16:10:55 UTC] Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [$ /usr/local/bin/wp option delete vip_workflow_editorial_metadata_options] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:20 include('phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php'), /usr/local/bin/wp:4 include('phar:///usr/local/binphp/boot-phar.php')]
[30-Sep-2024 16:10:55 UTC] Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [$ /usr/local/bin/wp option delete vip_workflow_editorial_metadata_options] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:20 include('phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php'), /usr/local/bin/wp:4 include('phar:///usr/local/binphp/boot-phar.php')]
[30-Sep-2024 16:10:55 UTC] Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [$ /usr/local/bin/wp option delete vip_workflow_editorial_metadata_options] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:20 include('phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php'), /usr/local/bin/wp:4 include('phar:///usr/local/binphp/boot-phar.php')]
[30-Sep-2024 16:10:55 UTC] Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [$ /usr/local/bin/wp option delete vip_workflow_editorial_metadata_options] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:20 include('phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php'), /usr/local/bin/wp:4 include('phar:///usr/local/binphp/boot-phar.php')]
[30-Sep-2024 16:10:55 UTC] Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [$ /usr/local/bin/wp option delete vip_workflow_editorial_metadata_options] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:20 include('phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php'), /usr/local/bin/wp:4 include('phar:///usr/local/binphp/boot-phar.php')]
Warning: Could not delete 'vip_workflow_editorial_metadata_options' option. Does it exist?

I'm also seeing a truckload of error logs via vip dev-env logs -f when loading the Editorial Metadata admin page:

php-1             | 2024-09-30T16:11:29.580656001Z NOTICE: PHP message: PHP Warning:  Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426
nginx-1           | 2024-09-30T16:11:29.635485626Z 2024/09/30 16:11:29 [error] 125#125: *10354 FastCGI sent in stderr: "PHP message: PHP Warning:  Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426; PHP message: PHP Warning:  The `/wp/wp-content/jetpack-waf` file cannot be managed by the `Automattic\VIP\Files\WP_Filesystem_VIP` class. Writes are only allowed for the `/tmp/` and `/wp/wp-content/uploads` directories and reads can be performed everywhere. in /wp/wp-content/mu-plugins/files/class-wp-filesystem-vip.php on line 94" while reading response header from upstream, client: 172.19.0.2, server: localhost, request: "GET /wp-admin/admin.php?page=vw-editorial-metadata HTTP/1.1", upstream: "fastcgi://172.23.0.8:9000", host: "workflow.vipdev.lndo.site", referrer: "http://workflow.vipdev.lndo.site/wp-admin/"
php-1             | 2024-09-30T16:11:30.527362002Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.527598752Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.527609252Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.527743210Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.527918585Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.639711710Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.639962710Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.640063043Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.640227418Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]
php-1             | 2024-09-30T16:11:30.640405377Z NOTICE: PHP message: Warning: Trying to access array offset on value of type null in /wp/wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php on line 426 [workflow.vipdev.lndo.site] [wp-content/plugins/vip-workflow-plugin/modules/editorial-metadata/editorial-metadata.php:65 VIPWorkflow\Modules\EditorialMetadata::get_postmeta_args(), wp-includes/class-wp-hook.php:324 VIPWorkflow\Modules\EditorialMetadata::register_editorial_metadata_terms_as_post_meta(), wp-includes/class-wp-hook.php:348 WP_Hook->apply_filters(), wp-includes/plugin.php:517 WP_Hook->do_action(), wp-settings.php:700 do_action('init'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1375 require('wp-settings.php'), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1294 WP_CLI\Runner->load_wordpress(), /usr/local/sharevendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:28 WP_CLI\Runner->start(), /usr/local/sharevendor/wp-cli/wp-cli/php/bootstrap.php:83 WP_CLI\Bootstrap\LaunchRunner->process(), /usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php:32 WP_CLI\bootstrap(), /var/wpvip/fpm-cron-runner.php:79 require_once('/usr/local/sharevendor/wp-cli/wp-cli/php/wp-cli.php')]

I also tried deleting the vip_workflow_custom_status_options option at the same time and still can not get anything to show up on the EM page. I'm going to try a clean install next.

@alecgeatches
Copy link
Contributor

alecgeatches commented Sep 30, 2024

Okay! Fresh install fixed it, I think I'm all set to test.

return [];
} );

console.log( requiredMetadatas );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left-over console log here.


public static function init(): void {
// Remove deleted users from required users, and if a user is reassigned, update the required users
add_action( 'delete_user', [ __CLASS__, 'remove_deleted_user_from_required_users' ], 10, 2 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a step toward more complexity from the prior implementation in required-user-ids.php, because we're combining the cleanup of several different types of metadata into a larger file, as opposed to having small encapsulated behaviors in meta-specific files. I see what you're trying to do here with combining functionality, but overall I think the prior logic is easy to read, simple, and directly scoped to the metadata type. These two filters aren't really connected other than the fact that they have similar logic for filtering a list.

If we add cleanup for new features, we'll probably need to expand this file to support those types, or if it doesn't fit this abstraction we'll need to change the abstraction or expand the file with unrelated code. Where possible, I think the best way to fight complexity is to keep file sizes smaller and class responsibilities self-contained, and I'm feeling like the design here goes in the opposite direction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked it over, and we will do a hybrid approach:

  • Keep the individual files focused on cleaning up one field
  • Move the common code to a utility file

* @param string $taxonomy_key The key of the taxonomy to get the required fields from
* @return array The required ids required to make changes to the status
*/
public static function get( int $term_id, string $taxonomy_key ): array {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should probably be private functions, unless we're expecting to call RequiredFieldsCronCleaner::get( ... )/update( ... ) from other files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yip, this should be private

$status->$key = $value;
}
}
$statuses = array_map( [ $this, 'add_metadata_to_term' ], $statuses );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a great alternative to add_metadata_to_term() would be if individual metadata fields could add themselves, e.g.

$statuses = array_map( function( $status ) {
    $term_meta = apply_filters( 'vw_register_custom_status_meta', [], $status );
    $status->meta = $term_meta;
}, $statuses );

Then if we have individual files for metadata fields, we could have self-contained method where we add metadata for a particular field, like this for user IDs:

add_filter( 'vw_register_custom_status_meta', [ __CLASS__, 'add_term_meta'] );

function add_term_meta( $term_meta, $status ) {
	$user_ids = get_term_meta( $term->term_id, self::META_KEY, true );
	if ( ! is_array( $user_ids ) ) {
		$user_ids = [];
	}

	$term_meta[ self::META_KEY ] = $user_ids;

	return $term_meta;
}

This would give us an easier way to add new metadata without continuing to grow this function and isolate individual metadata handling. What do you think?

* @param array $args The arguments to encode
* @return string Arguments encoded in base64
*/
public static function get_encoded_description( $args = array() ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 for removing the base64 encoding!

return $term;
}

// if metadata is already set, don't overwrite it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this check become necessary?

Copy link
Contributor

@alecgeatches alecgeatches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big PR! Lot of changes in here I'd like to discuss. First though, here are a couple of UI issues I noticed:

  1. Unable to removed saved EM fields on a custom status:

    2024-09-30 10 44 05

    To replicate, save some required EM fields on a status, re-open the status, and attempt to remove a saved field. This crashes React with this error:

    Uncaught TypeError: requiredMetadata is undefined
        <anonymous> metadata-select-form-token-field.js:22
        MetadataSelectFormTokenField metadata-select-form-token-field.js:21
        -- React 16 --
        handleOnChange metadata-select-form-token-field.js:82
        deleteToken components.js:60419
        onTokenClickRemove components.js:60276
        onClick components.js:59996
        key components.js:2265
        -- React 32 --
        handleEditStatus workflow-manager.js:168
        key components.js:2265
        -- React 22 --
        <anonymous> custom-status-configure.js:12
        domReady dom-ready.js:71
        <anonymous> custom-status-configure.js:8
        <anonymous> custom-status-configure.js:14019
        <anonymous> custom-status-configure.js:14021
    metadata-select-form-token-field.js:22:3
    
  2. Probably more importantly, I think the "Required Metadata Fields" might not be a good candidate for a <FormTokenField> control:

    Screenshot 2024-09-30 at 10 34 36 AM

    It feels awkward to have to type a couple letters of a EM field to see a dropdown, especially when there's only a handful of options. I really just want a list of EM fields without needing to remember and type their names specifically. A multiselect-like component would be nice, or maybe a <ComboboxControl> for EM field selection that dumps the selected fields into another control.

    If you disagree or now doesn't seem like the time, the __experimentalExpandOnFocus flag for <FormTokenField> improves the UI a bit. It's a big buggy in my testing whether or not suggestions show up on first click (it seems like you need to type something and then backspace to see all suggestions), but in general it makes finding EM fields easier.

  3. This is more of an unrelated UI thing I noticed today, but it would be great if EM text fields saved and dismissed on enter key press. I kept expecting that to work when using those fields:

    2024-09-30 10 34 13


There are some other design changes I've discussed in comments. The overarching discussion revolves around centralizing our meta management code versus splitting it into files that manage each bit of metadata.

I'm in favor of splitting meta management into smaller self-contained files that use filters to interact with the bigger picture. With that noted, this PR is still a great improvement over where we were, so that discussion isn't a blocker. I would like to plan splitting some of these larger files into separate self-contained classes in the future, though, or at least discuss it.

@ingeniumed
Copy link
Contributor Author

I've fixed everything save for 2 items:

  • Switching the formTokenField for the required metadata ids, to something else as well as fixing what happens when you hit x on a term. I'm leaving that for another PR as I want to tweak that further. Right now, this PR is large enough as is.
  • Saving/Dismissing on enter key press for the block editor - that'll be revisited when implementing the requirement of certain metadata fields so I'll leave it for that PR.

@ingeniumed ingeniumed merged commit 5aa93d7 into trunk Oct 1, 2024
@ingeniumed ingeniumed deleted the migrate/custom-status-to-use-meta branch October 1, 2024 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants