[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/includes/ -> template.php (source)

   1  <?php
   2  /**
   3   * Template WordPress Administration API.
   4   *
   5   * A Big Mess. Also some neat functions that are nicely written.
   6   *
   7   * @package WordPress
   8   * @subpackage Administration
   9   */
  10  
  11  /** Walker_Category_Checklist class */
  12  require_once( ABSPATH . 'wp-admin/includes/class-walker-category-checklist.php' );
  13  
  14  /** WP_Internal_Pointers class */
  15  require_once( ABSPATH . 'wp-admin/includes/class-wp-internal-pointers.php' );
  16  
  17  //
  18  // Category Checklists
  19  //
  20  
  21  /**
  22   * Output an unordered list of checkbox input elements labeled with category names.
  23   *
  24   * @since 2.5.1
  25   *
  26   * @see wp_terms_checklist()
  27   *
  28   * @param int    $post_id              Optional. Post to generate a categories checklist for. Default 0.
  29   *                                     $selected_cats must not be an array. Default 0.
  30   * @param int    $descendants_and_self Optional. ID of the category to output along with its descendants.
  31   *                                     Default 0.
  32   * @param int[]  $selected_cats        Optional. Array of category IDs to mark as checked. Default false.
  33   * @param int[]  $popular_cats         Optional. Array of category IDs to receive the "popular-category" class.
  34   *                                     Default false.
  35   * @param Walker $walker               Optional. Walker object to use to build the output.
  36   *                                     Default is a Walker_Category_Checklist instance.
  37   * @param bool   $checked_ontop        Optional. Whether to move checked items out of the hierarchy and to
  38   *                                     the top of the list. Default true.
  39   */
  40  function wp_category_checklist( $post_id = 0, $descendants_and_self = 0, $selected_cats = false, $popular_cats = false, $walker = null, $checked_ontop = true ) {
  41      wp_terms_checklist(
  42          $post_id,
  43          array(
  44              'taxonomy'             => 'category',
  45              'descendants_and_self' => $descendants_and_self,
  46              'selected_cats'        => $selected_cats,
  47              'popular_cats'         => $popular_cats,
  48              'walker'               => $walker,
  49              'checked_ontop'        => $checked_ontop,
  50          )
  51      );
  52  }
  53  
  54  /**
  55   * Output an unordered list of checkbox input elements labelled with term names.
  56   *
  57   * Taxonomy-independent version of wp_category_checklist().
  58   *
  59   * @since 3.0.0
  60   * @since 4.4.0 Introduced the `$echo` argument.
  61   *
  62   * @param int          $post_id Optional. Post ID. Default 0.
  63   * @param array|string $args {
  64   *     Optional. Array or string of arguments for generating a terms checklist. Default empty array.
  65   *
  66   *     @type int    $descendants_and_self ID of the category to output along with its descendants.
  67   *                                        Default 0.
  68   *     @type int[]  $selected_cats        Array of category IDs to mark as checked. Default false.
  69   *     @type int[]  $popular_cats         Array of category IDs to receive the "popular-category" class.
  70   *                                        Default false.
  71   *     @type Walker $walker               Walker object to use to build the output.
  72   *                                        Default is a Walker_Category_Checklist instance.
  73   *     @type string $taxonomy             Taxonomy to generate the checklist for. Default 'category'.
  74   *     @type bool   $checked_ontop        Whether to move checked items out of the hierarchy and to
  75   *                                        the top of the list. Default true.
  76   *     @type bool   $echo                 Whether to echo the generated markup. False to return the markup instead
  77   *                                        of echoing it. Default true.
  78   * }
  79   * @return string HTML list of input elements.
  80   */
  81  function wp_terms_checklist( $post_id = 0, $args = array() ) {
  82      $defaults = array(
  83          'descendants_and_self' => 0,
  84          'selected_cats'        => false,
  85          'popular_cats'         => false,
  86          'walker'               => null,
  87          'taxonomy'             => 'category',
  88          'checked_ontop'        => true,
  89          'echo'                 => true,
  90      );
  91  
  92      /**
  93       * Filters the taxonomy terms checklist arguments.
  94       *
  95       * @since 3.4.0
  96       *
  97       * @see wp_terms_checklist()
  98       *
  99       * @param array $args    An array of arguments.
 100       * @param int   $post_id The post ID.
 101       */
 102      $params = apply_filters( 'wp_terms_checklist_args', $args, $post_id );
 103  
 104      $parsed_args = wp_parse_args( $params, $defaults );
 105  
 106      if ( empty( $parsed_args['walker'] ) || ! ( $parsed_args['walker'] instanceof Walker ) ) {
 107          $walker = new Walker_Category_Checklist;
 108      } else {
 109          $walker = $parsed_args['walker'];
 110      }
 111  
 112      $taxonomy             = $parsed_args['taxonomy'];
 113      $descendants_and_self = (int) $parsed_args['descendants_and_self'];
 114  
 115      $args = array( 'taxonomy' => $taxonomy );
 116  
 117      $tax              = get_taxonomy( $taxonomy );
 118      $args['disabled'] = ! current_user_can( $tax->cap->assign_terms );
 119  
 120      $args['list_only'] = ! empty( $parsed_args['list_only'] );
 121  
 122      if ( is_array( $parsed_args['selected_cats'] ) ) {
 123          $args['selected_cats'] = $parsed_args['selected_cats'];
 124      } elseif ( $post_id ) {
 125          $args['selected_cats'] = wp_get_object_terms( $post_id, $taxonomy, array_merge( $args, array( 'fields' => 'ids' ) ) );
 126      } else {
 127          $args['selected_cats'] = array();
 128      }
 129  
 130      if ( is_array( $parsed_args['popular_cats'] ) ) {
 131          $args['popular_cats'] = $parsed_args['popular_cats'];
 132      } else {
 133          $args['popular_cats'] = get_terms(
 134              array(
 135                  'taxonomy'     => $taxonomy,
 136                  'fields'       => 'ids',
 137                  'orderby'      => 'count',
 138                  'order'        => 'DESC',
 139                  'number'       => 10,
 140                  'hierarchical' => false,
 141              )
 142          );
 143      }
 144  
 145      if ( $descendants_and_self ) {
 146          $categories = (array) get_terms(
 147              array(
 148                  'taxonomy'     => $taxonomy,
 149                  'child_of'     => $descendants_and_self,
 150                  'hierarchical' => 0,
 151                  'hide_empty'   => 0,
 152              )
 153          );
 154          $self       = get_term( $descendants_and_self, $taxonomy );
 155          array_unshift( $categories, $self );
 156      } else {
 157          $categories = (array) get_terms(
 158              array(
 159                  'taxonomy' => $taxonomy,
 160                  'get'      => 'all',
 161              )
 162          );
 163      }
 164  
 165      $output = '';
 166  
 167      if ( $parsed_args['checked_ontop'] ) {
 168          // Post process $categories rather than adding an exclude to the get_terms() query to keep the query the same across all posts (for any query cache)
 169          $checked_categories = array();
 170          $keys               = array_keys( $categories );
 171  
 172          foreach ( $keys as $k ) {
 173              if ( in_array( $categories[ $k ]->term_id, $args['selected_cats'] ) ) {
 174                  $checked_categories[] = $categories[ $k ];
 175                  unset( $categories[ $k ] );
 176              }
 177          }
 178  
 179          // Put checked cats on top
 180          $output .= $walker->walk( $checked_categories, 0, $args );
 181      }
 182      // Then the rest of them
 183      $output .= $walker->walk( $categories, 0, $args );
 184  
 185      if ( $parsed_args['echo'] ) {
 186          echo $output;
 187      }
 188  
 189      return $output;
 190  }
 191  
 192  /**
 193   * Retrieve a list of the most popular terms from the specified taxonomy.
 194   *
 195   * If the $echo argument is true then the elements for a list of checkbox
 196   * `<input>` elements labelled with the names of the selected terms is output.
 197   * If the $post_ID global isn't empty then the terms associated with that
 198   * post will be marked as checked.
 199   *
 200   * @since 2.5.0
 201   *
 202   * @param string $taxonomy Taxonomy to retrieve terms from.
 203   * @param int    $default  Not used.
 204   * @param int    $number   Number of terms to retrieve. Defaults to 10.
 205   * @param bool   $echo     Optionally output the list as well. Defaults to true.
 206   * @return int[] Array of popular term IDs.
 207   */
 208  function wp_popular_terms_checklist( $taxonomy, $default = 0, $number = 10, $echo = true ) {
 209      $post = get_post();
 210  
 211      if ( $post && $post->ID ) {
 212          $checked_terms = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
 213      } else {
 214          $checked_terms = array();
 215      }
 216  
 217      $terms = get_terms(
 218          array(
 219              'taxonomy'     => $taxonomy,
 220              'orderby'      => 'count',
 221              'order'        => 'DESC',
 222              'number'       => $number,
 223              'hierarchical' => false,
 224          )
 225      );
 226  
 227      $tax = get_taxonomy( $taxonomy );
 228  
 229      $popular_ids = array();
 230      foreach ( (array) $terms as $term ) {
 231          $popular_ids[] = $term->term_id;
 232          if ( ! $echo ) { // Hack for Ajax use.
 233              continue;
 234          }
 235          $id      = "popular-$taxonomy-$term->term_id";
 236          $checked = in_array( $term->term_id, $checked_terms ) ? 'checked="checked"' : '';
 237          ?>
 238  
 239          <li id="<?php echo $id; ?>" class="popular-category">
 240              <label class="selectit">
 241                  <input id="in-<?php echo $id; ?>" type="checkbox" <?php echo $checked; ?> value="<?php echo (int) $term->term_id; ?>" <?php disabled( ! current_user_can( $tax->cap->assign_terms ) ); ?> />
 242                  <?php
 243                  /** This filter is documented in wp-includes/category-template.php */
 244                  echo esc_html( apply_filters( 'the_category', $term->name, '', '' ) );
 245                  ?>
 246              </label>
 247          </li>
 248  
 249          <?php
 250      }
 251      return $popular_ids;
 252  }
 253  
 254  /**
 255   * Outputs a link category checklist element.
 256   *
 257   * @since 2.5.1
 258   *
 259   * @param int $link_id
 260   */
 261  function wp_link_category_checklist( $link_id = 0 ) {
 262      $default = 1;
 263  
 264      $checked_categories = array();
 265  
 266      if ( $link_id ) {
 267          $checked_categories = wp_get_link_cats( $link_id );
 268          // No selected categories, strange
 269          if ( ! count( $checked_categories ) ) {
 270              $checked_categories[] = $default;
 271          }
 272      } else {
 273          $checked_categories[] = $default;
 274      }
 275  
 276      $categories = get_terms(
 277          array(
 278              'taxonomy'   => 'link_category',
 279              'orderby'    => 'name',
 280              'hide_empty' => 0,
 281          )
 282      );
 283  
 284      if ( empty( $categories ) ) {
 285          return;
 286      }
 287  
 288      foreach ( $categories as $category ) {
 289          $cat_id = $category->term_id;
 290  
 291          /** This filter is documented in wp-includes/category-template.php */
 292          $name    = esc_html( apply_filters( 'the_category', $category->name, '', '' ) );
 293          $checked = in_array( $cat_id, $checked_categories ) ? ' checked="checked"' : '';
 294          echo '<li id="link-category-', $cat_id, '"><label for="in-link-category-', $cat_id, '" class="selectit"><input value="', $cat_id, '" type="checkbox" name="link_category[]" id="in-link-category-', $cat_id, '"', $checked, '/> ', $name, '</label></li>';
 295      }
 296  }
 297  
 298  /**
 299   * Adds hidden fields with the data for use in the inline editor for posts and pages.
 300   *
 301   * @since 2.7.0
 302   *
 303   * @param WP_Post $post Post object.
 304   */
 305  function get_inline_data( $post ) {
 306      $post_type_object = get_post_type_object( $post->post_type );
 307      if ( ! current_user_can( 'edit_post', $post->ID ) ) {
 308          return;
 309      }
 310  
 311      $title = esc_textarea( trim( $post->post_title ) );
 312  
 313      echo '
 314  <div class="hidden" id="inline_' . $post->ID . '">
 315      <div class="post_title">' . $title . '</div>' .
 316      /** This filter is documented in wp-admin/edit-tag-form.php */
 317      '<div class="post_name">' . apply_filters( 'editable_slug', $post->post_name, $post ) . '</div>
 318      <div class="post_author">' . $post->post_author . '</div>
 319      <div class="comment_status">' . esc_html( $post->comment_status ) . '</div>
 320      <div class="ping_status">' . esc_html( $post->ping_status ) . '</div>
 321      <div class="_status">' . esc_html( $post->post_status ) . '</div>
 322      <div class="jj">' . mysql2date( 'd', $post->post_date, false ) . '</div>
 323      <div class="mm">' . mysql2date( 'm', $post->post_date, false ) . '</div>
 324      <div class="aa">' . mysql2date( 'Y', $post->post_date, false ) . '</div>
 325      <div class="hh">' . mysql2date( 'H', $post->post_date, false ) . '</div>
 326      <div class="mn">' . mysql2date( 'i', $post->post_date, false ) . '</div>
 327      <div class="ss">' . mysql2date( 's', $post->post_date, false ) . '</div>
 328      <div class="post_password">' . esc_html( $post->post_password ) . '</div>';
 329  
 330      if ( $post_type_object->hierarchical ) {
 331          echo '<div class="post_parent">' . $post->post_parent . '</div>';
 332      }
 333  
 334      echo '<div class="page_template">' . ( $post->page_template ? esc_html( $post->page_template ) : 'default' ) . '</div>';
 335  
 336      if ( post_type_supports( $post->post_type, 'page-attributes' ) ) {
 337          echo '<div class="menu_order">' . $post->menu_order . '</div>';
 338      }
 339  
 340      $taxonomy_names = get_object_taxonomies( $post->post_type );
 341      foreach ( $taxonomy_names as $taxonomy_name ) {
 342          $taxonomy = get_taxonomy( $taxonomy_name );
 343  
 344          if ( $taxonomy->hierarchical && $taxonomy->show_ui ) {
 345  
 346              $terms = get_object_term_cache( $post->ID, $taxonomy_name );
 347              if ( false === $terms ) {
 348                  $terms = wp_get_object_terms( $post->ID, $taxonomy_name );
 349                  wp_cache_add( $post->ID, wp_list_pluck( $terms, 'term_id' ), $taxonomy_name . '_relationships' );
 350              }
 351              $term_ids = empty( $terms ) ? array() : wp_list_pluck( $terms, 'term_id' );
 352  
 353              echo '<div class="post_category" id="' . $taxonomy_name . '_' . $post->ID . '">' . implode( ',', $term_ids ) . '</div>';
 354  
 355          } elseif ( $taxonomy->show_ui ) {
 356  
 357              $terms_to_edit = get_terms_to_edit( $post->ID, $taxonomy_name );
 358              if ( ! is_string( $terms_to_edit ) ) {
 359                  $terms_to_edit = '';
 360              }
 361  
 362              echo '<div class="tags_input" id="' . $taxonomy_name . '_' . $post->ID . '">'
 363                  . esc_html( str_replace( ',', ', ', $terms_to_edit ) ) . '</div>';
 364  
 365          }
 366      }
 367  
 368      if ( ! $post_type_object->hierarchical ) {
 369          echo '<div class="sticky">' . ( is_sticky( $post->ID ) ? 'sticky' : '' ) . '</div>';
 370      }
 371  
 372      if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
 373          echo '<div class="post_format">' . esc_html( get_post_format( $post->ID ) ) . '</div>';
 374      }
 375  
 376      /**
 377       * Fires after outputting the fields for the inline editor for posts and pages.
 378       *
 379       * @since 4.9.8
 380       *
 381       * @param WP_Post      $post             The current post object.
 382       * @param WP_Post_Type $post_type_object The current post's post type object.
 383       */
 384      do_action( 'add_inline_data', $post, $post_type_object );
 385  
 386      echo '</div>';
 387  }
 388  
 389  /**
 390   * Outputs the in-line comment reply-to form in the Comments list table.
 391   *
 392   * @since 2.7.0
 393   *
 394   * @global WP_List_Table $wp_list_table
 395   *
 396   * @param int    $position
 397   * @param bool   $checkbox
 398   * @param string $mode
 399   * @param bool   $table_row
 400   */
 401  function wp_comment_reply( $position = 1, $checkbox = false, $mode = 'single', $table_row = true ) {
 402      global $wp_list_table;
 403      /**
 404       * Filters the in-line comment reply-to form output in the Comments
 405       * list table.
 406       *
 407       * Returning a non-empty value here will short-circuit display
 408       * of the in-line comment-reply form in the Comments list table,
 409       * echoing the returned value instead.
 410       *
 411       * @since 2.7.0
 412       *
 413       * @see wp_comment_reply()
 414       *
 415       * @param string $content The reply-to form content.
 416       * @param array  $args    An array of default args.
 417       */
 418      $content = apply_filters(
 419          'wp_comment_reply',
 420          '',
 421          array(
 422              'position' => $position,
 423              'checkbox' => $checkbox,
 424              'mode'     => $mode,
 425          )
 426      );
 427  
 428      if ( ! empty( $content ) ) {
 429          echo $content;
 430          return;
 431      }
 432  
 433      if ( ! $wp_list_table ) {
 434          if ( $mode == 'single' ) {
 435              $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table' );
 436          } else {
 437              $wp_list_table = _get_list_table( 'WP_Comments_List_Table' );
 438          }
 439      }
 440  
 441      ?>
 442  <form method="get">
 443      <?php if ( $table_row ) : ?>
 444  <table style="display:none;"><tbody id="com-reply"><tr id="replyrow" class="inline-edit-row" style="display:none;"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="colspanchange">
 445  <?php else : ?>
 446  <div id="com-reply" style="display:none;"><div id="replyrow" style="display:none;">
 447  <?php endif; ?>
 448      <fieldset class="comment-reply">
 449      <legend>
 450          <span class="hidden" id="editlegend"><?php _e( 'Edit Comment' ); ?></span>
 451          <span class="hidden" id="replyhead"><?php _e( 'Reply to Comment' ); ?></span>
 452          <span class="hidden" id="addhead"><?php _e( 'Add new Comment' ); ?></span>
 453      </legend>
 454  
 455      <div id="replycontainer">
 456      <label for="replycontent" class="screen-reader-text"><?php _e( 'Comment' ); ?></label>
 457      <?php
 458      $quicktags_settings = array( 'buttons' => 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' );
 459      wp_editor(
 460          '',
 461          'replycontent',
 462          array(
 463              'media_buttons' => false,
 464              'tinymce'       => false,
 465              'quicktags'     => $quicktags_settings,
 466          )
 467      );
 468      ?>
 469      </div>
 470  
 471      <div id="edithead" style="display:none;">
 472          <div class="inside">
 473          <label for="author-name"><?php _e( 'Name' ); ?></label>
 474          <input type="text" name="newcomment_author" size="50" value="" id="author-name" />
 475          </div>
 476  
 477          <div class="inside">
 478          <label for="author-email"><?php _e( 'Email' ); ?></label>
 479          <input type="text" name="newcomment_author_email" size="50" value="" id="author-email" />
 480          </div>
 481  
 482          <div class="inside">
 483          <label for="author-url"><?php _e( 'URL' ); ?></label>
 484          <input type="text" id="author-url" name="newcomment_author_url" class="code" size="103" value="" />
 485          </div>
 486      </div>
 487  
 488      <div id="replysubmit" class="submit">
 489          <p class="reply-submit-buttons">
 490              <button type="button" class="save button button-primary">
 491                  <span id="addbtn" style="display: none;"><?php _e( 'Add Comment' ); ?></span>
 492                  <span id="savebtn" style="display: none;"><?php _e( 'Update Comment' ); ?></span>
 493                  <span id="replybtn" style="display: none;"><?php _e( 'Submit Reply' ); ?></span>
 494              </button>
 495              <button type="button" class="cancel button"><?php _e( 'Cancel' ); ?></button>
 496              <span class="waiting spinner"></span>
 497          </p>
 498          <div class="notice notice-error notice-alt inline hidden">
 499              <p class="error"></p>
 500          </div>
 501      </div>
 502  
 503      <input type="hidden" name="action" id="action" value="" />
 504      <input type="hidden" name="comment_ID" id="comment_ID" value="" />
 505      <input type="hidden" name="comment_post_ID" id="comment_post_ID" value="" />
 506      <input type="hidden" name="status" id="status" value="" />
 507      <input type="hidden" name="position" id="position" value="<?php echo $position; ?>" />
 508      <input type="hidden" name="checkbox" id="checkbox" value="<?php echo $checkbox ? 1 : 0; ?>" />
 509      <input type="hidden" name="mode" id="mode" value="<?php echo esc_attr( $mode ); ?>" />
 510      <?php
 511          wp_nonce_field( 'replyto-comment', '_ajax_nonce-replyto-comment', false );
 512      if ( current_user_can( 'unfiltered_html' ) ) {
 513          wp_nonce_field( 'unfiltered-html-comment', '_wp_unfiltered_html_comment', false );
 514      }
 515      ?>
 516      </fieldset>
 517      <?php if ( $table_row ) : ?>
 518  </td></tr></tbody></table>
 519      <?php else : ?>
 520  </div></div>
 521      <?php endif; ?>
 522  </form>
 523      <?php
 524  }
 525  
 526  /**
 527   * Output 'undo move to trash' text for comments
 528   *
 529   * @since 2.9.0
 530   */
 531  function wp_comment_trashnotice() {
 532      ?>
 533  <div class="hidden" id="trash-undo-holder">
 534      <div class="trash-undo-inside">
 535          <?php
 536          /* translators: %s: Comment author, filled by AJAX. */
 537          printf( __( 'Comment by %s moved to the trash.' ), '<strong></strong>' );
 538          ?>
 539          <span class="undo untrash"><a href="#"><?php _e( 'Undo' ); ?></a></span>
 540      </div>
 541  </div>
 542  <div class="hidden" id="spam-undo-holder">
 543      <div class="spam-undo-inside">
 544          <?php
 545          /* translators: %s: Comment author, filled by AJAX. */
 546          printf( __( 'Comment by %s marked as spam.' ), '<strong></strong>' );
 547          ?>
 548          <span class="undo unspam"><a href="#"><?php _e( 'Undo' ); ?></a></span>
 549      </div>
 550  </div>
 551      <?php
 552  }
 553  
 554  /**
 555   * Outputs a post's public meta data in the Custom Fields meta box.
 556   *
 557   * @since 1.2.0
 558   *
 559   * @param array $meta
 560   */
 561  function list_meta( $meta ) {
 562      // Exit if no meta
 563      if ( ! $meta ) {
 564          echo '
 565  <table id="list-table" style="display: none;">
 566      <thead>
 567      <tr>
 568          <th class="left">' . _x( 'Name', 'meta name' ) . '</th>
 569          <th>' . __( 'Value' ) . '</th>
 570      </tr>
 571      </thead>
 572      <tbody id="the-list" data-wp-lists="list:meta">
 573      <tr><td></td></tr>
 574      </tbody>
 575  </table>'; //TBODY needed for list-manipulation JS
 576          return;
 577      }
 578      $count = 0;
 579      ?>
 580  <table id="list-table">
 581      <thead>
 582      <tr>
 583          <th class="left"><?php _ex( 'Name', 'meta name' ); ?></th>
 584          <th><?php _e( 'Value' ); ?></th>
 585      </tr>
 586      </thead>
 587      <tbody id='the-list' data-wp-lists='list:meta'>
 588      <?php
 589      foreach ( $meta as $entry ) {
 590          echo _list_meta_row( $entry, $count );
 591      }
 592      ?>
 593      </tbody>
 594  </table>
 595      <?php
 596  }
 597  
 598  /**
 599   * Outputs a single row of public meta data in the Custom Fields meta box.
 600   *
 601   * @since 2.5.0
 602   *
 603   * @staticvar string $update_nonce
 604   *
 605   * @param array $entry
 606   * @param int   $count
 607   * @return string
 608   */
 609  function _list_meta_row( $entry, &$count ) {
 610      static $update_nonce = '';
 611  
 612      if ( is_protected_meta( $entry['meta_key'], 'post' ) ) {
 613          return '';
 614      }
 615  
 616      if ( ! $update_nonce ) {
 617          $update_nonce = wp_create_nonce( 'add-meta' );
 618      }
 619  
 620      $r = '';
 621      ++ $count;
 622  
 623      if ( is_serialized( $entry['meta_value'] ) ) {
 624          if ( is_serialized_string( $entry['meta_value'] ) ) {
 625              // This is a serialized string, so we should display it.
 626              $entry['meta_value'] = maybe_unserialize( $entry['meta_value'] );
 627          } else {
 628              // This is a serialized array/object so we should NOT display it.
 629              --$count;
 630              return '';
 631          }
 632      }
 633  
 634      $entry['meta_key']   = esc_attr( $entry['meta_key'] );
 635      $entry['meta_value'] = esc_textarea( $entry['meta_value'] ); // using a <textarea />
 636      $entry['meta_id']    = (int) $entry['meta_id'];
 637  
 638      $delete_nonce = wp_create_nonce( 'delete-meta_' . $entry['meta_id'] );
 639  
 640      $r .= "\n\t<tr id='meta-{$entry['meta_id']}'>";
 641      $r .= "\n\t\t<td class='left'><label class='screen-reader-text' for='meta-{$entry['meta_id']}-key'>" . __( 'Key' ) . "</label><input name='meta[{$entry['meta_id']}][key]' id='meta-{$entry['meta_id']}-key' type='text' size='20' value='{$entry['meta_key']}' />";
 642  
 643      $r .= "\n\t\t<div class='submit'>";
 644      $r .= get_submit_button( __( 'Delete' ), 'deletemeta small', "deletemeta[{$entry['meta_id']}]", false, array( 'data-wp-lists' => "delete:the-list:meta-{$entry['meta_id']}::_ajax_nonce=$delete_nonce" ) );
 645      $r .= "\n\t\t";
 646      $r .= get_submit_button( __( 'Update' ), 'updatemeta small', "meta-{$entry['meta_id']}-submit", false, array( 'data-wp-lists' => "add:the-list:meta-{$entry['meta_id']}::_ajax_nonce-add-meta=$update_nonce" ) );
 647      $r .= '</div>';
 648      $r .= wp_nonce_field( 'change-meta', '_ajax_nonce', false, false );
 649      $r .= '</td>';
 650  
 651      $r .= "\n\t\t<td><label class='screen-reader-text' for='meta-{$entry['meta_id']}-value'>" . __( 'Value' ) . "</label><textarea name='meta[{$entry['meta_id']}][value]' id='meta-{$entry['meta_id']}-value' rows='2' cols='30'>{$entry['meta_value']}</textarea></td>\n\t</tr>";
 652      return $r;
 653  }
 654  
 655  /**
 656   * Prints the form in the Custom Fields meta box.
 657   *
 658   * @since 1.2.0
 659   *
 660   * @global wpdb $wpdb WordPress database abstraction object.
 661   *
 662   * @param WP_Post $post Optional. The post being edited.
 663   */
 664  function meta_form( $post = null ) {
 665      global $wpdb;
 666      $post = get_post( $post );
 667  
 668      /**
 669       * Filters values for the meta key dropdown in the Custom Fields meta box.
 670       *
 671       * Returning a non-null value will effectively short-circuit and avoid a
 672       * potentially expensive query against postmeta.
 673       *
 674       * @since 4.4.0
 675       *
 676       * @param array|null $keys Pre-defined meta keys to be used in place of a postmeta query. Default null.
 677       * @param WP_Post    $post The current post object.
 678       */
 679      $keys = apply_filters( 'postmeta_form_keys', null, $post );
 680  
 681      if ( null === $keys ) {
 682          /**
 683           * Filters the number of custom fields to retrieve for the drop-down
 684           * in the Custom Fields meta box.
 685           *
 686           * @since 2.1.0
 687           *
 688           * @param int $limit Number of custom fields to retrieve. Default 30.
 689           */
 690          $limit = apply_filters( 'postmeta_form_limit', 30 );
 691          $sql   = "SELECT DISTINCT meta_key
 692              FROM $wpdb->postmeta
 693              WHERE meta_key NOT BETWEEN '_' AND '_z'
 694              HAVING meta_key NOT LIKE %s
 695              ORDER BY meta_key
 696              LIMIT %d";
 697          $keys  = $wpdb->get_col( $wpdb->prepare( $sql, $wpdb->esc_like( '_' ) . '%', $limit ) );
 698      }
 699  
 700      if ( $keys ) {
 701          natcasesort( $keys );
 702          $meta_key_input_id = 'metakeyselect';
 703      } else {
 704          $meta_key_input_id = 'metakeyinput';
 705      }
 706      ?>
 707  <p><strong><?php _e( 'Add New Custom Field:' ); ?></strong></p>
 708  <table id="newmeta">
 709  <thead>
 710  <tr>
 711  <th class="left"><label for="<?php echo $meta_key_input_id; ?>"><?php _ex( 'Name', 'meta name' ); ?></label></th>
 712  <th><label for="metavalue"><?php _e( 'Value' ); ?></label></th>
 713  </tr>
 714  </thead>
 715  
 716  <tbody>
 717  <tr>
 718  <td id="newmetaleft" class="left">
 719      <?php if ( $keys ) { ?>
 720  <select id="metakeyselect" name="metakeyselect">
 721  <option value="#NONE#"><?php _e( '&mdash; Select &mdash;' ); ?></option>
 722          <?php
 723  
 724          foreach ( $keys as $key ) {
 725              if ( is_protected_meta( $key, 'post' ) || ! current_user_can( 'add_post_meta', $post->ID, $key ) ) {
 726                  continue;
 727              }
 728              echo "\n<option value='" . esc_attr( $key ) . "'>" . esc_html( $key ) . '</option>';
 729          }
 730          ?>
 731  </select>
 732  <input class="hide-if-js" type="text" id="metakeyinput" name="metakeyinput" value="" />
 733  <a href="#postcustomstuff" class="hide-if-no-js" onclick="jQuery('#metakeyinput, #metakeyselect, #enternew, #cancelnew').toggle();return false;">
 734  <span id="enternew"><?php _e( 'Enter new' ); ?></span>
 735  <span id="cancelnew" class="hidden"><?php _e( 'Cancel' ); ?></span></a>
 736  <?php } else { ?>
 737  <input type="text" id="metakeyinput" name="metakeyinput" value="" />
 738  <?php } ?>
 739  </td>
 740  <td><textarea id="metavalue" name="metavalue" rows="2" cols="25"></textarea></td>
 741  </tr>
 742  
 743  <tr><td colspan="2">
 744  <div class="submit">
 745      <?php
 746      submit_button(
 747          __( 'Add Custom Field' ),
 748          '',
 749          'addmeta',
 750          false,
 751          array(
 752              'id'            => 'newmeta-submit',
 753              'data-wp-lists' => 'add:the-list:newmeta',
 754          )
 755      );
 756      ?>
 757  </div>
 758      <?php wp_nonce_field( 'add-meta', '_ajax_nonce-add-meta', false ); ?>
 759  </td></tr>
 760  </tbody>
 761  </table>
 762      <?php
 763  
 764  }
 765  
 766  /**
 767   * Print out HTML form date elements for editing post or comment publish date.
 768   *
 769   * @since 0.71
 770   * @since 4.4.0 Converted to use get_comment() instead of the global `$comment`.
 771   *
 772   * @global WP_Locale $wp_locale WordPress date and time locale object.
 773   *
 774   * @param int|bool $edit      Accepts 1|true for editing the date, 0|false for adding the date.
 775   * @param int|bool $for_post  Accepts 1|true for applying the date to a post, 0|false for a comment.
 776   * @param int      $tab_index The tabindex attribute to add. Default 0.
 777   * @param int|bool $multi     Optional. Whether the additional fields and buttons should be added.
 778   *                            Default 0|false.
 779   */
 780  function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) {
 781      global $wp_locale;
 782      $post = get_post();
 783  
 784      if ( $for_post ) {
 785          $edit = ! ( in_array( $post->post_status, array( 'draft', 'pending' ) ) && ( ! $post->post_date_gmt || '0000-00-00 00:00:00' == $post->post_date_gmt ) );
 786      }
 787  
 788      $tab_index_attribute = '';
 789      if ( (int) $tab_index > 0 ) {
 790          $tab_index_attribute = " tabindex=\"$tab_index\"";
 791      }
 792  
 793      // todo: Remove this?
 794      // echo '<label for="timestamp" style="display: block;"><input type="checkbox" class="checkbox" name="edit_date" value="1" id="timestamp"'.$tab_index_attribute.' /> '.__( 'Edit timestamp' ).'</label><br />';
 795  
 796      $post_date = ( $for_post ) ? $post->post_date : get_comment()->comment_date;
 797      $jj        = ( $edit ) ? mysql2date( 'd', $post_date, false ) : current_time( 'd' );
 798      $mm        = ( $edit ) ? mysql2date( 'm', $post_date, false ) : current_time( 'm' );
 799      $aa        = ( $edit ) ? mysql2date( 'Y', $post_date, false ) : current_time( 'Y' );
 800      $hh        = ( $edit ) ? mysql2date( 'H', $post_date, false ) : current_time( 'H' );
 801      $mn        = ( $edit ) ? mysql2date( 'i', $post_date, false ) : current_time( 'i' );
 802      $ss        = ( $edit ) ? mysql2date( 's', $post_date, false ) : current_time( 's' );
 803  
 804      $cur_jj = current_time( 'd' );
 805      $cur_mm = current_time( 'm' );
 806      $cur_aa = current_time( 'Y' );
 807      $cur_hh = current_time( 'H' );
 808      $cur_mn = current_time( 'i' );
 809  
 810      $month = '<label><span class="screen-reader-text">' . __( 'Month' ) . '</span><select ' . ( $multi ? '' : 'id="mm" ' ) . 'name="mm"' . $tab_index_attribute . ">\n";
 811      for ( $i = 1; $i < 13; $i = $i + 1 ) {
 812          $monthnum  = zeroise( $i, 2 );
 813          $monthtext = $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) );
 814          $month    .= "\t\t\t" . '<option value="' . $monthnum . '" data-text="' . $monthtext . '" ' . selected( $monthnum, $mm, false ) . '>';
 815          /* translators: 1: Month number (01, 02, etc.), 2: Month abbreviation. */
 816          $month .= sprintf( __( '%1$s-%2$s' ), $monthnum, $monthtext ) . "</option>\n";
 817      }
 818      $month .= '</select></label>';
 819  
 820      $day    = '<label><span class="screen-reader-text">' . __( 'Day' ) . '</span><input type="text" ' . ( $multi ? '' : 'id="jj" ' ) . 'name="jj" value="' . $jj . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" /></label>';
 821      $year   = '<label><span class="screen-reader-text">' . __( 'Year' ) . '</span><input type="text" ' . ( $multi ? '' : 'id="aa" ' ) . 'name="aa" value="' . $aa . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" /></label>';
 822      $hour   = '<label><span class="screen-reader-text">' . __( 'Hour' ) . '</span><input type="text" ' . ( $multi ? '' : 'id="hh" ' ) . 'name="hh" value="' . $hh . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" /></label>';
 823      $minute = '<label><span class="screen-reader-text">' . __( 'Minute' ) . '</span><input type="text" ' . ( $multi ? '' : 'id="mn" ' ) . 'name="mn" value="' . $mn . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" /></label>';
 824  
 825      echo '<div class="timestamp-wrap">';
 826      /* translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute. */
 827      printf( __( '%1$s %2$s, %3$s at %4$s:%5$s' ), $month, $day, $year, $hour, $minute );
 828  
 829      echo '</div><input type="hidden" id="ss" name="ss" value="' . $ss . '" />';
 830  
 831      if ( $multi ) {
 832          return;
 833      }
 834  
 835      echo "\n\n";
 836      $map = array(
 837          'mm' => array( $mm, $cur_mm ),
 838          'jj' => array( $jj, $cur_jj ),
 839          'aa' => array( $aa, $cur_aa ),
 840          'hh' => array( $hh, $cur_hh ),
 841          'mn' => array( $mn, $cur_mn ),
 842      );
 843      foreach ( $map as $timeunit => $value ) {
 844          list( $unit, $curr ) = $value;
 845  
 846          echo '<input type="hidden" id="hidden_' . $timeunit . '" name="hidden_' . $timeunit . '" value="' . $unit . '" />' . "\n";
 847          $cur_timeunit = 'cur_' . $timeunit;
 848          echo '<input type="hidden" id="' . $cur_timeunit . '" name="' . $cur_timeunit . '" value="' . $curr . '" />' . "\n";
 849      }
 850      ?>
 851  
 852  <p>
 853  <a href="#edit_timestamp" class="save-timestamp hide-if-no-js button"><?php _e( 'OK' ); ?></a>
 854  <a href="#edit_timestamp" class="cancel-timestamp hide-if-no-js button-cancel"><?php _e( 'Cancel' ); ?></a>
 855  </p>
 856      <?php
 857  }
 858  
 859  /**
 860   * Print out option HTML elements for the page templates drop-down.
 861   *
 862   * @since 1.5.0
 863   * @since 4.7.0 Added the `$post_type` parameter.
 864   *
 865   * @param string $default   Optional. The template file name. Default empty.
 866   * @param string $post_type Optional. Post type to get templates for. Default 'post'.
 867   */
 868  function page_template_dropdown( $default = '', $post_type = 'page' ) {
 869      $templates = get_page_templates( null, $post_type );
 870      ksort( $templates );
 871      foreach ( array_keys( $templates ) as $template ) {
 872          $selected = selected( $default, $templates[ $template ], false );
 873          echo "\n\t<option value='" . esc_attr( $templates[ $template ] ) . "' $selected>" . esc_html( $template ) . '</option>';
 874      }
 875  }
 876  
 877  /**
 878   * Print out option HTML elements for the page parents drop-down.
 879   *
 880   * @since 1.5.0
 881   * @since 4.4.0 `$post` argument was added.
 882   *
 883   * @global wpdb $wpdb WordPress database abstraction object.
 884   *
 885   * @param int         $default Optional. The default page ID to be pre-selected. Default 0.
 886   * @param int         $parent  Optional. The parent page ID. Default 0.
 887   * @param int         $level   Optional. Page depth level. Default 0.
 888   * @param int|WP_Post $post    Post ID or WP_Post object.
 889   *
 890   * @return null|false Boolean False if page has no children, otherwise print out html elements.
 891   */
 892  function parent_dropdown( $default = 0, $parent = 0, $level = 0, $post = null ) {
 893      global $wpdb;
 894      $post  = get_post( $post );
 895      $items = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' ORDER BY menu_order", $parent ) );
 896  
 897      if ( $items ) {
 898          foreach ( $items as $item ) {
 899              // A page cannot be its own parent.
 900              if ( $post && $post->ID && $item->ID == $post->ID ) {
 901                  continue;
 902              }
 903  
 904              $pad      = str_repeat( '&nbsp;', $level * 3 );
 905              $selected = selected( $default, $item->ID, false );
 906  
 907              echo "\n\t<option class='level-$level' value='$item->ID' $selected>$pad " . esc_html( $item->post_title ) . '</option>';
 908              parent_dropdown( $default, $item->ID, $level + 1 );
 909          }
 910      } else {
 911          return false;
 912      }
 913  }
 914  
 915  /**
 916   * Print out option html elements for role selectors.
 917   *
 918   * @since 2.1.0
 919   *
 920   * @param string $selected Slug for the role that should be already selected.
 921   */
 922  function wp_dropdown_roles( $selected = '' ) {
 923      $r = '';
 924  
 925      $editable_roles = array_reverse( get_editable_roles() );
 926  
 927      foreach ( $editable_roles as $role => $details ) {
 928          $name = translate_user_role( $details['name'] );
 929          // preselect specified role
 930          if ( $selected == $role ) {
 931              $r .= "\n\t<option selected='selected' value='" . esc_attr( $role ) . "'>$name</option>";
 932          } else {
 933              $r .= "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
 934          }
 935      }
 936  
 937      echo $r;
 938  }
 939  
 940  /**
 941   * Outputs the form used by the importers to accept the data to be imported
 942   *
 943   * @since 2.0.0
 944   *
 945   * @param string $action The action attribute for the form.
 946   */
 947  function wp_import_upload_form( $action ) {
 948  
 949      /**
 950       * Filters the maximum allowed upload size for import files.
 951       *
 952       * @since 2.3.0
 953       *
 954       * @see wp_max_upload_size()
 955       *
 956       * @param int $max_upload_size Allowed upload size. Default 1 MB.
 957       */
 958      $bytes      = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
 959      $size       = size_format( $bytes );
 960      $upload_dir = wp_upload_dir();
 961      if ( ! empty( $upload_dir['error'] ) ) :
 962          ?>
 963          <div class="error"><p><?php _e( 'Before you can upload your import file, you will need to fix the following error:' ); ?></p>
 964          <p><strong><?php echo $upload_dir['error']; ?></strong></p></div>
 965                                  <?php
 966      else :
 967          ?>
 968  <form enctype="multipart/form-data" id="import-upload-form" method="post" class="wp-upload-form" action="<?php echo esc_url( wp_nonce_url( $action, 'import-upload' ) ); ?>">
 969  <p>
 970          <?php
 971          printf(
 972              '<label for="upload">%s</label> (%s)',
 973              __( 'Choose a file from your computer:' ),
 974              /* translators: %s: Maximum allowed file size. */
 975              sprintf( __( 'Maximum size: %s' ), $size )
 976          );
 977          ?>
 978  <input type="file" id="upload" name="import" size="25" />
 979  <input type="hidden" name="action" value="save" />
 980  <input type="hidden" name="max_file_size" value="<?php echo $bytes; ?>" />
 981  </p>
 982          <?php submit_button( __( 'Upload file and import' ), 'primary' ); ?>
 983  </form>
 984          <?php
 985      endif;
 986  }
 987  
 988  /**
 989   * Adds a meta box to one or more screens.
 990   *
 991   * @since 2.5.0
 992   * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs.
 993   *
 994   * @global array $wp_meta_boxes
 995   *
 996   * @param string                 $id            Meta box ID (used in the 'id' attribute for the meta box).
 997   * @param string                 $title         Title of the meta box.
 998   * @param callable               $callback      Function that fills the box with the desired content.
 999   *                                              The function should echo its output.
1000   * @param string|array|WP_Screen $screen        Optional. The screen or screens on which to show the box
1001   *                                              (such as a post type, 'link', or 'comment'). Accepts a single
1002   *                                              screen ID, WP_Screen object, or array of screen IDs. Default
1003   *                                              is the current screen.  If you have used add_menu_page() or
1004   *                                              add_submenu_page() to create a new screen (and hence screen_id),
1005   *                                              make sure your menu slug conforms to the limits of sanitize_key()
1006   *                                              otherwise the 'screen' menu may not correctly render on your page.
1007   * @param string                 $context       Optional. The context within the screen where the boxes
1008   *                                              should display. Available contexts vary from screen to
1009   *                                              screen. Post edit screen contexts include 'normal', 'side',
1010   *                                              and 'advanced'. Comments screen contexts include 'normal'
1011   *                                              and 'side'. Menus meta boxes (accordion sections) all use
1012   *                                              the 'side' context. Global default is 'advanced'.
1013   * @param string                 $priority      Optional. The priority within the context where the boxes
1014   *                                              should show ('high', 'low'). Default 'default'.
1015   * @param array                  $callback_args Optional. Data that should be set as the $args property
1016   *                                              of the box array (which is the second parameter passed
1017   *                                              to your callback). Default null.
1018   */
1019  function add_meta_box( $id, $title, $callback, $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null ) {
1020      global $wp_meta_boxes;
1021  
1022      if ( empty( $screen ) ) {
1023          $screen = get_current_screen();
1024      } elseif ( is_string( $screen ) ) {
1025          $screen = convert_to_screen( $screen );
1026      } elseif ( is_array( $screen ) ) {
1027          foreach ( $screen as $single_screen ) {
1028              add_meta_box( $id, $title, $callback, $single_screen, $context, $priority, $callback_args );
1029          }
1030      }
1031  
1032      if ( ! isset( $screen->id ) ) {
1033          return;
1034      }
1035  
1036      $page = $screen->id;
1037  
1038      if ( ! isset( $wp_meta_boxes ) ) {
1039          $wp_meta_boxes = array();
1040      }
1041      if ( ! isset( $wp_meta_boxes[ $page ] ) ) {
1042          $wp_meta_boxes[ $page ] = array();
1043      }
1044      if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
1045          $wp_meta_boxes[ $page ][ $context ] = array();
1046      }
1047  
1048      foreach ( array_keys( $wp_meta_boxes[ $page ] ) as $a_context ) {
1049          foreach ( array( 'high', 'core', 'default', 'low' ) as $a_priority ) {
1050              if ( ! isset( $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ] ) ) {
1051                  continue;
1052              }
1053  
1054              // If a core box was previously added or removed by a plugin, don't add.
1055              if ( 'core' == $priority ) {
1056                  // If core box previously deleted, don't add
1057                  if ( false === $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ] ) {
1058                      return;
1059                  }
1060  
1061                  /*
1062                   * If box was added with default priority, give it core priority to
1063                   * maintain sort order.
1064                   */
1065                  if ( 'default' == $a_priority ) {
1066                      $wp_meta_boxes[ $page ][ $a_context ]['core'][ $id ] = $wp_meta_boxes[ $page ][ $a_context ]['default'][ $id ];
1067                      unset( $wp_meta_boxes[ $page ][ $a_context ]['default'][ $id ] );
1068                  }
1069                  return;
1070              }
1071              // If no priority given and id already present, use existing priority.
1072              if ( empty( $priority ) ) {
1073                  $priority = $a_priority;
1074                  /*
1075                  * Else, if we're adding to the sorted priority, we don't know the title
1076                  * or callback. Grab them from the previously added context/priority.
1077                  */
1078              } elseif ( 'sorted' == $priority ) {
1079                  $title         = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['title'];
1080                  $callback      = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['callback'];
1081                  $callback_args = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['args'];
1082              }
1083              // An id can be in only one priority and one context.
1084              if ( $priority != $a_priority || $context != $a_context ) {
1085                  unset( $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ] );
1086              }
1087          }
1088      }
1089  
1090      if ( empty( $priority ) ) {
1091          $priority = 'low';
1092      }
1093  
1094      if ( ! isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
1095          $wp_meta_boxes[ $page ][ $context ][ $priority ] = array();
1096      }
1097  
1098      $wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = array(
1099          'id'       => $id,
1100          'title'    => $title,
1101          'callback' => $callback,
1102          'args'     => $callback_args,
1103      );
1104  }
1105  
1106  
1107  /**
1108   * Function that renders a "fake" meta box with an information message,
1109   * shown on the block editor, when an incompatible meta box is found.
1110   *
1111   * @since 5.0.0
1112   *
1113   * @param mixed $object The data object being rendered on this screen.
1114   * @param array $box    {
1115   *     Custom formats meta box arguments.
1116   *
1117   *     @type string   $id           Meta box 'id' attribute.
1118   *     @type string   $title        Meta box title.
1119   *     @type callable $old_callback The original callback for this meta box.
1120   *     @type array    $args         Extra meta box arguments.
1121   * }
1122   */
1123  function do_block_editor_incompatible_meta_box( $object, $box ) {
1124      $plugin  = _get_plugin_from_callback( $box['old_callback'] );
1125      $plugins = get_plugins();
1126      echo '<p>';
1127      if ( $plugin ) {
1128          /* translators: %s: The name of the plugin that generated this meta box. */
1129          printf( __( "This meta box, from the %s plugin, isn't compatible with the block editor." ), "<strong>{$plugin['Name']}</strong>" );
1130      } else {
1131          _e( "This meta box isn't compatible with the block editor." );
1132      }
1133      echo '</p>';
1134  
1135      if ( empty( $plugins['classic-editor/classic-editor.php'] ) ) {
1136          if ( current_user_can( 'install_plugins' ) ) {
1137              echo '<p>';
1138              printf(
1139                  /* translators: %s: A link to install the Classic Editor plugin. */
1140                  __( 'Please install the <a href="%s">Classic Editor plugin</a> to use this meta box.' ),
1141                  esc_url( wp_nonce_url( self_admin_url( 'plugin-install.php?tab=favorites&user=wordpressdotorg&save=0' ), 'save_wporg_username_' . get_current_user_id() ) )
1142              );
1143              echo '</p>';
1144          }
1145      } elseif ( is_plugin_inactive( 'classic-editor/classic-editor.php' ) ) {
1146          if ( current_user_can( 'activate_plugins' ) ) {
1147              $activate_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=classic-editor/classic-editor.php' ), 'activate-plugin_classic-editor/classic-editor.php' );
1148              echo '<p>';
1149              /* translators: %s: A link to activate the Classic Editor plugin. */
1150              printf( __( 'Please activate the <a href="%s">Classic Editor plugin</a> to use this meta box.' ), esc_url( $activate_url ) );
1151              echo '</p>';
1152          }
1153      } elseif ( $object instanceof WP_Post ) {
1154          $edit_url = add_query_arg(
1155              array(
1156                  'classic-editor'         => '',
1157                  'classic-editor__forget' => '',
1158              ),
1159              get_edit_post_link( $object )
1160          );
1161          echo '<p>';
1162          /* translators: %s: A link to use the Classic Editor plugin. */
1163          printf( __( 'Please open the <a href="%s">classic editor</a> to use this meta box.' ), esc_url( $edit_url ) );
1164          echo '</p>';
1165      }
1166  }
1167  
1168  /**
1169   * Internal helper function to find the plugin from a meta box callback.
1170   *
1171   * @since 5.0.0
1172   *
1173   * @access private
1174   *
1175   * @param callable $callback The callback function to check.
1176   * @return array|null The plugin that the callback belongs to, or null if it doesn't belong to a plugin.
1177   */
1178  function _get_plugin_from_callback( $callback ) {
1179      try {
1180          if ( is_array( $callback ) ) {
1181              $reflection = new ReflectionMethod( $callback[0], $callback[1] );
1182          } elseif ( is_string( $callback ) && false !== strpos( $callback, '::' ) ) {
1183              $reflection = new ReflectionMethod( $callback );
1184          } else {
1185              $reflection = new ReflectionFunction( $callback );
1186          }
1187      } catch ( ReflectionException $exception ) {
1188          // We could not properly reflect on the callable, so we abort here.
1189          return null;
1190      }
1191  
1192      // Don't show an error if it's an internal PHP function.
1193      if ( ! $reflection->isInternal() ) {
1194  
1195          // Only show errors if the meta box was registered by a plugin.
1196          $filename   = wp_normalize_path( $reflection->getFileName() );
1197          $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
1198          if ( strpos( $filename, $plugin_dir ) === 0 ) {
1199              $filename = str_replace( $plugin_dir, '', $filename );
1200              $filename = preg_replace( '|^/([^/]*/).*$|', '\\1', $filename );
1201  
1202              $plugins = get_plugins();
1203              foreach ( $plugins as $name => $plugin ) {
1204                  if ( strpos( $name, $filename ) === 0 ) {
1205                      return $plugin;
1206                  }
1207              }
1208          }
1209      }
1210  
1211      return null;
1212  }
1213  
1214  /**
1215   * Meta-Box template function.
1216   *
1217   * @since 2.5.0
1218   *
1219   * @global array $wp_meta_boxes
1220   *
1221   * @staticvar bool $already_sorted
1222   *
1223   * @param string|WP_Screen $screen  Screen identifier. If you have used add_menu_page() or
1224   *                                  add_submenu_page() to create a new screen (and hence screen_id)
1225   *                                  make sure your menu slug conforms to the limits of sanitize_key()
1226   *                                  otherwise the 'screen' menu may not correctly render on your page.
1227   * @param string           $context The screen context for which to display meta boxes.
1228   * @param mixed            $object  Gets passed to the first parameter of the meta box callback function.
1229   *                                  Often this is the object that's the focus of the current screen, for
1230   *                                  example a `WP_Post` or `WP_Comment` object.
1231   * @return int number of meta_boxes
1232   */
1233  function do_meta_boxes( $screen, $context, $object ) {
1234      global $wp_meta_boxes;
1235      static $already_sorted = false;
1236  
1237      if ( empty( $screen ) ) {
1238          $screen = get_current_screen();
1239      } elseif ( is_string( $screen ) ) {
1240          $screen = convert_to_screen( $screen );
1241      }
1242  
1243      $page = $screen->id;
1244  
1245      $hidden = get_hidden_meta_boxes( $screen );
1246  
1247      printf( '<div id="%s-sortables" class="meta-box-sortables">', esc_attr( $context ) );
1248  
1249      // Grab the ones the user has manually sorted. Pull them out of their previous context/priority and into the one the user chose
1250      $sorted = get_user_option( "meta-box-order_$page" );
1251      if ( ! $already_sorted && $sorted ) {
1252          foreach ( $sorted as $box_context => $ids ) {
1253              foreach ( explode( ',', $ids ) as $id ) {
1254                  if ( $id && 'dashboard_browser_nag' !== $id ) {
1255                      add_meta_box( $id, null, null, $screen, $box_context, 'sorted' );
1256                  }
1257              }
1258          }
1259      }
1260  
1261      $already_sorted = true;
1262  
1263      $i = 0;
1264  
1265      if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
1266          foreach ( array( 'high', 'sorted', 'core', 'default', 'low' ) as $priority ) {
1267              if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
1268                  foreach ( (array) $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
1269                      if ( false == $box || ! $box['title'] ) {
1270                          continue;
1271                      }
1272  
1273                      $block_compatible = true;
1274                      if ( is_array( $box['args'] ) ) {
1275                          // If a meta box is just here for back compat, don't show it in the block editor.
1276                          if ( $screen->is_block_editor() && isset( $box['args']['__back_compat_meta_box'] ) && $box['args']['__back_compat_meta_box'] ) {
1277                              continue;
1278                          }
1279  
1280                          if ( isset( $box['args']['__block_editor_compatible_meta_box'] ) ) {
1281                              $block_compatible = (bool) $box['args']['__block_editor_compatible_meta_box'];
1282                              unset( $box['args']['__block_editor_compatible_meta_box'] );
1283                          }
1284  
1285                          // If the meta box is declared as incompatible with the block editor, override the callback function.
1286                          if ( ! $block_compatible && $screen->is_block_editor() ) {
1287                              $box['old_callback'] = $box['callback'];
1288                              $box['callback']     = 'do_block_editor_incompatible_meta_box';
1289                          }
1290  
1291                          if ( isset( $box['args']['__back_compat_meta_box'] ) ) {
1292                              $block_compatible = $block_compatible || (bool) $box['args']['__back_compat_meta_box'];
1293                              unset( $box['args']['__back_compat_meta_box'] );
1294                          }
1295                      }
1296  
1297                      $i++;
1298                      // get_hidden_meta_boxes() doesn't apply in the block editor.
1299                      $hidden_class = ( ! $screen->is_block_editor() && in_array( $box['id'], $hidden ) ) ? ' hide-if-js' : '';
1300                      echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes( $box['id'], $page ) . $hidden_class . '" ' . '>' . "\n";
1301                      if ( 'dashboard_browser_nag' != $box['id'] ) {
1302                          $widget_title = $box['title'];
1303  
1304                          if ( is_array( $box['args'] ) && isset( $box['args']['__widget_basename'] ) ) {
1305                              $widget_title = $box['args']['__widget_basename'];
1306                              // Do not pass this parameter to the user callback function.
1307                              unset( $box['args']['__widget_basename'] );
1308                          }
1309  
1310                          echo '<button type="button" class="handlediv" aria-expanded="true">';
1311                          echo '<span class="screen-reader-text">' . sprintf(
1312                              /* translators: %s: Meta box title. */
1313                              __( 'Toggle panel: %s' ),
1314                              $widget_title
1315                          ) . '</span>';
1316                          echo '<span class="toggle-indicator" aria-hidden="true"></span>';
1317                          echo '</button>';
1318                      }
1319                      echo '<h2 class="hndle">';
1320                      if ( 'dashboard_php_nag' === $box['id'] ) {
1321                          echo '<span aria-hidden="true" class="dashicons dashicons-warning"></span>';
1322                          echo '<span class="screen-reader-text">' . __( 'Warning:' ) . ' </span>';
1323                      }
1324                      echo "<span>{$box['title']}</span>";
1325                      echo "</h2>\n";
1326                      echo '<div class="inside">' . "\n";
1327  
1328                      if ( WP_DEBUG && ! $block_compatible && 'edit' === $screen->parent_base && ! $screen->is_block_editor() && ! isset( $_GET['meta-box-loader'] ) ) {
1329                          $plugin = _get_plugin_from_callback( $box['callback'] );
1330                          if ( $plugin ) {
1331                              ?>
1332                              <div class="error inline">
1333                                  <p>
1334                                      <?php
1335                                          /* translators: %s: The name of the plugin that generated this meta box. */
1336                                          printf( __( "This meta box, from the %s plugin, isn't compatible with the block editor." ), "<strong>{$plugin['Name']}</strong>" );
1337                                      ?>
1338                                  </p>
1339                              </div>
1340                              <?php
1341                          }
1342                      }
1343  
1344                      call_user_func( $box['callback'], $object, $box );
1345                      echo "</div>\n";
1346                      echo "</div>\n";
1347                  }
1348              }
1349          }
1350      }
1351  
1352      echo '</div>';
1353  
1354      return $i;
1355  
1356  }
1357  
1358  /**
1359   * Removes a meta box from one or more screens.
1360   *
1361   * @since 2.6.0
1362   * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs.
1363   *
1364   * @global array $wp_meta_boxes
1365   *
1366   * @param string                 $id      Meta box ID (used in the 'id' attribute for the meta box).
1367   * @param string|array|WP_Screen $screen  The screen or screens on which the meta box is shown (such as a
1368   *                                        post type, 'link', or 'comment'). Accepts a single screen ID,
1369   *                                        WP_Screen object, or array of screen IDs.
1370   * @param string                 $context The context within the screen where the box is set to display.
1371   *                                        Contexts vary from screen to screen. Post edit screen contexts
1372   *                                        include 'normal', 'side', and 'advanced'. Comments screen contexts
1373   *                                        include 'normal' and 'side'. Menus meta boxes (accordion sections)
1374   *                                        all use the 'side' context.
1375   */
1376  function remove_meta_box( $id, $screen, $context ) {
1377      global $wp_meta_boxes;
1378  
1379      if ( empty( $screen ) ) {
1380          $screen = get_current_screen();
1381      } elseif ( is_string( $screen ) ) {
1382          $screen = convert_to_screen( $screen );
1383      } elseif ( is_array( $screen ) ) {
1384          foreach ( $screen as $single_screen ) {
1385              remove_meta_box( $id, $single_screen, $context );
1386          }
1387      }
1388  
1389      if ( ! isset( $screen->id ) ) {
1390          return;
1391      }
1392  
1393      $page = $screen->id;
1394  
1395      if ( ! isset( $wp_meta_boxes ) ) {
1396          $wp_meta_boxes = array();
1397      }
1398      if ( ! isset( $wp_meta_boxes[ $page ] ) ) {
1399          $wp_meta_boxes[ $page ] = array();
1400      }
1401      if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
1402          $wp_meta_boxes[ $page ][ $context ] = array();
1403      }
1404  
1405      foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
1406          $wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = false;
1407      }
1408  }
1409  
1410  /**
1411   * Meta Box Accordion Template Function.
1412   *
1413   * Largely made up of abstracted code from do_meta_boxes(), this
1414   * function serves to build meta boxes as list items for display as
1415   * a collapsible accordion.
1416   *
1417   * @since 3.6.0
1418   *
1419   * @uses global $wp_meta_boxes Used to retrieve registered meta boxes.
1420   *
1421   * @param string|object $screen  The screen identifier.
1422   * @param string        $context The meta box context.
1423   * @param mixed         $object  gets passed to the section callback function as first parameter.
1424   * @return int number of meta boxes as accordion sections.
1425   */
1426  function do_accordion_sections( $screen, $context, $object ) {
1427      global $wp_meta_boxes;
1428  
1429      wp_enqueue_script( 'accordion' );
1430  
1431      if ( empty( $screen ) ) {
1432          $screen = get_current_screen();
1433      } elseif ( is_string( $screen ) ) {
1434          $screen = convert_to_screen( $screen );
1435      }
1436  
1437      $page = $screen->id;
1438  
1439      $hidden = get_hidden_meta_boxes( $screen );
1440      ?>
1441      <div id="side-sortables" class="accordion-container">
1442          <ul class="outer-border">
1443      <?php
1444      $i          = 0;
1445      $first_open = false;
1446  
1447      if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
1448          foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
1449              if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
1450                  foreach ( $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
1451                      if ( false == $box || ! $box['title'] ) {
1452                          continue;
1453                      }
1454                      $i++;
1455                      $hidden_class = in_array( $box['id'], $hidden ) ? 'hide-if-js' : '';
1456  
1457                      $open_class = '';
1458                      if ( ! $first_open && empty( $hidden_class ) ) {
1459                          $first_open = true;
1460                          $open_class = 'open';
1461                      }
1462                      ?>
1463                      <li class="control-section accordion-section <?php echo $hidden_class; ?> <?php echo $open_class; ?> <?php echo esc_attr( $box['id'] ); ?>" id="<?php echo esc_attr( $box['id'] ); ?>">
1464                          <h3 class="accordion-section-title hndle" tabindex="0">
1465                              <?php echo esc_html( $box['title'] ); ?>
1466                              <span class="screen-reader-text"><?php _e( 'Press return or enter to open this section' ); ?></span>
1467                          </h3>
1468                          <div class="accordion-section-content <?php postbox_classes( $box['id'], $page ); ?>">
1469                              <div class="inside">
1470                                  <?php call_user_func( $box['callback'], $object, $box ); ?>
1471                              </div><!-- .inside -->
1472                          </div><!-- .accordion-section-content -->
1473                      </li><!-- .accordion-section -->
1474                      <?php
1475                  }
1476              }
1477          }
1478      }
1479      ?>
1480          </ul><!-- .outer-border -->
1481      </div><!-- .accordion-container -->
1482      <?php
1483      return $i;
1484  }
1485  
1486  /**
1487   * Add a new section to a settings page.
1488   *
1489   * Part of the Settings API. Use this to define new settings sections for an admin page.
1490   * Show settings sections in your admin page callback function with do_settings_sections().
1491   * Add settings fields to your section with add_settings_field().
1492   *
1493   * The $callback argument should be the name of a function that echoes out any
1494   * content you want to show at the top of the settings section before the actual
1495   * fields. It can output nothing if you want.
1496   *
1497   * @since 2.7.0
1498   *
1499   * @global $wp_settings_sections Storage array of all settings sections added to admin pages.
1500   *
1501   * @param string   $id       Slug-name to identify the section. Used in the 'id' attribute of tags.
1502   * @param string   $title    Formatted title of the section. Shown as the heading for the section.
1503   * @param callable $callback Function that echos out any content at the top of the section (between heading and fields).
1504   * @param string   $page     The slug-name of the settings page on which to show the section. Built-in pages include
1505   *                           'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using
1506   *                           add_options_page();
1507   */
1508  function add_settings_section( $id, $title, $callback, $page ) {
1509      global $wp_settings_sections;
1510  
1511      if ( 'misc' == $page ) {
1512          _deprecated_argument(
1513              __FUNCTION__,
1514              '3.0.0',
1515              sprintf(
1516                  /* translators: %s: misc */
1517                  __( 'The "%s" options group has been removed. Use another settings group.' ),
1518                  'misc'
1519              )
1520          );
1521          $page = 'general';
1522      }
1523  
1524      if ( 'privacy' == $page ) {
1525          _deprecated_argument(
1526              __FUNCTION__,
1527              '3.5.0',
1528              sprintf(
1529                  /* translators: %s: privacy */
1530                  __( 'The "%s" options group has been removed. Use another settings group.' ),
1531                  'privacy'
1532              )
1533          );
1534          $page = 'reading';
1535      }
1536  
1537      $wp_settings_sections[ $page ][ $id ] = array(
1538          'id'       => $id,
1539          'title'    => $title,
1540          'callback' => $callback,
1541      );
1542  }
1543  
1544  /**
1545   * Add a new field to a section of a settings page.
1546   *
1547   * Part of the Settings API. Use this to define a settings field that will show
1548   * as part of a settings section inside a settings page. The fields are shown using
1549   * do_settings_fields() in do_settings-sections()
1550   *
1551   * The $callback argument should be the name of a function that echoes out the
1552   * html input tags for this setting field. Use get_option() to retrieve existing
1553   * values to show.
1554   *
1555   * @since 2.7.0
1556   * @since 4.2.0 The `$class` argument was added.
1557   *
1558   * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections.
1559   *
1560   * @param string   $id       Slug-name to identify the field. Used in the 'id' attribute of tags.
1561   * @param string   $title    Formatted title of the field. Shown as the label for the field
1562   *                           during output.
1563   * @param callable $callback Function that fills the field with the desired form inputs. The
1564   *                           function should echo its output.
1565   * @param string   $page     The slug-name of the settings page on which to show the section
1566   *                           (general, reading, writing, ...).
1567   * @param string   $section  Optional. The slug-name of the section of the settings page
1568   *                           in which to show the box. Default 'default'.
1569   * @param array    $args {
1570   *     Optional. Extra arguments used when outputting the field.
1571   *
1572   *     @type string $label_for When supplied, the setting title will be wrapped
1573   *                             in a `<label>` element, its `for` attribute populated
1574   *                             with this value.
1575   *     @type string $class     CSS Class to be added to the `<tr>` element when the
1576   *                             field is output.
1577   * }
1578   */
1579  function add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() ) {
1580      global $wp_settings_fields;
1581  
1582      if ( 'misc' == $page ) {
1583          _deprecated_argument(
1584              __FUNCTION__,
1585              '3.0.0',
1586              sprintf(
1587                  /* translators: %s: misc */
1588                  __( 'The "%s" options group has been removed. Use another settings group.' ),
1589                  'misc'
1590              )
1591          );
1592          $page = 'general';
1593      }
1594  
1595      if ( 'privacy' == $page ) {
1596          _deprecated_argument(
1597              __FUNCTION__,
1598              '3.5.0',
1599              sprintf(
1600                  /* translators: %s: privacy */
1601                  __( 'The "%s" options group has been removed. Use another settings group.' ),
1602                  'privacy'
1603              )
1604          );
1605          $page = 'reading';
1606      }
1607  
1608      $wp_settings_fields[ $page ][ $section ][ $id ] = array(
1609          'id'       => $id,
1610          'title'    => $title,
1611          'callback' => $callback,
1612          'args'     => $args,
1613      );
1614  }
1615  
1616  /**
1617   * Prints out all settings sections added to a particular settings page
1618   *
1619   * Part of the Settings API. Use this in a settings page callback function
1620   * to output all the sections and fields that were added to that $page with
1621   * add_settings_section() and add_settings_field()
1622   *
1623   * @global $wp_settings_sections Storage array of all settings sections added to admin pages.
1624   * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections.
1625   * @since 2.7.0
1626   *
1627   * @param string $page The slug name of the page whose settings sections you want to output.
1628   */
1629  function do_settings_sections( $page ) {
1630      global $wp_settings_sections, $wp_settings_fields;
1631  
1632      if ( ! isset( $wp_settings_sections[ $page ] ) ) {
1633          return;
1634      }
1635  
1636      foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
1637          if ( $section['title'] ) {
1638              echo "<h2>{$section['title']}</h2>\n";
1639          }
1640  
1641          if ( $section['callback'] ) {
1642              call_user_func( $section['callback'], $section );
1643          }
1644  
1645          if ( ! isset( $wp_settings_fields ) || ! isset( $wp_settings_fields[ $page ] ) || ! isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) {
1646              continue;
1647          }
1648          echo '<table class="form-table" role="presentation">';
1649          do_settings_fields( $page, $section['id'] );
1650          echo '</table>';
1651      }
1652  }
1653  
1654  /**
1655   * Print out the settings fields for a particular settings section.
1656   *
1657   * Part of the Settings API. Use this in a settings page to output
1658   * a specific section. Should normally be called by do_settings_sections()
1659   * rather than directly.
1660   *
1661   * @global $wp_settings_fields Storage array of settings fields and their pages/sections.
1662   *
1663   * @since 2.7.0
1664   *
1665   * @param string $page Slug title of the admin page whose settings fields you want to show.
1666   * @param string $section Slug title of the settings section whose fields you want to show.
1667   */
1668  function do_settings_fields( $page, $section ) {
1669      global $wp_settings_fields;
1670  
1671      if ( ! isset( $wp_settings_fields[ $page ][ $section ] ) ) {
1672          return;
1673      }
1674  
1675      foreach ( (array) $wp_settings_fields[ $page ][ $section ] as $field ) {
1676          $class = '';
1677  
1678          if ( ! empty( $field['args']['class'] ) ) {
1679              $class = ' class="' . esc_attr( $field['args']['class'] ) . '"';
1680          }
1681  
1682          echo "<tr{$class}>";
1683  
1684          if ( ! empty( $field['args']['label_for'] ) ) {
1685              echo '<th scope="row"><label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label></th>';
1686          } else {
1687              echo '<th scope="row">' . $field['title'] . '</th>';
1688          }
1689  
1690          echo '<td>';
1691          call_user_func( $field['callback'], $field['args'] );
1692          echo '</td>';
1693          echo '</tr>';
1694      }
1695  }
1696  
1697  /**
1698   * Register a settings error to be displayed to the user.
1699   *
1700   * Part of the Settings API. Use this to show messages to users about settings validation
1701   * problems, missing settings or anything else.
1702   *
1703   * Settings errors should be added inside the $sanitize_callback function defined in
1704   * register_setting() for a given setting to give feedback about the submission.
1705   *
1706   * By default messages will show immediately after the submission that generated the error.
1707   * Additional calls to settings_errors() can be used to show errors even when the settings
1708   * page is first accessed.
1709   *
1710   * @since 3.0.0
1711   * @since 5.3.0 Added `warning` and `info` as possible values for `$type`.
1712   *
1713   * @global array $wp_settings_errors Storage array of errors registered during this pageload
1714   *
1715   * @param string $setting Slug title of the setting to which this error applies.
1716   * @param string $code    Slug-name to identify the error. Used as part of 'id' attribute in HTML output.
1717   * @param string $message The formatted message text to display to the user (will be shown inside styled
1718   *                        `<div>` and `<p>` tags).
1719   * @param string $type    Optional. Message type, controls HTML class. Possible values include 'error',
1720   *                        'success', 'warning', 'info'. Default 'error'.
1721   */
1722  function add_settings_error( $setting, $code, $message, $type = 'error' ) {
1723      global $wp_settings_errors;
1724  
1725      $wp_settings_errors[] = array(
1726          'setting' => $setting,
1727          'code'    => $code,
1728          'message' => $message,
1729          'type'    => $type,
1730      );
1731  }
1732  
1733  /**
1734   * Fetch settings errors registered by add_settings_error().
1735   *
1736   * Checks the $wp_settings_errors array for any errors declared during the current
1737   * pageload and returns them.
1738   *
1739   * If changes were just submitted ($_GET['settings-updated']) and settings errors were saved
1740   * to the 'settings_errors' transient then those errors will be returned instead. This
1741   * is used to pass errors back across pageloads.
1742   *
1743   * Use the $sanitize argument to manually re-sanitize the option before returning errors.
1744   * This is useful if you have errors or notices you want to show even when the user
1745   * hasn't submitted data (i.e. when they first load an options page, or in the {@see 'admin_notices'}
1746   * action hook).
1747   *
1748   * @since 3.0.0
1749   *
1750   * @global array $wp_settings_errors Storage array of errors registered during this pageload
1751   *
1752   * @param string $setting Optional slug title of a specific setting whose errors you want.
1753   * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors.
1754   * @return array Array of settings errors.
1755   */
1756  function get_settings_errors( $setting = '', $sanitize = false ) {
1757      global $wp_settings_errors;
1758  
1759      /*
1760       * If $sanitize is true, manually re-run the sanitization for this option
1761       * This allows the $sanitize_callback from register_setting() to run, adding
1762       * any settings errors you want to show by default.
1763       */
1764      if ( $sanitize ) {
1765          sanitize_option( $setting, get_option( $setting ) );
1766      }
1767  
1768      // If settings were passed back from options.php then use them.
1769      if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && get_transient( 'settings_errors' ) ) {
1770          $wp_settings_errors = array_merge( (array) $wp_settings_errors, get_transient( 'settings_errors' ) );
1771          delete_transient( 'settings_errors' );
1772      }
1773  
1774      // Check global in case errors have been added on this pageload.
1775      if ( empty( $wp_settings_errors ) ) {
1776          return array();
1777      }
1778  
1779      // Filter the results to those of a specific setting if one was set.
1780      if ( $setting ) {
1781          $setting_errors = array();
1782          foreach ( (array) $wp_settings_errors as $key => $details ) {
1783              if ( $setting == $details['setting'] ) {
1784                  $setting_errors[] = $wp_settings_errors[ $key ];
1785              }
1786          }
1787          return $setting_errors;
1788      }
1789  
1790      return $wp_settings_errors;
1791  }
1792  
1793  /**
1794   * Display settings errors registered by add_settings_error().
1795   *
1796   * Part of the Settings API. Outputs a div for each error retrieved by
1797   * get_settings_errors().
1798   *
1799   * This is called automatically after a settings page based on the
1800   * Settings API is submitted. Errors should be added during the validation
1801   * callback function for a setting defined in register_setting().
1802   *
1803   * The $sanitize option is passed into get_settings_errors() and will
1804   * re-run the setting sanitization
1805   * on its current value.
1806   *
1807   * The $hide_on_update option will cause errors to only show when the settings
1808   * page is first loaded. if the user has already saved new values it will be
1809   * hidden to avoid repeating messages already shown in the default error
1810   * reporting after submission. This is useful to show general errors like
1811   * missing settings when the user arrives at the settings page.
1812   *
1813   * @since 3.0.0
1814   * @since 5.3.0 Legacy `error` and `updated` CSS classes are mapped to
1815   *              `notice-error` and `notice-success`.
1816   *
1817   * @param string $setting        Optional slug title of a specific setting whose errors you want.
1818   * @param bool   $sanitize       Whether to re-sanitize the setting value before returning errors.
1819   * @param bool   $hide_on_update If set to true errors will not be shown if the settings page has
1820   *                               already been submitted.
1821   */
1822  function settings_errors( $setting = '', $sanitize = false, $hide_on_update = false ) {
1823  
1824      if ( $hide_on_update && ! empty( $_GET['settings-updated'] ) ) {
1825          return;
1826      }
1827  
1828      $settings_errors = get_settings_errors( $setting, $sanitize );
1829  
1830      if ( empty( $settings_errors ) ) {
1831          return;
1832      }
1833  
1834      $output = '';
1835      foreach ( $settings_errors as $key => $details ) {
1836          if ( 'updated' === $details['type'] ) {
1837              $details['type'] = 'success';
1838          }
1839  
1840          if ( in_array( $details['type'], array( 'error', 'success', 'warning', 'info' ) ) ) {
1841              $details['type'] = 'notice-' . $details['type'];
1842          }
1843  
1844          $css_id    = sprintf(
1845              'setting-error-%s',
1846              esc_attr( $details['code'] )
1847          );
1848          $css_class = sprintf(
1849              'notice %s settings-error is-dismissible',
1850              esc_attr( $details['type'] )
1851          );
1852  
1853          $output .= "<div id='$css_id' class='$css_class'> \n";
1854          $output .= "<p><strong>{$details['message']}</strong></p>";
1855          $output .= "</div> \n";
1856      }
1857      echo $output;
1858  }
1859  
1860  /**
1861   * Outputs the modal window used for attaching media to posts or pages in the media-listing screen.
1862   *
1863   * @since 2.7.0
1864   *
1865   * @param string $found_action
1866   */
1867  function find_posts_div( $found_action = '' ) {
1868      ?>
1869      <div id="find-posts" class="find-box" style="display: none;">
1870          <div id="find-posts-head" class="find-box-head">
1871              <?php _e( 'Attach to existing content' ); ?>
1872              <button type="button" id="find-posts-close"><span class="screen-reader-text"><?php _e( 'Close media attachment panel' ); ?></span></button>
1873          </div>
1874          <div class="find-box-inside">
1875              <div class="find-box-search">
1876                  <?php if ( $found_action ) { ?>
1877                      <input type="hidden" name="found_action" value="<?php echo esc_attr( $found_action ); ?>" />
1878                  <?php } ?>
1879                  <input type="hidden" name="affected" id="affected" value="" />
1880                  <?php wp_nonce_field( 'find-posts', '_ajax_nonce', false ); ?>
1881                  <label class="screen-reader-text" for="find-posts-input"><?php _e( 'Search' ); ?></label>
1882                  <input type="text" id="find-posts-input" name="ps" value="" />
1883                  <span class="spinner"></span>
1884                  <input type="button" id="find-posts-search" value="<?php esc_attr_e( 'Search' ); ?>" class="button" />
1885                  <div class="clear"></div>
1886              </div>
1887              <div id="find-posts-response"></div>
1888          </div>
1889          <div class="find-box-buttons">
1890              <?php submit_button( __( 'Select' ), 'primary alignright', 'find-posts-submit', false ); ?>
1891              <div class="clear"></div>
1892          </div>
1893      </div>
1894      <?php
1895  }
1896  
1897  /**
1898   * Displays the post password.
1899   *
1900   * The password is passed through esc_attr() to ensure that it is safe for placing in an html attribute.
1901   *
1902   * @since 2.7.0
1903   */
1904  function the_post_password() {
1905      $post = get_post();
1906      if ( isset( $post->post_password ) ) {
1907          echo esc_attr( $post->post_password );
1908      }
1909  }
1910  
1911  /**
1912   * Get the post title.
1913   *
1914   * The post title is fetched and if it is blank then a default string is
1915   * returned.
1916   *
1917   * @since 2.7.0
1918   *
1919   * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
1920   * @return string The post title if set.
1921   */
1922  function _draft_or_post_title( $post = 0 ) {
1923      $title = get_the_title( $post );
1924      if ( empty( $title ) ) {
1925          $title = __( '(no title)' );
1926      }
1927      return esc_html( $title );
1928  }
1929  
1930  /**
1931   * Displays the search query.
1932   *
1933   * A simple wrapper to display the "s" parameter in a `GET` URI. This function
1934   * should only be used when the_search_query() cannot.
1935   *
1936   * @since 2.7.0
1937   */
1938  function _admin_search_query() {
1939      echo isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : '';
1940  }
1941  
1942  /**
1943   * Generic Iframe header for use with Thickbox
1944   *
1945   * @since 2.7.0
1946   *
1947   * @global string    $hook_suffix
1948   * @global string    $admin_body_class
1949   * @global WP_Locale $wp_locale        WordPress date and time locale object.
1950   *
1951   * @param string $title      Optional. Title of the Iframe page. Default empty.
1952   * @param bool   $deprecated Not used.
1953   */
1954  function iframe_header( $title = '', $deprecated = false ) {
1955      show_admin_bar( false );
1956      global $hook_suffix, $admin_body_class, $wp_locale;
1957      $admin_body_class = preg_replace( '/[^a-z0-9_-]+/i', '-', $hook_suffix );
1958  
1959      $current_screen = get_current_screen();
1960  
1961      header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
1962      _wp_admin_html_begin();
1963      ?>
1964  <title><?php bloginfo( 'name' ); ?> &rsaquo; <?php echo $title; ?> &#8212; <?php _e( 'WordPress' ); ?></title>
1965      <?php
1966      wp_enqueue_style( 'colors' );
1967      ?>
1968  <script type="text/javascript">
1969  addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
1970  function tb_close(){var win=window.dialogArguments||opener||parent||top;win.tb_remove();}
1971  var ajaxurl = '<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>',
1972      pagenow = '<?php echo $current_screen->id; ?>',
1973      typenow = '<?php echo $current_screen->post_type; ?>',
1974      adminpage = '<?php echo $admin_body_class; ?>',
1975      thousandsSeparator = '<?php echo addslashes( $wp_locale->number_format['thousands_sep'] ); ?>',
1976      decimalPoint = '<?php echo addslashes( $wp_locale->number_format['decimal_point'] ); ?>',
1977      isRtl = <?php echo (int) is_rtl(); ?>;
1978  </script>
1979      <?php
1980      /** This action is documented in wp-admin/admin-header.php */
1981      do_action( 'admin_enqueue_scripts', $hook_suffix );
1982  
1983      /** This action is documented in wp-admin/admin-header.php */
1984      do_action( "admin_print_styles-{$hook_suffix}" );  // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
1985  
1986      /** This action is documented in wp-admin/admin-header.php */
1987      do_action( 'admin_print_styles' );
1988  
1989      /** This action is documented in wp-admin/admin-header.php */
1990      do_action( "admin_print_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
1991  
1992      /** This action is documented in wp-admin/admin-header.php */
1993      do_action( 'admin_print_scripts' );
1994  
1995      /** This action is documented in wp-admin/admin-header.php */
1996      do_action( "admin_head-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
1997  
1998      /** This action is documented in wp-admin/admin-header.php */
1999      do_action( 'admin_head' );
2000  
2001      $admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) );
2002  
2003      if ( is_rtl() ) {
2004          $admin_body_class .= ' rtl';
2005      }
2006  
2007      ?>
2008  </head>
2009      <?php
2010      /**
2011       * @global string $body_id
2012       */
2013      $admin_body_id = isset( $GLOBALS['body_id'] ) ? 'id="' . $GLOBALS['body_id'] . '" ' : '';
2014  
2015      /** This filter is documented in wp-admin/admin-header.php */
2016      $admin_body_classes = apply_filters( 'admin_body_class', '' );
2017      $admin_body_classes = ltrim( $admin_body_classes . ' ' . $admin_body_class );
2018      ?>
2019  <body <?php echo $admin_body_id; ?>class="wp-admin wp-core-ui no-js iframe <?php echo $admin_body_classes; ?>">
2020  <script type="text/javascript">
2021  (function(){
2022  var c = document.body.className;
2023  c = c.replace(/no-js/, 'js');
2024  document.body.className = c;
2025  })();
2026  </script>
2027      <?php
2028  }
2029  
2030  /**
2031   * Generic Iframe footer for use with Thickbox
2032   *
2033   * @since 2.7.0
2034   */
2035  function iframe_footer() {
2036      /*
2037       * We're going to hide any footer output on iFrame pages,
2038       * but run the hooks anyway since they output JavaScript
2039       * or other needed content.
2040       */
2041  
2042      /**
2043       * @global string $hook_suffix
2044       */
2045      global $hook_suffix;
2046      ?>
2047      <div class="hidden">
2048      <?php
2049      /** This action is documented in wp-admin/admin-footer.php */
2050      do_action( 'admin_footer', $hook_suffix );
2051  
2052      /** This action is documented in wp-admin/admin-footer.php */
2053      do_action( "admin_print_footer_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
2054  
2055      /** This action is documented in wp-admin/admin-footer.php */
2056      do_action( 'admin_print_footer_scripts' );
2057      ?>
2058      </div>
2059  <script type="text/javascript">if(typeof wpOnload=="function")wpOnload();</script>
2060  </body>
2061  </html>
2062      <?php
2063  }
2064  
2065  /**
2066   * Function to echo or return the post states as HTML.
2067   *
2068   * @since 2.7.0
2069   * @since 5.3.0 Added the `$echo` parameter and a return value.
2070   *
2071   * @see get_post_states()
2072   *
2073   * @param WP_Post $post The post to retrieve states for.
2074   * @param bool    $echo Optional. Whether to echo the post states as an HTML string. Default true.
2075   * @return string Post states string.
2076   */
2077  function _post_states( $post, $echo = true ) {
2078      $post_states        = get_post_states( $post );
2079      $post_states_string = '';
2080  
2081      if ( ! empty( $post_states ) ) {
2082          $state_count = count( $post_states );
2083          $i           = 0;
2084  
2085          $post_states_string .= ' &mdash; ';
2086          foreach ( $post_states as $state ) {
2087              ++$i;
2088              ( $i == $state_count ) ? $sep = '' : $sep = ', ';
2089              $post_states_string          .= "<span class='post-state'>$state$sep</span>";
2090          }
2091      }
2092  
2093      if ( $echo ) {
2094          echo $post_states_string;
2095      }
2096  
2097      return $post_states_string;
2098  }
2099  
2100  /**
2101   * Retrieves an array of post states from a post.
2102   *
2103   * @since 5.3.0
2104   *
2105   * @param WP_Post $post The post to retrieve states for.
2106   * @return string[] Array of post state labels keyed by their state.
2107   */
2108  function get_post_states( $post ) {
2109      $post_states = array();
2110      if ( isset( $_REQUEST['post_status'] ) ) {
2111          $post_status = $_REQUEST['post_status'];
2112      } else {
2113          $post_status = '';
2114      }
2115  
2116      if ( ! empty( $post->post_password ) ) {
2117          $post_states['protected'] = _x( 'Password protected', 'post status' );
2118      }
2119  
2120      if ( 'private' == $post->post_status && 'private' != $post_status ) {
2121          $post_states['private'] = _x( 'Private', 'post status' );
2122      }
2123  
2124      if ( 'draft' === $post->post_status ) {
2125          if ( get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) {
2126              $post_states[] = __( 'Customization Draft' );
2127          } elseif ( 'draft' !== $post_status ) {
2128              $post_states['draft'] = _x( 'Draft', 'post status' );
2129          }
2130      } elseif ( 'trash' === $post->post_status && get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) {
2131          $post_states[] = _x( 'Customization Draft', 'post status' );
2132      }
2133  
2134      if ( 'pending' == $post->post_status && 'pending' != $post_status ) {
2135          $post_states['pending'] = _x( 'Pending', 'post status' );
2136      }
2137  
2138      if ( is_sticky( $post->ID ) ) {
2139          $post_states['sticky'] = _x( 'Sticky', 'post status' );
2140      }
2141  
2142      if ( 'future' === $post->post_status ) {
2143          $post_states['scheduled'] = _x( 'Scheduled', 'post status' );
2144      }
2145  
2146      if ( 'page' === get_option( 'show_on_front' ) ) {
2147          if ( intval( get_option( 'page_on_front' ) ) === $post->ID ) {
2148              $post_states['page_on_front'] = _x( 'Front Page', 'page label' );
2149          }
2150  
2151          if ( intval( get_option( 'page_for_posts' ) ) === $post->ID ) {
2152              $post_states['page_for_posts'] = _x( 'Posts Page', 'page label' );
2153          }
2154      }
2155  
2156      if ( intval( get_option( 'wp_page_for_privacy_policy' ) ) === $post->ID ) {
2157          $post_states['page_for_privacy_policy'] = _x( 'Privacy Policy Page', 'page label' );
2158      }
2159  
2160      /**
2161       * Filters the default post display states used in the posts list table.
2162       *
2163       * @since 2.8.0
2164       * @since 3.6.0 Added the `$post` parameter.
2165       *
2166       * @param string[] $post_states An array of post display states.
2167       * @param WP_Post  $post        The current post object.
2168       */
2169      return apply_filters( 'display_post_states', $post_states, $post );
2170  }
2171  
2172  /**
2173   * Function to echo the attachment media states as HTML.
2174   *
2175   * @since 3.2.0
2176   *
2177   * @param WP_Post $post The attachment post to retrieve states for.
2178   * @return string Media states string.
2179   */
2180  function _media_states( $post ) {
2181      $media_states = array();
2182      $stylesheet   = get_option( 'stylesheet' );
2183  
2184      if ( current_theme_supports( 'custom-header' ) ) {
2185          $meta_header = get_post_meta( $post->ID, '_wp_attachment_is_custom_header', true );
2186  
2187          if ( is_random_header_image() ) {
2188              $header_images = wp_list_pluck( get_uploaded_header_images(), 'attachment_id' );
2189  
2190              if ( $meta_header == $stylesheet && in_array( $post->ID, $header_images ) ) {
2191                  $media_states[] = __( 'Header Image' );
2192              }
2193          } else {
2194              $header_image = get_header_image();
2195  
2196              // Display "Header Image" if the image was ever used as a header image
2197              if ( ! empty( $meta_header ) && $meta_header == $stylesheet && $header_image !== wp_get_attachment_url( $post->ID ) ) {
2198                  $media_states[] = __( 'Header Image' );
2199              }
2200  
2201              // Display "Current Header Image" if the image is currently the header image
2202              if ( $header_image && $header_image == wp_get_attachment_url( $post->ID ) ) {
2203                  $media_states[] = __( 'Current Header Image' );
2204              }
2205          }
2206      }
2207  
2208      if ( current_theme_supports( 'custom-background' ) ) {
2209          $meta_background = get_post_meta( $post->ID, '_wp_attachment_is_custom_background', true );
2210  
2211          if ( ! empty( $meta_background ) && $meta_background == $stylesheet ) {
2212              $media_states[] = __( 'Background Image' );
2213  
2214              $background_image = get_background_image();
2215              if ( $background_image && $background_image == wp_get_attachment_url( $post->ID ) ) {
2216                  $media_states[] = __( 'Current Background Image' );
2217              }
2218          }
2219      }
2220  
2221      if ( $post->ID == get_option( 'site_icon' ) ) {
2222          $media_states[] = __( 'Site Icon' );
2223      }
2224  
2225      if ( $post->ID == get_theme_mod( 'custom_logo' ) ) {
2226          $media_states[] = __( 'Logo' );
2227      }
2228  
2229      /**
2230       * Filters the default media display states for items in the Media list table.
2231       *
2232       * @since 3.2.0
2233       * @since 4.8.0 Added the `$post` parameter.
2234       *
2235       * @param string[] $media_states An array of media states. Default 'Header Image',
2236       *                               'Background Image', 'Site Icon', 'Logo'.
2237       * @param WP_Post  $post         The current attachment object.
2238       */
2239      $media_states = apply_filters( 'display_media_states', $media_states, $post );
2240  
2241      if ( ! empty( $media_states ) ) {
2242          $state_count = count( $media_states );
2243          $i           = 0;
2244          echo ' &mdash; ';
2245          foreach ( $media_states as $state ) {
2246              ++$i;
2247              ( $i == $state_count ) ? $sep = '' : $sep = ', ';
2248              echo "<span class='post-state'>$state$sep</span>";
2249          }
2250      }
2251  }
2252  
2253  /**
2254   * Test support for compressing JavaScript from PHP
2255   *
2256   * Outputs JavaScript that tests if compression from PHP works as expected
2257   * and sets an option with the result. Has no effect when the current user
2258   * is not an administrator. To run the test again the option 'can_compress_scripts'
2259   * has to be deleted.
2260   *
2261   * @since 2.8.0
2262   */
2263  function compression_test() {
2264      ?>
2265      <script type="text/javascript">
2266      var compressionNonce = <?php echo wp_json_encode( wp_create_nonce( 'update_can_compress_scripts' ) ); ?>;
2267      var testCompression = {
2268          get : function(test) {
2269              var x;
2270              if ( window.XMLHttpRequest ) {
2271                  x = new XMLHttpRequest();
2272              } else {
2273                  try{x=new ActiveXObject('Msxml2.XMLHTTP');}catch(e){try{x=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){};}
2274              }
2275  
2276              if (x) {
2277                  x.onreadystatechange = function() {
2278                      var r, h;
2279                      if ( x.readyState == 4 ) {
2280                          r = x.responseText.substr(0, 18);
2281                          h = x.getResponseHeader('Content-Encoding');
2282                          testCompression.check(r, h, test);
2283                      }
2284                  };
2285  
2286                  x.open('GET', ajaxurl + '?action=wp-compression-test&test='+test+'&_ajax_nonce='+compressionNonce+'&'+(new Date()).getTime(), true);
2287                  x.send('');
2288              }
2289          },
2290  
2291          check : function(r, h, test) {
2292              if ( ! r && ! test )
2293                  this.get(1);
2294  
2295              if ( 1 == test ) {
2296                  if ( h && ( h.match(/deflate/i) || h.match(/gzip/i) ) )
2297                      this.get('no');
2298                  else
2299                      this.get(2);
2300  
2301                  return;
2302              }
2303  
2304              if ( 2 == test ) {
2305                  if ( '"wpCompressionTest' == r )
2306                      this.get('yes');
2307                  else
2308                      this.get('no');
2309              }
2310          }
2311      };
2312      testCompression.check();
2313      </script>
2314      <?php
2315  }
2316  
2317  /**
2318   * Echoes a submit button, with provided text and appropriate class(es).
2319   *
2320   * @since 3.1.0
2321   *
2322   * @see get_submit_button()
2323   *
2324   * @param string       $text             The text of the button (defaults to 'Save Changes')
2325   * @param string       $type             Optional. The type and CSS class(es) of the button. Core values
2326   *                                       include 'primary', 'small', and 'large'. Default 'primary'.
2327   * @param string       $name             The HTML name of the submit button. Defaults to "submit". If no
2328   *                                       id attribute is given in $other_attributes below, $name will be
2329   *                                       used as the button's id.
2330   * @param bool         $wrap             True if the output button should be wrapped in a paragraph tag,
2331   *                                       false otherwise. Defaults to true.
2332   * @param array|string $other_attributes Other attributes that should be output with the button, mapping
2333   *                                       attributes to their values, such as setting tabindex to 1, etc.
2334   *                                       These key/value attribute pairs will be output as attribute="value",
2335   *                                       where attribute is the key. Other attributes can also be provided
2336   *                                       as a string such as 'tabindex="1"', though the array format is
2337   *                                       preferred. Default null.
2338   */
2339  function submit_button( $text = null, $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = null ) {
2340      echo get_submit_button( $text, $type, $name, $wrap, $other_attributes );
2341  }
2342  
2343  /**
2344   * Returns a submit button, with provided text and appropriate class
2345   *
2346   * @since 3.1.0
2347   *
2348   * @param string       $text             Optional. The text of the button. Default 'Save Changes'.
2349   * @param string       $type             Optional. The type and CSS class(es) of the button. Core values
2350   *                                       include 'primary', 'small', and 'large'. Default 'primary large'.
2351   * @param string       $name             Optional. The HTML name of the submit button. Defaults to "submit".
2352   *                                       If no id attribute is given in $other_attributes below, `$name` will
2353   *                                       be used as the button's id. Default 'submit'.
2354   * @param bool         $wrap             Optional. True if the output button should be wrapped in a paragraph
2355   *                                       tag, false otherwise. Default true.
2356   * @param array|string $other_attributes Optional. Other attributes that should be output with the button,
2357   *                                       mapping attributes to their values, such as `array( 'tabindex' => '1' )`.
2358   *                                       These attributes will be output as `attribute="value"`, such as
2359   *                                       `tabindex="1"`. Other attributes can also be provided as a string such
2360   *                                       as `tabindex="1"`, though the array format is typically cleaner.
2361   *                                       Default empty.
2362   * @return string Submit button HTML.
2363   */
2364  function get_submit_button( $text = '', $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = '' ) {
2365      if ( ! is_array( $type ) ) {
2366          $type = explode( ' ', $type );
2367      }
2368  
2369      $button_shorthand = array( 'primary', 'small', 'large' );
2370      $classes          = array( 'button' );
2371      foreach ( $type as $t ) {
2372          if ( 'secondary' === $t || 'button-secondary' === $t ) {
2373              continue;
2374          }
2375          $classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t;
2376      }
2377      // Remove empty items, remove duplicate items, and finally build a string.
2378      $class = implode( ' ', array_unique( array_filter( $classes ) ) );
2379  
2380      $text = $text ? $text : __( 'Save Changes' );
2381  
2382      // Default the id attribute to $name unless an id was specifically provided in $other_attributes
2383      $id = $name;
2384      if ( is_array( $other_attributes ) && isset( $other_attributes['id'] ) ) {
2385          $id = $other_attributes['id'];
2386          unset( $other_attributes['id'] );
2387      }
2388  
2389      $attributes = '';
2390      if ( is_array( $other_attributes ) ) {
2391          foreach ( $other_attributes as $attribute => $value ) {
2392              $attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important
2393          }
2394      } elseif ( ! empty( $other_attributes ) ) { // Attributes provided as a string
2395          $attributes = $other_attributes;
2396      }
2397  
2398      // Don't output empty name and id attributes.
2399      $name_attr = $name ? ' name="' . esc_attr( $name ) . '"' : '';
2400      $id_attr   = $id ? ' id="' . esc_attr( $id ) . '"' : '';
2401  
2402      $button  = '<input type="submit"' . $name_attr . $id_attr . ' class="' . esc_attr( $class );
2403      $button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';
2404  
2405      if ( $wrap ) {
2406          $button = '<p class="submit">' . $button . '</p>';
2407      }
2408  
2409      return $button;
2410  }
2411  
2412  /**
2413   * @global bool $is_IE
2414   */
2415  function _wp_admin_html_begin() {
2416      global $is_IE;
2417  
2418      $admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : '';
2419  
2420      if ( $is_IE ) {
2421          header( 'X-UA-Compatible: IE=edge' );
2422      }
2423  
2424      ?>
2425  <!DOCTYPE html>
2426  <!--[if IE 8]>
2427  <html xmlns="http://www.w3.org/1999/xhtml" class="ie8 <?php echo $admin_html_class; ?>"
2428      <?php
2429      /**
2430       * Fires inside the HTML tag in the admin header.
2431       *
2432       * @since 2.2.0
2433       */
2434      do_action( 'admin_xml_ns' );
2435  
2436      language_attributes();
2437      ?>
2438      >
2439  <![endif]-->
2440  <!--[if !(IE 8) ]><!-->
2441  <html xmlns="http://www.w3.org/1999/xhtml" class="<?php echo $admin_html_class; ?>"
2442      <?php
2443      /** This action is documented in wp-admin/includes/template.php */
2444      do_action( 'admin_xml_ns' );
2445  
2446      language_attributes();
2447      ?>
2448      >
2449  <!--<![endif]-->
2450  <head>
2451  <meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php echo get_option( 'blog_charset' ); ?>" />
2452      <?php
2453  }
2454  
2455  /**
2456   * Convert a screen string to a screen object
2457   *
2458   * @since 3.0.0
2459   *
2460   * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen.
2461   * @return WP_Screen Screen object.
2462   */
2463  function convert_to_screen( $hook_name ) {
2464      if ( ! class_exists( 'WP_Screen' ) ) {
2465          _doing_it_wrong(
2466              'convert_to_screen(), add_meta_box()',
2467              sprintf(
2468                  /* translators: 1: wp-admin/includes/template.php, 2: add_meta_box(), 3: add_meta_boxes */
2469                  __( 'Likely direct inclusion of %1$s in order to use %2$s. This is very wrong. Hook the %2$s call into the %3$s action instead.' ),
2470                  '<code>wp-admin/includes/template.php</code>',
2471                  '<code>add_meta_box()</code>',
2472                  '<code>add_meta_boxes</code>'
2473              ),
2474              '3.3.0'
2475          );
2476          return (object) array(
2477              'id'   => '_invalid',
2478              'base' => '_are_belong_to_us',
2479          );
2480      }
2481  
2482      return WP_Screen::get( $hook_name );
2483  }
2484  
2485  /**
2486   * Output the HTML for restoring the post data from DOM storage
2487   *
2488   * @since 3.6.0
2489   * @access private
2490   */
2491  function _local_storage_notice() {
2492      ?>
2493      <div id="local-storage-notice" class="hidden notice is-dismissible">
2494      <p class="local-restore">
2495          <?php _e( 'The backup of this post in your browser is different from the version below.' ); ?>
2496          <button type="button" class="button restore-backup"><?php _e( 'Restore the backup' ); ?></button>
2497      </p>
2498      <p class="help">
2499          <?php _e( 'This will replace the current editor content with the last backup version. You can use undo and redo in the editor to get the old content back or to return to the restored version.' ); ?>
2500      </p>
2501      </div>
2502      <?php
2503  }
2504  
2505  /**
2506   * Output a HTML element with a star rating for a given rating.
2507   *
2508   * Outputs a HTML element with the star rating exposed on a 0..5 scale in
2509   * half star increments (ie. 1, 1.5, 2 stars). Optionally, if specified, the
2510   * number of ratings may also be displayed by passing the $number parameter.
2511   *
2512   * @since 3.8.0
2513   * @since 4.4.0 Introduced the `echo` parameter.
2514   *
2515   * @param array $args {
2516   *     Optional. Array of star ratings arguments.
2517   *
2518   *     @type int|float $rating The rating to display, expressed in either a 0.5 rating increment,
2519   *                             or percentage. Default 0.
2520   *     @type string    $type   Format that the $rating is in. Valid values are 'rating' (default),
2521   *                             or, 'percent'. Default 'rating'.
2522   *     @type int       $number The number of ratings that makes up this rating. Default 0.
2523   *     @type bool      $echo   Whether to echo the generated markup. False to return the markup instead
2524   *                             of echoing it. Default true.
2525   * }
2526   * @return string Star rating HTML.
2527   */
2528  function wp_star_rating( $args = array() ) {
2529      $defaults    = array(
2530          'rating' => 0,
2531          'type'   => 'rating',
2532          'number' => 0,
2533          'echo'   => true,
2534      );
2535      $parsed_args = wp_parse_args( $args, $defaults );
2536  
2537      // Non-English decimal places when the $rating is coming from a string
2538      $rating = (float) str_replace( ',', '.', $parsed_args['rating'] );
2539  
2540      // Convert Percentage to star rating, 0..5 in .5 increments
2541      if ( 'percent' === $parsed_args['type'] ) {
2542          $rating = round( $rating / 10, 0 ) / 2;
2543      }
2544  
2545      // Calculate the number of each type of star needed
2546      $full_stars  = floor( $rating );
2547      $half_stars  = ceil( $rating - $full_stars );
2548      $empty_stars = 5 - $full_stars - $half_stars;
2549  
2550      if ( $parsed_args['number'] ) {
2551          /* translators: 1: The rating, 2: The number of ratings. */
2552          $format = _n( '%1$s rating based on %2$s rating', '%1$s rating based on %2$s ratings', $parsed_args['number'] );
2553          $title  = sprintf( $format, number_format_i18n( $rating, 1 ), number_format_i18n( $parsed_args['number'] ) );
2554      } else {
2555          /* translators: %s: The rating. */
2556          $title = sprintf( __( '%s rating' ), number_format_i18n( $rating, 1 ) );
2557      }
2558  
2559      $output  = '<div class="star-rating">';
2560      $output .= '<span class="screen-reader-text">' . $title . '</span>';
2561      $output .= str_repeat( '<div class="star star-full" aria-hidden="true"></div>', $full_stars );
2562      $output .= str_repeat( '<div class="star star-half" aria-hidden="true"></div>', $half_stars );
2563      $output .= str_repeat( '<div class="star star-empty" aria-hidden="true"></div>', $empty_stars );
2564      $output .= '</div>';
2565  
2566      if ( $parsed_args['echo'] ) {
2567          echo $output;
2568      }
2569  
2570      return $output;
2571  }
2572  
2573  /**
2574   * Output a notice when editing the page for posts (internal use only).
2575   *
2576   * @ignore
2577   * @since 4.2.0
2578   */
2579  function _wp_posts_page_notice() {
2580      echo '<div class="notice notice-warning inline"><p>' . __( 'You are currently editing the page that shows your latest posts.' ) . '</p></div>';
2581  }


Generated: Tue Jan 21 01:00:03 2020 Cross-referenced by PHPXref 0.7.1