query_flags();
$ctx = $this->current_object_info();
$render_ms = isset( $GLOBALS['wpcoder_render_start'] )
? round( ( microtime( true ) - (float) $GLOBALS['wpcoder_render_start'] ) * 1000, 1 )
: null;
$stats = $this->db_stats();
// Root node
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_info',
'title' => 'Dev Info',
'meta' => [ 'class' => 'wpcoder-dev-info' ],
'href' => false
] );
// Memory headline
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_mem',
'parent' => 'wpc_dev_info',
'title' => 'Memory: ' . size_format( memory_get_peak_usage( true ) ),
'href' => false,
] );
// Render headline
if ( $render_ms !== null ) {
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_render',
'parent' => 'wpc_dev_info',
'title' => 'Render: ' . $render_ms . ' ms',
'href' => false,
] );
}
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_theme',
'parent' => 'wpc_dev_info',
'title' => 'Active Theme',
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_theme_name',
'parent' => 'wpc_dev_theme',
'title' => 'Name: ' . esc_html( $theme->get( 'Name' ) ),
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_theme_version',
'parent' => 'wpc_dev_theme',
'title' => 'Version: ' . esc_html( $theme->get( 'Version' ) ),
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_theme_author',
'parent' => 'wpc_dev_theme',
'title' => 'Author: ' . esc_html( $theme->get( 'Author' ) ),
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_tpl',
'parent' => 'wpc_dev_info',
'title' => 'Template Info',
'href' => false
] );
if ( $tpl_file ) {
$wp_admin_bar->add_node( [
'id' => 'wpc_tpl_info',
'parent' => 'wpc_dev_tpl',
'title' => 'Template: ' . esc_html( $tpl_file ),
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_tpl_path',
'parent' => 'wpc_dev_tpl',
'title' => 'Path: ' . esc_html( $tpl_path ),
'href' => false
] );
}
$structure = get_option( 'permalink_structure' ) ?: 'plain';
$wp_admin_bar->add_node( [
'id' => 'wpc_tpl_permalinks',
'parent' => 'wpc_dev_tpl',
'title' => 'Permalinks: ' . esc_html( $structure ),
'href' => false
] );
$canonical = function_exists( 'wp_get_canonical_url' ) ? wp_get_canonical_url() : '';
$wp_admin_bar->add_node( [
'id' => 'wpc_tpl_urls',
'parent' => 'wpc_dev_tpl',
'title' => "canonical: " . esc_html( $canonical ),
'href' => false
] );
$scheme = is_ssl() ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'] ?? '';
$req = $_SERVER['REQUEST_URI'] ?? '';
$full = esc_url_raw( $scheme . $host . $req );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_full_url',
'parent' => 'wpc_dev_tpl',
'title' => 'Current URL: ' . $full,
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_query',
'parent' => 'wpc_dev_info',
'title' => 'Query Info',
] );
foreach ( $ctx as $line_id => $line ) {
$wp_admin_bar->add_node( [
'id' => 'wpcoder_ctx_' . $line_id,
'parent' => 'wpc_dev_query',
'title' => esc_html( $line ),
] );
}
if ( $query_type ) {
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_query_type',
'parent' => 'wpc_dev_query',
'title' => 'Query: ' . esc_html( $query_type ),
] );
}
if ( $stats['count'] !== null ) {
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_query_db',
'parent' => 'wpc_dev_query',
'title' => 'Database Queries: ' . (int) $stats['count'],
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_query_time',
'parent' => 'wpc_dev_query',
'title' => 'Query Time: ' . round( (float) $stats['time'] * 1000, 1 ) . ' ms',
] );
$avg = $stats['time'] / max( 1, $stats['count'] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_perf_db_avg',
'parent' => 'wpc_dev_query',
'title' => 'Avg Query: ' . number_format_i18n( $avg * 1000, 2 ) . ' ms',
'href' => false
] );
}
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES && ! empty( $GLOBALS['wpdb']->queries ) ) {
$qs = $GLOBALS['wpdb']->queries;
usort( $qs, fn( $a, $b ) => ( $b[1] ?? 0 ) <=> ( $a[1] ?? 0 ) );
$top = array_slice( $qs, 0, 3 );
$tip = [];
foreach ( $top as $i => $q ) {
$tip[] = sprintf( "#%d (%.2f ms)\n%s", $i + 1, ( $q[1] ?? 0 ) * 1000, $q[0] ?? '' );
}
$wp_admin_bar->add_node([
'id' => 'wpc_dev_query_top',
'parent' => 'wpc_dev_query',
'title' => 'Top slow queries ?',
'meta' => [
'title' => implode("\n\n",$tip),
'class' => 'wpc-dev-has-tooltip'
],
'href' => false,
]);
}
if ( ! empty( $body_cls ) ) {
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_body',
'parent' => 'wpc_dev_info',
'title' => 'Body Classes (' . count( $body_cls ) . ')',
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_body_classes',
'parent' => 'wpc_dev_body',
'title' => implode( ' ', $body_cls ),
'href' => false
] );
}
$scripts = wp_scripts();
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_js',
'parent' => 'wpc_dev_info',
'title' => 'JS (' . count( $scripts->queue ) . ')',
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_js_id',
'parent' => 'wpc_dev_js',
'title' => implode( ', ', (array) $scripts->queue ),
'href' => false
] );
$styles = wp_styles();
$style_queue = array_diff( (array) $styles->queue, [ 'wpcoder-debug-bar' ] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_css',
'parent' => 'wpc_dev_info',
'title' => 'CSS (' . count( $style_queue ) . ')',
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_css_id',
'parent' => 'wpc_dev_css',
'title' => implode( ', ', (array) $style_queue ),
'href' => false
] );
$wordpress_info = $this->get_wp_info();
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wordpress',
'parent' => 'wpc_dev_info',
'title' => __( 'WP Environment', 'wpcoderpro' ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wp_version',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP Version', 'wpcoderpro' ) . ': %s', $wordpress_info['wp_version'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wp_multisite',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP Multisite', 'wpcoderpro' ) . ': %s', ( $wordpress_info['wp_multisite'] ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wp_memory_limit',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP Memory Limit', 'wpcoderpro' ) . ': %s', $wordpress_info['wp_memory_limit'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wp_debug_mode',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP Debug Mode', 'wpcoderpro' ) . ': %s', ( $wordpress_info['wp_debug_mode'] ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wp_cron',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP Cron', 'wpcoderpro' ) . ': %s', ( $wordpress_info['wp_cron'] ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_language',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'WP language', 'wpcoderpro' ) . ': %s', $wordpress_info['language'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_timezone',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'Timezone', 'wpcoderpro' ) . ': %s', $wordpress_info['timezone'] ),
'href' => false
) );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_times',
'parent' => 'wpc_dev_wordpress',
'title' => 'Local: ' . wp_date( 'Y-m-d H:i:s' ) . ' · UTC: ' . gmdate( 'Y-m-d H:i:s' ),
'href' => false
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_wordpress_cache',
'parent' => 'wpc_dev_wordpress',
'title' => 'Object Cache: ' . ( wp_using_ext_object_cache() ? 'ON (persistent)' : 'OFF' ),
] );
$has_dropin = file_exists( WP_CONTENT_DIR . '/object-cache.php' );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_cache_dropin',
'parent' => 'wpc_dev_wordpress',
'title' => 'Cache drop-in: ' . ( $has_dropin ? 'present' : 'none' ),
'href' => false
] );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_wordpress_environment',
'parent' => 'wpc_dev_wordpress',
'title' => sprintf( __( 'Env', 'wpcoderpro' ) . ': %s', $wordpress_info['environment'] ),
'href' => false
) );
$get_environment_info = $this->get_environment_info();
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment',
'parent' => 'wpc_dev_info',
'title' => __( 'Server Environment', 'wpcoderpro' ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_server_info',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'Server info', 'wpcoderpro' ) . ': %s', $get_environment_info['server_info'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_php_version',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'PHP version', 'wpcoderpro' ) . ': %s', $get_environment_info['php_version'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_mysql_version',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'MySQL version', 'wpcoderpro' ) . ': %s', $get_environment_info['mysql_version'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_db_prefix',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'DB Prefix', 'wpcoderpro' ) . ': %s', $get_environment_info['db_prefix'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_db_charset',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'DB Charset/Collate', 'wpcoderpro' ) . ': %s', $get_environment_info['db_charset'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_php_post_max_size',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'PHP Post Max Size', 'wpcoderpro' ) . ': %s', $get_environment_info['php_post_max_size'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_php_max_execution_time',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'PHP Time Limit', 'wpcoderpro' ) . ': %s' . __( 'sec', 'wpcoderpro' ), $get_environment_info['php_max_execution_time'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_php_max_input_vars',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'PHP Max Input Vars', 'wpcoderpro' ) . ': %s', $get_environment_info['php_max_input_vars'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_max_upload_size',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'Max Upload Size', 'wpcoderpro' ) . ': %s', $get_environment_info['max_upload_size'] ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_gzip_enabled',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'GZip', 'wpcoderpro' ) . ': %s', ( $get_environment_info['gzip_enabled'] == '1' ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_mbstring_enabled',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'Multibyte String', 'wpcoderpro' ) . ': %s', ( $get_environment_info['mbstring_enabled'] == '1' ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
$wp_admin_bar->add_menu( array(
'id' => 'wpc_dev_environment_ssl_enabled',
'parent' => 'wpc_dev_environment',
'title' => sprintf( __( 'SSL', 'wpcoderpro' ) . ': %s', ( $get_environment_info['ssl_enabled'] == '1' ) ? __( 'enable', 'wpcoderpro' ) : __( 'disable', 'wpcoderpro' ) ),
'href' => false
) );
if(is_singular() || is_tax() || is_category() || is_tag() ) {
$shortcodes_content = $this->get_current_content_for_shortcode_scan();
$shortcodes_list = $this->collect_shortcodes_detailed( $shortcodes_content );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_shortcodes_full',
'parent' => 'wpc_dev_info',
'title' => 'Shortcodes (' . count( $shortcodes_list ) . ')',
'href' => false,
] );
$wp_admin_bar->add_node( [
'id' => 'wpc_dev_shortcodes_list',
'parent' => 'wpc_dev_shortcodes_full',
'title' => $shortcodes_list ? implode( ", ", array_map( static function ( $it ) {
return esc_html( $it['full'] );
}, $shortcodes_list ) ) : __( 'None found', 'wpcoderpro' ),
'href' => false
] );
}
}
private function db_stats(): array {
global $wpdb;
if ( ! defined( 'SAVEQUERIES' ) || ! SAVEQUERIES || empty( $wpdb->queries ) ) {
return [ 'count' => null, 'time' => null ];
}
// $wpdb->queries: [ [ sql, elapsed_time, callstack, start_time? ], ... ]
$count = count( $wpdb->queries );
$time = 0.0;
foreach ( $wpdb->queries as $q ) {
// $q[1] is seconds as float
$time += isset( $q[1] ) ? (float) $q[1] : 0.0;
}
return [ 'count' => $count, 'time' => $time ]; // time in seconds
}
private function query_flags(): string {
$flags = [];
// Order matters: more specific first
if ( is_front_page() ) {
$flags[] = 'front_page';
}
if ( is_home() ) {
$flags[] = 'home';
}
if ( is_singular() ) {
$flags[] = 'singular';
}
if ( is_page() ) {
$flags[] = 'page';
}
if ( is_single() ) {
$flags[] = 'single';
}
if ( is_attachment() ) {
$flags[] = 'attachment';
}
if ( is_archive() ) {
$flags[] = 'archive';
}
if ( is_category() ) {
$flags[] = 'category';
}
if ( is_tag() ) {
$flags[] = 'tag';
}
if ( is_tax() ) {
$flags[] = 'tax';
}
if ( is_author() ) {
$flags[] = 'author';
}
if ( is_date() ) {
$flags[] = 'date';
}
if ( is_search() ) {
$flags[] = 'search';
}
if ( is_404() ) {
$flags[] = '404';
}
if ( is_paged() ) {
$flags[] = 'paged';
}
return implode( ' · ', $flags );
}
private function current_object_info(): array {
$lines = [];
if ( is_singular() ) {
$post_id = get_the_ID();
$type = get_post_type( $post_id );
$slug = $post_id ? get_post_field( 'post_name', $post_id ) : '';
$lines[] = 'Post ID: ' . (int) $post_id;
$lines[] = 'Post Type: ' . (string) $type;
$lines[] = 'Slug: ' . (string) $slug;
return $lines;
}
if ( is_tax() || is_category() || is_tag() ) {
$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
$lines[] = 'Taxonomy: ' . (string) $term->taxonomy;
$lines[] = 'Term ID: ' . (int) $term->term_id;
$lines[] = 'Term Slug: ' . (string) $term->slug;
return $lines;
}
}
if ( is_author() ) {
$user = get_queried_object();
if ( $user && ! is_wp_error( $user ) ) {
$lines[] = 'Author ID: ' . (int) $user->ID;
$lines[] = 'Login: ' . (string) $user->user_login;
return $lines;
}
}
if ( is_search() ) {
$lines[] = 'Search: ' . (string) get_search_query();
return $lines;
}
// Fallbacks
if ( is_front_page() ) {
$lines[] = 'Front Page';
return $lines;
}
if ( is_home() ) {
$lines[] = 'Blog Home';
return $lines;
}
// Generic queried object (archives without specific object)
$obj = get_queried_object();
if ( $obj && ! is_wp_error( $obj ) ) {
$lines[] = 'Object: ' . get_class( $obj );
}
return $lines ?: [ 'No specific object' ];
}
private function get_environment_info(): array {
global $wpdb;
return array(
'server_info' => $_SERVER['SERVER_SOFTWARE'],
'php_version' => phpversion(),
'php_post_max_size' => $this->convert( $this->let_to_num( ini_get( 'post_max_size' ) ) ),
'php_max_execution_time' => ini_get( 'max_execution_time' ),
'php_max_input_vars' => ini_get( 'max_input_vars' ),
'max_upload_size' => size_format( wp_max_upload_size() ),
'gzip_enabled' => is_callable( 'gzopen' ),
'mbstring_enabled' => extension_loaded( 'mbstring' ),
'ssl_enabled' => ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) === 'on' ) ? 1 : 0,
'mysql_version' => ( ! empty( $wpdb->is_mysql ) ? $wpdb->db_version() : '' ),
'db_prefix' => $wpdb->prefix,
'db_charset' => DB_CHARSET . ' / ' . ( DB_COLLATE ?: 'default' ),
);
}
// Returns structured WP info (human-readable + safe fallbacks)
private function get_wp_info(): array {
// Use core helpers instead of custom convert/let_to_num
$to_bytes = static function ( string $hr ) {
return function_exists( 'wp_convert_hr_to_bytes' ) ? wp_convert_hr_to_bytes( $hr ) : (int) $hr;
};
// Memory limits (constants may be undefined in edge envs)
$wp_mem_limit_str = defined( 'WP_MEMORY_LIMIT' ) ? WP_MEMORY_LIMIT : ini_get( 'memory_limit' );
$wp_mem_limit_b = $to_bytes( (string) $wp_mem_limit_str );
$wp_mem_max_str = defined( 'WP_MAX_MEMORY_LIMIT' ) ? WP_MAX_MEMORY_LIMIT : $wp_mem_limit_str;
$wp_mem_max_b = $to_bytes( (string) $wp_mem_max_str );
// Timezone name via WP API (handles timezone_string/gmt_offset)
$tz = function_exists( 'wp_timezone' ) ? wp_timezone()->getName() : ( get_option( 'timezone_string' ) ?: 'UTC' );
return [
// Core
'wp_version' => get_bloginfo( 'version' ),
'wp_multisite' => is_multisite(),
// Memory (both raw bytes and human readable)
'wp_memory_limit' => size_format( $wp_mem_limit_b ),
'wp_memory_limit_b' => $wp_mem_limit_b,
'wp_max_memory' => size_format( $wp_mem_max_b ),
'wp_max_memory_b' => $wp_mem_max_b,
// Flags
'wp_debug_mode' => (int) ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
'wp_cron' => (int) ( ! defined( 'DISABLE_WP_CRON' ) || ! DISABLE_WP_CRON ),
// I18n / Time
'language' => get_locale(),
'timezone' => $tz,
'local_time' => function_exists( 'wp_date' ) ? wp_date( 'Y-m-d H:i:s' ) : date( 'Y-m-d H:i:s' ),
'utc_time' => gmdate( 'Y-m-d H:i:s' ),
// Env type (WP 5.5+)
'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
];
}
private function get_timezone(): string {
$tzstring = get_option( 'timezone_string' );
// Якщо в адмінці обрано місто → напр. Europe/Kiev
if ( ! empty( $tzstring ) ) {
return $tzstring;
}
// Якщо місто не задано → будуємо з gmt_offset
$offset = (float) get_option( 'gmt_offset' );
if ( 0 === $offset ) {
return 'UTC';
}
$hours = (int) $offset;
$minutes = abs( ( $offset - $hours ) * 60 );
return sprintf( 'UTC%+03d:%02d', $hours, $minutes );
}
private function convert( $size ): string {
$unit = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB' );
return @round( $size / pow( 1024, ( $i = floor( log( $size, 1024 ) ) ) ), 2 ) . ' ' . $unit[ $i ];
}
private function let_to_num( $size ) {
$l = substr( $size, - 1 );
$ret = substr( $size, 0, - 1 );
switch ( strtoupper( $l ) ) {
case 'P':
$ret *= 1024;
case 'T':
$ret *= 1024;
case 'G':
$ret *= 1024;
case 'M':
$ret *= 1024;
case 'K':
$ret *= 1024;
}
return $ret;
}
// Find shortcodes in a given string. Returns ['found'=>[tag=>count], 'unknown'=>[tag=>count]]
private function find_shortcodes_in_string(string $content): array {
global $wpc_shortcode_tags;
$result = ['found' => [], 'unknown' => []];
if ($content === '') return $result;
$pattern = get_shortcode_regex();
if ( preg_match_all( '/'.$pattern.'/s', $content, $matches, PREG_SET_ORDER ) ) {
foreach ( $matches as $m ) {
$tag = isset($m[2]) ? strtolower($m[2]) : '';
if ( $tag === '' ) continue;
// count found
$result['found'][$tag] = ($result['found'][$tag] ?? 0) + 1;
// mark unknown if not registered
if ( empty($wpc_shortcode_tags[$tag]) ) {
$result['unknown'][$tag] = ($result['unknown'][$tag] ?? 0) + 1;
}
}
}
// sort by count desc
arsort($result['found']);
arsort($result['unknown']);
return $result;
}
// Collect page content to scan for shortcodes
private function get_current_content_for_shortcode_scan(): string {
if ( is_singular() ) {
$pid = get_the_ID();
return $pid ? (string) get_post_field('post_content', $pid) : '';
}
if ( is_tax() || is_category() || is_tag() ) {
$term = get_queried_object();
return ($term && !is_wp_error($term) && !empty($term->description)) ? (string) $term->description : '';
}
return '';
}
// Scan content for shortcodes and return detailed list
private function collect_shortcodes_detailed(string $content): array {
$out = []; // each item: ['tag'=>string,'attrs'=>array,'full'=>string]
if ($content === '') return $out;
$regex = get_shortcode_regex();
if ( preg_match_all('/'.$regex.'/s', $content, $m, PREG_SET_ORDER) ) {
foreach ($m as $match) {
// $match[0] = full match, $match[2] = tag, $match[3] = attributes string, $match[5] = inner content (if any)
$tag = strtolower($match[2] ?? '');
$full = $match[0] ?? '';
$attrS = isset($match[3]) ? trim($match[3]) : '';
$attrs = shortcode_parse_atts($attrS) ?: [];
$out[] = [
'tag' => $tag,
'attrs' => $attrs,
'full' => $full, // original text as in content
];
}
}
return $out;
}
}