Skip to content

Instantly share code, notes, and snippets.

@snarfed
Created June 12, 2022 15:56
Show Gist options
  • Save snarfed/e068890d95b0c1057fa93fd2edb9f2b2 to your computer and use it in GitHub Desktop.
Save snarfed/e068890d95b0c1057fa93fd2edb9f2b2 to your computer and use it in GitHub Desktop.
snarfed.org custom theme functions.php, based on Ryu
<?php
/*
* Customizations for snarfed.org on top of the Ryu WordPress theme.
* Not (yet) a full child theme.
* Public domain.
*
* To log: dlog("xyz")
* Defined below. Wraps error_log(). Writes to wp-content/debug.log
*
* Requires WP_DEBUG and WP_DEBUG_LOG to be true in wp-config.php. Details:
* http://www.stumiller.me/sending-output-to-the-wordpress-debug-log/
* http://codex.wordpress.org/Debugging_in_WordPress
*
* to fix semantic-linkbacks breakage until WP 4.2, do this:
* update wp_comments set comment_type=NULL where comment_id=2586829;
*/
/* uncomment to turn on WP Super Cache debug log file in
* wp-content/cache/supercache. */
/* global $wp_super_cache_debug; */
/* $wp_super_cache_debug = true; */
/* Max media upload size. */
@ini_set('upload_max_size', '128M');
@ini_set('post_max_size', '128M');
function dlog($msg) {
if ( is_array( $msg ) || is_object( $msg ) ) {
error_log( print_r( $msg, true ) );
} else {
error_log( $msg );
}
}
/* Require WordPress.com login, which includes 2FA. */
add_filter( 'jetpack_remove_login_form', '__return_true' );
/* Change email address that WordPress emails me *from*. It defaults to
* wordpress@snarfed.org, but when Google sees emails from a domain without
* DKIM, SPF, etc set up, it eventually distrusts that domain and starts showing
* "Suspicious link - This link leads to an untrusted site" whenever anyone
* clicks on any link to that domain, which is obviously bad.
*
* https://gsuiteupdates.googleblog.com/2017/05/making-email-safer-with-Gmail-click-time-security-checks.html
* https://productforums.google.com/forum/#!topic/gmail/qg7rTa5B7ZA
* https://productforums.google.com/forum/#!topic/gmail/dK0da2oRnrE
*/
function snarfed_sender_email( $original_email_address ) {
return 'wordpress@ryanbarrett.org';
}
add_filter( 'wp_mail_from', 'snarfed_sender_email' );
/* The Syndication Links plugin's stylesheet includes genericons etc, which I
* already have, and I style the links myself, so ditch its style.
*/
remove_action('wp_enqueue_scripts', array('Syn_Config', 'enqueue_scripts'));
/* Disable XML-RPC. */
add_filter( 'xmlrpc_enabled', '__return_false' );
remove_action( 'wp_head', 'rsd_link' );
/* Jetpack Markdown: Enable by default for posts and pages.
* https://jetpack.com/support/markdown/#using-the-markdown-block
* https://jetpack.com/support/markdown/#cpt
*/
function snarfed_markdown_everywhere() {
add_post_type_support( 'post', 'wpcom-markdown' );
add_post_type_support( 'page', 'wpcom-markdown' );
}
add_action('init', 'snarfed_markdown_everywhere');
/* Jetpack Markdown: Don't make newlines meaningful. */
function wpautop_no_linebreaks( $content ) {
$content = wpautop( $content, false );
// maybe try to deal with trailing spaced newlines?
return $content;
}
remove_filter( 'the_content', 'wpautop' );
add_filter( 'the_content', 'wpautop_no_linebreaks' );
/* Filter for normal comments. Just remove the dash before "via ..."
*/
function snarfed_cite($text) {
return str_replace("<p><small>&mdash;&nbsp;<cite>", "<cite>",
str_replace("</cite></small></p>", "</cite>", $text));
}
add_filter('semantic_linkbacks_cite', 'snarfed_cite');
/* Allow categories and tags on pages as well as posts.
*/
function snarfed_tags_categories_on_pages() {
register_taxonomy_for_object_type( 'category', 'page' );
register_taxonomy_for_object_type( 'post_tag', 'page' );
}
add_action( 'init', 'snarfed_tags_categories_on_pages' );
/* Clear a post/page's cache when it receives a webmention.
*/
function snarfed_webmention_clear_cache($comment_ID) {
clean_post_cache(get_comment($comment_ID)->comment_post_ID);
// wp_cache_post_change stores the last seen post ID in a static local var,
// and short circuits if it's the same as last call. so set it to a different
// id first. (417 is /2003-06-29_blogtastic on both snarfed and localhost.)
$GLOBALS["super_cache_enabled"] = 1;
wp_cache_post_change(417);
wp_cache_post_change(get_comment($comment_ID)->comment_post_ID);
}
add_action('webmention_post', 'snarfed_webmention_clear_cache');
/* Don't let webmentions get marked as spam.
*/
function unspam_webmentions($approved, $commentdata) {
return ($commentdata['comment_type'] == 'webmention' ||
get_comment_meta($commentdata['comment_ID'], 'semantic_linkbacks_type', true)
) ? 1 : $approved;
}
add_filter('pre_comment_approved', 'unspam_webmentions', '99', 2);
/*
* Don't show the "Send me a WebMention" form below the comment form.
*/
// function snarfed_nothing($template_file) {
// return NULL;
// }
// add_filter('webmention_comment_form', 'snarfed_nothing');
/* Automatically mark comments that end in a 32-digit hex string as spam.
*
* https://snarfed.org/wordpress-mini-spam-filter-for-comments-ending-in-32-hex-characters
*/
function spam_32_hex_chars($approved, $commentdata) {
$text = trim(wp_strip_all_tags($commentdata['comment_content'], true));
return preg_match('|[0-9a-f]{32}$|', $text) ? 'spam' : $approved;
}
add_filter('pre_comment_approved', 'spam_32_hex_chars', '99', 2);
/* Capture the output from a PHP file in a string. Taken verbatim from the PHP
* docs for include(). Used in header.php.
*
* If needed, we can use this to capture and process *all* output:
* http://www.dagondesign.com/articles/wordpress-hook-for-entire-page-using-output-buffering/
*/
function get_include_contents($filename) {
ob_start();
include $filename;
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
/* Make Jetpack's Publicize opt in per post, instead of automatic and opt out.
*/
add_filter('publicize_checkbox_default', '__return_false');
/* Make Jetpack's Photon image CDN (used in its Tiled Galleries feature) handle
* connecting to us over SSL. Details:
* https://wordpress.org/support/topic/tiled-gallery-fetching-full-size-images-resizing-in-browser?replies=3#post-7214361
*
* Theoretically no longer needed; Photon now supports HTTPS by default:
* http://jetpack.me/2016/01/20/39-sitemaps-skype-sharing/
*
* ...but it broke on https://snarfed.org/2016-02-25_17194 when i tried removing it.
*/
add_filter( 'jetpack_photon_reject_https', '__return_false' );
/* Don't render featured images. I only use them for Twitter cards and Open
* Graph (Facebook) tags.
*/
function snarfed_hide_featured_image ($html) {
return ''; //preg_replace('/(width|height)="\d+"\s/', "", $html);
}
add_filter( 'post_thumbnail_html', 'snarfed_hide_featured_image' );
function snarfed_social_image_default ($url) {
if ( is_singular() ) {
global $post;
$matches = [];
if ( preg_match( "/< *img *[^>]+src *= *[\"']([^\"']+)/",
$post->post_content, $matches ) ) {
$url = $matches[1];
if ( substr( $url, 0, 4 ) == 'http' ) {
return $url;
} else if ( substr( $url, 0, 2 ) == '//' ) {
return 'https:' . $url;
} else {
return get_home_url( NULL, $url );
}
}
}
// default
return get_home_url( NULL, '/iraq_square.jpg' );
}
add_filter( 'jetpack_open_graph_image_default', 'snarfed_social_image_default' );
add_filter( 'jetpack_twitter_cards_image_default', 'snarfed_social_image_default' );
/* Don't put u-photo on Jetpack lazy loaded image placeholders.
* https://jetpack.com/support/lazy-images/
* https://developer.jetpack.com/hooks/jetpack_lazy_images_new_attributes/
*/
function snarfed_no_uphoto_lazy_images($attrs) {
$classes = explode(' ', $attrs['class']);
$attrs['class'] = implode(' ', array_filter($classes, function($cls) {
return $cls != 'photo' && $cls != 'u-photo';
}));
// dlog($attrs);
return $attrs;
}
add_filter( 'jetpack_lazy_images_new_attributes', 'snarfed_no_uphoto_lazy_images' );
/* WordPress 4.5 dropped the JPG quality of thumbnails to 82%, which makes them
* look blurry. Bump that back up.
* https://make.wordpress.org/core/2016/02/22/proposal-increase-the-default-image-compression-in-wordpress/
*/
function snarfed_better_quality_thumbnails($arg) {
return 90;
}
add_filter('jpeg_quality', 'snarfed_better_quality_thumbnails');
/* Redirect image attachment pages to parent post.
* https://www.wpexplorer.com/disable-image-page/
*/
function snarfed_redirect_attachment_page() {
if ( is_attachment() ) {
global $post;
if ( $post && $post->post_parent ) {
wp_redirect( esc_url( get_permalink( $post->post_parent ) ), 301 );
exit;
} else {
wp_redirect( esc_url( home_url( '/' ) ), 301 );
exit;
}
}
}
add_action( 'template_redirect', 'snarfed_redirect_attachment_page' );
/* Override and disable previous and next post links entirely. */
function ryu_content_nav($nav_id) {
}
/**
* Override entry meta to add last modified time and microformats2 classes.
*
* Ryu doesn't have any filters or hooks for customizing this, so I had to copy
* and modify ryu_[get_]entry_meta() from ryu/inc/template-tags.php. :/
*/
function ryu_entry_meta() {
echo ryu_get_entry_meta();
}
function ryu_get_entry_meta() {
$val = sprintf(__(
'<span class="entry-date">' .
'<a class="u-url" href="%1$s" title="%2$s" rel="bookmark">' .
'<time class="dt-published" datetime="%3$s">%4$s</time></a>' .
'%5$s</span>', 'ryu'),
esc_url(get_permalink()),
esc_attr(get_the_time()),
/* 'c' is the ISO 8601 format specifier, but it ignores WordPress's
* time zone and blindly uses GMT. DATE_W3C gets the time zone right.
* http://freetheweb.tumblr.com/post/11431306520/wordpress-obtaining-timezone-accurate-iso-8601-strings
*/
esc_attr(get_the_date(DATE_W3C)),
esc_html(get_the_date()),
function_exists('get_syndication_links') ? get_syndication_links( null ) : '');
if ('page' == get_post_type() && get_the_date() != get_the_modified_date()) {
$val = $val . sprintf(__(
'<span class="entry-modified-date">updated ' .
'<a class="u-url" href="%1$s" title="%2$s" rel="bookmark">' .
'<time class="dt-updated" datetime="%3$s">%4$s' .
'</time></a></span>', 'ryu'),
esc_url(get_permalink()),
esc_attr(get_the_modified_time()),
esc_attr(get_the_modified_date(DATE_W3C)),
esc_html(get_the_modified_date()));
}
$val = $val . sprintf(__(
'<span class="author p-author h-card vcard"> %1$s' .
'<a class="u-url url fn n p-name" href="%2$s" title="%3$s" rel="author">' .
'%4$s</a></span>', 'ryu'),
get_avatar(get_the_author_meta("ID"), 96, '', '', array( 'class' => 'u-photo' )),
esc_url(get_the_author_meta('user_url')),
esc_attr(get_the_author()),
get_the_author());
return $val;
}
/**
* Suppress title (p-name) in replies etc so post type discovery thinks they're notes.
*/
function snarfed_no_title_in_notes($title) {
if (is_singular() && !is_admin() &&
(has_category('reply') ||
has_category('like') ||
has_category('repost') ||
has_category('rsvp'))) {
return NULL;
}
return $title;
}
add_filter('the_title', 'snarfed_no_title_in_notes');
/**
* Override comment to tweak author and date.
*
* ...just like entry meta, above. Ryu doesn't have any filters or hooks for
* customizing this, so I had to copy and modify ryu_comment() from
* ryu/inc/template-tags.php. :/
*/
function ryu_comment( $comment, $args, $depth ) {
$GLOBALS['comment'] = $comment;
switch ( $comment->comment_type ) :
case 'pingback' :
case 'trackback' :
?>
<li class="post pingback">
<p><?php _e( 'Pingback:', 'ryu' ); ?> <?php comment_author_link(); ?></p>
<?php
break;
default :
?>
<li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
<article id="comment-<?php comment_ID(); ?>" class="comment">
<div class="comment-meta commentmetadata comment-author">
<span class="comment-author-avatar"><?php echo get_avatar( $comment, 48 ); ?></span>
<div class="vcard h-card p-author">
<?php printf( '<cite class="fn theme-genericon">%s</cite>', get_comment_author_link() ); ?>
</div><!-- .comment-author .vcard -->
<div class="comment-date">
<a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>"
title="<?php echo get_comment_time(); ?>">
<time class="dt-published" datetime="<?php comment_time( 'c' ); ?>">
<?php echo get_comment_date(); ?>
</time>
</a>
</div><!-- .comment-date -->
</div><!-- .comment-meta .commentmetadata -->
<div class="comment-content">
<?php comment_text(); ?>
</div>
</article><!-- #comment-## -->
<?php
break;
endswitch;
}
/**
* Remove some parts of wordpress-uf2 that I do myself above.
*/
remove_filter( 'the_author', 'uf2_the_author', 99, 1 );
/**
* Load enqueued scripts in the footer to speed up page load.
* Stolen from http://www.kevinleary.net/move-javascript-bottom-wordpress/
*
* Disabled because this includes stylesheets, and if they're in the footer, the
* page initially loads with blank style (ie ugly) before the stylesheets load
* and kick in.
*/
/*
function snarfed_footer_enqueue_scripts() {
remove_action('wp_head', 'wp_print_scripts');
remove_action('wp_head', 'wp_print_head_scripts', 9);
remove_action('wp_head', 'wp_enqueue_scripts', 1);
add_action('wp_footer', 'wp_print_scripts', 5);
add_action('wp_footer', 'wp_enqueue_scripts', 1);
add_action('wp_footer', 'wp_print_head_scripts', 9);
}
add_action('after_setup_theme', 'snarfed_footer_enqueue_scripts');
*/
/** Include my JavaScript files.
*/
function snarfed_scripts() {
wp_enqueue_script('snarfed-fragmention',
get_stylesheet_directory_uri() . '/fragmention.js',
false, '1.0', true);
}
add_action('wp_enqueue_scripts', 'snarfed_scripts');
/** IndieWeb Press This tweaks.
*/
function snarfed_press_this_tweak() {
?>
<script type='text/javascript'>
function press_this_tweak() {
/* map type to wordpress category id */
var categories = {
'like': '27',
'reply': '23',
'repost': '28',
'rsvp': '29',
// I currently show checkins on the front page.
// 'checkin': 23
};
/* get 'type' query param. default to 'reply'. */
var type = 'reply';
var params = window.location.search.substr(1).split('&');
for (var i = 0; i < params.length; i++) {
var parts = params[i].split('=');
if (parts[0] == 'type') {
type = parts[1];
break;
}
}
var cats = document.getElementsByClassName('category');
for (i = 0; i < cats.length; i++) {
if (cats[i].attributes['data-term-id'].value == categories[type]) {
cats[i].classList.add('selected');
} else {
cats[i].classList.remove('selected');
}
}
var content = document.getElementById('pressthis');
content.onchange = content.oninput = content.onfocus = function(event) {
// Tag Gina in checkins by default.
if (type == 'checkin') {
content.value = content.value.replace(
'with <a class="h-card" href=""></a>',
'with <a class="h-card" href="https://www.facebook.com/gina.rossman.50">Gina Barrett</a>.');
}
// Use Bridgy Fed for Mastodon etc domains.
for (const pattern of [
'//counter.social/',
'//friends.nico/',
'//lgbt.io/',
'//mastodon.',
'//mstdn.',
'//octodon.',
'//pawoo.net/',
'//toot.cafe/',
]) {
console.log('examining ' + pattern);
if (content.value.indexOf(pattern) >= 0 &&
content.value.indexOf('fed.brid.gy') == -1) {
var text = (type == 'like' || type == 'repost') ? 'via Bridgy Fed' : '';
content.value += ' <cite class="via">[' + text + '](https://fed.brid.gy/)</cite>';
break;
}
}
};
content.onchange();
// press-this.js's window.onload runs after onchange() above, and overwrites
// our changes, and i can't find any other event handler that will trigger
// after that automatically, so hack it with a timer. :/
window.setTimeout(content.onchange, 1000);
}
window.addEventListener('load', press_this_tweak, false);
</script>
<?php
}
add_action('admin_print_scripts-press-this.php', 'snarfed_press_this_tweak', 11);
/* Allow comments on pages by default. WordPress 4.3 switched the default off:
* https://make.wordpress.org/core/2015/07/06/comments-are-now-turned-off-on-pages-by-default/
*/
function snarfed_comments_on_pages($status, $post_type, $comment_type) {
return 'open';
}
add_filter('get_default_comment_status', 'snarfed_comments_on_pages', 10, 3);
/** Reply contexts via LinkPreview.
*/
function snarfed_embed_reply_context_script() {
if (has_category('reply')) {
$content = 'replying to:';
} else if (has_category('repost')) {
$content = '';
} else {
return;
}
?>
<script type='text/javascript'>
function embed_reply_contexts() {
var classes = ['u-in-reply-to', 'u-repost-of', 'u-quotation-of'];
for (i in classes) {
var origs = document.getElementsByClassName(classes[i]);
for (j = 0; j < origs.length; j++) {
if (origs[j].href.indexOf("twitter.com/") >= 0 ||
origs[j].href.indexOf("facebook.com/") >= 0 ||
origs[j].href.indexOf("plus.google.com/") >= 0 ||
origs[j].href.indexOf("instagram.com/") >= 0) {
continue;
}
origs[j].insertAdjacentHTML('afterend', `
<div class="box" style="margin-top: 1em">
<a id="lp-url" href="">
<img id="lp-image" style="float: right" src="">
<div class="is-clipped">
<h3 id="lp-title"></h3>
<p><em id="lp-description"></em></p>
</div>
</a>
</div>`);
fetch('https://api.linkpreview.net', {
method: 'POST',
mode: 'cors',
body: JSON.stringify({
key: '38cfb05179d598106ac12fe584811681',
q: origs[j].href,
}),
})
.then(res => res.json())
.then(response => {
document.getElementById('lp-title').innerHTML = response.title
document.getElementById('lp-description').innerHTML = response.description
document.getElementById('lp-image').src = response.image
document.getElementById('lp-url').href = response.url
});
}
}
}
window.addEventListener('load', embed_reply_contexts, false);
</script>
<?php
}
add_action('wp_footer', 'snarfed_embed_reply_context_script');
/* Used once on snarfed.org, 2017-11-20, to upgrade MySQL tables' charset and
* collation from utf8 to utf8mb4 to fix showing emoji beyond BMP in comments.
* From https://gist.github.com/FlorianBrinkmann/c3f57dd7c26328d7b4de04e696091eee
* Background in https://make.wordpress.org/core/2015/04/02/the-utf8mb4-upgrade/
* and etc/wordpress_emoji_mysql_utf8mb4.
*/
// function update_db_to_utf8mb4() {
// if (!isset($_GET['update-utf8bm4'])) {
// return;
// }
// require_once( ABSPATH . 'wp-admin/includes/upgrade.php');
// /** WordPress Administration API */
// require_once(ABSPATH . 'wp-admin/includes/admin.php');
// /** WordPress Schema API */
// require_once(ABSPATH . 'wp-admin/includes/schema.php');
// $tables = $wpdb->tables('all');
// if (!wp_should_upgrade_global_tables()) {
// $global_tables = $wpdb->tables('global');
// $tables = array_diff_assoc($tables, $global_tables);
// }
// foreach ($tables as $table) {
// maybe_convert_table_to_utf8mb4($table);
// }
// }
// add_action('wp_loaded', 'update_db_to_utf8mb4');
/* Return 404s appropriately. Don't redirect to a similar existing URL.
*/
add_filter('redirect_canonical', 'snarfed_no_redirect_on_404');
function snarfed_no_redirect_on_404($redirect_url)
{
if (is_404()) {
return false;
}
return $redirect_url;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment