UNIVERSITY OF ENGINEERING AND TECHNOLOGY, TAXILA
SOFTWARE ENGINEERING DEPARTMENT
LECTURE 11
Mini Project
Entrepreneurship and Leadership
SUBMITTED TO:
Sir Rizwan
SUBMITTED BY:
Faryal Nimra (21-SE-66)
Assignment: Practical Widget Development – WordPress Widgets
Date: May 31, 2025
Objective:
To gain hands-on experience with WordPress widget development by building custom widgets,
implementing visibility, adding accessibility features, styling widgets using CSS, and integrating
them into block-based themes.
Task 1: Build a Recent Posts Widget with Thumbnails
Objective:
Create a widget that shows recent posts along with featured images. The number of posts and
thumbnail visibility should be configurable via widget settings.
Code:
class Recent_Posts_Thumbnails_Widget extends WP_Widget {
function __construct() {
parent::__construct(
'recent_posts_thumbnails_widget',
__('Recent Posts with Thumbnails', 'text_domain'),
['description' => __('Displays recent posts with optional
thumbnails.')]
);
}
public function widget($args, $instance) {
$title = apply_filters('widget_title', $instance['title'] ?? 'Recent
Posts');
$num_posts = $instance['num_posts'] ?? 5;
$show_thumbnails = !empty($instance['show_thumbnails']);
echo $args['before_widget'];
echo $args['before_title'] . esc_html($title) . $args['after_title'];
$query = new WP_Query(['posts_per_page' => $num_posts]);
if ($query->have_posts()) {
echo '<ul>';
while ($query->have_posts()) {
$query->the_post();
echo '<li>';
if ($show_thumbnails && has_post_thumbnail()) {
echo get_the_post_thumbnail(get_the_ID(), 'thumbnail');
}
echo '<a href="' . esc_url(get_permalink()) . '">' .
esc_html(get_the_title()) . '</a>';
echo '</li>';
}
echo '</ul>';
wp_reset_postdata();
}
echo $args['after_widget'];
}
public function form($instance) {
$title = esc_attr($instance['title'] ?? '');
$num_posts = esc_attr($instance['num_posts'] ?? 5);
$show_thumbnails = !empty($instance['show_thumbnails']);
?>
<p><label>Title: <input class="widefat" name="<?php echo $this-
>get_field_name('title'); ?>"
value="<?php echo $title; ?>"></label></p>
<p><label>Number of Posts: <input class="widefat" type="number"
name="<?php echo $this->get_field_name('num_posts'); ?>" value="<?php
echo $num_posts; ?>"></label></p>
<p><input type="checkbox" name="<?php echo $this-
>get_field_name('show_thumbnails'); ?>" <?php checked($show_thumbnails); ?>>
Show Thumbnails</p>
<?php
}
public function update($new_instance, $old_instance) {
return [
'title' => sanitize_text_field($new_instance['title']),
'num_posts' => intval($new_instance['num_posts']),
'show_thumbnails' => !empty($new_instance['show_thumbnails']),
];
}
}
function register_recent_posts_thumbnails_widget() {
register_widget('Recent_Posts_Thumbnails_Widget');
}
add_action('widgets_init', 'register_recent_posts_thumbnails_widget');
Custom widget with recent posts and thumbnails.
Settings: Title, number of posts, thumbnail toggle.
Output structured using <ul><li> format.
Task 2: Build a Contact Info Widget
Objective:
Display customizable contact information (address, phone, email, social links) in a widget.
Code:
class Contact_Info_Widget extends WP_Widget {
function __construct() {
parent::__construct('contact_info_widget', __('Contact Info',
'text_domain'));
}
public function widget($args, $instance) {
echo $args['before_widget'];
echo $args['before_title'] . esc_html($instance['title']) .
$args['after_title'];
?>
<ul>
<li><strong>Address:</strong> <?php echo
esc_html($instance['address']); ?></li>
<li><strong>Phone:</strong> <?php echo
esc_html($instance['phone']); ?></li>
<li><strong>Email:</strong> <?php echo
sanitize_email($instance['email']); ?></li>
</ul>
<div><?php echo esc_textarea($instance['social_links']); ?></div>
<?php
echo $args['after_widget'];
}
public function form($instance) {
$title = esc_attr($instance['title'] ?? '');
$address = esc_attr($instance['address'] ?? '');
$phone = esc_attr($instance['phone'] ?? '');
$email = esc_attr($instance['email'] ?? '');
$social_links = esc_textarea($instance['social_links'] ?? '');
?>
<p><label>Title: <input class="widefat" name="<?php echo $this-
>get_field_name('title'); ?>" value="<?php echo $title; ?>"></label></p>
<p><label>Address: <input class="widefat" name="<?php echo $this-
>get_field_name('address'); ?>" value="<?php echo $address; ?>"></label></p>
<p><label>Phone: <input class="widefat" type="tel" pattern="[0-9]+"
name="<?php echo $this->get_field_name('phone'); ?>" value="<?php echo $phone;
?>"></label></p>
<p><label>Email: <input class="widefat" type="email" name="<?php echo
$this->get_field_name('email'); ?>" value="<?php echo $email; ?>"></label></p>
<p><label>Social Links (HTML allowed): <textarea class="widefat"
name="<?php echo $this->get_field_name('social_links'); ?>"><?php echo
$social_links; ?></textarea></label></p>
<?php
}
public function update($new_instance, $old_instance) {
return [
'title' => sanitize_text_field($new_instance['title']),
'address' => sanitize_text_field($new_instance['address']),
'phone' => sanitize_text_field($new_instance['phone']),
'email' => sanitize_email($new_instance['email']),
'social_links' => wp_kses_post($new_instance['social_links']),
];
}
}
function register_contact_info_widget() {
register_widget('Contact_Info_Widget');
}
add_action('widgets_init', 'register_contact_info_widget');
Task 3: Widget Visibility with Conditional Logic
Objective:
Show a welcome message widget only on the homepage.
Code (plus visibility check):
class Homepage_Welcome_Widget extends WP_Widget {
function __construct() {
parent::__construct('homepage_welcome_widget', __('Homepage Welcome
Message'));
}
public function widget($args, $instance) {
if (!is_front_page()) return;
echo $args['before_widget'];
echo $args['before_title'] . esc_html($instance['title']) .
$args['after_title'];
echo '<p>' . esc_html($instance['message']) . '</p>';
echo $args['after_widget'];
}
public function form($instance) {
$title = esc_attr($instance['title'] ?? '');
$message = esc_attr($instance['message'] ?? '');
?>
<p><label>Title: <input class="widefat" name="<?php echo $this-
>get_field_name('title'); ?>" value="<?php echo $title; ?>"></label></p>
<p><label>Message: <input class="widefat" name="<?php echo $this-
>get_field_name('message'); ?>" value="<?php echo $message; ?>"></label></p>
<?php
}
public function update($new, $old) {
return [
'title' => sanitize_text_field($new['title']),
'message' => sanitize_text_field($new['message']),
];
}
}
add_action('widgets_init', function() {
register_widget('Homepage_Welcome_Widget');
});
Task 4: Accessibility Enhancements
Implementation Notes:
Use ARIA attributes like aria-label.
Ensure all links/buttons are tabbable.
Use semantic HTML: <ul>, <p>, <label>.
Add alt to all images (e.g., in Recent Posts widget thumbnails):
echo get_the_post_thumbnail(get_the_ID(), 'thumbnail', ['alt' =>
get_the_title()]);
Task 5: Styling Widgets with CSS
Custom CSS:
.widget-custom {
background-color: #f9f9f9;
border: 1px solid #ddd;
padding: 15px;
border-radius: 5px;
}
.widget-custom h2 {
color: #2a2a2a;
font-size: 20px;
}
.widget-custom ul {
list-style: none;
padding: 0;
}
.widget-custom li {
margin-bottom: 10px;
}
@media (max-width: 600px) {
.widget-custom {
font-size: 14px;
}
}
Task 6: Widgets in Block-Based Themes
Steps:
1. Activate a block-based theme like Twenty Twenty-Three.
2. Go to Appearance > Widgets or Site Editor > Template Parts > Sidebar/Footer.
3. Add widget using “Legacy Widget” block.
4. Search and place your custom widget (e.g., “Recent Posts with Thumbnails”).
OUTPUT: