PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.7
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.7
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Addons / AddonRegistry.php

AddonRegistry.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.3.7, at includes/Addons/AddonRegistry.php

437 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Catalogue of available Easy Invoice addons.
4 *
5 * The Free plugin owns the metadata so the Addons page renders even when Pro
6 * is inactive. The Pro plugin owns the executable code at the `pro_file` path.
7 *
8 * @package EasyInvoice
9 */
10
11 namespace EasyInvoice\Addons;
12
13 if (!defined('ABSPATH')) {
14 exit;
15 }
16
17 class AddonRegistry {
18
19 /**
20 * @return array<int,array<string,mixed>>
21 */
22 public static function all(): array {
23 return apply_filters('easy_invoice_addons_registry', [
24
25 // ─── PROFESSIONAL ─────────────────────────────────────────────
26 [
27 'id' => 'time_tracking',
28 'name' => __('Time Tracking & Project Billing', 'easy-invoice'),
29 'short_name' => __('Time Tracking', 'easy-invoice'),
30 'tagline' => __('Track billable hours and convert them to invoice lines in one click.', 'easy-invoice'),
31 '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'),
32 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
33 'icon' => 'dashicons-clock',
34 'category' => 'productivity',
35 'badge' => 'popular',
36 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/time-tracking/',
37 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-time-tracking'),
38 'pro_class' => 'EasyInvoicePro\\Addons\\TimeTracking\\TimeTracking',
39 ],
40
41 [
42 'id' => 'expense_tracking',
43 'name' => __('Expense Tracking & Reimbursable Items', 'easy-invoice'),
44 'short_name' => __('Expenses', 'easy-invoice'),
45 'tagline' => __('Log billable expenses, mark them up, and convert to invoice lines in one click.', 'easy-invoice'),
46 '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'),
47 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
48 'icon' => 'dashicons-money',
49 'category' => 'billing',
50 'badge' => 'new',
51 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/expense-tracking/',
52 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-expense-tracking'),
53 'pro_class' => 'EasyInvoicePro\\Addons\\ExpenseTracking\\ExpenseTracking',
54 ],
55
56 [
57 'id' => 'dunning',
58 'name' => __('Smart Reminders & Late Fees', 'easy-invoice'),
59 'short_name' => __('Smart Reminders', 'easy-invoice'),
60 'tagline' => __('Recover overdue invoices automatically — without the awkward chase emails.', 'easy-invoice'),
61 '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'),
62 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
63 'icon' => 'dashicons-email-alt',
64 'category' => 'billing',
65 'badge' => null,
66 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/smart-reminders/',
67 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-dunning'),
68 'pro_class' => 'EasyInvoicePro\\Addons\\SmartReminders\\SmartReminders',
69 ],
70
71 // ─── AGENCY ───────────────────────────────────────────────────
72 [
73 'id' => 'white_label',
74 'name' => __('White-Label & Brand Override', 'easy-invoice'),
75 'short_name' => __('White-Label', 'easy-invoice'),
76 'tagline' => __('Rebrand Easy Invoice as your own product — every label, footer, and PDF.', 'easy-invoice'),
77 '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'),
78 'plan' => LicensePlanResolver::PLAN_AGENCY,
79 'icon' => 'dashicons-businesswoman',
80 'category' => 'branding',
81 'badge' => 'new',
82 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/white-label/',
83 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-white-label'),
84 'pro_class' => 'EasyInvoicePro\\Addons\\WhiteLabel\\WhiteLabel',
85 ],
86
87 [
88 'id' => 'team_roles',
89 'name' => __('Team Members & Audit Log', 'easy-invoice'),
90 'short_name' => __('Team & Audit', 'easy-invoice'),
91 'tagline' => __('Invite staff with scoped roles. See who did what, when, and why.', 'easy-invoice'),
92 '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'),
93 'plan' => LicensePlanResolver::PLAN_AGENCY,
94 'icon' => 'dashicons-groups',
95 'category' => 'team',
96 'badge' => 'new',
97 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/team-roles/',
98 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-team-roles'),
99 'pro_class' => 'EasyInvoicePro\\Addons\\TeamRoles\\TeamRoles',
100 ],
101
102 [
103 'id' => 'accounting_sync',
104 'name' => __('Accounting Sync (QuickBooks / Xero / FreshBooks)', 'easy-invoice'),
105 'short_name' => __('Accounting Sync', 'easy-invoice'),
106 'tagline' => __('Two-way sync with QuickBooks Online, Xero, and FreshBooks — invoices out, payments back.', 'easy-invoice'),
107 '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'),
108 'plan' => LicensePlanResolver::PLAN_AGENCY,
109 'icon' => 'dashicons-update-alt',
110 'category' => 'integrations',
111 'badge' => 'new',
112 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/accounting-sync/',
113 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-accounting-sync'),
114 'pro_class' => 'EasyInvoicePro\\Addons\\AccountingSync\\AccountingSync',
115 ],
116
117 [
118 'id' => 'webhooks',
119 'name' => __('Webhooks & Zapier Bridge', 'easy-invoice'),
120 'short_name' => __('Webhooks', 'easy-invoice'),
121 'tagline' => __('Push invoice events into Zapier, your CRM, Slack — anywhere with a URL.', 'easy-invoice'),
122 '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'),
123 'plan' => LicensePlanResolver::PLAN_AGENCY,
124 'icon' => 'dashicons-rest-api',
125 'category' => 'integrations',
126 'badge' => 'new',
127 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/webhooks/',
128 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-webhooks'),
129 'pro_class' => 'EasyInvoicePro\\Addons\\Webhooks\\Webhooks',
130 ],
131
132 // ─── PRO-FEATURE ADDONS (migrated from monolithic Pro plugin) ────
133 //
134 // These ten addons wrap features that previously loaded
135 // unconditionally inside easy-invoice-pro.php. They're enabled
136 // by default on EXISTING installs via the migration in
137 // ProAddonMigration::migrate(), and disabled by default on
138 // FRESH installs so new users can opt in only to what they need.
139 //
140 // None of these have settings pages of their own (they reuse
141 // existing Pro settings pages); the Addons grid only exposes
142 // the enable/disable toggle. The settings_url field points at
143 // the closest relevant settings tab.
144
145 [
146 'id' => 'recurring_invoices',
147 'name' => __('Recurring Invoices & Subscriptions', 'easy-invoice'),
148 'short_name' => __('Recurring', 'easy-invoice'),
149 'tagline' => __('Auto-bill clients on autopilot — weekly, monthly, or any custom schedule.', 'easy-invoice'),
150 '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'),
151 'plan' => LicensePlanResolver::PLAN_PERSONAL,
152 'icon' => 'dashicons-update',
153 'category' => 'billing',
154 'badge' => null,
155 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/recurring-invoices/',
156 // No dedicated settings page. Recurring data lives as
157 // post-meta on regular easy_invoice posts (META_ENABLED,
158 // META_FREQUENCY, etc. in RecurringInvoices.php) — the
159 // merchant toggles "Make this recurring" on the invoice
160 // editor. The legacy easy_invoice_recurring CPT was
161 // registered with show_in_menu=false + create_posts=
162 // do_not_allow, so linking to its list page from the
163 // addon card just dumped users on a WP-styled, read-only,
164 // dead-end screen. Empty settings_url hides that link.
165 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=invoice'),
166 'pro_class' => 'EasyInvoicePro\\Addons\\RecurringInvoices\\RecurringInvoices',
167 ],
168 [
169 'id' => 'partial_payments',
170 'name' => __('Partial Payments & Deposits', 'easy-invoice'),
171 'short_name' => __('Partial Payments', 'easy-invoice'),
172 'tagline' => __('Get paid sooner with deposits and flexible installment plans.', 'easy-invoice'),
173 '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'),
174 'plan' => LicensePlanResolver::PLAN_PERSONAL,
175 'icon' => 'dashicons-money-alt',
176 'category' => 'billing',
177 'badge' => null,
178 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/partial-payments/',
179 // PartialPaymentsSettingsController appends its fields to the
180 // main Settings page via the easy_invoice_settings_fields_config
181 // filter — no dedicated page slug. Leave settings_url empty
182 // so the addon card doesn't render a misleading "Settings →"
183 // link that just dumps the user on the main Settings page.
184 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=invoice'),
185 'pro_class' => 'EasyInvoicePro\\Addons\\PartialPayments\\PartialPayments',
186 ],
187 [
188 'id' => 'client_portal',
189 'name' => __('Client Portal', 'easy-invoice'),
190 'short_name' => __('Client Portal', 'easy-invoice'),
191 'tagline' => __('Give clients a branded self-service area for invoices, quotes, and receipts.', 'easy-invoice'),
192 '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'),
193 'plan' => LicensePlanResolver::PLAN_PERSONAL,
194 'icon' => 'dashicons-admin-users',
195 'category' => 'clients',
196 'badge' => null,
197 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/client-portal/',
198 // ClientPortal extension stores config at
199 // easy_invoice_pro_client_portal_settings; UI lives as a tab
200 // on the main Settings page. No dedicated slug → leave
201 // settings_url empty so the card doesn't render a misleading
202 // "Settings →" link.
203 'settings_url' => '',
204 'pro_class' => 'EasyInvoicePro\\Addons\\ClientPortal\\ClientPortal',
205 ],
206 [
207 'id' => 'pdf_toolkit',
208 'name' => __('PDF Toolkit', 'easy-invoice'),
209 'short_name' => __('PDF Toolkit', 'easy-invoice'),
210 'tagline' => __('Customise every detail of your invoice and quote PDFs.', 'easy-invoice'),
211 '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'),
212 'plan' => LicensePlanResolver::PLAN_PERSONAL,
213 'icon' => 'dashicons-pdf',
214 'category' => 'branding',
215 'badge' => null,
216 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/pdf-toolkit/',
217 // PdfCustomizationSettingsController appends fields to the
218 // main Settings page via filter; no dedicated slug. Empty
219 // settings_url hides the misleading "Settings →" link.
220 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=invoice'),
221 'pro_class' => 'EasyInvoicePro\\Addons\\PdfToolkit\\PdfToolkit',
222 ],
223 [
224 'id' => 'bulk_operations',
225 'name' => __('Bulk Email & Export', 'easy-invoice'),
226 'short_name' => __('Bulk Ops', 'easy-invoice'),
227 'tagline' => __('Send and export hundreds of invoices in a single click.', 'easy-invoice'),
228 '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'),
229 'plan' => LicensePlanResolver::PLAN_PERSONAL,
230 'icon' => 'dashicons-download',
231 'category' => 'productivity',
232 'badge' => null,
233 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/bulk-operations/',
234 'settings_url' => '',
235 'pro_class' => 'EasyInvoicePro\\Addons\\BulkOperations\\BulkOperations',
236 ],
237 [
238 'id' => 'item_library',
239 'name' => __('Item Library', 'easy-invoice'),
240 'short_name' => __('Item Library', 'easy-invoice'),
241 'tagline' => __('Build a reusable catalog of services and products.', 'easy-invoice'),
242 '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'),
243 'plan' => LicensePlanResolver::PLAN_PERSONAL,
244 'icon' => 'dashicons-products',
245 'category' => 'productivity',
246 'badge' => null,
247 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/item-library/',
248 // Verified slug: ItemLibraryController::addAdminMenu()
249 // registers 'easy-invoice-pro-item-library'.
250 'settings_url' => admin_url('admin.php?page=easy-invoice-pro-item-library'),
251 'pro_class' => 'EasyInvoicePro\\Addons\\ItemLibrary\\ItemLibrary',
252 ],
253 [
254 'id' => 'custom_templates',
255 'name' => __('Custom Invoice & Quote Templates', 'easy-invoice'),
256 'short_name' => __('Templates', 'easy-invoice'),
257 'tagline' => __('Design pixel-perfect invoice and quote layouts with a drag-and-drop builder.', 'easy-invoice'),
258 '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'),
259 'plan' => LicensePlanResolver::PLAN_PERSONAL,
260 'icon' => 'dashicons-layout',
261 'category' => 'branding',
262 'badge' => null,
263 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/custom-templates/',
264 // Verified slug: TemplateBuilderController registers
265 // 'easy-invoice-templates' (the listing) — that's the
266 // canonical entry point. settings_url here is used by
267 // the per-addon sidebar loop in main-template.php to
268 // render a sidebar entry BELOW the Addons menu. The
269 // addons-page.php card does NOT render a "Settings →"
270 // link anymore (the sidebar is the navigation).
271 'settings_url' => admin_url('admin.php?page=easy-invoice-templates'),
272 'pro_class' => 'EasyInvoicePro\\Addons\\CustomTemplates\\CustomTemplates',
273 ],
274 [
275 'id' => 'additional_tax',
276 'name' => __('Additional Tax Lines', 'easy-invoice'),
277 'short_name' => __('Additional Tax', 'easy-invoice'),
278 'tagline' => __('Multiple tax lines per invoice — VAT + duty, GST + PST, federal + state.', 'easy-invoice'),
279 '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'),
280 'plan' => LicensePlanResolver::PLAN_PERSONAL,
281 'icon' => 'dashicons-chart-bar',
282 'category' => 'billing',
283 'badge' => null,
284 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/additional-tax/',
285 // AdditionalTax extension appends "Enable Additional Tax"
286 // + per-tax-rate fields via the main Settings page; no
287 // dedicated slug → empty settings_url hides the
288 // misleading "Settings →" link.
289 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=tax'),
290 'pro_class' => 'EasyInvoicePro\\Addons\\AdditionalTax\\AdditionalTax',
291 ],
292 [
293 'id' => 'email_enhancements',
294 'name' => __('Email Enhancements', 'easy-invoice'),
295 'short_name' => __('Email Tools', 'easy-invoice'),
296 'tagline' => __('Send branded HTML emails with PDF attached, CC / BCC, and Reply-To.', 'easy-invoice'),
297 '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'),
298 'plan' => LicensePlanResolver::PLAN_PERSONAL,
299 'icon' => 'dashicons-email',
300 'category' => 'productivity',
301 'badge' => null,
302 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/email-enhancements/',
303 // EmailEnhancements appends Reply-To / advanced email
304 // fields to the main Settings page; no dedicated slug →
305 // empty settings_url hides the misleading "Settings →"
306 // link.
307 'settings_url' => '',
308 'pro_class' => 'EasyInvoicePro\\Addons\\EmailEnhancements\\EmailEnhancements',
309 ],
310 [
311 'id' => 'secure_links',
312 'name' => __('Secure Links for Invoices & Quotes', 'easy-invoice'),
313 'short_name' => __('Secure Links', 'easy-invoice'),
314 'tagline' => __('Share invoices and quotes with unguessable, signed URLs instead of plain post slugs.', 'easy-invoice'),
315 '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'),
316 'plan' => LicensePlanResolver::PLAN_PERSONAL,
317 'icon' => 'dashicons-lock',
318 'category' => 'compliance',
319 'badge' => null,
320 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/secure-links/',
321 // Settings live inside Settings → Advanced, injected
322 // by SecureLinks::registerAdvancedFields() (the same
323 // pattern Payment Reminder uses for the Email tab).
324 // The toggle there stays in lock-step with the
325 // addon-enabled state via the addon's
326 // update_option_* hooks.
327 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=advanced'),
328 'pro_class' => 'EasyInvoicePro\\Addons\\SecureLinks\\SecureLinks',
329 ],
330 [
331 'id' => 'privacy_tools',
332 'name' => __('Privacy & GDPR', 'easy-invoice'),
333 'short_name' => __('Privacy', 'easy-invoice'),
334 'tagline' => __('Comply with GDPR, CCPA, and other data-protection laws in one click.', 'easy-invoice'),
335 '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'),
336 'plan' => LicensePlanResolver::PLAN_PERSONAL,
337 'icon' => 'dashicons-shield',
338 'category' => 'compliance',
339 'badge' => null,
340 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/privacy-tools/',
341 // The privacy_tools addon hooks WordPress's built-in
342 // personal-data exporter / eraser registries — those
343 // registries are managed by WP core under
344 // Tools → Export/Erase Personal Data (a WP-native page,
345 // not our UI). There is no addon-specific settings page
346 // to surface from the addons grid, so leave settings_url
347 // empty — the addon card just shows Active/Inactive.
348 'settings_url' => '',
349 'pro_class' => 'EasyInvoicePro\\Addons\\PrivacyTools\\PrivacyTools',
350 ],
351 [
352 'id' => 'reports',
353 'name' => __('Reports & Analytics', 'easy-invoice'),
354 'short_name' => __('Reports', 'easy-invoice'),
355 'tagline' => __('See your revenue, outstanding balances, and best clients at a glance.', 'easy-invoice'),
356 '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'),
357 'plan' => LicensePlanResolver::PLAN_PERSONAL,
358 'icon' => 'dashicons-chart-line',
359 'category' => 'analytics',
360 'badge' => null,
361 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/reports/',
362 // ReportController lives in the Free plugin (the class
363 // existed before addonization) but the page is a Pro
364 // feature shown to Free users only as an upsell badge.
365 // Gating its sidebar link + page dispatch on this addon
366 // makes "Reports" opt-in for Pro users too. The slug
367 // 'easy-invoice-reports' is registered as an EI admin
368 // submenu by EasyInvoiceAdmin::registerMenuPages().
369 'settings_url' => admin_url('admin.php?page=easy-invoice-reports'),
370 'pro_class' => 'EasyInvoicePro\\Addons\\Reports\\Reports',
371 ],
372
373 ]);
374 }
375
376 /**
377 * IDs of every addon that wraps a previously-monolithic Pro feature.
378 * Used by ProAddonMigration to know which flags to set for existing
379 * Pro installs (so their currently-active features keep working) and
380 * to leave disabled for fresh installs.
381 *
382 * @return array<int,string>
383 */
384 public static function migratedProAddonIds(): array {
385 return [
386 'recurring_invoices',
387 'partial_payments',
388 'client_portal',
389 'pdf_toolkit',
390 'bulk_operations',
391 'item_library',
392 'custom_templates',
393 'additional_tax',
394 'email_enhancements',
395 'privacy_tools',
396 // Reports was previously gated only by easy_invoice_has_pro();
397 // any Pro install was using it. The migration falls through
398 // to isExistingProInstall() for this id, so existing Pro
399 // sites keep Reports active after the addon-ization migration.
400 'reports',
401 // Secure Links was always-loaded Pro infrastructure
402 // gated only by easy_invoice_pro_enable_secure_links.
403 // Migration auto-enables the addon when that legacy
404 // option was 'yes' so signed URLs already in the wild
405 // (emails, shortcodes) keep resolving.
406 'secure_links',
407 ];
408 }
409
410 /**
411 * Find a single addon definition by id.
412 *
413 * @return array<string,mixed>|null
414 */
415 public static function find(string $id): ?array {
416 foreach (self::all() as $addon) {
417 if ($addon['id'] === $id) {
418 return $addon;
419 }
420 }
421 return null;
422 }
423
424 /**
425 * Distinct categories present in the registry — drives the filter chips in the UI.
426 *
427 * @return array<int,string>
428 */
429 public static function categories(): array {
430 $cats = [];
431 foreach (self::all() as $addon) {
432 $cats[$addon['category']] = true;
433 }
434 return array_keys($cats);
435 }
436 }
437