'clanfront_applicant', 'post_status' => 'publish', 'posts_per_page' => 1, 'fields' => 'ids', 'meta_key' => 'clanfront_app_status', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- a small inbox. 'meta_value' => 'new', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- a small inbox. ) ); return (int) $q->found_posts; } add_action( 'admin_menu', function () { add_menu_page( 'Clanfront', 'Clanfront', 'edit_posts', CLANFRONT_MENU, '', 'dashicons-shield', 26 ); add_submenu_page( CLANFRONT_MENU, 'Clanfront settings', 'Settings', 'manage_options', 'clanfront-settings', 'clanfront_render_settings', 20 ); }, 9 ); // Menu order: Matches & events, News, Members, Medals, Games, Hall of Shame, History, Tournaments, Gallery, Game servers, Applications (with a count), Settings, Getting started. add_action( 'admin_menu', function () { global $submenu; if ( empty( $submenu[ CLANFRONT_MENU ] ) ) { return; } $wanted = array( CLANFRONT_MENU, 'edit.php?post_type=clanfront_news', 'edit.php?post_type=clanfront_member', 'edit.php?post_type=clanfront_award', 'edit.php?post_type=clanfront_game', 'edit.php?post_type=clanfront_shame', 'edit.php?post_type=clanfront_milestone', 'edit.php?post_type=clanfront_tourney', 'edit.php?post_type=clanfront_media', 'edit.php?post_type=clanfront_server', 'edit.php?post_type=clanfront_applicant', 'clanfront-settings', 'clanfront-guide', ); $by_slug = array(); foreach ( $submenu[ CLANFRONT_MENU ] as $item ) { $by_slug[ $item[2] ] = $item; } $items = array(); foreach ( $wanted as $slug ) { if ( isset( $by_slug[ $slug ] ) ) { $item = $by_slug[ $slug ]; if ( 'edit.php?post_type=clanfront_applicant' === $slug ) { $n = clanfront_new_application_count(); if ( $n ) { $item[0] .= ' ' . (int) $n . ''; } } $items[] = $item; } } $submenu[ CLANFRONT_MENU ] = $items; // phpcs:ignore WordPress.WP.GlobalVariablesOverride }, 999 ); /* ---------- Settings ---------- */ add_action( 'admin_init', function () { register_setting( 'clanfront_settings_group', 'clanfront_settings', array( 'sanitize_callback' => 'clanfront_sanitize_settings' ) ); } ); function clanfront_sanitize_settings( $in ) { $out = clanfront_default_settings(); $in = is_array( $in ) ? $in : array(); $text = array( 'clan_name', 'tagline', 'join_label', 'twitch_client_id', 'twitch_client_secret', 'support_label' ); $urls = array( 'logo', 'hero_image', 'hero_video', 'application_url', 'discord_invite', 'instagram', 'x', 'youtube_channel', 'tiktok', 'twitch_channel', 'support_url' ); $emails = array( 'email', 'application_email' ); $checks = array( 'recruiting', 'show_tournaments', 'twitch_videos' ); foreach ( $out as $key => $default ) { $v = isset( $in[ $key ] ) ? $in[ $key ] : ''; if ( ! is_scalar( $v ) ) { $v = ''; } $v = trim( (string) $v, " \n\r\t\v\x00" ); if ( 'min_age' === $key ) { $out[ $key ] = min( 99, absint( $v ) ); } elseif ( in_array( $key, $emails, true ) ) { $out[ $key ] = sanitize_email( $v ); } elseif ( 'color' === $key ) { $color = sanitize_hex_color( $v ); $out[ $key ] = $color ? $color : $default; } elseif ( 'layout' === $key ) { $out[ $key ] = 'full' === $v ? 'full' : 'centered'; } elseif ( in_array( $key, $checks, true ) ) { $out[ $key ] = '1' === $v ? '1' : '0'; } elseif ( 'discord_server_id' === $key ) { $out[ $key ] = preg_match( '/^\d{15,25}$/', $v ) ? $v : ''; } elseif ( in_array( $key, clanfront_textarea_keys(), true ) ) { $out[ $key ] = sanitize_textarea_field( $v ); } elseif ( in_array( $key, $text, true ) ) { $out[ $key ] = sanitize_text_field( $v ); } elseif ( in_array( $key, $urls, true ) ) { $out[ $key ] = clanfront_clean_url( $v ); } else { $out[ $key ] = sanitize_text_field( $v ); } } if ( '' === $out['clan_name'] ) { $defaults = clanfront_default_settings(); $out['clan_name'] = $defaults['clan_name']; } // A changed Twitch key or channel must not keep using old saved answers. clanfront_twitch_clear_cache(); return $out; } add_action( 'admin_enqueue_scripts', function ( $hook ) { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; $own_post = $screen && 0 === strpos( (string) $screen->post_type, 'clanfront_' ); $own_page = false !== strpos( $hook, 'clanfront' ); if ( $own_post || $own_page ) { wp_enqueue_style( 'clanfront-admin', CLANFRONT_URL . 'assets/admin.css', array(), CLANFRONT_VERSION ); wp_enqueue_script( 'clanfront-admin', CLANFRONT_URL . 'assets/admin.js', array( 'jquery' ), CLANFRONT_VERSION, true ); } if ( false !== strpos( $hook, 'clanfront-settings' ) ) { wp_enqueue_media(); } if ( 'widgets.php' === $hook ) { wp_enqueue_script( 'clanfront-widgets-fix', CLANFRONT_URL . 'assets/widgets-fix.js', array( 'wp-dom-ready', 'wp-plugins' ), CLANFRONT_VERSION, true ); } } ); /** Ready-made accent colours offered next to the colour pickers: name => #rrggbb. */ function clanfront_color_presets() { return array( 'Blaze orange' => '#ff6a00', 'Ember red' => '#e5383b', 'Blood red' => '#b5121b', 'Hot pink' => '#e0457b', 'Violet' => '#7c5cff', 'Cobalt blue' => '#3d6bff', 'Ice blue' => '#2fb4ff', 'Teal' => '#14b8a6', 'Toxic green' => '#39e75f', 'Olive drab' => '#8a9a3b', 'Gold' => '#f2c230', 'Desert sand' => '#d2a86b', 'Steel grey' => '#9aa3ad', 'Arctic white' => '#e9e8ee', ); } /** A row of clickable colour swatches that fill in the colour picker with this id. */ function clanfront_color_swatches( $target_id ) { echo '
'; foreach ( clanfront_color_presets() as $name => $hex ) { printf( '', esc_attr( $target_id ), esc_attr( $hex ), esc_attr( $name . ' ' . $hex ) ); } echo '
'; } function clanfront_settings_row( $key, $label, $type = 'text', $help = '' ) { $s = clanfront_settings(); printf( '%5$s', esc_attr( $key ), esc_html( $label ), esc_attr( $type ), esc_attr( $s[ $key ] ), $help ? '

