PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.14.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.14.0
2.14.0 2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 All 81 releases
ablocks / addons / link-guard / invalidation.php

invalidation.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.14.0, at addons/link-guard/invalidation.php

126 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ABlocksLinkGuard;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 use ABlocks\Classes\CacheBackend;
10
11 /**
12 * Keeps the stored link maps honest and tells caches when a page changed
13 * because of *another* post.
14 *
15 * When a scheduled post publishes, a page cache purges that post, the home
16 * page and its archives. It has no idea that last week's article linked to it
17 * and is still being served with the link taken out. The reverse index written
18 * by `Frontend` answers "who links here?", and this class cleans those posts'
19 * object cache and fires `ablocks/link_guard/linking_posts_changed` so a cache
20 * integration can purge exactly those URLs.
21 */
22 class Invalidation {
23
24 public static function init() {
25 $self = new self();
26 add_action( 'save_post', [ $self, 'forget_links' ] );
27 add_action( 'transition_post_status', [ $self, 'status_changed' ], 10, 3 );
28 add_action( 'post_updated', [ $self, 'slug_changed' ], 10, 3 );
29 add_action( 'deleted_post', [ $self, 'deleted' ] );
30 }
31
32 /**
33 * The post's content may have changed, so its links are scanned afresh on
34 * the next render.
35 *
36 * @param int $post_id Saved post.
37 */
38 public function forget_links( $post_id ) {
39 if ( wp_is_post_revision( $post_id ) ) {
40 return;
41 }
42 delete_post_meta( $post_id, Frontend::META );
43 delete_post_meta( $post_id, Frontend::TARGET_META );
44 }
45
46 /**
47 * @param string $new_status New status.
48 * @param string $old_status Previous status.
49 * @param \WP_Post $post The post.
50 */
51 public function status_changed( $new_status, $old_status, $post ) {
52 if ( $new_status === $old_status || in_array( $new_status, [ 'auto-draft', 'inherit' ], true ) ) {
53 return;
54 }
55
56 // A post that was not there before may be what a stored "not a post"
57 // was waiting for.
58 CacheBackend::bump_generation( ABLOCKS_LINK_GUARD_GENERATION_OPTION );
59
60 if ( is_post_status_viewable( $new_status ) !== is_post_status_viewable( $old_status ) ) {
61 self::announce( $post->ID );
62 }
63 }
64
65 /**
66 * @param int $post_id Post ID.
67 * @param \WP_Post $after Post after the update.
68 * @param \WP_Post $before Post before the update.
69 */
70 public function slug_changed( $post_id, $after, $before ) {
71 if ( $after->post_name !== $before->post_name ) {
72 CacheBackend::bump_generation( ABLOCKS_LINK_GUARD_GENERATION_OPTION );
73 }
74 }
75
76 /**
77 * A deleted target makes its links dead, the same as unpublishing it.
78 *
79 * @param int $post_id Deleted post.
80 */
81 public function deleted( $post_id ) {
82 self::announce( $post_id );
83 }
84
85 /**
86 * Posts whose content links to a post.
87 *
88 * @param int $target_id Linked post.
89 * @return int[]
90 */
91 public static function linking_posts( $target_id ) {
92 global $wpdb;
93
94 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
95 $ids = $wpdb->get_col(
96 $wpdb->prepare(
97 "SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s",
98 Frontend::TARGET_META,
99 (string) (int) $target_id
100 )
101 );
102
103 return array_map( 'intval', $ids );
104 }
105
106 private static function announce( $target_id ) {
107 $ids = self::linking_posts( $target_id );
108 if ( ! $ids ) {
109 return;
110 }
111
112 foreach ( $ids as $id ) {
113 clean_post_cache( $id );
114 }
115
116 /**
117 * Posts whose rendered content changed because a post they link to was
118 * published, unpublished or deleted. Purge these from any page cache.
119 *
120 * @param int[] $post_ids Linking posts.
121 * @param int $target_id The post whose status changed.
122 */
123 do_action( 'ablocks/link_guard/linking_posts_changed', $ids, (int) $target_id );
124 }
125 }
126