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

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.4.0. 789 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.4.0/code/includes/Admin/EasyInvoiceAdmin.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.4.0/raw/includes/Admin/EasyInvoiceAdmin.php
- Modified: 2026-09-15T12:31:20+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.4.0/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'));
        add_action('admin_menu', array($this, 'relaxMenuCapabilities'), 9999);

        // 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'));
    }

    /**
     * Let an addon lower the capability a menu page demands.
     *
     * Every page is registered with `manage_options`, which is right for a
     * site with one administrator and wrong the moment the Team Roles addon
     * hands a colleague an "EI Viewer" role: WordPress refused them every
     * screen before the plugin's own capability checks were even consulted.
     * add_submenu_page() drops a page outright when the current user lacks
     * the capability, so the plugin's own pages pass through menuCapability()
     * at registration; this late pass covers pages registered elsewhere.
     */
    public function menuCapability($slug) {
        /** This filter is documented in relaxMenuCapabilities(). */
        return (string) apply_filters('easy_invoice_menu_capability', 'manage_options', (string) $slug);
    }

    public function relaxMenuCapabilities() {
        global $menu, $submenu;
        $relax = static function ($cap, $slug) {
            if (!is_string($slug) || 0 !== strpos($slug, 'easy-') ) {
                return $cap;
            }
            /**
             * Filter the capability required to open an Easy Invoice admin page.
             *
             * @param string $cap  Capability registered for the page.
             * @param string $slug Page slug.
             */
            return (string) apply_filters('easy_invoice_menu_capability', $cap, $slug);
        };
        if (is_array($menu)) {
            foreach ($menu as $i => $item) {
                if (isset($item[1], $item[2])) {
                    $menu[$i][1] = $relax($item[1], $item[2]);
                }
            }
        }
        if (is_array($submenu)) {
            foreach ($submenu as $parent => $items) {
                foreach ((array) $items as $i => $item) {
                    if (isset($item[1], $item[2])) {
                        $submenu[$parent][$i][1] = $relax($item[1], $item[2]);
                    }
                }
            }
        }
    }

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

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

        // All invoices submenu
        add_submenu_page(
            'easy-invoice',
            __('All Invoices', 'easy-invoice'),
            __('All Invoices', 'easy-invoice'),
            $this->menuCapability(PagesSlugs::ALL_INVOICES),
            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'),
            $this->menuCapability(PagesSlugs::INVOICE_NEW),
            PagesSlugs::INVOICE_NEW,
            array($this, 'displayMainPage')
        );

        // All quotes submenu
        add_submenu_page(
            'easy-invoice',
            __('All Quotes', 'easy-invoice'),
            __('All Quotes', 'easy-invoice'),
            $this->menuCapability(PagesSlugs::ALL_QUOTES),
            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'),
            $this->menuCapability(PagesSlugs::QUOTE_NEW),
            PagesSlugs::QUOTE_NEW,
            array($this, 'displayMainPage')
        );

        // Payments submenu
        add_submenu_page(
            'easy-invoice-hidden',
            __('Payments', 'easy-invoice'),
            __('Payments', 'easy-invoice'),
            $this->menuCapability(PagesSlugs::PAYMENTS),
            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'),
            $this->menuCapability(PagesSlugs::PAYMENT_NEW),
            PagesSlugs::PAYMENT_NEW,
            array($this, 'displayMainPage')
        );

        // Clients submenu
        add_submenu_page(
            'easy-invoice',
            __('All Clients', 'easy-invoice'),
            __('All Clients', 'easy-invoice'),
            $this->menuCapability(PagesSlugs::CLIENTS),
            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'),
                $this->menuCapability('easy-invoice-pro-item-library'),
                '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'),
                $this->menuCapability('easy-invoice-templates'),
                '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'),
                $this->menuCapability('easy-invoice-templates-new'),
                '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'),
                $this->menuCapability('easy-invoice-template-builder'),
                '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'),
            $this->menuCapability(PagesSlugs::CLIENT_EDIT),
            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'),
            $this->menuCapability(PagesSlugs::CLIENT_VIEW),
            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'),
            $this->menuCapability(PagesSlugs::INVOICE_PREVIEW),
            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'),
            $this->menuCapability(PagesSlugs::QUOTE_PREVIEW),
            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'),
                $this->menuCapability(PagesSlugs::REPORTS),
                PagesSlugs::REPORTS,
                array($this, 'displayMainPage')
            );
        }

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

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

        // License submenu
        add_submenu_page(
            'easy-invoice',
            __('License', 'easy-invoice'),
            __('License', 'easy-invoice'),
            $this->menuCapability(PagesSlugs::LICENSE),
            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'),
                $this->menuCapability('easy-invoice-free-vs-pro'),
                '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_safe_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' => sanitize_key(wp_unslash($_GET['action']))]); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                } 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;
                }

                /**
                 * Slugs whose page draws itself on the same hook at a later
                 * priority, and which must therefore not get the Dashboard
                 * rendered underneath them.
                 *
                 * Addon pages were special-cased by prefix above, which left
                 * anything in the free plugin that renders the same way — the
                 * credit note screen, for one — falling through to the
                 * Dashboard and stacking two pages on top of each other. A
                 * filter means the next such page registers itself instead of
                 * editing this switch and rediscovering the same bug.
                 *
                 * @param string[] $slugs Page slugs that render themselves.
                 */
                // "Create New Template" is a deep-link slug with no screen of
                // its own; send it to the builder rather than draw the Dashboard.
                if ('easy-invoice-templates-new' === $page) {
                    echo '<script>window.location.replace(' . wp_json_encode(admin_url('admin.php?page=easy-invoice-template-builder&action=new')) . ');</script>';
                    break;
                }
                $self_rendering = (array) apply_filters('easy_invoice_self_rendering_pages', [
                    \EasyInvoice\Controllers\CreditNoteController::PAGE_SLUG,
                ]);

                if (in_array($page, $self_rendering, true)) {
                    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
        }
    }
}

```
