Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change delete term trigger #117

Merged
merged 6 commits into from
Sep 16, 2021
Merged

Change delete term trigger #117

merged 6 commits into from
Sep 16, 2021

Conversation

pschoffer
Copy link

@pschoffer pschoffer commented Sep 10, 2021

Description of the Change

Deleting term needs to do 2 actions:

  • Delete the term
  • Reindex all the child terms

However, if the hook is invoked on delete_term the term is already deleted in WP by then. The operations needed to get the list of child terms then fails.

This change switches the two actions into 2 hooks. On pre_delete_term which happens both before the term is deleted but also before the child terms were updated in WP already, we will enqueue child terms to sync queue. Then on delete_term (same as before) we will remove the term from ES.

The sync queue is then processed on shutdown, that is after the children terms were already updated with the correct parent.

Another change in this PR is adding the permission check bypass for CLI and cron on term resyncing.

Test steps

  1. dev-env exec -- wp elasticpress activate-feature terms

  2. dev-env exec -- wp vip-search index --setup

  3. Create some hierarchy of categories

  4. Delete middle one `dev-env exec -- wp term delete category

  5. No errors

  6. Term is deleted

  7. Check that index is correctly showing the children of deleted term pointing to the parent of deleted term as their parent now

@rebeccahum
Copy link

Just testing this and it looks like you don't even need to create a hierarchy of categories to trigger the below error:

Warning: array_merge(): Expected parameter 2 to be an array, object given in /wp/wp-content/mu-plugins/search/elasticpress/includes/classes/Indexable/Term/SyncManager.php on line 185 [example-site.vipdev.lndo.site/] [wp-content/mu-plugins/search/elasticpress/includes/classes/Indexable/Term/SyncManager.php:185 array_merge(), wp-includes/class-wp-hook.php:305 ElasticPress\Indexable\Term\SyncManager->action_sync_on_delete(), wp-includes/class-wp-hook.php:327 WP_Hook->apply_filters(), wp-includes/plugin.php:470 WP_Hook->do_action(), wp-includes/taxonomy.php:2072 do_action('delete_term'), phar:///usr/local/binvendor/wp-cli/entity-command/src/Term_Command.php:452 wp_delete_term(), Term_Command->delete(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/CommandFactory.php:100 call_user_func(), WP_CLI\Dispatcher\CommandFactory::WP_CLI\Dispatcher\{closure}(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/Subcommand.php:491 call_user_func(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:399 WP_CLI\Dispatcher\Subcommand->invoke(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:422 WP_CLI\Runner->run_command(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Runner.php:1194 WP_CLI\Runner->run_command_and_exit(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php:23 WP_CLI\Runner->start(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/bootstrap.php:77 WP_CLI\Bootstrap\LaunchRunner->process(), phar:///usr/local/binvendor/wp-cli/wp-cli/php/wp-cli.php:27 WP_CLI\bootstrap(), phar:///usr/local/binphp/boot-phar.php:11 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')]

@@ -40,7 +40,7 @@ public function setup() {
add_action( 'added_term_meta', [ $this, 'action_queue_meta_sync' ], 10, 2 );
add_action( 'deleted_term_meta', [ $this, 'action_queue_meta_sync' ], 10, 2 );
add_action( 'updated_term_meta', [ $this, 'action_queue_meta_sync' ], 10, 2 );
add_action( 'delete_term', [ $this, 'action_sync_on_delete' ] );
add_action( 'pre_delete_term', [ $this, 'action_sync_on_delete' ] );

Choose a reason for hiding this comment

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

Is pre_delete_term too early of a hook?

Would it be better to use a later hook such as deleted_term_taxonomy hook which fires right after the deletion occurs to ensure that the term is actually deleted on the DB level right before ES deletes on its side? https://github.com/WordPress/WordPress/blob/243e75eb416657464870ea9092c8750b7221b8fc/wp-includes/taxonomy.php#L2039-L2046

Copy link
Author

Choose a reason for hiding this comment

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

That was my initial thought too, but that hook happens after the child terms were reassigned to another parent. So say you have this scenario if using deleted_term_taxonomy:

  1. A <- B <- C
  2. B is being deleted
  3. pre_delete_term is executed (we do nothing)
  4. C is assigned as a child to A
  5. deleted_term_taxonomy is executed. We look up B's children and find nothing.
  6. Delete B
  7. END (C was not scheduled for reindexing)

vs pre_delete_term

  1. A <- B <- C
  2. B is being deleted
  3. pre_delete_term is executed. We look up B's children and find C.
  4. C is assigned as a child to A
  5. deleted_term_taxonomy is executed. We do nothing
  6. Delete B
  7. END
  8. On shutdown we will reindex C.

I guess another solution is to split the two things into two hooks do the "lookup term being deleted children and queue them up" on pre_delete_term and leave "delete the term" on delete_term. What do you think @rebeccahum ?

Choose a reason for hiding this comment

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

Oh, good point with the nesting hierarchies!

Breaking it up into two separate hooks seems like a good idea to me.

Copy link
Author

Choose a reason for hiding this comment

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

Done.

@@ -185,10 +203,6 @@ public function action_sync_on_delete( $term_id ) {
$hierarchy = array_merge( $ancestors, $children );

foreach ( $hierarchy as $hierarchy_term_id ) {
if ( ! current_user_can( 'edit_term', $hierarchy_term_id ) ) {
Copy link

@rebeccahum rebeccahum Sep 14, 2021

Choose a reason for hiding this comment

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

What are your thoughts on checking if ep_sync_insert_permissions_bypass is applied as well instead of completely removing the permissions check? I'm seeing that it's hooked onto filter_bypass_permission_checks_for_machines to account for CLI: https://github.com/10up/ElasticPress/blob/e3639bbcdec9efdc4680162563bc215c85c6e6bb/includes/classes/Indexable/Post/SyncManager.php#L68.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah there is ep_sync_delete_permissions_bypass as well. I would say it is a plan B on push back :) But I don't really see the benefit of doing permission checking at this state....oooh now I do. I guess anybody's evil plugin could invoke the delete_term hooks not just core WordPress? So even if we are not really deleting the term.

But then again, we are not deleting anything here. We are just saying please update these items to what they really are in DB.

Copy link
Author

Choose a reason for hiding this comment

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

I re-added the check now. Thanks for the input.

Copy link

@rebeccahum rebeccahum left a comment

Choose a reason for hiding this comment

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

LGTM! 🚢

@pschoffer pschoffer merged commit e1c76c2 into develop Sep 16, 2021
@pschoffer pschoffer deleted the update/delete_taxanomy_fix branch September 16, 2021 04:44
@pschoffer
Copy link
Author

Upstream PR: 10up#2349

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants