> */ public static function all(): array { return apply_filters('easy_invoice_addons_registry', [ // ─── PROFESSIONAL ───────────────────────────────────────────── [ 'id' => 'time_tracking', 'name' => __('Time Tracking & Project Billing', 'easy-invoice'), 'short_name' => __('Time Tracking', 'easy-invoice'), 'tagline' => __('Track billable hours and convert them to invoice lines in one click.', 'easy-invoice'), 'description' => __('Built-in start/stop timer with per-project and per-client entries. Convert any block of tracked time into invoice line items in one click — replaces your standalone time-tracking tool.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL, 'icon' => 'dashicons-clock', 'category' => 'productivity', 'badge' => 'popular', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/time-tracking/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-time-tracking'), 'pro_class' => 'EasyInvoicePro\\Addons\\TimeTracking\\TimeTracking', ], [ 'id' => 'expense_tracking', 'name' => __('Expense Tracking & Reimbursable Items', 'easy-invoice'), 'short_name' => __('Expenses', 'easy-invoice'), 'tagline' => __('Log billable expenses, mark them up, and convert to invoice lines in one click.', 'easy-invoice'), 'description' => __('Track project expenses (software, mileage, materials, contractor costs) with receipt uploads. Apply markup and roll selected expenses into invoice line items — the same pattern as Time Tracking, for everything that isn\'t billable hours.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL, 'icon' => 'dashicons-money', 'category' => 'billing', 'badge' => 'new', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/expense-tracking/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-expense-tracking'), 'pro_class' => 'EasyInvoicePro\\Addons\\ExpenseTracking\\ExpenseTracking', ], [ 'id' => 'dunning', 'name' => __('Smart Reminders & Late Fees', 'easy-invoice'), 'short_name' => __('Smart Reminders', 'easy-invoice'), 'tagline' => __('Recover overdue invoices automatically — without the awkward chase emails.', 'easy-invoice'), 'description' => __('Configure a multi-step reminder cadence with per-step templates that escalate in tone. Auto-apply late fees and offer early-payment discounts — typically recovers 30%+ of overdue invoices.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL, 'icon' => 'dashicons-email-alt', 'category' => 'billing', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/smart-reminders/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-dunning'), 'pro_class' => 'EasyInvoicePro\\Addons\\SmartReminders\\SmartReminders', ], // ─── AGENCY ─────────────────────────────────────────────────── [ 'id' => 'white_label', 'name' => __('White-Label & Brand Override', 'easy-invoice'), 'short_name' => __('White-Label', 'easy-invoice'), 'tagline' => __('Rebrand Easy Invoice as your own product — every label, footer, and PDF.', 'easy-invoice'), 'description' => __('Replace the plugin name, admin menu, dashboard icon, PDF footer, and email signature with your own brand. Hide every upgrade prompt — essential for agencies reselling Easy Invoice as a managed service.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_AGENCY, 'icon' => 'dashicons-businesswoman', 'category' => 'branding', 'badge' => 'new', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/white-label/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-white-label'), 'pro_class' => 'EasyInvoicePro\\Addons\\WhiteLabel\\WhiteLabel', ], [ 'id' => 'team_roles', 'name' => __('Team Members & Audit Log', 'easy-invoice'), 'short_name' => __('Team & Audit', 'easy-invoice'), 'tagline' => __('Invite staff with scoped roles. See who did what, when, and why.', 'easy-invoice'), 'description' => __('Scoped roles (Manager / Accountant / Sales / Viewer) so staff can work without touching refunds or settings. Every action lands in a searchable audit log — required for compliance and accountant hand-offs.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_AGENCY, 'icon' => 'dashicons-groups', 'category' => 'team', 'badge' => 'new', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/team-roles/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-team-roles'), 'pro_class' => 'EasyInvoicePro\\Addons\\TeamRoles\\TeamRoles', ], [ 'id' => 'accounting_sync', 'name' => __('Accounting Sync (QuickBooks / Xero / FreshBooks)', 'easy-invoice'), 'short_name' => __('Accounting Sync', 'easy-invoice'), 'tagline' => __('Two-way sync with QuickBooks Online, Xero, and FreshBooks — invoices out, payments back.', 'easy-invoice'), 'description' => __('Push invoices to your accounting tool when created; pull payment status back when reconciled there. Chart-of-accounts mapping, customer mirroring, and bank-rec friendly. Pluggable provider layer for QBO, Xero, FreshBooks (and adding more).', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_AGENCY, 'icon' => 'dashicons-update-alt', 'category' => 'integrations', 'badge' => 'new', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/accounting-sync/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-accounting-sync'), 'pro_class' => 'EasyInvoicePro\\Addons\\AccountingSync\\AccountingSync', ], [ 'id' => 'webhooks', 'name' => __('Webhooks & Zapier Bridge', 'easy-invoice'), 'short_name' => __('Webhooks', 'easy-invoice'), 'tagline' => __('Push invoice events into Zapier, your CRM, Slack — anywhere with a URL.', 'easy-invoice'), 'description' => __('Subscribe any URL to invoice events (paid, accepted, failed, recurring run). HMAC-SHA256 signed payloads, automatic retries. Drops into Zapier, Make, n8n, your CRM — connect to 5,000+ tools.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_AGENCY, 'icon' => 'dashicons-rest-api', 'category' => 'integrations', 'badge' => 'new', 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/webhooks/', 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-webhooks'), 'pro_class' => 'EasyInvoicePro\\Addons\\Webhooks\\Webhooks', ], // ─── PRO-FEATURE ADDONS (migrated from monolithic Pro plugin) ──── // // These ten addons wrap features that previously loaded // unconditionally inside easy-invoice-pro.php. They're enabled // by default on EXISTING installs via the migration in // ProAddonMigration::migrate(), and disabled by default on // FRESH installs so new users can opt in only to what they need. // // None of these have settings pages of their own (they reuse // existing Pro settings pages); the Addons grid only exposes // the enable/disable toggle. The settings_url field points at // the closest relevant settings tab. [ 'id' => 'recurring_invoices', 'name' => __('Recurring Invoices & Subscriptions', 'easy-invoice'), 'short_name' => __('Recurring', 'easy-invoice'), 'tagline' => __('Auto-bill clients on autopilot — weekly, monthly, or any custom schedule.', 'easy-invoice'), 'description' => __('Set the frequency, end date, and payment method once; Easy Invoice generates and sends each invoice on schedule. Optional auto-charge through your gateway closes the loop — predictable revenue, zero admin.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-update', 'category' => 'billing', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/recurring-invoices/', // No dedicated settings page. Recurring data lives as // post-meta on regular easy_invoice posts (META_ENABLED, // META_FREQUENCY, etc. in RecurringInvoices.php) — the // merchant toggles "Make this recurring" on the invoice // editor. The legacy easy_invoice_recurring CPT was // registered with show_in_menu=false + create_posts= // do_not_allow, so linking to its list page from the // addon card just dumped users on a WP-styled, read-only, // dead-end screen. Empty settings_url hides that link. 'settings_url' => admin_url('admin.php?page=easy-invoice-settings§ion=invoice'), 'pro_class' => 'EasyInvoicePro\\Addons\\RecurringInvoices\\RecurringInvoices', ], [ 'id' => 'partial_payments', 'name' => __('Partial Payments & Deposits', 'easy-invoice'), 'short_name' => __('Partial Payments', 'easy-invoice'), 'tagline' => __('Get paid sooner with deposits and flexible installment plans.', 'easy-invoice'), 'description' => __('Require a deposit (% or flat) before work begins, then let clients pay the balance in installments. Tracks every part-payment and shows the running balance — no spreadsheets, no manual reconciliation.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-money-alt', 'category' => 'billing', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/partial-payments/', // PartialPaymentsSettingsController appends its fields to the // main Settings page via the easy_invoice_settings_fields_config // filter — no dedicated page slug. Leave settings_url empty // so the addon card doesn't render a misleading "Settings →" // link that just dumps the user on the main Settings page. 'settings_url' => admin_url('admin.php?page=easy-invoice-settings§ion=invoice'), 'pro_class' => 'EasyInvoicePro\\Addons\\PartialPayments\\PartialPayments', ], [ 'id' => 'client_portal', 'name' => __('Client Portal', 'easy-invoice'), 'short_name' => __('Client Portal', 'easy-invoice'), 'tagline' => __('Give clients a branded self-service area for invoices, quotes, and receipts.', 'easy-invoice'), 'description' => __('Clients log in to a branded portal to view invoices, download PDFs, see payment history, and accept or decline quotes — on their own time. Stops the back-and-forth email asking for old documents.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-admin-users', 'category' => 'clients', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/client-portal/', // ClientPortal extension stores config at // easy_invoice_pro_client_portal_settings; UI lives as a tab // on the main Settings page. No dedicated slug → leave // settings_url empty so the card doesn't render a misleading // "Settings →" link. 'settings_url' => '', 'pro_class' => 'EasyInvoicePro\\Addons\\ClientPortal\\ClientPortal', ], [ 'id' => 'pdf_toolkit', 'name' => __('PDF Toolkit', 'easy-invoice'), 'short_name' => __('PDF Toolkit', 'easy-invoice'), 'tagline' => __('Customise every detail of your invoice and quote PDFs.', 'easy-invoice'), 'description' => __('Custom headers and footers, watermark stamps (PAID / DRAFT / OVERDUE / VOID), color and font controls, and per-document branding. Make every PDF look enterprise-grade — not stock WordPress.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-pdf', 'category' => 'branding', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/pdf-toolkit/', // PdfCustomizationSettingsController appends fields to the // main Settings page via filter; no dedicated slug. Empty // settings_url hides the misleading "Settings →" link. 'settings_url' => admin_url('admin.php?page=easy-invoice-settings§ion=invoice'), 'pro_class' => 'EasyInvoicePro\\Addons\\PdfToolkit\\PdfToolkit', ], [ 'id' => 'bulk_operations', 'name' => __('Bulk Email & Export', 'easy-invoice'), 'short_name' => __('Bulk Ops', 'easy-invoice'), 'tagline' => __('Send and export hundreds of invoices in a single click.', 'easy-invoice'), 'description' => __('Bulk actions on every list screen — email batches of invoices in one click, or export selected rows to CSV, Excel, or PDF. \"Export All\" downloads your entire history, perfect for year-end accounting.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-download', 'category' => 'productivity', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/bulk-operations/', 'settings_url' => '', 'pro_class' => 'EasyInvoicePro\\Addons\\BulkOperations\\BulkOperations', ], [ 'id' => 'item_library', 'name' => __('Item Library', 'easy-invoice'), 'short_name' => __('Item Library', 'easy-invoice'), 'tagline' => __('Build a reusable catalog of services and products.', 'easy-invoice'), 'description' => __('Save your common services and products with name, description, price, and SKU. Insert into any invoice or quote in one click — stop retyping and keep pricing consistent across every document.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-products', 'category' => 'productivity', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/item-library/', // Verified slug: ItemLibraryController::addAdminMenu() // registers 'easy-invoice-pro-item-library'. 'settings_url' => admin_url('admin.php?page=easy-invoice-pro-item-library'), 'pro_class' => 'EasyInvoicePro\\Addons\\ItemLibrary\\ItemLibrary', ], [ 'id' => 'custom_templates', 'name' => __('Custom Invoice & Quote Templates', 'easy-invoice'), 'short_name' => __('Templates', 'easy-invoice'), 'tagline' => __('Design pixel-perfect invoice and quote layouts with a drag-and-drop builder.', 'easy-invoice'), 'description' => __('Build your own invoice and quote layouts with the visual editor — drag in logos, company info, item tables, totals, signatures, and footers. Save multiple templates and assign different layouts per client.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-layout', 'category' => 'branding', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/custom-templates/', // Verified slug: TemplateBuilderController registers // 'easy-invoice-templates' (the listing) — that's the // canonical entry point. settings_url here is used by // the per-addon sidebar loop in main-template.php to // render a sidebar entry BELOW the Addons menu. The // addons-page.php card does NOT render a "Settings →" // link anymore (the sidebar is the navigation). 'settings_url' => admin_url('admin.php?page=easy-invoice-templates'), 'pro_class' => 'EasyInvoicePro\\Addons\\CustomTemplates\\CustomTemplates', ], [ 'id' => 'additional_tax', 'name' => __('Additional Tax Lines', 'easy-invoice'), 'short_name' => __('Additional Tax', 'easy-invoice'), 'tagline' => __('Multiple tax lines per invoice — VAT + duty, GST + PST, federal + state.', 'easy-invoice'), 'description' => __('Add unlimited named tax lines per invoice — VAT + duty, GST + PST, federal + state — each with its own rate. Renders every tax as a separate line on the PDF so clients see exactly what they\'re paying.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-chart-bar', 'category' => 'billing', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/additional-tax/', // AdditionalTax extension appends "Enable Additional Tax" // + per-tax-rate fields via the main Settings page; no // dedicated slug → empty settings_url hides the // misleading "Settings →" link. 'settings_url' => admin_url('admin.php?page=easy-invoice-settings§ion=tax'), 'pro_class' => 'EasyInvoicePro\\Addons\\AdditionalTax\\AdditionalTax', ], [ 'id' => 'email_enhancements', 'name' => __('Email Enhancements', 'easy-invoice'), 'short_name' => __('Email Tools', 'easy-invoice'), 'tagline' => __('Send branded HTML emails with PDF attached, CC / BCC, and Reply-To.', 'easy-invoice'), 'description' => __('Branded HTML emails with your colors and logo. Add CC / BCC, auto-attach the PDF, customise the subject and body per invoice, and set a Reply-To so client replies reach the right inbox.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-email', 'category' => 'productivity', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/email-enhancements/', // EmailEnhancements appends Reply-To / advanced email // fields to the main Settings page; no dedicated slug → // empty settings_url hides the misleading "Settings →" // link. 'settings_url' => '', 'pro_class' => 'EasyInvoicePro\\Addons\\EmailEnhancements\\EmailEnhancements', ], [ 'id' => 'secure_links', 'name' => __('Secure Links for Invoices & Quotes', 'easy-invoice'), 'short_name' => __('Secure Links', 'easy-invoice'), 'tagline' => __('Share invoices and quotes with unguessable, signed URLs instead of plain post slugs.', 'easy-invoice'), 'description' => __('Replace predictable invoice/quote permalinks with cryptographically signed, expiring URLs. Stops competitors and customers from incrementing IDs to view documents that aren\'t theirs. Already wired into emails, the [easy_invoice_links] shortcode, and recurring child invoices.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-lock', 'category' => 'compliance', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/secure-links/', // Settings live inside Settings → Advanced, injected // by SecureLinks::registerAdvancedFields() (the same // pattern Payment Reminder uses for the Email tab). // The toggle there stays in lock-step with the // addon-enabled state via the addon's // update_option_* hooks. 'settings_url' => admin_url('admin.php?page=easy-invoice-settings§ion=advanced'), 'pro_class' => 'EasyInvoicePro\\Addons\\SecureLinks\\SecureLinks', ], [ 'id' => 'privacy_tools', 'name' => __('Privacy & GDPR', 'easy-invoice'), 'short_name' => __('Privacy', 'easy-invoice'), 'tagline' => __('Comply with GDPR, CCPA, and other data-protection laws in one click.', 'easy-invoice'), 'description' => __('Wires Easy Invoice into WordPress\'s Personal Data Export and Erase tools. Client invoice, quote, and payment history is included automatically in data-subject requests — required for EU and California compliance.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-shield', 'category' => 'compliance', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/privacy-tools/', // The privacy_tools addon hooks WordPress's built-in // personal-data exporter / eraser registries — those // registries are managed by WP core under // Tools → Export/Erase Personal Data (a WP-native page, // not our UI). There is no addon-specific settings page // to surface from the addons grid, so leave settings_url // empty — the addon card just shows Active/Inactive. 'settings_url' => '', 'pro_class' => 'EasyInvoicePro\\Addons\\PrivacyTools\\PrivacyTools', ], [ 'id' => 'reports', 'name' => __('Reports & Analytics', 'easy-invoice'), 'short_name' => __('Reports', 'easy-invoice'), 'tagline' => __('See your revenue, outstanding balances, and best clients at a glance.', 'easy-invoice'), 'description' => __('Visual dashboard for invoice revenue, outstanding balances, payment status, and per-client performance. Filter by any date range, export for your accountant, and decide on data instead of guessing.', 'easy-invoice'), 'plan' => LicensePlanResolver::PLAN_PERSONAL, 'icon' => 'dashicons-chart-line', 'category' => 'analytics', 'badge' => null, 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/reports/', // ReportController lives in the Free plugin (the class // existed before addonization) but the page is a Pro // feature shown to Free users only as an upsell badge. // Gating its sidebar link + page dispatch on this addon // makes "Reports" opt-in for Pro users too. The slug // 'easy-invoice-reports' is registered as an EI admin // submenu by EasyInvoiceAdmin::registerMenuPages(). 'settings_url' => admin_url('admin.php?page=easy-invoice-reports'), 'pro_class' => 'EasyInvoicePro\\Addons\\Reports\\Reports', ], ]); } /** * IDs of every addon that wraps a previously-monolithic Pro feature. * Used by ProAddonMigration to know which flags to set for existing * Pro installs (so their currently-active features keep working) and * to leave disabled for fresh installs. * * @return array */ public static function migratedProAddonIds(): array { return [ 'recurring_invoices', 'partial_payments', 'client_portal', 'pdf_toolkit', 'bulk_operations', 'item_library', 'custom_templates', 'additional_tax', 'email_enhancements', 'privacy_tools', // Reports was previously gated only by easy_invoice_has_pro(); // any Pro install was using it. The migration falls through // to isExistingProInstall() for this id, so existing Pro // sites keep Reports active after the addon-ization migration. 'reports', // Secure Links was always-loaded Pro infrastructure // gated only by easy_invoice_pro_enable_secure_links. // Migration auto-enables the addon when that legacy // option was 'yes' so signed URLs already in the wild // (emails, shortcodes) keep resolving. 'secure_links', ]; } /** * Find a single addon definition by id. * * @return array|null */ public static function find(string $id): ?array { foreach (self::all() as $addon) { if ($addon['id'] === $id) { return $addon; } } return null; } /** * Distinct categories present in the registry — drives the filter chips in the UI. * * @return array */ public static function categories(): array { $cats = []; foreach (self::all() as $addon) { $cats[$addon['category']] = true; } return array_keys($cats); } }