Skip to content

Instantly share code, notes, and snippets.

@nikolov-tmw
Last active August 29, 2015 13:56
Show Gist options
  • Save nikolov-tmw/9216716 to your computer and use it in GitHub Desktop.
Save nikolov-tmw/9216716 to your computer and use it in GitHub Desktop.
Switchable Content WordPress plugin
This is a simple plugin that allows you to create "switchable" content blocks.
A "switchable" block is a block of content that can be placed inside of a post/page/widget via a shortcode and be turned on/off globally from a single page in the admin.
After activating the plugin, just go to "Switchable Contents > Add New" and enter your title and content(the title is generally used for organizational purposes only).
The content of each block is wrapped in <div class="switchable-content switchable-content-visible">, but if you want to customize the output, simply copy the "switchable-content-template.php" file in your theme's root directory and do any changes there.
You can easily have a default message that will be displayed when a block is disabled, or you can add some text before/after the content. You have no limitations in how to use the template :)
<?php
// Silence is golden...
<?php
/*
This template part is included when the [switchable-content] shortcode is parsed.
You can access the $sc_post and $display variables.
$sc_post is a WP_Post object of the Switchable Content post.
$display is a boolean which defines whether the content should be displayed or not.
If you want to modify this template, just copy the file to your theme's directory and
change it however you want. For instance you can have a custom message when
the content is not supposed to be displayed.
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Cheating huh?' );
}
if ( $display ) : ?>
<div class="switchable-content switchable-content-visible">
<?php echo apply_filters( 'the_content', $sc_post->post_content ); ?>
</div>
<?php
// If we're not supposed to display the content - do nothing(get rid of /* and */ to do something)
else : /*?>
<?php*/
endif; ?>
<?php
/*
Plugin Name: Switchable Content
Description: This plugin creates an extra custom post type, which allows you to create blocks of content independent of posts and pages. You can display these blocks of content with the use of a simple shortcode. You can also enable/disable individual content blocks with a single click of the mouse.
Author: Nikola Nikolov
Author URI: http://paiyakdev.com/
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Cheating huh?' );
}
/**
* The main class for the plugin
*
* It allows everything to be nice and tidy without polluting the global scope too much :)
*/
class PD_Switchable_Content {
private $sc_depth = 0;
private $plugin_dir;
function __construct() {
// Do nothing
}
public static function instance() {
// Store the instance locally to avoid private static replication
static $instance = null;
// Only run these methods if they haven't been ran previously
if ( null === $instance ) {
$instance = new PD_Switchable_Content;
$instance->plugin_dir = trailingslashit( plugin_dir_path( __FILE__ ) );
add_action( 'plugins_loaded', array( $instance, 'init' ) );
}
// Always return the instance
return $instance;
}
public function init() {
load_plugin_textdomain( 'switchable-content', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
$this->add_actions();
$this->add_filters();
$this->register_shortcodes();
}
public function add_actions() {
add_action( 'init', array( $this, 'register_cpt' ), 10 );
add_action( 'admin_menu', array( $this, 'register_submenu_page' ), 10 );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 10 );
add_action( 'wp_ajax_sc_switch', array( $this, 'ajax_switch_handle' ), 10 );
add_action( 'add_meta_boxes', array( $this, 'add_shortcode_metabox' ), 10 );
}
public function admin_enqueue_scripts( $handle ) {
if ( 'switchable_contents_page_switchable-content-switches' == $handle ) {
wp_enqueue_script( 'jquery' );
add_action( 'admin_head', array( $this, 'admin_page_scripts' ), 10 );
}
}
public function add_filters() {
}
public function register_shortcodes() {
add_shortcode( 'switchable-content', array( $this, 'shortcode' ) );
}
public function add_shortcode_metabox() {
add_meta_box( 'switchable_contents_shortcode', __( 'Shortcode', 'switchable-content' ), array( $this, 'shortcode_metabox' ), 'switchable_contents', 'side', 'high' );
}
public function register_submenu_page() {
add_submenu_page( 'edit.php?post_type=switchable_contents', __( 'Switches', 'switchable-content' ), __( 'Switches', 'switchable-content' ), 'manage_options', 'switchable-content-switches', array( $this, 'switches_page' ) );
}
public function register_cpt() {
$labels = array(
'name' => _x( 'Switchable Contents', 'post type general name', 'switchable-content' ),
'singular_name' => _x( 'Switchable Content', 'post type singular name', 'switchable-content' ),
'add_new' => _x( 'Add New', 'Switchable Content', 'switchable-content' ),
'add_new_item' => __( 'Add New Switchable Content', 'switchable-content' ),
'edit_item' => __( 'Edit Switchable Content', 'switchable-content' ),
'new_item' => __( 'New Switchable Content', 'switchable-content' ),
'view_item' => __( 'View Switchable Content', 'switchable-content' ),
'search_items' => __( 'Search Switchable Contents', 'switchable-content' ),
'not_found' => __( 'No Switchable Contents found', 'switchable-content' ),
'not_found_in_trash' => __( 'No Switchable Contents found in Trash', 'switchable-content' ),
'parent_item_colon' => ''
);
$args = array(
'labels' => $labels,
'public' => false,
'publicly_queryable' => false,
'show_ui' => true,
'query_var' => true,
'rewrite' => false,
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => null,
'has_archive' => false,
'supports' => array( 'title', 'editor' ),
);
register_post_type( 'switchable_contents', $args );
}
public function ajax_switch_handle() {
$sc_post = get_post( intval( $_POST['pid'] ) );
// Don't allow unauthorized users to use that
if ( ! $sc_post || 'switchable_contents' != $sc_post->post_type || ! current_user_can( 'manage_options', $sc_post->ID ) /* same as the permission for add_submenu_page() */ ) {
echo 'Unauthorized access!';
exit;
}
$sc_post->post_status = 'enable' == $_POST['act'] ? 'publish' : 'draft';
$result = wp_update_post( $sc_post, true );
echo ! is_wp_error( $result ) ? 'Success' : 'Error: ' . $result->get_error_messages();
exit;
}
public function admin_page_scripts() {
?>
<style>
.sc-content-block { padding: 5px; margin-bottom: 5px; border: 1px solid #ccc; background: #fff; position: relative; }
.sc-content-block .disabled-overlay { display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; z-index: 10; cursor: wait; background: #fff; opacity: 0.5; -moz-opacity: 0.5; filter:alpha(opacity=50); }
.sc-content-block.disabled .disabled-overlay { display: block; }
.sc-content-block label { display: block; line-height: 26px; }
</style>
<script>
(function($){
$(document).ready(function(){
$('.sc-content-block .sc-content-block-check').on('change', function(){
var $th = $(this);
$th.closest('.sc-content-block').addClass('disabled');
$.post(ajaxurl, {
action: 'sc_switch',
pid: $th.val(),
// Since this happens after the input changed states we have to use that logic
act: $th.attr('checked') ? 'enable' : 'disable'
}, function(){
$th.closest('.sc-content-block').removeClass('disabled');
})
})
})
})(jQuery)
</script>
<?php
}
public function switches_page() {
$content_blocks = get_posts( array( 'post_type' => 'switchable_contents', 'post_status' => 'any', 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC' ) ); ?>
<div class="wrap">
<h2><?php _e( 'Content Switches', 'switchable-content' ); ?></h2>
<div class="updated">
<h4><?php _e( 'Here you can easily manage which content blocks are enabled and which are disabled. Just click on the checkbox next to the title of each content block to enable/disable it.', 'switchable-content' ); ?></h4>
</div>
<?php if ( $content_blocks ) : ?>
<?php foreach ( $content_blocks as $block ) :
$checked = 'publish' == $block->post_status ? ' checked="checked"' : ''; ?>
<div class="sc-content-block">
<label for="sc_content_block_<?php echo $block->ID; ?>"><input type="checkbox" name="sc_content_block_<?php echo $block->ID; ?>" id="sc_content_block_<?php echo $block->ID; ?>" class="sc-content-block-check" value="<?php echo $block->ID; ?>"<?php echo $checked; ?> /><?php echo get_the_title( $block->ID ); ?></label>
<div class="disabled-overlay"></div>
</div>
<?php endforeach; ?>
<?php else : ?>
<h4><?php _e( 'Ooops... It seems that you do not have any content blocks yet :( Please add some first.', 'switchable-content' ); ?></h4>
<?php endif; ?>
<p class="help"><?php _e( 'Hint: this is the same as changing the status of a Switchable Contents post to Published(enable) or anything else(disable) - it is just a bit more easy to do so here.', 'switchable-content' ); ?></p>
</div>
<?
}
public function shortcode_metabox( $post ) {
?>
<p class="help"><?php _e( 'In order to display the content of this block in a post/page, just paste the following shortcode.', 'switchable-content' ); ?></p>
<input class="widefat" type="text" readonly="readonly" id="sc_shortcode_holder" value="<?php echo esc_attr( '[switchable-content id="' . $post->ID . '"]' ); ?>" />
<script>
// We should have jQuery, but let's be cautios just in case :)
if ( jQuery ) {
(function($){
$(document).ready(function(){
var focusedElement;
$('#sc_shortcode_holder').on('focus', function(){
if ( focusedElement == this ) {
return; //already focused, return so user can now place cursor at specific point in input.
}
focusedElement = this;
//select all text in the text field on focus for easy re-entry. Delay sightly to allow focus to "stick" before selecting.
setTimeout(function(){
focusedElement.select();
}, 50);
}).on('blur', function(){
focusedElement = null;
});
});
})(jQuery)
};
</script>
<?php
}
public function get_template( $template ) {
$_theme_template = locate_template( $template );
// Use the default template
if ( ! $_theme_template ) {
return $this->plugin_dir . $template;
}
// Use the theme's template
return $_theme_template;
}
public function shortcode( $atts, $content = null ) {
$sc_post = $atts['id'] ? get_post( $atts['id'] ) : false;
// Does not exist
if ( ! $sc_post || 'switchable_contents' != $sc_post->post_type ) {
return '';
}
// Avoid too much recursion - do you really need to have recursion anyway? :)
if ( 10 <= $this->sc_depth ) {
return '';
}
// We'll display only if post is published
$display = 'publish' == $sc_post->post_status ? true : false;
$template = $this->get_template( 'switchable-content-template.php' );
ob_start();
$this->sc_depth ++;
include( $template );
$this->sc_depth --;
return ob_get_clean();
}
}
// Allow easy access to the plugin's interface
function _switchable_cnt() {
return PD_Switchable_Content::instance();
}
// Instantiate the plugin
_switchable_cnt();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment