570 lines
13 KiB
PHP
570 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Customizer Layouts functionality.
|
|
*
|
|
* @class Primer_Customizer_Layouts
|
|
* @package Classes/Customizer
|
|
* @category Class
|
|
* @author GoDaddy
|
|
* @since 1.0.0
|
|
*/
|
|
class Primer_Customizer_Layouts {
|
|
|
|
/**
|
|
* Array of custom layouts.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $layouts = array();
|
|
|
|
/**
|
|
* Default layout key.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $default = 'two-column-default';
|
|
|
|
/**
|
|
* Enable post/page overrides via meta box.
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $meta_box = true;
|
|
|
|
/**
|
|
* Array of page widths.
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $page_widths = array();
|
|
|
|
/**
|
|
* Class constructor.
|
|
*/
|
|
public function __construct() {
|
|
|
|
/**
|
|
* Filter the registered layouts.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var array
|
|
*/
|
|
$this->layouts = (array) apply_filters( 'primer_layouts',
|
|
array(
|
|
'one-column-wide' => esc_html__( 'One Column: Wide', 'primer' ),
|
|
'one-column-narrow' => esc_html__( 'One Column: Narrow', 'primer' ),
|
|
'two-column-default' => esc_html__( 'Two Columns: Content | Sidebar', 'primer' ),
|
|
'two-column-reversed' => esc_html__( 'Two Columns: Sidebar | Content', 'primer' ),
|
|
'three-column-default' => esc_html__( 'Three Columns: Content | Sidebar | Sidebar', 'primer' ),
|
|
'three-column-center' => esc_html__( 'Three Columns: Sidebar | Content | Sidebar', 'primer' ),
|
|
'three-column-reversed' => esc_html__( 'Three Columns: Sidebar | Sidebar | Content', 'primer' ),
|
|
)
|
|
);
|
|
|
|
if ( ! $this->layouts ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
* Filter the default layout.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var string
|
|
*/
|
|
$default = (string) apply_filters( 'primer_default_layout', $this->default );
|
|
$this->default = $this->layout_exists( $default ) ? $default : ( $this->layout_exists( $this->default ) ? $this->default : key( $this->layouts ) );
|
|
|
|
/**
|
|
* Filter if post/page overrides via meta box should be enabled.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var bool
|
|
*/
|
|
$this->meta_box = (bool) apply_filters( 'primer_layouts_meta_box_enabled', $this->meta_box );
|
|
|
|
/**
|
|
* Filter the registered page widths.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var array
|
|
*/
|
|
$this->page_widths = (array) apply_filters( 'primer_page_widths',
|
|
array(
|
|
'fixed' => /* translators: fixed-width page layout */ esc_html__( 'Fixed', 'primer' ),
|
|
'fluid' => /* translators: fluid-width page layout */ esc_html__( 'Fluid', 'primer' ),
|
|
)
|
|
);
|
|
|
|
add_action( 'init', array( $this, 'rtl_layouts' ), 11 );
|
|
add_action( 'init', array( $this, 'post_type_support' ), 11 );
|
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
|
|
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
|
|
|
if ( $this->meta_box ) {
|
|
|
|
add_action( 'load-post.php', array( $this, 'load_post' ) );
|
|
add_action( 'load-post-new.php', array( $this, 'load_post' ) );
|
|
add_action( 'save_post', array( $this, 'save_post' ) );
|
|
|
|
}
|
|
|
|
add_filter( 'body_class', array( $this, 'body_class' ) );
|
|
|
|
}
|
|
|
|
/**
|
|
* Alter some registered layouts when in RTL mode.
|
|
*
|
|
* @action init
|
|
* @uses primer_layouts_rtl To filter the possible layouts.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function rtl_layouts() {
|
|
|
|
if ( ! is_rtl() ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
* Filter changes needed for registered layouts when in RTL mode.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var array
|
|
*/
|
|
$rtl_layouts = (array) apply_filters( 'primer_layouts_rtl',
|
|
array(
|
|
'two-column-default' => esc_html__( 'Two Columns: Sidebar | Content', 'primer' ),
|
|
'two-column-reversed' => esc_html__( 'Two Columns: Content | Sidebar', 'primer' ),
|
|
'three-column-default' => esc_html__( 'Three Columns: Sidebar | Sidebar | Content', 'primer' ),
|
|
'three-column-reversed' => esc_html__( 'Three Columns: Content | Sidebar | Sidebar', 'primer' ),
|
|
)
|
|
);
|
|
|
|
$this->layouts = array_merge( $this->layouts, $rtl_layouts );
|
|
|
|
}
|
|
|
|
/**
|
|
* Add post type support.
|
|
*
|
|
* @action init
|
|
* @uses [add_post_type_support](https://codex.wordpress.org/Function_Reference/add_post_type_support) To add layout support to specified post types.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function post_type_support() {
|
|
|
|
/**
|
|
* Filter the post types that allow layouts.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var array
|
|
*/
|
|
$post_types = (array) apply_filters( 'primer_layouts_post_types', get_post_types( array( 'public' => true ) ) );
|
|
|
|
foreach ( $post_types as $post_type ) {
|
|
|
|
add_post_type_support( $post_type, 'primer-layouts' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Enqueue scripts and styles for post meta box.
|
|
*
|
|
* @action admin_enqueue_scripts
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $hook The suffix of the current admin page.
|
|
*/
|
|
public function admin_enqueue_scripts( $hook ) {
|
|
|
|
if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$rtl = is_rtl() ? '-rtl' : '';
|
|
$suffix = SCRIPT_DEBUG ? '' : '.min';
|
|
|
|
wp_enqueue_script(
|
|
'primer-layouts',
|
|
get_template_directory_uri() . "/assets/js/admin/layouts{$suffix}.js",
|
|
array( 'jquery' ),
|
|
PRIMER_VERSION
|
|
);
|
|
|
|
wp_enqueue_style(
|
|
'primer-layouts',
|
|
get_template_directory_uri() . "/assets/css/admin/layouts{$rtl}{$suffix}.css",
|
|
array(),
|
|
PRIMER_VERSION
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
* Add a new meta box to post screens.
|
|
*
|
|
* @action load-post.php
|
|
* @action load-post-new.php
|
|
*
|
|
* @since 1.0.0
|
|
* @uses $this->add_meta_box()
|
|
*/
|
|
public function load_post() {
|
|
|
|
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ), 10, 2 );
|
|
|
|
}
|
|
|
|
/**
|
|
* Add post meta box for custom layouts.
|
|
*
|
|
* @see $this->load_post()
|
|
* @since 1.0.0
|
|
* @uses $this->render_meta_box()
|
|
*
|
|
* @param string $post_type Post type slug name.
|
|
* @param WP_Post $post Post object.
|
|
*/
|
|
public function add_meta_box( $post_type, WP_Post $post ) {
|
|
|
|
if (
|
|
! post_type_supports( $post_type, 'primer-layouts' )
|
|
||
|
|
! current_user_can( 'edit_post_meta', $post->ID )
|
|
||
|
|
! current_user_can( 'add_post_meta', $post->ID )
|
|
||
|
|
! current_user_can( 'delete_post_meta', $post->ID )
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add_meta_box(
|
|
'primer-layouts-meta-box',
|
|
esc_html__( 'Layout', 'primer' ),
|
|
array( $this, 'render_meta_box' ),
|
|
$post_type,
|
|
'side',
|
|
'default',
|
|
null
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
* Display the custom layouts post meta box.
|
|
*
|
|
* @see $this->add_meta_box()
|
|
* @since 1.0.0
|
|
*
|
|
* @param WP_Post $post Post object.
|
|
*/
|
|
public function render_meta_box( WP_Post $post ) {
|
|
|
|
$current_layout = $this->get_post_layout( $post->ID );
|
|
$has_custom = ! empty( $current_layout );
|
|
|
|
wp_nonce_field( basename( __FILE__ ), 'primer-layout-nonce' );
|
|
|
|
?>
|
|
<div class="primer-layout">
|
|
|
|
<p>
|
|
<label for="primer-layout-use-default">
|
|
<input type="radio" name="primer-layout-override" id="primer-layout-use-default" value="0" autocomplete="off" <?php checked( ! $has_custom ); ?>>
|
|
<?php esc_html_e( 'Default', 'primer' ); ?>
|
|
</label>
|
|
<label for="primer-layout-use-custom">
|
|
<input type="radio" name="primer-layout-override" id="primer-layout-use-custom" value="1" autocomplete="off" <?php checked( $has_custom ); ?>>
|
|
<?php esc_html_e( 'Custom', 'primer' ); ?>
|
|
</label>
|
|
<span class="clear"></span>
|
|
</p>
|
|
|
|
<?php $this->print_layout_choices( $this->layouts, $post->ID, $current_layout, $has_custom ); ?>
|
|
|
|
</div>
|
|
<?php
|
|
|
|
}
|
|
|
|
/**
|
|
* Print all layouts choices to a meta-box or the Customizer.
|
|
*
|
|
* @global WP_Customize_Manager $wp_customize
|
|
* @since 1.0.0
|
|
*
|
|
* @param array $layouts Array of layouts.
|
|
* @param int $post_id (optional) Post ID. Default is `null`.
|
|
* @param string $current_layout (optional) Current layout slug name. Default is `null`.
|
|
* @param bool $has_custom (optional) Whether the current layout is a custom one. Default is `true`.
|
|
*/
|
|
public function print_layout_choices( $layouts, $post_id = null, $current_layout = null, $has_custom = true ) {
|
|
|
|
global $wp_customize;
|
|
|
|
$global_layout = $this->get_global_layout();
|
|
|
|
if ( ! $current_layout ) {
|
|
|
|
$current_layout = $global_layout;
|
|
|
|
}
|
|
|
|
$name = isset( $wp_customize ) ? '_customize-radio' : 'primer';
|
|
|
|
?>
|
|
<div class="primer-layout-wrap">
|
|
|
|
<ul>
|
|
<?php
|
|
|
|
foreach ( $layouts as $layout => $label ) :
|
|
|
|
$class = ( $has_custom ) ? 'active' : 'disabled';
|
|
$class .= ( $layout === $global_layout ) ? ' active global' : '';
|
|
|
|
?>
|
|
<li class="<?php echo esc_attr( $class ); ?>">
|
|
<label for="primer-layout-<?php echo esc_attr( $layout ); ?>">
|
|
<input type="radio" name="<?php echo esc_attr( $name ); ?>-layout" data-customize-setting-link="layout" id="primer-layout-<?php echo esc_attr( $layout ); ?>" value="<?php echo esc_attr( $layout ); ?>" <?php checked( $current_layout, $layout ); ?> <?php disabled( 'disabled' === $class ); ?>>
|
|
<img src="<?php echo esc_url( sprintf( '%s/assets/images/layouts/%s%s.svg', get_template_directory_uri(), $layout, is_rtl() ? '-rtl' : '' ) ); ?>"
|
|
alt="<?php echo esc_attr( $label ); ?>"
|
|
title="<?php echo esc_attr( $label ); ?>">
|
|
<span><?php echo esc_html( $label ); ?></span>
|
|
</label>
|
|
</li>
|
|
<?php
|
|
|
|
endforeach;
|
|
|
|
?>
|
|
</ul>
|
|
|
|
</div>
|
|
<?php
|
|
|
|
}
|
|
|
|
/**
|
|
* Save layout post meta.
|
|
*
|
|
* @action save_post
|
|
* @since 1.0.0
|
|
*
|
|
* @param int $post_id Post ID.
|
|
*/
|
|
public function save_post( $post_id ) {
|
|
|
|
if (
|
|
empty( $_POST['primer-layout-nonce'] ) // input var ok.
|
|
||
|
|
! wp_verify_nonce( $_POST['primer-layout-nonce'], basename( __FILE__ ) ) // input var ok, sanitization ok.
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$override = ! empty( $_POST['primer-layout-override'] ); // input var ok.
|
|
$current = $this->get_post_layout( $post_id );
|
|
|
|
if ( ! $override && $current ) {
|
|
|
|
delete_post_meta( $post_id, 'primer_layout' );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$layout = isset( $_POST['primer-layout'] ) ? sanitize_key( $_POST['primer-layout'] ) : null; // input var ok.
|
|
|
|
if ( ! $override || ! $this->layout_exists( $layout ) || $layout === $current ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
update_post_meta( $post_id, 'primer_layout', $layout );
|
|
|
|
}
|
|
|
|
/**
|
|
* Register custom layout settings.
|
|
*
|
|
* @action customize_register
|
|
* @see WP_Customize_Manager
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param WP_Customize_Manager $wp_customize Instance of the WP_Customize_Manager class.
|
|
*/
|
|
public function customize_register( WP_Customize_Manager $wp_customize ) {
|
|
|
|
$wp_customize->add_section(
|
|
'layout',
|
|
array(
|
|
'title' => esc_html__( 'Layout', 'primer' ),
|
|
'priority' => 30,
|
|
'capability' => 'edit_theme_options',
|
|
)
|
|
);
|
|
|
|
if ( ! $this->page_widths ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
reset( $this->page_widths );
|
|
|
|
$wp_customize->add_setting(
|
|
'page_width',
|
|
array(
|
|
'default' => key( $this->page_widths ),
|
|
'sanitize_callback' => 'sanitize_key',
|
|
'transport' => 'postMessage',
|
|
)
|
|
);
|
|
|
|
$wp_customize->add_control(
|
|
'page_width',
|
|
array(
|
|
'label' => esc_html__( 'Page Width', 'primer' ),
|
|
'description' => esc_html__( 'Display your site differently on larger screens.', 'primer' ),
|
|
'section' => 'layout',
|
|
'settings' => 'page_width',
|
|
'type' => 'radio',
|
|
'choices' => $this->page_widths,
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
* Add layout class to body element on the front-end.
|
|
*
|
|
* @filter body_class
|
|
* @since 1.0.0
|
|
*
|
|
* @param array $classes Array of body classes.
|
|
*
|
|
* @return array Returns the filtered array of body classes.
|
|
*/
|
|
public function body_class( array $classes ) {
|
|
|
|
$classes[] = sanitize_html_class( sprintf( 'layout-%s', $this->get_current_layout() ) );
|
|
$classes[] = primer_is_fluid_width() ? 'no-max-width' : null;
|
|
|
|
return array_filter( $classes );
|
|
|
|
}
|
|
|
|
/**
|
|
* Check if a layout exists.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $layout The layout name to check.
|
|
*
|
|
* @return bool Returns true if the layout is set, otherwise false.
|
|
*/
|
|
protected function layout_exists( $layout ) {
|
|
|
|
return isset( $this->layouts[ $layout ] );
|
|
|
|
}
|
|
|
|
/**
|
|
* Return a post ID.
|
|
*
|
|
* @param WP_Post|int $post (optional) The WP_Post object.
|
|
*
|
|
* @return int Returns the post ID.
|
|
*/
|
|
protected function get_post_id( $post = null ) {
|
|
|
|
return is_a( 'WP_Post', $post ) ? $post->ID : ( is_numeric( $post ) ? absint( $post ) : get_queried_object_id() );
|
|
|
|
}
|
|
|
|
/**
|
|
* Return the layout override for a post.
|
|
*
|
|
* @param WP_Post|int $post (optional) The WP_Post object.
|
|
*
|
|
* @return string Returns the post layout.
|
|
*/
|
|
protected function get_post_layout( $post = null ) {
|
|
|
|
return get_post_meta( $this->get_post_id( $post ), 'primer_layout', true );
|
|
|
|
}
|
|
|
|
/**
|
|
* Return the global layout.
|
|
*
|
|
* @uses [get_theme_mod](https://codex.wordpress.org/Function_Reference/get_theme_mod) To retreive the layout mod.
|
|
*
|
|
* @return string Returns the layout theme modification.
|
|
*/
|
|
public function get_global_layout() {
|
|
|
|
return get_theme_mod( 'layout', $this->default );
|
|
|
|
}
|
|
|
|
/**
|
|
* Return the current layout.
|
|
*
|
|
* @uses get_post_layout
|
|
* @uses get_global_layout
|
|
* @uses layout_exists
|
|
*
|
|
* @param WP_Post|int $post (optional) The WP_Post object.
|
|
*
|
|
* @return string Returns the current layout which is set.
|
|
*/
|
|
public function get_current_layout( $post = null ) {
|
|
|
|
$override = $this->get_post_layout( $post );
|
|
$layout = ( $override ) ? $override : $this->get_global_layout();
|
|
|
|
/**
|
|
* Filter the current layout.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param WP_Post|int|null $post
|
|
*
|
|
* @var string
|
|
*/
|
|
$layout = (string) apply_filters( 'primer_current_layout', $layout, $post );
|
|
|
|
return $this->layout_exists( $layout ) ? $layout : $this->default;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$GLOBALS['primer_customizer_layouts'] = new Primer_Customizer_Layouts;
|