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 / Forms / ItemFieldRenderer.php

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

323 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Item Field Renderer Class
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\Forms;
13
14 use EasyInvoice\Forms\BaseFieldRegistration;
15
16 /**
17 * Item Field Renderer
18 *
19 * Handles rendering of all invoice item field types.
20 *
21 * @since 1.0.0
22 */
23 class ItemFieldRenderer {
24
25 /**
26 * Render an item field
27 *
28 * @since 1.0.0
29 * @param array $field Field configuration
30 * @param int $item_index Item index
31 * @param string|null $item_value Current item value
32 * @return string Rendered HTML
33 */
34 public function renderItemField(array $field, int $item_index, ?string $item_value = ''): string {
35 $type = $field['type'] ?? 'text';
36 $method = 'renderItem' . ucfirst($type) . 'Field';
37
38 if (method_exists($this, $method)) {
39 return $this->$method($field, $item_index, $item_value);
40 }
41
42 // Fallback to text field
43 return $this->renderItemTextField($field, $item_index, $item_value);
44 }
45
46 /**
47 * Render an item text field
48 *
49 * @since 1.0.0
50 * @param array $field Field configuration
51 * @param int $item_index Item index
52 * @param string|null $item_value Current item value
53 * @return string Rendered HTML
54 */
55 private function renderItemTextField(array $field, int $item_index, ?string $item_value = ''): string {
56 $id = $field['id'] ?? '';
57 $name = $field['name'] ?? '';
58 $label = $field['label'] ?? '';
59 $placeholder = $field['placeholder'] ?? '';
60 $required = $field['required'] ?? false;
61 $readonly = $field['readonly'] ?? false;
62 $container_class = $field['container_class'] ?? 'sm:col-span-6';
63
64 $value = $item_value ?: ($field['default_value'] ?? '');
65 $description = $field['description'] ?? '';
66
67 $required_attr = $required ? 'required' : '';
68 $readonly_attr = $readonly ? 'readonly' : '';
69 $required_class = $required ? 'required' : '';
70 $description_html = $description ? '<p class="text-gray-500 mt-1 text-xs">' . esc_html($description) . '</p>' : '';
71
72 return sprintf(
73 '<div class="%s">
74 <label for="%s_%d" class="block text-sm font-bold text-gray-700 %s">%s</label>
75 <div class="mt-1">
76 <input type="text"
77 id="%s_%d"
78 name="items[%d][%s]"
79 value="%s"
80 placeholder="%s"
81 class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm %s"
82 %s %s>
83 %s
84 </div>
85 </div>',
86 esc_attr($container_class),
87 esc_attr($id),
88 $item_index,
89 esc_attr($required_class),
90 esc_html($label),
91 esc_attr($id),
92 $item_index,
93 $item_index,
94 esc_attr($name),
95 esc_attr($value),
96 esc_attr($placeholder),
97 esc_attr($required_class),
98 $required_attr,
99 $readonly_attr,
100 $description_html
101 );
102 }
103
104 /**
105 * Render an item textarea field
106 *
107 * @since 1.0.0
108 * @param array $field Field configuration
109 * @param int $item_index Item index
110 * @param string|null $item_value Current item value
111 * @return string Rendered HTML
112 */
113 private function renderItemTextareaField(array $field, int $item_index, ?string $item_value = ''): string {
114 $id = $field['id'] ?? '';
115 $name = $field['name'] ?? '';
116 $label = $field['label'] ?? '';
117 $placeholder = $field['placeholder'] ?? '';
118 $required = $field['required'] ?? false;
119 $readonly = $field['readonly'] ?? false;
120 $container_class = $field['container_class'] ?? 'sm:col-span-6';
121 $value = $item_value ?: ($field['default_value'] ?? '');
122 $rows = $field['rows'] ?? 3;
123 $description = $field['description'] ?? '';
124
125 $required_attr = $required ? 'required' : '';
126 $readonly_attr = $readonly ? 'readonly' : '';
127 $required_class = $required ? 'required' : '';
128 $description_html = $description ? '<p class="text-gray-500 mt-1 text-xs">' . esc_html($description) . '</p>' : '';
129
130 return sprintf(
131 '<div class="%s">
132 <label for="%s_%d" class="block text-sm font-bold text-gray-700 %s">%s</label>
133 <div class="mt-1">
134 <textarea id="%s_%d"
135 name="items[%d][%s]"
136 rows="%s"
137 placeholder="%s"
138 class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm %s"
139 %s %s>%s</textarea>
140 %s
141 </div>
142 </div>',
143 esc_attr($container_class),
144 esc_attr($id),
145 $item_index,
146 esc_attr($required_class),
147 esc_html($label),
148 esc_attr($id),
149 $item_index,
150 $item_index,
151 esc_attr($name),
152 esc_attr($rows),
153 esc_attr($placeholder),
154 esc_attr($required_class),
155 $required_attr,
156 $readonly_attr,
157 wp_kses_post($value),
158 $description_html
159 );
160 }
161
162 /**
163 * Render an item number field
164 *
165 * @since 1.0.0
166 * @param array $field Field configuration
167 * @param int $item_index Item index
168 * @param string $item_value Current item value
169 * @return string Rendered HTML
170 */
171 private function renderItemNumberField(array $field, int $item_index, ?string $item_value = ''): string {
172 $id = $field['id'] ?? '';
173 $name = $field['name'] ?? '';
174 $label = $field['label'] ?? '';
175 $placeholder = $field['placeholder'] ?? '';
176 $required = $field['required'] ?? false;
177 $readonly = $field['readonly'] ?? false;
178 $container_class = $field['container_class'] ?? 'sm:col-span-6';
179 $value = $item_value ?: ($field['default_value'] ?? '');
180 $min = $field['min'] ?? '';
181 $max = $field['max'] ?? '';
182 $step = $field['step'] ?? '';
183 $description = $field['description'] ?? '';
184
185 $required_attr = $required ? 'required' : '';
186 $readonly_attr = $readonly ? 'readonly' : '';
187 $required_class = $required ? 'required' : '';
188 $min_attr = $min !== '' ? 'min="' . esc_attr($min) . '"' : '';
189 $max_attr = $max !== '' ? 'max="' . esc_attr($max) . '"' : '';
190 $step_attr = $step !== '' ? 'step="' . esc_attr($step) . '"' : '';
191 $description_html = $description ? '<p class="text-gray-500 mt-1 text-xs">' . esc_html($description) . '</p>' : '';
192
193 return sprintf(
194 '<div class="%s">
195 <label for="%s_%d" class="block text-sm font-bold text-gray-700 %s">%s</label>
196 <div class="mt-1">
197 <input type="number"
198 id="%s_%d"
199 name="items[%d][%s]"
200 value="%s"
201 placeholder="%s"
202 class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm %s"
203 %s %s %s %s %s>
204 %s
205 </div>
206 </div>',
207 esc_attr($container_class),
208 esc_attr($id),
209 $item_index,
210 esc_attr($required_class),
211 esc_html($label),
212 esc_attr($id),
213 $item_index,
214 $item_index,
215 esc_attr($name),
216 esc_attr($value),
217 esc_attr($placeholder),
218 esc_attr($required_class),
219 $required_attr,
220 $readonly_attr,
221 $min_attr,
222 $max_attr,
223 $step_attr,
224 $description_html
225 );
226 }
227
228 /**
229 * Render an item checkbox field
230 *
231 * @since 1.0.0
232 * @param array $field Field configuration
233 * @param int $item_index Item index
234 * @param string $item_value Current item value
235 * @return string Rendered HTML
236 */
237 private function renderItemCheckboxField(array $field, int $item_index, ?string $item_value = ''): string {
238 $id = $field['id'] ?? '';
239 $name = $field['name'] ?? '';
240 $label = $field['label'] ?? '';
241 $required = $field['required'] ?? false;
242 $container_class = $field['container_class'] ?? 'sm:col-span-6';
243 // A new row (the template, index -1, or no stored value at all) takes
244 // the field's default; "Taxable" defaults to on, so a line added
245 // with tax enabled is taxed unless the merchant unticks it. A stored
246 // '0' stays off.
247 if (null === $item_value || '' === $item_value) {
248 $default = $field['default_value'] ?? '';
249 $item_value = is_callable($default) ? (string) $default() : (string) $default;
250 }
251 $value = ('1' === (string) $item_value || 'true' === (string) $item_value || 'yes' === (string) $item_value || 'on' === (string) $item_value);
252 $description = $field['description'] ?? '';
253 $required_attr = $required ? 'required' : '';
254 $required_class = $required ? 'required' : '';
255 $checked = ($value == '1' || $value === true) ? 'checked' : '';
256
257 $description_html = $description ? '<p class="text-gray-500 mt-1 text-xs">' . esc_html($description) . '</p>' : '';
258
259 return sprintf(
260 '<div class="%s">
261 <div class="flex items-start">
262 <div class="flex items-center h-5">
263 <input type="checkbox"
264 id="%s_%d"
265 name="items[%d][%s]"
266 value="1"
267 class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded %s"
268 %s %s>
269 </div>
270 <div class="ml-3 text-sm">
271 <label for="%s_%d" class="font-bold text-gray-700 %s">%s</label>
272 %s
273 </div>
274 </div>
275 </div>',
276 esc_attr($container_class),
277 esc_attr($id),
278 $item_index,
279 $item_index,
280 esc_attr($name),
281 esc_attr($required_class),
282 $checked,
283 $required_attr,
284 esc_attr($id),
285 $item_index,
286 esc_attr($required_class),
287 esc_html($label),
288 $description_html
289 );
290 }
291
292 /**
293 * Generate HTML for a blank (template) item
294 *
295 * @since 1.0.0
296 * @param BaseFieldRegistration|null $field_registration Optional field registration to use
297 * @return string
298 */
299 public function generateItemTemplateHtml($field_registration = null): string {
300 $html = '';
301
302 // If no field registration provided, use a default one
303 if (!$field_registration) {
304 // Try to determine the correct field registration based on context
305 // This is a fallback for backward compatibility
306 $field_registration = new \EasyInvoice\Forms\Invoice\InvoiceFieldRegistration();
307 }
308
309 $fields = $field_registration->getItemFields();
310
311 // Wrap fields in a grid container
312 $html .= '<div class="grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-4">';
313
314 // Use index -1 for template fields
315 foreach ($fields as $field) {
316 $html .= $this->renderItemField($field, -1, '');
317 }
318
319 $html .= '</div>';
320
321 return $html;
322 }
323 }