Widget Class Generator
All four methods, wired to your fields: the output, the admin form, and an update() that sanitises each value by its own type.
The widget
Shown under the name in the widget picker.
What it renders
get_posts() with no_found_rows, driven by your number field, printed as an escaped list.
Settings fields
Titletitle
How many to showcount
Orderorder
Show the dateshow_date
Extras
Shortcode wrapper
Renders the same widget output outside a sidebar, via output buffering.
<?php // Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Plugin Name: Recent Case Studies * Description: Adds the Recent Case Studies widget. * Version: 1.0.0 * Requires PHP: 7.4 * Text Domain: acme */ defined( 'ABSPATH' ) || exit; /** * Recent Case Studies. */ class Acme_Case_Studies_Widget extends WP_Widget { /** * Register the widget with its id base and picker labels. */ public function __construct() { parent::__construct( 'acme_case_studies', __( 'Recent Case Studies', 'acme' ), array( 'description' => __( 'Lists the newest case studies with links.', 'acme' ), 'classname' => 'acme-case-studies', ) ); } /** * Default values for every field. * * @return array */ protected function defaults() { return array( 'title' => 'Recent work', 'count' => 5, 'order' => 'date', 'show_date' => false, ); } /** * Front-end output. * * @param array $args Sidebar arguments. * @param array $instance Saved settings. */ public function widget( $args, $instance ) { $instance = wp_parse_args( (array) $instance, $this->defaults() ); echo $args['before_widget']; if ( ! empty( $instance['title'] ) ) { echo $args['before_title'] . esc_html( apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) ) . $args['after_title']; } $posts = get_posts( array( 'post_type' => 'post', 'posts_per_page' => (int) $instance['count'], 'post_status' => 'publish', 'no_found_rows' => true, ) ); if ( $posts ) { echo '<ul>'; foreach ( $posts as $post ) { printf( '<li><a href="%1$s">%2$s</a></li>', esc_url( get_permalink( $post ) ), esc_html( get_the_title( $post ) ) ); } echo '</ul>'; } echo $args['after_widget']; } /** * The settings form in the admin. * * @param array $instance Saved settings. */ public function form( $instance ) { $instance = wp_parse_args( (array) $instance, $this->defaults() ); printf( '<p><label for="%1$s">%3$s</label><input class="widefat" type="text" id="%1$s" name="%2$s" value="%4$s" /></p>', esc_attr( $this->get_field_id( 'title' ) ), esc_attr( $this->get_field_name( 'title' ) ), esc_html( __( 'Title', 'acme' ) ), esc_attr( $instance['title'] ) ); printf( '<p><label for="%1$s">%3$s</label><input class="widefat" type="number" id="%1$s" name="%2$s" value="%4$s" /></p>', esc_attr( $this->get_field_id( 'count' ) ), esc_attr( $this->get_field_name( 'count' ) ), esc_html( __( 'How many to show', 'acme' ) ), esc_attr( $instance['count'] ) ); printf( '<p><label for="%1$s">%3$s</label>', esc_attr( $this->get_field_id( 'order' ) ), esc_attr( $this->get_field_name( 'order' ) ), esc_html( __( 'Order', 'acme' ) ) ); printf( '<select class="widefat" id="%1$s" name="%2$s">', esc_attr( $this->get_field_id( 'order' ) ), esc_attr( $this->get_field_name( 'order' ) ) ); foreach ( array( 'date' => __( 'Newest first', 'acme' ), 'title' => __( 'A to Z', 'acme' ), ) as $value => $label ) { printf( '<option value="%1$s"%2$s>%3$s</option>', esc_attr( $value ), selected( $instance['order'], $value, false ), esc_html( $label ) ); } echo '</select></p>'; printf( '<p><input class="checkbox" type="checkbox" id="%1$s" name="%2$s" value="1"%3$s /> <label for="%1$s">%4$s</label></p>', esc_attr( $this->get_field_id( 'show_date' ) ), esc_attr( $this->get_field_name( 'show_date' ) ), checked( (bool) $instance['show_date'], true, false ), esc_html( __( 'Show the date', 'acme' ) ) ); } /** * Sanitise settings on save. * * @param array $new_instance Submitted values. * @param array $old_instance Previously saved values. * @return array */ public function update( $new_instance, $old_instance ) { $instance = $old_instance; $instance['title'] = isset( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : 'Recent work'; $instance['count'] = isset( $new_instance['count'] ) ? absint( $new_instance['count'] ) : 5; $instance['order'] = isset( $new_instance['order'] ) && in_array( sanitize_key( $new_instance['order'] ), array( 'date', 'title' ), true ) ? sanitize_key( $new_instance['order'] ) : 'date'; $instance['show_date'] = ! empty( $new_instance['show_date'] ); return $instance; } } /** * Register the widget. */ function acme_case_studies_register() { register_widget( 'Acme_Case_Studies_Widget' ); } add_action( 'widgets_init', 'acme_case_studies_register' );