PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
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.4.0, at includes/Addons/AddonRegistry.php

546 lines 39.0 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 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=client_portal'),
199 'pro_class' => 'EasyInvoicePro\\Addons\\ClientPortal\\ClientPortal',
200 ],
201 [
202 'id' => 'pdf_toolkit',
203 'name' => __('PDF Toolkit', 'easy-invoice'),
204 'short_name' => __('PDF Toolkit', 'easy-invoice'),
205 'tagline' => __('Stamp your invoices and quotes with a custom watermark.', 'easy-invoice'),
206 // Describes what the addon actually offers. It previously advertised
207 // "custom headers and footers" and "color and font controls": those are
208 // not implemented and not exposed anywhere in its settings. The handlers
209 // for them hang off six `easy_invoice_pdf_*` filters that nothing in
210 // either plugin ever fires, because PDFs are rendered in the browser
211 // from the document view rather than by a server-side pipeline there
212 // would be something to hook. Headers, footers and font control need
213 // that server-side renderer first. The watermark is real: it is drawn
214 // into the document view, which is what the PDF is rasterised from.
215 'description' => __('Watermark your invoices and quotes — text or image, with control over the wording, colour, size and opacity. Use it to stamp PAID, DRAFT, OVERDUE or VOID across a document, or to drop your logo behind the content.', 'easy-invoice'),
216 'plan' => LicensePlanResolver::PLAN_PERSONAL,
217 'icon' => 'dashicons-pdf',
218 'category' => 'branding',
219 'badge' => null,
220 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/pdf-toolkit/',
221 // PdfCustomizationSettingsController appends fields to the
222 // main Settings page via filter; no dedicated slug. Empty
223 // settings_url hides the misleading "Settings →" link.
224 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=invoice'),
225 'pro_class' => 'EasyInvoicePro\\Addons\\PdfToolkit\\PdfToolkit',
226 ],
227 [
228 'id' => 'bulk_operations',
229 'name' => __('Bulk Email & Export', 'easy-invoice'),
230 'short_name' => __('Bulk Ops', 'easy-invoice'),
231 'tagline' => __('Send and export hundreds of invoices in a single click.', 'easy-invoice'),
232 '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'),
233 'plan' => LicensePlanResolver::PLAN_PERSONAL,
234 'icon' => 'dashicons-download',
235 'category' => 'productivity',
236 'badge' => null,
237 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/bulk-operations/',
238 // The addon does own a screen — Export Data. Leaving this empty meant
239 // the Addons card offered no way into it, and, more importantly, the
240 // admin dispatcher uses this list to recognise addon-owned slugs: with
241 // no entry it fell through and painted the Dashboard, then the export
242 // form rendered underneath it (the "two pages stacked" case the
243 // dispatcher's default branch warns about).
244 'settings_url' => admin_url('admin.php?page=easy-invoice-export'),
245 'pro_class' => 'EasyInvoicePro\\Addons\\BulkOperations\\BulkOperations',
246 ],
247 [
248 'id' => 'item_library',
249 'name' => __('Item Library', 'easy-invoice'),
250 'short_name' => __('Item Library', 'easy-invoice'),
251 'tagline' => __('Build a reusable catalog of services and products.', 'easy-invoice'),
252 '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'),
253 'plan' => LicensePlanResolver::PLAN_PERSONAL,
254 'icon' => 'dashicons-products',
255 'category' => 'productivity',
256 'badge' => null,
257 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/item-library/',
258 // Verified slug: ItemLibraryController::addAdminMenu()
259 // registers 'easy-invoice-pro-item-library'.
260 'settings_url' => admin_url('admin.php?page=easy-invoice-pro-item-library'),
261 'pro_class' => 'EasyInvoicePro\\Addons\\ItemLibrary\\ItemLibrary',
262 ],
263 [
264 'id' => 'custom_templates',
265 'name' => __('Custom Invoice & Quote Templates', 'easy-invoice'),
266 'short_name' => __('Templates', 'easy-invoice'),
267 'tagline' => __('Design pixel-perfect invoice and quote layouts with a drag-and-drop builder.', 'easy-invoice'),
268 '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'),
269 'plan' => LicensePlanResolver::PLAN_PERSONAL,
270 'icon' => 'dashicons-layout',
271 'category' => 'branding',
272 'badge' => null,
273 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/custom-templates/',
274 // Verified slug: TemplateBuilderController registers
275 // 'easy-invoice-templates' (the listing) — that's the
276 // canonical entry point. settings_url here is used by
277 // the per-addon sidebar loop in main-template.php to
278 // render a sidebar entry BELOW the Addons menu. The
279 // addons-page.php card does NOT render a "Settings →"
280 // link anymore (the sidebar is the navigation).
281 'settings_url' => admin_url('admin.php?page=easy-invoice-templates'),
282 'pro_class' => 'EasyInvoicePro\\Addons\\CustomTemplates\\CustomTemplates',
283 ],
284 [
285 'id' => 'additional_tax',
286 'name' => __('Additional Tax Lines', 'easy-invoice'),
287 'short_name' => __('Additional Tax', 'easy-invoice'),
288 'tagline' => __('Multiple tax lines per invoice — VAT + duty, GST + PST, federal + state.', 'easy-invoice'),
289 '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'),
290 'plan' => LicensePlanResolver::PLAN_PERSONAL,
291 'icon' => 'dashicons-chart-bar',
292 'category' => 'billing',
293 'badge' => null,
294 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/additional-tax/',
295 // AdditionalTax extension appends "Enable Additional Tax"
296 // + per-tax-rate fields via the main Settings page; no
297 // dedicated slug → empty settings_url hides the
298 // misleading "Settings →" link.
299 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=tax'),
300 'pro_class' => 'EasyInvoicePro\\Addons\\AdditionalTax\\AdditionalTax',
301 ],
302 [
303 'id' => 'email_enhancements',
304 'name' => __('Email Enhancements', 'easy-invoice'),
305 'short_name' => __('Email Tools', 'easy-invoice'),
306 'tagline' => __('Your own email layout, and a Reply-To per kind of email.', 'easy-invoice'),
307 'description' => __('Wrap every email Easy Invoice sends in your own HTML layout, and route replies by kind — invoice questions to accounts, quote replies to sales, receipts and reminders wherever they belong.', 'easy-invoice'),
308 'plan' => LicensePlanResolver::PLAN_PERSONAL,
309 'icon' => 'dashicons-email',
310 'category' => 'productivity',
311 'badge' => null,
312 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/email-enhancements/',
313 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-email-enhancements'),
314 'pro_class' => 'EasyInvoicePro\\Addons\\EmailEnhancements\\EmailEnhancements',
315 ],
316 [
317 'id' => 'secure_links',
318 'name' => __('Secure Links for Invoices & Quotes', 'easy-invoice'),
319 'short_name' => __('Secure Links', 'easy-invoice'),
320 'tagline' => __('Share invoices and quotes with unguessable, signed URLs instead of plain post slugs.', 'easy-invoice'),
321 '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'),
322 'plan' => LicensePlanResolver::PLAN_PERSONAL,
323 'icon' => 'dashicons-lock',
324 'category' => 'compliance',
325 'badge' => null,
326 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/secure-links/',
327 // Settings live inside Settings → Advanced, injected
328 // by SecureLinks::registerAdvancedFields() (the same
329 // pattern Payment Reminder uses for the Email tab).
330 // The toggle there stays in lock-step with the
331 // addon-enabled state via the addon's
332 // update_option_* hooks.
333 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&section=advanced'),
334 'pro_class' => 'EasyInvoicePro\\Addons\\SecureLinks\\SecureLinks',
335 ],
336 [
337 'id' => 'privacy_tools',
338 'name' => __('Privacy & GDPR', 'easy-invoice'),
339 'short_name' => __('Privacy', 'easy-invoice'),
340 'tagline' => __('Comply with GDPR, CCPA, and other data-protection laws in one click.', 'easy-invoice'),
341 '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'),
342 'plan' => LicensePlanResolver::PLAN_PERSONAL,
343 'icon' => 'dashicons-shield',
344 'category' => 'compliance',
345 'badge' => null,
346 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/privacy-tools/',
347 // The privacy_tools addon hooks WordPress's built-in
348 // personal-data exporter / eraser registries — those
349 // registries are managed by WP core under
350 // Tools → Export/Erase Personal Data (a WP-native page,
351 // not our UI). There is no addon-specific settings page
352 // to surface from the addons grid, so leave settings_url
353 // empty — the addon card just shows Active/Inactive.
354 'settings_url' => '',
355 'pro_class' => 'EasyInvoicePro\\Addons\\PrivacyTools\\PrivacyTools',
356 ],
357 [
358 'id' => 'einvoicing',
359 'name' => __('E-Invoicing (Factur-X / ZUGFeRD / Peppol UBL)', 'easy-invoice'),
360 'short_name' => __('E-Invoicing', 'easy-invoice'),
361 'tagline' => __('Issue and read the structured invoices now required across the EU.', 'easy-invoice'),
362 'description' => __('Turn any invoice into Factur-X — a PDF your client can read with the EN 16931 machine-readable document carried inside it — or into Peppol BIS 3.0 UBL, which is what Belgium, the Netherlands and the Peppol network run on. Your customer\'s country decides which. Also opens incoming Factur-X, ZUGFeRD, CII and UBL invoices from your suppliers, which is the obligation that lands first: France requires every VAT-registered business to receive structured invoices from September 2026, Germany has since 2025. Produces the compliant file; sending stays with your own Peppol, KSeF or PDP provider.', 'easy-invoice'),
363 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
364 'icon' => 'dashicons-media-code',
365 'category' => 'compliance',
366 'badge' => 'new',
367 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/e-invoicing/',
368 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-einvoicing'),
369 'pro_class' => 'EasyInvoicePro\\Addons\\EInvoicing\\EInvoicing',
370 ],
371 [
372 'id' => 'client_language',
373 'name' => __('Client Language', 'easy-invoice'),
374 // Sidebar label: the page it opens is the Translations screen.
375 'short_name' => __('Translations', 'easy-invoice'),
376 'tagline' => __('Each client gets invoices, PDFs and emails in their own language.', 'easy-invoice'),
377 'description' => __('Set a language on the client record and every document for that client — the public page, the PDF, the emails — is produced in it, using the WordPress language pack and the per-language wording from the Translations screen. Invoice French, German and Italian clients from one site without three sites.', 'easy-invoice'),
378 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
379 'icon' => 'dashicons-translation',
380 'category' => 'clients',
381 'badge' => 'new',
382 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/client-language/',
383 // The language is chosen on each client's record; the wording
384 // per language lives on the Translations screen — that is the
385 // one place this addon has settings of its own.
386 'settings_url' => admin_url('admin.php?page=easy-invoice-pro-translations'),
387 'settings_label' => __('Translations', 'easy-invoice'),
388 'pro_class' => 'EasyInvoicePro\\Addons\\ClientLanguage\\ClientLanguage',
389 ],
390 [
391 'id' => 'retainers',
392 'name' => __('Retainers & Prepaid Credit', 'easy-invoice'),
393 'short_name' => __('Retainers', 'easy-invoice'),
394 'tagline' => __('Record a prepayment once; let invoices draw it down.', 'easy-invoice'),
395 'description' => __('A monthly block of hours, a deposit that covers several small jobs, a negotiated prepayment: record it against the client and apply it to invoices as they come, by hand from the client record or automatically the moment an invoice is issued. Applied credit is an ordinary payment, so statements, reports and accounting sync all see money received, and the balance is always on the client record.', 'easy-invoice'),
396 'plan' => LicensePlanResolver::PLAN_PROFESSIONAL,
397 'icon' => 'dashicons-vault',
398 'category' => 'billing',
399 'badge' => 'new',
400 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/retainers/',
401 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&tab=invoice'),
402 'pro_class' => 'EasyInvoicePro\\Addons\\Retainers\\Retainers',
403 ],
404 [
405 'id' => 'payment_links',
406 'name' => __('Payment Links & QR Codes', 'easy-invoice'),
407 'short_name' => __('Payment Links', 'easy-invoice'),
408 'tagline' => __('Get paid from a link or a QR code — no invoice needed first.', 'easy-invoice'),
409 'description' => __('Create a link for a fixed amount, or one where the payer enters the amount, and share it anywhere: an email signature, a social post, a printed QR code at the counter. The payer types their name and email, an invoice is created for them on the spot, and they pay it with any of your gateways — so receipts, the client record, reports and accounting sync all just work. Every link shows what it has collected.', 'easy-invoice'),
410 'plan' => LicensePlanResolver::PLAN_PERSONAL,
411 'icon' => 'dashicons-admin-links',
412 'category' => 'billing',
413 'badge' => 'new',
414 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/payment-links/',
415 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-payment-links'),
416 'pro_class' => 'EasyInvoicePro\\Addons\\PaymentLinks\\PaymentLinks',
417 ],
418 [
419 'id' => 'quote_signatures',
420 'name' => __('Quote E-Signatures', 'easy-invoice'),
421 'short_name' => __('E-Signatures', 'easy-invoice'),
422 'tagline' => __('Accepted means signed: a drawn signature, name, time and address on every approval.', 'easy-invoice'),
423 'description' => __('When a client accepts a quote they sign it — drawn with a mouse or finger, with their typed name, the time and their connection details recorded. The signature block is printed on the quote, its PDF and any invoice made from it, so an approval is something you can show rather than a click in a log. Required or optional, your choice.', 'easy-invoice'),
424 'plan' => LicensePlanResolver::PLAN_PERSONAL,
425 'icon' => 'dashicons-edit',
426 'category' => 'documents',
427 'badge' => 'new',
428 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/quote-signatures/',
429 'settings_url' => admin_url('admin.php?page=easy-invoice-settings&tab=quote'),
430 'pro_class' => 'EasyInvoicePro\\Addons\\QuoteSignatures\\QuoteSignatures',
431 ],
432 [
433 'id' => 'quote_forms',
434 'name' => __('Quote Request Forms', 'easy-invoice'),
435 'short_name' => __('Quote Forms', 'easy-invoice'),
436 'tagline' => __('A form submission becomes a draft quote, client included.', 'easy-invoice'),
437 'description' => __('Connect WPForms, Gravity Forms, Contact Form 7 or Fluent Forms: when someone submits your quote-request form, the client is found or created from their email and a draft quote opens with what they wrote — and a first line item if the form asks for a service or amount. You price it and send it; nothing is retyped. Any other form can feed it through one action hook.', 'easy-invoice'),
438 'plan' => LicensePlanResolver::PLAN_PERSONAL,
439 'icon' => 'dashicons-feedback',
440 'category' => 'integrations',
441 'badge' => 'new',
442 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/quote-forms/',
443 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-quote-forms'),
444 'pro_class' => 'EasyInvoicePro\\Addons\\QuoteForms\\QuoteForms',
445 ],
446 [
447 'id' => 'woocommerce',
448 'name' => __('WooCommerce Invoicing', 'easy-invoice'),
449 'short_name' => __('WooCommerce', 'easy-invoice'),
450 'tagline' => __('A real invoice for every shop order — and a credit note for every refund.', 'easy-invoice'),
451 'description' => __('Issue an Easy Invoice invoice automatically when a WooCommerce order is paid, mirroring its lines and totals exactly. Refunds become credit notes against the invoice. Customers get an Invoice link in My Account, the order screen shows the invoice with its PDF, and with the E-Invoicing addon every order can be sent as Factur-X or Peppol UBL — which no WooCommerce PDF plugin offers without a further paid extension. Works with High-Performance Order Storage.', 'easy-invoice'),
452 'plan' => LicensePlanResolver::PLAN_PERSONAL,
453 'icon' => 'dashicons-cart',
454 'category' => 'integrations',
455 'badge' => 'new',
456 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/woocommerce/',
457 'settings_url' => admin_url('admin.php?page=easy-invoice-addon-woocommerce'),
458 'pro_class' => 'EasyInvoicePro\\Addons\\WooCommerce\\WooCommerce',
459 ],
460 [
461 'id' => 'reports',
462 'name' => __('Reports & Analytics', 'easy-invoice'),
463 'short_name' => __('Reports', 'easy-invoice'),
464 'tagline' => __('See your revenue, outstanding balances, and best clients at a glance.', 'easy-invoice'),
465 'description' => __('Visual dashboard for invoice revenue, outstanding balances, payment status, and per-client performance, plus a month-by-month profit & loss statement — money received against costs from Expense Tracking, with net and margin. Filter by any date range, export for your accountant, and decide on data instead of guessing.', 'easy-invoice'),
466 'plan' => LicensePlanResolver::PLAN_PERSONAL,
467 'icon' => 'dashicons-chart-line',
468 'category' => 'analytics',
469 'badge' => null,
470 'docs_url' => 'https://easy-invoice.matrixaddons.com/docs/addons/reports/',
471 // ReportController lives in the Free plugin (the class
472 // existed before addonization) but the page is a Pro
473 // feature shown to Free users only as an upsell badge.
474 // Gating its sidebar link + page dispatch on this addon
475 // makes "Reports" opt-in for Pro users too. The slug
476 // 'easy-invoice-reports' is registered as an EI admin
477 // submenu by EasyInvoiceAdmin::registerMenuPages().
478 'settings_url' => admin_url('admin.php?page=easy-invoice-reports'),
479 'pro_class' => 'EasyInvoicePro\\Addons\\Reports\\Reports',
480 ],
481
482 ]);
483 }
484
485 /**
486 * IDs of every addon that wraps a previously-monolithic Pro feature.
487 * Used by ProAddonMigration to know which flags to set for existing
488 * Pro installs (so their currently-active features keep working) and
489 * to leave disabled for fresh installs.
490 *
491 * @return array<int,string>
492 */
493 public static function migratedProAddonIds(): array {
494 return [
495 'recurring_invoices',
496 'partial_payments',
497 'client_portal',
498 'pdf_toolkit',
499 'bulk_operations',
500 'item_library',
501 'custom_templates',
502 'additional_tax',
503 'email_enhancements',
504 'privacy_tools',
505 // Reports was previously gated only by easy_invoice_has_pro();
506 // any Pro install was using it. The migration falls through
507 // to isExistingProInstall() for this id, so existing Pro
508 // sites keep Reports active after the addon-ization migration.
509 'reports',
510 // Secure Links was always-loaded Pro infrastructure
511 // gated only by easy_invoice_pro_enable_secure_links.
512 // Migration auto-enables the addon when that legacy
513 // option was 'yes' so signed URLs already in the wild
514 // (emails, shortcodes) keep resolving.
515 'secure_links',
516 ];
517 }
518
519 /**
520 * Find a single addon definition by id.
521 *
522 * @return array<string,mixed>|null
523 */
524 public static function find(string $id): ?array {
525 foreach (self::all() as $addon) {
526 if ($addon['id'] === $id) {
527 return $addon;
528 }
529 }
530 return null;
531 }
532
533 /**
534 * Distinct categories present in the registry — drives the filter chips in the UI.
535 *
536 * @return array<int,string>
537 */
538 public static function categories(): array {
539 $cats = [];
540 foreach (self::all() as $addon) {
541 $cats[$addon['category']] = true;
542 }
543 return array_keys($cats);
544 }
545 }
546