I wanted to output the current versions of specific plugins automatically and the parent theme (I am using a child theme), just to draw attention to what is being used. Originally, I thought I would limit it to Bricks, but I immediately had a need to use it in Etch, so I opted for the shortcode approach.
The shortcode syntax
Here are examples of the shortcodes (you would wrap with brackets []). In Etch, you can add shortcodes in the builder without quotations (at least for now). If you are adding this in Core, you would need to wrap values in quotes (e.g., plugin_version slug=”automaticcss-plugin”).
- Plugin
- plugin_version slug=akismet/akismet.php
- plugin_version slug=automaticcss-plugin
- Theme
- theme_version (active/child)
- theme_version which=parent
- theme_version which=twentytwentyfive
The Code
<?php
/**
* Plugin Name: FW Versions (Themes & Plugins)
* Description: Output current versions of selected plugins/themes via shortcodes & Bricks dynamic data/echo.
* Version: 0.2.0
* Requires at least: 6.0
* Tested up to: 6.8.3
*/
// ---------- Helpers -----------------------------------------------------------
if ( ! function_exists( 'fw_get_plugin_version' ) ) {
function fw_get_plugin_version( $ref = '' ) {
if ( empty( $ref ) ) {
return '';
}
// Cache briefly to avoid repeated scans.
$key = 'fw_plugin_ver_' . md5( $ref );
$ver = get_transient( $key );
if ( false !== $ver ) { return $ver; }
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = get_plugins();
// 1) Exact match like "akismet/akismet.php"
if ( isset( $plugins[ $ref ] ) && ! empty( $plugins[ $ref ]['Version'] ) ) {
$ver = $plugins[ $ref ]['Version'];
set_transient( $key, $ver, MINUTE_IN_SECONDS * 5 );
return $ver;
}
// 2) Try by folder or slug
$needle = trim( strtolower( $ref ) );
foreach ( $plugins as $file => $data ) {
// $file is "folder/plugin.php"
$folder = strtolower( strtok( $file, '/' ) );
$name = strtolower( $data['Name'] ?? '' );
if ( $needle === $folder || $needle === strtolower( $name ) ) {
$ver = $data['Version'] ?? '';
set_transient( $key, $ver, MINUTE_IN_SECONDS * 5 );
return $ver;
}
}
return '';
}
}
if ( ! function_exists( 'fw_get_theme_version' ) ) {
function fw_get_theme_version( $which = 'active' ) {
// $which: 'active' (child if present), 'parent', or a stylesheet slug.
$key = 'fw_theme_ver_' . md5( $which );
$ver = get_transient( $key );
if ( false !== $ver ) { return $ver; }
if ( 'parent' === $which ) {
$theme = wp_get_theme();
$theme = $theme->parent() ?: $theme; // fall back to active if no parent
} elseif ( 'active' === $which ) {
$theme = wp_get_theme();
} else {
// Treat as stylesheet slug
$theme = wp_get_theme( $which );
if ( ! $theme->exists() ) {
return '';
}
}
$ver = $theme->get( 'Version' ) ?: '';
set_transient( $key, $ver, MINUTE_IN_SECONDS * 5 );
return $ver;
}
}
if ( ! function_exists( 'fw_get_wp_version' ) ) {
function fw_get_wp_version() {
return get_bloginfo( 'version' );
}
}
// ---------- Shortcodes --------------------------------------------------------
/**
* [plugin_version slug="akismet/akismet.php"] or [plugin_version slug="akismet"]
*/
add_shortcode( 'plugin_version', function( $atts ) {
$atts = shortcode_atts( [
'slug' => '',
], $atts, 'plugin_version' );
return esc_html( fw_get_plugin_version( $atts['slug'] ) );
});
/**
* [theme_version] (active/child), [theme_version which="parent"], or [theme_version which="twentytwentyfive"]
*/
add_shortcode( 'theme_version', function( $atts ) {
$atts = shortcode_atts( [
'which' => 'active', // active|parent|{stylesheet}
], $atts, 'theme_version' );
return esc_html( fw_get_theme_version( $atts['which'] ) );
});
/**
* [wp_version] or [wp_version prefix="WordPress "]
*/
add_shortcode( 'wp_version', function( $atts ) {
$atts = shortcode_atts( [
'prefix' => '', // e.g., "WordPress "
], $atts, 'wp_version' );
$version = get_bloginfo( 'version' ); // same as $GLOBALS['wp_version']
return esc_html( $atts['prefix'] . $version );
});
