PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.1.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.1.0
2.4.3 2.4.4 2.4.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 All 60 releases
easy-invoice / includes / Repositories / InvoiceRepository.php

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

555 lines 17.1 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 published invoice by ID
291 *
292 * @param int $id The invoice ID
293 * @return Invoice|null The invoice model or null if not found
294 */
295 public function findPublished(int $id) {
296 $post = get_post($id);
297
298 if (!$post || $post->post_type !== $this->post_type || $post->post_status !== 'publish') {
299 return null;
300 }
301
302 $invoice = new Invoice($post);
303
304 // Ensure invoice has proper slug for pretty URLs
305 $invoice->ensureProperSlug();
306
307 return $invoice;
308 }
309
310 /**
311 * Update all existing draft invoices to published status for proper permalinks
312 *
313 * @return int Number of invoices updated
314 */
315 public function updateAllExistingInvoices(): int {
316 global $wpdb;
317
318 // Find all draft invoices
319 $draft_invoices = $wpdb->get_col($wpdb->prepare(
320 "SELECT ID FROM {$wpdb->posts}
321 WHERE post_type = %s
322 AND post_status = 'draft'",
323 $this->post_type
324 ));
325
326 $updated_count = 0;
327
328 foreach ($draft_invoices as $invoice_id) {
329 $invoice = $this->find($invoice_id);
330 if ($invoice) {
331 // Save the invoice (this will publish it and ensure proper permalinks)
332 if ($invoice->save()) {
333 $updated_count++;
334 }
335 }
336 }
337
338 // Allow plugins to perform actions after bulk update
339 do_action('easy_invoice_invoices_bulk_updated', $updated_count);
340
341 return $updated_count;
342 }
343
344 /**
345 * Set invoice data from array
346 *
347 * @param Invoice $invoice
348 * @param array $data
349 * @param bool $preserve_number
350 * @return void
351 */
352 protected function setInvoiceData(Invoice $invoice, array $data, $preserve_number = false) {
353 // Allow plugins to modify the data setting process
354 do_action('easy_invoice_invoice_set_data_before', $invoice, $data);
355
356 // Set basic invoice fields (core fields that have dedicated methods)
357 if (isset($data['title'])) {
358 $invoice->setTitle($data['title']);
359 }
360
361 if (isset($data['invoice_title'])) {
362 $invoice->setTitle($data['invoice_title']);
363 }
364
365 if (isset($data['description'])) {
366 $invoice->setDescription($data['description']);
367 }
368
369 if (isset($data['invoice_description'])) {
370 $invoice->setDescription($data['invoice_description']);
371 }
372
373 // Set invoice number (only if not preserving existing)
374 if (isset($data['invoice_number']) && !empty($data['invoice_number'])) {
375 $invoice->setNumber($data['invoice_number']);
376 } elseif (isset($data['number']) && !empty($data['number'])) {
377 $invoice->setNumber($data['number']);
378 }
379
380 // Set dates
381 if (isset($data['issue_date'])) {
382 $invoice->setIssueDate($data['issue_date']);
383 }
384
385 if (isset($data['invoice_date'])) {
386 $invoice->setIssueDate($data['invoice_date']);
387 }
388
389 if (isset($data['issue-date'])) {
390 $invoice->setIssueDate($data['issue-date']);
391 }
392
393 if (isset($data['due_date'])) {
394 $invoice->setDueDate($data['due_date']);
395 }
396
397 if (isset($data['due-date'])) {
398 $invoice->setDueDate($data['due-date']);
399 }
400
401 // Set status
402 if (isset($data['status'])) {
403 $invoice->setStatus($data['status']);
404 }
405
406 if (isset($data['invoice_status'])) {
407 $invoice->setStatus($data['invoice_status']);
408 }
409
410 if (isset($data['payment_status'])) {
411 $invoice->setStatus($data['payment_status']);
412 }
413
414 // Set notes and terms
415 if (isset($data['notes'])) {
416 $invoice->setNotes($data['notes']);
417 }
418
419 if (isset($data['terms_and_conditions'])) {
420 $invoice->setTerms($data['terms_and_conditions']);
421 }
422
423 if (isset($data['internal_notes'])) {
424 $invoice->setInternalNotes($data['internal_notes']);
425 }
426
427 if (isset($data['payment_instructions'])) {
428 $invoice->setPaymentInstructions($data['payment_instructions']);
429 }
430
431 // Set payment gateways
432 if (isset($data['payment_gateways']) && is_array($data['payment_gateways'])) {
433 $invoice->setPaymentGateways($data['payment_gateways']);
434 } elseif (isset($data['payment_gateways']) && is_string($data['payment_gateways'])) {
435 $gateways = array_filter(explode(',', $data['payment_gateways']));
436 $invoice->setPaymentGateways($gateways);
437 } else {
438 $invoice->setPaymentGateways([]);
439 }
440
441 // Set payment gateways toggle state
442 if (isset($data['payment_gateways_toggle_state'])) {
443 $invoice->setPaymentGatewaysToggleState((string)$data['payment_gateways_toggle_state']);
444 }
445
446 // Set template
447 if (isset($data['invoice_template'])) {
448 $invoice->setTemplate($data['invoice_template']);
449 }
450
451 // Set client information
452 if (isset($data['customer_name'])) {
453 $invoice->setCustomerName($data['customer_name']);
454 }
455
456 if (isset($data['customer_address'])) {
457 $invoice->setCustomerAddress($data['customer_address']);
458 }
459
460 if (isset($data['customer_email'])) {
461 $invoice->setCustomerEmail($data['customer_email']);
462 }
463
464 // Set discount and tax settings
465 if (isset($data['discount_type'])) {
466 $invoice->setDiscountType($data['discount_type']);
467 }
468
469 if (isset($data['discount_value'])) {
470 $invoice->setDiscountValue($data['discount_value']);
471 }
472
473 if (isset($data['discount'])) {
474 $invoice->setDiscountValue($data['discount']);
475 }
476
477 if (isset($data['tax_rate'])) {
478 $invoice->setTaxRate($data['tax_rate']);
479 }
480
481 if (isset($data['calculation_method'])) {
482 $invoice->setCalculationMethod($data['calculation_method']);
483 }
484
485 if (isset($data['prices_include_tax'])) {
486 $invoice->setPricesIncludeTax($data['prices_include_tax']);
487 }
488
489 // Set currency settings
490 if (isset($data['currency_code'])) {
491 $invoice->setCurrencyCode($data['currency_code']);
492 }
493
494 if (isset($data['currency_position'])) {
495 $invoice->setCurrencyPosition($data['currency_position']);
496 }
497
498 // Set footer text
499 if (isset($data['footer_text'])) {
500 $invoice->setFooterText($data['footer_text']);
501 }
502
503 // Set client ID
504 if (isset($data['client_id']) && !empty($data['client_id'])) {
505 $invoice->setClientId((int) $data['client_id']);
506 }
507
508 // Set items
509 if (isset($data['items']) && is_array($data['items'])) {
510 $invoice->setItems($data['items']);
511 }
512
513 // Set custom fields
514 if (isset($data['custom_fields']) && is_array($data['custom_fields'])) {
515 $invoice->setCustomFields($data['custom_fields']);
516 }
517
518 // Set recurring fields
519 if (isset($data['recurring_enabled'])) {
520 $invoice->setRecurringEnabled((bool) $data['recurring_enabled']);
521 }
522
523 if (isset($data['recurring_frequency'])) {
524 $invoice->setRecurringFrequency($data['recurring_frequency']);
525 }
526
527 if (isset($data['recurring_interval'])) {
528 $invoice->setRecurringInterval((int) $data['recurring_interval']);
529 }
530
531 if (isset($data['recurring_start_date'])) {
532 $invoice->setRecurringStartDate($data['recurring_start_date']);
533 }
534
535 // Use configuration-driven approach for all other fields
536 $form_processor = new \EasyInvoice\Forms\FormProcessor();
537 $field_registration = new \EasyInvoice\Forms\Invoice\InvoiceFieldRegistration();
538
539 // Get all field definitions from all tabs
540 $field_definitions = [];
541 $tabs = $field_registration->getTabs();
542 foreach ($tabs as $tab_id => $tab) {
543 $tab_fields = $field_registration->getFields($tab_id);
544 foreach ($tab_fields as $field) {
545 $field_definitions[] = $field;
546 }
547 }
548
549 // Save form data using field configuration
550 $form_processor->saveFormDataToDatabase($data, $field_definitions, $invoice);
551
552 // Allow plugins to modify the data setting process
553 do_action('easy_invoice_invoice_set_data_after', $invoice, $data);
554 }
555 }