# easy-invoice/2.3.3/includes/Helpers/AutoloadOptimizer.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.3.3. 114 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.3.3/code/includes/Helpers/AutoloadOptimizer.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.3.3/raw/includes/Helpers/AutoloadOptimizer.php
- Modified: 2026-05-21T08:29:24+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.3.3/code/includes/Helpers/AutoloadOptimizer.php#L10-L20`.

```php
<?php
/**
 * One-shot autoload optimiser.
 *
 * WordPress loads every wp_option row whose `autoload` column is 'yes'
 * into memory on EVERY page hit (front + admin). The plugin's settings
 * options were written via `register_setting()` which defaults to
 * autoload=yes — so a marketing-site visitor's first request loads
 * tens of KB of admin-only invoice / dunning / white-label settings,
 * even though that data is never read on the frontend.
 *
 * This helper flips autoload to 'no' on options the plugin owns that
 * are read only inside admin / cron / addon contexts. The migration is
 * idempotent (guarded by a version flag) and only runs when an admin
 * loads a wp-admin page, so frontend visitors never pay the cost.
 *
 * Adding a new option to the list:
 *   1. Make sure the option is genuinely admin-only (no frontend code path
 *      reads it without an `is_admin()` gate).
 *   2. Bump AUTOLOAD_VERSION below so the migration re-runs once on update.
 *   3. Append the option name to ADMIN_ONLY_OPTIONS.
 *
 * NEVER add options that are read on the frontend (currency code, company
 * name, public payment instructions, etc.) — flipping those to autoload=no
 * just moves the cost from autoload to a per-request SELECT, which can be
 * slower than autoload reads.
 */

if (!defined('ABSPATH')) {
    exit;
}

if (!class_exists('EasyInvoice_AutoloadOptimizer')) {

    class EasyInvoice_AutoloadOptimizer {

        // Bump this when you change ADMIN_ONLY_OPTIONS so existing installs
        // re-run the migration for the new entries. The version is stored
        // in the easy_invoice_autoload_version option (which itself is
        // autoload=no so it doesn't bloat the wp_options autoload set).
        const AUTOLOAD_VERSION = '1.0';

        // Options the plugin / addons / Pro should NOT autoload.
        // Comment for each entry explains why it's safe to skip autoload.
        const ADMIN_ONLY_OPTIONS = [
            // Addon settings — only read on the addon's own admin page or
            // during its cron / hook callbacks (which themselves are
            // hooked in from PHP, not wp_options autoload).
            'easy_invoice_white_label_settings',  // 35+ keys, read in admin + on EI screen filters
            'easy_invoice_dunning_settings',      // steps[] + late-fee + SMS config

            // Schema versions — read exactly once per request from the
            // addon bootstrap to decide whether to run dbDelta. Doesn't
            // need to autoload because the addon files are PHP-loaded
            // first and the option read happens immediately after.
            'easy_invoice_time_tracking_db_version',
            'easy_invoice_team_roles_db_version',
            'easy_invoice_team_roles_caps_version',
            'easy_invoice_webhooks_db_version',

            // Per-addon enable flags — read once during AddonManager bootstrap.
            // Six total addons in the registry; one flag per.
            'easy_invoice_addon_time_tracking_enabled',
            'easy_invoice_addon_dunning_enabled',
            'easy_invoice_addon_white_label_enabled',
            'easy_invoice_addon_team_roles_enabled',
            'easy_invoice_addon_webhooks_enabled',
        ];

        /**
         * Run the migration once per AUTOLOAD_VERSION bump. Hooked to
         * `admin_init` so the cost only hits the first admin page load
         * after the upgrade — frontend visitors are unaffected.
         */
        public static function maybeMigrate(): void {
            $current = (string) get_option('easy_invoice_autoload_version', '');
            if ($current === self::AUTOLOAD_VERSION) {
                return;
            }
            self::migrate();
            // Store the version itself with autoload=no so this guard row
            // doesn't add to the wp_options autoload set.
            update_option('easy_invoice_autoload_version', self::AUTOLOAD_VERSION, false);
        }

        /**
         * The actual flip. WordPress 6.4+ has wp_set_option_autoload_values()
         * which handles the bulk case efficiently; we feature-detect and
         * fall back to per-option update_option() calls for older WP.
         */
        public static function migrate(): void {
            if (function_exists('wp_set_option_autoload_values')) {
                // 6.4+: single SQL UPDATE under the hood, no individual writes.
                $payload = array_fill_keys(self::ADMIN_ONLY_OPTIONS, false);
                wp_set_option_autoload_values($payload);
                return;
            }
            // Pre-6.4 fallback: update each option in-place with autoload=false.
            // get_option → update_option with the same value but explicit
            // autoload=false flips the flag without changing the stored data.
            foreach (self::ADMIN_ONLY_OPTIONS as $name) {
                $value = get_option($name, null);
                if ($value === null) {
                    continue; // option doesn't exist; nothing to migrate
                }
                // The 3rd arg = false forces autoload=no on the existing row.
                update_option($name, $value, false);
            }
        }
    }

    add_action('admin_init', ['EasyInvoice_AutoloadOptimizer', 'maybeMigrate'], 5);
}

```
