Skip to content

Instantly share code, notes, and snippets.

@glueckpress
Created August 27, 2018 10:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glueckpress/36f87a2b665949c39dc72cfadf88c0f5 to your computer and use it in GitHub Desktop.
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.
<?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>&lt;?php do_action( 'site_wide_top_banner' ); ?&gt;</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! &lt;a href="https://example.com/sample-post/">Learn more&lt;/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;
}
@glueckpress
Copy link
Author

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.

screen shot 2018-08-27 at 12 01 07

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment