# easy-invoice/2.3.7/includes/Controllers/AddonsController.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.3.7. 188 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.3.7/code/includes/Controllers/AddonsController.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.3.7/raw/includes/Controllers/AddonsController.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.7/code/includes/Controllers/AddonsController.php#L10-L20`.

```php
<?php
/**
 * Addons admin page controller + AJAX toggle endpoint.
 *
 * @package EasyInvoice
 */

namespace EasyInvoice\Controllers;

use EasyInvoice\Addons\AddonManager;
use EasyInvoice\Addons\AddonRegistry;
use EasyInvoice\Addons\LicensePlanResolver;

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

class AddonsController {

    public const PAGE_SLUG = 'easy-invoice-addons';
    public const NONCE     = 'easy_invoice_addons_nonce';

    public function init(): void {
        add_action('wp_ajax_easy_invoice_toggle_addon', [$this, 'ajaxToggleAddon']);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
    }

    /**
     * Page renderer (called by EasyInvoiceAdmin::mainPageContent).
     */
    public function display(): void {
        if (!current_user_can('manage_options')) {
            wp_die(__('Sorry, you are not allowed to access this page.', 'easy-invoice'));
        }

        $addons        = AddonRegistry::all();
        $current_plan  = LicensePlanResolver::getCurrentPlan();
        $upgrade_urls  = [
            LicensePlanResolver::PLAN_PROFESSIONAL => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
            LicensePlanResolver::PLAN_AGENCY       => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
        ];

        // License banner state — surfaced below the page header instead of via
        // wp-admin's global admin_notices (which would appear ABOVE the header).
        $license_banner = $this->resolveLicenseBanner($current_plan);

        include EASY_INVOICE_PLUGIN_DIR . 'templates/admin/addons-page.php';
    }

    /**
     * Decide whether to show a contextual license banner inside the addons page.
     *
     * @return array{type:string,title:string,message:string,cta_label:string,cta_url:string}|null
     */
    private function resolveLicenseBanner(string $current_plan): ?array {
        // No Pro plugin installed → encourage upgrade to unlock any addon.
        if (!function_exists('easy_invoice_has_pro') || !easy_invoice_has_pro()) {
            return [
                'type'      => 'info',
                'title'     => __('You\'re on the Free version.', 'easy-invoice'),
                'message'   => __('These addons require Easy Invoice Pro. Install Pro to unlock Personal-tier addons — recurring invoices, client portal, reports, item library, partial payments, and more — included at no extra cost. Activate a license key to enable Professional and Agency tiers.', 'easy-invoice'),
                'cta_label' => __('Get Easy Invoice Pro', 'easy-invoice'),
                'cta_url'   => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
            ];
        }

        // Pro plugin is installed. Personal is granted without a license
        // (entry-level tier). A license unlocks Professional / Agency.
        $has_valid = class_exists('\\EasyInvoicePro\\Updater\\License')
            && \EasyInvoicePro\Updater\License::has_valid_license();

        if (!$has_valid) {
            // Pro installed but no license — Personal-tier addons are
            // already usable. Surface an "Activate License" CTA so the
            // merchant knows higher tiers exist.
            return [
                'type'      => 'info',
                'title'     => __('You\'re on the Personal plan.', 'easy-invoice'),
                'message'   => __('All Personal-tier addons are unlocked. Activate your Easy Invoice Pro license to enable Professional and Agency addons.', 'easy-invoice'),
                'cta_label' => __('Activate License', 'easy-invoice'),
                'cta_url'   => admin_url('admin.php?page=easy-invoice-license'),
            ];
        }

        // License is valid but a lower tier than the addons that exist — soft suggestion.
        if ($current_plan === LicensePlanResolver::PLAN_PROFESSIONAL) {
            return [
                'type'      => 'info',
                'title'     => __('You\'re on the Professional plan.', 'easy-invoice'),
                'message'   => __('Upgrade to Agency to unlock Agency-tier addons like White-Label.', 'easy-invoice'),
                'cta_label' => __('See Agency plan', 'easy-invoice'),
                'cta_url'   => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
            ];
        }

        return null; // All good — no banner.
    }

    /**
     * AJAX: toggle a single addon on/off.
     *
     * Expects POST: addon_id (string), enabled (0|1), _nonce.
     */
    public function ajaxToggleAddon(): void {
        check_ajax_referer(self::NONCE, '_nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'code'    => 'forbidden',
                'message' => __('Permission denied.', 'easy-invoice'),
            ], 403);
        }

        $addon_id = isset($_POST['addon_id']) ? sanitize_key($_POST['addon_id']) : '';
        $enabled  = !empty($_POST['enabled']);

        if ($addon_id === '') {
            wp_send_json_error([
                'code'    => 'missing_addon_id',
                'message' => __('Addon ID is required.', 'easy-invoice'),
            ], 400);
        }

        $result = $enabled
            ? AddonManager::enable($addon_id)
            : AddonManager::disable($addon_id);

        if (!$result['success']) {
            $payload = [
                'code'    => $result['code'],
                'message' => $result['message'],
            ];
            if (!empty($result['required_plan'])) {
                $payload['required_plan']       = $result['required_plan'];
                $payload['required_plan_label'] = LicensePlanResolver::getPlanLabel($result['required_plan']);
                $payload['upgrade_url']         = $this->upgradeUrlFor($result['required_plan']);
            }
            wp_send_json_error($payload, 200); // 200 — payload tells client what to do
        }

        wp_send_json_success([
            'code'    => $result['code'],
            'message' => $result['message'],
            'status'  => AddonManager::statusFor($addon_id),
        ]);
    }

    private function upgradeUrlFor(string $plan): string {
        $base = 'https://matrixaddons.com/plugins/easy-invoice/#pricing';
        return add_query_arg([
            'plan'     => $plan,
            'discount' => 'EIEARLYBIRD',
            'utm_source'   => 'easy-invoice-plugin',
            'utm_medium'   => 'addons-page',
            'utm_campaign' => 'addon-upgrade',
        ], $base);
    }

    public function enqueueAssets(string $hook): void {
        $current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
        if ($current_page !== self::PAGE_SLUG) {
            return;
        }

        // Page chrome (sidebar, layout) comes from Easy Invoice's existing Tailwind UI;
        // we only need the toggle/upgrade JS for this page.
        wp_enqueue_script(
            'easy-invoice-addons-page',
            EASY_INVOICE_PLUGIN_URL . 'assets/js/addons-page.js',
            ['jquery'],
            EASY_INVOICE_VERSION,
            true
        );

        wp_localize_script('easy-invoice-addons-page', 'EasyInvoiceAddons', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce'   => wp_create_nonce(self::NONCE),
            'strings' => [
                'enabling'      => __('Enabling…', 'easy-invoice'),
                'disabling'     => __('Disabling…', 'easy-invoice'),
                'enableError'   => __('Could not enable this addon.', 'easy-invoice'),
                'disableError'  => __('Could not disable this addon.', 'easy-invoice'),
                'genericError'  => __('Something went wrong. Please try again.', 'easy-invoice'),
            ],
        ]);
    }
}

```
