Blog

Code Snippet: Oxygen Template Verwendung

(2020)

Inhalt

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.

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

Das Code Snippet steht hier zum Download zur Verfügung:

oxygen-template-usage.code-snippets.json
Version 1.0.4, 2021-01-22

Zur Installation und Nutzung dieser JSON Datei wird das Plugin Code Snippets benötigt.
Dort kann diese JSON Datei mit der Funktion "Import" hochgeladen und anschließend aktiviert werden.

Falls noch mein vorheriges Snippet "Spalte 'Application' in Oxygen Template Liste" installiert ist, muss dieses bitte gelöscht werden!

Alternativ: Am Ende dieser Seite kann der vollständige Source Code des Snippets eingesehen und kopiert werden.

Im Change Log sind neue Funktionalitäten und Fehlerbehebungen dokumentiert.

Disclaimer

Das Code Snippet habe ich nach bestem Wissen und Gewissen unter WordPress 5.6 und Oxygen 3.6.1 sowie Oxygen Gutenberg Integration 1.4 entwickelt und getestet.
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.

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.

Change Log

Siehe "Version History" in Source Code

Source Code

<?php 
/*
Plugin Name:  MA Oxygen Template Usage
Description:  Adds a new column "Template Usage" in Oxygen Templates and Block Library lists to show usage.
Author:       <a href="https://www.altmann.de/">Matthias Altmann</a>
Version:      1.0.4
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-2021, Matthias Altmann

Version History:
Date		Version		Description
---------------------------------------------------------------------------------------------------------------------
2020-09-12	1.0.0		Initial Release 
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
2021-01-10	1.0.2		Bug Fix: 
						- Correct detection of assignment "All Post Types / Categories / Tags / Authors" 
						  (Thanks to Wolfgang Rotschek for reporting!)
2021-01-10	1.0.3		Enhancement:
						- Detect "All [Custom Taxonomies]" with proper naming
2021-01-22	1.0.4		Fix:
						- Corrected typo 
						  (Thanks to Adrien Robert for reporting!)
*/


//===================================================================================================================
// Utility functions
//===================================================================================================================
//-------------------------------------------------------------------------------------------------------------------
// Translates post type slugs (page, post, ...) to localized names (Seiten, Beiträge, ...)
function _maltmann_oxyuse_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);if ($post_type_object) {$retval[] = $post_type_object->label;}
			}
		}
	}
	return $retval;
}
//-------------------------------------------------------------------------------------------------------------------
// Retrieves term names from ID list or Oxygen names,values array 
function _maltmann_oxyuse_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 
function _maltmann_oxyuse_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
function _maltmann_oxyuse_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;
}


//===================================================================================================================
// Oxygen Templates / Re-usable Parts
//===================================================================================================================
add_action( 'after_setup_theme', function() {
	// add column title
	add_filter('manage_ct_template_posts_columns', function($columns){;
		$columns['maltmann_oxy_tpl_apply']  = 'Template Usage';
		return $columns;
	});
	// add column content
	add_action( 'manage_ct_template_posts_custom_column', function($column_name, $post_id) {
		if ($column_name != 'maltmann_oxy_tpl_apply') return;

		global $post;
		// get_post_meta does not fire a db query since post meta is still cached from listing
		$meta = get_post_meta($post->ID);

		if (isset($meta['ct_template_type']) && $meta['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="ct_builder_shortcodes" AND meta_value LIKE "%%ct_options=\'{\"view_id\":%d,%%"', $wpdb->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['ct_template_single_all'][0] == 'true') 		{$post_types[] = '<i>All</i>';}
			$specific_post_types = maybe_unserialize(@$meta['ct_template_post_types'][0]);
			if (is_array($specific_post_types) && count($specific_post_types)) {
				$post_types = array_merge($post_types,_maltmann_oxyuse_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['ct_use_template_taxonomies'][0]=='true') {
				$taxonomies = maybe_unserialize(@$meta['ct_template_taxonomies'][0]);
				$taxonomies =  _maltmann_oxyuse_parse_oxy_taxonomies($taxonomies);
				if (is_array($taxonomies) && count($taxonomies)) {
					$apply[] = 'Taxonomies: ' . join(', ',$taxonomies);
				}
			}
			// Singular Parents
			if (@$meta['ct_template_apply_if_post_of_parents'][0]=='true') {
				$parents = maybe_unserialize(@$meta['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['ct_template_all_archives'][0]=='true') 		{$apply[] = '<i>All</i>';}

			// Archive Taxonomies
			if (@$meta['ct_template_apply_if_archive_among_taxonomies'][0]=='true') {
				$taxonomies = maybe_unserialize(@$meta['ct_template_archive_among_taxonomies'][0]);
				$taxonomies =  _maltmann_oxyuse_parse_oxy_taxonomies($taxonomies);
				if (is_array($taxonomies) && count($taxonomies)) {
					$apply[] = 'Taxonomies: ' . join(', ',$taxonomies);
				}
			}
			// Archive Post Types
			if (@$meta['ct_template_apply_if_archive_among_cpt'][0]=='true') {
				$post_types = maybe_unserialize(@$meta['ct_template_archive_post_types'][0]);
				$post_types = _maltmann_oxyuse_parse_oxy_post_types($post_types);
				if (is_array($post_types) && count($post_types)) {
					$apply[] = 'Post Types: ' . join(', ',$post_types);
				}
			}
			// Archive Authors
			if (@$meta['ct_template_apply_if_archive_among_authors'][0]=='true') {
				$authors = maybe_unserialize(@$meta['ct_template_authors_archives'][0]);
				$authors = _maltmann_oxyuse_parse_oxy_authors($authors);
				if (is_array($authors) && count($authors)) {
					$apply[] = 'Authors: ' . join(', ',$authors);
				}
			}
			// Archive Date
			if (@$meta['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['ct_template_front_page'][0] == 'true') 		{$apply[] = 'Front Page';}
			if (@$meta['ct_template_blog_posts'][0] == 'true') 		{$apply[] = 'Blog Posts Index';}
			if (@$meta['ct_template_search_page'][0] == 'true') 	{$apply[] = 'Search Page';}
			if (@$meta['ct_template_404_page'][0] == 'true') 		{$apply[] = '404';}
			if (@$meta['ct_template_inner_content'][0] == 'true') 	{$apply[] = 'Inner Content';}
			if (@$meta['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 );
});

//===================================================================================================================
// Oxygen Gutenberg Blocks
//===================================================================================================================
add_action( 'after_setup_theme', function() {
	// add column title
	add_filter('manage_oxy_user_library_posts_columns', function($columns){
		$columns['maltmann_oxygen_gutenberg_blocks_reference']  = 'Template Usage';
		return $columns;
	});
	// add column content
	add_action( 'manage_oxy_user_library_posts_custom_column', function($column_name, $post_id){
		if ($column_name != 'maltmann_oxygen_gutenberg_blocks_reference') return;
		global $post;
		global $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 );
});

magnifier