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 / Admin / AdminAssets.php

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

487 lines 23.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Assets Class
4 *
5 * @package Easy_Invoice
6 * @subpackage Admin
7 */
8
9 namespace EasyInvoice\Admin;
10
11 use EasyInvoice\Constants\PagesSlugs;
12
13 /**
14 * AdminAssets Class
15 *
16 * Handles registration and enqueuing of admin CSS and JS assets.
17 */
18 class AdminAssets {
19 /**
20 * Register hooks
21 */
22 public function register() {
23 add_action('admin_enqueue_scripts', array($this, 'enqueueAdminAssets'));
24 }
25
26 /**
27 * Enqueue admin assets
28 *
29 * @param string $hook The current admin page
30 */
31 public function enqueueAdminAssets($hook) {
32 // Only load on our plugin pages
33 if (empty($hook) || strpos($hook, 'easy-invoice') === false) {
34 return;
35 }
36
37 // Enqueue styles
38 $this->enqueueStyles();
39
40 // Enqueue scripts
41 $this->enqueueScripts($hook);
42
43 // Localize script data
44 $this->localizeScripts($hook);
45 }
46
47 /**
48 * Enqueue stylesheets
49 */
50 private function enqueueStyles() {
51
52 // Tailwind: opt-in switch between the unpurged 2.8 MB shipped file
53 // and a purged ~50 KB file that an admin has built via
54 // tools/tailwind-build/. The default is the unpurged file so
55 // merchants who haven't run the build see zero behavior change.
56 //
57 // To enable the win:
58 // 1. cd tools/tailwind-build && npm install && npm run build
59 // 2. Verify visually on a few representative pages
60 // 3. Set option `easy_invoice_tailwind_purged = '1'` OR add the
61 // filter below to your theme's functions.php:
62 // add_filter('easy_invoice_use_purged_tailwind', '__return_true');
63 //
64 // The fallback below also defensively checks the purged file exists,
65 // so flipping the option without actually building falls back to the
66 // shipped file rather than 404-ing the stylesheet.
67 $use_purged = apply_filters(
68 'easy_invoice_use_purged_tailwind',
69 (bool) get_option('easy_invoice_tailwind_purged', false)
70 );
71 $purged_rel = 'assets/lib/tailwind/tailwind.purged.min.css';
72 $shipped_rel = 'assets/lib/tailwind/tailwind.min.css';
73 $tailwind_rel = ($use_purged && file_exists(EASY_INVOICE_PLUGIN_DIR . $purged_rel))
74 ? $purged_rel
75 : $shipped_rel;
76
77 wp_enqueue_style(
78 'easy-invoice-tailwind',
79 EASY_INVOICE_PLUGIN_URL . $tailwind_rel,
80 array(),
81 EASY_INVOICE_VERSION
82 );
83
84 $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
85
86 // Main plugin layout + header strip alignment (always on Easy Invoice admin screens).
87 wp_enqueue_style(
88 'easy-invoice-main',
89 EASY_INVOICE_PLUGIN_URL . 'assets/css/easy-invoice.css',
90 array(),
91 EASY_INVOICE_VERSION
92 );
93
94 if($page === 'easy-invoice-builder') {
95 // Main admin styles
96
97 wp_enqueue_style(
98 'easy-invoice-preview',
99 EASY_INVOICE_PLUGIN_URL . 'assets/css/invoice-preview.css',
100 array(),
101 EASY_INVOICE_VERSION
102 );
103 }
104
105 // Font Awesome (~87 KB) is used by the heavyweight templates
106 // (clients, settings, reports, invoices, quotes, payments) but
107 // NOT by the lightweight admin pages — Dashboard, Addons grid,
108 // License, Free-vs-Pro, Join Community, and every addon-settings
109 // sub-page (those use dashicons). Skip enqueueing FA on the
110 // deny-listed pages to save the bandwidth and the parse cost.
111 // Filterable so site-specific custom templates can opt back in.
112 $fa_deny = (array) apply_filters('easy_invoice_font_awesome_skip_pages', [
113 'easy-invoice-dashboard',
114 'easy-invoice-addons',
115 'easy-invoice-license',
116 'easy-invoice-free-vs-pro',
117 'easy-invoice-join-community',
118 ]);
119 $is_addon_subpage = ($page !== '' && strpos($page, 'easy-invoice-addon-') === 0);
120 if (!in_array($page, $fa_deny, true) && !$is_addon_subpage) {
121 wp_enqueue_style(
122 'font-awesome',
123 EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css',
124 array(),
125 EASY_INVOICE_VERSION
126 );
127 }
128
129
130 // RTL support.
131 //
132 // Strategy: 'append' (not 'replace') because Tailwind utility
133 // classes generated into easy-invoice.css remain valid LTR — only
134 // the small set of custom directional rules (sidebar borders,
135 // page-header negative margins, drawer offsets) need mirroring.
136 // WordPress loads assets/css/easy-invoice-rtl.css AFTER
137 // easy-invoice.css when is_rtl() is true; that file holds only the
138 // directional overrides.
139 //
140 // 'easy-invoice-main' is the handle of the file we want to extend
141 // (line 87 above). The previous handle 'easy-invoice-admin' did
142 // not exist and so the call was a no-op.
143 wp_style_add_data('easy-invoice-main', 'rtl', 'append');
144 }
145
146 /**
147 * Enqueue scripts
148 *
149 * @param string $hook The current admin page
150 */
151 private function enqueueScripts($hook) {
152 // Only load on Easy Invoice pages
153 if (empty($hook) || strpos($hook, 'easy-invoice') === false) {
154 return;
155 }
156
157 // Common admin scripts
158 wp_enqueue_script('jquery');
159 wp_enqueue_script('jquery-ui-core');
160 wp_enqueue_script('jquery-ui-datepicker');
161 wp_enqueue_script('wp-util');
162
163 // Add WordPress core dependencies that provide the 'wp' object
164 wp_enqueue_script('wp-api-fetch');
165 wp_enqueue_script('wp-i18n');
166 wp_enqueue_script('wp-a11y');
167 wp_enqueue_script('wp-hooks');
168
169 // Settings page script
170 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-settings') {
171 wp_enqueue_script(
172 'easy-invoice-settings',
173 EASY_INVOICE_PLUGIN_URL . 'assets/js/settings.js',
174 array('jquery', 'wp-util', 'wp-api-fetch', 'wp-i18n'),
175 EASY_INVOICE_VERSION,
176 true
177 );
178
179 // Localize the script with necessary data
180 wp_localize_script('easy-invoice-settings', 'easyInvoiceSettings', array(
181 'nonce' => wp_create_nonce('easy_invoice_settings'),
182 'ajaxurl' => admin_url('admin-ajax.php')
183 ));
184 return; // Don't load other scripts on settings page
185 }
186
187 // Load dependencies
188 wp_enqueue_script('jquery-ui-sortable');
189
190 // Main admin script
191 wp_enqueue_script('jquery');
192
193 // Register and enqueue our scripts
194 wp_register_script('easy-invoice-scripts', EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice.js', array('jquery', 'wp-api-fetch', 'wp-i18n', 'wp-a11y'), EASY_INVOICE_VERSION, true);
195 wp_enqueue_script('easy-invoice-scripts');
196
197 // Conditionally load client manager only on invoice pages (not quote pages or invoice builder)
198 if (!(isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-quote-builder' || $_GET['page'] === 'easy-invoice-builder'))) {
199 wp_register_script('easy-invoice-client-manager', EASY_INVOICE_PLUGIN_URL . 'assets/js/client-manager.js', array('jquery', 'easy-invoice-scripts', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
200 wp_enqueue_script('easy-invoice-client-manager');
201 }
202
203 // Load clients.js on the clients page
204 if (isset($_GET['page']) && $_GET['page'] === PagesSlugs::CLIENTS) {
205 wp_register_script('easy-invoice-clients', EASY_INVOICE_PLUGIN_URL . 'assets/js/clients.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-confirmation-modal', 'easy-invoice-toast', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
206 wp_enqueue_script('easy-invoice-clients');
207 }
208
209 wp_register_script('easy-invoice-payment-manager', EASY_INVOICE_PLUGIN_URL . 'assets/js/payment-manager.js', array('jquery', 'easy-invoice-scripts', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
210 wp_enqueue_script('easy-invoice-payment-manager');
211
212 // Tooltip manager - reusable across the plugin
213 wp_register_script('easy-invoice-tooltip', EASY_INVOICE_PLUGIN_URL . 'assets/js/tooltip-manager.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
214 wp_enqueue_script('easy-invoice-tooltip');
215
216 // Confirmation modal - reusable across the plugin
217 wp_register_script('easy-invoice-confirmation-modal', EASY_INVOICE_PLUGIN_URL . 'assets/js/confirmation-modal.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
218 wp_enqueue_script('easy-invoice-confirmation-modal');
219
220 // Toast notification system - global across the plugin
221 wp_register_script('easy-invoice-toast', EASY_INVOICE_PLUGIN_URL . 'assets/js/easy-invoice-toast.js', array('jquery', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
222 wp_enqueue_script('easy-invoice-toast');
223
224 // Bulk "Send Email" teaser — only on the invoice / quote listings.
225 // Always injects the option (even without Pro) so users discover the
226 // feature; when Pro is inactive, clicking Apply opens the upgrade
227 // dialog instead of doing the work.
228 $current_page = isset($_GET['page']) ? sanitize_key($_GET['page']) : '';
229 if (in_array($current_page, ['easy-invoice-all', 'easy-quote-all'], true)) {
230 wp_register_script(
231 'easy-invoice-bulk-send-email-teaser',
232 EASY_INVOICE_PLUGIN_URL . 'assets/js/bulk-send-email-teaser.js',
233 array('jquery', 'easy-invoice-confirmation-modal', 'easy-invoice-toast'),
234 EASY_INVOICE_VERSION,
235 true
236 );
237 wp_localize_script('easy-invoice-bulk-send-email-teaser', 'easyInvoiceBulkSendTeaser', array(
238 'hasPro' => function_exists('easy_invoice_has_pro') && easy_invoice_has_pro(),
239 'upgradeUrl' => 'https://matrixaddons.com/plugins/easy-invoice/#pricing',
240 'i18n' => array(
241 // Send Email
242 'send_email_label' => __('Send Email (Pro)', 'easy-invoice'),
243 'send_email_feature_name' => __('Bulk Send Email', 'easy-invoice'),
244 'send_email_feature_description'=> __('Select multiple invoices or quotes and send the configured "Available" email to every selected document\'s client in a single click. Includes a per-row success / failure report so you can spot deliverability problems immediately.', 'easy-invoice'),
245 // Export
246 'export_feature_name' => __('Bulk Export Selected', 'easy-invoice'),
247 'export_feature_description' => __('Export your selected invoices or quotes to a clean, accounting-ready CSV — perfect for QuickBooks, Xero, audit trails, or migrating to a new system.', 'easy-invoice'),
248 // Generic
249 'upgrade_required' => __('This action requires Easy Invoice Pro.', 'easy-invoice'),
250 ),
251 ));
252 wp_enqueue_script('easy-invoice-bulk-send-email-teaser');
253 }
254
255 // jsPDF for PDF generation - available on all Easy Invoice pages
256 wp_register_script('jspdf', 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js', array(), '2.5.1', true);
257 wp_enqueue_script('jspdf');
258
259
260 // Conditionally load invoice-specific scripts only on invoice pages
261 if (isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-new' || $_GET['page'] === 'easy-invoice-builder')) {
262 // Invoice builder scripts
263 wp_register_script('easy-invoice-builder', EASY_INVOICE_PLUGIN_URL . 'assets/js/invoice-builder.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
264 wp_enqueue_script('easy-invoice-builder');
265
266 // Use invoice-save.js for comprehensive save functionality
267 wp_register_script('easy-invoice-save', EASY_INVOICE_PLUGIN_URL . 'assets/js/invoice-save.js', array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'), EASY_INVOICE_VERSION, true);
268 wp_enqueue_script('easy-invoice-save');
269 }
270
271 // Quote builder (full-screen editor)
272 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-quote-builder') {
273 wp_register_script(
274 'easy-quote-save',
275 EASY_INVOICE_PLUGIN_URL . 'assets/js/quote-save.js',
276 array('jquery', 'easy-invoice-scripts', 'easy-invoice-payment-manager', 'wp-api-fetch', 'wp-i18n'),
277 EASY_INVOICE_VERSION,
278 true
279 );
280 wp_enqueue_script('easy-quote-save');
281 }
282
283 if (isset($_GET['page']) && in_array($_GET['page'], array('easy-invoice-builder', 'easy-invoice-quote-builder'), true)) {
284 wp_enqueue_script(
285 'easy-invoice-builder-mobile-tabs',
286 EASY_INVOICE_PLUGIN_URL . 'assets/js/builder-mobile-tabs.js',
287 array('jquery'),
288 EASY_INVOICE_VERSION,
289 true
290 );
291 wp_enqueue_script(
292 'easy-invoice-builder-ux',
293 EASY_INVOICE_PLUGIN_URL . 'assets/js/builder-ux.js',
294 array('jquery', 'easy-invoice-scripts'),
295 EASY_INVOICE_VERSION,
296 true
297 );
298 }
299 }
300
301 /**
302 * Localize script data
303 *
304 * @param string $hook The current admin page
305 */
306 private function localizeScripts($hook) {
307 global $pagenow, $post;
308
309 // Get currency settings
310 $settings_controller = new \EasyInvoice\Controllers\SettingsController();
311 $settings = $settings_controller->getSettings();
312 $currency_code = $settings['easy_invoice_currency_code'] ?? 'USD';
313 $currency_position = $settings['easy_invoice_currency_position'] ?? 'left';
314 $currency_symbol = easy_invoice_get_currency_symbol();
315
316 $current_admin_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
317
318 // Default data
319 $script_data = array(
320 'ajaxUrl' => admin_url('admin-ajax.php'),
321 'nonce' => wp_create_nonce('easy_invoice_nonce'),
322 'i18n' => array(
323 'confirm_delete' => __('Are you sure you want to delete this invoice?', 'easy-invoice'),
324 'invoice_deleted' => __('Invoice deleted successfully', 'easy-invoice'),
325 'client_deleted' => __('Client deleted successfully', 'easy-invoice'),
326 'confirm_delete_client' => __('Are you sure you want to delete this client?', 'easy-invoice'),
327 'edit_invoice' => __('Edit Invoice', 'easy-invoice'),
328 'create_invoice' => __('Create Invoice', 'easy-invoice'),
329 'save' => __('Save', 'easy-invoice'),
330 'cancel' => __('Cancel', 'easy-invoice'),
331 'add_item' => __('Add Item', 'easy-invoice'),
332 'delete_item' => __('Delete Item', 'easy-invoice'),
333 'error' => __('An error occurred', 'easy-invoice'),
334 ),
335 );
336
337 if (in_array($current_admin_page, array('easy-invoice-builder', 'easy-invoice-quote-builder'), true)) {
338 $script_data['i18n'] = array_merge(
339 $script_data['i18n'],
340 array(
341 'saving' => __('Saving…', 'easy-invoice'),
342 'sending' => __('Sending…', 'easy-invoice'),
343 'save_invoice' => __('Save Invoice', 'easy-invoice'),
344 'update_invoice' => __('Update Invoice', 'easy-invoice'),
345 'save_quote' => __('Save Quote', 'easy-invoice'),
346 'update_quote' => __('Update Quote', 'easy-invoice'),
347 'send_invoice' => __('Send Invoice', 'easy-invoice'),
348 'send_quote' => __('Send Quote', 'easy-invoice'),
349 'save_first_invoice' => __('Please save the invoice before sending.', 'easy-invoice'),
350 'save_first_quote' => __('Please save the quote before sending.', 'easy-invoice'),
351 'email_sent_invoice' => __('Invoice email sent successfully.', 'easy-invoice'),
352 'email_sent_quote' => __('Quote email sent successfully.', 'easy-invoice'),
353 'email_error' => __('Error sending email.', 'easy-invoice'),
354 'network_error' => __('Error connecting to server.', 'easy-invoice'),
355 'tab_editor' => __('Editor', 'easy-invoice'),
356 'tab_preview' => __('Preview', 'easy-invoice'),
357 'confirm_send_invoice_title' => __('Send invoice by email?', 'easy-invoice'),
358 'confirm_send_invoice_message' => __('This will email the invoice to the client using your configured template.', 'easy-invoice'),
359 'confirm_send_quote_title' => __('Send quote by email?', 'easy-invoice'),
360 'confirm_send_quote_message' => __('This will email the quote to the client using your configured template.', 'easy-invoice'),
361 'confirm_send_confirm' => __('Send', 'easy-invoice'),
362 'confirm_cancel' => __('Cancel', 'easy-invoice'),
363 'builder_unsaved_warning' => __('You have unsaved changes. If you leave this page, your changes may be lost.', 'easy-invoice'),
364 'builder_title_hint' => __('The title above matches the document title field in the editor.', 'easy-invoice'),
365 'builder_shell_hint' => __('On smaller screens, use the tabs to switch between the editor and the live preview.', 'easy-invoice'),
366 'builder_shell_hint_dismiss' => __('Got it', 'easy-invoice'),
367 'send_invoice_confirm_browser' => __('Send this invoice by email?', 'easy-invoice'),
368 'send_quote_confirm_browser' => __('Send this quote by email?', 'easy-invoice'),
369 )
370 );
371 }
372
373 $script_data = array_merge(
374 $script_data,
375 array(
376 'urls' => array(
377 'preview' => admin_url('admin.php?action=easy_invoice_preview&invoice_id='),
378 'edit' => admin_url('admin.php?page=easy-invoice-new&id='),
379 ),
380 'settings' => array(
381 'currency_symbol' => $currency_symbol,
382 'currency_position' => $currency_position,
383 'currency_code' => $currency_code,
384 'decimal_separator' => $settings['easy_invoice_decimal_separator'] ?? '.',
385 'thousand_separator' => $settings['easy_invoice_thousands_separator'] ?? ',',
386 'decimal_places' => $settings['easy_invoice_decimal_precision'] ?? 2,
387 'date_format' => get_option('date_format', 'F j, Y'),
388 ),
389 'showAdjustField' => \EasyInvoice\Controllers\SettingsController::shouldShowInvoiceAdjustField(),
390 )
391 );
392
393 // Localize common scripts
394 wp_localize_script('easy-invoice-scripts', 'easyInvoice', $script_data);
395
396 // Conditionally localize client manager only when it's loaded
397 if (!(isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-quote-builder' || $_GET['page'] === 'easy-invoice-builder'))) {
398 wp_localize_script('easy-invoice-client-manager', 'easyInvoice', $script_data);
399 }
400
401 wp_localize_script('easy-invoice-payment-manager', 'easyInvoice', $script_data);
402 wp_localize_script('easy-invoice-tooltip', 'easyInvoice', $script_data);
403
404 // Conditionally localize invoice-specific scripts
405 if (isset($_GET['page']) && ($_GET['page'] === 'easy-invoice-new' || $_GET['page'] === 'easy-invoice-builder')) {
406 // Add invoice-specific field configuration
407 $form_manager = new \EasyInvoice\Forms\Invoice\InvoiceFormManager();
408 $script_data['fieldConfig'] = $form_manager->getFieldConfigForJavaScript();
409
410 // Add additional data for the invoice edit page
411 $invoice_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
412 $invoice_items_json = '';
413
414 if ($invoice_id > 0) {
415 // Existing invoice - get its data
416 $repository = \EasyInvoice\Providers\InvoiceServiceProvider::getInvoiceRepository();
417 $invoice = $repository->find($invoice_id);
418
419 if ($invoice) {
420 $script_data['invoice_id'] = $invoice_id;
421 $script_data['editMode'] = true;
422
423 // Get invoice data for JavaScript
424 $invoice_data = $invoice->toArray();
425 $script_data['invoiceData'] = $invoice_data;
426
427 // Get invoice items
428 $items = $invoice->getItems();
429 $items_data = [];
430 foreach ($items as $item) {
431 $items_data[] = [
432 'id' => $item->getId(),
433 'name' => $item->getName(),
434 'description' => $item->getDescription(),
435 'quantity' => $item->getQuantity(),
436 'price' => $item->getPrice(),
437 'taxable' => $item->isTaxable(),
438 'total' => $item->getAmount()
439 ];
440 }
441 $script_data['invoiceItems'] = $items_data;
442
443 // Get client data if available
444 if ($invoice->getClientId()) {
445 $client_repository = \EasyInvoice\Providers\ClientServiceProvider::getClientRepository();
446 $client = $client_repository->find($invoice->getClientId());
447 if ($client) {
448 $script_data['clientData'] = [
449 'id' => $client->getId(),
450 'name' => $client->getBusinessClientName() ?: ($client->getFirstName() . ' ' . $client->getLastName()),
451 'email' => $client->getEmail(),
452 'phone' => $client->getExtraInfo(),
453 'address' => $client->getAddress(),
454 'company' => $client->getBusinessClientName()
455 ];
456 }
457 }
458 }
459 } else {
460 // New invoice - set default items
461 $script_data['editMode'] = false;
462 $script_data['invoice_id'] = 0;
463 $default_items = [
464 [
465 'name' => '',
466 'description' => '',
467 'quantity' => 0,
468 'price' => 0,
469 'taxable' => true
470 ]
471 ];
472 $script_data['default_items'] = $default_items;
473 }
474
475 // Localize invoice-specific scripts
476 wp_localize_script('easy-invoice-builder', 'easyInvoice', $script_data);
477 wp_localize_script('easy-invoice-save', 'easyInvoice', $script_data);
478 }
479
480 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-quote-builder') {
481 // Override showAdjustField for quote pages
482 $script_data['showAdjustField'] = \EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField();
483 wp_localize_script('easy-quote-save', 'easyInvoice', $script_data);
484 }
485 }
486 }
487