# easy-invoice/2.3.1/includes/Admin/EasyInvoiceAdmin.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.3.1. 712 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.3.1/code/includes/Admin/EasyInvoiceAdmin.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.3.1/raw/includes/Admin/EasyInvoiceAdmin.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.1/code/includes/Admin/EasyInvoiceAdmin.php#L10-L20`.

```php
<?php
/**
 * EasyInvoice Admin Class
 *
 * @package Easy_Invoice
 * @subpackage Admin
 */

namespace EasyInvoice\Admin;

use EasyInvoice\Admin\AdminAssets;
use EasyInvoice\Constants\PagesSlugs;
use EasyInvoice\Controllers\InvoiceController;
use EasyInvoice\Controllers\QuoteController;
use EasyInvoice\Controllers\ClientController;
use EasyInvoice\Controllers\SettingsController;
use EasyInvoice\Controllers\ReportController;
use EasyInvoice\Controllers\DashboardController;
use EasyInvoice\Controllers\PaymentController;

/**
 * EasyInvoiceAdmin is the main admin class that initializes all controllers
 */
class EasyInvoiceAdmin {
    /**
     * Invoice controller instance
     *
     * @var InvoiceController
     */
    private $invoice_controller;

    /**
     * Quote controller instance
     *
     * @var QuoteController
     */
    private $quote_controller;

    /**
     * Client controller instance
     *
     * @var ClientController
     */
    private $client_controller;

    /**
     * Settings controller instance
     *
     * @var SettingsController
     */
    private $settings_controller;

    /**
     * Report controller instance
     *
     * @var ReportController
     */
    private $report_controller;

    /**
     * Dashboard controller instance
     *
     * @var DashboardController
     */
    private $dashboard_controller;

    /**
     * Payment controller instance
     *
     * @var PaymentController
     */
    private $payment_controller;

    /**
     * Template Builder controller instance
     *
     * @var \EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController
     */
    private $template_builder_controller;

    /**
     * Constructor
     */
    public function __construct() {
        $this->invoice_controller = new InvoiceController();
        $this->quote_controller = new QuoteController();
        $this->client_controller = new ClientController();
        $this->settings_controller = new SettingsController();
        $this->report_controller = new ReportController();
        $this->dashboard_controller = new DashboardController();
        $this->payment_controller = new PaymentController();
        
        // Initialize Template Builder controller if Pro is active AND
        // the custom_templates addon is enabled. The addon owns this
        // feature — see addons/CustomTemplates/addon.php in the Pro
        // plugin. Constructing the controller here always-on would
        // register its admin_menu hook regardless of addon state.
        if (
            easy_invoice_has_pro()
            && \EasyInvoice\Addons\AddonManager::shouldLoad('custom_templates')
            && class_exists('\EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController')
        ) {
            $this->template_builder_controller = new \EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController();
        }
    }

    /**
     * Initialize the admin class
     */
    public function init() {
        // Add menu items
        add_action('admin_menu', array($this, 'registerMenuPages'));

        // Register admin assets
        $admin_assets = new AdminAssets();
        $admin_assets->register();

        // Register invoice preview page
        add_action('admin_init', array($this, 'registerPreviewPage'));

        // Ensure proper page titles to avoid WordPress core issues
        add_filter('admin_title', array($this, 'setAdminTitle'));

        // Hide admin UI
        add_action('admin_head', array($this, 'hideAdminUi'));

        // Body class for layout fixes (admin bar offset, header strip alignment)
        add_filter('admin_body_class', array($this, 'adminBodyClass'));

        // Initialize controllers
        $this->invoice_controller->init();
        $this->quote_controller->init();
        $this->client_controller->init();
        $this->settings_controller->init();
        $this->report_controller->init();
        $this->dashboard_controller->init();
        $this->payment_controller->init();

        // Main content hook
        add_action('easy_invoice_admin_main_content', array($this, 'mainPageContent'));
    }

    /**
     * Register admin menu pages
     */
    public function registerMenuPages() {
        // Main menu item
        add_menu_page(
            __('Easy Invoice', 'easy-invoice'),
            __('Easy Invoice', 'easy-invoice'),
            'manage_options',
            PagesSlugs::DASHBOARD,
            array($this, 'displayMainPage'),
            'dashicons-media-text',
            25
        );

        // Dashboard submenu
        add_submenu_page(
            'easy-invoice',
            __('Dashboard', 'easy-invoice'),
            __('Dashboard', 'easy-invoice'),
            'manage_options',
            PagesSlugs::DASHBOARD,
            array($this, 'displayMainPage')
        );

        // All invoices submenu
        add_submenu_page(
            'easy-invoice',
            __('All Invoices', 'easy-invoice'),
            __('All Invoices', 'easy-invoice'),
            'manage_options',
            PagesSlugs::ALL_INVOICES,
            array($this, 'displayMainPage')
        );

        // Add new invoice submenu
        add_submenu_page(
			'easy-invoice-hidden',
            __('Add New Invoice', 'easy-invoice'),
            __('Add New', 'easy-invoice'),
            'manage_options',
            PagesSlugs::INVOICE_NEW,
            array($this, 'displayMainPage')
        );

        // All quotes submenu
        add_submenu_page(
            'easy-invoice',
            __('All Quotes', 'easy-invoice'),
            __('All Quotes', 'easy-invoice'),
            'manage_options',
            PagesSlugs::ALL_QUOTES,
            array($this, 'displayMainPage')
        );

        // Add new quote submenu
        add_submenu_page(
            'easy-invoice-hidden',
            __('Add New Quote', 'easy-invoice'),
            __('Add New Quote', 'easy-invoice'),
            'manage_options',
            PagesSlugs::QUOTE_NEW,
            array($this, 'displayMainPage')
        );

        // Payments submenu
        add_submenu_page(
            'easy-invoice-hidden',
            __('Payments', 'easy-invoice'),
            __('Payments', 'easy-invoice'),
            'manage_options',
            PagesSlugs::PAYMENTS,
            array($this, 'displayMainPage')
        );

        // Add new payment submenu
        add_submenu_page(
            'easy-invoice-hidden',
            __('Add New Payment', 'easy-invoice'),
            __('Add New Payment', 'easy-invoice'),
            'manage_options',
            PagesSlugs::PAYMENT_NEW,
            array($this, 'displayMainPage')
        );

        // Clients submenu
        add_submenu_page(
            'easy-invoice',
            __('All Clients', 'easy-invoice'),
            __('All Clients', 'easy-invoice'),
            'edit_posts',
            PagesSlugs::CLIENTS,
            array($this, 'displayMainPage')
        );

        // Item Library + Template Builder pages are reached via the
        // Easy Invoice in-app sidebar (templates/main-template.php), NOT
        // the WP admin submenu. We still register the page slugs so the
        // URLs resolve, but we parent them under 'easy-invoice-hidden'
        // so they don't render duplicate entries in the WP submenu —
        // the WP submenu showed the link AND the in-app sidebar showed
        // the same link, giving the user two visible navigation
        // entry-points to the same page.
        //
        // Registration is still gated on the addon being active — if
        // the addon is off, the slug isn't registered, so direct-URL
        // access returns the standard "you do not have sufficient
        // permissions" page.
        if (easy_invoice_has_pro() && \EasyInvoice\Addons\AddonManager::shouldLoad('item_library')) {
            add_submenu_page(
                'easy-invoice-hidden',
                __('Item Library', 'easy-invoice'),
                __('Item Library', 'easy-invoice'),
                'manage_options',
                'easy-invoice-pro-item-library',
                array($this, 'displayMainPage')
            );
        }

        if (easy_invoice_has_pro() && \EasyInvoice\Addons\AddonManager::shouldLoad('custom_templates')) {
            // Template listing — reachable from the in-app sidebar.
            add_submenu_page(
                'easy-invoice-hidden',
                __('Template Builder', 'easy-invoice'),
                __('Template Builder', 'easy-invoice'),
                'manage_options',
                'easy-invoice-templates',
                array($this, 'displayMainPage')
            );

            // Create New Template — used by deep-links from inside the
            // builder UI.
            add_submenu_page(
                'easy-invoice-hidden',
                __('Create New Template', 'easy-invoice'),
                __('Create New', 'easy-invoice'),
                'manage_options',
                'easy-invoice-templates-new',
                array($this, 'displayMainPage')
            );

            // Template Builder canvas — full-screen builder, reached
            // from the listing page's Edit / New buttons.
            add_submenu_page(
                'easy-invoice-hidden',
                __('Template Builder Page', 'easy-invoice'),
                __('Template Builder Page', 'easy-invoice'),
                'manage_options',
                'easy-invoice-template-builder',
                array($this, 'displayMainPage')
            );
        }

        // Hidden submenu pages - not shown in the menu but accessible
        add_submenu_page(
            'easy-invoice-hidden', // Use main menu as parent to avoid title issues
            __('Edit Client', 'easy-invoice'),
            __('Edit Client', 'easy-invoice'),
            'manage_options',
            PagesSlugs::CLIENT_EDIT,
            array($this, 'displayMainPage')
        );

        add_submenu_page(
            'easy-invoice-hidden', // Use main menu as parent to avoid title issues
            __('View Client', 'easy-invoice'),
            __('View Client', 'easy-invoice'),
            'manage_options',
            PagesSlugs::CLIENT_VIEW,
            array($this, 'displayMainPage')
        );

        add_submenu_page(
            'easy-invoice-hidden', // Use main menu as parent to avoid title issues
            __('Preview Invoice', 'easy-invoice'),
            __('Preview Invoice', 'easy-invoice'),
            'manage_options',
            PagesSlugs::INVOICE_PREVIEW,
            array($this, 'displayPreviewPage')
        );

        add_submenu_page(
            'easy-invoice-hidden', // Use main menu as parent to avoid title issues
            __('Preview Quote', 'easy-invoice'),
            __('Preview Quote', 'easy-invoice'),
            'manage_options',
            PagesSlugs::QUOTE_PREVIEW,
            array($this, 'displayMainPage')
        );

        // Reports — addon-gated (Personal tier). Slug registered as a
        // HIDDEN submenu so the WP admin sidebar doesn't double the
        // in-app sidebar entry. When the reports addon is disabled, the
        // slug isn't registered at all, so direct-URL access falls
        // through to WP's "no permission" page.
        if (\EasyInvoice\Addons\AddonManager::shouldLoad('reports')) {
            add_submenu_page(
                'easy-invoice-hidden',
                __('Reports', 'easy-invoice'),
                __('Reports', 'easy-invoice'),
                'manage_options',
                PagesSlugs::REPORTS,
                array($this, 'displayMainPage')
            );
        }

        // Settings submenu
        add_submenu_page(
            'easy-invoice',
            __('Settings', 'easy-invoice'),
            __('Settings', 'easy-invoice'),
            'manage_options',
            PagesSlugs::SETTINGS,
            array($this, 'displayMainPage')
        );

        // Addons submenu
        add_submenu_page(
            'easy-invoice',
            __('Addons', 'easy-invoice'),
            __('Addons', 'easy-invoice'),
            'manage_options',
            PagesSlugs::ADDONS,
            array($this, 'displayMainPage')
        );

        // License submenu
        add_submenu_page(
            'easy-invoice',
            __('License', 'easy-invoice'),
            __('License', 'easy-invoice'),
            'manage_options',
            PagesSlugs::LICENSE,
            array($this, 'displayMainPage')
        );

        // Free vs Pro submenu - only show in free version
        if (!easy_invoice_has_pro()) {
            add_submenu_page(
                'easy-invoice',
                __('Free vs Pro', 'easy-invoice'),
                __('Free vs Pro', 'easy-invoice'),
                'manage_options',
                'easy-invoice-free-vs-pro',
                array($this, 'displayMainPage')
            );
        }

        // Join Community submenu
        add_submenu_page(
            'easy-invoice-hidden',
            __('Join Community', 'easy-invoice'),
            __('Join Community', 'easy-invoice'),
            'read',
            'easy-invoice-join-community',
            array($this, 'redirectToCommunity')
        );
    }

    /**
     * Redirect to community page
     */
    public function redirectToCommunity() {
        wp_redirect(esc_url_raw('https://www.facebook.com/groups/mantrabraincommunity'));
        exit;
    }

    /**
     * Register invoice preview page.
     *
     * Placeholder kept as an extension point — the preview-page hook used to
     * be wired here but is now routed through the per-document preview
     * controller. Left in place so themes/plugins relying on a no-op
     * `registerPreviewPage()` call don't fatal.
     */
    public function registerPreviewPage() {
        // No-op: preview rendering is handled by the per-document controller.
    }

    /**
     * Display main page
     */
    public function displayMainPage() {
        include EASY_INVOICE_PLUGIN_DIR . 'templates/main-template.php';
    }

    /**
     * Display preview page
     */
    public function displayPreviewPage() {
        $this->invoice_controller->display(['page' => PagesSlugs::INVOICE_PREVIEW]);
    }

    /**
     * Display license page
     */
    public function displayLicensePage() {
        include EASY_INVOICE_PLUGIN_DIR . 'templates/admin/license-page.php';
    }

    /**
     * Display addons page
     */
    public function displayAddonsPage() {
        if (class_exists('\\EasyInvoice\\Controllers\\AddonsController')) {
            (new \EasyInvoice\Controllers\AddonsController())->display();
        }
    }

    /**
     * Handle main page content based on the current page
     *
     * @param string $page Current page
     */
    public function mainPageContent($page) {
        switch ($page) {
            case PagesSlugs::DASHBOARD:
                $this->dashboard_controller->display(['page' => PagesSlugs::DASHBOARD]);
                break;

            case PagesSlugs::ALL_INVOICES:
                $this->invoice_controller->display(['page' => PagesSlugs::ALL_INVOICES]);
                break;

            case PagesSlugs::INVOICE_NEW:
                $this->invoice_controller->display(['page' => PagesSlugs::INVOICE_NEW]);
                break;

            case PagesSlugs::INVOICE_PREVIEW:
                $this->invoice_controller->display(['page' => PagesSlugs::INVOICE_PREVIEW]);
                break;

            case PagesSlugs::ALL_QUOTES:
                $this->quote_controller->display(['page' => PagesSlugs::ALL_QUOTES]);
                break;

            case PagesSlugs::QUOTE_NEW:
                $this->quote_controller->display(['page' => PagesSlugs::QUOTE_NEW]);
                break;

            case PagesSlugs::QUOTE_PREVIEW:
                $this->quote_controller->display(['page' => PagesSlugs::QUOTE_PREVIEW]);
                break;

            case PagesSlugs::PAYMENTS:
                if (isset($_GET['action'])) {
                    $this->payment_controller->display(['page' => $_GET['action']]);
                } else {
                    $this->payment_controller->display(['page' => PagesSlugs::PAYMENTS]);
                }
                break;

            case PagesSlugs::PAYMENT_NEW:
                $this->payment_controller->display(['page' => PagesSlugs::PAYMENT_NEW]);
                break;

            case PagesSlugs::CLIENTS:
                $this->client_controller->display(['page' => PagesSlugs::CLIENTS]);
                break;

            case PagesSlugs::CLIENT_EDIT:
                $this->client_controller->display(['page' => PagesSlugs::CLIENT_EDIT]);
                break;

            // Handle Pro features — gated on addon-state. The menu
            // registrations above are also addon-gated, so these cases
            // should only fire when the addon is enabled. Re-checking
            // shouldLoad() here is defensive in case the user hits the
            // page slug directly via URL.
            case 'easy-invoice-pro-item-library':
                if (
                    easy_invoice_has_pro()
                    && \EasyInvoice\Addons\AddonManager::shouldLoad('item_library')
                    && class_exists('\EasyInvoicePro\Addons\ItemLibrary\Controllers\ItemLibraryController')
                ) {
                    $item_library_controller = new \EasyInvoicePro\Addons\ItemLibrary\Controllers\ItemLibraryController();
                    $item_library_controller->displayMainPage();
                }
                break;

            case 'easy-invoice-templates':
                if (
                    easy_invoice_has_pro()
                    && \EasyInvoice\Addons\AddonManager::shouldLoad('custom_templates')
                    && class_exists('\EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController')
                ) {
                    $template_builder_controller = new \EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController();
                    $template_builder_controller->displayMainPage();
                }
                break;

            case 'easy-invoice-template-builder':
                if (
                    easy_invoice_has_pro()
                    && \EasyInvoice\Addons\AddonManager::shouldLoad('custom_templates')
                    && class_exists('\EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController')
                ) {
                    $template_builder_controller = new \EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController();
                    $template_builder_controller->displayMainPage();
                }
                break;

            case PagesSlugs::CLIENT_VIEW:
                $this->client_controller->display(['page' => PagesSlugs::CLIENT_VIEW]);
                break;

            case PagesSlugs::REPORTS:
                // Reports is addon-gated. The submenu page slug is only
                // registered when shouldLoad('reports') is true, so this
                // case ordinarily only fires for active-addon users —
                // but recheck defensively in case the page is reached
                // via direct URL right after the addon was disabled.
                if (\EasyInvoice\Addons\AddonManager::shouldLoad('reports')) {
                    $this->report_controller->display(['page' => PagesSlugs::REPORTS]);
                }
                break;

            case PagesSlugs::SETTINGS:
                $this->settings_controller->display(['page' => PagesSlugs::SETTINGS]);
                break;

            case PagesSlugs::LICENSE:
                $this->displayLicensePage();
                break;

            case PagesSlugs::ADDONS:
                $this->displayAddonsPage();
                break;

            case PagesSlugs::EMAIL_SETTINGS:
            case PagesSlugs::EMAIL_SETTINGS_GENERAL:
            case PagesSlugs::EMAIL_SETTINGS_INVOICE:
            case PagesSlugs::EMAIL_SETTINGS_QUOTE:
            case PagesSlugs::EMAIL_SETTINGS_PAYMENT:
                $this->settings_controller->display(['page' => PagesSlugs::SETTINGS, 'subsection' => $page]);
                break;

            case 'easy-invoice-migration':
                include EASY_INVOICE_PLUGIN_DIR . 'includes/Migration/templates/migration-page.php';
                break;

            case 'easy-invoice-free-vs-pro':
                include EASY_INVOICE_PLUGIN_DIR . 'templates/admin/free-vs-pro-page.php';
                break;

            default:
                // Addon pages render themselves via the
                // `easy_invoice_admin_main_content` action at priority 11. The
                // dispatcher must NOT fall through to the Dashboard for those
                // slugs, otherwise the Dashboard markup gets emitted first and
                // the addon panel renders on top of it (two pages stacked).
                //
                // We treat any slug that's either (a) prefixed with
                // `easy-invoice-addon-` or (b) registered in AddonRegistry as
                // an addon page — and just `break` to let the addon's own hook
                // handle the rendering.
                if (strpos($page, 'easy-invoice-addon-') === 0) {
                    break;
                }
                if (class_exists('\\EasyInvoice\\Addons\\AddonRegistry')) {
                    foreach (\EasyInvoice\Addons\AddonRegistry::all() as $_addon) {
                        if (empty($_addon['settings_url'])) continue;
                        $parsed = wp_parse_url($_addon['settings_url']);
                        if (empty($parsed['query'])) continue;
                        parse_str($parsed['query'], $q);
                        if (($q['page'] ?? '') === $page) {
                            return; // Addon owns this slug — bail without rendering.
                        }
                    }
                }
                $this->dashboard_controller->display(['page' => PagesSlugs::DASHBOARD]);
                break;
        }
    }

    /**
     * Set proper admin title to avoid WordPress core issues
     *
     * @param string $title The current admin title
     * @return string The modified admin title
     */
    public function setAdminTitle($title) {
        $current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';

        // Only modify titles for our plugin pages
        if (strpos($current_page, 'easy-invoice') === 0 || strpos($current_page, 'easy-quote') === 0) {
            $page_titles = [
                'easy-invoice' => __('Dashboard', 'easy-invoice'),
                'easy-invoice-all' => __('All Invoices', 'easy-invoice'),
                'easy-invoice-builder' => __('Add New Invoice', 'easy-invoice'),
                'easy-invoice-preview' => __('Preview Invoice', 'easy-invoice'),
                'easy-quote-all' => __('All Quotes', 'easy-invoice'),
                'easy-invoice-quote-builder' => __('Add New Quote', 'easy-invoice'),
                'easy-quote-preview' => __('Preview Quote', 'easy-invoice'),
                'easy-invoice-payments' => __('Payments', 'easy-invoice'),
                'easy-invoice-payment-new' => __('Add New Payment', 'easy-invoice'),
                'easy-invoice-clients' => __('Clients', 'easy-invoice'),
                'easy-invoice-client-edit' => __('Edit Client', 'easy-invoice'),
                'easy-invoice-client-view' => __('View Client', 'easy-invoice'),
                'easy-invoice-reports' => __('Reports', 'easy-invoice'),
                'easy-invoice-settings' => __('Settings', 'easy-invoice'),
                'easy-invoice-email-settings' => __('Email Settings', 'easy-invoice'),
                'easy-invoice-migration' => __('Migration', 'easy-invoice'),
                'easy-invoice-free-vs-pro' => __('Free vs Pro', 'easy-invoice'),
                'easy-invoice-addons' => __('Addons', 'easy-invoice'),
            ];

            if (isset($page_titles[$current_page])) {
                return $page_titles[$current_page] . ' - ' . get_bloginfo('name');
            }
        }

        return $title;
    }

    /**
     * Body class for Easy Invoice full-width layout (used by hideAdminUi CSS).
     *
     * @param string $classes Space-separated classes.
     * @return string
     */
    public function adminBodyClass($classes) {
        $screen = get_current_screen();
        if (!$screen || !isset($screen->id)) {
            return $classes;
        }
        if (strpos($screen->id, 'easy-invoice') !== false || strpos($screen->id, 'easy-quote') !== false) {
            $classes .= ' easy-invoice-admin-body';
        }
        return $classes;
    }

    /**
     * Hide the WordPress admin UI for our custom pages
     */
    public function hideAdminUi() {
        $screen = get_current_screen();
        if ($screen && property_exists($screen, 'id') && (strpos($screen->id, 'easy-invoice') !== false || strpos($screen->id, 'easy-quote') !== false)) {
            ?>
            <style>
                #wpadminbar,
                #adminmenumain,
                #wpfooter {
                    display: none !important;
                }
                #wpcontent {
                    margin-left: 0 !important;
                    padding: 0 !important;
                }
                .wrap {
                    margin: 0 !important;
                    padding: 0 !important;
                }
                /*
                 * Admin bar is hidden but body.admin-bar often still gets top padding,
                 * shifting #wpbody down while the fixed plugin sidebar stays at y=0 — header borders misalign.
                 */
                body.easy-invoice-admin-body.admin-bar {
                    padding-top: 0 !important;
                }
                body.easy-invoice-admin-body.admin-bar #wpbody,
                body.easy-invoice-admin-body.admin-bar #wpbody-content {
                    padding-top: 0 !important;
                }
            </style>
            <?php
        }
    }
}

```
