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 / Repositories / InvoiceRepository.php

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

589 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Invoice Repository Class
4 *
5 * @package Easy_Invoice
6 * @subpackage Repositories
7 */
8
9 namespace EasyInvoice\Repositories;
10
11 use EasyInvoice\Interfaces\InvoiceRepositoryInterface;
12 use EasyInvoice\Models\Invoice;
13 use WP_Post;
14 use WP_Query;
15
16 /**
17 * InvoiceRepository Class
18 *
19 * Handles data access for invoice objects with extensible architecture for pro features.
20 */
21 class InvoiceRepository implements InvoiceRepositoryInterface {
22
23 /**
24 * The post type name
25 *
26 * @var string
27 */
28 protected $post_type = \EasyInvoice\Constants\PostTypes::EASY_INVOICE_POST_TYPE;
29
30 /**
31 * Find an invoice by ID
32 *
33 * @param int $id The invoice ID
34 * @return Invoice|null The invoice model or null if not found
35 */
36 public function find($id) {
37 $post = get_post($id);
38
39 if (!$post || $post->post_type !== $this->post_type) {
40 return null;
41 }
42
43 $invoice = new Invoice($post);
44
45 // Ensure invoice has proper slug for pretty URLs
46 $invoice->ensureProperSlug();
47
48 // Allow plugins to modify the found invoice
49 return apply_filters('easy_invoice_invoice_found', $invoice, $id);
50 }
51
52 /**
53 * Get all invoices
54 *
55 * @param array $args Optional arguments to filter the results
56 * @return array Array of Invoice models
57 */
58 public function all($args = []) {
59 $default_args = [
60 'post_type' => $this->post_type,
61 'posts_per_page' => -1,
62 'post_status' => 'publish',
63 'orderby' => 'date',
64 'order' => 'DESC',
65 ];
66
67 $query_args = wp_parse_args($args, $default_args);
68
69 // Allow plugins to modify query arguments
70 $query_args = apply_filters('easy_invoice_invoice_query_args', $query_args);
71
72 $query = new WP_Query($query_args);
73 $invoices = [];
74
75 if ($query->have_posts()) {
76 foreach ($query->posts as $post) {
77 $invoice = new Invoice($post);
78
79 // Ensure invoice has proper slug for pretty URLs
80 $invoice->ensureProperSlug();
81
82 $invoices[] = $invoice;
83 }
84 }
85
86 // Allow plugins to modify the results
87 return apply_filters('easy_invoice_invoices_found', $invoices, $query_args);
88 }
89
90 /**
91 * Create a new invoice
92 *
93 * @param array $data Invoice data
94 * @return Invoice|false The created invoice or false on failure
95 */
96 public function create($data) {
97 // Allow plugins to modify the data before creation
98 $data = apply_filters('easy_invoice_invoice_create_data', $data);
99
100 // Create a new invoice object
101 $invoice = new Invoice();
102
103 // Set basic data
104 $invoice->setTitle($data['title'] ?? 'New Invoice');
105
106 // Auto-generate invoice number if not provided
107 if ((!isset($data['number']) || empty($data['number'])) &&
108 (!isset($data['invoice_number']) || empty($data['invoice_number']))) {
109 $invoice_number_service = easy_invoice_get_invoice_number_service();
110 $data['number'] = $invoice_number_service->generateUniqueNumber();
111 }
112
113 // Set invoice data
114 $this->setInvoiceData($invoice, $data, false);
115
116 // Allow plugins to modify the invoice before saving
117 do_action('easy_invoice_invoice_before_create', $invoice, $data);
118
119 // Save the invoice (this will create the post and ensure proper permalinks)
120 if ($invoice->save()) {
121 // Allow plugins to perform actions after creation
122 do_action('easy_invoice_invoice_created', $invoice, $data);
123 return $invoice;
124 }
125
126 return false;
127 }
128
129 /**
130 * Update an existing invoice
131 *
132 * @param int $id The invoice ID
133 * @param array $data The invoice data
134 * @return Invoice|null The updated invoice model or null if not found
135 */
136 public function update($id, $data) {
137 try {
138 $invoice = $this->find($id);
139
140 if (!$invoice) {
141 return null;
142 }
143
144 // Set invoice data
145 $this->setInvoiceData($invoice, $data);
146
147 // Save the invoice
148 $result = $invoice->save();
149
150 return $result ? $invoice : null;
151 } catch (\Exception $e) {
152 return null;
153 }
154 }
155
156 /**
157 * Delete an invoice
158 *
159 * @param int $id The invoice ID
160 * @return bool True if successful, false otherwise
161 */
162 public function delete($id) {
163 $invoice = $this->find($id);
164
165 if (!$invoice) {
166 return false;
167 }
168
169 // Allow plugins to perform actions before deletion
170 do_action('easy_invoice_invoice_before_delete', $invoice);
171
172 $result = wp_delete_post($id, true);
173
174 if ($result) {
175 // Allow plugins to perform actions after deletion
176 do_action('easy_invoice_invoice_deleted', $id);
177 }
178
179 return $result instanceof WP_Post;
180 }
181
182 /**
183 * Find invoices by customer ID
184 *
185 * @param int $customer_id The customer ID
186 * @return array Array of Invoice models
187 */
188 public function findByCustomer($customer_id) {
189 $args = [
190 'meta_query' => [
191 [
192 'key' => '_easy_invoice_customer_id',
193 'value' => $customer_id,
194 'compare' => '=',
195 ],
196 ],
197 ];
198
199 $invoices = $this->all($args);
200
201 // Allow plugins to modify the filtered results
202 return apply_filters('easy_invoice_invoices_by_customer', $invoices, $customer_id);
203 }
204
205 /**
206 * Find invoices by status
207 *
208 * @param string $status The invoice status
209 * @return array Array of Invoice models
210 */
211 public function findByStatus($status) {
212 $args = [
213 'meta_query' => [
214 [
215 'key' => '_easy_invoice_status',
216 'value' => $status,
217 'compare' => '=',
218 ],
219 ],
220 ];
221
222 $invoices = $this->all($args);
223
224 // Allow plugins to modify the filtered results
225 return apply_filters('easy_invoice_invoices_by_status', $invoices, $status);
226 }
227
228 /**
229 * Find invoices due within a date range
230 *
231 * @param string $start_date The start date in 'Y-m-d' format
232 * @param string $end_date The end date in 'Y-m-d' format
233 * @return array Array of Invoice models
234 */
235 public function findByDueDate($start_date, $end_date = null) {
236 $meta_query = [
237 [
238 'key' => '_easy_invoice_due_date',
239 'value' => $start_date,
240 'compare' => '>=',
241 'type' => 'DATE',
242 ],
243 ];
244
245 if ($end_date) {
246 $meta_query[] = [
247 'key' => '_easy_invoice_due_date',
248 'value' => $end_date,
249 'compare' => '<=',
250 'type' => 'DATE',
251 ];
252 }
253
254 $args = [
255 'meta_query' => $meta_query,
256 ];
257
258 $invoices = $this->all($args);
259
260 // Allow plugins to modify the filtered results
261 return apply_filters('easy_invoice_invoices_by_due_date', $invoices, $start_date, $end_date);
262 }
263
264 /**
265 * Count invoices
266 *
267 * @param array $args Optional arguments to filter the results
268 * @return int Number of invoices
269 */
270 public function count($args = []) {
271 $default_args = [
272 'post_type' => $this->post_type,
273 'post_status' => 'publish',
274 ];
275
276 $query_args = wp_parse_args($args, $default_args);
277
278 // Allow plugins to modify query arguments
279 $query_args = apply_filters('easy_invoice_invoice_count_query_args', $query_args);
280
281 $query = new WP_Query($query_args);
282
283 $count = $query->found_posts;
284
285 // Allow plugins to modify the count
286 return apply_filters('easy_invoice_invoice_count', $count, $query_args);
287 }
288
289 /**
290 * Find an invoice by its invoice number (stored in post meta)
291 *
292 * @param string $number Invoice number (exact match)
293 * @return Invoice|null
294 */
295 public function findByNumber(string $number) {
296 $args = [
297 'post_type' => $this->post_type,
298 'post_status' => ['publish', 'draft', 'private', 'pending'],
299 'posts_per_page' => 1,
300 'meta_query' => [
301 [
302 'key' => \EasyInvoice\Constants\InvoiceMetaKeys::NUMBER,
303 'value' => $number,
304 'compare' => '=',
305 ],
306 ],
307 'orderby' => 'date',
308 'order' => 'DESC',
309 ];
310
311 $query = new WP_Query($args);
312 if (!empty($query->posts)) {
313 $post = $query->posts[0];
314 if ($post && $post->post_type === $this->post_type) {
315 $invoice = new Invoice($post);
316 $invoice->ensureProperSlug();
317 return apply_filters('easy_invoice_invoice_found_by_number', $invoice, $number);
318 }
319 }
320 return null;
321 }
322
323 /**
324 * Find published invoice by ID
325 *
326 * @param int $id The invoice ID
327 * @return Invoice|null The invoice model or null if not found
328 */
329 public function findPublished(int $id) {
330 $post = get_post($id);
331
332 if (!$post || $post->post_type !== $this->post_type || $post->post_status !== 'publish') {
333 return null;
334 }
335
336 $invoice = new Invoice($post);
337
338 // Ensure invoice has proper slug for pretty URLs
339 $invoice->ensureProperSlug();
340
341 return $invoice;
342 }
343
344 /**
345 * Update all existing draft invoices to published status for proper permalinks
346 *
347 * @return int Number of invoices updated
348 */
349 public function updateAllExistingInvoices(): int {
350 global $wpdb;
351
352 // Find all draft invoices
353 $draft_invoices = $wpdb->get_col($wpdb->prepare(
354 "SELECT ID FROM {$wpdb->posts}
355 WHERE post_type = %s
356 AND post_status = 'draft'",
357 $this->post_type
358 ));
359
360 $updated_count = 0;
361
362 foreach ($draft_invoices as $invoice_id) {
363 $invoice = $this->find($invoice_id);
364 if ($invoice) {
365 // Save the invoice (this will publish it and ensure proper permalinks)
366 if ($invoice->save()) {
367 $updated_count++;
368 }
369 }
370 }
371
372 // Allow plugins to perform actions after bulk update
373 do_action('easy_invoice_invoices_bulk_updated', $updated_count);
374
375 return $updated_count;
376 }
377
378 /**
379 * Set invoice data from array
380 *
381 * @param Invoice $invoice
382 * @param array $data
383 * @param bool $preserve_number
384 * @return void
385 */
386 protected function setInvoiceData(Invoice $invoice, array $data, $preserve_number = false) {
387 // Allow plugins to modify the data setting process
388 do_action('easy_invoice_invoice_set_data_before', $invoice, $data);
389
390 // Set basic invoice fields (core fields that have dedicated methods)
391 if (isset($data['title'])) {
392 $invoice->setTitle($data['title']);
393 }
394
395 if (isset($data['invoice_title'])) {
396 $invoice->setTitle($data['invoice_title']);
397 }
398
399 if (isset($data['description'])) {
400 $invoice->setDescription($data['description']);
401 }
402
403 if (isset($data['invoice_description'])) {
404 $invoice->setDescription($data['invoice_description']);
405 }
406
407 // Set invoice number (only if not preserving existing)
408 if (isset($data['invoice_number']) && !empty($data['invoice_number'])) {
409 $invoice->setNumber($data['invoice_number']);
410 } elseif (isset($data['number']) && !empty($data['number'])) {
411 $invoice->setNumber($data['number']);
412 }
413
414 // Set dates
415 if (isset($data['issue_date'])) {
416 $invoice->setIssueDate($data['issue_date']);
417 }
418
419 if (isset($data['invoice_date'])) {
420 $invoice->setIssueDate($data['invoice_date']);
421 }
422
423 if (isset($data['issue-date'])) {
424 $invoice->setIssueDate($data['issue-date']);
425 }
426
427 if (isset($data['due_date'])) {
428 $invoice->setDueDate($data['due_date']);
429 }
430
431 if (isset($data['due-date'])) {
432 $invoice->setDueDate($data['due-date']);
433 }
434
435 // Set status
436 if (isset($data['status'])) {
437 $invoice->setStatus($data['status']);
438 }
439
440 if (isset($data['invoice_status'])) {
441 $invoice->setStatus($data['invoice_status']);
442 }
443
444 if (isset($data['payment_status'])) {
445 $invoice->setStatus($data['payment_status']);
446 }
447
448 // Set notes and terms
449 if (isset($data['notes'])) {
450 $invoice->setNotes($data['notes']);
451 }
452
453 if (isset($data['terms_and_conditions'])) {
454 $invoice->setTerms($data['terms_and_conditions']);
455 }
456
457 if (isset($data['internal_notes'])) {
458 $invoice->setInternalNotes($data['internal_notes']);
459 }
460
461 if (isset($data['payment_instructions'])) {
462 $invoice->setPaymentInstructions($data['payment_instructions']);
463 }
464
465 // Set payment gateways
466 if (isset($data['payment_gateways']) && is_array($data['payment_gateways'])) {
467 $invoice->setPaymentGateways($data['payment_gateways']);
468 } elseif (isset($data['payment_gateways']) && is_string($data['payment_gateways'])) {
469 $gateways = array_filter(explode(',', $data['payment_gateways']));
470 $invoice->setPaymentGateways($gateways);
471 } else {
472 $invoice->setPaymentGateways([]);
473 }
474
475 // Set payment gateways toggle state
476 if (isset($data['payment_gateways_toggle_state'])) {
477 $invoice->setPaymentGatewaysToggleState((string)$data['payment_gateways_toggle_state']);
478 }
479
480 // Set template
481 if (isset($data['invoice_template'])) {
482 $invoice->setTemplate($data['invoice_template']);
483 }
484
485 // Set client information
486 if (isset($data['customer_name'])) {
487 $invoice->setCustomerName($data['customer_name']);
488 }
489
490 if (isset($data['customer_address'])) {
491 $invoice->setCustomerAddress($data['customer_address']);
492 }
493
494 if (isset($data['customer_email'])) {
495 $invoice->setCustomerEmail($data['customer_email']);
496 }
497
498 // Set discount and tax settings
499 if (isset($data['discount_type'])) {
500 $invoice->setDiscountType($data['discount_type']);
501 }
502
503 if (isset($data['discount_value'])) {
504 $invoice->setDiscountValue($data['discount_value']);
505 }
506
507 if (isset($data['discount'])) {
508 $invoice->setDiscountValue($data['discount']);
509 }
510
511 if (isset($data['tax_rate'])) {
512 $invoice->setTaxRate($data['tax_rate']);
513 }
514
515 if (isset($data['calculation_method'])) {
516 $invoice->setCalculationMethod($data['calculation_method']);
517 }
518
519 if (isset($data['prices_include_tax'])) {
520 $invoice->setPricesIncludeTax($data['prices_include_tax']);
521 }
522
523 // Set currency settings
524 if (isset($data['currency_code'])) {
525 $invoice->setCurrencyCode($data['currency_code']);
526 }
527
528 if (isset($data['currency_position'])) {
529 $invoice->setCurrencyPosition($data['currency_position']);
530 }
531
532 // Set footer text
533 if (isset($data['footer_text'])) {
534 $invoice->setFooterText($data['footer_text']);
535 }
536
537 // Set client ID
538 if (isset($data['client_id']) && !empty($data['client_id'])) {
539 $invoice->setClientId((int) $data['client_id']);
540 }
541
542 // Set items
543 if (isset($data['items']) && is_array($data['items'])) {
544 $invoice->setItems($data['items']);
545 }
546
547 // Set custom fields
548 if (isset($data['custom_fields']) && is_array($data['custom_fields'])) {
549 $invoice->setCustomFields($data['custom_fields']);
550 }
551
552 // Set recurring fields
553 if (isset($data['recurring_enabled'])) {
554 $invoice->setRecurringEnabled((bool) $data['recurring_enabled']);
555 }
556
557 if (isset($data['recurring_frequency'])) {
558 $invoice->setRecurringFrequency($data['recurring_frequency']);
559 }
560
561 if (isset($data['recurring_interval'])) {
562 $invoice->setRecurringInterval((int) $data['recurring_interval']);
563 }
564
565 if (isset($data['recurring_start_date'])) {
566 $invoice->setRecurringStartDate($data['recurring_start_date']);
567 }
568
569 // Use configuration-driven approach for all other fields
570 $form_processor = new \EasyInvoice\Forms\FormProcessor();
571 $field_registration = new \EasyInvoice\Forms\Invoice\InvoiceFieldRegistration();
572
573 // Get all field definitions from all tabs
574 $field_definitions = [];
575 $tabs = $field_registration->getTabs();
576 foreach ($tabs as $tab_id => $tab) {
577 $tab_fields = $field_registration->getFields($tab_id);
578 foreach ($tab_fields as $field) {
579 $field_definitions[] = $field;
580 }
581 }
582
583 // Save form data using field configuration
584 $form_processor->saveFormDataToDatabase($data, $field_definitions, $invoice);
585
586 // Allow plugins to modify the data setting process
587 do_action('easy_invoice_invoice_set_data_after', $invoice, $data);
588 }
589 }