PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.1
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.1
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Helpers / AutoloadOptimizer.php

AutoloadOptimizer.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.1, at includes/Helpers/AutoloadOptimizer.php

114 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * One-shot autoload optimiser.
4 *
5 * WordPress loads every wp_option row whose `autoload` column is 'yes'
6 * into memory on EVERY page hit (front + admin). The plugin's settings
7 * options were written via `register_setting()` which defaults to
8 * autoload=yes — so a marketing-site visitor's first request loads
9 * tens of KB of admin-only invoice / dunning / white-label settings,
10 * even though that data is never read on the frontend.
11 *
12 * This helper flips autoload to 'no' on options the plugin owns that
13 * are read only inside admin / cron / addon contexts. The migration is
14 * idempotent (guarded by a version flag) and only runs when an admin
15 * loads a wp-admin page, so frontend visitors never pay the cost.
16 *
17 * Adding a new option to the list:
18 * 1. Make sure the option is genuinely admin-only (no frontend code path
19 * reads it without an `is_admin()` gate).
20 * 2. Bump AUTOLOAD_VERSION below so the migration re-runs once on update.
21 * 3. Append the option name to ADMIN_ONLY_OPTIONS.
22 *
23 * NEVER add options that are read on the frontend (currency code, company
24 * name, public payment instructions, etc.) — flipping those to autoload=no
25 * just moves the cost from autoload to a per-request SELECT, which can be
26 * slower than autoload reads.
27 */
28
29 if (!defined('ABSPATH')) {
30 exit;
31 }
32
33 if (!class_exists('EasyInvoice_AutoloadOptimizer')) {
34
35 class EasyInvoice_AutoloadOptimizer {
36
37 // Bump this when you change ADMIN_ONLY_OPTIONS so existing installs
38 // re-run the migration for the new entries. The version is stored
39 // in the easy_invoice_autoload_version option (which itself is
40 // autoload=no so it doesn't bloat the wp_options autoload set).
41 const AUTOLOAD_VERSION = '1.0';
42
43 // Options the plugin / addons / Pro should NOT autoload.
44 // Comment for each entry explains why it's safe to skip autoload.
45 const ADMIN_ONLY_OPTIONS = [
46 // Addon settings — only read on the addon's own admin page or
47 // during its cron / hook callbacks (which themselves are
48 // hooked in from PHP, not wp_options autoload).
49 'easy_invoice_white_label_settings', // 35+ keys, read in admin + on EI screen filters
50 'easy_invoice_dunning_settings', // steps[] + late-fee + SMS config
51
52 // Schema versions — read exactly once per request from the
53 // addon bootstrap to decide whether to run dbDelta. Doesn't
54 // need to autoload because the addon files are PHP-loaded
55 // first and the option read happens immediately after.
56 'easy_invoice_time_tracking_db_version',
57 'easy_invoice_team_roles_db_version',
58 'easy_invoice_team_roles_caps_version',
59 'easy_invoice_webhooks_db_version',
60
61 // Per-addon enable flags — read once during AddonManager bootstrap.
62 // Six total addons in the registry; one flag per.
63 'easy_invoice_addon_time_tracking_enabled',
64 'easy_invoice_addon_dunning_enabled',
65 'easy_invoice_addon_white_label_enabled',
66 'easy_invoice_addon_team_roles_enabled',
67 'easy_invoice_addon_webhooks_enabled',
68 ];
69
70 /**
71 * Run the migration once per AUTOLOAD_VERSION bump. Hooked to
72 * `admin_init` so the cost only hits the first admin page load
73 * after the upgrade — frontend visitors are unaffected.
74 */
75 public static function maybeMigrate(): void {
76 $current = (string) get_option('easy_invoice_autoload_version', '');
77 if ($current === self::AUTOLOAD_VERSION) {
78 return;
79 }
80 self::migrate();
81 // Store the version itself with autoload=no so this guard row
82 // doesn't add to the wp_options autoload set.
83 update_option('easy_invoice_autoload_version', self::AUTOLOAD_VERSION, false);
84 }
85
86 /**
87 * The actual flip. WordPress 6.4+ has wp_set_option_autoload_values()
88 * which handles the bulk case efficiently; we feature-detect and
89 * fall back to per-option update_option() calls for older WP.
90 */
91 public static function migrate(): void {
92 if (function_exists('wp_set_option_autoload_values')) {
93 // 6.4+: single SQL UPDATE under the hood, no individual writes.
94 $payload = array_fill_keys(self::ADMIN_ONLY_OPTIONS, false);
95 wp_set_option_autoload_values($payload);
96 return;
97 }
98 // Pre-6.4 fallback: update each option in-place with autoload=false.
99 // get_option → update_option with the same value but explicit
100 // autoload=false flips the flag without changing the stored data.
101 foreach (self::ADMIN_ONLY_OPTIONS as $name) {
102 $value = get_option($name, null);
103 if ($value === null) {
104 continue; // option doesn't exist; nothing to migrate
105 }
106 // The 3rd arg = false forces autoload=no on the existing row.
107 update_option($name, $value, false);
108 }
109 }
110 }
111
112 add_action('admin_init', ['EasyInvoice_AutoloadOptimizer', 'maybeMigrate'], 5);
113 }
114