Repository navigation
Expand file tree
/
Copy pathindex.php
More file actions
130 lines (116 loc) · 5.86 KB
/
Copy pathindex.php
File metadata and controls
130 lines (116 loc) · 5.86 KB
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
<?php
/*
Plugin Name: nginx Cache
Plugin URI: https://github.com/mindstellar/shopclass-plugin-nginx-cache
Description: Hold pages in nginx's FastCGI cache for an hour instead of thirty seconds, and purge them the moment a listing changes — including after a storage offload rewrites its image URLs.
Version: 0.5.2
Author: Navjot Tomer (Mindstellar)
Author URI: https://mindstellar.com
Short Name: nginx-cache
Requires Shopclass: 6.2.0
Tested up to: 6.4
Requires PHP: 8.0
Support URI: https://github.com/mindstellar/shopclass-plugin-nginx-cache/issues
*/
/*
* This file is part of the nginx Cache plugin for Shopclass.
* Copyright (c) 2021-2026 Navjot Tomer (Mindstellar) and contributors
*
* Distributed under the GNU General Public License v3.0 or later.
* See LICENSE (GPL-3.0).
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
use mindstellar\nginxcache\Plugin;
use mindstellar\nginxcache\Purge;
use mindstellar\nginxcache\Queue;
use mindstellar\nginxcache\Ttl;
if (!defined('ABS_PATH')) {
exit('Direct access is not allowed.');
}
require_once __DIR__ . '/src/Plugin.php';
require_once __DIR__ . '/src/Ttl.php';
require_once __DIR__ . '/src/Purge.php';
require_once __DIR__ . '/src/Client.php';
require_once __DIR__ . '/src/Queue.php';
require_once __DIR__ . '/src/Setup.php';
osc_register_plugin(osc_plugin_path(__FILE__), array(Plugin::class, 'install'));
osc_add_hook(osc_plugin_path(__FILE__) . '_uninstall', array(Plugin::class, 'uninstall'));
osc_add_hook(osc_plugin_path(__FILE__) . '_configure', 'nginx_cache_configure');
// ── Admin ────────────────────────────────────────────────────────────────────
osc_add_route(
'nginx-cache-settings',
'nginx-cache/settings',
'nginx-cache/settings',
osc_plugin_folder(__FILE__) . 'admin/settings.php'
);
osc_add_route(
'nginx-cache-help',
'nginx-cache/help',
'nginx-cache/help',
osc_plugin_folder(__FILE__) . 'admin/help.php'
);
function nginx_cache_admin_menu()
{
osc_admin_menu_plugins(__('nginx Cache', 'nginx-cache'), osc_route_admin_url('nginx-cache-settings'), 'nginx-cache-menu');
osc_admin_menu_plugins(__('nginx Cache: Setup', 'nginx-cache'), osc_route_admin_url('nginx-cache-help'), 'nginx-cache-help-menu');
}
function nginx_cache_configure()
{
osc_redirect_to(osc_route_admin_url('nginx-cache-settings'));
}
osc_add_hook('admin_menu_init', 'nginx_cache_admin_menu');
osc_add_hook('init_admin', array(Plugin::class, 'handleAdminPost'));
// ── How long a page may be held ──────────────────────────────────────────────
// The only thing that lengthens the window. Deliberately gated: Ttl returns core's
// own default until the purge self-test has passed, so an install that is
// misconfigured behaves exactly as it does today rather than a great deal worse.
osc_add_filter('public_cache_max_age', array(Ttl::class, 'forCurrentPage'));
// ── What makes a page stale ──────────────────────────────────────────────────
// The same hook set the Cloudflare plugin uses, which is the tested list of every
// event core actually fires, plus invalidate_item_cache -- the one that carries a
// completed storage offload. Nothing else announces that, and an offload rewrites
// a listing's image URLs, so without it a cached page keeps pointing at local
// files that have been moved to the remote.
osc_add_hook('posted_item', array(Purge::class, 'onItemArray'));
osc_add_hook('edited_item', array(Purge::class, 'onItemArray'));
osc_add_hook('after_delete_item', array(Purge::class, 'onItemDeleted'));
osc_add_hook('invalidate_item_cache', array(Purge::class, 'onItemId'));
foreach (array(
'enable_item',
'disable_item',
'activate_item',
'deactivate_item',
'item_premium_on',
'item_premium_off',
'item_expiration_updated',
) as $nginx_cache_hook) {
osc_add_hook($nginx_cache_hook, array(Purge::class, 'onItemId'));
}
unset($nginx_cache_hook);
osc_add_hook('add_category', array(Purge::class, 'onCategory'));
osc_add_hook('after_delete_category', array(Purge::class, 'onCategory'));
osc_add_hook('edit_page', array(Purge::class, 'onPage'));
osc_add_hook('after_delete_page', array(Purge::class, 'onPage'));
// ── Site-wide changes ────────────────────────────────────────────────────────
// Core 6.4.2+ fires page_cache_purge once per request; older cores get the shim hooks.
foreach (Purge::purgeAllHooks(function_exists('osc_purge_page_cache')) as $nginx_cache_hook => $nginx_cache_cb) {
osc_add_hook($nginx_cache_hook, $nginx_cache_cb);
}
unset($nginx_cache_hook, $nginx_cache_cb);
// A PURGE that reaches PHP was not handled by nginx. Answer 405 so the sender falls back.
if (Purge::isStrayPurge((string) ($_SERVER['REQUEST_METHOD'] ?? ''))) {
http_response_code(405);
header('Allow: GET, HEAD, POST');
exit;
}
// One request may fire several of the hooks above for the same listing. Collect the
// URLs, de-duplicate, and send once the response is out of the way. This is a filter,
// not a hook -- core builds the shutdown list with applyFilter (see Csrf::init), and
// registering it the other way silently never runs.
osc_add_filter('shutdown_functions', array(Purge::class, 'registerFlush'));
// Fallback only -- purging itself is immediate, in the request that changed the
// content. This just picks up whatever the origin refused or was not reachable for.
// The generic `cron` hook, not `cron_hourly`: a retry has to come round more often
// than the window it protects, and the default window is an hour.
osc_add_hook('cron', array(Queue::class, 'retry'));