Episode 5 – WordPress Plugin Development with WooCommerce
The badge
Now we leave the admin. We print a badge on products that are on sale.
Step 1. Make the file
cd "/Users/sejim/Local Sites/simple-boards/app/public/wp-content/plugins/order-boost"
touch includes/class-orb-badge.php
Step 2. Type the class
Open includes/class-orb-badge.php and type this:
<?php
/**
* The sale badge.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ORB_Badge {
public function __construct() {
add_action( 'woocommerce_before_shop_loop_item_title', array( $this, 'render_badge' ) );
add_action( 'woocommerce_single_product_summary', array( $this, 'render_badge' ), 6 );
}
}
Two bells this time, because there are two places to show a badge.
woocommerce_before_shop_loop_item_titlerings once per product on the shop page, just above the title.woocommerce_single_product_summaryrings on one product page, in the block beside the photo.
These bells belong to WooCommerce, not WordPress. Every big plugin adds its own bells so other plugins can join in.
The number 6
Look at the second line. It ends with , 6 ).
That is the priority. It is a queue number. Everything booked on that bell runs in number order. Low runs first. The default is 10.
WooCommerce prints the title at 5, and the price at 10. We chose 6. So our badge lands between them.
Change it to 60 later and the badge drops to the bottom. Nothing errors. It only moves.
Step 3. Type the method
Add this inside the class, under the constructor:
public function render_badge() {
global $product;
if ( 'yes' !== get_option( 'orb_badge_enabled', 'yes' ) ) {
return;
}
if ( ! $product instanceof WC_Product || ! $product->is_on_sale() ) {
return;
}
$text = get_option( 'orb_badge_text', 'Hot Deal' );
echo '<span class="orb-badge">' . esc_html( $text ) . '</span>';
}
global $product
WooCommerce puts the current product in a global variable while it draws each item. Our function is not given the product, so we reach out and take it.
Think of a whiteboard in a kitchen. The chef writes the current order on it. Anybody in the room can read it.
The instanceof check
global $product can hold nothing. It happens on a page that is not a shop page, or when another plugin clears it. Then $product->is_on_sale() kills the page with a fatal error.
instanceof WC_Product asks “is this really a product object?”. If not, we leave quietly.
This one line is the difference between a plugin that annoys people and a plugin that breaks sites.
is_on_sale()
A method that WooCommerce gives you. It is true when the product has a sale price today. Sale schedules count too.
esc_html again
The text came from the database. We escape it on the way out. Same rule as the admin screen.
Step 4. Load it
In order-boost.php, add the require line under the first one:
require_once ORB_DIR . 'includes/class-orb-badge.php';
And add the object inside orb_init:
new ORB_Badge();
Two steps, always. Load the file. Build the object.
Step 5. Put a product on sale
- Go to Products in the admin.
- Edit any product.
- In the Product data box, set a Sale price lower than the regular price.
- Update.
Step 6. Test
Open your shop page. The product shows Hot Deal above the title. Open the single product page. It shows there too.
It has no colour yet. It is plain text. That is correct for now.
Now go to WooCommerce > Order Boost, set Show sale badge to No, and save. Reload the shop. The badge is gone.
Your settings screen and your shop are connected. That is the full loop of a plugin.
Break it on purpose
Change the badge text to Big <b>Sale</b> in the settings, and save.
The shop shows the letters <b> on the page. It does not print bold text.
That is esc_html doing its job. Now delete esc_html( and the closing bracket, so the line is:
echo '<span class="orb-badge">' . $text . '</span>';
Reload. The text is bold now.
It looks nicer, and it is a hole. Any admin can put a script in that box, and it runs for every visitor on your shop. Put esc_html back.
Next episode: CSS and JS. We make the badge red, and we learn why a stylesheet does not load on some pages.