PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.1.2
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.1.2
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 / Forms / Invoice / InvoiceFieldRegistration.php

InvoiceFieldRegistration.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.1.2, at includes/Forms/Invoice/InvoiceFieldRegistration.php

657 lines 25.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Invoice Field Registration Class
4 *
5 * @package EasyInvoice
6 * @author Your Name
7 * @copyright Copyright (c) 2023, Your Company
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 */
11
12 namespace EasyInvoice\Forms\Invoice;
13
14 use EasyInvoice\Forms\BaseFieldRegistration;
15
16 /**
17 * Invoice Field Registration
18 *
19 * Handles registration of invoice-specific form fields, tabs, and templates.
20 *
21 * @since 1.0.0
22 */
23 class InvoiceFieldRegistration extends BaseFieldRegistration {
24
25 /**
26 * Register default tabs
27 *
28 * @since 1.0.0
29 * @return void
30 */
31 public function registerDefaultTabs(): void {
32 // Define all tabs in a single array for easy modification by pro plugins
33 $all_tabs = $this->getDefaultTabsArray();
34
35 // Apply filter to allow pro plugins to modify tabs
36 $all_tabs = apply_filters('easy_invoice_invoice_form_tabs', $all_tabs);
37
38 // Register all tabs from the array
39 foreach ($all_tabs as $tab_id => $tab_config) {
40 $this->registerTab($tab_id, $tab_config);
41 }
42 }
43
44 /**
45 * Get default tabs array
46 *
47 * @since 1.0.0
48 * @return array
49 */
50 private function getDefaultTabsArray(): array {
51 return [
52 'invoice-tab' => [
53 'label' => __('Invoice Details', 'easy-invoice'),
54 'icon' => 'fas fa-file-invoice',
55 'active' => true,
56 'order' => 1
57 ],
58 'items-tab' => [
59 'label' => __('Items', 'easy-invoice'),
60 'icon' => 'fas fa-list',
61 'active' => false,
62 'order' => 2
63 ],
64 'client-tab' => [
65 'label' => __('Client', 'easy-invoice'),
66 'icon' => 'fas fa-user',
67 'active' => false,
68 'order' => 3
69 ],
70 'discounts-taxes-tab' => [
71 'label' => __('Discounts & Taxes', 'easy-invoice'),
72 'icon' => 'fas fa-percentage',
73 'active' => false,
74 'order' => 4
75 ],
76 'payments-tab' => [
77 'label' => __('Payment', 'easy-invoice'),
78 'icon' => 'fas fa-credit-card',
79 'active' => false,
80 'order' => 5
81 ]
82 ];
83 }
84
85 /**
86 * Register default fields
87 *
88 * @since 1.0.0
89 * @return void
90 */
91 public function registerDefaultFields(): void {
92 // Define all fields in a single array for easy modification by pro plugins
93 $all_fields = $this->getDefaultFieldsArray();
94
95 // Apply filter to allow pro plugins to modify fields
96 $all_fields = apply_filters('easy_invoice_invoice_fields', $all_fields);
97
98 // Register all fields from the array
99 foreach ($all_fields as $field_config) {
100 $this->registerField($field_config['tab_id'], $field_config);
101 }
102 }
103
104 /**
105 * Get default fields array
106 *
107 * @since 1.0.0
108 * @return array
109 */
110 private function getDefaultFieldsArray(): array {
111 return [
112 // Invoice Tab Fields
113 [
114 'tab_id' => 'invoice-tab',
115 'name' => 'invoice_template',
116 'type' => 'hidden',
117 'label' => __('Invoice Template', 'easy-invoice'),
118 'required' => false,
119 'grid_cols' => 'sm:col-span-6',
120 'order' => 0,
121 'default_value' => 'standard',
122 'sanitize_callback' => 'sanitize_text_field',
123 'validate_callback' => function($value) {
124 return !empty(trim($value)) ? true : __('Invoice template is required.', 'easy-invoice');
125 }
126 ],
127 [
128 'tab_id' => 'invoice-tab',
129 'name' => 'title',
130 'type' => 'text',
131 'label' => __('Invoice Title', 'easy-invoice'),
132 'placeholder' => __('Enter invoice title', 'easy-invoice'),
133 'required' => true,
134 'grid_cols' => 'sm:col-span-6',
135 'order' => 1,
136 'sanitize_callback' => 'sanitize_text_field',
137 'validate_callback' => function($value) {
138 return !empty(trim($value)) ? true : __('Invoice title is required.', 'easy-invoice');
139 }
140 ],
141 [
142 'tab_id' => 'invoice-tab',
143 'name' => 'description',
144 'type' => 'textarea',
145 'label' => __('Invoice Description', 'easy-invoice'),
146 'placeholder' => __('Enter invoice description or additional details', 'easy-invoice'),
147 'required' => false,
148 'grid_cols' => 'sm:col-span-6',
149 'rows' => 3,
150 'order' => 2,
151 'description' => __('Optional description or additional details about this invoice.', 'easy-invoice'),
152 'sanitize_callback' => 'sanitize_textarea_field',
153 ],
154 [
155 'tab_id' => 'invoice-tab',
156 'name' => 'number',
157 'type' => 'text',
158 'label' => __('Invoice Number', 'easy-invoice'),
159 'placeholder' => __('INV-001', 'easy-invoice'),
160 'required' => true,
161 'readonly' => true,
162 'description' => __('This is the unique number for your invoice. It cannot be changed.', 'easy-invoice'),
163 'grid_cols' => 'sm:col-span-3',
164 'order' => 3,
165 'default_value' => function() {
166 // For new invoices, show the next number without incrementing
167 // For existing invoices, this will be overridden by the invoice object's getNumber() method
168 if (class_exists('\\EasyInvoice\\Services\\InvoiceNumberService')) {
169 $service = new \EasyInvoice\Services\InvoiceNumberService();
170 return $service->getNextNumber();
171 }
172 return 'INV-' . str_pad(time(), 6, '0', STR_PAD_LEFT);
173 },
174 'sanitize_callback' => 'sanitize_text_field',
175 'validate_callback' => function($value) {
176 return !empty(trim($value)) ? true : __('Invoice number is required.', 'easy-invoice');
177 }
178 ],
179 [
180 'tab_id' => 'invoice-tab',
181 'name' => 'issue_date',
182 'type' => 'date',
183 'label' => __('Issue Date', 'easy-invoice'),
184 'required' => true,
185 'grid_cols' => 'sm:col-span-3',
186 'order' => 4,
187 'sanitize_callback' => 'sanitize_text_field',
188 'validate_callback' => function($value) {
189 return !empty($value) && strtotime($value) ? true : __('Please enter a valid issue date.', 'easy-invoice');
190 }
191 ],
192 [
193 'tab_id' => 'invoice-tab',
194 'name' => 'due_date',
195 'type' => 'date',
196 'label' => __('Due Date', 'easy-invoice'),
197 'required' => true,
198 'grid_cols' => 'sm:col-span-3',
199 'order' => 5,
200 'sanitize_callback' => 'sanitize_text_field',
201 'validate_callback' => function($value) {
202 return !empty($value) && strtotime($value) ? true : __('Please enter a valid due date.', 'easy-invoice');
203 }
204 ],
205 [
206 'tab_id' => 'invoice-tab',
207 'name' => 'status',
208 'type' => 'select',
209 'label' => __('Status', 'easy-invoice'),
210 'required' => true,
211 'grid_cols' => 'sm:col-span-3',
212 'options' => [
213 'available' => __('Available', 'easy-invoice'),
214 'draft' => __('Draft', 'easy-invoice'),
215 'overdue' => __('Overdue', 'easy-invoice'),
216 'paid' => __('Paid', 'easy-invoice'),
217 'unpaid' => __('Unpaid', 'easy-invoice'),
218 'cancelled' => __('Cancelled', 'easy-invoice')
219 ],
220 'order' => 6
221 ],
222 [
223 'tab_id' => 'invoice-tab',
224 'name' => 'notes',
225 'type' => 'textarea',
226 'label' => __('Notes', 'easy-invoice'),
227 'placeholder' => __('Additional notes for the client', 'easy-invoice'),
228 'grid_cols' => 'sm:col-span-6',
229 'rows' => 3,
230 'section' => 'notes',
231 'order' => 6,
232 'description' => __('These notes will be visible to your client on the invoice.', 'easy-invoice'),
233 ],
234 [
235 'tab_id' => 'invoice-tab',
236 'name' => 'internal_notes',
237 'type' => 'textarea',
238 'label' => __('Internal Notes', 'easy-invoice'),
239 'placeholder' => __('Internal notes (not visible to client)', 'easy-invoice'),
240 'grid_cols' => 'sm:col-span-6',
241 'rows' => 3,
242 'section' => 'notes',
243 'order' => 7,
244 'description' => __('Only you and your team can see these notes. Clients will not see them.', 'easy-invoice'),
245 ],
246 [
247 'tab_id' => 'invoice-tab',
248 'name' => 'terms',
249 'type' => 'textarea',
250 'label' => __('Payment Terms', 'easy-invoice'),
251 'placeholder' => __('Payment terms and conditions', 'easy-invoice'),
252 'grid_cols' => 'sm:col-span-6',
253 'rows' => 3,
254 'section' => 'notes',
255 'order' => 8,
256 'default_value' => function() {
257 return \EasyInvoice\Controllers\SettingsController::getInvoiceTermsConditions();
258 },
259 'description' => __('Specify the payment terms and conditions for this invoice.', 'easy-invoice'),
260 ],
261
262
263 // Client Tab Fields
264 [
265 'tab_id' => 'client-tab',
266 'name' => 'client_id',
267 'type' => 'select',
268 'label' => __('Select Client', 'easy-invoice'),
269 'required' => false,
270 'grid_cols' => 'sm:col-span-6',
271 'options' => $this->getClientOptions(),
272 'order' => 1,
273 'description' => __('Choose an existing client or add a new one.', 'easy-invoice'),
274 ],
275
276 // Discounts & Taxes Tab Fields
277 [
278 'tab_id' => 'discounts-taxes-tab',
279 'name' => 'discount_type',
280 'type' => 'select',
281 'label' => __('Discount Type', 'easy-invoice'),
282 'grid_cols' => 'sm:col-span-2',
283 'section' => 'discount',
284 'options' => [
285 'none' => __('No Discount', 'easy-invoice'),
286 'percentage' => __('Percentage', 'easy-invoice'),
287 'fixed' => __('Fixed Amount', 'easy-invoice')
288 ],
289 'order' => 1,
290 'description' => __('Choose how the discount should be applied to this invoice.', 'easy-invoice'),
291 ],
292 [
293 'tab_id' => 'discounts-taxes-tab',
294 'name' => 'discount_value',
295 'type' => 'number',
296 'label' => __('Discount Value', 'easy-invoice'),
297 'placeholder' => '0.00',
298 'grid_cols' => 'sm:col-span-2',
299 'section' => 'discount',
300 'min' => '0',
301 'step' => '0.01',
302 'order' => 2,
303 'sanitize_callback' => 'floatval',
304 'validate_callback' => function($value) {
305 return is_numeric($value) && $value >= 0 ? true : __('Discount value must be a non-negative number.', 'easy-invoice');
306 },
307 'description' => __('Enter the discount amount or percentage for this invoice.', 'easy-invoice'),
308 ],
309 [
310 'tab_id' => 'discounts-taxes-tab',
311 'name' => 'discount_calculation_method',
312 'type' => 'select',
313 'label' => __('Calculation Method', 'easy-invoice'),
314 'grid_cols' => 'sm:col-span-2',
315 'section' => 'tax',
316 'options' => [
317 'before_tax' => __('Before Tax', 'easy-invoice'),
318 'after_tax' => __('After Tax', 'easy-invoice')
319 ],
320 'order' => 3,
321 'description' => __('Apply discount before tax (reduces taxable amount) or after tax (tax on full amount)', 'easy-invoice'),
322 ],
323 [
324 'tab_id' => 'discounts-taxes-tab',
325 'name' => 'tax_rate',
326 'type' => 'number',
327 'label' => __('Tax Rate (%)', 'easy-invoice'),
328 'placeholder' => '0.00',
329 'grid_cols' => 'sm:col-span-3',
330 'section' => 'tax',
331 'min' => '0',
332 'max' => '100',
333 'step' => '0.01',
334 'order' => 4,
335 'default_value' => function() {
336 return easy_invoice_get_tax_rate();
337 },
338 'sanitize_callback' => 'floatval',
339 'validate_callback' => function($value) {
340 return is_numeric($value) && $value >= 0 && $value <= 100 ? true : __('Tax rate must be between 0 and 100.', 'easy-invoice');
341 },
342 'description' => __('The tax rate that will be applied to taxable items in this invoice.', 'easy-invoice'),
343 ],
344
345 [
346 'tab_id' => 'discounts-taxes-tab',
347 'name' => 'prices_include_tax',
348 'type' => 'select',
349 'label' => __('Price Includes Tax', 'easy-invoice'),
350 'grid_cols' => 'sm:col-span-3',
351 'section' => 'tax',
352 'options' => [
353 'no' => __('No', 'easy-invoice'),
354 'yes' => __('Yes', 'easy-invoice')
355 ],
356 'order' => 4,
357 'description' => __('Choose whether the prices in this invoice include tax or not.', 'easy-invoice'),
358 ],
359
360 // Payments Tab Fields
361 [
362 'tab_id' => 'payments-tab',
363 'name' => 'payment_gateways',
364 'type' => 'payment_gateways',
365 'label' => __('Payment Gateways', 'easy-invoice'),
366 'grid_cols' => 'sm:col-span-12',
367 'section' => 'payment',
368 'order' => 1
369 ],
370 [
371 'tab_id' => 'payments-tab',
372 'name' => 'payment_gateways_toggle_state',
373 'type' => 'hidden',
374 'label' => __('Payment Gateways Toggle State', 'easy-invoice'),
375 'default_value' => '0',
376 'section' => 'payment',
377 'order' => 2
378 ],
379
380 // Currency Section in Payment Tab
381 [
382 'tab_id' => 'payments-tab',
383 'name' => 'currency_code',
384 'type' => 'select',
385 'label' => __('Currency', 'easy-invoice'),
386 'grid_cols' => 'sm:col-span-3',
387 'section' => 'currency',
388 'options' => array_merge(
389 ['global' => __('Use from Global Settings', 'easy-invoice')],
390 \EasyInvoice\Helpers\CurrencyHelper::getCurrencyOptions()
391 ),
392 'default_value' => 'global',
393 'order' => 2,
394 'description' => __('Select the currency for this invoice or use global settings.', 'easy-invoice'),
395 ],
396 [
397 'tab_id' => 'payments-tab',
398 'name' => 'currency_position',
399 'type' => 'select',
400 'label' => __('Currency Symbol Position', 'easy-invoice'),
401 'grid_cols' => 'sm:col-span-3',
402 'section' => 'currency',
403 'options' => [
404 'global' => __('Use from Global Settings', 'easy-invoice'),
405 'before' => __('Before Amount', 'easy-invoice'),
406 'after' => __('After Amount', 'easy-invoice'),
407 ],
408 'default_value' => 'global',
409 'order' => 3,
410 'description' => __('Choose where to display the currency symbol or use global setting.', 'easy-invoice'),
411 ],
412 ];
413 }
414
415 /**
416 * Register default templates
417 *
418 * @since 1.0.0
419 * @return void
420 */
421 public function registerDefaultTemplates(): void {
422 // Define all templates in a single array for easy modification by pro plugins
423 $all_templates = $this->getDefaultTemplatesArray();
424
425 // Apply filter to allow pro plugins to modify templates
426 $all_templates = apply_filters('easy_invoice_invoice_templates', $all_templates);
427
428 // Register all templates from the array
429 foreach ($all_templates as $template_id => $template_config) {
430 $this->registerTemplate($template_id, $template_config);
431 }
432 }
433
434 /**
435 * Get default templates array
436 *
437 * @since 1.0.0
438 * @return array
439 */
440 private function getDefaultTemplatesArray(): array {
441 // Check if this is the free version (no pro plugin active)
442 $is_free_version = !easy_invoice_has_pro();
443
444 return [
445 'standard' => [
446 'name' => __('Standard', 'easy-invoice'),
447 'icon' => 'fas fa-file-invoice',
448 'description' => __('Clean and professional standard template', 'easy-invoice'),
449 'order' => 1,
450 'is_free' => true
451 ],
452 'legacy' => [
453 'name' => __('Legacy', 'easy-invoice'),
454 'icon' => 'fas fa-file-alt',
455 'description' => __('Clean, minimalist design with traditional business layout', 'easy-invoice'),
456 'order' => 2,
457 'is_free' => true
458 ],
459 'professional' => [
460 'name' => __('Professional', 'easy-invoice'),
461 'icon' => 'fas fa-briefcase',
462 'description' => __('Professional business template with modern design', 'easy-invoice'),
463 'order' => 3,
464 'is_free' => !$is_free_version
465 ],
466 'modern' => [
467 'name' => __('Modern', 'easy-invoice'),
468 'icon' => 'fas fa-rocket',
469 'description' => __('Modern and sleek design template', 'easy-invoice'),
470 'order' => 4,
471 'is_free' => !$is_free_version
472 ]
473 ];
474 }
475
476 /**
477 * Register default item fields
478 *
479 * @since 1.0.0
480 * @return void
481 */
482 public function registerDefaultItemFields(): void {
483 // Define all item fields in a single array for easy modification by pro plugins
484 $all_item_fields = $this->getDefaultItemFieldsArray();
485
486 // Apply filter to allow pro plugins to modify item fields
487 $all_item_fields = apply_filters('easy_invoice_invoice_item_fields', $all_item_fields);
488
489 // Register all item fields from the array
490 foreach ($all_item_fields as $field_config) {
491 $this->registerItemField($field_config);
492 }
493 }
494
495 /**
496 * Get default item fields array
497 *
498 * @since 1.0.0
499 * @return array
500 */
501 private function getDefaultItemFieldsArray(): array {
502 $fields = [
503 [
504 'name' => 'title',
505 'type' => 'text',
506 'label' => __('Item Title', 'easy-invoice'),
507 'placeholder' => __('Enter item title', 'easy-invoice'),
508 'required' => true,
509 'container_class' => 'sm:col-span-6',
510 'order' => 1,
511 'description' => __('A short name for this item (e.g. Service Fee, Product Name).', 'easy-invoice'),
512 ],
513 [
514 'name' => 'description',
515 'type' => 'textarea',
516 'label' => __('Description', 'easy-invoice'),
517 'placeholder' => __('Enter item description', 'easy-invoice'),
518 'container_class' => 'sm:col-span-6',
519 'rows' => 3,
520 'order' => 2,
521 'description' => __('Details about this item for your client.', 'easy-invoice'),
522 ],
523 [
524 'name' => 'quantity',
525 'type' => 'number',
526 'label' => __('Quantity', 'easy-invoice'),
527 'placeholder' => '1',
528 'required' => true,
529 'container_class' => 'sm:col-span-1',
530 'min' => '0',
531 'step' => '0.01',
532 'default_value' => '1',
533 'order' => 3,
534 'description' => __('How many units of this item are being billed?', 'easy-invoice'),
535 ],
536 [
537 'name' => 'price',
538 'type' => 'number',
539 'label' => __('Price', 'easy-invoice'),
540 'placeholder' => '0.00',
541 'required' => true,
542 'container_class' => 'sm:col-span-1',
543 'min' => '0',
544 'step' => '0.01',
545 'default_value' => '0.00',
546 'order' => 4,
547 'description' => __('Unit price for this item.', 'easy-invoice'),
548 ]
549 ];
550
551 // Add adjust field only if setting allows it
552 if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()) {
553 $fields[] = [
554 'name' => 'adjust_percentage',
555 'type' => 'number',
556 'label' => __('Adjust (%)', 'easy-invoice'),
557 'placeholder' => '0.00',
558 'container_class' => 'sm:col-span-1',
559 'min' => '-100',
560 'max' => '1000',
561 'step' => '0.01',
562 'default_value' => '0.00',
563 'order' => 5,
564 'description' => __('Percentage adjustment to apply to this item (positive for markup, negative for discount).', 'easy-invoice'),
565 ];
566 }
567
568 // Add total field
569 $fields[] = [
570 'name' => 'total',
571 'type' => 'number',
572 'label' => __('Total', 'easy-invoice'),
573 'placeholder' => '0.00',
574 'container_class' => 'sm:col-span-1',
575 'min' => '0',
576 'step' => '0.01',
577 'default_value' => '0.00',
578 'readonly' => true,
579 'order' => \EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField() ? 6 : 5,
580 'description' => __('Total amount for this item (Quantity x Price) with adjustment applied.', 'easy-invoice'),
581 ];
582
583 // Add taxable field
584 $fields[] = [
585 'name' => 'taxable',
586 'type' => 'checkbox',
587 'label' => __('Taxable', 'easy-invoice'),
588 'container_class' => 'sm:col-span-6',
589 'default_value' => '1',
590 'order' => \EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField() ? 7 : 6,
591 'description' => __('Check if this item is subject to tax.', 'easy-invoice'),
592 ];
593
594 return $fields;
595 }
596
597 /**
598 * Get client options for select field
599 *
600 * @since 1.0.0
601 * @return array
602 */
603 private function getClientOptions(): array {
604 $options = ['' => __('Select a client', 'easy-invoice')];
605
606 // Get clients from repository
607 $client_repository = new \EasyInvoice\Repositories\ClientRepository();
608 $clients = $client_repository->all();
609
610 foreach ($clients as $client) {
611 $client_name = $client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName());
612 $options[$client->getId()] = $client_name;
613 }
614
615 return $options;
616 }
617
618 /**
619 * Get the filter name for tabs
620 *
621 * @since 1.0.0
622 * @return string
623 */
624 protected function getTabFilterName(): string {
625 return 'easy_invoice_invoice_register_tab';
626 }
627
628 /**
629 * Get the filter name for fields
630 *
631 * @since 1.0.0
632 * @return string
633 */
634 protected function getFieldFilterName(): string {
635 return 'easy_invoice_invoice_register_field';
636 }
637
638 /**
639 * Get the filter name for templates
640 *
641 * @since 1.0.0
642 * @return string
643 */
644 protected function getTemplateFilterName(): string {
645 return 'easy_invoice_invoice_register_template';
646 }
647
648 /**
649 * Get the filter name for item fields
650 *
651 * @since 1.0.0
652 * @return string
653 */
654 protected function getItemFieldFilterName(): string {
655 return 'easy_invoice_invoice_register_item_field';
656 }
657 }