Files
wordpress-preseed/wp-content/plugins/scripts-n-styles/includes/class-sns-meta-box.php
2019-09-11 19:08:46 +02:00

452 lines
20 KiB
PHP

<?php
/**
* SnS_Admin_Meta_Box
*
* Allows WordPress admin users the ability to add custom CSS
* and JavaScript directly to individual Post, Pages or custom
* post types.
*/
class SnS_Admin_Meta_Box
{
/*
* Constants
*/
const NONCE_NAME = 'scripts_n_styles_noncename';
static $post_types;
/**
* Initializing method.
*/
static function init() {
add_action( 'current_screen', array( __CLASS__, 'add_meta_boxes' ) );
add_action( 'save_post', array( __CLASS__, 'save_post' ) );
}
static function mce_buttons_2( $buttons ) {
global $post;
$SnS = get_post_meta( $post->ID, '_SnS', true );
$SnS = is_array( $SnS ) ? $SnS: array();
$styles = isset( $SnS['styles'] ) ? $SnS[ 'styles' ]: array();
if ( ! empty( $styles[ 'classes_mce' ] ) )
array_unshift( $buttons, 'styleselect' );
return $buttons;
}
static function tiny_mce_before_init( $initArray ) {
global $post;
$SnS = get_post_meta( $post->ID, '_SnS', true );
$SnS = is_array( $SnS ) ? $SnS: array();
$styles = isset( $SnS['styles'] ) ? $SnS[ 'styles' ]: array();
// Add div as a format option, should probably use a string replace thing here.
// Better yet, a setting for adding these. Postpone for now.
//$initArray['theme_advanced_blockformats'] = "p,address,pre,h1,h2,h3,h4,h5,h6,div";
if ( ( ! empty( $styles[ 'classes_body' ] ) || ! empty( $styles[ 'classes_post' ] ) ) && ! isset( $initArray['body_class'] ) )
$initArray['body_class'] = '';
// Add body_class (and/or maybe post_class) values... somewhat problematic.
if ( ! empty( $styles[ 'classes_body' ] ) )
$initArray['body_class'] .= ' ' . $styles[ 'classes_body' ];
if ( ! empty( $styles[ 'classes_post' ] ) )
$initArray['body_class'] .= ' ' . $styles[ 'classes_post' ];
// In case Themes or plugins have added style_formats, not tested.
if ( isset( $initArray['style_formats'] ) )
$style_formats = json_decode( $initArray['style_formats'], true );
else
$style_formats = array();
if ( ! empty( $styles[ 'classes_mce' ] ) )
foreach ( $styles[ 'classes_mce' ] as $format )
$style_formats[] = $format;
if ( ! empty( $style_formats ) )
$initArray['style_formats'] = json_encode( $style_formats );
return $initArray;
}
/**
* Admin Action: 'mce_css'
* Adds a styles sheet to TinyMCE via ajax that contains the current styles data.
*/
static function mce_css( $mce_css ) {
$url = admin_url( 'admin-ajax.php' );
$url = wp_nonce_url( $url, 'sns_tinymce_styles' );
$url = add_query_arg( 'post_id', get_the_ID(), $url );
$url = add_query_arg( 'action', 'sns_tinymce_styles', $url );
add_theme_support( 'editor-styles' );
add_editor_style( $url );
return $mce_css;
}
/**
* Admin Action: 'add_meta_boxes'
* Main Meta Box function. Checks restriction options and display options, calls add_meta_box() and adds actions for adding admin CSS and JavaScript.
*/
static function add_meta_boxes() {
if ( current_user_can( 'unfiltered_html' ) ) {
$post_type = get_current_screen()->post_type;
if ( in_array( $post_type, get_post_types( array('show_ui' => true, 'public' => true ) ) ) ) {
add_meta_box( 'SnS_meta_box', __( 'Scripts n Styles', 'scripts-n-styles' ), array( __CLASS__, 'admin_meta_box' ), $post_type, 'normal', 'high' );
add_filter( 'default_hidden_meta_boxes', array( __CLASS__, 'default_hidden_meta_boxes' ) );
add_action( "admin_print_styles", array( __CLASS__, 'meta_box_styles'));
add_action( "admin_print_scripts", array( __CLASS__, 'meta_box_scripts'));
add_filter( 'contextual_help', array( 'SnS_Admin', 'help' ) );
add_filter( 'mce_buttons_2', array( __CLASS__, 'mce_buttons_2' ) );
add_filter( 'tiny_mce_before_init', array( __CLASS__, 'tiny_mce_before_init' ) );
add_filter( 'replace_editor', array( __CLASS__, 'mce_css' ) );
}
}
}
static function default_hidden_meta_boxes( $hidden ) {
$options = get_option( 'SnS_options' );
if ( ! ( isset( $options[ 'metabox' ] ) && 'yes' == $options[ 'metabox' ] ) ) {
$hidden[] = 'SnS_meta_box';
$hidden[] = 'SnS_shortcode';
}
return $hidden;
}
/**
* Admin Action: 'add_meta_boxes'
* Outputs the Meta Box. Only called on callback from add_meta_box() during the add_meta_boxes action.
* @param unknown_type WordPress Post object.
*/
static function admin_meta_box( $post ) {
$registered_handles = Scripts_n_Styles::get_wp_registered();
$SnS = get_post_meta( $post->ID, '_SnS', true );
$SnS = is_array( $SnS ) ? $SnS: array();
$styles = isset( $SnS['styles'] ) ? $SnS[ 'styles' ]: array();
$scripts = isset( $SnS['scripts'] ) ? $SnS[ 'scripts' ]: array();
$html = isset( $SnS['html'] ) ? $SnS[ 'html' ]: array();
$position = get_user_option( "current_sns_tab" );
if ( ! in_array( $position, array( 's0', 's1', 's2', 's3', 's4', 's5', 's6' ) ) ) $position = 's0';
wp_nonce_field( Scripts_n_Styles::$file, self::NONCE_NAME );
?>
<ul class="wp-tab-bar">
<li<?php echo ( 's0' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_scripts-tab"><?php _e( 'Scripts', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's1' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_styles-tab"><?php _e( 'Styles', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's2' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_classes_body-tab"><?php _e( 'Classes', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's3' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_enqueue_scripts-tab"><?php _e( 'Include Scripts', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's4' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_shortcodes-tab"><?php _e( 'Shortcodes', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's5' == $position ) ? ' class="wp-tab-active"': ''; ?> style="display:none"><a href="#SnS_post_styles-tab"><?php _e( 'Dropdown', 'scripts-n-styles' ) ?></a></li>
<li<?php echo ( 's6' == $position ) ? ' class="wp-tab-active"': ''; ?>><a href="#SnS_html-tab"><?php _e( 'HTML', 'scripts-n-styles' ) ?></a></li>
</ul>
<div class="wp-tab-panel" id="SnS_scripts-tab">
<p><em><?php _e( "This code will be included <strong>verbatim</strong> in <code>&lt;script></code> tags at the end of your page's (or post's)", 'scripts-n-styles' ) ?> ...</em></p>
<label for="SnS_scripts_in_head" class="title"><?php _e( '<strong>Scripts</strong> (for the <code>head</code> element):', 'scripts-n-styles' ) ?> </label>
<div class="script">
<textarea class="codemirror js" name="SnS_scripts_in_head" id="SnS_scripts_in_head" rows="5" cols="40" style="width: 98%;"><?php echo isset( $scripts[ 'scripts_in_head' ] ) ? esc_textarea( $scripts[ 'scripts_in_head' ] ) : ''; ?></textarea>
</div>
<p><em>... <code>&lt;/head></code> <?php _e( 'tag', 'scripts-n-styles' ) ?>.</em></p>
<label for="SnS_scripts" class="title"><strong>Scripts</strong>: </label>
<div class="script">
<textarea class="codemirror js" name="SnS_scripts" id="SnS_scripts" rows="5" cols="40" style="width: 98%;"><?php echo isset( $scripts[ 'scripts' ] ) ? esc_textarea( $scripts[ 'scripts' ] ) : ''; ?></textarea>
</div>
<p><em>... <code>&lt;/body></code> <?php _e( 'tag', 'scripts-n-styles' ) ?>.</em></p>
</div>
<div class="wp-tab-panel" id="SnS_styles-tab">
<label for="SnS_styles" class="title"><?php _e( '<strong>Styles</strong>:', 'scripts-n-styles' ) ?> </label>
<div class="style">
<textarea class="codemirror css" name="SnS_styles" id="SnS_styles" rows="5" cols="40" style="width: 98%;"><?php echo isset( $styles[ 'styles' ] ) ? esc_textarea( $styles[ 'styles' ] ) : ''; ?></textarea>
</div>
<p><em><?php _e( 'This code will be included <strong>verbatim</strong> in <code>&lt;style></code> tags in the <code>&lt;head></code> tag of your page (or post).', 'scripts-n-styles' ) ?></em></p>
</div>
<div class="wp-tab-panel" id="SnS_classes_body-tab">
<strong class="title"><?php _e( 'Classes', 'scripts-n-styles' ) ?></strong>
<div id="sns-classes">
<p>
<label for="SnS_classes_body"><?php _e( '<strong>Body Classes</strong>:', 'scripts-n-styles' ) ?> </label>
<input name="SnS_classes_body" id="SnS_classes_body" type="text" class="code" style="width: 99%;"
value="<?php echo isset( $styles[ 'classes_body' ] ) ? esc_attr( $styles[ 'classes_body' ] ) : ''; ?>" />
</p>
<p>
<label for="SnS_classes_post"><strong>Post Classes</strong>: </label>
<input name="SnS_classes_post" id="SnS_classes_post" type="text" class="code" style="width: 99%;"
value="<?php echo isset( $styles[ 'classes_post' ] ) ? esc_attr( $styles[ 'classes_post' ] ) : ''; ?>" />
</p>
<p><em><?php _e( 'These <strong>space separated</strong> class names will be added to the <code>body_class()</code> or <code>post_class()</code> function (provided your theme uses these functions).', 'scripts-n-styles' ) ?></em></p>
</div>
</div>
<?php
/*
* Note: Styles Dropdown section only makes sense when Javascript is enabled. (Otherwise, no TinyMCE.)
*/
?>
<div class="wp-tab-panel" id="SnS_post_styles-tab" style="display: none;">
<strong class="title"><?php _e( 'Post Styles', 'scripts-n-styles' ) ?></strong>
<div id="mce-dropdown-names">
<h4><?php _e( 'The Styles Dropdown', 'scripts-n-styles' ) ?></h4>
<div id="add-mce-dropdown-names">
<p><?php _e( 'Add (or update) a class for the "Styles" drop-down:', 'scripts-n-styles' ) ?></p>
<p class="sns-mce-title">
<label for="SnS_classes_mce_title"><?php _e( 'Title:', 'scripts-n-styles' ) ?></label>
<input name="SnS_classes_mce_title" id="SnS_classes_mce_title"
value="" type="text" class="code" style="width: 80px;" />
</p>
<p class="sns-mce-type">
<label for="SnS_classes_mce_type"><?php _e( 'Type:', 'scripts-n-styles' ) ?></label>
<select name="SnS_classes_mce_type" id="SnS_classes_mce_type" style="width: 80px;">
<option value="inline"><?php _ex( 'Inline', 'css type', 'scripts-n-styles' ) ?></option>
<option value="block"><?php _ex( 'Block', 'css type', 'scripts-n-styles' ) ?></option>
<option value="selector"><?php _ex( 'Selector:', 'css type', 'scripts-n-styles' ) ?></option>
</select>
</p>
<p class="sns-mce-element">
<label for="SnS_classes_mce_element"><?php _e( 'Element:', 'scripts-n-styles' ) ?></label>
<input name="SnS_classes_mce_element" id="SnS_classes_mce_element"
value="" type="text" class="code" style="width: 80px;" />
</p>
<p class="sns-mce-classes">
<label for="SnS_classes_mce_classes"><?php _e( 'Classes:', 'scripts-n-styles' ) ?></label>
<input name="SnS_classes_mce_classes" id="SnS_classes_mce_classes"
value="" type="text" class="code" style="width: 80px;" />
</p>
<p class="sns-mce-wrapper" style="display: none;">
<label for="SnS_classes_mce_wrapper"><?php _e( 'Wrapper:', 'scripts-n-styles' ) ?></label>
<input name="SnS_classes_mce_wrapper" id="SnS_classes_mce_wrapper" type="checkbox" value="true" />
</p>
</div>
<div id="delete-mce-dropdown-names" style="display: none;">
<p id="instructions-mce-dropdown-names"><?php _e( 'Classes currently in the dropdown:', 'scripts-n-styles' ) ?></p>
</div>
</div>
</div>
<div class="wp-tab-panel" id="SnS_enqueue_scripts-tab">
<strong class="title">Include Scripts</strong>
<select name="SnS_enqueue_scripts[]" id="SnS_enqueue_scripts" size="5" multiple="multiple" style="height: auto; float: left; margin: 6px 10px 8px 0;">
<?php
if ( ! empty( $scripts[ 'enqueue_scripts' ] ) && is_array( $scripts[ 'enqueue_scripts' ] ) ) {
foreach ( $registered_handles as $value ) { ?>
<option value="<?php echo esc_attr( $value ) ?>"<?php foreach ( $scripts[ 'enqueue_scripts' ] as $handle ) selected( $handle, $value ); ?>><?php echo esc_html( $value ) ?></option>
<?php }
} else {
foreach ( $registered_handles as $value ) { ?>
<option value="<?php echo esc_attr( $value ) ?>"><?php echo esc_html( $value ) ?></option>
<?php }
} ?>
</select>
<?php if ( ! empty( $scripts[ 'enqueue_scripts' ] ) && is_array( $scripts[ 'enqueue_scripts' ] ) ) { ?>
<p><?php _e( 'Currently Enqueued Scripts:', 'scripts-n-styles' ) ?>
<?php foreach ( $scripts[ 'enqueue_scripts' ] as $handle ) echo '<code>' . esc_html( $handle ) . '</code> '; ?>
</p>
<?php } ?>
<p><em><?php _e( 'The chosen scripts will be enqueued and placed before your codes if your code is dependant on certain scripts (like jQuery).', 'scripts-n-styles' ) ?></em></p>
</div>
<div class="wp-tab-panel" id="SnS_shortcodes-tab">
<strong class="title">Shortcodes</strong>
<div id="sns-add-shortcode">
<?php
$meta_name = 'SnS_shortcodes';
$SnS = get_post_meta( $post->ID, '_SnS', true );
$SnS = is_array( $SnS ) ? $SnS: array();
$shortcodes = isset( $SnS['shortcodes'] ) ? $SnS[ 'shortcodes' ] : array();
?>
<label for="<?php echo $meta_name; ?>">Name: </label>
<input id="<?php echo $meta_name; ?>" name="<?php echo $meta_name . '[new][name]'; ?>" type="text" />
<textarea id="<?php echo $meta_name; ?>_new" class="codemirror htmlmixed" name="<?php echo $meta_name . '[new][value]'; ?>" rows="5" cols="40" style="width: 98%;"></textarea>
</div>
<div id="sns-shortcodes">
<h4>Existing Codes: </h4>
<div id="sns-shortcodes-wrap">
<?php if ( ! empty( $shortcodes ) ) { ?>
<?php foreach ( $shortcodes as $key => $value ) { ?>
<div class="sns-shortcode widget"><div class="inside">
<p>[hoops name="<?php echo $key ?>"]</p>
<textarea class="codemirror htmlmixed" data-sns-shortcode-key="<?php echo $key ?>" name="<?php echo $meta_name . '[existing][' . $key . ']'; ?>" rows="5" cols="40" style="width: 98%;"><?php echo esc_textarea( $value ); ?></textarea>
</div></div>
<?php } ?>
<?php } ?>
</div>
</div>
</div>
<div class="wp-tab-panel" id="SnS_html-tab">
<p><em><?php _e( "<strong>HTML</strong> for the <code>head</code> element", 'scripts-n-styles' ) ?> ...</em></p>
<label for="SnS_html_in_head" class="title"><?php _e( '<strong>HTML</strong> (for the <code>head</code> element):', 'scripts-n-styles' ) ?> </label>
<div class="html">
<textarea class="codemirror html" name="SnS_html_in_head" id="SnS_html_in_head" rows="5" cols="40" style="width: 98%;"><?php echo isset( $html[ 'html_in_head' ] ) ? esc_textarea( $html[ 'html_in_head' ] ) : ''; ?></textarea>
</div>
<p>&nbsp;</p>
<p><em><?php _e( "<strong>HTML</strong> for the <code>bottom of the body</code> element", 'scripts-n-styles' ) ?> ...</em></p>
<label for="SnS_html_in_footer" class="title"><strong><?php _e( '<strong>HTML</strong> (for the <code>bottom of the body</code>):', 'scripts-n-styles' ) ?></strong>: </label>
<div class="html">
<textarea class="codemirror html" name="SnS_html_in_footer" id="SnS_html_in_footer" rows="5" cols="40" style="width: 98%;"><?php echo isset( $html[ 'html_in_footer' ] ) ? esc_textarea( $html[ 'html_in_footer' ] ) : ''; ?></textarea>
</div>
</div>
<?php
}
static function current_classes( $type, $post_id ) {
if ( 'body' == $type ) {
global $wp_query, $pagenow;
if ( 'post-new.php' == $pagenow ) {
echo join( ' ', get_body_class( '', $post_id ) );
echo ' ' . __( '(plus others once saved.)', 'scripts-n-styles' );
return;
}
// This returns more of what actually get used on the theme side.
$save = $wp_query;
$param = ( 'page' == get_post_type( $post_id ) ) ? 'page_id': 'p';
$wp_query = new WP_Query( "$param=$post_id" );
echo join( ' ', get_body_class( '', $post_id ) );
$wp_query = $save;
} else {
echo join( ' ', get_post_class( '', $post_id ) );
}
}
/**
* Admin Action: 'admin_print_styles' Action added during 'add_meta_boxes' (which restricts output to Edit Screens).
* Enqueues the CSS for admin styling of the Meta Box.
*/
static function meta_box_styles() {
wp_enqueue_style( 'chosen' );
wp_enqueue_style( 'sns-meta-box' );
}
/**
* Admin Action: 'admin_print_styles' Action added during 'add_meta_boxes' (which restricts output to Edit Screens).
* Enqueues the JavaScript for the admin Meta Box.
*/
static function meta_box_scripts() {
$options = get_option( 'SnS_options' );
$cm_theme = isset( $options[ 'cm_theme' ] ) ? $options[ 'cm_theme' ] : 'default';
wp_enqueue_script( 'sns-meta-box' );
wp_localize_script( 'sns-meta-box', 'codemirror_options', array( 'theme' => $cm_theme ) );
}
/**
* Admin Action: 'save_post'
* Saves the values entered in the Meta Box when a post is saved (on the Edit Screen only, excluding autosaves) if the user has permission.
* @param int $post_id ID value of the WordPress post.
*/
static function save_post( $post_id ) {
if ( ! isset( $_POST[ self::NONCE_NAME ] ) || ! wp_verify_nonce( $_POST[ self::NONCE_NAME ], Scripts_n_Styles::$file )
|| ! current_user_can( 'unfiltered_html' )
|| wp_is_post_revision( $post_id ) // is needed for get_post_meta compatibility.
|| ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
) return;
/*
NOTE: There is no current_user_can( 'edit_post' ) check here, because as far as I
can tell, in /wp-admin/post.php the calls edit_post(), write_post(), post_preview(),
wp_untrash_post(), etc., the check is already done prior to the 'save_post' action,
which is where this function is called. Other calls are from other pages so the
NONCE covers those cases, and that leaves autosave, which is also checked here.
*/
$SnS = get_post_meta( $post_id, '_SnS', true );
$SnS = is_array( $SnS ) ? $SnS: array(); // automatic array conversion became an error in PHP 7.1
$scripts = isset( $SnS['scripts'] ) ? $SnS[ 'scripts' ]: array();
$styles = isset( $SnS['styles'] ) ? $SnS[ 'styles' ]: array();
$html = isset( $SnS['html'] ) ? $SnS[ 'html' ]: array();
$scripts = self::maybe_set( $scripts, 'scripts_in_head' );
$scripts = self::maybe_set( $scripts, 'scripts' );
$scripts = self::maybe_set( $scripts, 'enqueue_scripts' );
$styles = self::maybe_set( $styles, 'styles' );
$styles = self::maybe_set( $styles, 'classes_body' );
$styles = self::maybe_set( $styles, 'classes_post' );
$html = self::maybe_set( $html, 'html_in_head' );
$html = self::maybe_set( $html, 'html_in_footer' );
$shortcodes = array();
$SnS_shortcodes = isset( $_REQUEST[ 'SnS_shortcodes' ] ) ? $_REQUEST[ 'SnS_shortcodes' ]: array();
$existing_shortcodes = isset( $SnS_shortcodes[ 'existing' ] ) ? $SnS_shortcodes[ 'existing' ]: array();
foreach ( $existing_shortcodes as $key => $value )
if ( ! empty( $value ) )
$shortcodes[ $key ] = $value;
$new_shortcode = isset( $SnS_shortcodes[ 'new' ] ) ? $SnS_shortcodes[ 'new' ]: array();
if ( ! empty( $new_shortcode[ 'value' ] ) ) {
$key = ( isset( $new_shortcode[ 'name' ] ) ) ? $new_shortcode[ 'name' ] : '';
if ( '' == $key ) {
$key = count( $shortcodes );
while ( isset( $shortcodes[ $key ] ) )
$key++;
}
if ( isset( $shortcodes[ $key ] ) ) {
$countr = 1;
while ( isset( $shortcodes[ $key . '_' . $countr ] ) )
$countr++;
$key .= '_' . $countr;
}
$shortcodes[ $key ] = $new_shortcode[ 'value' ];
}
// This one isn't posted, it's ajax only. Cleanup anyway.
if ( isset( $styles[ 'classes_mce' ] ) && empty( $styles[ 'classes_mce' ] ) )
unset( $styles[ 'classes_mce' ] );
if ( empty( $scripts ) ) {
if ( isset( $SnS['scripts'] ) )
unset( $SnS['scripts'] );
} else {
$SnS['scripts'] = $scripts;
}
if ( empty( $styles ) ) {
if ( isset( $SnS['styles'] ) )
unset( $SnS['styles'] );
} else {
$SnS['styles'] = $styles;
}
if ( empty( $html ) ) {
if ( isset( $SnS['html'] ) )
unset( $SnS['html'] );
} else {
$SnS['html'] = $html;
}
if ( empty( $shortcodes ) ) {
if ( isset( $SnS['shortcodes'] ) )
unset( $SnS['shortcodes'] );
} else {
$SnS['shortcodes'] = $shortcodes;
}
if ( empty( $SnS ) )
delete_post_meta( $post_id, '_SnS' );
else
update_post_meta( $post_id, '_SnS', $SnS );
}
/**
* maybe_set()
* Filters $o and Checks if the sent data $i is empty (intended to clear). If not, updates.
*/
static function maybe_set( $o, $i, $p = 'SnS_' ) {
if ( ! is_array( $o ) ) return array();
if ( empty( $_REQUEST[ $p . $i ] ) ) {
if ( isset( $o[ $i ] ) ) unset( $o[ $i ] );
} else {
$o[ $i ] = $_REQUEST[ $p . $i ];
}
return $o;
}
}