Changeset 3472269
- Timestamp:
- 03/01/2026 10:12:26 PM (9 days ago)
- Location:
- forms-bridge/trunk
- Files:
-
- 6 edited
-
addons/odoo/class-odoo-form-bridge.php (modified) (2 diffs)
-
deps/http/includes/class-backend.php (modified) (8 diffs)
-
forms-bridge.php (modified) (1 diff)
-
includes/class-forms-bridge.php (modified) (5 diffs)
-
integrations/wpforms/class-wpforms-integration.php (modified) (8 diffs)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
forms-bridge/trunk/addons/odoo/class-odoo-form-bridge.php
r3456613 r3472269 143 143 */ 144 144 private static function rpc_login( $login, $backend ) { 145 if ( self::$session ) { 146 return self::$session; 147 } 148 145 149 $session_id = 'forms-bridge-' . time(); 146 150 … … 195 199 return new WP_Error( 196 200 'invalid_credential', 197 'The bridge does not have a valid credential' 201 'The bridge does not have a valid credential', 202 $backend->data(), 198 203 ); 199 204 } -
forms-bridge/trunk/deps/http/includes/class-backend.php
r3455079 r3472269 296 296 'opaque' => null, 297 297 ); 298 298 299 foreach ( array_keys( $fields ) as $field ) { 299 if ( 300 ! preg_match( "/{$field}=\"([^\"]+)\"/", $digest_header, $matches ) 301 ) { 300 if ( ! preg_match( "/{$field}=\"([^\"]+)\"/", $digest_header, $matches ) ) { 302 301 return $error; 303 302 } … … 314 313 $uri = $parsed_url['path'] ?? ''; 315 314 316 $a1 = md5( 317 "{$credential->client_id}:{$credential->realm}:{$credential->client_secret}" 318 ); 315 $a1 = md5( "{$credential->client_id}:{$credential->realm}:{$credential->client_secret}" ); 319 316 $a2 = md5( "{$this->method}:{$this->endpoint}" ); 320 317 $response = md5( "{$a1}:{$fields['nonce']}:{$a2}" ); … … 332 329 * @param array $params URL query params. 333 330 * @param array $headers Additional HTTP headers. 331 * @param array $args Additional request args. 334 332 * 335 333 * @return array|WP_Error Request response. 336 334 */ 337 public function head( $endpoint, $params = array(), $headers = array() ) {335 public function head( $endpoint, $params = array(), $headers = array(), $args = array() ) { 338 336 if ( ! $this->is_valid ) { 339 337 return new WP_Error( 'invalid_backend' ); … … 342 340 $url = $this->url( $endpoint ); 343 341 $headers = array_merge( $this->headers(), (array) $headers ); 344 $response = forms_bridge_http_head( $url, $params, $headers ); 342 $response = forms_bridge_http_head( $url, $params, $headers, $args ); 343 345 344 return $this->handle_response( $response ); 346 345 } … … 390 389 } 391 390 392 $url = $this->url( $endpoint ); 393 $headers = array_merge( $this->headers(), (array) $headers ); 394 return forms_bridge_http_post( $url, $data, $headers, $files, $args ); 391 $url = $this->url( $endpoint ); 392 $headers = array_merge( $this->headers(), (array) $headers ); 393 $response = forms_bridge_http_post( $url, $data, $headers, $files, $args ); 394 395 return $this->handle_response( $response ); 395 396 } 396 397 … … 417 418 } 418 419 419 $url = $this->url( $endpoint ); 420 $headers = array_merge( $this->headers(), (array) $headers ); 421 return forms_bridge_http_put( $url, $data, $headers, $files, $args ); 420 $url = $this->url( $endpoint ); 421 $headers = array_merge( $this->headers(), (array) $headers ); 422 $response = forms_bridge_http_put( $url, $data, $headers, $files, $args ); 423 424 return $this->handle_response( $response ); 422 425 } 423 426 … … 444 447 } 445 448 446 $url = $this->url( $endpoint ); 447 $headers = array_merge( $this->headers(), (array) $headers ); 448 return forms_bridge_http_patch( $url, $data, $headers, $files, $args ); 449 $url = $this->url( $endpoint ); 450 $headers = array_merge( $this->headers(), (array) $headers ); 451 $response = forms_bridge_http_patch( $url, $data, $headers, $files, $args ); 452 453 return $this->handle_response( $response ); 449 454 } 450 455 … … 464 469 } 465 470 466 $url = $this->url( $endpoint ); 467 $headers = array_merge( $this->headers(), (array) $headers ); 468 return forms_bridge_http_delete( $url, $params, $headers, $args ); 471 $url = $this->url( $endpoint ); 472 $headers = array_merge( $this->headers(), (array) $headers ); 473 $response = forms_bridge_http_delete( $url, $params, $headers, $args ); 474 475 return $this->handle_response( $response ); 469 476 } 470 477 -
forms-bridge/trunk/forms-bridge.php
r3463692 r3472269 10 10 * Text Domain: forms-bridge 11 11 * Domain Path: /languages 12 * Version: 4.4. 312 * Version: 4.4.4 13 13 * Requires PHP: 8.0 14 14 * Requires at least: 6.7 -
forms-bridge/trunk/includes/class-forms-bridge.php
r3451059 r3472269 50 50 */ 51 51 private static $current_bridge; 52 53 /** 54 * Handles the current bridge request. Available only during form submissions. 55 * 56 * @var array|null 57 */ 58 private static $current_request; 52 59 53 60 /** … … 302 309 303 310 if ( ! $bridge->enabled ) { 304 Logger::log( 305 'Skip submission for disabled bridge ' . $bridge->name 306 ); 311 Logger::log( "Skip submission for disabled bridge '{$bridge->name}'" ); 307 312 continue; 308 313 } 309 314 310 315 self::$current_bridge = $bridge; 316 317 Logger::log( "Start submission for bridge '{$bridge->name}'" ); 311 318 312 319 try { … … 408 415 ); 409 416 417 add_action( 'forms_bridge_http_before_request', array( self::class, 'http_request_interceptor' ), 99, 1 ); 418 410 419 $response = $bridge->submit( $payload, $attachments ); 411 420 … … 419 428 $attachments 420 429 ); 430 431 if ( 432 false === $bridge->allow_failure 433 && count( $bridges ) > 1 434 && $i < count( $bridges ) - 1 435 ) { 436 Logger::log( 'Early exit from the submission loop due to an error', Logger::ERROR ); 437 break; 438 } 421 439 } else { 440 if ( self::$current_request ) { 441 Logger::log( 'Submission request' ); 442 Logger::log( self::$current_request ); 443 } 444 422 445 Logger::log( 'Submission response' ); 423 446 Logger::log( $response ); … … 463 486 } 464 487 } finally { 465 self::$current_bridge = null; 466 } 467 } 488 self::$current_bridge = null; 489 self::$current_request = null; 490 491 remove_action( 'forms_bridge_http_before_request', array( self::class, 'http_request_interceptor' ), 99 ); 492 } 493 } 494 } 495 496 /** 497 * Intercepts http requests and, if request matches with current bridge endpoint, 498 * stores its params. 499 * 500 * @param array $request Current HTTP request params. 501 * 502 * @return array 503 */ 504 public static function http_request_interceptor( $request ) { 505 if ( ! self::$current_bridge ) { 506 return $request; 507 } 508 509 $backend = self::$current_bridge->backend; 510 if ( ! $backend ) { 511 return $request; 512 } 513 514 $url = $backend->url( self::$current_bridge->endpoint ); 515 if ( $url === $request['url'] ) { 516 self::$current_request = $request; 517 } 518 519 return $request; 468 520 } 469 521 -
forms-bridge/trunk/integrations/wpforms/class-wpforms-integration.php
r3442111 r3472269 415 415 'schema' => $this->field_value_schema( $field, $type, $children ), 416 416 'basetype' => $field['type'], 417 'dynamic' => ! empty( $field['dynamic_choices'] ), 417 418 ), 418 419 $field, … … 430 431 */ 431 432 private function is_multi_field( $field, $norm_type ) { 432 if ( 'checkbox' === $field['type']&& 'select' === $norm_type ) {433 if ( ( 'checkbox' === $field['type'] || 'payment-checkbox' === $field['type'] ) && 'select' === $norm_type ) { 433 434 return true; 434 435 } … … 467 468 case 'text': 468 469 case 'textarea': 469 case 'payment-total':470 470 case 'payment-single': 471 case 'radio':472 471 case 'password': 473 472 case 'url': 474 473 return array( 'type' => 'string' ); 474 case 'payment-total': 475 475 case 'number-slider': 476 476 case 'number': … … 480 480 case 'payment-checkbox': 481 481 case 'select': 482 if ( $field['multiple'] ?? false ) {483 $items = array();484 $count = count( $field['choices'] );485 for ( $i = 0; $i < $count; $i++ ) {486 $items[] = array( 'type' => 'string' );487 }488 489 return array(490 'type' => 'array',491 'items' => $items,492 'additionalItems' => false,493 );494 }495 496 return array( 'type' => 'string' );497 482 case 'checkbox': 483 case 'radio': 498 484 if ( 'checkbox' === $norm_type ) { 499 485 return array( 'type' => 'boolean' ); 500 486 } 501 487 502 $items = array(); 503 $count = count( $field['choices'] ); 504 for ( $i = 0; $i < $count; $i++ ) { 505 $items[] = array( 'type' => 'string' ); 506 } 507 508 return array( 509 'type' => 'array', 510 'items' => $items, 511 'additionalItems' => false, 512 ); 488 if ( $field['multiple'] ?? false || false !== strstr( $field['type'], 'checkbox' ) ) { 489 if ( ! empty( $field['dynamic_choices'] ) ) { 490 return array( 491 'type' => 'array', 492 'items' => array( 493 'type' => 'object', 494 'properties' => array( 495 'value' => array( 'type' => 'string' ), 496 'id' => array( 'type' => 'integer' ), 497 ), 498 ), 499 ); 500 } 501 502 return array( 503 'type' => 'array', 504 'items' => array( 'type' => 'string' ), 505 ); 506 } 507 508 if ( ! empty( $field['dynamic_choices'] ) ) { 509 return array( 510 'type' => 'object', 511 'properties' => array( 512 'value' => array( 'type' => 'string' ), 513 'id' => array( 'type' => 'integer' ), 514 ), 515 ); 516 } 517 518 return array( 'type' => 'string' ); 513 519 case 'date-time': 514 520 if ( 'date-time' === $field['format'] ) { … … 636 642 foreach ( $repeater['children'] as $child ) { 637 643 foreach ( $fields_in_repeaters as $id => $fields ) { 644 // phpcs:disable Universal.Operators.StrictComparisons 638 645 if ( $id == $child['id'] ) { 639 646 break; 640 647 } 648 // phpcs:enable 641 649 } 642 650 … … 658 666 } 659 667 668 /** 669 * Formats the field value based on its type and settings. 670 * 671 * @param array $field Submission field. 672 * @param array $field_data Serialized form field data. 673 * 674 * @return mixed 675 */ 660 676 private function format_value( $field, $field_data ) { 661 if ( strstr( $field_data['basetype'], 'payment' ) ) { 662 $field['value'] = html_entity_decode( $field['value'] ); 663 } 664 665 if ( 'hidden' === $field_data['basetype'] ) { 677 if ( $field_data['dynamic'] && isset( $field['value_raw'] ) ) { 678 $ids = array_map( 'intval', explode( ',', $field['value_raw'] ) ); 679 $values = array_map( 'trim', explode( "\n", $field['value'] ) ); 680 $count = count( $values ); 681 682 $field_value = array(); 683 for ( $i = 0; $i < $count; ++$i ) { 684 $field_values[] = array( 685 'id' => $ids[ $i ], 686 'value' => $values[ $i ], 687 ); 688 } 689 690 return $field_data['is_multi'] ? $field_values : $field_values[0]; 691 } elseif ( 'payment-total' === $field_data['basetype'] ) { 692 return (float) $field['amount']; 693 } elseif ( strstr( $field_data['basetype'], 'payment' ) ) { 694 $field_value = html_entity_decode( $field['value'] ); 695 696 if ( 'payment-checkbox' === $field_data['basetype'] ) { 697 return array_map( 'trim', explode( "\n", $field_value ) ); 698 } 699 700 if ( isset( $field['quantity'] ) ) { 701 $field_value .= ' (x' . $field['quantity'] . ')'; 702 } 703 704 return $field_value; 705 } elseif ( 'hidden' === $field_data['basetype'] ) { 666 706 $number_val = (float) $field['value']; 667 707 if ( strval( $number_val ) === $field['value'] ) { 668 708 return $number_val; 669 709 } 670 } 671 672 if (710 711 return $field['value']; 712 } elseif ( 673 713 'number' === $field_data['basetype'] || 674 714 'number-slider' === $field_data['basetype'] 675 715 ) { 676 if ( isset( $field['amount'] ) ) { 677 $value = (float) $field['amount']; 678 if ( isset( $field['currency'] ) ) { 679 $value .= ' ' . $field['currency']; 680 } 681 682 return $value; 683 } else { 684 return (float) preg_replace( '/[^0-9\.,]/', '', $field['value'] ); 685 } 686 } 687 688 if ( 689 'select' === $field_data['basetype'] || 690 'checkbox' === $field_data['basetype'] && 'select' === $field_data['type'] 691 ) { 716 return (float) $field['value']; 717 } elseif ( 'select' === $field_data['type'] ) { 692 718 if ( $field_data['is_multi'] ) { 693 return array_map( 694 function ( $value ) { 695 return trim( $value ); 696 }, 697 explode( "\n", $field['value'] ) 698 ); 699 } 700 } 701 702 if ( 'checkbox' === $field_data['basetype'] && 'checkbox' === $field_data['type'] ) { 719 return array_map( 'trim', explode( "\n", $field['value_raw'] ?? $field['value'] ) ); 720 } 721 722 return $field['value_raw'] ?? $field['value']; 723 } elseif ( 'checkbox' === $field_data['type'] ) { 703 724 return (bool) $field['value']; 704 } 705 706 if ( 'address' === $field_data['basetype'] ) { 707 $post_values = $_POST['wpforms']['fields'][ $field['id'] ] ?? array(); 708 $field_values = array(); 725 } elseif ( 'address' === $field_data['basetype'] ) { 726 $post_values = $_POST['wpforms']['fields'][ $field['id'] ] ?? array(); 727 $field_value = array(); 709 728 foreach ( array_keys( $field_data['schema']['properties'] ) as $prop ) { 710 $field_values[ $prop ] = $post_values[ $prop ] ?? ''; 711 } 712 713 return $field_values; 714 } 715 716 if ( 'date-time' === $field_data['basetype'] ) { 729 $field_value[ $prop ] = $post_values[ $prop ] ?? ''; 730 } 731 732 return $field_value; 733 } elseif ( 'date-time' === $field_data['basetype'] ) { 717 734 if ( 'object' === $field_data['schema']['type'] ) { 718 $post_values = $_POST['wpforms']['fields'][ $field['id'] ] ;735 $post_values = $_POST['wpforms']['fields'][ $field['id'] ] ?? array(); 719 736 return array( 720 'date' => $post_values['date'] ,721 'time' => $post_values['time'] ,737 'date' => $post_values['date'] ?? '', 738 'time' => $post_values['time'] ?? '', 722 739 ); 723 740 } … … 738 755 $form_fields = wpforms_get_form_fields( 739 756 (int) $form_data['id'], 740 array( 741 'file-upload', 742 ) 757 array( 'file-upload' ) 743 758 ); 744 759 … … 750 765 foreach ( $form_fields as $form_field ) { 751 766 foreach ( $submission['fields'] as $submission_field ) { 767 // phpcs:disable Universal.Operators.StrictComparisons 752 768 if ( $submission_field['id'] == $form_field['id'] ) { 753 769 $fields[] = $submission_field; 754 770 } 771 // phpcs:enable 755 772 } 756 773 } -
forms-bridge/trunk/readme.txt
r3463692 r3472269 6 6 License: GPLv2 or later 7 7 License URI: http://www.gnu.org/licenses/gpl-2.0.html 8 Stable Tag: 4.4. 38 Stable Tag: 4.4.4 9 9 Tested up to: 6.9 10 10 … … 163 163 164 164 == Changelog == 165 166 = 4.4.4 = 167 * feat: support for wpforms dynamic choices and raw values 168 * feat: submission loop current request logs 169 * fix: reuse odoo rpc session 170 * fix: submission loop breaks on bridge failures 165 171 166 172 = 4.4.3 =
Note: See TracChangeset
for help on using the changeset viewer.