Code Snippet: Oxygen Template Verwendung
Einführung
Oxygen ist ein mächtiges Plugin für WordPress, welches das WordPress Theme deaktiviert, die Erstellung eigener Templates mit einem visuellen Builder unterstützt, und damit ein ganz individuelles Design für die Website ermöglicht.
Innerhalb jedes Oxygen Templates wird dabei definiert, unter welchen Bedingungen es genutzt wird, beispielsweise für das Archiv oder den Blog, die Suchergebnisse, Einzeldarstellung von Seiten oder Beiträgen, all das für alle oder nur bestimmte Kategorien, Autoren, usw.
In der Liste der Templates sind diese Bedingungen leider nicht ersichtlich. Beim Einsatz vieler Templates geht daher schnell der Überblick verloren.
In Oxygen kann man Element-Blöcke als "Re-usable Part" speichern, um sie in anderen Templates wieder zu verwenden.
Hier fehlt in Oxygen dann aber der Überblick, ob und in welchen anderen Templates diese Element-Blöcke tatsächlich verwendet werden.
Mit der Oxygen Gutenberg Integration lassen sich Element-Blöcke zur Verwendung im Gutenberg Editor bereitstellen.
Auch hier bietet Oxygen keine Übersicht, ob und auf welchen Seiten diese Blöcke verwendet werden.
Lösung
Ich habe ein Code Snippet entwickelt, das die Verwendung von Templates und Blöcken anzeigt:
- Die Ansicht "Oxygen > Templates" wird um eine neue Spalte "Template Usage" erweitert.
Für Templates wird hier angezeigt, unter welchen Bedingungen das Template verwendet wird.
Für Re-usable Parts wird angezeigt, in welchen Templates sie verwendet werden. - Die Ansicht "Oxygen > Block Library" (verfügbar mit der Oxygen Gutenberg Integration) wird um eine neue Spalte "Template Usage" erweitert, die alle Seiten und Beiträge anzeigt, in denen dieser Gutenberg Block verwendet wird.
- Die Ansichten "Seiten" und Beiträge" werden um eine neue Spalte "Uses Template" erweitert, die das zugewiesene Oxygen Template anzeigt.
Zur Beachtung:
Werden Re-usable Parts mit der Option "editable" (statt "single") in ein Template oder eine Oxygen Seite eingefügt, erzeugt Oxygen eine Kopie des Inhaltes, ohne eine Referenz auf den originalen Re-usable Part zu hinterlegen. In diesem Fall kann mein Snippet die Verwendung nicht anzeigen.
Download
Dieser JSON-Download kann direkt in die Plugins Code Snippets oder Advanced Scripts importiert werden. Vergiss nicht, das Snippet nach dem Import zu aktivieren.
Falls Du ein anderes Snippet Plugin verwendest, kannst Du stattdessen den Source Code kopieren und damit selbst ein neues Snippet anlegen.
ma-oxygen-template-usage.code-snippets.json
Version 1.1.0, 2024-05-22
Spenden
Es macht mir viel Freude, Code Snippets zu entwickeln und damit Anforderungen zu lösen. Die Snippets stelle ich kostenfrei zur Verfügung.
Wenn Du möchtest, kannst Du meine vielen Stunden Arbeit mit einer kleinen Kaffee-Spende über PayPal honorieren.
Spenden werden selbstverständlich ordnungsgemäß durch mich versteuert.
Disclaimer
Das Code Snippet habe ich nach bestem Wissen und Gewissen getestet. (Siehe den Abschnitt "TESTED WITH" im Source Code)
Ich stelle das Code Snippet zur freien Verwendung zur Verfügung.
Eine Garantie für die Funktionalität in allen denkbaren WordPress Umgebungen kann ich nicht geben.
Download und Nutzung dieses Code Snippets erfolgen auf eigene Gefahr und Verantwortung.
Change Log
Siehe "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;