Code Snippet: Oxygen Template Usage
Introduction
Oxygen is a powerful plugin for WordPress that deactivates the WordPress theme, supports the creation of own templates with a visual builder and thus enables a fully individual design for your website.
Within each Oxygen template you define the conditions under which it will be used, e.g. for the archive or blog, search results, single pages or posts, for all or only certain categories, authors, etc.
Unfortunately, these conditions are not visible in the list of templates. When working with a larger number of templates, the overview is quickly lost.
In Oxygen you can save element blocks as "Re-usable Part" to use them in other templates.
However, Oxygen lacks an overview of whether and in which other templates these element blocks are actually used.
With the Oxygen Gutenberg integration, element blocks can be made available for use in the Gutenberg editor.
Here, too, Oxygen does not provide an overview of whether and on which pages these blocks are used.
Solution
I developed a code snippet that shows the usage of templates and blocks:
- A new column "Template Usage" is added to the "Oxygen > Templates" view.
For templates it shows under which conditions the template is used.
For re-usable parts it shows in which templates they are used. - The "Oxygen > Block Library" view (available with the Oxygen Gutenberg integration) is extended by a new "Template Usage" column that shows all pages and posts in which this Gutenberg block is used.
- The views "Pages" and "Posts" are extended by a new column "Uses Template", which shows the assigned Oxygen template.
Note:
When adding Re-usable Parts to an Oxygen Template or Page with the option "editable" (instead of "single"), Oxygen creates a copy of the content without storing a reference to the original Re-usable Part. In this case my snippet is not able to display the usage.
Download
This JSON download can be imported directly into the plugins Code Snippets or Advanced Scripts. Don't forget to activate the snippet after import.
If you are using a different snippet plugin, you can copy the source code instead and create a new snippet yourself.
ma-oxygen-template-usage.code-snippets.json
Version 1.1.0, 2024-05-22
Donation
I enjoy developing code snippets and solving requirements with them. I provide the snippets free of charge.
If you like, you can honor my many hours of work with a small coffee donation via PayPal.
Your donation will of course be taxed properly by me.
Disclaimer
I have tested the code snippet to the best of my knowledge and belief. (See the section "TESTED WITH" in the source code)
I provide the code snippet for free use.
I cannot give a guarantee for the functionality in all conceivable WordPress environments.
Download and use of this code snippet is at your own risk and responsibility.
Change Log
See "Version History" in Source Code
Source Code
<?php /* Plugin Name: MA Oxygen Template Usage Description: Adds new columns "Template Usage" in Oxygen Templates and Block Library lists, and "Uses Template" in posts/pages list. Author: <a href="https://www.altmann.de/">Matthias Altmann</a> Version: 1.1.0 Plugin URI: https://www.altmann.de/en/blog-en/blog-en/code-snippet-oxygen-template-usage/ Description: en: https://www.altmann.de/en/blog-en/code-snippet-oxygen-template-usage/ de: https://www.altmann.de/blog/code-snippet-oxygen-template-verwendung/ Copyright: © 2020-2024, Matthias Altmann TESTED WITH: Product Versions -------------------------------------------------------------------------------------------------------------- PHP 7.4, ..., 8.1 WordPress 5.9, ..., 6.5.3 Oxygen 4.0, ..., 4.8.3 -------------------------------------------------------------------------------------------------------------- VERSION HISTORY Date Version Description --------------------------------------------------------------------------------------------------------------------- 2024-05-22 1.1.0 New Features: - Show template used in pages and posts lists (Thanks to Christian van 't Hof for the inspiration) Changes: - Code redesign as class - Compatibility to Oxygen 4.8.3 with changed post meta keys 2022-02-11 Tested with PHP 8.0, WordPress 5.9, Oxygen 4.0 beta 1 2021-01-22 1.0.4 Fix: - Corrected typo (Thanks to Adrien Robert for reporting!) 2021-01-10 1.0.3 Enhancement: - Detect "All [Custom Taxonomies]" with proper naming 2021-01-10 1.0.2 Bug Fix: - Correct detection of assignment "All Post Types / Categories / Tags / Authors" (Thanks to Wolfgang Rotschek for reporting!) 2020-12-14 1.0.1 New Features: - Oxygen Templates list: For Re-usable Parts, show usage (as single) in templates/pages - Oxygen Block Library list: Show usage in pages 2020-09-12 1.0.0 Initial Release */ if (!class_exists('MA_OxygenTemplateUsage')) : class MA_OxygenTemplateUsage { const TITLE = 'MA Oxygen Template Usage'; const SLUG = 'ma-oxygen-template-usage'; const SHRT = 'maotu'; const VERSION = '1.1.0'; //------------------------------------------------------------------------------------------------------------------- function __construct(){ add_action('after_setup_theme', [$this, 'oxy_templates']); add_action('after_setup_theme', [$this, 'oxy_user_library']); add_action('after_setup_theme', [$this, 'posts']); add_action('after_setup_theme', [$this, 'pages']); } //------------------------------------------------------------------------------------------------------------------- /** * Adds column "Template Usage" to post lists "Oxygen Templates" and "Oxygen Re-usables" */ function oxy_templates() { // add column title add_filter('manage_ct_template_posts_columns', function($columns){; $columns[self::SHRT] = 'Template Usage'; return $columns; }); // add column content add_action('manage_ct_template_posts_custom_column', function($column_name, $post_id) { if ($column_name != self::SHRT) return; global $post; // Oxygen pre or post 4.8.3? $meta_prefix = function_exists('oxy_get_post_meta') ? '_' : ''; // get_post_meta does not fire a db query since post meta is still cached from listing $meta = get_post_meta($post->ID); if (($meta[$meta_prefix.'ct_template_type'][0]??'') == 'reusable_part') { // REUSABLE PART // search database for references to this reusable part global $wpdb; $stmt = sprintf('SELECT * FROM %spostmeta WHERE meta_key="%sct_builder_shortcodes" AND meta_value LIKE "%%ct_options=\'{\"view_id\":%d,%%"', $wpdb->prefix, $meta_prefix, $post->ID); $references = $wpdb->get_results($stmt, OBJECT ); $refs = []; foreach ($references as $reference) { $reference_post = get_post($reference->post_id); $refs[] = sprintf('<a href="%s">%s</a>',get_edit_post_link($reference_post->ID), $reference_post->post_title); } if (count($refs)) { echo '<b>Used in:</b><br/>'.implode(', ', $refs); } } else { // TEMPLATE // --- Singular -------------------------------------------------------- // collect settings for Oxygen's Sigular section $apply= []; // Singular Post Types $post_types = []; if (@$meta[$meta_prefix.'ct_template_single_all'][0] == 'true') {$post_types[] = '<i>All</i>';} $specific_post_types = maybe_unserialize(@$meta[$meta_prefix.'ct_template_post_types'][0]); if (is_array($specific_post_types) && count($specific_post_types)) { $post_types = array_merge($post_types,$this->parse_oxy_post_types($specific_post_types)); } if (is_array($post_types) && count($post_types)) { $apply[] = 'Post Types: ' . join(', ',$post_types); } // Singular Taxonomies if (@$meta[$meta_prefix.'ct_use_template_taxonomies'][0]=='true') { $taxonomies = maybe_unserialize(@$meta[$meta_prefix.'ct_template_taxonomies'][0]); $taxonomies = $this->parse_oxy_taxonomies($taxonomies); if (is_array($taxonomies) && count($taxonomies)) { $apply[] = 'Taxonomies: ' . join(', ',$taxonomies); } } // Singular Parents if (@$meta[$meta_prefix.'ct_template_apply_if_post_of_parents'][0]=='true') { $parents = maybe_unserialize(@$meta[$meta_prefix.'ct_template_post_of_parents'][0]); $apply[] = 'Parent IDs: '.join(', ',$parents); } // Final output if (count($apply)) {echo '<b>Singular:</b><br/>'.join('<br/>',$apply).'<br/>';} // --- Archive --------------------------------------------------------- // collect settings for Oxygen's Archive section $apply = []; // All Archives if (@$meta[$meta_prefix.'ct_template_all_archives'][0]=='true') {$apply[] = '<i>All</i>';} // Archive Taxonomies if (@$meta[$meta_prefix.'ct_template_apply_if_archive_among_taxonomies'][0]=='true') { $taxonomies = maybe_unserialize(@$meta[$meta_prefix.'ct_template_archive_among_taxonomies'][0]); $taxonomies = $this->parse_oxy_taxonomies($taxonomies); if (is_array($taxonomies) && count($taxonomies)) { $apply[] = 'Taxonomies: ' . join(', ',$taxonomies); } } // Archive Post Types if (@$meta[$meta_prefix.'ct_template_apply_if_archive_among_cpt'][0]=='true') { $post_types = maybe_unserialize(@$meta[$meta_prefix.'ct_template_archive_post_types'][0]); $post_types = $this->parse_oxy_post_types($post_types); if (is_array($post_types) && count($post_types)) { $apply[] = 'Post Types: ' . join(', ',$post_types); } } // Archive Authors if (@$meta[$meta_prefix.'ct_template_apply_if_archive_among_authors'][0]=='true') { $authors = maybe_unserialize(@$meta[$meta_prefix.'ct_template_authors_archives'][0]); $authors = $this->parse_oxy_authors($authors); if (is_array($authors) && count($authors)) { $apply[] = 'Authors: ' . join(', ',$authors); } } // Archive Date if (@$meta[$meta_prefix.'ct_template_date_archive'][0] == 'true') {$apply[] = 'Date Archive';} // Final output if (count($apply)) {echo '<b>Archive:</b><br/>'.join('<br/>',$apply).'<br/>';} // --- Others ---------------------------------------------------------- // collect settings for Oxygen's Other section $apply = []; if (@$meta[$meta_prefix.'ct_template_front_page'][0] == 'true') {$apply[] = 'Front Page';} if (@$meta[$meta_prefix.'ct_template_blog_posts'][0] == 'true') {$apply[] = 'Blog Posts Index';} if (@$meta[$meta_prefix.'ct_template_search_page'][0] == 'true') {$apply[] = 'Search Page';} if (@$meta[$meta_prefix.'ct_template_404_page'][0] == 'true') {$apply[] = '404';} if (@$meta[$meta_prefix.'ct_template_inner_content'][0] == 'true') {$apply[] = 'Inner Content';} if (@$meta[$meta_prefix.'ct_template_index'][0] == 'true') {$apply[] = '<i>Catch All</i>';} // Final output if (count($apply)) {echo '<b>Others:</b><br/>' . join(', ',$apply).'<br/>';} } }, 10, 2 ); } //------------------------------------------------------------------------------------------------------------------- /** * Adds column "Template Usage" to post lists "Oxygen Block Library" */ function oxy_user_library(){ // add column title add_filter('manage_oxy_user_library_posts_columns', function($columns){ $columns[self::SHRT] = 'Template Usage'; return $columns; }); // add column content add_action('manage_oxy_user_library_posts_custom_column', function($column_name, $post_id){ if ($column_name != self::SHRT) return; global $post, $wpdb; $stmt = sprintf('SELECT * FROM %sposts WHERE post_type != "revision" AND post_content LIKE "%%<!-- wp:oxygen-vsb/ovsb-%s%%"', $wpdb->prefix, $post->post_name); $references = $wpdb->get_results($stmt, OBJECT ); $refs = []; foreach ($references as $reference) { $refs[] = sprintf('<a href="%s">%s</a>',get_edit_post_link($reference->ID), $reference->post_title); } echo implode(', ', $refs); }, 10, 2 ); } //------------------------------------------------------------------------------------------------------------------- /** * Adds column "Template Usage" to posts (post, page) lists */ //------------------------------------------------------------------------------------------------------------------- private function add_post_list_column($type='post'){ // add column title to posts add_filter('manage_'.$type.'_posts_columns', function($columns){ $columns[self::SHRT] = 'Uses Template'; return $columns; }); // add column content add_action('manage_'.$type.'_posts_custom_column', function($column_name, $post_id=null){ if ($column_name != self::SHRT) return; if (!$post_id) { $post_id = get_the_id(); } // Oxygen pre or post 4.8.3? $meta_function_name = function_exists('oxy_get_post_meta') ? 'oxy_get_post_meta' : 'get_post_meta'; $templates = call_user_func($meta_function_name, $post_id, 'ct_other_template', false ); if ($templates) { foreach ($templates as $template) { switch($template) { case '-1': echo 'None'; break; case '0': { $tpl = ct_get_posts_template($post_id); echo $tpl->post_title.' <i>(Default)</i>'; break; } default: { $title = get_the_title($template, false); if (empty($title)) $title = '<span style="color:red">Unknown ID '.$template.'</span>'; echo $title; } } } } else { $tpl = ct_get_posts_template($post_id); echo $tpl->post_title.' <i>(Default)</i>'; } }); } //------------------------------------------------------------------------------------------------------------------- /** * Adds column "Template Usage" to posts lists */ function posts(){ $this->add_post_list_column('post'); } //------------------------------------------------------------------------------------------------------------------- /** * Adds column "Template Usage" to pages lists */ function pages(){ $this->add_post_list_column('page'); } //------------------------------------------------------------------------------------------------------------------- /** * Translates post type slugs (page, post, ...) to localized names (Pages, Posts, ...) */ private function parse_oxy_post_types($post_types) { $retval = []; if (is_array($post_types) && count($post_types)) { foreach($post_types as $post_type) { switch ($post_type) { case 'all_posttypes': $retval[] = '<i>All Post Types</i>'; break; default: $post_type_object = get_post_type_object($post_type); $retval[] = $post_type_object->label??''; } } } return $retval; } //------------------------------------------------------------------------------------------------------------------- /** * Retrieves term names from ID list or Oxygen names,values array */ private function parse_oxy_taxonomies_with_group($taxonomies) { $retval = ''; if (is_array($taxonomies)) { $apply_tax = []; foreach ($taxonomies['names'] as $idx => $name) { if ($name=='tag') {$name = 'post_tag';} $tax_obj = get_taxonomy($name); if (!$tax_obj) {continue;} $tax_lab = $tax_obj->labels->singular_name; $term_id = $taxonomies['values'][$idx]; $term = get_term($term_id, $name); if ($term) { if (!array_key_exists($name,$apply_tax)) { $apply_tax[$name] = (object)['slug'=>$name,'name'=>$tax_lab,'terms'=>[]]; } $apply_tax[$name]->terms[] = $term->name; } } foreach (array_keys($apply_tax) as $tax_slug) { $tax = $apply_tax[$tax_slug]; $tax_title = $tax->name; if (!in_array($tax_slug,['post_tag','category'])) {$tax_title .= ' ('.$tax_slug.')';} $retval .= '<i>'.$tax_title.': '.join(', ',$tax->terms).'</i>'; } } return $retval; } //------------------------------------------------------------------------------------------------------------------- /** * Retrieves term names from ID list or Oxygen names,values array */ private function parse_oxy_taxonomies($taxonomies) { $retval = []; if (is_array($taxonomies) && count($taxonomies)) { if (array_key_exists('values',$taxonomies)) {$taxonomies = $taxonomies['values'];} foreach ($taxonomies as $tax_id) { $tax_name = null; if ($tax_id == 'all_categories') {$tax_name = '<i>All Categories</i>';} elseif ($tax_id == 'all_tags') {$tax_name = '<i>All Tags</i>';} elseif (preg_match('/^all_(.*)$/', $tax_id, $matches)) { $tax_slug = $matches[1]; $tax_object = get_taxonomy($tax_slug); if ($tax_object) { $tax_labels = get_taxonomy_labels($tax_object); if ($tax_labels) { $tax_name = '<i>All '.$tax_labels->name.'</i>'; } } } if (!$tax_name) { $term = get_term($tax_id); if ($term) {$tax_name = $term->name;} } if (!$tax_name) { // final fallback $tax_name = '<i>'.$tax_slug.'</i>'; } $retval[] = $tax_name; } } return $retval; } //------------------------------------------------------------------------------------------------------------------- /** * Retrieves author IDs to names */ private function parse_oxy_authors($authors) { $retval = []; if (is_array($authors) && count($authors)) { foreach ($authors as $user_id) { if ($user_id == 'all_authors') {$retval[] = '<i>All Authors</i>'; continue;} $user = get_userdata($user_id); if ($user) {$retval[] = $user->user_login;} } } return $retval; } } //=================================================================================================================== // Initialize if (is_admin() && !wp_doing_ajax() && !wp_doing_cron() ) { new MA_OxygenTemplateUsage(); } endif;