PluginProbe
SuperFrete / 3.3.2
SuperFrete v3.3.2
trunk 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4
superfrete / app / Controllers / DocumentFields.php

DocumentFields.php in SuperFrete 3.3.2, at app/Controllers/DocumentFields.php

478 lines 17.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SuperFrete_API\Controllers;
4
5 if (!defined('ABSPATH')) {
6 exit;
7 }
8
9 class DocumentFields
10 {
11 public function __construct()
12 {
13 error_log('SuperFrete DocumentFields: Constructor called - adding both classic and blocks support');
14
15 // Classic checkout support
16 add_filter('woocommerce_billing_fields', array($this, 'checkout_billing_fields'), 10);
17 add_filter('woocommerce_checkout_fields', array($this, 'add_document_to_checkout_fields'), 10);
18 add_action('woocommerce_checkout_process', array($this, 'valid_checkout_fields'), 10);
19 add_action('woocommerce_checkout_update_order_meta', array($this, 'save_document_field'));
20
21 // WooCommerce Blocks support
22 add_action('woocommerce_blocks_loaded', array($this, 'register_checkout_field_block'));
23 add_action('woocommerce_store_api_checkout_update_customer_from_request', array($this, 'save_document_from_blocks'), 10, 2);
24 add_action('woocommerce_rest_checkout_process_payment', array($this, 'validate_document_in_blocks'), 10, 2);
25 add_action('woocommerce_checkout_order_processed', array($this, 'save_document_from_checkout_blocks'), 10, 3);
26 add_action('woocommerce_store_api_checkout_order_data', array($this, 'save_document_from_store_api'), 10, 2);
27
28 // Display in admin and customer areas
29 add_action('woocommerce_admin_order_data_after_billing_address', array($this, 'display_document_in_admin'));
30 add_action('woocommerce_order_details_after_customer_details', array($this, 'display_document_in_order'));
31
32 // Add action to check what type of checkout is being used
33 add_action('wp_footer', array($this, 'debug_checkout_type'));
34
35 error_log('SuperFrete DocumentFields: All hooks added for both classic and blocks checkout');
36 }
37
38 /**
39 * New checkout billing fields - following reference plugin pattern
40 */
41 public function checkout_billing_fields($fields)
42 {
43 error_log('SuperFrete DocumentFields: checkout_billing_fields called with ' . count($fields) . ' fields');
44
45 $new_fields = array();
46
47 // Keep existing fields first
48 foreach ($fields as $key => $field) {
49 $new_fields[$key] = $field;
50 }
51
52 // Add document field after first/last name (similar to reference plugin)
53 $new_fields['billing_document'] = array(
54 'label' => __('CPF/CNPJ', 'superfrete'),
55 'placeholder' => __('Digite seu CPF ou CNPJ', 'superfrete'),
56 'class' => array('form-row-wide'),
57 'required' => true,
58 'type' => 'text',
59 'priority' => 25,
60 'custom_attributes' => array(
61 'pattern' => '[0-9\.\-\/]*',
62 'maxlength' => '18'
63 )
64 );
65
66 error_log('SuperFrete DocumentFields: Document field added to billing fields');
67 return $new_fields;
68 }
69
70 /**
71 * Add document field to checkout fields (alternative hook)
72 */
73 public function add_document_to_checkout_fields($fields)
74 {
75 error_log('SuperFrete DocumentFields: add_document_to_checkout_fields called');
76
77 if (isset($fields['billing'])) {
78 $fields['billing']['billing_document'] = array(
79 'label' => __('CPF/CNPJ', 'superfrete'),
80 'placeholder' => __('Digite seu CPF ou CNPJ', 'superfrete'),
81 'class' => array('form-row-wide'),
82 'required' => true,
83 'type' => 'text',
84 'priority' => 25,
85 'custom_attributes' => array(
86 'pattern' => '[0-9\.\-\/]*',
87 'maxlength' => '18'
88 )
89 );
90 error_log('SuperFrete DocumentFields: Document field added via checkout_fields hook');
91 }
92
93 return $fields;
94 }
95
96 /**
97 * Debug what type of checkout is being used
98 */
99 public function debug_checkout_type()
100 {
101 if (is_checkout()) {
102 error_log('SuperFrete DocumentFields: On checkout page - checking for blocks');
103
104 // Check if blocks checkout is being used
105 if (has_block('woocommerce/checkout')) {
106 error_log('SuperFrete DocumentFields: WooCommerce Blocks checkout detected');
107 } else {
108 error_log('SuperFrete DocumentFields: Classic checkout detected');
109 }
110
111 // Also check for checkout shortcode
112 global $post;
113 if ($post && has_shortcode($post->post_content, 'woocommerce_checkout')) {
114 error_log('SuperFrete DocumentFields: Checkout shortcode found');
115 }
116 }
117 }
118
119 /**
120 * Register checkout field for WooCommerce Blocks
121 */
122 public function register_checkout_field_block()
123 {
124 error_log('SuperFrete DocumentFields: Registering blocks checkout field using new Checkout Field API');
125
126 // Use the new WooCommerce 8.6+ Checkout Field API
127 if (function_exists('woocommerce_register_additional_checkout_field')) {
128 woocommerce_register_additional_checkout_field(array(
129 'id' => 'superfrete/document',
130 'label' => __('CPF/CNPJ', 'superfrete'),
131 'location' => 'contact',
132 'type' => 'text',
133 'required' => true,
134 'attributes' => array(
135 'data-1p-ignore' => 'true',
136 'data-lpignore' => 'true',
137 'autocomplete' => 'off',
138 ),
139 'validate_callback' => array($this, 'validate_document_callback'),
140 'sanitize_callback' => 'sanitize_text_field',
141 ));
142
143 error_log('SuperFrete DocumentFields: Document field registered using Checkout Field API');
144 } else {
145 error_log('SuperFrete DocumentFields: Checkout Field API not available, trying legacy Store API approach');
146
147 // Fallback to legacy Store API approach
148 if (function_exists('woocommerce_store_api_register_endpoint_data')) {
149 woocommerce_store_api_register_endpoint_data(array(
150 'endpoint' => \Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema::IDENTIFIER,
151 'namespace' => 'superfrete',
152 'data_callback' => array($this, 'add_checkout_field_data'),
153 'schema_callback' => array($this, 'add_checkout_field_schema'),
154 ));
155 }
156 }
157 }
158
159 /**
160 * Validate document callback for Checkout Field API
161 */
162 public function validate_document_callback($field_value, $errors)
163 {
164 error_log('SuperFrete DocumentFields: Validating document via Checkout Field API: ' . $field_value);
165
166 if (empty($field_value)) {
167 return new \WP_Error('superfrete_document_required', __('CPF/CNPJ é um campo obrigatório.', 'superfrete'));
168 }
169
170 if (!$this->is_valid_document($field_value)) {
171 return new \WP_Error('superfrete_document_invalid', __('CPF/CNPJ não é válido.', 'superfrete'));
172 }
173
174 return true;
175 }
176
177 /**
178 * Add checkout field data for blocks
179 */
180 public function add_checkout_field_data()
181 {
182 return array(
183 'document' => ''
184 );
185 }
186
187 /**
188 * Add checkout field schema for blocks
189 */
190 public function add_checkout_field_schema()
191 {
192 return array(
193 'document' => array(
194 'description' => 'Customer document (CPF/CNPJ)',
195 'type' => 'string',
196 'context' => array('view', 'edit'),
197 'required' => true,
198 ),
199 );
200 }
201
202 /**
203 * Save document from blocks checkout
204 */
205 public function save_document_from_blocks($customer, $request)
206 {
207 error_log('SuperFrete DocumentFields: Saving document from blocks');
208
209 $document = $request->get_param('billing_document');
210 if ($document) {
211 $customer->update_meta_data('billing_document', sanitize_text_field($document));
212 }
213 }
214
215 /**
216 * Validate document in blocks checkout
217 */
218 public function validate_document_in_blocks($request, $errors)
219 {
220 error_log('SuperFrete DocumentFields: Validating document in blocks');
221
222 $document = $request->get_param('billing_document');
223 if (empty($document)) {
224 $errors->add('billing_document_required', __('CPF/CNPJ é um campo obrigatório.', 'superfrete'));
225 } elseif (!$this->is_valid_document($document)) {
226 $errors->add('billing_document_invalid', __('CPF/CNPJ não é válido.', 'superfrete'));
227 }
228 }
229
230 /**
231 * Save document from checkout blocks using order processed hook
232 */
233 public function save_document_from_checkout_blocks($order_id, $posted_data, $order)
234 {
235 error_log('SuperFrete DocumentFields: save_document_from_checkout_blocks called for order ' . $order_id);
236 error_log('SuperFrete DocumentFields: Posted data keys: ' . implode(', ', array_keys($posted_data)));
237
238 // Try to find the document field in posted data
239 $document = '';
240
241 // Check various possible field names for blocks checkout
242 $possible_keys = array(
243 'superfrete/document',
244 'superfrete--document',
245 'billing_document',
246 'extensions',
247 );
248
249 foreach ($possible_keys as $key) {
250 if (isset($posted_data[$key])) {
251 if ($key === 'extensions' && is_array($posted_data[$key])) {
252 // Look for our field in extensions array
253 if (isset($posted_data[$key]['superfrete']) && isset($posted_data[$key]['superfrete']['document'])) {
254 $document = sanitize_text_field($posted_data[$key]['superfrete']['document']);
255 error_log('SuperFrete DocumentFields: Found document in extensions: ' . $document);
256 break;
257 }
258 } else {
259 $document = sanitize_text_field($posted_data[$key]);
260 error_log('SuperFrete DocumentFields: Found document in ' . $key . ': ' . $document);
261 break;
262 }
263 }
264 }
265
266 if (!empty($document)) {
267 $order->update_meta_data('_billing_document', $document);
268 $order->update_meta_data('_superfrete_document', $document);
269 $order->save();
270 error_log('SuperFrete DocumentFields: Document saved from blocks checkout: ' . $document);
271 } else {
272 error_log('SuperFrete DocumentFields: No document found in blocks checkout data');
273 }
274 }
275
276 /**
277 * Save document from Store API order data
278 */
279 public function save_document_from_store_api($order_data, $request)
280 {
281 error_log('SuperFrete DocumentFields: save_document_from_store_api called');
282 error_log('SuperFrete DocumentFields: Order data keys: ' . implode(', ', array_keys($order_data)));
283
284 // Check if our field is in the request
285 $document_value = '';
286
287 // Try to get the field value from various possible locations
288 if (method_exists($request, 'get_param')) {
289 $extensions = $request->get_param('extensions');
290 if (is_array($extensions) && isset($extensions['superfrete']) && isset($extensions['superfrete']['document'])) {
291 $document_value = sanitize_text_field($extensions['superfrete']['document']);
292 error_log('SuperFrete DocumentFields: Found document in extensions: ' . $document_value);
293 }
294
295 // Also try direct parameter
296 $direct_value = $request->get_param('superfrete/document');
297 if ($direct_value) {
298 $document_value = sanitize_text_field($direct_value);
299 error_log('SuperFrete DocumentFields: Found document in direct param: ' . $document_value);
300 }
301 }
302
303 // If we found a document value, add it to the order data meta
304 if (!empty($document_value)) {
305 if (!isset($order_data['meta_data'])) {
306 $order_data['meta_data'] = array();
307 }
308
309 $order_data['meta_data'][] = array(
310 'key' => '_billing_document',
311 'value' => $document_value
312 );
313 $order_data['meta_data'][] = array(
314 'key' => '_superfrete_document',
315 'value' => $document_value
316 );
317
318 error_log('SuperFrete DocumentFields: Added document to order meta data: ' . $document_value);
319 } else {
320 error_log('SuperFrete DocumentFields: No document found in Store API request');
321 }
322
323 return $order_data;
324 }
325
326 /**
327 * Valid checkout fields - following reference plugin pattern
328 */
329 public function valid_checkout_fields()
330 {
331 error_log('SuperFrete DocumentFields: valid_checkout_fields called');
332
333 if (empty($_POST['billing_document'])) {
334 wc_add_notice(sprintf('<strong>%s</strong> %s.', __('CPF/CNPJ', 'superfrete'), __('é um campo obrigatório', 'superfrete')), 'error');
335 return;
336 }
337
338 $document = sanitize_text_field($_POST['billing_document']);
339
340 if (!$this->is_valid_document($document)) {
341 wc_add_notice(sprintf('<strong>%s</strong> %s.', __('CPF/CNPJ', 'superfrete'), __('não é válido', 'superfrete')), 'error');
342 }
343 }
344
345 /**
346 * Save document field to order meta
347 */
348 public function save_document_field($order_id)
349 {
350 error_log('SuperFrete DocumentFields: save_document_field called for order ' . $order_id);
351
352 // Handle both classic checkout and blocks checkout
353 $document = '';
354
355 // Try to get from POST (classic checkout)
356 if (!empty($_POST['billing_document'])) {
357 $document = sanitize_text_field($_POST['billing_document']);
358 error_log('SuperFrete DocumentFields: Document from POST: ' . $document);
359 }
360
361 // Try to get from blocks checkout field
362 if (empty($document) && !empty($_POST['superfrete--document'])) {
363 $document = sanitize_text_field($_POST['superfrete--document']);
364 error_log('SuperFrete DocumentFields: Document from blocks field: ' . $document);
365 }
366
367 // Also try the namespaced field format
368 if (empty($document) && !empty($_POST['superfrete/document'])) {
369 $document = sanitize_text_field($_POST['superfrete/document']);
370 error_log('SuperFrete DocumentFields: Document from namespaced field: ' . $document);
371 }
372
373 if (!empty($document)) {
374 $order = wc_get_order($order_id);
375 if ($order) {
376 $order->update_meta_data('_billing_document', $document);
377 $order->update_meta_data('_superfrete_document', $document);
378 $order->save();
379 error_log('SuperFrete DocumentFields: Document saved to order meta: ' . $document);
380 }
381 } else {
382 error_log('SuperFrete DocumentFields: No document found in POST data');
383 error_log('SuperFrete DocumentFields: POST keys: ' . implode(', ', array_keys($_POST)));
384 }
385 }
386
387 /**
388 * Display document in admin order details
389 */
390 public function display_document_in_admin($order)
391 {
392 $document = $order->get_meta('_billing_document');
393 if ($document) {
394 echo '<p><strong>' . __('CPF/CNPJ:', 'superfrete') . '</strong> ' . esc_html($document) . '</p>';
395 }
396 }
397
398 /**
399 * Display document in customer order details
400 */
401 public function display_document_in_order($order)
402 {
403 $document = $order->get_meta('_billing_document');
404 if ($document) {
405 echo '<p><strong>' . __('CPF/CNPJ:', 'superfrete') . '</strong> ' . esc_html($document) . '</p>';
406 }
407 }
408
409 /**
410 * Validate if document is a valid CPF or CNPJ - using reference plugin algorithms
411 */
412 private function is_valid_document($document)
413 {
414 $document = preg_replace('/[^0-9]/', '', $document);
415
416 if (strlen($document) == 11) {
417 return $this->is_cpf($document);
418 } elseif (strlen($document) == 14) {
419 return $this->is_cnpj($document);
420 }
421
422 return false;
423 }
424
425 /**
426 * Checks if the CPF is valid - exact copy from reference plugin
427 */
428 private function is_cpf($cpf)
429 {
430 $cpf = preg_replace('/[^0-9]/', '', $cpf);
431
432 if (11 !== strlen($cpf) || preg_match('/^([0-9])\1+$/', $cpf)) {
433 return false;
434 }
435
436 $digit = substr($cpf, 0, 9);
437
438 for ($j = 10; $j <= 11; $j++) {
439 $sum = 0;
440
441 for ($i = 0; $i < $j - 1; $i++) {
442 $sum += ($j - $i) * intval($digit[$i]);
443 }
444
445 $summod11 = $sum % 11;
446 $digit[$j - 1] = $summod11 < 2 ? 0 : 11 - $summod11;
447 }
448
449 return intval($digit[9]) === intval($cpf[9]) && intval($digit[10]) === intval($cpf[10]);
450 }
451
452 /**
453 * Checks if the CNPJ is valid - exact copy from reference plugin
454 */
455 private function is_cnpj($cnpj)
456 {
457 $cnpj = sprintf('%014s', preg_replace('{\D}', '', $cnpj));
458
459 if (14 !== strlen($cnpj) || 0 === intval(substr($cnpj, -4))) {
460 return false;
461 }
462
463 for ($t = 11; $t < 13;) {
464 for ($d = 0, $p = 2, $c = $t; $c >= 0; $c--, ($p < 9) ? $p++ : $p = 2) {
465 $d += $cnpj[$c] * $p;
466 }
467
468 $d = ((10 * $d) % 11) % 10;
469 if (intval($cnpj[++$t]) !== $d) {
470 return false;
471 }
472 }
473
474 return true;
475 }
476 }
477
478 new \SuperFrete_API\Controllers\DocumentFields();