Varnish HTTP Purge - Version 4.0

Version Description

  • Added Varnish Status Page - Tools -> Varnish Status (includes basic scanning etc)
  • Allow filter for home_url()
  • Update readme with list of filters.
  • Added wp-cli commands to flush specific URLs and wildcards
  • Requires wp-cli 0.25+ to work 3315 for WP 4.6+
  • Update purgePost() to validate page_for_posts (Props JeremyClarke)
  • Add check for AMP (Props JeremyClarke)
  • Purge 'default' AMP URL as well
  • Cleanup on Uninstall

=

Download this release

Release Info

Developer Ipstenu
Plugin Icon 128x128 Varnish HTTP Purge
Version 4.0
Comparing to
See all releases

Version 4.0

Files changed (7) hide show
  1. changelog.txt +106 -0
  2. readme.txt +228 -0
  3. todo.txt +8 -0
  4. uninstall.php +22 -0
  5. varnish-http-purge.php +464 -0
  6. varnish-status.php +434 -0
  7. wp-cli.php +95 -0
changelog.txt ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = 3.9.3 =
2
+ * Update Documentation and Readme
3
+
4
+ = 3.9.2 =
5
+ * Change purge notice so it can be dismissed.
6
+ * Fix purging of deleted posts.
7
+
8
+ = 3.9.1 =
9
+ * Fixing i18n which wasn't working and threw a stupid error on sites without pretty permalinks. (Props DH customer Rasmus and employee Heckman!)
10
+
11
+ = 3.9 =
12
+ * Retain query params on purge
13
+ * Do not use query part for regex purging [Credit: shaula](https://github.com/Ipstenu/varnish-http-purge/pull/18)
14
+ * Allow Varnish IP to be filtered. [Credit: floatingio](https://wordpress.org/support/topic/supply-varnish-ip-via-filter)
15
+ * Improve flushing for cases when there's no Post ID
16
+ * Add filter so other plugins can add events to trigger purge when they have no post ID
17
+ * Add compatibility with [Autoptimize](https://wordpress.org/plugins/autoptimize/) so it flushes Varnish when you flush their cache
18
+
19
+ = 3.8 =
20
+ * Add varnish_http_purge_events filter to allow people to add their own events for purging. (props @norcross)
21
+ * Add a method to grab the response from purge request and pass to the 'after_purge_url' action for debugging. (props @shaula)
22
+ * Added wp-cli command: wp varnish purge (to purge varnish)
23
+ * Adding some docblocks
24
+ * Fixing i18n
25
+
26
+ = 3.7.3 =
27
+ * Add varnish_http_purge_schema filter for changing the default schema. The default remains http (even if you set your home and/or site URL to https) because of sanity, but in order to support some edge cases, they can filter if they want. (props Drumba)
28
+
29
+ = 3.7.2 =
30
+ * Revisions were being mishandled and purging all inappropriately. (props Cha0sgr)
31
+
32
+ = 3.7.1 =
33
+ * Archives weren't purging. (props Ingraye)
34
+
35
+ = 3.7 =
36
+ * Optimizing flushes.
37
+ * Add filter to allow other people to hook in when 3rd party plugins are abjectly weird (props jnachtigall)
38
+
39
+ = 3.6 =
40
+ * Making purge be http only, since Varnish doesn't support https. This will prevent other issues for people using SSL with Varnish (though goodness knows why...)
41
+ * Forcing backslash on home_url. Why WP doesn't, I have no idea, but this will help sites not running regex.
42
+
43
+ = 3.5.1 =
44
+ * Language fix
45
+ * Using add_query_arg
46
+ * Ignore revisions
47
+
48
+ = 3.5 =
49
+ * Isset wrap for URL path and query which may not be set in rare conditions (props <a href="https://wordpress.org/support/topic/undefined-index-notices-4">hsz</a>)
50
+ * Added in flushing for feeds (requested by <a href="https://wordpress.org/support/topic/feed-not-purged">heypete</a>)
51
+
52
+ = 3.4 =
53
+ * Multisite support
54
+ * Button in toolbar
55
+ * Fix define message in debug mode
56
+ * Better parsing for if you set the define in the DB or config.
57
+
58
+ = 3.3.4 =
59
+ * Rollback. Sorry.
60
+
61
+ = 3.3.3 =
62
+ * Per request of Jetpack team, added in a <code>wp_cache_flush()</code> call when manually purging. This should only impact server side PHP caches (APC, Memcached etc)
63
+
64
+ = 3.3.2 =
65
+ * Varnish IP was too persnickity in PHP 5.4 (added in an 'and if not null' check - props <a href="http://wordpress.org/support/topic/patch-a-little-patch-to-purge-on-comment-posting">colinleroy</a>)
66
+
67
+ = 3.3.1 =
68
+ * Language Pack fixing.
69
+
70
+ = 3.3 =
71
+ * Quick and dirty fix for a plugin that is causing the URLs to purge <em>ALL THE TIME</em>
72
+
73
+ = 3.2 =
74
+ * Correcting conflict with host's default config.
75
+
76
+ = 3.1 =
77
+ * Refactoring Cleanup (otherwise known as Copy/Pasta error in variable name). (props Shredder)
78
+
79
+ = 3.0 =
80
+ * Adds 'Purge Varnish' button
81
+ * More selective purging, to account for different server setups
82
+ * Tighened up what purges and when
83
+ * Flushing categories and tags (per code from WP Super Cache, thanks!)
84
+ * Clarify requirements (Varnish and Pretty Permalinks)
85
+
86
+ = 2.3 =
87
+ * Purge images on deletion
88
+ * Fix for a VarnishIP when behind proxy servers not working on all hosts (props Berler)
89
+
90
+ = 2.2.1 =
91
+ * typo (hit . instead of / - Props John B. Manos)
92
+
93
+ = 2.2 =
94
+ * Added in workaround for Varnish purge reqs going AWOL when another proxy server is in place. (props to Shredder and Berler)
95
+ * Cache flushes when you change themes
96
+
97
+ = 2.1 =
98
+ * Header Image
99
+
100
+ = 2.0 =
101
+ * Commit access handed to Ipstenu
102
+ * Changed CURL to wp_remote_request (thank you <a href="http://wordpress.org/support/topic/incompatability-with-editorial-calendar-plugin?replies=1">Kenn Wilson</a>) so we don't have to do <a href="http://wordpress.org/support/topic/plugin-varnish-http-purge-incompatibility-with-woocommerce?replies=6">CURLOPT_RETURNTRANSFER</a> Remember kids, CURL is okay, but wp_remote_request is more better.
103
+
104
+ = 1.2.0 =
105
+ * Moved actual request execution to "shutdown" event
106
+ * Removed GET request due to bad performance impact
readme.txt ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Varnish HTTP Purge ===
2
+ Contributors: Ipstenu, mikeschroder, techpriester
3
+ Tags: varnish, purge, cache
4
+ Requires at least: 4.0
5
+ Tested up to: 4.7
6
+ Stable tag: 4.0
7
+
8
+ Automatically purge Varnish Cache when content on your site is modified.
9
+
10
+ == Description ==
11
+ Varnish HTTP Purge sends a PURGE request to the URL of a page or post every time it it modified. This occurs when editing, publishing, commenting or deleting an item, and when changing themes.
12
+
13
+ <a href="https://www.varnish-cache.org/">Varnish</a> is a web application accelerator also known as a caching HTTP reverse proxy. You install it in front of any server that speaks HTTP and configure it to cache the contents. This plugin <em>does not</em> install Varnish for you, nor does it configure Varnish for WordPress. It's expected you already did that on your own.
14
+
15
+ Not all pages are purged every time, depending on your Varnish configuration. When a post, page, or custom post type is edited, or a new comment is added, <em>only</em> the following pages will purge:
16
+
17
+ * The front page
18
+ * The post/page edited
19
+ * Any categories or tags associated with the page
20
+
21
+ In addition, your entire cache will be purged on the following actions:
22
+
23
+ * Changing themes
24
+ * Press the 'Purge Varnish Cache' button on the dashboard
25
+ * Press the 'Purge Varnish' button on the toolbar
26
+
27
+ Plugins can hook into the purge actions as well, to filter their own events to trigger a purge.
28
+
29
+ And if you're into WP-CLI, you can use that too: `wp varnish purge`
30
+
31
+ Please note: On a multisite network using subfolders, only <strong>network admins</strong> can purge the main site.
32
+
33
+ == Installation ==
34
+ No WordPress configuration needed.
35
+
36
+ When used on Multisite, the plugin is Network Activatable Only.
37
+
38
+ = Requirements =
39
+ * Pretty Permalinks enabled
40
+ * Varnish 3.x or higher
41
+
42
+ == Frequently Asked Questions ==
43
+
44
+ **Please report all issues in the [support forums](https://wordpress.org/support/plugin/varnish-http-purge)**
45
+
46
+ If you have code patches, [pull requests are welcome](https://github.com/Ipstenu/varnish-http-purge).
47
+
48
+ = How can I tell everything's working? =
49
+
50
+ This can be difficult, since it's a silent plugin. That is you turn it on and walk away. The easiest way to tell would be view a page as a non-logged-in user. I recommend a private browsing window. Then, as a logged in user in another window, edit an existing post (make a small change). Refresh the view in your private window. If the change is there, then everything's working!
51
+
52
+ = Does every WordPress plugin and theme work with Varnish? =
53
+
54
+ No. Some of them have behavior that causes Varnish not to cache. While debugging that is outside the scope of this plugin, there is an "Is Varnish Working?" tool (see WP Admin -> Tools -> Varnish Status) that tries to detect most of the common issues and direct you to resolutions.
55
+
56
+ = How can I debug my site? =
57
+
58
+ From your WordPress Dashboard, go to Tools -> Varnish Status. There a page will auto-scan your main plugin page and report back any issues found. This includes any known problematic plugins.
59
+
60
+ = What version of Varnish is supported? =
61
+
62
+ This was built and tested on Varnish 3.x. While it is reported to work on 2.x and 4.x, it is only supported on v3 at this time.
63
+
64
+ = Why doesn't every page flush when I make a new post? =
65
+
66
+ The only pages that should purge are the post's page, the front page, categories, and tags. The reason why is a little philosophical.
67
+
68
+ When building out this plugin, there were a couple pathways on how best to handle purging caches and they boiled down to two: Decisions (the plugin purges what it purges when it purges) and Options (you decide what to purge, when and why). It's entirely possible to make this plugin purge everything, every time a 'trigger' happens, have it purge some things, or have it be so you can pick that purges.
69
+
70
+ In the interests of design, we decided that the KISS principle was key. Since you can configure your Varnish to always purge all pages recursively (i.e. purging http://example.com/ would purge all pages below it), if that's a requirement, you can set it yourself. There are also other Varnish plugins that allow for more granular control (including W3 Total Cache), however this plugin will not be gaining a whole bunch of options to handle that.
71
+
72
+ = Why doesn't my cache purge when I edit my theme? =
73
+
74
+ Because the plugin only purges your <em>content</em> when you edit it. That means if you edit a page/post, or someone leaves a comment, it'll change. Otherwise, you have to purge the whole cache. The plugin will do this for you if you activate a new theme, but not when you edit your current theme's files.
75
+
76
+ If you use Jetpack's CSS editor, it will purge the whole cache for your site on save.
77
+
78
+ = How do I manually purge the whole cache? =
79
+
80
+ Click the 'Purge Varnish Cache' button on the "Right Now" Dashboard (see the screenshot if you can't find it).
81
+
82
+ There's also a "Purge Varnish" button on the admin toolbar.
83
+
84
+ = I don't see a button! =
85
+
86
+ If you're on a Multisite Network and you're on the primary site in the network, only the <em>network</em> admins can purge that site
87
+
88
+ On a subfolder network if you flush the site at `example.com`, then everything under that (like `example.com/site1` and `example.com/siten` and everything else) would also get flushed. That means that a purge on the main site purges the entire network.
89
+
90
+ In order to mitigate the destructive nature of that power, only the network admins can purge everything on the main site of a subfolder network.
91
+
92
+ = Why is nothing caching when I use PageSpeed? =
93
+
94
+ PageSpeed likes to put in Caching headers to say <em>not</em> to cache. To fix this, you need to put this in your .htaccess section for PageSpeed: `ModPagespeedModifyCachingHeaders off`
95
+
96
+ If you're using nginx, it's `pagespeed ModifyCachingHeaders off;`
97
+
98
+ = Can I use this with a proxy service like CloudFlare? =
99
+
100
+ Yes, but you'll need to make some additional changes (see "Why aren't my changes showing when I use CloudFlare or another proxy?" below).
101
+
102
+ = Why aren't my changes showing when I use CloudFlare or another proxy? =
103
+
104
+ When you use CloudFlare or any other similar service, you've got a proxy in front of the Varnish proxy. In general this isn't a bad thing. The problem arises when the DNS shenanigans send the purge request to your domain name. When you've got an additional proxy like CloudFlare, you don't want the request to go to the proxy, you want it to go to Varnish server.
105
+
106
+ On single-site, you can edit this via the Tools -> Varnish Status page. On Multisite, you'll need to add the following to your wp-config.php file:
107
+
108
+ `define('VHP_VARNISH_IP','123.45.67.89');`
109
+
110
+ Replace "123.45.67.89" with the IP of your <em>Varnish Server</em> (not CloudFlare, Varnish). <em>DO NOT</em> put in http in this define.
111
+
112
+ If you want to use WP-CLI, you can set an option in the database. This will NOT take precedence over the define, it's just there to let hosts who are using something like wp-cli do this for you in an automated fashion:
113
+
114
+ `wp option add vhp_varnish_ip 123.45.67.89`
115
+
116
+ and
117
+
118
+ `wp option update vhp_varnish_ip 123.45.67.890`
119
+
120
+ = How do I find my Varnish IP? =
121
+
122
+ Your Varnish IP must be one of the IPs that Varnish is listening on. If you use multiple IPs, or if you've customized your ACLs, you'll need to pick on that doesn't conflict with your other settings. For example, if you have Varnish listening on a public and private IP, you'll want to pick the private. On the other hand, if you told Varnish to listen on 0.0.0.0 (i.e. "listen on every interface you can") you would need to check what IP you set your purge ACL to allow (commonly 127.0.0.1 aka localhost), and use that (i.e. 127.0.0.1).
123
+
124
+ If your webhost set up Varnish for you, you may need to ask them for the specifics if they don't have it documented. I've listed the ones I know about here, however you should still check with them if you're not sure.
125
+
126
+ <ul>
127
+ <li><strong>DreamHost</strong> - If you're using DreamPress and Cloudflare, go into the Panel and click on the DNS settings for the domain. The entry for <em>resolve-to.domain</em> is your varnish server: `resolve-to.www A 208.97.157.172` -- If you're <em>NOT</em> using Cloudflare, you don't need it, but it's just your normal IP.</li>
128
+ </ul>
129
+
130
+ = What if I have multiple varnish IPs? =
131
+
132
+ Multiple IPs are not supported at this time.
133
+
134
+ I have a major issue with writing code I don't use, which means that since I'm only using one IP right now, I don't want to be on the ball for supporting multiple IPs. I don't even have a place to test it, which is just insane to attempt to code if you think about it. Yes, I could accept pull requests, but that means everyone's at some other person's discretion. So no, I won't be doing that at this time.
135
+
136
+ = Why don't my gzip'd pages flush? =
137
+
138
+ Make sure your Varnish VCL is configured correctly to purge all the right pages. This is normally an issue with Varnish 2, which is not supported by this plugin.
139
+
140
+ = Why isn't the whole cache purge working? =
141
+
142
+ The plugin sends a PURGE command of <code>/.*</code> and `X-Purge-Method` in the header with a value of regex. If your Varnish server doesn't doesn't understand the wildcard, you can configure it to check for the header.
143
+
144
+ = How can I debug? =
145
+
146
+ If `WP_DEBUG` is on and you're not seeing any errors, you'll have to jump into the command line.
147
+
148
+ To see every request made to varnish, use this:
149
+ `varnishncsa -F "%m %U"`
150
+
151
+ If you want to grab the last purge requests, it's this:
152
+ `varnishlog -d -c -m RxRequest:PURGE`
153
+
154
+ And this will show you if the WP button was used:
155
+ `varnishlog -d -c -m RxURL:.*vhp_flush_all.*`
156
+
157
+ In general, I leave the first command up and test the plugin.
158
+
159
+ A full Varnish flush looks like this:
160
+ `PURGE /.*`
161
+
162
+ And a new-post (or edited post) would look like this:
163
+
164
+ <pre>
165
+ PURGE /category/uncategorized/
166
+ PURGE /author/ipstenu/
167
+ PURGE /author/ipstenu/feed/
168
+ PURGE /2015/08/test-post/
169
+ PURGE /feed/rdf/
170
+ PURGE /feed/rss/
171
+ PURGE /feed/
172
+ PURGE /feed/atom/
173
+ PURGE /comments/feed/
174
+ PURGE /2015/08/test-post/feed/
175
+ PURGE /
176
+ </pre>
177
+
178
+ It's just a matter of poking at things from then on.
179
+
180
+ = How do I configure my VCL? =
181
+
182
+ This is a question beyond the support of plugin. I don't offer any Varnish Config help due to resources. I will say this, you absolutely must have PURGE set up in your VCL. This is still supported in Varnish v3, though may not be set up by default. Also, here are some links to other people who use this plugin and have made public their VCLs:
183
+
184
+ * <a href="https://github.com/dreamhost/varnish-vcl-collection">DreamHost's Varnish VCL Collection</a>
185
+
186
+ All of these VCLs work with this plugin.
187
+
188
+ = Can I filter things to add special URLs? =
189
+
190
+ Yes!
191
+
192
+ * `vhp_home_url` - Change the home URL (default is `home_url()`)
193
+ * `vhp_purge_urls` - Add additional URLs to what will be purged
194
+ * `varnish_http_purge_events` - Add a specific event to trigger a page purge
195
+ * `varnish_http_purge_events_full` - Add a specific event to trigger a full site purge
196
+ * `varnish_http_purge_schema` - Allows you to change the schema (default is http)
197
+
198
+ I strongly urge you to use the last one with caution. If you trigger a full site purge too often, you'll obviate the usefulness of caching!
199
+
200
+ = I added in an event to purge on and it's not working =
201
+
202
+ If you're using `varnish_http_purge_events` then you have to make sure your event spits out a post ID.
203
+
204
+ If you don't have a post ID and you still need this, add it to *both* `varnish_http_purge_events_full` and `varnish_http_purge_events` - but please use this with caution, otherwise you'll be purging everything all the time, and you're a terrible person.
205
+
206
+ = Hey, don't you work at DreamHost? Is this Official or DreamHost only? =
207
+
208
+ Yes I do, and yes and no. This plugin is installed by default for _all_ DreamPress installs on DreamHost, and I maintain it for DreamHost, but it was not originally an official DH plugin which means I will continue to support all users to the best of my ability.
209
+
210
+ == Changelog ==
211
+
212
+ = 4.0 =
213
+ * Added Varnish Status Page - Tools -> Varnish Status (includes basic scanning etc)
214
+ * Allow filter for `home_url()`
215
+ * Update readme with list of filters.
216
+ * Added wp-cli commands to flush specific URLs and wildcards
217
+ * Requires wp-cli 0.25+ to work [3315](https://github.com/wp-cli/wp-cli/issues/3315) for WP 4.6+
218
+ * Update `purgePost()` to validate page_for_posts ([Props JeremyClarke](https://github.com/Ipstenu/varnish-http-purge/pull/20))
219
+ * Add check for AMP ([Props JeremyClarke](https://wordpress.org/support/topic/varnish-http-purge-doesnt-update-amp-urls-on-post-update/))
220
+ * Purge 'default' AMP URL as well
221
+ * Cleanup on Uninstall
222
+
223
+ == Screenshots ==
224
+
225
+ 1. Purge button on Right Now (Dashboard Admin)
226
+ 2. Purge button on Toolbar
227
+ 3. Scanner results
228
+ 4. Change Varnish IP address
todo.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ = The future ... =
2
+
3
+ We're going to sit down and look into how the plugin is structured to make it even faster and more organized. Please send coffee. Here's the wish list:
4
+
5
+ * Only purge all automatically once an hour (manual button click will continue to work)
6
+ * Refactor automated purge all to be kinder
7
+ * Reorganize code for sanity
8
+ * Get rid of the need to parse_url()
uninstall.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+
4
+ Copyright 2016 Mika Epstein (email: ipstenu@halfelf.org)
5
+
6
+ This file is part of Varnish HTTP Purge, a plugin for WordPress.
7
+
8
+ Varnish HTTP Purge is free software: you can redistribute it and/or modify
9
+ it under the terms of the Apache License 2.0 license.
10
+
11
+ Varnish HTTP Purge is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
+ */
15
+
16
+ // This is the uninstall script.
17
+
18
+ if( !defined( 'ABSPATH') && !defined('WP_UNINSTALL_PLUGIN') )
19
+ exit();
20
+
21
+ delete_site_option('vhp_varnish_url');
22
+ delete_site_option('vhp_varnish_ip');
varnish-http-purge.php ADDED
@@ -0,0 +1,464 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Varnish HTTP Purge
4
+ Plugin URI: https://halfelf.org/plugins/varnish-http-purge/
5
+ Description: Automatically purge Varnish Cache when content on your site is modified.
6
+ Version: 4.0
7
+ Author: Mika Epstein
8
+ Author URI: https://halfelf.org/
9
+ License: http://www.apache.org/licenses/LICENSE-2.0
10
+ Text Domain: varnish-http-purge
11
+ Network: true
12
+
13
+ Copyright 2013-2016: Mika A. Epstein (email: ipstenu@halfelf.org)
14
+
15
+ Original Author: Leon Weidauer ( http:/www.lnwdr.de/ )
16
+
17
+ This file is part of Varnish HTTP Purge, a plugin for WordPress.
18
+
19
+ Varnish HTTP Purge is free software: you can redistribute it and/or modify
20
+ it under the terms of the Apache License 2.0 license.
21
+
22
+ Varnish HTTP Purge is distributed in the hope that it will be useful,
23
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25
+
26
+ */
27
+
28
+ /**
29
+ * Purge Varnish Class
30
+ *
31
+ * @since 2.0
32
+ */
33
+
34
+ class VarnishPurger {
35
+ protected $purgeUrls = array();
36
+
37
+ /**
38
+ * Init
39
+ *
40
+ * @since 2.0
41
+ * @access public
42
+ */
43
+ public function __construct( ) {
44
+ defined('VHP_VARNISH_IP') || define('VHP_VARNISH_IP', false );
45
+ add_action( 'init', array( &$this, 'init' ) );
46
+ add_action( 'activity_box_end', array( $this, 'varnish_rightnow' ), 100 );
47
+ }
48
+
49
+ /**
50
+ * Plugin Init
51
+ *
52
+ * @since 1.0
53
+ * @access public
54
+ */
55
+ public function init() {
56
+ global $blog_id;
57
+
58
+ // Warning: No Pretty Permalinks!
59
+ if ( '' == get_option( 'permalink_structure' ) && current_user_can('manage_options') ) {
60
+ add_action( 'admin_notices' , array( $this, 'prettyPermalinksMessage'));
61
+ return;
62
+ }
63
+
64
+ // get my events
65
+ $events = $this->getRegisterEvents();
66
+ $noIDevents = $this->getNoIDEvents();
67
+
68
+ // make sure we have events and they're in an array
69
+ if ( !empty( $events ) && !empty( $noIDevents ) ) {
70
+
71
+ // Force it to be an array, in case someone's stupid
72
+ $events = (array) $events;
73
+ $noIDevents = (array) $noIDevents;
74
+
75
+ // Add the action for each event
76
+ foreach ( $events as $event) {
77
+ if ( in_array($event, $noIDevents ) ) {
78
+ // These events have no post ID and, thus, will perform a full purge
79
+ add_action( $event, array($this, 'purgeNoID') );
80
+ } else {
81
+ add_action( $event, array($this, 'purgePost'), 10, 2 );
82
+ }
83
+ }
84
+ }
85
+
86
+ add_action( 'shutdown', array($this, 'executePurge') );
87
+
88
+ // Success: Admin notice when purging
89
+ if ( isset($_GET['vhp_flush_all']) && check_admin_referer('vhp-flush-all') ) {
90
+ add_action( 'admin_notices' , array( $this, 'purgeMessage'));
91
+ }
92
+
93
+ // Checking user permissions for who can and cannot use the admin button
94
+ if (
95
+ // SingleSite - admins can always purge
96
+ ( !is_multisite() && current_user_can('activate_plugins') ) ||
97
+ // Multisite - Network Admin can always purge
98
+ current_user_can('manage_network') ||
99
+ // Multisite - Site admins can purge UNLESS it's a subfolder install and we're on site #1
100
+ ( is_multisite() && !current_user_can('manage_network') && ( SUBDOMAIN_INSTALL || ( !SUBDOMAIN_INSTALL && ( BLOG_ID_CURRENT_SITE != $blog_id ) ) ) )
101
+ ) {
102
+ add_action( 'admin_bar_menu', array( $this, 'varnish_rightnow_adminbar' ), 100 );
103
+ }
104
+
105
+ }
106
+
107
+ /**
108
+ * Purge Message
109
+ * Informs of a succcessful purge
110
+ *
111
+ * @since 2.0
112
+ */
113
+ function purgeMessage() {
114
+ echo "<div id='message' class='notice notice-success fade is-dismissible'><p><strong>".__('Varnish cache purged!', 'varnish-http-purge')."</strong></p></div>";
115
+ }
116
+
117
+ /**
118
+ * Permalinks Message
119
+ * Explains you need Pretty Permalinks on to use this plugin
120
+ *
121
+ * @since 2.0
122
+ */
123
+ function prettyPermalinksMessage() {
124
+ echo "<div id='message' class='error'><p>" . sprintf( __( 'Varnish HTTP Purge requires you to use custom permalinks. Please go to the <a href="%1$s">Permalinks Options Page</a> to configure them.', 'varnish-http-purge' ), admin_url( 'options-permalink.php' ) ) . "</p></div>";
125
+ }
126
+
127
+ /**
128
+ * The Home URL
129
+ * Get the Home URL and allow it to be filterable
130
+ * This is for domain mapping plugins that, for some reason, don't filter
131
+ * on their own (including WPMU, Ron's, and so on).
132
+ *
133
+ * @since 4.0
134
+ */
135
+ static public function the_home_url(){
136
+ $home_url = apply_filters( 'vhp_home_url', home_url() );
137
+ return $home_url;
138
+ }
139
+
140
+ /**
141
+ * Varnish Purge Button in the Admin Bar
142
+ *
143
+ * @since 2.0
144
+ */
145
+ function varnish_rightnow_adminbar($admin_bar){
146
+ $admin_bar->add_menu( array(
147
+ 'id' => 'purge-varnish-cache-all',
148
+ 'title' => __('Purge Varnish','varnish-http-purge'),
149
+ 'href' => wp_nonce_url( add_query_arg('vhp_flush_all', 1), 'vhp-flush-all'),
150
+ 'meta' => array(
151
+ 'title' => __('Purge Varnish','varnish-http-purge'),
152
+ ),
153
+ ));
154
+ }
155
+
156
+ /**
157
+ * Varnish Right Now Information
158
+ * This information is put on the Dashboard 'Right now' widget
159
+ *
160
+ * @since 1.0
161
+ */
162
+ function varnish_rightnow() {
163
+ global $blog_id;
164
+ $url = wp_nonce_url(add_query_arg('vhp_flush_all', 1), 'vhp-flush-all');
165
+ $intro = sprintf( __('<a href="%1$s">Varnish HTTP Purge</a> automatically purges your posts when published or updated. Sometimes you need a manual flush.', 'varnish-http-purge' ), 'http://wordpress.org/plugins/varnish-http-purge/' );
166
+ $button = __('Press the button below to force it to purge your entire cache.', 'varnish-http-purge' );
167
+ $button .= '</p><p><span class="button"><a href="'.$url.'"><strong>';
168
+ $button .= __('Purge Varnish', 'varnish-http-purge' );
169
+ $button .= '</strong></a></span>';
170
+ $nobutton = __('You do not have permission to purge the cache for the whole site. Please contact your administrator.', 'varnish-http-purge' );
171
+
172
+ if (
173
+ // SingleSite - admins can always purge
174
+ ( !is_multisite() && current_user_can('activate_plugins') ) ||
175
+ // Multisite - Network Admin can always purge
176
+ current_user_can('manage_network') ||
177
+ // Multisite - Site admins can purge UNLESS it's a subfolder install and we're on site #1
178
+ ( is_multisite() && !current_user_can('manage_network') && ( SUBDOMAIN_INSTALL || ( !SUBDOMAIN_INSTALL && ( BLOG_ID_CURRENT_SITE != $blog_id ) ) ) )
179
+ ) {
180
+ $text = $intro.' '.$button;
181
+ } else {
182
+ $text = $intro.' '.$nobutton;
183
+ }
184
+ echo "<p class='varnish-rightnow'>$text</p>\n";
185
+ }
186
+
187
+ /**
188
+ * Registered Events
189
+ * These are when the purge is triggered
190
+ *
191
+ * @since 1.0
192
+ * @access protected
193
+ */
194
+ protected function getRegisterEvents() {
195
+
196
+ // Define registered purge events
197
+ $actions = array(
198
+ 'switch_theme', // After a theme is changed
199
+ 'autoptimize_action_cachepurged', // Compat with https://wordpress.org/plugins/autoptimize/
200
+ 'save_post', // Save a post
201
+ 'deleted_post', // Delete a post
202
+ 'trashed_post', // Empty Trashed post
203
+ 'edit_post', // Edit a post - includes leaving comments
204
+ 'delete_attachment', // Delete an attachment - includes re-uploading
205
+ );
206
+
207
+ // send back the actions array, filtered
208
+ // @param array $actions the actions that trigger the purge event
209
+ return apply_filters( 'varnish_http_purge_events', $actions );
210
+ }
211
+
212
+ /**
213
+ * Events that have no post IDs
214
+ * These are when a full purge is triggered
215
+ *
216
+ * @since 3.9
217
+ * @access protected
218
+ */
219
+ protected function getNoIDEvents() {
220
+
221
+ // Define registered purge events
222
+ $actions = array(
223
+ 'switch_theme', // After a theme is changed
224
+ 'autoptimize_action_cachepurged,' // Compat with https://wordpress.org/plugins/autoptimize/
225
+ );
226
+
227
+ // send back the actions array, filtered
228
+ // @param array $actions the actions that trigger the purge event
229
+ // DEVELOPERS! USE THIS SPARINGLY! YOU'RE A GREAT BIG 💩 IF YOU USE IT FLAGRANTLY
230
+ // Remember to add your action to this AND varnish_http_purge_events due to shenanigans
231
+ return apply_filters( 'varnish_http_purge_events_full', $actions );
232
+ }
233
+
234
+ /**
235
+ * Execute Purge
236
+ * Run the purge command for the URLs. Calls $this->purgeUrl for each URL
237
+ *
238
+ * @since 1.0
239
+ * @access protected
240
+ */
241
+ public function executePurge() {
242
+ $purgeUrls = array_unique( $this->purgeUrls );
243
+
244
+ if ( empty($purgeUrls) ) {
245
+ if ( isset($_GET['vhp_flush_all']) && check_admin_referer('vhp-flush-all') ) {
246
+ $this->purgeUrl( $this->the_home_url() .'/?vhp-regex' );
247
+ }
248
+ } else {
249
+ foreach($purgeUrls as $url) {
250
+ $this->purgeUrl($url);
251
+ }
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Purge URL
257
+ * Parse the URL for proxy proxies
258
+ *
259
+ * @since 1.0
260
+ * @param array $url the url to be purged
261
+ * @access protected
262
+ */
263
+ public function purgeUrl($url) {
264
+ $p = parse_url($url);
265
+
266
+ if ( isset($p['query']) && ( $p['query'] == 'vhp-regex' ) ) {
267
+ $pregex = '.*';
268
+ $varnish_x_purgemethod = 'regex';
269
+ } else {
270
+ $pregex = '';
271
+ $varnish_x_purgemethod = 'default';
272
+ }
273
+
274
+ // Build a varniship
275
+ if ( VHP_VARNISH_IP != false ) {
276
+ $varniship = VHP_VARNISH_IP;
277
+ } else {
278
+ $varniship = get_option('vhp_varnish_ip');
279
+ }
280
+ $varniship = apply_filters('vhp_varnish_ip', $varniship);
281
+
282
+ if (isset($p['path'] ) ) {
283
+ $path = $p['path'];
284
+ } else {
285
+ $path = '';
286
+ }
287
+
288
+ /**
289
+ * Schema filter
290
+ *
291
+ * Allows default http:// schema to be changed to https
292
+ * varnish_http_purge_schema()
293
+ *
294
+ * @since 3.7.3
295
+ *
296
+ */
297
+
298
+ $schema = apply_filters( 'varnish_http_purge_schema', 'http://' );
299
+
300
+ // If we made varniship, let it sail
301
+ if ( isset($varniship) && $varniship != null ) {
302
+ $host = $varniship;
303
+ } else {
304
+ $host = $p['host'];
305
+ }
306
+
307
+ $purgeme = $schema.$host.$path.$pregex;
308
+
309
+ if (!empty($p['query']) && $p['query'] != 'vhp-regex') {
310
+ $purgeme .= '?' . $p['query'];
311
+ }
312
+
313
+ // Cleanup CURL functions to be wp_remote_request and thus better
314
+ // http://wordpress.org/support/topic/incompatability-with-editorial-calendar-plugin
315
+ $response = wp_remote_request($purgeme, array('method' => 'PURGE', 'headers' => array( 'host' => $p['host'], 'X-Purge-Method' => $varnish_x_purgemethod ) ) );
316
+
317
+ do_action('after_purge_url', $url, $purgeme, $response);
318
+ }
319
+
320
+ /**
321
+ * Purge - No IDs
322
+ * Flush the whole cache
323
+ *
324
+ * @since 3.9
325
+ * @access private
326
+ */
327
+ public function purgeNoID( $postId ) {
328
+ $listofurls = array();
329
+
330
+ array_push($listofurls, $this->the_home_url().'/?vhp-regex' );
331
+
332
+ // Now flush all the URLs we've collected provided the array isn't empty
333
+ if ( !empty($listofurls) ) {
334
+ foreach ($listofurls as $url) {
335
+ array_push($this->purgeUrls, $url ) ;
336
+ }
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Purge Post
342
+ * Flush the post
343
+ *
344
+ * @since 1.0
345
+ * @param array $postId the ID of the post to be purged
346
+ * @access public
347
+ */
348
+ public function purgePost( $postId ) {
349
+
350
+ // If this is a valid post we want to purge the post,
351
+ // the home page and any associated tags and categories
352
+
353
+ $validPostStatus = array("publish", "trash");
354
+ $thisPostStatus = get_post_status($postId);
355
+
356
+ // array to collect all our URLs
357
+ $listofurls = array();
358
+
359
+ if( get_permalink($postId) == true && in_array($thisPostStatus, $validPostStatus) ) {
360
+ // If this is a post with a permalink AND it's published or trashed,
361
+ // we're going to add a ton of things to flush.
362
+
363
+ // Category purge based on Donnacha's work in WP Super Cache
364
+ $categories = get_the_category($postId);
365
+ if ( $categories ) {
366
+ foreach ($categories as $cat) {
367
+ array_push($listofurls, get_category_link( $cat->term_id ) );
368
+ }
369
+ }
370
+ // Tag purge based on Donnacha's work in WP Super Cache
371
+ $tags = get_the_tags($postId);
372
+ if ( $tags ) {
373
+ foreach ($tags as $tag) {
374
+ array_push($listofurls, get_tag_link( $tag->term_id ) );
375
+ }
376
+ }
377
+
378
+ // Author URL
379
+ array_push($listofurls,
380
+ get_author_posts_url( get_post_field( 'post_author', $postId ) ),
381
+ get_author_feed_link( get_post_field( 'post_author', $postId ) )
382
+ );
383
+
384
+ // Archives and their feeds
385
+ $archiveurls = array();
386
+ if ( get_post_type_archive_link( get_post_type( $postId ) ) == true ) {
387
+ array_push($listofurls,
388
+ get_post_type_archive_link( get_post_type( $postId ) ),
389
+ get_post_type_archive_feed_link( get_post_type( $postId ) )
390
+ );
391
+ }
392
+
393
+ // Post URL
394
+ array_push( $listofurls, get_permalink($postId) );
395
+
396
+ // Also clean URL for trashed post.
397
+ if ( $thisPostStatus == "trash" ) {
398
+ $trashpost = get_permalink($postId);
399
+ $trashpost = str_replace("__trashed", "", $trashpost);
400
+ array_push( $listofurls, $trashpost, $trashpost.'feed/' );
401
+ }
402
+
403
+ // Add in AMP permalink if Automattic's AMP is installed
404
+ if ( function_exists('amp_get_permalink') ) {
405
+ array_push( $listofurls, amp_get_permalink($postId) );
406
+ }
407
+
408
+ // Regular AMP url for posts
409
+ array_push( $listofurls, get_permalink($postId).'amp/' );
410
+
411
+ // Feeds
412
+ array_push($listofurls,
413
+ get_bloginfo_rss('rdf_url') ,
414
+ get_bloginfo_rss('rss_url') ,
415
+ get_bloginfo_rss('rss2_url'),
416
+ get_bloginfo_rss('atom_url'),
417
+ get_bloginfo_rss('comments_rss2_url'),
418
+ get_post_comments_feed_link($postId)
419
+ );
420
+
421
+ // Home Page and (if used) posts page
422
+ array_push( $listofurls, $this->the_home_url().'/' );
423
+ if ( get_option('show_on_front') == 'page' ) {
424
+ // Ensure we have a page_for_posts setting to avoid empty URL
425
+ if ( get_option('page_for_posts') ) {
426
+ array_push( $listofurls, get_permalink( get_option('page_for_posts') ) );
427
+ }
428
+ }
429
+ } else {
430
+ // We're not sure how we got here, but bail instead of processing anything else.
431
+ return;
432
+ }
433
+
434
+ // Now flush all the URLs we've collected provided the array isn't empty
435
+ if ( !empty($listofurls) ) {
436
+ foreach ($listofurls as $url) {
437
+ array_push($this->purgeUrls, $url ) ;
438
+ }
439
+ }
440
+
441
+ // Filter to add or remove urls to the array of purged urls
442
+ // @param array $purgeUrls the urls (paths) to be purged
443
+ // @param int $postId the id of the new/edited post
444
+ $this->purgeUrls = apply_filters( 'vhp_purge_urls', $this->purgeUrls, $postId );
445
+ }
446
+
447
+ }
448
+
449
+ $purger = new VarnishPurger();
450
+
451
+ /**
452
+ * Purge Varnish via WP-CLI
453
+ *
454
+ * @since 3.8
455
+ */
456
+ if ( defined('WP_CLI') && WP_CLI ) {
457
+ include( 'wp-cli.php' );
458
+ }
459
+
460
+ /* Varnish Status Page
461
+ *
462
+ * @since 4.0
463
+ */
464
+ include_once( 'varnish-status.php' );
varnish-status.php ADDED
@@ -0,0 +1,434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ This file is part of Varnish HTTP Purge, a plugin for WordPress.
5
+
6
+ Varnish HTTP Purge is free software: you can redistribute it and/or modify
7
+ it under the terms of the Apache License 2.0 license.
8
+
9
+ Varnish HTTP Purge is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ */
14
+
15
+ if (!defined('ABSPATH')) {
16
+ die();
17
+ }
18
+
19
+ /**
20
+ * Varnish Status Class
21
+ *
22
+ * @since 4.0
23
+ */
24
+
25
+ class VarnishStatus {
26
+
27
+ /**
28
+ * Construct
29
+ * Fires when class is constructed, adds init hook
30
+ *
31
+ * @since 4.0
32
+ */
33
+ function __construct() {
34
+ // Admin Init Hooks
35
+ add_action( 'admin_init', array( &$this, 'admin_init' ) );
36
+ // Admin Menu
37
+ add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
38
+ }
39
+
40
+ /**
41
+ * Admin init Callback
42
+ *
43
+ * @since 4.0
44
+ */
45
+ function admin_init() {
46
+ // Register Settings
47
+ $this->register_settings();
48
+ }
49
+
50
+ /**
51
+ * Admin Menu Callback
52
+ *
53
+ * @since 4.0
54
+ */
55
+ function admin_menu() {
56
+ add_management_page( __('Is Varnish Working?', 'varnish-http-purge'), __('Varnish Status', 'varnish-http-purge'), 'manage_options', 'varnish-status', array( &$this, 'settings_page' ) );
57
+ }
58
+
59
+ /**
60
+ * Register Admin Settings
61
+ *
62
+ * @since 4.0
63
+ */
64
+ function register_settings() {
65
+ register_setting( 'varnish-http-purge', 'vhp_varnish_ip', array( &$this, 'varnish_ip_sanitize' ) );
66
+ register_setting( 'varnish-http-purge', 'vhp_varnish_url', array( &$this, 'varnish_url_sanitize' ) );
67
+
68
+ add_settings_section( 'varnish-url-settings-section', __('Current Varnish Status', 'varnish-http-purge'), array( &$this, 'options_callback_url'), 'varnish-url-settings' );
69
+ add_settings_field( 'varnish_url', __('Check Another URL', 'varnish-http-purge'), array( &$this, 'varnish_url_callback'), 'varnish-url-settings', 'varnish-url-settings-section' );
70
+
71
+ add_settings_section( 'varnish-ip-settings-section', __('Configure Custom Varnish IP', 'varnish-http-purge'), array( &$this, 'options_callback_ip'), 'varnish-ip-settings' );
72
+ add_settings_field( 'varnish_ip', __('Set Varnish IP', 'varnish-http-purge'), array( &$this, 'varnish_ip_callback'), 'varnish-ip-settings', 'varnish-ip-settings-section' );
73
+ }
74
+
75
+ /**
76
+ * Options Callback - IP Address
77
+ *
78
+ * @since 4.0
79
+ */
80
+ function options_callback_ip() {
81
+ ?>
82
+ <p><a name="#configure"></a><?php _e('The majority of users will never need to so much as look down here. However there are cases when a custom Varnish IP Address will need to be set, in order to tell the plugin to flush cache in a specific location. If you\'re using a CDN like Cloudflare or a Firewall Proxy like Sucuri, you will want to set this.', 'varnish-http-purge'); ?></p>
83
+ <p><?php _e('Your Varnish IP is just the IP address of the server where Varnish is installed. Your Varnish IP must be one of the IPs that Varnish is listening on. If you use multiple IPs, or if you\'ve customized your ACLs, you\'ll need to pick one that doesn\'t conflict with your other settings. For example, if you have Varnish listening on a public and private IP, pick the private. On the other hand, if you told Varnish to listen on 0.0.0.0 (i.e. "listen on every interface you can") you would need to check what IP you set your purge ACL to allow (commonly 127.0.0.1 aka localhost), and use that (i.e. 127.0.0.1).', 'varnish-http-purge'); ?></p>
84
+ <p><?php _e('If your webhost set up Varnish for you, you may need to ask them for the specifics if they don\'t have it documented. I\'ve listed the ones I know about here, however you should still check with them if you\'re not sure.', 'varnish-http-purge'); ?></p>
85
+
86
+ <ul>
87
+ <li><?php _e('DreamHost - Go into the Panel and click on the DNS settings for the domain. The entry for <em>resolve-to.domain</em> (if set) will your varnish server. If it\'s not set, then you don\'t need to worry about this at all. Example:', 'varnish-http-purge'); ?> <code>resolve-to.www A 208.97.157.172</code></li>
88
+ </ul>
89
+
90
+ <?php
91
+ }
92
+
93
+ /**
94
+ * Varnish IP Callback
95
+ *
96
+ * @since 4.0
97
+ */
98
+ function varnish_ip_callback() {
99
+
100
+ $disabled = false;
101
+
102
+ if ( VHP_VARNISH_IP != false ) {
103
+ $disabled = true;
104
+ $varniship = VHP_VARNISH_IP;
105
+ } else {
106
+ $varniship = get_option('vhp_varnish_ip');
107
+ }
108
+ ?>
109
+ <input type="text" id="vhp_varnish_ip" name="vhp_varnish_ip" value="<?php echo $varniship; ?>" size="25" <?php if ( $disabled == true ) { echo 'disabled'; } ?>/>
110
+ <label for="vhp_varnish_ip">
111
+ <?php
112
+ if ( $disabled == true ) {
113
+ _e('The Varnish IP has been defined in your wp-config, so it is not editable here.', 'varnish-http-purge');
114
+ } else {
115
+ _e('Example:', 'varnish-http-purge'); ?> <code>123.45.67.89</code><?php
116
+ }
117
+ ?>
118
+ </label>
119
+ <?php
120
+ }
121
+
122
+ /**
123
+ * Options Callback - URL Scanner
124
+ *
125
+ * @since 4.0
126
+ */
127
+ function options_callback_url() {
128
+ $icon_awesome = '<span class="dashicons dashicons-heart" style="color:#008000;"></span>';
129
+ $icon_good = '<span class="dashicons dashicons-thumbs-up" style="color:#008000;"></span>';
130
+ $icon_warning = '<span class="dashicons dashicons-warning" style="color:#FF9933"></span>';
131
+ $icon_awkward = '<span class="dashicons dashicons-flag" style="color:#FF9933;">';
132
+ $icon_bad = '<span class="dashicons dashicons-thumbs-down" style="color:#990000;"></span>';
133
+
134
+ $url = esc_url( VarnishPurger::the_home_url() );
135
+ $varnishurl = get_option( 'vhp_varnish_url', $url );
136
+
137
+ $args = array(
138
+ 'headers' => array(
139
+ 'timeout' => 30,
140
+ 'redirection' => 10,
141
+ )
142
+ );
143
+
144
+ $response = wp_remote_get( $varnishurl, $args );
145
+ $headers = wp_remote_retrieve_headers( $response );
146
+ $preflight = true;
147
+
148
+ // Basic checks that should stop a scan
149
+ if( is_wp_error($response) ) {
150
+ $preflight = false;
151
+ $failure_to_launch = __('This request cannot be performed.', 'varnish-http-purge');
152
+ }
153
+ if( wp_remote_retrieve_response_code($response) == '404' ) {
154
+ $preflight = false;
155
+ $failure_to_launch = __('This URL is a 404. Please check your typing and try again.', 'varnish-http-purge');
156
+ }
157
+ ?>
158
+
159
+ <table class="wp-list-table widefat fixed posts">
160
+ <?php
161
+
162
+ if ( $preflight == false ) {
163
+ ?><tr>
164
+ <td width="40px"><?php echo $icon_bad; ?></td>
165
+ <td><?php echo $failure_to_launch; ?></td>
166
+ </tr><?php
167
+ } else {
168
+ /* Pre Flight Checks */
169
+
170
+ // VARNISH
171
+ if ( isset( $headers['x-cacheable'] ) && strpos( $headers['x-cacheable'] ,'YES') !== false ) {
172
+ ?><tr>
173
+ <td width="40px"><?php echo $icon_good; ?></td>
174
+ <td><?php _e( 'Varnish is running properly and caching is happening.', 'varnish-http-purge' ); ?></td>
175
+ </tr><?php
176
+ } elseif (isset( $headers['x-cacheable'] ) && strpos( $headers['x-cacheable'] ,'NO') !== false ) {
177
+ ?><tr>
178
+ <td width="40px"><?php echo $icon_bad; ?></td>
179
+ <td><?php _e( 'Varnish is running but cannot cache.', 'varnish-http-purge' ); ?></td>
180
+ </tr><?php
181
+ } else {
182
+ ?><tr>
183
+ <td width="40px"><?php echo $icon_warning; ?></td>
184
+ <td><?php _e( 'We did not find Varnish active for this domain.', 'varnish-http-purge' ); ?></td>
185
+ </tr><?php
186
+ }
187
+
188
+ // Cloudflare
189
+ if ( strpos( $headers['Server'] ,'cloudflare') !== false ) {
190
+ ?><tr>
191
+ <td><?php echo $icon_warning; ?></td>
192
+ <td><?php printf( __( 'Because CloudFlare is running, you may experience some cache oddities. Make sure you <a href="%s">configure WordPress for Cloudflare</a>?', 'varnish-http-purge' ), '#configure' ); ?></td>
193
+ </tr><?php
194
+ }
195
+
196
+ // HHVM
197
+ if ( isset( $headers['X-Powered-By'] ) ) {
198
+ if ( strpos( $headers['X-Powered-By'] ,'HHVM') !== false ) {
199
+ ?><tr>
200
+ <td><?php echo $icon_good; ?></td>
201
+ <td><?php _e( 'You are running HHVM instead of PHP. Hip Hop!', 'varnish-http-purge' ); ?></td>
202
+ </tr><?php
203
+ }
204
+ }
205
+
206
+ // GZIP
207
+ if ( isset( $headers['Content-Encoding'] ) ) {
208
+ // Regular gZIP
209
+ if( strpos( $headers['Content-Encoding'] ,'gzip') !== false || ( isset( $headers['Vary']) && strpos( $headers['Vary'] ,'gzip') !== false ) ) {
210
+ ?><tr>
211
+ <td><?php echo $icon_good; ?></td>
212
+ <td><?php _e( 'Your site is compressing content and making the internet faster.', 'varnish-http-purge' ); ?></td>
213
+ </tr><?php
214
+ }
215
+
216
+ // Fastly
217
+ if ( strpos( $headers['Content-Encoding'] ,'Fastly') !== false ) {
218
+ ?><tr>
219
+ <td><?php echo $icon_good; ?></td>
220
+ <td><?php printf( __( '<a href="%s">Fastly</a> is speeding up your site. Keep in mind, it may cache your CSS and images longer than Varnish does. Remember to flush both caches.', 'varnish-http-purge' ), esc_url('https://fastly.com') ); ?></td>
221
+ </tr><?php
222
+ }
223
+ }
224
+
225
+ /* Things that breaks Varnish */
226
+
227
+ // SET COOKIE
228
+ if ( isset( $headers['Set-Cookie'] ) ) {
229
+
230
+ if ( strpos( $headers['Set-Cookie'] , 'PHPSESSID') !== false ) {
231
+ ?><tr>
232
+ <td><?php echo $icon_bad; ?></td>
233
+ <td><?php _e( 'A plugin or theme is setting a PHPSESSID cookie on every pageload. This makes Varnish not deliver cached pages.', 'varnish-http-purge' ); ?></td>
234
+ </tr><?php
235
+ }
236
+ if ( strpos( $headers['Set-Cookie'], 'edd_wp_session' ) !== false ) {
237
+ ?><tr>
238
+ <td><?php echo $icon_bad; ?></td>
239
+ <td><?php printf( __( '<a href="%s">Easy Digital Downloads</a> is being used with cookie sessions. This may cause your cache to misbehave. If you have issues, please set <code>define( "EDD_USE_PHP_SESSIONS", true );</code> in your <code>wp-config.php</code> file.', 'varnish-http-purge' ), esc_url('https://wordpress.org/plugins/easy-digital-downloads/') ); ?></td>
240
+ </tr><?php
241
+ }
242
+ if ( strpos( $headers['Set-Cookie'], 'edd_items_in_cart' ) !== false ) {
243
+ ?><tr>
244
+ <td><?php echo $icon_warning; ?></td>
245
+ <td><?php printf( __( '<a href="%s">Easy Digital Downloads</a> is putting down a shopping cart cookie on every page load. Make sure Varnish is set up to ignore that when it\'s empty.', 'varnish-http-purge' ), esc_url('https://wordpress.org/plugins/easy-digital-downloads/') ); ?></td>
246
+ </tr><?php
247
+ }
248
+ if ( strpos( $headers['Set-Cookie'], 'wfvt_' ) !== false ) {
249
+ ?><tr>
250
+ <td><?php echo $icon_bad; ?></td>
251
+ <td><?php printf( __( '<a href="%s">Wordfence</a> is putting down cookies on every page load. Please disable that in your options (available from version 4.0.4 and up).', 'varnish-http-purge' ), esc_url('https://wordpress.org/plugins/wordfence/') ); ?></td>
252
+ </tr><?php
253
+ }
254
+ if ( strpos( $headers['Set-Cookie'], 'invite-anyone' ) !== false ) {
255
+ ?><tr>
256
+ <td><?php echo $icon_bad; ?></td>
257
+ <td><?php printf( __( '<a href="%s">Invite Anyone</a>, a plugin for BuddyPress, is putting down a cookie on every page load. This will prevent Varnish from caching.', 'varnish-http-purge' ), esc_url('https://wordpress.org/plugins/invite-anyone/') ); ?></td>
258
+ </tr><?php
259
+ }
260
+ }
261
+
262
+ // AGE
263
+ if( !isset($headers['Age']) ) {
264
+ ?><tr>
265
+ <td><?php echo $icon_bad; ?></td>
266
+ <td><?php _e( 'Your domain does not report an "Age" header, which means we can\'t tell if the page is actually serving from cache.', 'varnish-http-purge' ); ?></td>
267
+ </tr><?php
268
+ } elseif( $headers['Age'] <= 0 || $headers['Age'] == 0 ) {
269
+ if( !isset($headers['Cache-Control']) || strpos($headers['Cache-Control'], 'max-age') === FALSE ) {
270
+ ?><tr>
271
+ <td><?php echo $icon_warning; ?></td>
272
+ <td><?php _e( 'The "Age" header is set to less than 1, which means you checked right when Varnish cleared the cache for that url or Varnish is not actually serving the content for that url from cache. Check again (refresh the page) but if it happens again, it could be one of the following reasons:', 'varnish-http-purge' ); ?>
273
+ <ul style=\"text-align: left;\">
274
+ <li><?php _e( 'That url is excluded from the cache on purpose in the Varnish vcl file (in which case everything is working.)', 'varnish-http-purge' ); ?></li>
275
+ <li><?php _e( 'A theme or plugin is sending cache headers that are telling Varnish not to serve that content from cache. This means you will have to fix the cache headers the application is sending to Varnish. A lot of the time those headers are Cache-Control and/or Expires.', 'varnish-http-purge' ); ?></li>
276
+ <li><?php _e( 'A theme or plugin is setting a session cookie, which can prevent Varnish from serving content from cache. You need to make it not send a session cookie for anonymous traffic. ', 'varnish-http-purge' ); ?></li>
277
+ </ul>
278
+ </td>
279
+ </tr><?php
280
+ }
281
+ }
282
+
283
+ // CACHE-CONTROL
284
+ if ( isset( $headers['Cache-Control'] ) && strpos( $headers['Cache-Control'] ,'no-cache') !== false ) {
285
+ ?><tr>
286
+ <td><?php echo $icon_bad; ?></td>
287
+ <td><?php _e( 'Something is setting the header Cache-Control to "no-cache" which means visitors will never get cached pages.', 'varnish-http-purge' ); ?></td>
288
+ </tr><?php
289
+ }
290
+
291
+ // MAX AGE
292
+ if ( isset( $headers['Cache-Control'] ) && strpos( $headers['Cache-Control'] ,'max-age=0') !== false ) {
293
+ ?><tr>
294
+ <td><?php echo $icon_bad; ?></td>
295
+ <td><?php _e( 'Something is setting the header Cache-Control to "max-age=0" which means a page can be no older than 0 seconds before it needs to regenerate the cache.', 'varnish-http-purge' ); ?></td>
296
+ </tr><?php
297
+ }
298
+
299
+ // PRAGMA
300
+ if ( isset( $headers['Pragma'] ) && strpos( $headers['Pragma'] ,'no-cache') !== false ) {
301
+ ?><tr>
302
+ <td><?php echo $icon_bad; ?></td>
303
+ <td><?php _e( 'Something is setting the header Pragma to "no-cache" which means visitors will never get cached pages.', 'varnish-http-purge' ); ?></td>
304
+ </tr><?php
305
+ }
306
+
307
+ // X-CACHE (we're not running this)
308
+ if ( isset( $headers['X-Cache-Status'] ) && strpos( $headers['X-Cache-Status'] ,'MISS') !== false ) {
309
+ ?><tr>
310
+ <td><?php echo $icon_bad; ?></td>
311
+ <td><?php _e( 'X-Cache missed, which means it was not able to serve this page as cached.', 'varnish-http-purge' ); ?></td>
312
+ </tr><?php
313
+ }
314
+
315
+ /* Server features */
316
+
317
+ // PAGESPEED
318
+ if ( isset( $headers['X-Mod-Pagespeed'] ) ) {
319
+ if ( strpos( $headers['X-Cacheable'] , 'YES:Forced') !== false ) {
320
+ ?><tr>
321
+ <td><?php echo $icon_good; ?></td>
322
+ <td><?php _e( 'Mod Pagespeed is active and working properly with Varnish.', 'varnish-http-purge' ); ?></td>
323
+ </tr><?php
324
+ } else {
325
+ ?><tr>
326
+ <td><?php echo $icon_bad; ?></td>
327
+ <td><?php _e( 'Mod Pagespeed is active but it looks like your caching headers may not be right. This may be a false negative if other parts of your site are overwriting headers. Fix all other errors listed, then come back to this. If you are still having errors, you will need to look into using htaccess or nginx to override the Pagespeed headers.', 'varnish-http-purge' ); ?></td>
328
+ </tr><?php
329
+ }
330
+ }
331
+ }
332
+ ?>
333
+ </table>
334
+ <?php
335
+ }
336
+
337
+ /**
338
+ * Varnish URL Callback
339
+ *
340
+ * @since 4.0
341
+ */
342
+ function varnish_url_callback() {
343
+ $url = esc_url( VarnishPurger::the_home_url() );
344
+ $varnishurl = get_option( 'vhp_varnish_url', $url );
345
+ ?>
346
+ <input type="text" id="vhp_varnish_url" name="vhp_varnish_url" value="<?php echo $varnishurl; ?>" size="50" />
347
+ <label for="vhp_varnish_url">
348
+ <?php printf( __( 'Example: <code>%s</code>', 'varnish-http-purge' ), esc_url( VarnishPurger::the_home_url() ) ); ?>
349
+ </label>
350
+ <?php
351
+ }
352
+
353
+ /*
354
+ * Call settings page
355
+ *
356
+ * @since 4.0
357
+ */
358
+ function settings_page() {
359
+ ?>
360
+ <div class="wrap">
361
+
362
+ <h1><?php _e( 'Is Varnish Working?', 'varnish-http-purge' ); ?></h1>
363
+
364
+ <p><?php _e( 'While it would be impossible to detect all possible conflicts, this Status Page will perform a check of the most common issues that prevent Varnish from caching your site properly.', 'varnish-http-purge' ); ?></p>
365
+
366
+ <?php settings_errors(); ?>
367
+
368
+ <form action="options.php" method="POST" ><?php
369
+ settings_fields( 'varnish-http-purge' );
370
+
371
+ do_settings_sections( 'varnish-url-settings' );
372
+ submit_button( 'Check URL', 'primary');
373
+
374
+ // Only available if _not_ multisite
375
+ if ( !is_multisite() ) {
376
+ do_settings_sections( 'varnish-ip-settings' );
377
+ submit_button( 'Save IP', 'primary');
378
+ }
379
+ ?></form>
380
+
381
+ </div>
382
+ <?php
383
+ }
384
+
385
+ /**
386
+ * Sanitization and validation for IP
387
+ *
388
+ * @param $input the input to be sanitized
389
+ * @since 4.0
390
+ */
391
+ function varnish_ip_sanitize( $input ) {
392
+
393
+ if ( filter_var( $input, FILTER_VALIDATE_IP) ) {
394
+ $output = filter_var( $input, FILTER_VALIDATE_IP);
395
+ } else {
396
+ add_settings_error( 'vhp_varnish_ip', 'invalid-ip', 'You have entered an invalid IP address.' );
397
+ }
398
+ return $output;
399
+ }
400
+
401
+ /**
402
+ * Sanitization and validation for URL
403
+ *
404
+ * @param $input the input to be sanitized
405
+ * @since 4.0
406
+ */
407
+ function varnish_url_sanitize( $input ) {
408
+
409
+ $baseurl_host = parse_url( esc_url( VarnishPurger::the_home_url() ), PHP_URL_HOST );
410
+
411
+ if ( filter_var( $input, FILTER_VALIDATE_URL) ) {
412
+ $thisurl = filter_var( $input, FILTER_VALIDATE_URL);
413
+ $set_message = 'Scanned URL '.$thisurl;
414
+ $set_type = 'updated';
415
+ } else {
416
+ $set_message = 'You have entered an invalid URL address.';
417
+ $set_type = 'error';
418
+ }
419
+
420
+ if ( $baseurl_host == parse_url( $thisurl, PHP_URL_HOST ) ) {
421
+ $output = $thisurl;
422
+ } else {
423
+ $output = esc_url( VarnishPurger::the_home_url() );
424
+ $set_message = 'You cannot scan URLs on other domains.';
425
+ $set_type = 'error';
426
+ }
427
+
428
+ add_settings_error( 'vhp_varnish_url', 'varnish-url', $set_message, $set_type );
429
+ return $output;
430
+ }
431
+
432
+ }
433
+
434
+ $status = new VarnishStatus();
wp-cli.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ This file is part of Varnish HTTP Purge, a plugin for WordPress.
5
+
6
+ Varnish HTTP Purge is free software: you can redistribute it and/or modify
7
+ it under the terms of the Apache License 2.0 license.
8
+
9
+ Varnish HTTP Purge is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+
13
+ */
14
+
15
+ if (!defined('ABSPATH')) {
16
+ die();
17
+ }
18
+
19
+ // Bail if WP-CLI is not present
20
+ if ( !defined( 'WP_CLI' ) ) return;
21
+
22
+ /**
23
+ * Purges Varnish Cache
24
+ */
25
+ class WP_CLI_Varnish_Purge_Command extends WP_CLI_Command {
26
+
27
+ private $wildcard = false;
28
+
29
+ public function __construct() {
30
+ $this->varnish_purge = new VarnishPurger();
31
+ }
32
+
33
+ /**
34
+ * Forces a full Varnish Purge of the entire site (provided
35
+ * regex is supported).
36
+ *
37
+ * ## EXAMPLES
38
+ *
39
+ * wp varnish purge
40
+ *
41
+ * wp varnish purge http://example.com/wp-content/themes/twentyeleventy/style.css
42
+ *
43
+ * wp vanrish purge "/wp-content/themes/twentysixty/style.css"
44
+ *
45
+ * wp varnish purge http://example.com/wp-content/themes/ --wildcard
46
+ *
47
+ * wp varnish purge "/wp-content/themes/" --wildcard
48
+ *
49
+ */
50
+
51
+ function purge( $args , $assoc_args ) {
52
+
53
+ $wp_version = get_bloginfo( 'version' );
54
+ $cli_version = WP_CLI_VERSION;
55
+
56
+ // Set the URL/path
57
+ list( $url ) = $args;
58
+
59
+ // If wildcard is set, or the URL argument is empty
60
+ // then treat this as a full purge
61
+ if ( isset( $assoc_args['wildcard'] ) || empty($url) ) {
62
+ $pregex = '/?vhp-regex';
63
+ $wild = ".*";
64
+ } else {
65
+ $pregex = $wild = '';
66
+ }
67
+
68
+ wp_create_nonce('vhp-flush-cli');
69
+
70
+ // Make sure the URL is a URL:
71
+ if ( !empty($url) ) {
72
+ // If the URL isn't a URL, make it a URL
73
+ if ( empty( esc_url( $url ) ) ) {
74
+ $url = $this->varnish_purge->the_home_url() . $url;
75
+ }
76
+ } else {
77
+ $url = $this->varnish_purge->the_home_url();
78
+ }
79
+
80
+ if ( version_compare( $wp_version, '4.6', '>=' ) && ( version_compare( $cli_version, '0.25.0', '<' ) || version_compare( $cli_version, '0.25.0-alpha', 'eq' ) ) ) {
81
+
82
+ WP_CLI::log( sprintf( 'This plugin does not work on WP 4.6 and up, unless WP-CLI is version 0.25.0 or greater. You\'re using WP-CLI %s and WordPress %s.', $cli_version, $wp_version ) );
83
+ WP_CLI::log( 'To flush your cache, please run the following command:');
84
+ WP_CLI::log( sprintf( '$ curl -X PURGE "%s"' , $url.$wild ) );
85
+ WP_CLI::error( 'Varnish Cache must be purged manually.' );
86
+ }
87
+
88
+ $this->varnish_purge->purgeUrl( $url.$pregex );
89
+
90
+ WP_CLI::success( 'The Varnish cache was purged.' );
91
+ }
92
+
93
+ }
94
+
95
+ WP_CLI::add_command( 'varnish', 'WP_CLI_Varnish_Purge_Command' );