+function _wp_admin_html_begin() {
+ global $is_IE;
+
+ $admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : '';
+
+ if ( $is_IE )
+ @header('X-UA-Compatible: IE=edge');
+
+?>
+<!DOCTYPE html>
+<!--[if IE 8]>
+<html xmlns="http://www.w3.org/1999/xhtml" class="ie8 <?php echo $admin_html_class; ?>" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
+<![endif]-->
+<!--[if !(IE 8) ]><!-->
+<html xmlns="http://www.w3.org/1999/xhtml" class="<?php echo $admin_html_class; ?>" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
+<!--<![endif]-->
+<head>
+<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
+<?php
+}
+
+final class WP_Internal_Pointers {
+ /**
+ * Initializes the new feature pointers.
+ *
+ * @since 3.3.0
+ *
+ * All pointers can be disabled using the following:
+ * remove_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) );
+ *
+ * Individual pointers (e.g. wp330_toolbar) can be disabled using the following:
+ * remove_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_wp330_toolbar' ) );
+ */
+ public static function enqueue_scripts( $hook_suffix ) {
+ /*
+ * Register feature pointers
+ * Format: array( hook_suffix => pointer_id )
+ */
+
+ $registered_pointers = array(
+ 'index.php' => 'wp330_toolbar',
+ 'post-new.php' => 'wp350_media',
+ 'post.php' => array( 'wp350_media', 'wp360_revisions' ),
+ 'edit.php' => 'wp360_locks',
+ 'themes.php' => array( 'wp330_saving_widgets', 'wp340_customize_current_theme_link' ),
+ 'appearance_page_custom-header' => 'wp340_choose_image_from_library',
+ 'appearance_page_custom-background' => 'wp340_choose_image_from_library',
+ );
+
+ // Check if screen related pointer is registered
+ if ( empty( $registered_pointers[ $hook_suffix ] ) )
+ return;
+
+ $pointers = (array) $registered_pointers[ $hook_suffix ];
+
+ $caps_required = array(
+ 'wp330_saving_widgets' => array( 'edit_theme_options', 'switch_themes' ),
+ 'wp340_customize_current_theme_link' => array( 'edit_theme_options' ),
+ 'wp340_choose_image_from_library' => array( 'edit_theme_options' ),
+ 'wp350_media' => array( 'upload_files' ),
+ );
+
+ // Get dismissed pointers
+ $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
+
+ $got_pointers = false;
+ foreach ( array_diff( $pointers, $dismissed ) as $pointer ) {
+ if ( isset( $caps_required[ $pointer ] ) ) {
+ foreach ( $caps_required[ $pointer ] as $cap ) {
+ if ( ! current_user_can( $cap ) )
+ continue 2;
+ }
+ }
+
+ // Bind pointer print function
+ add_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_' . $pointer ) );
+ $got_pointers = true;
+ }
+
+ if ( ! $got_pointers )
+ return;
+
+ // Add pointers script and style to queue
+ wp_enqueue_style( 'wp-pointer' );
+ wp_enqueue_script( 'wp-pointer' );
+ }
+
+ /**
+ * Print the pointer javascript data.
+ *
+ * @since 3.3.0
+ *
+ * @param string $pointer_id The pointer ID.
+ * @param string $selector The HTML elements, on which the pointer should be attached.
+ * @param array $args Arguments to be passed to the pointer JS (see wp-pointer.js).
+ */
+ private static function print_js( $pointer_id, $selector, $args ) {
+ if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) )
+ return;
+
+ ?>
+ <script type="text/javascript">
+ //<![CDATA[
+ (function($){
+ var options = <?php echo json_encode( $args ); ?>, setup;
+
+ if ( ! options )
+ return;
+
+ options = $.extend( options, {
+ close: function() {
+ $.post( ajaxurl, {
+ pointer: '<?php echo $pointer_id; ?>',
+ action: 'dismiss-wp-pointer'
+ });
+ }
+ });
+
+ setup = function() {
+ $('<?php echo $selector; ?>').first().pointer( options ).pointer('open');
+ };
+
+ if ( options.position && options.position.defer_loading )
+ $(window).bind( 'load.wp-pointers', setup );
+ else
+ $(document).ready( setup );
+
+ })( jQuery );
+ //]]>
+ </script>
+ <?php
+ }
+
+ public static function pointer_wp330_toolbar() {
+ $content = '<h3>' . __( 'New Feature: Toolbar' ) . '</h3>';
+ $content .= '<p>' . __( 'We’ve combined the admin bar and the old Dashboard header into one persistent toolbar. Hover over the toolbar items to see what’s new.' ) . '</p>';
+
+ if ( is_multisite() && is_super_admin() )
+ $content .= '<p>' . __( 'Network Admin is now located in the My Sites menu.' ) . '</p>';
+
+ WP_Internal_Pointers::print_js( 'wp330_toolbar', '#wpadminbar', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => 'top', 'align' => 'center' ),
+ ) );
+ }
+
+ /**
+ * Print 'Updated Media Uploader' for 3.3.0.
+ *
+ * @since 3.3.0
+ */
+ public static function pointer_wp330_media_uploader() {}
+
+ /**
+ * Print 'New Feature: Saving Widgets' for 3.3.0.
+ *
+ * @since 3.3.0
+ */
+ public static function pointer_wp330_saving_widgets() {
+ $content = '<h3>' . __( 'New Feature: Saving Widgets' ) . '</h3>';
+ $content .= '<p>' . __( 'If you change your mind and revert to your previous theme, we’ll put the widgets back the way you had them.' ) . '</p>';
+
+ WP_Internal_Pointers::print_js( 'wp330_saving_widgets', '#message2', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left' ),
+ ) );
+ }
+
+ /**
+ * Print 'New Feature: Current Theme Customize Link' for 3.4.0.
+ *
+ * @since 3.4.0
+ */
+ public static function pointer_wp340_customize_current_theme_link() {
+ $content = '<h3>' . __( 'New Feature: Customizer' ) . '</h3>';
+ $content .= '<p>' . __( 'Click Customize to change the header, background, title and menus of the current theme, all in one place.' ) . '</p>';
+ $content .= '<p>' . __( 'Click the Live Preview links in the Available Themes list below to customize and preview another theme before activating it.' ) . '</p>';
+
+ WP_Internal_Pointers::print_js( 'wp340_customize_current_theme_link', '#customize-current-theme-link', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'offset' => is_rtl() ? '32 0' : '-32 0' ),
+ ) );
+ }
+
+ /**
+ * Print 'New Feature: Choose Image from Library' for 3.4.0.
+ *
+ * @since 3.4.0
+ */
+ public static function pointer_wp340_choose_image_from_library() {
+ $content = '<h3>' . __( 'New Feature: Choose Image from Library' ) . '</h3>';
+ $content .= '<p>' . __( 'Want to use an image you uploaded earlier? Select it from your media library instead of uploading it again.' ) . '</p>';
+
+ WP_Internal_Pointers::print_js( 'wp340_choose_image_from_library', '#choose-from-library-link', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'defer_loading' => true ),
+ ) );
+ }
+
+ public static function pointer_wp350_media() {
+ $content = '<h3>' . __( 'New Media Manager' ) . '</h3>';
+ $content .= '<p>' . __( 'Uploading files and creating image galleries has a whole new look. Check it out!' ) . '</p>';
+
+ self::print_js( 'wp350_media', '.insert-media', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => is_rtl() ? 'right' : 'left', 'align' => 'center' ),
+ ) );
+ }
+
+ public static function pointer_wp360_revisions() {
+ $content = '<h3>' . __( 'Compare Revisions' ) . '</h3>';
+ $content .= '<p>' . __( 'View, compare, and restore other versions of this content on the improved revisions screen.' ) . '</p>';
+
+ self::print_js( 'wp360_revisions', '.misc-pub-section.misc-pub-revisions', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => is_rtl() ? 'left' : 'right', 'align' => 'center', 'my' => is_rtl() ? 'left' : 'right-14px' ),
+ ) );
+ }
+
+ public static function pointer_wp360_locks() {
+ $content = '<h3>' . __( 'Edit Lock' ) . '</h3>';
+ $content .= '<p>' . __( 'Someone else is editing this. No need to refresh; the lock will disappear when they’re done.' ) . '</p>';
+
+ if ( ! is_multi_author() )
+ return;
+
+ self::print_js( 'wp360_locks', 'tr.wp-locked .locked-indicator', array(
+ 'content' => $content,
+ 'position' => array( 'edge' => 'left', 'align' => 'left' ),
+ ) );
+ }
+
+ /**
+ * Prevents new users from seeing existing 'new feature' pointers.
+ *
+ * @since 3.3.0
+ */
+ public static function dismiss_pointers_for_new_users( $user_id ) {
+ add_user_meta( $user_id, 'dismissed_wp_pointers', 'wp330_toolbar,wp330_saving_widgets,wp340_choose_image_from_library,wp340_customize_current_theme_link,wp350_media,wp360_revisions,wp360_locks' );
+ }
+}
+
+add_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) );
+add_action( 'user_register', array( 'WP_Internal_Pointers', 'dismiss_pointers_for_new_users' ) );
+
+/**
+ * Convert a screen string to a screen object
+ *
+ * @since 3.0.0
+ *
+ * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen.
+ * @return WP_Screen Screen object.
+ */
+function convert_to_screen( $hook_name ) {
+ if ( ! class_exists( 'WP_Screen' ) ) {
+ _doing_it_wrong( 'convert_to_screen(), add_meta_box()', __( "Likely direct inclusion of wp-admin/includes/template.php in order to use add_meta_box(). This is very wrong. Hook the add_meta_box() call into the add_meta_boxes action instead." ), '3.3' );
+ return (object) array( 'id' => '_invalid', 'base' => '_are_belong_to_us' );
+ }
+
+ return WP_Screen::get( $hook_name );
+}
+
+/**
+ * Output the HTML for restoring the post data from DOM storage
+ *
+ * @since 3.6
+ * @access private
+ */
+function _local_storage_notice() {
+ ?>
+ <div id="local-storage-notice" class="hidden">
+ <p class="local-restore">
+ <?php _e('The backup of this post in your browser is different from the version below.'); ?>
+ <a class="restore-backup" href="#"><?php _e('Restore the backup.'); ?></a>
+ </p>
+ <p class="undo-restore hidden">
+ <?php _e('Post restored successfully.'); ?>
+ <a class="undo-restore-backup" href="#"><?php _e('Undo.'); ?></a>
+ </p>
+ </div>
+ <?php
+}
+
+/**
+ * Output a HTML element with a star rating for a given rating.
+ *
+ * Outputs a HTML element with the star rating exposed on a 0..5 scale in
+ * half star increments (ie. 1, 1.5, 2 stars). Optionally, if specified, the
+ * number of ratings may also be displayed by passing the $number parameter.
+ *
+ * @since 3.8.0
+ * @param array $args {
+ * Optional. Array of star ratings arguments.
+ *
+ * @type int $rating The rating to display, expressed in either a 0.5 rating increment,
+ * or percentage. Default 0.
+ * @type string $type Format that the $rating is in. Valid values are 'rating' (default),
+ * or, 'percent'. Default 'rating'.
+ * @type int $number The number of ratings that makes up this rating. Default 0.
+ * }
+ */
+function wp_star_rating( $args = array() ) {
+ $defaults = array(
+ 'rating' => 0,
+ 'type' => 'rating',
+ 'number' => 0,
+ );
+ $r = wp_parse_args( $args, $defaults );
+ extract( $r, EXTR_SKIP );
+
+ // Non-english decimal places when the $rating is coming from a string
+ $rating = str_replace( ',', '.', $rating );
+
+ // Convert Percentage to star rating, 0..5 in .5 increments
+ if ( 'percent' == $type ) {
+ $rating = round( $rating / 10, 0 ) / 2;
+ }
+
+ // Calculate the number of each type of star needed
+ $full_stars = floor( $rating );
+ $half_stars = ceil( $rating - $full_stars );
+ $empty_stars = 5 - $full_stars - $half_stars;
+
+ if ( $number ) {
+ /* translators: 1: The rating, 2: The number of ratings */
+ $title = _n( '%1$s rating based on %2$s rating', '%1$s rating based on %2$s ratings', $number );
+ $title = sprintf( $title, number_format_i18n( $rating, 1 ), number_format_i18n( $number ) );
+ } else {
+ /* translators: 1: The rating */
+ $title = sprintf( __( '%s rating' ), number_format_i18n( $rating, 1 ) );
+ }
+
+ echo '<div class="star-rating" title="' . esc_attr( $title ) . '">';
+ echo str_repeat( '<div class="star star-full"></div>', $full_stars );
+ echo str_repeat( '<div class="star star-half"></div>', $half_stars );
+ echo str_repeat( '<div class="star star-empty"></div>', $empty_stars);
+ echo '</div>';
+}
\ No newline at end of file