https://sergeliatko.com
* @GitHub https://github.com/sergeliatko/content-widgets
*
*/
/** define content-widgets text domain */
if( !defined('CONTENT_WIDGETS_TXD') ) {
define( 'CONTENT_WIDGETS_TXD', 'content-widgets' );
}
/**
* Load class only once
*/
if( !class_exists('Content_Widgets') ) {
/**
* Class Content_Widgets
*/
class Content_Widgets {
/**
* @var Content_Widgets $instance
*/
public static $instance;
/**
* Content_Widgets constructor.
*/
protected function __construct() {
/** register content widget areas */
add_action( 'widgets_init', array( $this, 'register_content_widget_areas' ), 10, 0 );
/** add meta box */
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 1 );
/** save post meta */
add_action( 'save_post', array( $this, 'save_post_meta' ), 10, 3 );
/** add user interface to customizer */
add_action( 'customize_register', array( $this, 'customize_register' ), 10, 1 );
/** add display controller */
add_action( 'wp', array( $this, 'display_controller' ), 10, 0 );
}
/**
* Saves post meta.
*
* @param int $post_ID
* @param WP_Post $post
* @param $update
*/
public function save_post_meta( $post_ID, WP_Post $post, $update ) {
/** process only if not autosave and the nonce is verified */
if(
( true === $update )
&& !( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
&& ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'update-post_' . $post->ID ) )
) {
/** @var array $fields to save */
$fields = array(
'_hide_content_widgets' => array(
array( $this, 'sanitize_checkbox_field' )
)
);
/**
* @var string $field to save
* @var array $sanitizers array of functions to use to sanitize the submitted value
*/
foreach ( $fields as $field => $sanitizers ) {
/** if not submitted - delete post meta and do next field */
if( !isset( $_POST[ $field ] ) ) {
delete_post_meta( $post->ID, $field );
continue;
}
/** @var mixed $value submitted */
$value = $_POST[ $field ];
/** @var callable $sanitizer */
foreach ( $sanitizers as $sanitizer ) {
$value = call_user_func( $sanitizer, $value );
}
/** save/delete post meta */
$this->is_empty_not_zero( $value ) ? delete_post_meta( $post->ID, $field ) : update_post_meta( $post->ID, $field, $value );
}
}
}
/**
* Adds meta box to edit post screen.
*
* @param string $type
*/
public function add_meta_boxes( $type = 'post' ) {
if( in_array( $type, array_keys( $this->get_post_types() ) ) ) {
add_meta_box(
'content_widgets',
__( 'Content widgets', CONTENT_WIDGETS_TXD ),
array( $this, 'do_meta_box' ),
$type,
'side',
'low'
);
}
}
/**
* Displays meta box.
*
* @param WP_Post $post
*/
public function do_meta_box( WP_Post $post ) {
/** @var array $post_types */
$post_types = $this->get_post_types();
/** @var WP_Post_Type $post_type */
$post_type = $post_types[ get_post_type( $post ) ];
printf(
'
',
checked( 1, absint( get_post_meta( $post->ID, '_hide_content_widgets', true ) ), false ),
sprintf(
__( 'Hide content widgets on this %s?', CONTENT_WIDGETS_TXD ),
strtolower( $post_type->labels->singular_name )
)
);
}
/**
* Registers content widget areas.
*/
public function register_content_widget_areas() {
/**
* @var string $type post type name
* @var WP_Post_Type $object post type
*/
foreach( $this->get_post_types() as $type => $object ) {
register_sidebar(
apply_filters(
'content_widget_area_attributes',
array(
'name' => sprintf(
__( 'After %s widgets', CONTENT_WIDGETS_TXD ),
strtolower( $object->labels->name )
),
'id' => "content-widgets-{$type}",
'description' => sprintf(
__( 'Widgets placed here will be displayed after the content on %s.', CONTENT_WIDGETS_TXD ),
strtolower( $object->labels->name )
),
'before_widget' => '',
'after_widget' => "
\n",
'before_title' => '',
'after_title' => "
\n"
),
$type,
$object
)
);
}
}
/**
* Adds content widgets to the end of the content.
*
* @param string $content
*
* @return string
*/
public function add_content_widgets( $content ) {
global $post, $wp_query;
if( $wp_query->is_main_query() ) {
$content .= $this->get_content_widgets_area( $post->post_type );
}
return $content;
}
/**
* Returns content widget area by post type name.
*
* @param string $type post type
*
* @return string
*/
public function get_content_widgets_area( $type = 'post' ) {
$out = '';
if( is_active_sidebar("content-widgets-{$type}") ) {
ob_start();
dynamic_sidebar("content-widgets-{$type}");
$widgets = ob_get_clean();
if( !empty( $widgets ) ) {
$format = apply_filters(
'content_widget_area_format',
array(
'before' => '',
'after' => "
\n"
)
);
$before = sprintf( $format['before'], $type );
$after = sprintf( $format['after'], $type );
$out .= $before . $widgets . $after;
}
}
return $out;
}
/**
* Adds content widgets display filter to the_content if necessary.
*/
public function display_controller() {
global $post;
if(
is_singular()
&& !is_front_page()
&& !$this->is_empty( get_theme_mod("content_widgets_display_{$post->post_type}") )
&& $this->is_empty( get_post_meta( $post->ID, '_hide_content_widgets', true ) )
&& ( true === apply_filters( 'display_content_widgets', true, $post ) )
) {
/** hook into the_content filter */
add_filter(
'the_content',
array( $this, 'add_content_widgets' ),
absint( get_theme_mod("content_widgets_filter_order_{$post->post_type}", 9 ) ),
1
);
}
}
/**
* Registers interface in customizer.
*
* @param WP_Customize_Manager $wp_customize_manager
*/
public function customize_register( WP_Customize_Manager $wp_customize_manager ) {
/** register settings */
$this->register_customizer_settings( $wp_customize_manager );
/** add section */
$wp_customize_manager->add_section(
'content_widgets',
array(
'title' => __( 'Content Widgets', CONTENT_WIDGETS_TXD ),
'priority' => 115
)
);
/** add controls */
$this->register_customizer_controls( $wp_customize_manager );
}
/**
* Registers customizer controls.
*
* @param WP_Customize_Manager $wp_customize_manager
*/
protected function register_customizer_controls( WP_Customize_Manager $wp_customize_manager ) {
/** require Content_Widgets_Control */
require_once( dirname( __FILE__ ) . '/Content_Widgets_Control.php' );
/**
* @var string $type
* @var WP_Post_Type $object
*/
foreach( $this->get_post_types() as $type => $object ) {
/** add display control */
$wp_customize_manager->add_control(
new Content_Widgets_Control(
$wp_customize_manager,
"content_widgets_display_control_{$type}",
array(
'settings' => "content_widgets_display_{$type}",
'section' => 'content_widgets',
'type' => 'checkbox',
'post_type' => $type,
'active_callback' => array( $this, 'show_control' ),
'label' => sprintf(
__( 'Display content widgets on %s', CONTENT_WIDGETS_TXD ),
strtolower( $object->labels->name )
)
)
)
);
/** add display filter order control */
$wp_customize_manager->add_control(
new Content_Widgets_Control(
$wp_customize_manager,
"content_widgets_filter_order_control_{$type}",
array(
'settings' => "content_widgets_filter_order_{$type}",
'section' => 'content_widgets',
'type' => 'number',
'post_type' => $type,
'active_callback' => array( $this, 'show_control' ),
'label' => __( 'Display order', CONTENT_WIDGETS_TXD ),
'input_attrs' => array(
'min' => 0,
'max' => 100,
'step' => 1
)
)
)
);
}
}
/**
* Registers customizer settings.
*
* @param WP_Customize_Manager $wp_customize_manager
*/
protected function register_customizer_settings( WP_Customize_Manager $wp_customize_manager ) {
/** @var string $type post type name */
foreach( array_keys( $this->get_post_types() ) as $type ) {
/** add display setting */
$wp_customize_manager->add_setting(
"content_widgets_display_{$type}",
array(
'type' => 'theme_mod',
'transport' => 'refresh',
'sanitize_callback' => 'sanitize_text_field',
'default' => ''
)
);
/** add display filter order */
$wp_customize_manager->add_setting(
"content_widgets_filter_order_{$type}",
array(
'type' => 'theme_mod',
'transport' => 'refresh',
'sanitize_callback' => 'absint',
'default' => 9
)
);
}
}
/**
* Checks if the control should be displayed in customizer.
*
* @param Content_Widgets_Control $control
*
* @return bool
*/
public function show_control( Content_Widgets_Control $control ) {
return ( is_singular( $control->post_type ) && !is_front_page() );
}
/*
* Returns array of public post types objects.
*/
protected function get_post_types() {
return get_post_types( array( 'public' => true ), 'objects', 'and' );
}
/**
* Checks if data is empty but accepts integer zero value.
*
* @param mixed $data
*
* @return bool
*/
protected function is_empty_not_zero( $data ) {
return ( empty( $data ) && ( 0 !== $data ) );
}
/**
* Sanitizes submitted checkbox.
*
* @param $data
*
* @return int|string
*/
public function sanitize_checkbox_field( $data ) {
return $this->is_empty( absint( $data ) ) ? '' : 1;
}
/**
* Checks if data is empty.
*
* @param mixed $data
*
* @return bool
*/
protected function is_empty( $data ) {
return empty( $data );
}
/**
* @return Content_Widgets|static
*/
public static function getInstance() {
return ( null === static::$instance ) ? ( static::$instance = new static() ) : static::$instance;
}
/**
* prevent cloning
*/
private function __clone() {}
}
/** load the addon after the theme is loaded */
add_action( 'after_setup_theme', array( 'Content_Widgets', 'getInstance' ), 10, 0 );
}