PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.1
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.1
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 / Client.php

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

226 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Client Model Class
4 *
5 * @package Easy_Invoice
6 * @subpackage Models
7 */
8
9 namespace EasyInvoice\Models;
10
11 use EasyInvoice\Constants\ClientFields;
12
13 /**
14 * Client Class
15 *
16 * Represents a client entity.
17 */
18 class Client {
19 /**
20 * The client ID (WP user ID)
21 *
22 * @var int
23 */
24 protected $id = 0;
25
26 /**
27 * Client data array
28 *
29 * @var array
30 */
31 protected $data = [];
32
33 /**
34 * Whether the data is dirty/changed
35 *
36 * @var bool
37 */
38 protected $is_dirty = false;
39
40 /**
41 * Constructor
42 *
43 * @param int|array $id_or_data The client ID or data array
44 */
45 public function __construct($id_or_data = 0) {
46 if (is_array($id_or_data)) {
47 $this->data = $id_or_data;
48 $this->id = isset($id_or_data['id']) ? (int) $id_or_data['id'] : 0;
49 } else {
50 $this->id = (int) $id_or_data;
51 // Load data from user meta if we have a valid ID
52 if ($this->id > 0) {
53 $this->loadFromUserMeta();
54 }
55 }
56 }
57
58 /**
59 * Magic method to get dynamic properties
60 *
61 * @since 1.0.0
62 * @param string $name Property name
63 * @return mixed Property value
64 */
65 public function __get($name) {
66 // Handle special properties
67 if ($name === 'id') {
68 return $this->id;
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_dirty = 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 * Dynamic getter method
111 *
112 * @since 1.0.0
113 * @param string $name Method name
114 * @param array $arguments Method arguments
115 * @return mixed
116 */
117 public function __call($name, $arguments) {
118 // Handle getter methods (getFieldName)
119 if (strpos($name, 'get') === 0) {
120 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'get' prefix
121 return $this->__get($field_name);
122 }
123
124 // Handle setter methods (setFieldName)
125 if (strpos($name, 'set') === 0) {
126 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'set' prefix
127 $value = $arguments[0] ?? null;
128 $this->__set($field_name, $value);
129 return null;
130 }
131
132 // Handle isset methods (isFieldName)
133 if (strpos($name, 'is') === 0) {
134 $field_name = $this->camelCaseToSnakeCase(substr($name, 2)); // Remove 'is' prefix
135 return (bool) $this->__get($field_name);
136 }
137
138 // Handle has methods (hasFieldName)
139 if (strpos($name, 'has') === 0) {
140 $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'has' prefix
141 return !empty($this->__get($field_name));
142 }
143
144 throw new \BadMethodCallException(esc_html("Method $name does not exist"));
145 }
146
147 /**
148 * Convert camelCase to snake_case
149 *
150 * @since 1.0.0
151 * @param string $camelCase
152 * @return string
153 */
154 private function camelCaseToSnakeCase($camelCase) {
155 return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $camelCase));
156 }
157
158 /**
159 * Load client data from user meta
160 */
161 protected function loadFromUserMeta() {
162 if ($this->id <= 0) {
163 return;
164 }
165
166 // Easy-Invoice-owned meta (what the user explicitly set through this plugin).
167 $this->data['business_client_name'] = get_user_meta($this->id, ClientFields::BUSINESS_CLIENT_NAME, true);
168 $this->data['email'] = get_user_meta($this->id, ClientFields::EMAIL, true);
169 $this->data['username'] = get_user_meta($this->id, ClientFields::USERNAME, true);
170 $this->data['address'] = get_user_meta($this->id, ClientFields::ADDRESS, true);
171 $this->data['extra_info'] = get_user_meta($this->id, ClientFields::EXTRA_INFO, true);
172 $this->data['first_name'] = get_user_meta($this->id, ClientFields::FIRST_NAME, true);
173 $this->data['last_name'] = get_user_meta($this->id, ClientFields::LAST_NAME, true);
174 $this->data['website'] = get_user_meta($this->id, ClientFields::WEBSITE, true);
175 $this->data['phone'] = get_user_meta($this->id, ClientFields::PHONE, true);
176
177 // Fallback chain for clients NOT created through Easy Invoice
178 // (typically WooCommerce customers imported via order placement,
179 // or plain WP users with profile fields filled in):
180 //
181 // 1. EI meta (above) — explicit entry in Easy Invoice
182 // 2. WP standard meta — user profile / WC sync
183 // 3. WC billing_* meta — set the first time a customer checks out
184 //
185 // Without this fallback, WooCommerce customers render as their bare
186 // user_login (e.g. "callum_smith42") everywhere — Clients listing,
187 // invoice builder client-search dropdown, and invoice header — even
188 // though their real name sits in billing_first_name / billing_last_name.
189 $user = get_user_by('id', $this->id);
190
191 if (empty($this->data['email'])) {
192 $this->data['email'] = $user ? (string) $user->user_email : '';
193 if (empty($this->data['email'])) {
194 $this->data['email'] = (string) get_user_meta($this->id, 'billing_email', true);
195 }
196 }
197 if (empty($this->data['username'])) {
198 $this->data['username'] = $user ? (string) $user->user_login : '';
199 }
200 if (empty($this->data['first_name'])) {
201 $this->data['first_name'] = $user ? (string) $user->first_name : '';
202 if (empty($this->data['first_name'])) {
203 $this->data['first_name'] = (string) get_user_meta($this->id, 'billing_first_name', true);
204 }
205 }
206 if (empty($this->data['last_name'])) {
207 $this->data['last_name'] = $user ? (string) $user->last_name : '';
208 if (empty($this->data['last_name'])) {
209 $this->data['last_name'] = (string) get_user_meta($this->id, 'billing_last_name', true);
210 }
211 }
212 if (empty($this->data['business_client_name'])) {
213 $this->data['business_client_name'] = (string) get_user_meta($this->id, 'billing_company', true);
214 }
215 if (empty($this->data['phone'])) {
216 $this->data['phone'] = (string) get_user_meta($this->id, 'billing_phone', true);
217 }
218 }
219
220 // Essential methods only
221 public function getId(): int { return $this->id; }
222 public function setId(int $id): void { $this->id = $id; }
223 public function isDirty(): bool { return $this->is_dirty; }
224 public function resetDirty() { $this->is_dirty = false; return $this; }
225 public function toArray(): array { return array_merge(['id' => $this->id], $this->data); }
226 }