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

Documentation on writing custom Watchers #224

Open
fyaconiello opened this issue Jul 15, 2022 · 1 comment
Open

Documentation on writing custom Watchers #224

fyaconiello opened this issue Jul 15, 2022 · 1 comment
Labels
documentation Something about our documentation needs updated

Comments

@fyaconiello
Copy link

Is your feature request related to a problem? Please describe.
I am trying to hook into the watcher system to add support for Events Calendar Pro recurrence. On current recurrence "Add New Event" the posts that are created do not contain all of the updated meta for event instances - notably the permalink is still set to include the date "1970-01-01" until a later action/filter occurs in the ECP save stack. ECP provides a hook

add_action( 'tribe_events_pro_recurring_event_save_after', ...

but there is no documented/supported way to force sync an item in that hook

Describe the solution you'd like
I'd like an example and documentation on how to implement custom Algolia_Changes_Watcher instances or how to add additional watchers to an existing one (Algolia_Post_Changes_Watcher).

Describe alternatives you've considered
I've tried creating a custom Watcher and implementing the filter, but it didn't fire.

<?php

use Algolia\AlgoliaSearch\Exceptions\AlgoliaException;


/**
 * Class My_Post_Changes_Watcher
 *
 * @since 1.0.0
 */
class My_Post_Changes_Watcher implements Algolia_Changes_Watcher {

	/**
	 * Algolia_Index instance.
	 *
	 * @author WebDevStudios <contact@webdevstudios.com>
	 * @since  1.0.0
	 *
	 * @var Algolia_Index
	 */
	private $index;

	/**
	 * Deleted posts array.
	 *
	 * @author WebDevStudios <contact@webdevstudios.com>
	 * @since  1.0.0
	 *
	 * @var Array
	 */
	private $posts_deleted = array();

	/**
	 * Algolia_Post_Changes_Watcher constructor.
	 *
	 * @author WebDevStudios <contact@webdevstudios.com>
	 * @since  1.0.0
	 *
	 * @param Algolia_Index $index Algolia_Index instance.
	 */
	public function __construct( Algolia_Index $index ) {
		$this->index = $index;
	}

	/**
	 * Watch WordPress events.
	 *
	 * @author  WebDevStudios <contact@webdevstudios.com>
	 * @since   1.0.0
	 */
	public function watch() {
		// Fires once recurring event info has been saved.
		add_action( 'tribe_events_pro_recurring_event_save_after', array( $this, 'sync_item' ) );
	}

	/**
	 * Sync item.
	 *
	 * @author  WebDevStudios <contact@webdevstudios.com>
	 * @since   1.0.0
	 *
	 * @param int $post_id The post ID to sync.
	 * @param int $parent_id The postparent ID to sync.
	 *
	 * @return void
	 */
	public function sync_item( $post_id, $parent_id=NULL ) {

		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}

		if ( in_array( $post_id, $this->posts_deleted, true ) ) {
			return;
		}

		$post = get_post( (int) $post_id );
		if ( ! $post || ! $this->index->supports( $post ) ) {
			return;
		}

		try {
			$this->index->sync( $post );
		} catch ( AlgoliaException $exception ) {
			error_log( $exception->getMessage() ); // phpcs:ignore -- Legacy.
		}
	}

	/**
	 * Delete item.
	 *
	 * @author  WebDevStudios <contact@webdevstudios.com>
	 * @since   1.0.0
	 *
	 * @param int $post_id The post ID to delete.
	 *
	 * @return void
	 */
	public function delete_item( $post_id ) {

		$post = get_post( (int) $post_id );
		if ( ! $post || ! $this->index->supports( $post ) ) {
			return;
		}

		try {
			$this->index->delete_item( $post );
			$this->posts_deleted[] = $post->ID;
		} catch ( AlgoliaException $exception ) {
			error_log( $exception->getMessage() ); // phpcs:ignore -- Legacy.
		}
	}

	/**
	 * Watch meta changes for item.
	 *
	 * @author WebDevStudios <contact@webdevstudios.com>
	 * @since  1.0.0
	 *
	 * @param string|array $meta_id   The meta ID.
	 * @param int          $object_id The post ID.
	 * @param string       $meta_key  The meta key.
	 *
	 * @return void
	 */
	public function on_meta_change( $meta_id, $object_id, $meta_key ) {
		$keys = array( '_thumbnail_id' );
		$keys = (array) apply_filters( 'algolia_watch_post_meta_keys', $keys, $object_id );

		if ( ! in_array( $meta_key, $keys, true ) ) {
			return;
		}

		$this->sync_item( $object_id );
	}
}

and

add_filter( 'algolia_changes_watchers', function ( $changes_watchers ) {
	// Allow developers to filter the indices.
	$indices 			= [];
	$indices 			= (array) apply_filters( 'algolia_indices', $indices );
	$settings			= new Algolia_Settings();
	$api  				= new Algolia_API( $settings );
	$client     		= $api->get_client();
	$index_name_prefix 	= $settings->get_index_name_prefix();
	$synced_indices_ids = $settings->get_synced_indices_ids();

	foreach ( $indices as $index ) {
		$index->set_name_prefix( $index_name_prefix );
		$index->set_client( $client );

		if ( in_array( $index->get_id(), $synced_indices_ids, true ) ) {
			$index->set_enabled( true );

			if ( $index->contains_only( 'posts' ) ) {
				require_once( './class-my-post-changes-watcher.php' );
				$changes_watchers[] = new My_Post_Changes_Watcher( $index );
			}
		}
	}

	return $changes_watchers;
} );

Additional context
If I just drop my add_action( 'tribe_events_pro_recurring_event_save_after', array( $this, 'sync_item' ) ); line in the Algolia_Post_Changes_Watcher's watch function, then it works, but i can't update.

@tw2113
Copy link
Member

tw2113 commented Jul 15, 2022

Hmm. New to watcher customization, so doing my best to follow along here.

The primary issue, is that the pushing up of an event, to Algolia, is running before needed, to include all of the expected meta data? So you're trying to hook in and watch/sync yourself at a later point so that all the information is available to index?

I see you have your callback to add a new watcher, based on the filter on line 331 of includes/class-algolia-plugin.php

You're fetching the indices similar to how the load_indices() method is doing, which is also where the algolia_changes_watchers filter is run from.

My first question is if you've verified that at minimum, the $change_watchers array got updated with all the parts you're expecting, and if they match pretty close to the other items in that array.

My second question is if the My_Post_Changes_Watcher class is known to be loading at all. A "dumb" way to test would be just perhaps a temporary wp_die('testing') inside the constructor, for example.

Followed up by a similar test perhaps in that sync_item method from your class.

Taking baby steps through it all here :).

@tw2113 tw2113 added the documentation Something about our documentation needs updated label Aug 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Something about our documentation needs updated
Projects
None yet
Development

No branches or pull requests

2 participants