alleyinteractive / wordpress-fieldmanager

Custom field types for WordPress
Other
535 stars 101 forks source link

Can't delete repeater items #687

Open pressoholics opened 6 years ago

pressoholics commented 6 years ago

We have a repeater field group and when a user tries to delete items in the field group, when they click update the fields return:

https://cl.ly/2e1H3H0n3s34

I have noticed that Fieldmanager_Field::prevsave_all() Compares the saved value with the new value from $_POST. If the new $_POST value is smaller than the old one it adds another item to the values array which results in an empty item being added to the meta data, even if that item has been deleted.

If i comment out this loop it works as you would expect.

The field group is a group within a group, here is an example of how the field is init:

$fm = new Fieldmanager_Group(
            array(
                'name'     => 'secondary-highlight-sections',
                'children' => array(
                    'title' => new Fieldmanager_TextArea(
                        esc_html_x( 'Section Title', 'field manager label', 'fbmpl-plugin-domain' ),
                        array(
                            'attributes' => array(
                                'rows' => 4,
                                'cols' => 180,
                            ),
                        )
                    ),
                    'items' => new Fieldmanager_Group( array(
                        'limit'          => 0,
                        'minimum_count'  => 0,
                        'extra_elements' => 0,
                        'sortable'       => 1,
                        'add_more_label' => esc_html_x( 'Add Content', 'field manager label', 'fbmpl-plugin-domain' ),
                        'sortable'       => true,
                        'label'          => esc_html_x( 'Section', 'field manager label', 'fbmpl-plugin-domain' ),
                        'children'       => array(
                            'media'   => Fbmpl_Field_Manager_Shared::render_media_group( esc_html_x( 'Item Image', 'field manager label', 'fbmpl-plugin-domain' ), 'image' ),
                            'title'   => new Fieldmanager_TextArea(
                                esc_html_x( 'Item Title', 'field manager label', 'fbmpl-plugin-domain' ),
                                array(
                                    'attributes' => array(
                                        'rows' => 4,
                                        'cols' => 180,
                                    ),
                                )
                            ),
                            'content' => new Fieldmanager_TextArea(
                                esc_html_x( 'Item Content', 'field manager label', 'fbmpl-plugin-domain' ),
                                array(
                                    'attributes' => array(
                                        'rows' => 4,
                                        'cols' => 180,
                                    ),
                                )
                            ),
                            'ctas'    => new Fieldmanager_Group( array(
                                'limit'          => 0,
                                'minimum_count'  => 0,
                                'extra_elements' => 0,
                                'sortable'       => 1,
                                'add_more_label' => esc_html_x( 'Add Call to Action', 'field manager label', 'fbmpl-plugin-domain' ),
                                'sortable'       => true,
                                'label'          => esc_html_x( 'Call to Action', 'field manager label', 'fbmpl-plugin-domain' ),
                                'children'       => array(
                                    'cta' => Fbmpl_Field_Manager_Shared::render_call_to_action_group( esc_html_x( 'CTA Item', 'field manager label', 'fbmpl-plugin-domain' ), $cta_search_cpts ),
                                ),
                            ) ),
                        ),
                    ) ),

                ),
            )
        );

        $fm->add_meta_box( $metabox_title, 'page' );
dlh01 commented 6 years ago

Hey @pressoholics — this is a little difficult to investigate without knowing what's happening in Fbmpl_Field_Manager_Shared. When I remove the references to it, I can't replicate the behavior you describe. Can you post the code for Fbmpl_Field_Manager_Shared, or, if that's not feasible, can you describe the fields it's generating?

pressoholics commented 6 years ago

Sure,

render_call_to_action_group():

