PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.2
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.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 / Models / InvoiceItem.php

InvoiceItem.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.3.2, at includes/Models/InvoiceItem.php

262 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Invoice Item Model
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\Models;
13
14 use WP_Post;
15
16 /**
17 * InvoiceItem Class
18 *
19 * Represents an invoice item.
20 */
21 class InvoiceItem {
22 /**
23 * Item ID
24 *
25 * @var int
26 */
27 private $id;
28
29 /**
30 * Invoice ID
31 *
32 * @var int
33 */
34 private $invoice_id;
35
36 /**
37 * Dynamic data storage for all fields
38 *
39 * @var array
40 */
41 private $data = [];
42
43 /**
44 * Modified flag
45 *
46 * @var bool
47 */
48 private $is_modified = false;
49
50 /**
51 * Whether this item is based on a post
52 *
53 * @var bool
54 */
55 private $is_post = false;
56
57 /**
58 * Constructor
59 *
60 * @param WP_Post|array $data The item data (WP_Post object or array)
61 */
62 public function __construct($data) {
63 $this->data = $data;
64
65 if ($data instanceof \WP_Post) {
66 $this->is_post = true;
67 $this->id = $data->ID;
68 } elseif (is_array($data)) {
69 $this->is_post = false;
70 $this->id = isset($data['id']) ? intval($data['id']) : 0;
71 }
72 }
73
74 /**
75 * Magic method to get dynamic properties
76 *
77 * @since 1.0.0
78 * @param string $name Property name
79 * @return mixed Property value
80 */
81 public function __get($name) {
82 // Handle special properties
83 if ($name === 'id') {
84 return $this->id;
85 }
86
87 // Handle name/title compatibility
88 if ($name === 'name' && empty($this->data[$name]) && !empty($this->data['title'])) {
89 return $this->data['title'];
90 }
91 if ($name === 'title' && empty($this->data[$name]) && !empty($this->data['name'])) {
92 return $this->data['name'];
93 }
94
95 // Return from dynamic data array
96 return $this->data[$name] ?? null;
97 }
98
99 /**
100 * Magic method to set dynamic properties
101 *
102 * @since 1.0.0
103 * @param string $name Property name
104 * @param mixed $value Property value
105 */
106 public function __set($name, $value) {
107 // Handle special properties
108 if ($name === 'id') {
109 $this->id = $value;
110 return;
111 }
112
113 // Store in dynamic data array
114 $this->data[$name] = $value;
115 $this->is_modified = true;
116 }
117
118 /**
119 * Magic method to check if property exists
120 *
121 * @since 1.0.0
122 * @param string $name Property name
123 * @return bool
124 */
125 public function __isset($name) {
126 if ($name === 'id') {
127 return isset($this->id);
128 }
129
130 return isset($this->data[$name]);
131 }
132
133 /**
134 * Dynamic getter method
135 *
136 * @since 1.0.0
137 * @param string $name Method name
138 * @param array $arguments Method arguments
139 * @return mixed
140 */
141 public function __call($name, $arguments) {
142 // Handle getter methods (getFieldName)
143 if (strpos($name, 'get') === 0) {
144 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'get' prefix
145
146 // Special handling for getName() to check both 'name' and 'title' fields
147 if ($field_name === 'name') {
148 if (!empty($this->data['name'])) {
149 return $this->data['name'];
150 } elseif (!empty($this->data['title'])) {
151 return $this->data['title'];
152 }
153 return null;
154 }
155
156 return $this->__get($field_name);
157 }
158
159 // Handle setter methods (setFieldName)
160 if (strpos($name, 'set') === 0) {
161 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'set' prefix
162 $value = $arguments[0] ?? null;
163 $this->__set($field_name, $value);
164 return null;
165 }
166
167 // Handle isset methods (isFieldName)
168 if (strpos($name, 'is') === 0) {
169 $field_name = $this->camelCaseToSnakeCase(substr($name, 2)); // Remove 'is' prefix
170 return (bool) $this->__get($field_name);
171 }
172
173 // Handle has methods (hasFieldName)
174 if (strpos($name, 'has') === 0) {
175 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'has' prefix
176 return !empty($this->__get($field_name));
177 }
178
179 throw new \BadMethodCallException("Method $name does not exist");
180 }
181
182 /**
183 * Convert camelCase to snake_case
184 *
185 * @since 1.0.0
186 * @param string $camelCase
187 * @return string
188 */
189 private function camelCaseToSnakeCase($camelCase) {
190 return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $camelCase));
191 }
192
193 /**
194 * Get all data as array
195 *
196 * @since 1.0.0
197 * @return array
198 */
199 public function toArray(): array {
200 $data = $this->data;
201 $data['id'] = $this->id;
202 // Ensure taxable field is properly set as a boolean
203 $data['taxable'] = $this->isTaxable();
204 return $data;
205 }
206
207 /**
208 * Get data array
209 *
210 * @since 1.0.0
211 * @return array
212 */
213 public function getData(): array {
214 return $this->data;
215 }
216
217 // Essential methods only
218 public function getId(): int { return $this->id; }
219 public function setId(int $id): void { $this->id = $id; }
220 public function isDirty(): bool { return $this->is_modified; }
221 public function resetDirty() { $this->is_modified = false; return $this; }
222
223 /**
224 * Get the calculated amount for this item
225 *
226 * @since 1.0.0
227 * @return float The calculated amount
228 */
229 public function getAmount(): float {
230 $quantity = floatval($this->data['quantity'] ?? 0);
231 $price = floatval($this->data['price'] ?? 0);
232
233 // Calculate base total
234 $base_total = $quantity * $price;
235
236 // Only apply adjustment percentage if the adjust field setting is enabled
237 if (\EasyInvoice\Controllers\SettingsController::shouldShowInvoiceAdjustField()) {
238 $adjust_percentage = floatval($this->data['adjust_percentage'] ?? 0);
239 if ($adjust_percentage != 0) {
240 $base_total = $base_total * (1 + $adjust_percentage / 100);
241 }
242 }
243
244 return $base_total;
245 }
246
247 /**
248 * Check if the item is taxable
249 *
250 * @since 1.0.0
251 * @return bool
252 */
253 public function isTaxable(): bool {
254 // Convert various values to boolean
255 $value = $this->data['taxable'] ?? true;
256 if (is_string($value)) {
257 $value = strtolower($value);
258 return $value === '1' || $value === 'true' || $value === 'yes' || $value === 'on';
259 }
260 return (bool) $value;
261 }
262 }