Plugin Directory

Changeset 3472269


Ignore:
Timestamp:
03/01/2026 10:12:26 PM (9 days ago)
Author:
codeccoop
Message:

feat: wpforms dynamic choices and fix odoo session handling

Location:
forms-bridge/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • forms-bridge/trunk/addons/odoo/class-odoo-form-bridge.php

    r3456613 r3472269  
    143143     */
    144144    private static function rpc_login( $login, $backend ) {
     145        if ( self::$session ) {
     146            return self::$session;
     147        }
     148
    145149        $session_id = 'forms-bridge-' . time();
    146150
     
    195199            return new WP_Error(
    196200                'invalid_credential',
    197                 'The bridge does not have a valid credential'
     201                'The bridge does not have a valid credential',
     202                $backend->data(),
    198203            );
    199204        }
  • forms-bridge/trunk/deps/http/includes/class-backend.php

    r3455079 r3472269  
    296296            'opaque' => null,
    297297        );
     298
    298299        foreach ( array_keys( $fields ) as $field ) {
    299             if (
    300                 ! preg_match( "/{$field}=\"([^\"]+)\"/", $digest_header, $matches )
    301             ) {
     300            if ( ! preg_match( "/{$field}=\"([^\"]+)\"/", $digest_header, $matches ) ) {
    302301                return $error;
    303302            }
     
    314313        $uri        = $parsed_url['path'] ?? '';
    315314
    316         $a1       = md5(
    317             "{$credential->client_id}:{$credential->realm}:{$credential->client_secret}"
    318         );
     315        $a1       = md5( "{$credential->client_id}:{$credential->realm}:{$credential->client_secret}" );
    319316        $a2       = md5( "{$this->method}:{$this->endpoint}" );
    320317        $response = md5( "{$a1}:{$fields['nonce']}:{$a2}" );
     
    332329     * @param array  $params URL query params.
    333330     * @param array  $headers Additional HTTP headers.
     331     * @param array  $args Additional request args.
    334332     *
    335333     * @return array|WP_Error Request response.
    336334     */
    337     public function head( $endpoint, $params = array(), $headers = array() ) {
     335    public function head( $endpoint, $params = array(), $headers = array(), $args = array() ) {
    338336        if ( ! $this->is_valid ) {
    339337            return new WP_Error( 'invalid_backend' );
     
    342340        $url      = $this->url( $endpoint );
    343341        $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
    345344        return $this->handle_response( $response );
    346345    }
     
    390389        }
    391390
    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 );
    395396    }
    396397
     
    417418        }
    418419
    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 );
    422425    }
    423426
     
    444447        }
    445448
    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 );
    449454    }
    450455
     
    464469        }
    465470
    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 );
    469476    }
    470477
  • forms-bridge/trunk/forms-bridge.php

    r3463692 r3472269  
    1010 * Text Domain:         forms-bridge
    1111 * Domain Path:         /languages
    12  * Version:             4.4.3
     12 * Version:             4.4.4
    1313 * Requires PHP:        8.0
    1414 * Requires at least:   6.7
  • forms-bridge/trunk/includes/class-forms-bridge.php

    r3451059 r3472269  
    5050     */
    5151    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;
    5259
    5360    /**
     
    302309
    303310            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}'" );
    307312                continue;
    308313            }
    309314
    310315            self::$current_bridge = $bridge;
     316
     317            Logger::log( "Start submission for bridge '{$bridge->name}'" );
    311318
    312319            try {
     
    408415                );
    409416
     417                add_action( 'forms_bridge_http_before_request', array( self::class, 'http_request_interceptor' ), 99, 1 );
     418
    410419                $response = $bridge->submit( $payload, $attachments );
    411420
     
    419428                        $attachments
    420429                    );
     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                    }
    421439                } else {
     440                    if ( self::$current_request ) {
     441                        Logger::log( 'Submission request' );
     442                        Logger::log( self::$current_request );
     443                    }
     444
    422445                    Logger::log( 'Submission response' );
    423446                    Logger::log( $response );
     
    463486                }
    464487            } 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;
    468520    }
    469521
  • forms-bridge/trunk/integrations/wpforms/class-wpforms-integration.php

    r3442111 r3472269  
    415415                'schema'      => $this->field_value_schema( $field, $type, $children ),
    416416                'basetype'    => $field['type'],
     417                'dynamic'     => ! empty( $field['dynamic_choices'] ),
    417418            ),
    418419            $field,
     
    430431     */
    431432    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 ) {
    433434            return true;
    434435        }
     
    467468            case 'text':
    468469            case 'textarea':
    469             case 'payment-total':
    470470            case 'payment-single':
    471             case 'radio':
    472471            case 'password':
    473472            case 'url':
    474473                return array( 'type' => 'string' );
     474            case 'payment-total':
    475475            case 'number-slider':
    476476            case 'number':
     
    480480            case 'payment-checkbox':
    481481            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' );
    497482            case 'checkbox':
     483            case 'radio':
    498484                if ( 'checkbox' === $norm_type ) {
    499485                    return array( 'type' => 'boolean' );
    500486                }
    501487
    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' );
    513519            case 'date-time':
    514520                if ( 'date-time' === $field['format'] ) {
     
    636642            foreach ( $repeater['children'] as $child ) {
    637643                foreach ( $fields_in_repeaters as $id => $fields ) {
     644                    // phpcs:disable Universal.Operators.StrictComparisons
    638645                    if ( $id == $child['id'] ) {
    639646                        break;
    640647                    }
     648                    // phpcs:enable
    641649                }
    642650
     
    658666    }
    659667
     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     */
    660676    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'] ) {
    666706            $number_val = (float) $field['value'];
    667707            if ( strval( $number_val ) === $field['value'] ) {
    668708                return $number_val;
    669709            }
    670         }
    671 
    672         if (
     710
     711            return $field['value'];
     712        } elseif (
    673713            'number' === $field_data['basetype'] ||
    674714            'number-slider' === $field_data['basetype']
    675715        ) {
    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'] ) {
    692718            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'] ) {
    703724            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();
    709728            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'] ) {
    717734            if ( 'object' === $field_data['schema']['type'] ) {
    718                 $post_values = $_POST['wpforms']['fields'][ $field['id'] ];
     735                $post_values = $_POST['wpforms']['fields'][ $field['id'] ] ?? array();
    719736                return array(
    720                     'date' => $post_values['date'],
    721                     'time' => $post_values['time'],
     737                    'date' => $post_values['date'] ?? '',
     738                    'time' => $post_values['time'] ?? '',
    722739                );
    723740            }
     
    738755        $form_fields = wpforms_get_form_fields(
    739756            (int) $form_data['id'],
    740             array(
    741                 'file-upload',
    742             )
     757            array( 'file-upload' )
    743758        );
    744759
     
    750765        foreach ( $form_fields as $form_field ) {
    751766            foreach ( $submission['fields'] as $submission_field ) {
     767                // phpcs:disable Universal.Operators.StrictComparisons
    752768                if ( $submission_field['id'] == $form_field['id'] ) {
    753769                    $fields[] = $submission_field;
    754770                }
     771                // phpcs:enable
    755772            }
    756773        }
  • forms-bridge/trunk/readme.txt

    r3463692 r3472269  
    66License: GPLv2 or later
    77License URI: http://www.gnu.org/licenses/gpl-2.0.html
    8 Stable Tag: 4.4.3
     8Stable Tag: 4.4.4
    99Tested up to: 6.9
    1010
     
    163163
    164164== 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
    165171
    166172= 4.4.3 =
Note: See TracChangeset for help on using the changeset viewer.