getFieldConfigForJavaScript(); // Trigger form initialization to allow pro version to register new elements do_action('easy_invoice_form_init'); $tabs = $form_manager->getTabs(); $templates = $form_manager->getTemplates(); // Create a separate array for browse templates modal with all available templates $all_templates = apply_filters('easy_invoice_invoice_templates', [ 'standard' => [ 'name' => __('Standard', 'easy-invoice'), 'icon' => 'fas fa-file-invoice', 'description' => __('Clean and professional standard template', 'easy-invoice'), 'order' => 1, 'is_free' => true ], 'legacy' => [ 'name' => __('Legacy', 'easy-invoice'), 'icon' => 'fas fa-file-alt', 'description' => __('Clean, minimalist design with traditional business layout', 'easy-invoice'), 'order' => 2, 'is_free' => true ], 'professional' => [ 'name' => __('Professional', 'easy-invoice'), 'icon' => 'fas fa-briefcase', 'description' => __('Professional business template with modern design', 'easy-invoice'), 'order' => 3, 'is_free' => false ], 'modern' => [ 'name' => __('Modern', 'easy-invoice'), 'icon' => 'fas fa-rocket', 'description' => __('Modern and sleek design template', 'easy-invoice'), 'order' => 4, 'is_free' => false ], 'classic' => [ 'name' => __('Classic', 'easy-invoice'), 'icon' => 'fas fa-landmark', 'description' => __('Traditional business template', 'easy-invoice'), 'order' => 5, 'is_free' => false ], 'minimal' => [ 'name' => __('Minimal', 'easy-invoice'), 'icon' => 'fas fa-minus', 'description' => __('Simple and clean minimal template', 'easy-invoice'), 'order' => 6, 'is_free' => false ], 'corporate' => [ 'name' => __('Corporate', 'easy-invoice'), 'icon' => 'fas fa-building', 'description' => __('Professional corporate template', 'easy-invoice'), 'order' => 7, 'is_free' => false ], 'elegant' => [ 'name' => __('Elegant', 'easy-invoice'), 'icon' => 'fas fa-gem', 'description' => __('Elegant and sophisticated design', 'easy-invoice'), 'order' => 8, 'is_free' => false ], 'creative' => [ 'name' => __('Creative', 'easy-invoice'), 'icon' => 'fas fa-palette', 'description' => __('Creative and artistic design template', 'easy-invoice'), 'order' => 9, 'is_free' => false ] ]); // Load client data directly in PHP if invoice has a client $client_data = null; if ($invoice && $invoice->getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { $client_data = array( 'id' => $client->getId(), 'name' => $client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName()), 'email' => $client->getEmail() ?: '', 'phone' => $client->getExtraInfo() ?: '', 'company' => $client->getBusinessClientName() ?: '', 'address' => $client->getAddress() ?: '', 'website' => $client->getWebsite() ?: '', ); } } ?>

0): ?>
>

getTemplate() : 'standard'; if (empty($current_template)) { $current_template = 'standard'; } // Always include the hidden input for the template field ?>
= 3) break; if ($template_id !== $current_template && isset($all_templates[$template_id])) { $main_grid_templates[$template_id] = $all_templates[$template_id]; } } // If we still don't have 3 templates, add any remaining templates foreach ($all_templates as $template_id => $template) { if (count($main_grid_templates) >= 3) break; if (!isset($main_grid_templates[$template_id])) { $main_grid_templates[$template_id] = $template; } } // Display the main grid templates foreach ($main_grid_templates as $template_id => $template) : $checked = ($current_template === $template_id) ? 'checked' : ''; $selected_class = ($current_template === $template_id) ? 'selected' : ''; // Check if this template is premium (not free) $is_premium = isset($template['is_free']) && !$template['is_free']; // Add premium overlay classes $premium_classes = ''; if ($is_free_version && $is_premium) { $premium_classes = 'premium-template-blurred'; } ?>
, so assistive tech announced these radios as unnamed. ?> >

getFields('invoice-tab'); foreach ($main_fields as $field): // Skip fields that have a section (like notes) - they're rendered separately // Also skip the template field as it's rendered manually in the template selection section if (!isset($field['section']) && $field['name'] !== 'invoice_template') { echo $form_manager->renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. } endforeach; ?>

getFieldsBySection('invoice-tab', 'recurring'); if (!empty($recurring_fields)): ?>

renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>

getFieldsBySection('invoice-tab', 'subscription'); if (!empty($subscription_fields)): ?>

renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>

getFieldsBySection('invoice-tab', 'notes'); foreach ($notes_fields as $field): echo $form_manager->renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>

getItems()) : $index = 0; foreach ($invoice->getItems() as $item) : // Generate a unique ID for the item $item_id = 'item_' . time() . '_' . $index . '_' . wp_rand(1000, 9999); // Get display title for header using dynamic field access $title = $item->getName(); if (empty($title) && method_exists($item, 'getData')) { $item_data = $item->getData(); if (is_array($item_data) && isset($item_data['title'])) { $title = $item_data['title']; } } /* translators: %d: title. */ $display_title = !empty($title) ? $title : sprintf(__('Item #%d', 'easy-invoice'), $index + 1); $short_title = strlen($display_title) > 30 ? substr($display_title, 0, 30) . '...' : $display_title; ?>

generateExistingItemHtml($item, $index); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- ItemFieldRenderer escapes every value it emits. ?>
getItemFields(); $title_placeholder = ''; foreach ($item_fields as $field) { if ($field['name'] === 'title') { $title_placeholder = $field['placeholder'] ?? __('Item', 'easy-invoice'); break; } } // Try to get the value from POST (if form was submitted and errored) $item_title = isset($_POST['items'][0]['title']) ? trim($_POST['items'][0]['title']) : ''; ?>

generateItemTemplateHtml(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- form markup built by ItemFieldRenderer, which escapes every value. ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName())); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getEmail() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName())); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getBusinessClientName() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getEmail() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getExtraInfo() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getWebsite() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getClientId()) { $client = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository()->find($invoice->getClientId()); if ($client) { echo esc_html($client->getAddress() ?: esc_html__('—', 'easy-invoice')); } else { echo esc_html__('—', 'easy-invoice'); } } else { echo esc_html__('—', 'easy-invoice'); } ?>

getFieldsBySection('discounts-taxes-tab', 'discount'); $tax_fields = $form_manager->getFieldsBySection('discounts-taxes-tab', 'tax'); $additional_tax_fields = $form_manager->getFieldsBySection('discounts-taxes-tab', 'additional_tax'); // Combine and sort by order $all_fields = array_merge($discount_fields, $tax_fields, $additional_tax_fields); usort($all_fields, function($a, $b) { return ($a['order'] ?? 0) - ($b['order'] ?? 0); }); foreach ($all_fields as $field): echo $form_manager->renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>

getFieldsBySection('payments-tab', 'payment'); foreach ($payment_fields as $field): echo $form_manager->renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>

getFieldsBySection('payments-tab', 'currency'); foreach ($currency_fields as $field): echo $form_manager->renderField($field, $invoice); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- FieldRenderer escapes every attribute and label it emits. endforeach; ?>
admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('easy_invoice_nonce'), 'clientData' => $client_data ?: array() )); ?>