PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
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 / QuoteItem.php

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

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