' . esc_html( $help ) . '

' : '' ); } function clanfront_settings_textarea( $key, $label, $rows = 4, $help = '', $placeholder = '' ) { $s = clanfront_settings(); printf( '%6$s', esc_attr( $key ), esc_html( $label ), (int) $rows, esc_attr( $placeholder ), esc_textarea( $s[ $key ] ), $help ? '

' . esc_html( $help ) . '

' : '' ); } function clanfront_settings_check( $key, $label, $help = '' ) { $s = clanfront_settings(); printf( '%2$s', esc_attr( $key ), esc_html( $label ), checked( '1', (string) $s[ $key ], false ), esc_html( $help ) ); } function clanfront_settings_image( $key, $label, $help, $show_preview = true ) { $s = clanfront_settings(); ?>

Clanfront settings

Add a match or event Add a member View the site

Your clan

Homepage banner

About page

The history is the text of the About page itself (Pages → About). The lists below are added under it.

Recruitment

Code of conduct

Discord

Page width

Tournaments (optional)

Hidden from visitors until you switch it on. You can fill it in first, then turn it on when you are ready. The menu link only appears once there is a tournament to show.

Live data (optional)

Off until you fill it in. Live status is saved for two minutes and videos for an hour, and the site shows nothing if Twitch cannot be reached.

Contact

Support us (optional)

A button for visitors who want to support the clan, for example your Buy Me a Coffee, Ko-fi or PayPal page. It shows in the footer and on the About page. Leave the link empty to hide it.

Social icons

Shown in the footer. Only icons with a link appear. The Twitch channel is also checked for "Live now" when Twitch is set up.

