0

The code works as expected.

The issue happens if I set 'show_post_count' => 1 by default. In this case checkbox will be enabled always.

How should I update the code to work as expected even if checkbox value set to 1 by default.

<?php

class Custom_Archives_Widget extends WP_Widget {

    /**
     * Register widget with WordPress.
     */
    function __construct() {
        parent::__construct(
            'custom_archives_widget', // Base ID
            __( 'Custom Archives', 'custom' ), // Name
            array( 'description' => __( 'Custom Archives Widget', 'custom' ) ) // Args
        );
    }


    /**
     * Front-end display of widget.
     *
     * @see WP_Widget::widget()
     *
     * @param array $args     Widget arguments.
     * @param array $instance Saved values from database.
     */
    public function widget( $args, $instance ) {
        //extract( $args );
        $instance = wp_parse_args( (array) $instance, self::get_defaults() );

        echo $args['before_widget'];

        if ( ! empty( $instance['title'] ) ) {
            echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ). $args['after_title'];
        }

        $instance['echo'] = false;
        $archives = wp_get_archives( $instance );

        if ( $instance['format'] == 'option' ) { // Archives as a dropdown

            echo '<p class="custom-archives"><select name="archive-dropdown" onchange=\'document.location.href=this.options[this.selectedIndex].value;\'>';
                echo '<option value=""></option>';
                echo $archives;
            echo '</select></p><!-- .custom-archives -->';

        } elseif ( $instance['format'] == 'html' ) { // Archives as an unordered list

            echo '<ul class="custom-archives">' . $archives . '</ul><!-- .custom-archives -->';

        } else { // Other formats

            echo $archives;

        }
        echo $args['after_widget'];
    }


    /**
     * Back-end widget form.
     *
     * @see WP_Widget::form()
     *
     * @param array $instance Previously saved values from database.
     */
    public function form( $instance ) {
        $instance = wp_parse_args( (array) $instance, self::get_defaults() );

        $type_list = array( 
            'yearly' => __( 'Yearly', 'custom' ),
            'monthly' => __( 'Monthly', 'custom' ),
            'daily' => __( 'Daily', 'custom' ),
            'weekly' => __( 'Weekly', 'custom' ),
            'postbypost' => __( 'Post By Post', 'custom' ),
            'alpha' => __( 'Alphabetical', 'custom' )
        );

        $format_list = array(
            'html' => __( 'HTML', 'custom' ),
            'option' => __( 'Dropdown', 'custom' ),
            'custom' => __( 'Custom', 'custom' )
        );

        $order_list = array(
            'ASC'  => __( 'Ascending (A-Z)', 'custom' ),
            'DESC' => __( 'Descending (Z-A)', 'custom' )
        );

        ?>
<p>
    <label><?php _e( 'Title:', 'custom' ); ?><br>
        <input type="text" class="widefat" name="<?php echo $this->get_field_name( 'title' ); ?>" 
            value="<?php echo esc_attr( $instance['title'] ); ?>">
    </label>
</p>

<p>
    <label><?php _e( 'Type:', 'custom' ); ?><br>
        <select class="widefat" name="<?php echo $this->get_field_name( 'type' ); ?>">
            <?php foreach ( $type_list as $option_value => $option_label ) { ?>
                <option value="<?php echo esc_attr( $option_value ); ?>" <?php selected( $instance['type'], $option_value ); ?>><?php echo esc_html( $option_label ); ?></option>
            <?php } ?>
        </select>
    </label>
</p>

<p>
    <label><?php _e( 'Limit:', 'custom' ); ?><br>
        <input type="number" class="widefat" min="0" name="<?php echo $this->get_field_name( 'limit' ); ?>" 
            value="<?php echo esc_attr( $instance['limit'] ); ?>" />
    </label>
</p>

<p>
    <label><?php _e( 'Format:', 'custom' ); ?><br>
        <select class="widefat" name="<?php echo $this->get_field_name( 'format' ); ?>">
            <?php foreach ( $format_list as $option_value => $option_label ) { ?>
                <option value="<?php echo esc_attr( $option_value ); ?>" <?php selected( $instance['format'], $option_value ); ?>><?php echo esc_html( $option_label ); ?></option>
            <?php } ?>
        </select>
    </label>
</p>

<p>
    <label>
        <input class="checkbox" type="checkbox" <?php checked( $instance['show_post_count'] ); ?> 
            name="<?php echo $this->get_field_name( 'show_post_count' ); ?>" />
        <?php _e( 'Show post count', 'custom' ); ?>
    </label>
</p>

<p>
    <label><?php _e( 'Order:', 'custom' ); ?><br>
        <select class="widefat" name="<?php echo $this->get_field_name( 'order' ); ?>">
            <?php foreach ( $order_list as $option_value => $option_label ) { ?>
                <option value="<?php echo esc_attr( $option_value ); ?>" <?php selected( $instance['order'], $option_value ); ?>><?php echo esc_html( $option_label ); ?></option>
            <?php } ?>
        </select>
    </label>
</p>
        <?php 
    }


    /**
     * Sanitize widget form values as they are saved.
     *
     * @see WP_Widget::update()
     *
     * @param array $new_instance Values just sent to be saved.
     * @param array $old_instance Previously saved values from database.
     *
     * @return array Updated safe values to be saved.
     */
    public function update( $new_instance, $old_instance ) {
        $instance = $old_instance;
        $new_instance = wp_parse_args( (array) $new_instance, self::get_defaults() );
        $instance['title'] = trim(strip_tags($new_instance['title']));
        $instance['type'] = $new_instance['type'];
        $instance['limit'] = intval( $new_instance['limit'] );
        $instance['limit'] = $instance['limit'] === 0 ? '' : $instance['limit'];
        $instance['format'] = $new_instance['format'];

        $instance['show_post_count'] = $new_instance['show_post_count'] ? 1 : 0;

        /*$instance['show_post_count'] = 1;
        if( !isset( $new_instance['show_post_count'] ) || empty( $new_instance['show_post_count'] ) ) {
            $instance['show_post_count'] = 0;
        }*/

        $instance['order'] = $new_instance['order'];
        return $instance;
    }


    /**
     * Render an array of default values.
     *
     * @return array default values
     */
    private static function get_defaults() {
        $defaults = array(
            'title' => __( 'Archives', 'custom' ),
            'description' => '',
            'type' => 'monthly',
            'limit' => 10,
            'format' => 'html',
            'show_post_count' => 0,
            'order' => 'DESC'
        );
        return $defaults;
    }

}


function custom_archives_register_widget() {
    register_widget( 'Custom_Archives_Widget' );
}
add_action( 'widgets_init', 'custom_archives_register_widget' );
1

Please note when checkbox is not checked then key is not set in posted form data. So when you uncheck show_post_count, posted array does not has this key and in update() function you are parsing it with default value.

$new_instance = wp_parse_args( (array) $new_instance, self::get_defaults() );

Thus $instance['show_post_count'] will have 1 always even when you uncheck it.

Solution:

Please give the priority to user input and if something is missing then fill it with default arguments. The updated function will look like!

public function update( $new_instance, $instance ) {
    $instance['title'] = trim(strip_tags($new_instance['title']));
    $instance['type'] = $new_instance['type'];
    $instance['limit'] = intval( $new_instance['limit'] );
    $instance['limit'] = $instance['limit'] === 0 ? '' : $instance['limit'];
    $instance['format'] = $new_instance['format'];
    //Add isset to check if key is set!
    $instance['show_post_count'] = isset($new_instance['show_post_count']) ? 1 : 0;
    $instance['order'] = $new_instance['order'];

    //Fill with default value if any key is missing!
    $updated_instance = wp_parse_args( (array) $instance, self::get_defaults() );

    return $updated_instance;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.