Blog

Code Snippet: Oxygen Template Verwendung

Version: 1.1.0 (22.05.2024)

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.

  Bei Klick auf den Button wird eine Verbindung zu PayPal aufgebaut.

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;


Erstveröffentlichung: 14.12.2020 auf Code Snippet: Oxygen Template Verwendung
magnifier