GeneratorsDesignWidget Class

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.

class-acme-case-studies-widget.php
Saved just now
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' );