label. */
function clanfront_page_templates() {
return array(
'clanfront-home' => 'Clanfront: Homepage',
'clanfront-about' => 'Clanfront: About',
'clanfront-join' => 'Clanfront: Join us',
'clanfront-rules' => 'Clanfront: Rules',
'clanfront-servers' => 'Clanfront: Game servers',
'clanfront-page' => 'Clanfront: Page',
);
}
add_filter(
'theme_page_templates',
function ( $templates ) {
return array_merge( $templates, clanfront_page_templates() );
}
);
/** Which Clanfront view is showing, or '' for normal theme pages. */
function clanfront_view() {
if ( is_singular( 'clanfront_member' ) ) {
return 'single-member';
}
if ( is_singular( 'clanfront_match' ) ) {
return 'single-match';
}
if ( is_post_type_archive( 'clanfront_member' ) ) {
return 'archive-member';
}
if ( is_post_type_archive( 'clanfront_match' ) ) {
return 'archive-match';
}
if ( is_post_type_archive( 'clanfront_media' ) ) {
return 'archive-media';
}
if ( is_singular( 'clanfront_news' ) ) {
return 'single-news';
}
if ( is_post_type_archive( 'clanfront_news' ) ) {
return 'archive-news';
}
if ( is_singular( 'clanfront_game' ) ) {
return 'single-game';
}
if ( is_post_type_archive( 'clanfront_game' ) ) {
return 'archive-game';
}
if ( is_post_type_archive( 'clanfront_shame' ) ) {
return 'archive-shame';
}
if ( is_post_type_archive( 'clanfront_milestone' ) ) {
return 'archive-history';
}
$section = function_exists( 'clanfront_competition_request' ) ? clanfront_competition_request() : '';
if ( $section && ( clanfront_feature_on( $section ) || current_user_can( 'edit_posts' ) ) ) {
if ( is_singular( 'clanfront_tourney' ) ) {
return 'single-tournament';
}
return is_post_type_archive( 'clanfront_tourney' ) ? 'archive-tournament' : '';
}
if ( is_page() ) {
$slug = (string) get_page_template_slug( get_queried_object_id() );
if ( 0 === strpos( $slug, 'clanfront-' ) && array_key_exists( $slug, clanfront_page_templates() ) ) {
return substr( $slug, strlen( 'clanfront-' ) );
}
}
return '';
}
// A gallery item has no page of its own: send visitors to the gallery.
add_action(
'template_redirect',
function () {
if ( is_singular( 'clanfront_media' ) ) {
wp_safe_redirect( get_post_type_archive_link( 'clanfront_media' ) );
exit;
}
}
);
add_filter(
'template_include',
function ( $template ) {
$view = clanfront_view();
if ( $view ) {
$file = CLANFRONT_DIR . 'templates/' . $view . '.php';
if ( file_exists( $file ) ) {
return $file;
}
}
return $template;
},
99
);
add_action(
'wp_enqueue_scripts',
function () {
if ( ! clanfront_view() ) {
return;
}
wp_enqueue_style( 'clanfront-site', CLANFRONT_URL . 'assets/style.css', array(), CLANFRONT_VERSION );
wp_enqueue_script( 'clanfront-site', CLANFRONT_URL . 'assets/site.js', array(), CLANFRONT_VERSION, true );
}
);
// On Clanfront views, unload the theme's own styles so they can't fight the design.
add_action(
'wp_print_styles',
function () {
if ( ! clanfront_view() ) {
return;
}
$wp_styles = wp_styles();
$theme_dirs = array_unique( array( get_template_directory_uri(), get_stylesheet_directory_uri() ) );
foreach ( (array) $wp_styles->queue as $handle ) {
$src = isset( $wp_styles->registered[ $handle ] ) ? (string) $wp_styles->registered[ $handle ]->src : '';
foreach ( $theme_dirs as $dir ) {
if ( $src && 0 === strpos( $src, $dir ) ) {
wp_dequeue_style( $handle );
}
}
}
// GeneratePress prints its customiser colours inline under these handles (harmless with other themes).
wp_dequeue_style( 'generate-style' );
wp_dequeue_style( 'generate-main' );
},
100
);
add_filter(
'body_class',
function ( $classes ) {
if ( clanfront_view() ) {
$classes[] = 'clanfront-site';
}
return $classes;
}
);
/** Default
when the active theme does not manage it. */
function clanfront_document_title() {
if ( current_theme_supports( 'title-tag' ) ) {
return;
}
echo '' . esc_html( wp_get_document_title() ) . '' . "\n";
}
/* ---------- Calendar feed (.ics) ---------- */
function clanfront_ics_escape( $text ) {
$text = str_replace( array( '\\', ';', ',' ), array( '\\\\', '\;', '\\,' ), (string) $text );
return str_replace( array( "\r\n", "\r", "\n" ), '\\n', $text );
}
/** Fold a line to 75 bytes as the calendar format asks. */
function clanfront_ics_fold( $line ) {
$out = '';
while ( strlen( $line ) > 75 ) {
$cut = 75;
while ( $cut > 0 && ( ord( $line[ $cut ] ) & 0xC0 ) === 0x80 ) {
--$cut; // Do not split inside a multi-byte character.
}
$out .= substr( $line, 0, $cut ) . "\r\n ";
$line = substr( $line, $cut );
}
return $out . $line;
}
/** Calendar text for upcoming events, or for one event when $only is given. */
function clanfront_ics( $events ) {
$lines = array( 'BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Clanfront//EN', 'CALSCALE:GREGORIAN', 'METHOD:PUBLISH', 'X-WR-CALNAME:' . clanfront_ics_escape( clanfront_name() ) );
$host = (string) wp_parse_url( home_url(), PHP_URL_HOST );
$utc = new DateTimeZone( 'UTC' );
$stamp = gmdate( 'Ymd\THis\Z' );
foreach ( $events as $e ) {
$start = clanfront_event_start( $e );
if ( ! $start ) {
continue;
}
$game = (string) get_post_meta( $e->ID, 'clanfront_game', true );
$opp = (string) get_post_meta( $e->ID, 'clanfront_opponent', true );
$notes = (string) get_post_meta( $e->ID, 'clanfront_notes', true );
$summary = get_the_title( $e ) . ( $game ? ' (' . $game . ')' : '' );
$desc = trim( clanfront_event_kind_label( $e ) . ( $opp ? ' vs ' . $opp : '' ) . ( $notes ? "\n" . $notes : '' ) );
$lines[] = 'BEGIN:VEVENT';
$lines[] = 'UID:clanfront-' . (int) $e->ID . '@' . $host;
$lines[] = 'DTSTAMP:' . $stamp;
if ( clanfront_event_time( $e ) ) {
$s = clone $start;
$s->setTimezone( $utc );
$end = clone $s;
$end->modify( '+2 hours' );
$lines[] = 'DTSTART:' . $s->format( 'Ymd\THis\Z' );
$lines[] = 'DTEND:' . $end->format( 'Ymd\THis\Z' );
} else {
$next = clone $start;
$next->modify( '+1 day' );
$lines[] = 'DTSTART;VALUE=DATE:' . $start->format( 'Ymd' );
$lines[] = 'DTEND;VALUE=DATE:' . $next->format( 'Ymd' );
}
$lines[] = 'SUMMARY:' . clanfront_ics_escape( $summary );
$lines[] = 'DESCRIPTION:' . clanfront_ics_escape( $desc );
$lines[] = 'URL:' . esc_url_raw( get_permalink( $e ) );
$lines[] = 'END:VEVENT';
}
$lines[] = 'END:VCALENDAR';
return implode( "\r\n", array_map( 'clanfront_ics_fold', $lines ) ) . "\r\n";
}
/** The feed address people add to Google Calendar, Apple Calendar or Outlook. */
function clanfront_ics_url() {
return add_query_arg( 'clanfront_ics', '1', home_url( '/' ) );
}
add_action(
'template_redirect',
function () {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- a public, read-only feed.
if ( ! isset( $_GET['clanfront_ics'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$one = isset( $_GET['event'] ) ? absint( $_GET['event'] ) : 0;
$events = array();
if ( $one ) {
$p = get_post( $one );
if ( $p && 'clanfront_match' === $p->post_type && 'publish' === $p->post_status ) {
$events = array( $p );
}
} else {
$events = clanfront_get_events( array( 'when' => 'upcoming' ) );
}
nocache_headers();
header( 'Content-Type: text/calendar; charset=utf-8' );
header( 'Content-Disposition: inline; filename="' . ( $one ? 'event' : 'schedule' ) . '.ics"' );
echo clanfront_ics( $events ); // phpcs:ignore WordPress.Security.EscapeOutput -- calendar text, escaped by clanfront_ics_escape().
exit;
},
1
);
// Layout choice as a body class (centered column or full width).
add_filter(
'body_class',
function ( $classes ) {
if ( function_exists( 'clanfront_view' ) && clanfront_view() ) {
$classes[] = 'full' === clanfront_setting( 'layout' ) ? 'clanfront-layout-full' : 'clanfront-layout-centered';
}
return $classes;
}
);