return new Fieldmanager_Group( array(
            'label'    => esc_html( $group_title ),
            'children' => array(
                'cta-status' => new Fieldmanager_Select(
                    esc_html_x( 'Status', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'default_value' => 'select',
                        'options'       => array(
                            'select'   => 'Select Status',
                            'enabled'  => 'Enabled',
                            'disabled' => 'Disabled',
                        ),
                        'description'   => esc_html_x( 'Enabled or Disabled CTA', 'field manager label', 'fbmpl-plugin-domain' ),
                    )
                ),
                'cta-group'  => new Fieldmanager_Group( array(
                    'label'      => esc_html_x( 'CTA Item', 'field manager label', 'fbmpl-plugin-domain' ),
                    'display_if' => array(
                        'src'   => 'cta-status',
                        'value' => 'enabled',
                    ),
                    'children'   => array(
                        'section-cta-title' => new Fieldmanager_TextField(
                            esc_html_x( 'Call to Action Title', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'attributes'       => array(
                                    'size' => 100,
                                ),
                                'display_if'       => array(
                                    'src'   => 'cta-status',
                                    'value' => 'enabled',
                                ),
                                'validation_rules' => array( 'required' => true ),
                            )
                        ),
                        'cta-link-type'     => new Fieldmanager_Select(
                            esc_html_x( 'Link Content Type', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'default_value' => 'select',
                                'options'       => array(
                                    'select'   => 'Select Type',
                                    'internal' => 'Internal Page',
                                    'external' => 'External',
                                ),
                                'description'   => esc_html_x( 'Is CTA linking to internal or external page', 'field manager label', 'fbmpl-plugin-domain' ),
                            )
                        ),
                        'cta-post'          => new Fieldmanager_Autocomplete( array(
                            'label'            => esc_html_x( 'Select Call to Action Page', 'field manager label', 'fbmpl-plugin-domain' ),
                            'description'      => esc_html_x( 'Start typing the title of the page you wish to select', 'field manager label', 'fbmpl-plugin-domain' ),
                            'display_if'       => array(
                                'src'   => 'cta-link-type',
                                'value' => 'internal',
                            ),
                            'validation_rules' => array( 'required' => true ),
                            'datasource'       => new Fieldmanager_Datasource_Post( array(
                                'query_args' => array(
                                    'post_type' => $apply_to_cpts,
                                ),
                            ) ),
                        ) ),
                        'anchor'            => new Fieldmanager_TextField(
                            esc_html_x( 'Page Anchor (optional)', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'attributes'  => array(
                                    'size' => 100,
                                ),
                                'description' => esc_html_x( 'ID of page section to jump to (DO NOT INCLUDE #)', 'field manager label', 'fbmpl-plugin-domain' ),
                                'display_if'  => array(
                                    'src'   => 'cta-status',
                                    'value' => 'enabled',
                                ),
                            )
                        ),
                        'cta-external-link' => new Fieldmanager_Link(
                            esc_html_x( 'External Link URL', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'attributes'       => array(
                                    'size'        => 100,
                                    'placeholder' => 'http://',
                                ),
                                'description'      => esc_html_x( 'Must be full URL with http://', 'field manager label', 'fbmpl-plugin-domain' ),
                                'display_if'       => array(
                                    'src'   => 'cta-link-type',
                                    'value' => 'external',
                                ),
                                'validation_rules' => array(
                                    'required' => true,
                                    'url'      => true,
                                ),
                            )
                        ),
                    ),
                ) ),
            ),
        ) );

render_media_group()

return new Fieldmanager_Group( array(
            'label'    => esc_html( $group_title ),
            'children' => array(
                'content-type'       => new Fieldmanager_Select(
                    esc_html_x( 'Content Type', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'options'     => $content_type_options,
                        'description' => esc_html_x( 'Select media type.', 'field manager label', 'fbmpl-plugin-domain' ),
                    )
                ),
                'image'              => new Fieldmanager_Media(
                    esc_html_x( 'Image (desktop)', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'button_label'       => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_title'        => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_button_label' => esc_html_x( 'Set Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'preview_size'       => 'thumbnail',
                        'display_if'         => array(
                            'src'   => 'content-type',
                            'value' => 'image',
                        ),
                    )
                ),
                'image-mobile'       => new Fieldmanager_Media(
                    esc_html_x( 'Image Mobile (optional)', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'button_label'       => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_title'        => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_button_label' => esc_html_x( 'Set Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'preview_size'       => 'thumbnail',
                        'display_if'         => array(
                            'src'   => 'content-type',
                            'value' => 'image',
                        ),
                    )
                ),
                'videos'             => new Fieldmanager_Group( array(
                    'label'       => esc_html_x( 'Video Files', 'field manager label', 'fbmpl-plugin-domain' ),
                    'description' => esc_html_x( 'Although not required, for optimal browser support Videos should be provided in all three types.', 'field manager label', 'fbmpl-plugin-domain' ),
                    'display_if'  => array(
                        'src'   => 'content-type',
                        'value' => 'video',
                    ),
                    'children'    => array(
                        'video-mp4'  => new Fieldmanager_Media(
                            esc_html_x( 'Video MP4', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'button_label'       => esc_html_x( 'Select MP4 Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_title'        => esc_html_x( 'Select  MP4 Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_button_label' => esc_html_x( 'Set  MP4 Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'mime_type'          => 'video/mp4',
                            )
                        ),
                        'video-webm' => new Fieldmanager_Media(
                            esc_html_x( 'Video WebM', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'button_label'       => esc_html_x( 'Select WebM Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_title'        => esc_html_x( 'Select  WebM Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_button_label' => esc_html_x( 'Set  WebM Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'mime_type'          => 'video/webm',
                            )
                        ),
                        'video-ogg'  => new Fieldmanager_Media(
                            esc_html_x( 'Video Ogg/Theora', 'field manager label', 'fbmpl-plugin-domain' ),
                            array(
                                'button_label'       => esc_html_x( 'Select Ogg Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_title'        => esc_html_x( 'Select  Ogg Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'modal_button_label' => esc_html_x( 'Set  Ogg Video', 'field manager label', 'fbmpl-plugin-domain' ),
                                'mime_type'          => 'video/ogg',
                            )
                        ),
                    ),
                ) ),
                'poster'             => new Fieldmanager_Media(
                    esc_html_x( 'Video Poster (optional)', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'button_label'       => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_title'        => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_button_label' => esc_html_x( 'Set Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'preview_size'       => 'thumbnail',
                        'display_if'         => array(
                            'src'   => 'content-type',
                            'value' => 'video',
                        ),
                    )
                ),
                'video-mobile-image' => new Fieldmanager_Media(
                    esc_html_x( 'Video Mobile Image (optional)', 'field manager label', 'fbmpl-plugin-domain' ),
                    array(
                        'button_label'       => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_title'        => esc_html_x( 'Select Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'modal_button_label' => esc_html_x( 'Set Image', 'field manager label', 'fbmpl-plugin-domain' ),
                        'preview_size'       => 'thumbnail',
                        'display_if'         => array(
                            'src'   => 'content-type',
                            'value' => 'video',
                        ),
                        'description'        => esc_html_x( 'Replace Video with this image on Mobile.', 'field manager label', 'fbmpl-plugin-domain' ),
                    )
                ),
            ),
        ) );
lchheng commented 6 years ago

If this issue is still be investigated, I just encountered this one myself and it looks like in our case if we set sanitize to intval like so:

$group->add_child( new \Fieldmanager_Select( 'Item', array(
            'name'              => 'post_id',
            'limit'             => 3,
            'add_more_label'    => 'Add Another Item',
            'minimum_count'     => 0,
            'extra_elements'    => 0,
            'type_ahead'        => true,
            'sortable'          => true,
            'sanitize'          => 'intval',
            ) ) );

Fieldmanager_Field::presave() will receive null for $value and will return 0 as intval(null) returns 0. This 0 value will return 1 when passed to return strlen( $value ) in array_filter():

https://github.com/alleyinteractive/wordpress-fieldmanager/blob/d401659612fdff785088e731e69538c085dac443/php/class-fieldmanager-field.php#L930-L941

...which leads to the deleted item remaining.

NicktheGeek commented 5 years ago

I'm running into this with nested children. It's creating new, empty child elements on each save and it is impossible to delete the items once they exist. I've had to add limits where I didn't want them to prevent the pages from being impossible to work on, but even in cases where the pages has a few sections with 1-3 columns each the end result of a few rounds of revisions is 50 sections with 5 columns each, maxing my limits.

Here is the code I've got, which is really pretty simple and fully contained so it should be repeatable.

$fm = new \Fieldmanager_Group(
            [
                'name'     => 'sections',
                'children' => [
                    'section'    => new \Fieldmanager_Group(
                        [
                            'label'       => __( 'Section', 'scheiner-theme' ),
                            'tabbed'      => 'horizontal',
                            'limit'       => 50,
                            'sortable'    => true,
                            'collapsible' => true,
                            'children'    => [
                                'columns' => new \Fieldmanager_Group(
                                    [
                                        'label'    => esc_html__( 'Column', 'scheiner-theme' ),
                                        'limit'    => 5,
                                        'children' => [
                                            'content' => new \Fieldmanager_RichTextArea( esc_html__( 'Content', 'scheiner-theme' ) ),
                                            'size'    => new \Fieldmanager_Select(
                                                [
                                                    'label' => esc_html__( 'Size', 'scheiner-theme' ),
                                                    'options' => [
                                                        ''             => esc_html__( 'Full Width', 'scheiner-theme' ),
                                                        'one-half'     => esc_html__( 'One Half', 'scheiner-theme' ),
                                                        'one-third'    => esc_html__( 'One Third', 'scheiner-theme' ),
                                                        'one-fourth'   => esc_html__( 'One Fourth', 'scheiner-theme' ),
                                                        'one-sixth'    => esc_html__( 'One Sixth', 'scheiner-theme' ),
                                                        'two-thirds'   => esc_html__( 'Two Thirds', 'scheiner-theme' ),
                                                        'five-sixths'  => esc_html__( 'Five Sixths', 'scheiner-theme' ),
                                                    ]
                                                ]
                                            ),
                                            'first'  => new \Fieldmanager_Checkbox( esc_html__( 'First', 'scheiner-theme' ) ),
                                            'last'   => new \Fieldmanager_Checkbox( esc_html__( 'Last', 'scheiner-theme' ) ),
                                            'mobile' => new \Fieldmanager_Group(
                                                [
                                                    'label'    => __( 'Mobile Layout', 'scheiner-theme' ),
                                                    'children' => [
                                                        'margin-top'    => new \Fieldmanager_TextField(
                                                            [
                                                                'label'      => esc_html__( 'Margin Top', 'scheiner-theme' ),
                                                                'input_type' => 'number',
                                                            ]
                                                        ),
                                                        'margin-bottom' => new \Fieldmanager_TextField(
                                                            [
                                                                'label'      => esc_html__( 'Margin Bottom', 'scheiner-theme' ),
                                                                'input_type' => 'number',
                                                            ]
                                                        ),
                                                        'margin-left'   => new \Fieldmanager_TextField(
                                                            [
                                                                'label'      => esc_html__( 'Margin Left', 'scheiner-theme' ),
                                                                'input_type' => 'number',
                                                            ]
                                                        ),
                                                        'margin-right'  => new \Fieldmanager_TextField(
                                                            [
                                                                'label'      => esc_html__( 'Margin Right', 'scheiner-theme' ),
                                                                'input_type' => 'number',
                                                            ]
                                                        ),
                                                    ],
                                                ]
                                            )
                                        ]
                                    ]
                                ),
                                'design'  => new \Fieldmanager_Group(
                                    [
                                        'label'       => esc_attr__( 'Design', 'scheiner-theme' ),
                                        'children' => [
                                            'background'  => new \Fieldmanager_Colorpicker( esc_html__( 'Background Color', 'scheiner-theme' ) ),
                                            'color'       => new \Fieldmanager_Colorpicker( esc_html__( 'Text Color', 'scheiner-theme' ) ),
                                            'class'       => new \Fieldmanager_Select(
                                                [
                                                    'label'   => esc_html__( 'Class', 'scheiner-theme' ),
                                                    'options' => [
                                                        'top-blue'          => 'top-blue',
                                                        'wrap-white'        => 'wrap-white',
                                                        'blue-circles'      => 'blue-circles',
                                                        'position-relative' => 'position-relative',
                                                    ],
                                                ]
                                            ),
                                            'wrap'        => new \Fieldmanager_Checkbox( esc_html__( 'Include Wrap', 'scheiner-theme' ) ),
                                            'padding_top' => new \Fieldmanager_TextField(
                                                [
                                                    'label'      => esc_html__( 'Padding Top', 'scheiner-theme' ),
                                                    'input_type' => 'number',
                                                ]
                                            ),
                                            'padding_bottom' => new \Fieldmanager_TextField(
                                                [
                                                    'label'      => esc_html__( 'Padding Bottom', 'scheiner-theme' ),
                                                    'input_type' => 'number',
                                                ]
                                            ),
                                            'margin_top' => new \Fieldmanager_TextField(
                                                [
                                                    'label'      => esc_html__( 'Margin Top', 'scheiner-theme' ),
                                                    'input_type' => 'number',
                                                ]
                                            ),
                                            'margin_bottom' => new \Fieldmanager_TextField(
                                                [
                                                    'label'      => esc_html__( 'Margin Bottom', 'scheiner-theme' ),
                                                    'input_type' => 'number',
                                                ]
                                            ),
                                        ]
                                    ]
                                ),
                            ],
                        ]
                    ),
                ],
            ]
        );
        $fm->add_meta_box( __( 'Landing Page Sections', 'scheiner-theme' ), [ 'page' ], 'normal', 'high' );