Instantly share code, notes, and snippets.
Created
August 27, 2018 10:02
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save glueckpress/36f87a2b665949c39dc72cfadf88c0f5 to your computer and use it in GitHub Desktop.
[WordPress][plugin] Adds an optional site-wide top banner to the website, editable via Posts screen. Requires a custom hook in a (child) theme template.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Site-wide Top Banner | |
* Description: Adds an optional site-wide top banner to the website, editable via Posts screen. Requires a custom hook in your theme’s header.php: <code><?php do_action( 'site_wide_top_banner' ); ?></code> | |
* Version: 0.1.0 | |
* Author: Caspar Hübinger | |
* Author URI: https://profiles.wordpress.org/glueckpress/ | |
* License: GNU General Public License v2 or later | |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
* | |
* Copyright Caspar Hübinger 2018 | |
*/ | |
namespace CH201808\SitewideTopBanner; | |
defined( 'ABSPATH' ) && function_exists( 'add_action' ) or exit; | |
/** | |
* Load plugin. | |
*/ | |
add_action( 'plugins_loaded', function() { | |
// L10n business. | |
$locale = get_locale(); | |
if ( defined( 'WP_LANG_DIR' ) ) { | |
$locale = apply_filters( 'plugin_locale', $locale, 'site-wide-top-banner' ); | |
load_textdomain( 'site-wide-top-banner', WP_LANG_DIR . '/plugins/site-wide-top-banner-' . $locale . '.mo' ); | |
} | |
load_plugin_textdomain( 'site-wide-top-banner', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); | |
// Plugin business. | |
add_action( 'admin_init', __NAMESPACE__ . '\update' ); | |
add_action( 'admin_notices', __NAMESPACE__ . '\render_form', 0 ); | |
/** | |
* HEADS UP! | |
* You will need to place this hook in your (child) theme’s header.php file, | |
* like so: <?php do_action( 'site_wide_top_banner' ); ?> | |
*/ | |
add_action( 'site_wide_top_banner', __NAMESPACE__ . '\render_banner' ); | |
/** | |
* Filter: Load included front-end CSS. | |
* | |
* @var boolean Set to false to not load included CSS; default: true | |
*/ | |
if ( apply_filters( 'site_wide_top_banner_render_css', true ) ) { | |
add_action( 'wp_head', __NAMESPACE__ . '\render_style' ); | |
} | |
}); | |
/** | |
* Saminitize HTML, allow links and new lines. | |
*/ | |
function sanitize_multiline_html( $html ) { | |
$sanitized_html = wp_kses( $html, [ 'a' => [ 'href' => [] ], 'br' ] ); | |
return $sanitized_html; | |
} | |
/** | |
* Detect if option is empty. | |
*/ | |
function has_content() { | |
$option = get_option( 'site_wide_top_banner_content', '' ); | |
return '' !== sanitize_text_field( $option ); | |
} | |
/** | |
* Validate and process form input. | |
*/ | |
function update() { | |
if ( isset($_POST['site_wide_top_banner_nonce'] ) ) { | |
if ( wp_verify_nonce( $_POST['site_wide_top_banner_nonce'], 'site-wide-top-banner-nonce' ) ) { | |
$content = sanitize_multiline_html( $_POST['site_wide_top_banner_content'] ); | |
// Update banner content. | |
update_option('site_wide_top_banner_content', $content ); | |
// Auto-support for WP Rocket: clear cache. | |
if ( function_exists( '\rocket_clean_domain' ) ) { | |
\rocket_clean_domain(); | |
} | |
} | |
} | |
} | |
/** | |
* Display form on wp-admin/edit.php. | |
*/ | |
function render_form() { | |
/** | |
* Filter: Minimum user capability to manage banner. | |
* | |
* @var string User capability; default: delete_others_posts (role: Editor) | |
*/ | |
$min_cap = apply_filters( 'site_wide_top_banner_capability', 'delete_others_posts' ); | |
if ( ! current_user_can( $min_cap ) ) { | |
return; | |
} | |
$screen = get_current_screen(); | |
// We only want this above the post list. | |
if ( 'edit-post' !== $screen->id ) { | |
return; | |
} | |
// Fetch banner content; default: empty string. | |
$content = get_option('site_wide_top_banner_content', '' ); | |
// Render admin form: | |
?> | |
<div class="notice"> | |
<h2><?php _e( 'Site-wide Top Banner', 'site-wide-top-banner' ) ?></h2> | |
<p><?php _e( 'Here you can enter a short teaser text. It will be displayed at the top of each page everywhere on your site. Remove existing banner: Empty field and save.', 'site-wide-top-banner' ); | |
if ( has_content() ) : ?></p><?php else : ?> | |
<br><?php _e( 'Line breaks will be kept; you can enter a link as HTML; use Emoji if applicable. Example:', 'site-wide-top-banner' ); ?></p> | |
<pre style="background:#eaeaea;box-sizing:border-box;font-family:Consolas,Monaco,monospace;padding:0.475em;width:99%;white-space:pre-wrap"><?php _e( '🗓 Visit our event! <a href="https://example.com/sample-post/">Learn more</a>', 'site-wide-top-banner' ); ?></pre> | |
<?php endif; ?> | |
<form method="post" action=""> | |
<input type="hidden" name="site_wide_top_banner_nonce" value="<?php echo wp_create_nonce( 'site-wide-top-banner-nonce' ); ?>"/> | |
<p><textarea class="large-text" rows="2" name="site_wide_top_banner_content" id="site_wide_top_banner_content"><?php echo esc_textarea( $content ); ?></textarea></p> | |
<p><?php submit_button( null, 'primary', 'submit', false ); ?></p> | |
</form> | |
</div> | |
<?php | |
} | |
/** | |
* Render top bar on the front end. | |
*/ | |
function render_banner() { | |
if ( ! has_content() ) { | |
return; | |
} | |
$option = get_option( 'site_wide_top_banner_content', '' ); | |
$content = sanitize_multiline_html( $option ); | |
printf( '<aside class="site-wide-top-banner"><p>%s</p></aside>', nl2br( $content ) ); | |
} | |
/** | |
* Render style on the front end. | |
*/ | |
function render_style() { | |
if ( ! has_content() ) { | |
return; | |
} | |
echo '<style id="site-wide-top-banner-css">.site-wide-top-banner{background:#d30606;color:#fff;font-size:.875em;font-weight:600;padding:.4375em 0;position:relative;z-index:99999}.site-wide-top-banner p{margin:0 1.5em;text-align:center}.site-wide-top-banner a,.site-wide-top-banner a:visited{color:inherit;text-decoration:underline}</style>' . PHP_EOL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: I’m aware this would typically be solved via Customizer. However, I needed a quick solution for a site editor who wasn’t used to use the Customizer on a daily basis, so I chose to implement it as a custom form on the Posts screen.