+function _wp_admin_html_begin() {
+ $admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : '';
+?>
+<!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; ?>').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.num-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
+}