Hi,
to structure our posts better and have a clearer division between the content, we’ve added a sources meta box that automatically appends them at the end of the post, linking to them via a target=”_blank” solution.
NOTE: If you use custom post types, use the following code. If not, scroll down to “Snippet”.
function add_sources_meta_box() {
$post_types = ['post', 'glossary']; // Add your custom post types here
foreach ($post_types as $post_type) {
add_meta_box(
'post_sources',
'Sources',
'render_sources_meta_box',
$post_type,
'normal',
'high'
);
}
}
add_action('add_meta_boxes', 'add_sources_meta_box');
// Render the meta box content
function render_sources_meta_box($post) {
wp_nonce_field('sources_meta_box', 'sources_meta_box_nonce');
$sources = get_post_meta($post->ID, '_post_sources', true);
if (!is_array($sources)) {
$sources = array();
}
?>
<div id="sources-container">
<?php
if (!empty($sources)) {
foreach ($sources as $index => $source) {
?>
<div class="source-row">
<input type="text" name="sources[<?php echo $index; ?>][name]"
value="<?php echo esc_attr($source['name']); ?>"
placeholder="Source Name" style="width: 40%;">
<input type="url" name="sources[<?php echo $index; ?>][url]"
value="<?php echo esc_url($source['url']); ?>"
placeholder="Source URL" style="width: 40%;">
<button type="button" class="remove-source button">-</button>
</div>
<?php
}
}
?>
</div>
<button type="button" id="add-source" class="button">+ Add Source</button>
<style>
.source-row { margin-bottom: 10px; }
.source-row input { margin-right: 10px; }
#add-source { margin-top: 10px; }
</style>
<script>
jQuery(document).ready(function($) {
var container = $('#sources-container');
var count = $('.source-row').length;
$('#add-source').on('click', function() {
var row = $('<div class="source-row">' +
'<input type="text" name="sources[' + count + '][name]" placeholder="Source Name" style="width: 40%;">' +
'<input type="url" name="sources[' + count + '][url]" placeholder="Source URL" style="width: 40%;">' +
'<button type="button" class="remove-source button">-</button>' +
'</div>');
container.append(row);
count++;
});
$(document).on('click', '.remove-source', function() {
$(this).parent().remove();
});
});
</script>
<?php
}
// Save the meta box data
function save_sources_meta_box($post_id) {
if (!isset($_POST['sources_meta_box_nonce']) ||
!wp_verify_nonce($_POST['sources_meta_box_nonce'], 'sources_meta_box')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (isset($_POST['sources'])) {
$sources = array_values(array_filter($_POST['sources'], function($source) {
return !empty($source['name']) || !empty($source['url']);
}));
update_post_meta($post_id, '_post_sources', $sources);
} else {
delete_post_meta($post_id, '_post_sources');
}
}
add_action('save_post', 'save_sources_meta_box');
// Display sources at the end of post content
function display_post_sources($content) {
$supported_post_types = ['post', 'glossary']; // Add your custom post types here
if (!is_singular($supported_post_types)) {
return $content;
}
$post_id = get_the_ID();
$sources = get_post_meta($post_id, '_post_sources', true);
// Force array type
$sources = (array) $sources;
// Filter out empty sources
$valid_sources = array_filter($sources, function($source) {
return !empty($source['name']) || !empty($source['url']);
});
// Only display sources if there are valid sources
if (empty($valid_sources)) {
return $content;
}
$sources_html = '<div class="post-sources">';
$sources_html .= '<h3>Quellen</h3>'; // German translation for Sources
$sources_html .= '<ul>';
foreach ($valid_sources as $source) {
$sources_html .= '<li>';
if (!empty($source['url'])) {
$sources_html .= sprintf(
'<a href="%s" target="_blank" rel="nofollow noopener">%s</a>',
esc_url($source['url']),
esc_html($source['name'] ?? $source['url'])
);
} else {
$sources_html .= esc_html($source['name']);
}
$sources_html .= '</li>';
}
$sources_html .= '</ul></div>';
return $content . $sources_html;
}
add_filter('the_content', 'display_post_sources', 999);
Snippet
Use the following Snippet in your functions.php:
function add_sources_meta_box() {
add_meta_box(
'post_sources',
'Sources',
'render_sources_meta_box',
'post',
'normal',
'high'
);
}
add_action('add_meta_boxes', 'add_sources_meta_box');
// Render the meta box content
function render_sources_meta_box($post) {
wp_nonce_field('sources_meta_box', 'sources_meta_box_nonce');
$sources = get_post_meta($post->ID, '_post_sources', true);
if (!is_array($sources)) {
$sources = array();
}
?>
<div id="sources-container">
<?php
if (!empty($sources)) {
foreach ($sources as $index => $source) {
?>
<div class="source-row">
<input type="text" name="sources[<?php echo $index; ?>][name]"
value="<?php echo esc_attr($source['name']); ?>"
placeholder="Source Name" style="width: 40%;">
<input type="url" name="sources[<?php echo $index; ?>][url]"
value="<?php echo esc_url($source['url']); ?>"
placeholder="Source URL" style="width: 40%;">
<button type="button" class="remove-source button">-</button>
</div>
<?php
}
}
?>
</div>
<button type="button" id="add-source" class="button">+ Add Source</button>
<style>
.source-row { margin-bottom: 10px; }
.source-row input { margin-right: 10px; }
#add-source { margin-top: 10px; }
</style>
<script>
jQuery(document).ready(function($) {
var container = $('#sources-container');
var count = $('.source-row').length;
$('#add-source').on('click', function() {
var row = $('<div class="source-row">' +
'<input type="text" name="sources[' + count + '][name]" placeholder="Source Name" style="width: 40%;">' +
'<input type="url" name="sources[' + count + '][url]" placeholder="Source URL" style="width: 40%;">' +
'<button type="button" class="remove-source button">-</button>' +
'</div>');
container.append(row);
count++;
});
$(document).on('click', '.remove-source', function() {
$(this).parent().remove();
});
});
</script>
<?php
}
// Save the meta box data
function save_sources_meta_box($post_id) {
if (!isset($_POST['sources_meta_box_nonce']) ||
!wp_verify_nonce($_POST['sources_meta_box_nonce'], 'sources_meta_box')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (isset($_POST['sources'])) {
$sources = array_values(array_filter($_POST['sources'], function($source) {
return !empty($source['name']) || !empty($source['url']);
}));
update_post_meta($post_id, '_post_sources', $sources);
} else {
delete_post_meta($post_id, '_post_sources');
}
}
add_action('save_post', 'save_sources_meta_box');
// Display sources at the end of post content
function display_post_sources($content) {
if (!is_singular('post')) {
return $content;
}
$post_id = get_the_ID();
$sources = get_post_meta($post_id, '_post_sources', true);
// Force array type
$sources = (array) $sources;
// Filter out empty sources
$valid_sources = array_filter($sources, function($source) {
return !empty($source['name']) || !empty($source['url']);
});
// Only display sources if there are valid sources
if (empty($valid_sources)) {
return $content;
}
$sources_html = '<div class="post-sources">';
$sources_html .= '<h3>Quellen</h3>'; // German translation for Sources
$sources_html .= '<ul>';
foreach ($valid_sources as $source) {
$sources_html .= '<li>';
if (!empty($source['url'])) {
$sources_html .= sprintf(
'<a href="%s" target="_blank" rel="nofollow noopener">%s</a>',
esc_url($source['url']),
esc_html($source['name'] ?? $source['url'])
);
} else {
$sources_html .= esc_html($source['name']);
}
$sources_html .= '</li>';
}
$sources_html .= '</ul></div>';
return $content . $sources_html;
}
add_filter('the_content', 'display_post_sources', 999);
CSS
Additionally, add the following CSS to your Theme:
.post-sources {
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid #ddd;
}
.post-sources h3 {
margin-top: 1.5em; /* Added margin for the heading */
margin-bottom: 15px;
}
.post-sources ul {
list-style: none;
padding-left: 0;
}
.post-sources li {
margin-bottom: 10px;
}
.post-sources a {
color: #0073aa;
text-decoration: none;
}
.post-sources a:hover {
text-decoration: underline;
}
Leave a Reply