'Member name', 'clanfront_match' => 'For example: vs Team Nova, or Friday game night', 'clanfront_media' => 'Title', 'clanfront_news' => 'Article title', 'clanfront_server' => 'Server name', ); return isset( $titles[ $post->post_type ] ) ? $titles[ $post->post_type ] : $text; }, 10, 2 ); function clanfront_field( $post, $key, $label, $type = 'text', $help = '', $placeholder = '' ) { printf( '
%6$s
', esc_attr( $key ), esc_html( $label ), esc_attr( $type ), esc_attr( get_post_meta( $post->ID, 'clanfront_' . $key, true ) ), esc_attr( $placeholder ), $help ? '

' . esc_html( $help ) . '

' : '' ); } function clanfront_games_datalist() { echo ''; foreach ( clanfront_game_names() as $g ) { echo ''; } function clanfront_member_box( $post ) { wp_nonce_field( 'clanfront_save', 'clanfront_nonce' ); $active = get_post_meta( $post->ID, 'clanfront_active', true ); if ( '' === $active ) { $active = '1'; } ?>

Their own colour for the line under their picture on hover, and on their profile page. Click a ready-made colour or pick any colour; that switches off "Use the clan colour" for you.

Untick to hide someone without deleting them. The order on the roster follows Order under Page Attributes: lower numbers first, so give leaders 1, 2, 3.

Links

The large text box above is the member's bio. Set the picture in the Member picture box on the right; a square image works best.

ID, 'clanfront_kind', true ); $kind = $kind ? $kind : 'match'; $res = (string) get_post_meta( $post->ID, 'clanfront_result', true ); ?>

Result

Fill in after the match. Only played matches with a result count towards the win/loss record.

Shown on the event page: map, lineup, how to join, anything useful.

Set the picture in the Image box on the right. For a video, use a thumbnail or screenshot.

'; } function clanfront_server_box( $post ) { wp_nonce_field( 'clanfront_save', 'clanfront_nonce' ); clanfront_games_datalist(); ?>
'New', 'reviewing' => 'Reviewing', 'accepted' => 'Accepted', 'declined' => 'Declined', ); } function clanfront_application_box( $post ) { wp_nonce_field( 'clanfront_save', 'clanfront_nonce' ); $status = (string) get_post_meta( $post->ID, 'clanfront_app_status', true ); $status = $status ? $status : 'new'; echo ''; foreach ( clanfront_application_fields() as $key => $f ) { printf( '', esc_html( $f[0] ), nl2br( esc_html( (string) get_post_meta( $post->ID, 'clanfront_app_' . $key, true ) ) ) ); } printf( '', esc_html( get_the_date( 'M j, Y H:i', $post ) ) ); echo '
%s%s
Received%s
'; ?>

Only you and other admins see this. Answers cannot be edited. To remove someone's data, move the application to the Bin and delete it permanently.

$label ) { if ( 'date' === $key && ! isset( $add['__keep_date'] ) ) { continue; } $new[ $key ] = $label; if ( 'cb' === $key && $before ) { $new[ $before ] = $add[ $before ]; } if ( 'title' === $key ) { foreach ( $add as $k => $v ) { if ( $k !== $before && '__keep_date' !== $k ) { $new[ $k ] = $v; } } } } return $new; } add_filter( 'manage_clanfront_match_posts_columns', function ( $cols ) { return clanfront_columns( $cols, array( 'clanfront_when' => 'Date', 'clanfront_kind' => 'Type', 'clanfront_game' => 'Game', 'clanfront_result' => 'Result', ) ); } ); add_filter( 'manage_clanfront_member_posts_columns', function ( $cols ) { return clanfront_columns( $cols, array( 'clanfront_picture' => 'Picture', 'clanfront_role' => 'Role', 'clanfront_games' => 'Games', 'clanfront_active' => 'Shown', ), 'clanfront_picture' ); } ); add_filter( 'manage_clanfront_media_posts_columns', function ( $cols ) { return clanfront_columns( $cols, array( 'clanfront_picture' => 'Image' ), 'clanfront_picture' ); } ); add_filter( 'manage_clanfront_server_posts_columns', function ( $cols ) { return clanfront_columns( $cols, array( 'clanfront_game' => 'Game', 'clanfront_address' => 'Address' ) ); } ); add_filter( 'manage_clanfront_applicant_posts_columns', function ( $cols ) { return clanfront_columns( $cols, array( 'clanfront_status' => 'Status', 'clanfront_game' => 'Main game', 'clanfront_contact' => 'Contact', '__keep_date' => true, ) ); } ); foreach ( array( 'match', 'member', 'media', 'server', 'applicant' ) as $clanfront_type ) { add_action( 'manage_clanfront_' . $clanfront_type . '_posts_custom_column', function ( $col, $post_id ) { $post = get_post( $post_id ); switch ( $col ) { case 'clanfront_picture': echo has_post_thumbnail( $post ) ? wp_kses_post( get_the_post_thumbnail( $post, array( 48, 48 ) ) ) : wp_kses_post( 'None yet' ); break; case 'clanfront_role': echo esc_html( clanfront_member_role( $post ) ? clanfront_member_role( $post ) : '—' ); break; case 'clanfront_games': echo esc_html( (string) get_post_meta( $post_id, 'clanfront_games', true ) ?: '—' ); break; case 'clanfront_active': echo wp_kses_post( '0' === (string) get_post_meta( $post_id, 'clanfront_active', true ) ? 'Hidden' : 'Yes' ); break; case 'clanfront_when': $d = clanfront_event_date( $post ); echo esc_html( $d ? clanfront_event_when( $post ) : 'No date yet' ); if ( ! $d ) { echo '
Hidden on the site until you set a date'; } elseif ( clanfront_is_upcoming( $post ) ) { echo '
Upcoming'; } break; case 'clanfront_kind': echo esc_html( clanfront_event_kind_label( $post ) ); break; case 'clanfront_game': echo esc_html( (string) get_post_meta( $post_id, 'clanfront_game', true ) ?: ( 'clanfront_applicant' === $post->post_type ? (string) get_post_meta( $post_id, 'clanfront_app_game', true ) : '' ) ?: '—' ); break; case 'clanfront_result': $r = (string) get_post_meta( $post_id, 'clanfront_result', true ); $l = clanfront_event_results(); echo esc_html( $r && isset( $l[ $r ] ) ? $l[ $r ] . ' ' . get_post_meta( $post_id, 'clanfront_score', true ) : '—' ); break; case 'clanfront_address': echo esc_html( (string) get_post_meta( $post_id, 'clanfront_address', true ) ?: '—' ); break; case 'clanfront_status': $st = (string) get_post_meta( $post_id, 'clanfront_app_status', true ); $st = $st ? $st : 'new'; $ls = clanfront_application_statuses(); echo wp_kses_post( ( 'new' === $st ) ? '' . esc_html( $ls[ $st ] ) . '' : esc_html( isset( $ls[ $st ] ) ? $ls[ $st ] : $st ) ); break; case 'clanfront_contact': echo esc_html( (string) get_post_meta( $post_id, 'clanfront_app_contact', true ) ); break; } }, 10, 2 ); } add_filter( 'manage_edit-clanfront_match_sortable_columns', function ( $cols ) { $cols['clanfront_when'] = 'clanfront_when'; return $cols; } ); // Matches in the admin list: newest date first, unless you sort by another column. add_action( 'pre_get_posts', function ( $q ) { if ( ! is_admin() || ! $q->is_main_query() || 'clanfront_match' !== $q->get( 'post_type' ) ) { return; } $orderby = $q->get( 'orderby' ); if ( ! $orderby || 'clanfront_when' === $orderby ) { $q->set( 'meta_key', 'clanfront_date' ); $q->set( 'orderby', 'meta_value' ); if ( empty( $q->query['order'] ) ) { $q->set( 'order', 'DESC' ); } } } ); /* ---------- Welcome notice ---------- */ add_action( 'admin_notices', function () { if ( ! get_transient( 'clanfront_welcome' ) || ! current_user_can( 'manage_options' ) ) { return; } $screen = get_current_screen(); if ( ! $screen || ( 'plugins' !== $screen->id && false === strpos( (string) $screen->id, 'clanfront' ) ) ) { return; } delete_transient( 'clanfront_welcome' ); printf( '

Clanfront is set up. An example clan, members, matches and pages are ready. Start with Settings and the Getting started guide, then view the site.

', esc_url( admin_url( 'admin.php?page=clanfront-settings' ) ), esc_url( admin_url( 'admin.php?page=clanfront-guide' ) ), esc_url( home_url( '/' ) ) ); } );