This repository has been archived by the owner on Apr 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwpe-graphql-cache.php
155 lines (130 loc) · 4.87 KB
/
wpe-graphql-cache.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php
/**
* Plugin Name: WP Engine Graphql Cache
* Plugin URI: https://wpengine.com
* Description: WP Engine add ons for wp-graphql in the WP Engine hosted WP environment
* Author: Mark Kelnar
* Text Domain: wpe-graphql-cache
* Domain Path: /languages
* Version: 0.1.3
*
* @package Wpe_Graphql
*/
namespace WPEngine\Graphql;
use WPGraphQL\SmartCache\Cache\Collection;
use WPGraphQL\SmartCache\Admin\Settings;
const MAGIC_STRING = 'wpe-graphql:';
if ( ! function_exists( __NAMESPACE__ . 'log' ) ) {
function log( $msg ) {
if ( defined('GRAPHQL_DEBUG_ENABLED') ) {
error_log( $msg );
graphql_debug( $msg, $config[ 'debug' ] );
}
}
}
/**
* For wpe, when our varnish cache function is invoked, add to paths being filtered.
* See the wpengine must-use plugin for the 'wpe_purge_varnish_cache_paths' filter.
*
* @param array $paths Path, urls to pages cached in varnish to be purged.
* @param int $identifier The requested post_id to purge if one was passed
* or string 'wpe-graphql:all', 'wpe-graphql:cG9zdDo1NjQ='
*/
add_filter( 'wpe_purge_varnish_cache_paths', function ( $paths, $identifier ) {
// If the id doesn't start with our magic string, that means we didn't initiate the purge.
$id = substr( $identifier, 0, strlen( MAGIC_STRING ) );
if ( MAGIC_STRING !== $id ) {
// If not initiated by us, return
return $paths;
}
log( "WpeGraphql Purge Varnish: $identifier " );
// Get the rest of the string after our magic string
$id = substr( $identifier, strlen( MAGIC_STRING ) );
if ( 'all' === $id ) {
// This purges all cached pages at graphql endpoint.
return [ preg_quote( Settings::graphql_endpoint() ) ];
}
// Erase any other paths cause we triggered this and want to purge something specific.
$paths = [];
$collection = new Collection();
$nodes = $collection->get( $id );
log( "WpeGraphql Purge Post: $id " . print_r($nodes, 1) );
// Get the list of queries associated with this key
// Look up graphql path/urls previously queried containing resources and purge those
if ( is_array( $nodes ) ) {
foreach( $nodes as $request_key ) {
$urls = wpe_cache_retrieve_urls( $request_key );
if ( is_array( $urls ) ) {
// Add these specific paths to be purged
foreach ( $urls as $url ) {
// The saved url was raw, unencoded. quote/escape any regex characters in the path for varnish to purge.
$paths[] = preg_quote( $url );
}
}
}
}
// If got here but don't have any actual paths, have to return something, otherwise WPE will purge everything
if ( empty( $paths ) ) {
$paths = [ preg_quote( Settings::graphql_endpoint() . '/' . uniqid('--notreal--') ) ];
}
log( 'WpeGraphql Purge Paths: ' . print_r($paths, 1) );
return array_unique( $paths );
}, 10, 2 );
add_action( 'wpgraphql_cache_purge_all', function () {
/**
* Invoke the WPE varnish purge function with specific identifier
*/
if ( is_callable( [ 'WpeCommon', 'purge_varnish_cache' ] ) ) {
log( 'WpeGraphql Trigger Varnish Purge All' );
// Second argument is 'force'.
\WpeCommon::purge_varnish_cache( MAGIC_STRING . 'all', true );
}
}, 10, 0);
add_action( 'wpgraphql_cache_purge_nodes', function ( $id, $nodes ) {
/**
* Invoke the WPE varnish purge function with specific identifier
*/
if ( is_callable( [ 'WpeCommon', 'purge_varnish_cache' ] ) ) {
log( 'WpeGraphql Trigger Varnish Purge '. $id );
// Second argument is 'force'.
\WpeCommon::purge_varnish_cache( MAGIC_STRING . $id, true );
log( 'WpeGraphql Trigger Varnish Purge - After '. $id );
}
}, 10, 2);
add_action( 'wpgraphql_cache_save_request', function( $request_key ) {
// Only store mappings of urls when it's a GET request
$map_the_url = false;
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
$map_the_url = true;
}
// We don't want POSTs during mutations or nothing on the url. cause it'll purge /graphql*
if ( $map_the_url && ! empty( $_SERVER['REQUEST_URI'] ) ) {
$url_to_save = wp_unslash( $_SERVER['REQUEST_URI'] );
// Save the url this query request came in on, so we can purge it later when something changes
$collection = new Collection();
$urls = $collection->store_content( wpe_cache_url_key( $request_key ), $url_to_save );
log( "Graphql Save Urls: $request_key " . print_r( $urls, 1 ) );
}
}, 10, 1 );
/**
* When save or retrieve urls for a specific Unique identifier for this request for use in the collection map
*
* @param string $id Id for the node
*
* @return string unique id for this request
*/
function wpe_cache_url_key( $id ) {
return 'url:' . $id;
}
/**
* Get the list of urls associated with the content/node/list id
*
* @param mixed|string|int $id The content node identifier
*
* @return array The unique list of content stored
*/
function wpe_cache_retrieve_urls( $id ) {
$key = wpe_cache_url_key( $id );
$collection = new Collection();
return $collection->get( $key );
}