wp-search-with-algolia
wp-search-with-algolia copied to clipboard
Documentation on writing custom Watchers
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 <[email protected]>
* @since 1.0.0
*
* @var Algolia_Index
*/
private $index;
/**
* Deleted posts array.
*
* @author WebDevStudios <[email protected]>
* @since 1.0.0
*
* @var Array
*/
private $posts_deleted = array();
/**
* Algolia_Post_Changes_Watcher constructor.
*
* @author WebDevStudios <[email protected]>
* @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 <[email protected]>
* @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 <[email protected]>
* @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 <[email protected]>
* @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 <[email protected]>
* @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.
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 :).