Faulty 'text_list' update

Support MB Custom Table Faulty 'text_list' updateResolved

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #23063

    Hello!

    I created a table like this (relevant columns shown only):

    
    MB_Custom_Table_API::create( "{$wpdb->prefix}_characters", array(
            'height_known'          => 'BOOLEAN',
            'height_imperial'       => 'TEXT',
            'height_metric'         => 'DECIMAL(5, 2) UNSIGNED NOT NULL',
        ), array() );
    

    And then I created a metabox like this (relevant custom fields only):

    
    $meta_boxes[] = array(
            'title'         => esc_html__( 'Characters Extra Info', 'my_text_domain' ),
            'id'            => 'characters-extra-info',
            'post_types'    => array( CHARACTER_CPT_SLUG ),
            'context'       => 'normal',
            'priority'      => 'high',
            'autosave'      => true,
            'storage_type'  => 'custom_table',
            'table'         => "{$wpdb->prefix}_characters",
            'fields'        => [
                [
                    'id'        => 'height_known',
                    'type'      => 'switch',
                    'name'      => esc_html__( 'Height known?', 'my_text_domain' ),
                    'std'       => 0,
                    'style'     => 'square',
                    'on_label'  => 'Yes',
                    'off_label' => 'No',
                    'columns'   => 4,
                    'tab'       => 'biological-tab',
                ],
                [
                    'id'      => 'height_imperial',
                    'type'    => 'text_list',
                    'name'    => esc_html__( 'Imperial height', 'my_text_domain' ),
                    'options' => [
                        'ft' => '',
                        'in' => '',
                    ],
                    'columns' => 4,
                    'tab'     => 'biological-tab',
                    'visible' => [
                        'when'     => [['height_known', '=', 1]],
                        'relation' => 'and',
                    ],
                ],
                [
                    'id'          => 'height_metric',
                    'type'        => 'text',
                    'name'        => esc_html__( 'Metric height', 'my_text_domain' ),
                    'placeholder' => esc_html__( 'cm', 'my_text_domain' ),
                    'columns'     => 4,
                    'readonly'    => 1,
                    'tab'         => 'biological-tab',
                    'visible'     => [
                        'when'     => [['height_known', '=', 1]],
                        'relation' => 'and',
                    ],
                ],
            ],
            'tab_style'     => 'default',
            'tab_wrapper'   => true,
            'tabs'          => array(
                'biological-tab'  => [
                    'label' => 'Biological',
                    'icon'  => 'dashicons-admin-users',
                ],
            ),
    

    Here's the problem: the first time I set the 'height_imperial' field, everything is fine. The database column is NULL and it all works out nicely. For values "5 feet 7 inches", the database column will be:

    a:2:{i:0;s:1:"5";i:1;s:1:"7";}

    The next time I update the post, regardless of whether I change the values or not, the database changes to:

    a:3:{i:0;s:0:"";i:1;s:1:"5";i:2;s:1:"7";}

    That extra "0" at the beginning of the array causes the values to shift and the field is not displayed properly anymore, and it's saved wrongly from now on.

    I was able to confirm with the filter 'rmwb_height_imperial_value' that the values passed on is correct, namely array(5,7) AND that it all works out perfectly if I disable the custom table storage.

    #23116

    I found the problem!

    Since the 'text_list' field has the parameter 'multiple' set to true automatically by MetaBox, in the file /meta-box/inc/field.php, in the function 'save', the "Save cloned fields as multiple values instead serialized array" block is being called (lines 314-321).

    Inside that function, there is a call to $storage->delete( $post_id, $name ).

    Now, moving back to the MetaBox Custom Table plugin, in the function /inc/class-rwmb-table-storage.php there is the function "delete" around line 100. Inside, there is an "if" check for "$delete_all || ! $meta_value || $row[ $meta_key ] === $meta_value" and in there there is an assignment: $row[ $meta_key ] = "";

    Because of that assignment to "", the function "add" a few lines above fails. Namely, when it calls $this->get( $object_id, $meta_key ) because there is an array conversion happening. The exact line is (array) $this->get( $object_id, $meta_key );

    In this case, the "" value gets converted to [""] which is NOT an empty array. All the other values from the text_list get appended and thus the first value is always wrong.

    The solution is one of two:

    a) in the "delete" function, instead of assigning "", assign an empty array [] if the field accepts multiple entries

    b) in the "add" function, rewrite the line $values = (array) $this->get( $object_id, $meta_key ) to:

    
    $values = $this->get( $object_id, $meta_key );
    if ( $values === '' ) {
        $values = array();
    } else {
        $values = (array) $values;
    }
    
    #23118
    Long NguyenLong Nguyen
    Moderator

    Hi,

    Thank you for your effort. I will send all information to the developer team to cover this case.

    #23389
    Long NguyenLong Nguyen
    Moderator
Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.