File "Provider.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/the-events-calendar/src/Events/Custom_Tables/V1/Updates/Provider.php
File size: 10.97 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Handles the custom tables updates integrating with the normal WordPress flow.
*
* @since 6.0.0
*
* @package TEC\Events\Custom_Tables\V1\Updates
*/
namespace TEC\Events\Custom_Tables\V1\Updates;
use TEC\Common\Contracts\Service_Provider;
use TEC\Events\Custom_Tables\V1\Provider_Contract;
use Tribe__Events__Main as TEC;
use WP_Post;
use WP_REST_Request;
use WP_REST_Server;
/**
* Class Provider
*
* @since 6.0.0
*
* @package TEC\Events\Custom_Tables\V1\Updates
*/
class Provider extends Service_Provider implements Provider_Contract {
public function register() {
// Make this provider available in the Service Locator by class and slug.
$this->container->singleton( self::class, $this );
$this->container->singleton( 'tec.events.custom-tables-v1.updates', $this );
/*
* We need this to be a singleton to keep track of the Events to update in the WRITE phase
* of the request and update them before the READ phase of the request.
*/
$this->container->singleton( Controller::class, Controller::class );
/*
* For the whole life cycle of any request, not only explicit update ones, watch for meta updates
* using an object that will need to be the same from the start to the end of the request.
*/
$this->container->singleton( Meta_Watcher::class, Meta_Watcher::class );
// Other bindings are bound as singletons to save some resources.
$this->container->singleton( Requests::class, Requests::class );
$this->container->singleton( Post_Ops::class, Post_Ops::class );
$this->hook_to_watch_for_post_updates();
$this->hook_to_redirect_post_updates();
$this->hook_to_commit_post_updates();
$this->hook_to_delete_post_data();
}
/**
* Before an HTTP request is processed and updates an Event Post, we might need to redirect the update
* to either the real post ID or to a different post ID.
*
* @since 6.0.0
*/
private function hook_to_redirect_post_updates() {
/*
* Classic Editor updates will come through the `wp-admin/post.php` file.
* This includes Trash and Delete requests.
* What will differ is the HTTP method used: POST for updates, GET for Trash and Delete requests.
* In both instances, this is a good place to hook before WordPress identifies the update target.
*/
if ( ! has_action( 'load-post.php', [ $this, 'redirect_classic_editor_post_id' ] ) ) {
add_action( 'load-post.php', [ $this, 'redirect_classic_editor_post_id' ] );
}
/*
* Intercept requests coming from the REST API (thus including Blocks Editor).
*/
add_filter( 'rest_pre_dispatch', [ $this, 'redirect_rest_request_post_id' ], 5, 3 );
}
/**
* Following a request (that _might_ have been redirected to a different post ID), WordPress might
* have updated meta we care about (dates, duration ,timezone et al.).
* Running an update each time one of the meta we care about is updated would be inefficient
* and prone to errors.
* Just earmark Events whose meta has changed as possibly requiring an update, no **actual**
* update to the custom tables happened yet.
*
* @since 6.0.0
*/
private function hook_to_watch_for_post_updates() {
add_action( 'updated_postmeta', [ $this, 'watch_for_meta_updates' ], 10, 3 );
add_action( 'added_post_meta', [ $this, 'watch_for_meta_updates' ], 10, 3 );
add_action( 'deleted_post_meta', [ $this, 'watch_for_meta_updates' ], 10, 3 );
}
/**
* At the end of the request, update the custom tables, if required, following updates
* to the meta we use to model Events.
* The "end of the request" will change depending on the kind of request.
* Requests coming from both the Classic and Blocks Editor will perform updates following
* a WRITE-THEN-READ model: the Event data is updated, then the updated Event data is read
* to build the response or redirect the user to the correct page.
* Other updates might happen programmatically, i.e. by means of calls to the `wp_insert_post`
* and similar functions.
*
* @since 6.0.0
*
*/
private function hook_to_commit_post_updates() {
/*
* Performing updates on `shutdown` will work for any Event that was updated programmatically
* by means of a function like `wp_insert_post`. It's too late for any post that is the object
* of an Editor request, though.
*/
add_action( 'shutdown', [ $this, 'commit_updates' ] );
/*
* This action fires in the context of the `wp-includes/post.php` file and will
* fire after the post has been updated (WRITE) and before it's redirected (READ).
*/
add_filter( 'redirect_post_location', [ $this, 'commit_and_redirect_classic_editor' ], 100, 2 );
/*
* This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
* It fires after the post has been updated (WRITE) following the REST request, and before the
* response is returned (READ).
*/
add_action( 'rest_after_insert_' . TEC::POSTTYPE, [ $this, 'commit_rest_update' ], 100, 2 );
/**
* Hook into the logic that would rebuild the known range, setting the `earliest_date`
* and `latest_date` options, to parse Occurrences, not Events.
*/
add_filter( 'tribe_events_rebuild_known_range', [ $this, 'rebuild_known_range' ] );
}
/**
* Unregisters, from the Filters API, the actions and filters added by this provider.
*
* @since 6.0.0
*/
public function unregister() {
remove_action( 'updated_postmeta', [ $this, 'watch_for_meta_updates' ] );
remove_action( 'added_post_meta', [ $this, 'watch_for_meta_updates' ] );
remove_action( 'deleted_post_meta', [ $this, 'watch_for_meta_updates' ] );
remove_action( 'load-post.php', [ $this, 'redirect_classic_editor_post_id' ] );
remove_filter( 'rest_pre_dispatch', [ $this, 'redirect_rest_request_post_id' ], 5 );
remove_action( 'rest_after_insert_' . TEC::POSTTYPE, [ $this, 'commit_rest_update' ], 100 );
remove_action( 'delete_post', [ $this, 'delete_custom_tables_data' ] );
}
/**
* This plugin will, by default, not redirect the post ID at all.
* It will, instead, fire an action allowing other plugins to
* intervene and redirect the post ID.
*
* @since 6.0.0
*/
public function redirect_classic_editor_post_id() {
/**
* Fires when a Classic Editor request is ready to be redirected, before
* any update specified by the request is applied to the post ID.
*
* @since 6.0.0
*/
do_action( 'tec_events_custom_tables_v1_redirect_classic_editor_event_post' );
}
/**
* Redirect the REST Request, modifying it.
*
* By default, this method will NOT redirect the REST request and will
* only provide other plugins the chance to do so.
*
* @since 6.0.0
*
* @param null|mixed $result The result of the dispatch, as filtered by
* WordPress and previous filters.
* @param WP_REST_Server $server A reference to the REST Server instance
* currently handling the request.
* @param WP_REST_Request $request A reference to the REST Request that is
* going to be handled.
*
* @return null|mixed The input result value: this method will not modify
* the result and will just use the filter as an action.
*/
public function redirect_rest_request_post_id( $result, $server, $request ) {
/**
* Fires when a REST request for an Event is ready to be processed and has not
* yet, been dispatched.
* Plugins that need to redirect the request should do so here.
*
* @since 6.0.0
*
* @param WP_REST_Request $request A reference to the REST Request that is
* going to be handled.
* @param WP_REST_Server $server A reference to the REST Server instance
* currently handling the request.
*/
do_action( 'tec_events_custom_tables_v1_redirect_rest_event_post', $request, $server );
return $result;
}
/**
* Watches the updates to the post objects meta values to detect and keep track
* of changes that might require the data in the custom tables to be updated.
*
* @since 6.0.0
*
* @param array|int $meta_ids Either a meta id or an array of meta ids that
* are being updated.
* @param int $post_id The id of the post that is being updated.
* @param string $meta_key The meta key that is being updated.
*/
public function watch_for_meta_updates( $meta_ids, $post_id, $meta_key ) {
$this->container->make( Meta_Watcher::class )->mark_for_update( $post_id, $meta_key );
}
/**
* Iterates over the list of Event posts that had their Event-related meta
* updated to update their custom tables data.
*
* @since 6.0.0
*/
public function commit_updates() {
$this->container->make( Controller::class )->commit_updates();
}
/**
* Commits custom tables updates for an Event post that might require it in the
* context of a REST API request (including Blocks Editor).
*
* @since 6.0.0
*
* @param WP_Post $post A reference to the Event post object
* that is being updated.
* @param WP_REST_Request $request A reference to the REST Request that is being
* processed.
*/
public function commit_rest_update( $post, $request ) {
if ( ! ( $post instanceof WP_Post && $request instanceof WP_REST_Request ) ) {
return;
}
$this->container->make( Controller::class )->commit_post_rest_update( $post, $request );
}
/**
* Commits custom tables updates for an Event post that might require it in the
* context of a Classic Editor request.
*
* The filter is used as an action, the input `$location` value is not changed.
*
* @since 6.0.0
*
* @param string $location The location the post will be redirected to. Unused by the method.
* @param int $post_id The post ID of the post that is being updated.
*/
public function commit_and_redirect_classic_editor( $location, $post_id ) {
$controller = $this->container->make( Controller::class );
$controller->commit_post_updates( $post_id );
return $controller->redirect_post_location( $location, $post_id );
}
/**
* Hooks on the actions that will be fired when a post is deleted (NOT trashed)
* from the database to, then, remove the custom tables data.
*
* @since 6.0.0
*/
private function hook_to_delete_post_data() {
add_action( 'delete_post', [ $this, 'delete_custom_tables_data' ] );
}
/**
* Hooked on the post delete action, this method will clear all the custom
* tables information related to the Event.
*
* @since 6.0.0
*
* @param int $post_id The deleted Event post ID.
*/
public function delete_custom_tables_data( $post_id ) {
if ( ! is_int( $post_id ) ) {
return;
}
$this->container->make( Controller::class )->delete_custom_tables_data( $post_id );
}
/**
* Rebuild the known range of Events from the Occurrences information.
*
* @since 6.0.0
*
* @return bool Whether the method did take care of rebuilding the known range or not.
*/
public function rebuild_known_range() {
return $this->container->make( Events::class )->rebuild_known_range();
}
}