| [ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
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 // 12 // Category Checklists 13 // 14 15 /** 16 * Walker to output an unordered list of category checkbox <input> elements. 17 * 18 * @see Walker 19 * @see wp_category_checklist() 20 * @see wp_terms_checklist() 21 * @since 2.5.1 22 */ 23 class Walker_Category_Checklist extends Walker { 24 var $tree_type = 'category'; 25 var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this 26 27 function start_lvl( &$output, $depth = 0, $args = array() ) { 28 $indent = str_repeat("\t", $depth); 29 $output .= "$indent<ul class='children'>\n"; 30 } 31 32 function end_lvl( &$output, $depth = 0, $args = array() ) { 33 $indent = str_repeat("\t", $depth); 34 $output .= "$indent</ul>\n"; 35 } 36 37 function start_el( &$output, $category, $depth, $args, $id = 0 ) { 38 extract($args); 39 if ( empty($taxonomy) ) 40 $taxonomy = 'category'; 41 42 if ( $taxonomy == 'category' ) 43 $name = 'post_category'; 44 else 45 $name = 'tax_input['.$taxonomy.']'; 46 47 $class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : ''; 48 $output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>'; 49 } 50 51 function end_el( &$output, $category, $depth = 0, $args = array() ) { 52 $output .= "</li>\n"; 53 } 54 } 55 56 /** 57 * Output an unordered list of checkbox <input> elements labelled 58 * with category names. 59 * 60 * @see wp_terms_checklist() 61 * @since 2.5.1 62 * 63 * @param int $post_id Mark categories associated with this post as checked. $selected_cats must not be an array. 64 * @param int $descendants_and_self ID of the category to output along with its descendents. 65 * @param bool|array $selected_cats List of categories to mark as checked. 66 * @param bool|array $popular_cats Override the list of categories that receive the "popular-category" class. 67 * @param object $walker Walker object to use to build the output. 68 * @param bool $checked_ontop Move checked items out of the hierarchy and to the top of the list. 69 */ 70 function wp_category_checklist( $post_id = 0, $descendants_and_self = 0, $selected_cats = false, $popular_cats = false, $walker = null, $checked_ontop = true ) { 71 wp_terms_checklist( $post_id, array( 72 'taxonomy' => 'category', 73 'descendants_and_self' => $descendants_and_self, 74 'selected_cats' => $selected_cats, 75 'popular_cats' => $popular_cats, 76 'walker' => $walker, 77 'checked_ontop' => $checked_ontop 78 ) ); 79 } 80 81 /** 82 * Output an unordered list of checkbox <input> elements labelled 83 * with term names. Taxonomy independent version of wp_category_checklist(). 84 * 85 * @since 3.0.0 86 * 87 * @param int $post_id 88 * @param array $args 89 */ 90 function wp_terms_checklist($post_id = 0, $args = array()) { 91 $defaults = array( 92 'descendants_and_self' => 0, 93 'selected_cats' => false, 94 'popular_cats' => false, 95 'walker' => null, 96 'taxonomy' => 'category', 97 'checked_ontop' => true 98 ); 99 $args = apply_filters( 'wp_terms_checklist_args', $args, $post_id ); 100 101 extract( wp_parse_args($args, $defaults), EXTR_SKIP ); 102 103 if ( empty($walker) || !is_a($walker, 'Walker') ) 104 $walker = new Walker_Category_Checklist; 105 106 $descendants_and_self = (int) $descendants_and_self; 107 108 $args = array('taxonomy' => $taxonomy); 109 110 $tax = get_taxonomy($taxonomy); 111 $args['disabled'] = !current_user_can($tax->cap->assign_terms); 112 113 if ( is_array( $selected_cats ) ) 114 $args['selected_cats'] = $selected_cats; 115 elseif ( $post_id ) 116 $args['selected_cats'] = wp_get_object_terms($post_id, $taxonomy, array_merge($args, array('fields' => 'ids'))); 117 else 118 $args['selected_cats'] = array(); 119 120 if ( is_array( $popular_cats ) ) 121 $args['popular_cats'] = $popular_cats; 122 else 123 $args['popular_cats'] = get_terms( $taxonomy, array( 'fields' => 'ids', 'orderby' => 'count', 'order' => 'DESC', 'number' => 10, 'hierarchical' => false ) ); 124 125 if ( $descendants_and_self ) { 126 $categories = (array) get_terms($taxonomy, array( 'child_of' => $descendants_and_self, 'hierarchical' => 0, 'hide_empty' => 0 ) ); 127 $self = get_term( $descendants_and_self, $taxonomy ); 128 array_unshift( $categories, $self ); 129 } else { 130 $categories = (array) get_terms($taxonomy, array('get' => 'all')); 131 } 132 133 if ( $checked_ontop ) { 134 // 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) 135 $checked_categories = array(); 136 $keys = array_keys( $categories ); 137 138 foreach( $keys as $k ) { 139 if ( in_array( $categories[$k]->term_id, $args['selected_cats'] ) ) { 140 $checked_categories[] = $categories[$k]; 141 unset( $categories[$k] ); 142 } 143 } 144 145 // Put checked cats on top 146 echo call_user_func_array(array(&$walker, 'walk'), array($checked_categories, 0, $args)); 147 } 148 // Then the rest of them 149 echo call_user_func_array(array(&$walker, 'walk'), array($categories, 0, $args)); 150 } 151 152 /** 153 * Retrieve a list of the most popular terms from the specified taxonomy. 154 * 155 * If the $echo argument is true then the elements for a list of checkbox 156 * <input> elements labelled with the names of the selected terms is output. 157 * If the $post_ID global isn't empty then the terms associated with that 158 * post will be marked as checked. 159 * 160 * @since 2.5.0 161 * 162 * @param string $taxonomy Taxonomy to retrieve terms from. 163 * @param int $default Unused. 164 * @param int $number Number of terms to retrieve. Defaults to 10. 165 * @param bool $echo Optionally output the list as well. Defaults to true. 166 * @return array List of popular term IDs. 167 */ 168 function wp_popular_terms_checklist( $taxonomy, $default = 0, $number = 10, $echo = true ) { 169 $post = get_post(); 170 171 if ( $post && $post->ID ) 172 $checked_terms = wp_get_object_terms($post->ID, $taxonomy, array('fields'=>'ids')); 173 else 174 $checked_terms = array(); 175 176 $terms = get_terms( $taxonomy, array( 'orderby' => 'count', 'order' => 'DESC', 'number' => $number, 'hierarchical' => false ) ); 177 178 $tax = get_taxonomy($taxonomy); 179 180 $popular_ids = array(); 181 foreach ( (array) $terms as $term ) { 182 $popular_ids[] = $term->term_id; 183 if ( !$echo ) // hack for AJAX use 184 continue; 185 $id = "popular-$taxonomy-$term->term_id"; 186 $checked = in_array( $term->term_id, $checked_terms ) ? 'checked="checked"' : ''; 187 ?> 188 189 <li id="<?php echo $id; ?>" class="popular-category"> 190 <label class="selectit"> 191 <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 ) ); ?> /> 192 <?php echo esc_html( apply_filters( 'the_category', $term->name ) ); ?> 193 </label> 194 </li> 195 196 <?php 197 } 198 return $popular_ids; 199 } 200 201 /** 202 * {@internal Missing Short Description}} 203 * 204 * @since 2.5.1 205 * 206 * @param unknown_type $link_id 207 */ 208 function wp_link_category_checklist( $link_id = 0 ) { 209 $default = 1; 210 211 if ( $link_id ) { 212 $checked_categories = wp_get_link_cats( $link_id ); 213 // No selected categories, strange 214 if ( ! count( $checked_categories ) ) 215 $checked_categories[] = $default; 216 } else { 217 $checked_categories[] = $default; 218 } 219 220 $categories = get_terms( 'link_category', array( 'orderby' => 'name', 'hide_empty' => 0 ) ); 221 222 if ( empty( $categories ) ) 223 return; 224 225 foreach ( $categories as $category ) { 226 $cat_id = $category->term_id; 227 $name = esc_html( apply_filters( 'the_category', $category->name ) ); 228 $checked = in_array( $cat_id, $checked_categories ) ? ' checked="checked"' : ''; 229 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>"; 230 } 231 } 232 233 // adds hidden fields with the data for use in the inline editor for posts and pages 234 /** 235 * {@internal Missing Short Description}} 236 * 237 * @since 2.7.0 238 * 239 * @param unknown_type $post 240 */ 241 function get_inline_data($post) { 242 $post_type_object = get_post_type_object($post->post_type); 243 if ( ! current_user_can($post_type_object->cap->edit_post, $post->ID) ) 244 return; 245 246 $title = esc_textarea( trim( $post->post_title ) ); 247 248 echo ' 249 <div class="hidden" id="inline_' . $post->ID . '"> 250 <div class="post_title">' . $title . '</div> 251 <div class="post_name">' . apply_filters('editable_slug', $post->post_name) . '</div> 252 <div class="post_author">' . $post->post_author . '</div> 253 <div class="comment_status">' . esc_html( $post->comment_status ) . '</div> 254 <div class="ping_status">' . esc_html( $post->ping_status ) . '</div> 255 <div class="_status">' . esc_html( $post->post_status ) . '</div> 256 <div class="jj">' . mysql2date( 'd', $post->post_date, false ) . '</div> 257 <div class="mm">' . mysql2date( 'm', $post->post_date, false ) . '</div> 258 <div class="aa">' . mysql2date( 'Y', $post->post_date, false ) . '</div> 259 <div class="hh">' . mysql2date( 'H', $post->post_date, false ) . '</div> 260 <div class="mn">' . mysql2date( 'i', $post->post_date, false ) . '</div> 261 <div class="ss">' . mysql2date( 's', $post->post_date, false ) . '</div> 262 <div class="post_password">' . esc_html( $post->post_password ) . '</div>'; 263 264 if ( $post_type_object->hierarchical ) 265 echo '<div class="post_parent">' . $post->post_parent . '</div>'; 266 267 if ( $post->post_type == 'page' ) 268 echo '<div class="page_template">' . esc_html( get_post_meta( $post->ID, '_wp_page_template', true ) ) . '</div>'; 269 270 if ( post_type_supports( $post->post_type, 'page-attributes' ) ) 271 echo '<div class="menu_order">' . $post->menu_order . '</div>'; 272 273 $taxonomy_names = get_object_taxonomies( $post->post_type ); 274 foreach ( $taxonomy_names as $taxonomy_name) { 275 $taxonomy = get_taxonomy( $taxonomy_name ); 276 277 if ( $taxonomy->hierarchical && $taxonomy->show_ui ) { 278 echo '<div class="post_category" id="' . $taxonomy_name . '_' . $post->ID . '">' 279 . implode( ',', wp_get_object_terms( $post->ID, $taxonomy_name, array( 'fields' => 'ids' ) ) ) . '</div>'; 280 } elseif ( $taxonomy->show_ui ) { 281 echo '<div class="tags_input" id="'.$taxonomy_name.'_'.$post->ID.'">' 282 . esc_html( str_replace( ',', ', ', get_terms_to_edit( $post->ID, $taxonomy_name ) ) ) . '</div>'; 283 } 284 } 285 286 if ( !$post_type_object->hierarchical ) 287 echo '<div class="sticky">' . (is_sticky($post->ID) ? 'sticky' : '') . '</div>'; 288 289 if ( post_type_supports( $post->post_type, 'post-formats' ) ) 290 echo '<div class="post_format">' . esc_html( get_post_format( $post->ID ) ) . '</div>'; 291 292 echo '</div>'; 293 } 294 295 /** 296 * {@internal Missing Short Description}} 297 * 298 * @since 2.7.0 299 * 300 * @param unknown_type $position 301 * @param unknown_type $checkbox 302 * @param unknown_type $mode 303 */ 304 function wp_comment_reply($position = '1', $checkbox = false, $mode = 'single', $table_row = true) { 305 // allow plugin to replace the popup content 306 $content = apply_filters( 'wp_comment_reply', '', array('position' => $position, 'checkbox' => $checkbox, 'mode' => $mode) ); 307 308 if ( ! empty($content) ) { 309 echo $content; 310 return; 311 } 312 313 if ( $mode == 'single' ) { 314 $wp_list_table = _get_list_table('WP_Post_Comments_List_Table'); 315 } else { 316 $wp_list_table = _get_list_table('WP_Comments_List_Table'); 317 } 318 319 ?> 320 <form method="get" action=""> 321 <?php if ( $table_row ) : ?> 322 <table style="display:none;"><tbody id="com-reply"><tr id="replyrow" style="display:none;"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="colspanchange"> 323 <?php else : ?> 324 <div id="com-reply" style="display:none;"><div id="replyrow" style="display:none;"> 325 <?php endif; ?> 326 <div id="replyhead" style="display:none;"><h5><?php _e( 'Reply to Comment' ); ?></h5></div> 327 <div id="addhead" style="display:none;"><h5><?php _e('Add new Comment'); ?></h5></div> 328 <div id="edithead" style="display:none;"> 329 <div class="inside"> 330 <label for="author"><?php _e('Name') ?></label> 331 <input type="text" name="newcomment_author" size="50" value="" id="author" /> 332 </div> 333 334 <div class="inside"> 335 <label for="author-email"><?php _e('E-mail') ?></label> 336 <input type="text" name="newcomment_author_email" size="50" value="" id="author-email" /> 337 </div> 338 339 <div class="inside"> 340 <label for="author-url"><?php _e('URL') ?></label> 341 <input type="text" id="author-url" name="newcomment_author_url" size="103" value="" /> 342 </div> 343 <div style="clear:both;"></div> 344 </div> 345 346 <div id="replycontainer"> 347 <?php 348 $quicktags_settings = array( 'buttons' => 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' ); 349 wp_editor( '', 'replycontent', array( 'media_buttons' => false, 'tinymce' => false, 'quicktags' => $quicktags_settings ) ); 350 ?> 351 </div> 352 353 <p id="replysubmit" class="submit"> 354 <a href="#comments-form" class="save button-primary alignright"> 355 <span id="addbtn" style="display:none;"><?php _e('Add Comment'); ?></span> 356 <span id="savebtn" style="display:none;"><?php _e('Update Comment'); ?></span> 357 <span id="replybtn" style="display:none;"><?php _e('Submit Reply'); ?></span></a> 358 <a href="#comments-form" class="cancel button-secondary alignleft"><?php _e('Cancel'); ?></a> 359 <span class="waiting spinner"></span> 360 <span class="error" style="display:none;"></span> 361 <br class="clear" /> 362 </p> 363 364 <input type="hidden" name="user_ID" id="user_ID" value="<?php echo get_current_user_id(); ?>" /> 365 <input type="hidden" name="action" id="action" value="" /> 366 <input type="hidden" name="comment_ID" id="comment_ID" value="" /> 367 <input type="hidden" name="comment_post_ID" id="comment_post_ID" value="" /> 368 <input type="hidden" name="status" id="status" value="" /> 369 <input type="hidden" name="position" id="position" value="<?php echo $position; ?>" /> 370 <input type="hidden" name="checkbox" id="checkbox" value="<?php echo $checkbox ? 1 : 0; ?>" /> 371 <input type="hidden" name="mode" id="mode" value="<?php echo esc_attr($mode); ?>" /> 372 <?php 373 wp_nonce_field( 'replyto-comment', '_ajax_nonce-replyto-comment', false ); 374 if ( current_user_can( 'unfiltered_html' ) ) 375 wp_nonce_field( 'unfiltered-html-comment', '_wp_unfiltered_html_comment', false ); 376 ?> 377 <?php if ( $table_row ) : ?> 378 </td></tr></tbody></table> 379 <?php else : ?> 380 </div></div> 381 <?php endif; ?> 382 </form> 383 <?php 384 } 385 386 /** 387 * Output 'undo move to trash' text for comments 388 * 389 * @since 2.9.0 390 */ 391 function wp_comment_trashnotice() { 392 ?> 393 <div class="hidden" id="trash-undo-holder"> 394 <div class="trash-undo-inside"><?php printf(__('Comment by %s moved to the trash.'), '<strong></strong>'); ?> <span class="undo untrash"><a href="#"><?php _e('Undo'); ?></a></span></div> 395 </div> 396 <div class="hidden" id="spam-undo-holder"> 397 <div class="spam-undo-inside"><?php printf(__('Comment by %s marked as spam.'), '<strong></strong>'); ?> <span class="undo unspam"><a href="#"><?php _e('Undo'); ?></a></span></div> 398 </div> 399 <?php 400 } 401 402 /** 403 * {@internal Missing Short Description}} 404 * 405 * @since 1.2.0 406 * 407 * @param unknown_type $meta 408 */ 409 function list_meta( $meta ) { 410 // Exit if no meta 411 if ( ! $meta ) { 412 echo ' 413 <table id="list-table" style="display: none;"> 414 <thead> 415 <tr> 416 <th class="left">' . _x( 'Name', 'meta name' ) . '</th> 417 <th>' . __( 'Value' ) . '</th> 418 </tr> 419 </thead> 420 <tbody id="the-list" data-wp-lists="list:meta"> 421 <tr><td></td></tr> 422 </tbody> 423 </table>'; //TBODY needed for list-manipulation JS 424 return; 425 } 426 $count = 0; 427 ?> 428 <table id="list-table"> 429 <thead> 430 <tr> 431 <th class="left"><?php _ex( 'Name', 'meta name' ) ?></th> 432 <th><?php _e( 'Value' ) ?></th> 433 </tr> 434 </thead> 435 <tbody id='the-list' data-wp-lists='list:meta'> 436 <?php 437 foreach ( $meta as $entry ) 438 echo _list_meta_row( $entry, $count ); 439 ?> 440 </tbody> 441 </table> 442 <?php 443 } 444 445 /** 446 * {@internal Missing Short Description}} 447 * 448 * @since 2.5.0 449 * 450 * @param unknown_type $entry 451 * @param unknown_type $count 452 * @return unknown 453 */ 454 function _list_meta_row( $entry, &$count ) { 455 static $update_nonce = false; 456 457 if ( is_protected_meta( $entry['meta_key'], 'post' ) ) 458 return; 459 460 if ( !$update_nonce ) 461 $update_nonce = wp_create_nonce( 'add-meta' ); 462 463 $r = ''; 464 ++ $count; 465 if ( $count % 2 ) 466 $style = 'alternate'; 467 else 468 $style = ''; 469 470 if ( is_serialized( $entry['meta_value'] ) ) { 471 if ( is_serialized_string( $entry['meta_value'] ) ) { 472 // this is a serialized string, so we should display it 473 $entry['meta_value'] = maybe_unserialize( $entry['meta_value'] ); 474 } else { 475 // this is a serialized array/object so we should NOT display it 476 --$count; 477 return; 478 } 479 } 480 481 $entry['meta_key'] = esc_attr($entry['meta_key']); 482 $entry['meta_value'] = esc_textarea( $entry['meta_value'] ); // using a <textarea /> 483 $entry['meta_id'] = (int) $entry['meta_id']; 484 485 $delete_nonce = wp_create_nonce( 'delete-meta_' . $entry['meta_id'] ); 486 487 $r .= "\n\t<tr id='meta-{$entry['meta_id']}' class='$style'>"; 488 $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']}' />"; 489 490 $r .= "\n\t\t<div class='submit'>"; 491 $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" ) ); 492 $r .= "\n\t\t"; 493 $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" ) ); 494 $r .= "</div>"; 495 $r .= wp_nonce_field( 'change-meta', '_ajax_nonce', false, false ); 496 $r .= "</td>"; 497 498 $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>"; 499 return $r; 500 } 501 502 /** 503 * {@internal Missing Short Description}} 504 * 505 * @since 1.2.0 506 */ 507 function meta_form() { 508 global $wpdb; 509 $limit = (int) apply_filters( 'postmeta_form_limit', 30 ); 510 $keys = $wpdb->get_col( " 511 SELECT meta_key 512 FROM $wpdb->postmeta 513 GROUP BY meta_key 514 HAVING meta_key NOT LIKE '\_%' 515 ORDER BY meta_key 516 LIMIT $limit" ); 517 if ( $keys ) 518 natcasesort($keys); 519 ?> 520 <p><strong><?php _e( 'Add New Custom Field:' ) ?></strong></p> 521 <table id="newmeta"> 522 <thead> 523 <tr> 524 <th class="left"><label for="metakeyselect"><?php _ex( 'Name', 'meta name' ) ?></label></th> 525 <th><label for="metavalue"><?php _e( 'Value' ) ?></label></th> 526 </tr> 527 </thead> 528 529 <tbody> 530 <tr> 531 <td id="newmetaleft" class="left"> 532 <?php if ( $keys ) { ?> 533 <select id="metakeyselect" name="metakeyselect"> 534 <option value="#NONE#"><?php _e( '— Select —' ); ?></option> 535 <?php 536 537 foreach ( $keys as $key ) { 538 if ( is_protected_meta( $key, 'post' ) ) 539 continue; 540 echo "\n<option value='" . esc_attr($key) . "'>" . esc_html($key) . "</option>"; 541 } 542 ?> 543 </select> 544 <input class="hide-if-js" type="text" id="metakeyinput" name="metakeyinput" value="" /> 545 <a href="#postcustomstuff" class="hide-if-no-js" onclick="jQuery('#metakeyinput, #metakeyselect, #enternew, #cancelnew').toggle();return false;"> 546 <span id="enternew"><?php _e('Enter new'); ?></span> 547 <span id="cancelnew" class="hidden"><?php _e('Cancel'); ?></span></a> 548 <?php } else { ?> 549 <input type="text" id="metakeyinput" name="metakeyinput" value="" /> 550 <?php } ?> 551 </td> 552 <td><textarea id="metavalue" name="metavalue" rows="2" cols="25"></textarea></td> 553 </tr> 554 555 <tr><td colspan="2"> 556 <div class="submit"> 557 <?php submit_button( __( 'Add Custom Field' ), 'secondary', 'addmeta', false, array( 'id' => 'newmeta-submit', 'data-wp-lists' => 'add:the-list:newmeta' ) ); ?> 558 </div> 559 <?php wp_nonce_field( 'add-meta', '_ajax_nonce-add-meta', false ); ?> 560 </td></tr> 561 </tbody> 562 </table> 563 <?php 564 565 } 566 567 /** 568 * {@internal Missing Short Description}} 569 * 570 * @since 0.71 571 * 572 * @param unknown_type $edit 573 * @param unknown_type $for_post 574 * @param unknown_type $tab_index 575 * @param unknown_type $multi 576 */ 577 function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) { 578 global $wp_locale, $comment; 579 $post = get_post(); 580 581 if ( $for_post ) 582 $edit = ! ( in_array($post->post_status, array('draft', 'pending') ) && (!$post->post_date_gmt || '0000-00-00 00:00:00' == $post->post_date_gmt ) ); 583 584 $tab_index_attribute = ''; 585 if ( (int) $tab_index > 0 ) 586 $tab_index_attribute = " tabindex=\"$tab_index\""; 587 588 // 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 />'; 589 590 $time_adj = current_time('timestamp'); 591 $post_date = ($for_post) ? $post->post_date : $comment->comment_date; 592 $jj = ($edit) ? mysql2date( 'd', $post_date, false ) : gmdate( 'd', $time_adj ); 593 $mm = ($edit) ? mysql2date( 'm', $post_date, false ) : gmdate( 'm', $time_adj ); 594 $aa = ($edit) ? mysql2date( 'Y', $post_date, false ) : gmdate( 'Y', $time_adj ); 595 $hh = ($edit) ? mysql2date( 'H', $post_date, false ) : gmdate( 'H', $time_adj ); 596 $mn = ($edit) ? mysql2date( 'i', $post_date, false ) : gmdate( 'i', $time_adj ); 597 $ss = ($edit) ? mysql2date( 's', $post_date, false ) : gmdate( 's', $time_adj ); 598 599 $cur_jj = gmdate( 'd', $time_adj ); 600 $cur_mm = gmdate( 'm', $time_adj ); 601 $cur_aa = gmdate( 'Y', $time_adj ); 602 $cur_hh = gmdate( 'H', $time_adj ); 603 $cur_mn = gmdate( 'i', $time_adj ); 604 605 $month = "<select " . ( $multi ? '' : 'id="mm" ' ) . "name=\"mm\"$tab_index_attribute>\n"; 606 for ( $i = 1; $i < 13; $i = $i +1 ) { 607 $monthnum = zeroise($i, 2); 608 $month .= "\t\t\t" . '<option value="' . $monthnum . '"'; 609 if ( $i == $mm ) 610 $month .= ' selected="selected"'; 611 /* translators: 1: month number (01, 02, etc.), 2: month abbreviation */ 612 $month .= '>' . sprintf( __( '%1$s-%2$s' ), $monthnum, $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) ) . "</option>\n"; 613 } 614 $month .= '</select>'; 615 616 $day = '<input type="text" ' . ( $multi ? '' : 'id="jj" ' ) . 'name="jj" value="' . $jj . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; 617 $year = '<input type="text" ' . ( $multi ? '' : 'id="aa" ' ) . 'name="aa" value="' . $aa . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" />'; 618 $hour = '<input type="text" ' . ( $multi ? '' : 'id="hh" ' ) . 'name="hh" value="' . $hh . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; 619 $minute = '<input type="text" ' . ( $multi ? '' : 'id="mn" ' ) . 'name="mn" value="' . $mn . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; 620 621 echo '<div class="timestamp-wrap">'; 622 /* translators: 1: month, 2: day, 3: year, 4: hour, 5: minute */ 623 printf( __( '%1$s %2$s, %3$s @ %4$s : %5$s' ), $month, $day, $year, $hour, $minute ); 624 625 echo '</div><input type="hidden" id="ss" name="ss" value="' . $ss . '" />'; 626 627 if ( $multi ) return; 628 629 echo "\n\n"; 630 foreach ( array('mm', 'jj', 'aa', 'hh', 'mn') as $timeunit ) { 631 echo '<input type="hidden" id="hidden_' . $timeunit . '" name="hidden_' . $timeunit . '" value="' . $$timeunit . '" />' . "\n"; 632 $cur_timeunit = 'cur_' . $timeunit; 633 echo '<input type="hidden" id="'. $cur_timeunit . '" name="'. $cur_timeunit . '" value="' . $$cur_timeunit . '" />' . "\n"; 634 } 635 ?> 636 637 <p> 638 <a href="#edit_timestamp" class="save-timestamp hide-if-no-js button"><?php _e('OK'); ?></a> 639 <a href="#edit_timestamp" class="cancel-timestamp hide-if-no-js"><?php _e('Cancel'); ?></a> 640 </p> 641 <?php 642 } 643 644 /** 645 * {@internal Missing Short Description}} 646 * 647 * @since 1.5.0 648 * 649 * @param unknown_type $default 650 */ 651 function page_template_dropdown( $default = '' ) { 652 $templates = get_page_templates(); 653 ksort( $templates ); 654 foreach (array_keys( $templates ) as $template ) 655 : if ( $default == $templates[$template] ) 656 $selected = " selected='selected'"; 657 else 658 $selected = ''; 659 echo "\n\t<option value='".$templates[$template]."' $selected>$template</option>"; 660 endforeach; 661 } 662 663 /** 664 * {@internal Missing Short Description}} 665 * 666 * @since 1.5.0 667 * 668 * @param unknown_type $default 669 * @param unknown_type $parent 670 * @param unknown_type $level 671 * @return unknown 672 */ 673 function parent_dropdown( $default = 0, $parent = 0, $level = 0 ) { 674 global $wpdb; 675 $post = get_post(); 676 $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) ); 677 678 if ( $items ) { 679 foreach ( $items as $item ) { 680 // A page cannot be its own parent. 681 if ( $post && $post->ID && $item->ID == $post->ID ) 682 continue; 683 684 $pad = str_repeat( ' ', $level * 3 ); 685 if ( $item->ID == $default) 686 $current = ' selected="selected"'; 687 else 688 $current = ''; 689 690 echo "\n\t<option class='level-$level' value='$item->ID'$current>$pad " . esc_html($item->post_title) . "</option>"; 691 parent_dropdown( $default, $item->ID, $level +1 ); 692 } 693 } else { 694 return false; 695 } 696 } 697 698 /** 699 * {@internal Missing Short Description}} 700 * 701 * @since 2.0.0 702 * 703 * @param unknown_type $id 704 * @return unknown 705 */ 706 function the_attachment_links( $id = false ) { 707 $id = (int) $id; 708 $post = get_post( $id ); 709 710 if ( $post->post_type != 'attachment' ) 711 return false; 712 713 $icon = wp_get_attachment_image( $post->ID, 'thumbnail', true ); 714 $attachment_data = wp_get_attachment_metadata( $id ); 715 $thumb = isset( $attachment_data['thumb'] ); 716 ?> 717 <form id="the-attachment-links"> 718 <table> 719 <col /> 720 <col class="widefat" /> 721 <tr> 722 <th scope="row"><?php _e( 'URL' ) ?></th> 723 <td><textarea rows="1" cols="40" type="text" class="attachmentlinks" readonly="readonly"><?php echo esc_textarea( wp_get_attachment_url() ); ?></textarea></td> 724 </tr> 725 <?php if ( $icon ) : ?> 726 <tr> 727 <th scope="row"><?php $thumb ? _e( 'Thumbnail linked to file' ) : _e( 'Image linked to file' ); ?></th> 728 <td><textarea rows="1" cols="40" type="text" class="attachmentlinks" readonly="readonly"><a href="<?php echo wp_get_attachment_url(); ?>"><?php echo $icon ?></a></textarea></td> 729 </tr> 730 <tr> 731 <th scope="row"><?php $thumb ? _e( 'Thumbnail linked to page' ) : _e( 'Image linked to page' ); ?></th> 732 <td><textarea rows="1" cols="40" type="text" class="attachmentlinks" readonly="readonly"><a href="<?php echo get_attachment_link( $post->ID ) ?>" rel="attachment wp-att-<?php echo $post->ID; ?>"><?php echo $icon ?></a></textarea></td> 733 </tr> 734 <?php else : ?> 735 <tr> 736 <th scope="row"><?php _e( 'Link to file' ) ?></th> 737 <td><textarea rows="1" cols="40" type="text" class="attachmentlinks" readonly="readonly"><a href="<?php echo wp_get_attachment_url(); ?>" class="attachmentlink"><?php echo basename( wp_get_attachment_url() ); ?></a></textarea></td> 738 </tr> 739 <tr> 740 <th scope="row"><?php _e( 'Link to page' ) ?></th> 741 <td><textarea rows="1" cols="40" type="text" class="attachmentlinks" readonly="readonly"><a href="<?php echo get_attachment_link( $post->ID ) ?>" rel="attachment wp-att-<?php echo $post->ID ?>"><?php the_title(); ?></a></textarea></td> 742 </tr> 743 <?php endif; ?> 744 </table> 745 </form> 746 <?php 747 } 748 749 /** 750 * Print out <option> html elements for role selectors 751 * 752 * @since 2.1.0 753 * 754 * @param string $selected slug for the role that should be already selected 755 */ 756 function wp_dropdown_roles( $selected = false ) { 757 $p = ''; 758 $r = ''; 759 760 $editable_roles = get_editable_roles(); 761 762 foreach ( $editable_roles as $role => $details ) { 763 $name = translate_user_role($details['name'] ); 764 if ( $selected == $role ) // preselect specified role 765 $p = "\n\t<option selected='selected' value='" . esc_attr($role) . "'>$name</option>"; 766 else 767 $r .= "\n\t<option value='" . esc_attr($role) . "'>$name</option>"; 768 } 769 echo $p . $r; 770 } 771 772 /** 773 * Outputs the form used by the importers to accept the data to be imported 774 * 775 * @since 2.0.0 776 * 777 * @param string $action The action attribute for the form. 778 */ 779 function wp_import_upload_form( $action ) { 780 $bytes = apply_filters( 'import_upload_size_limit', wp_max_upload_size() ); 781 $size = size_format( $bytes ); 782 $upload_dir = wp_upload_dir(); 783 if ( ! empty( $upload_dir['error'] ) ) : 784 ?><div class="error"><p><?php _e('Before you can upload your import file, you will need to fix the following error:'); ?></p> 785 <p><strong><?php echo $upload_dir['error']; ?></strong></p></div><?php 786 else : 787 ?> 788 <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' ) ); ?>"> 789 <p> 790 <label for="upload"><?php _e( 'Choose a file from your computer:' ); ?></label> (<?php printf( __('Maximum size: %s' ), $size ); ?>) 791 <input type="file" id="upload" name="import" size="25" /> 792 <input type="hidden" name="action" value="save" /> 793 <input type="hidden" name="max_file_size" value="<?php echo $bytes; ?>" /> 794 </p> 795 <?php submit_button( __('Upload file and import'), 'button' ); ?> 796 </form> 797 <?php 798 endif; 799 } 800 801 /** 802 * Add a meta box to an edit form. 803 * 804 * @since 2.5.0 805 * 806 * @param string $id String for use in the 'id' attribute of tags. 807 * @param string $title Title of the meta box. 808 * @param string $callback Function that fills the box with the desired content. The function should echo its output. 809 * @param string|object $screen Optional. The screen on which to show the box (post, page, link). Defaults to current screen. 810 * @param string $context Optional. The context within the page where the boxes should show ('normal', 'advanced'). 811 * @param string $priority Optional. The priority within the context where the boxes should show ('high', 'low'). 812 * @param array $callback_args Optional. Data that should be set as the "args" property of the box array (which is the second parameter passed to your callback). 813 */ 814 function add_meta_box( $id, $title, $callback, $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null ) { 815 global $wp_meta_boxes; 816 817 if ( empty( $screen ) ) 818 $screen = get_current_screen(); 819 elseif ( is_string( $screen ) ) 820 $screen = convert_to_screen( $screen ); 821 822 $page = $screen->id; 823 824 if ( !isset($wp_meta_boxes) ) 825 $wp_meta_boxes = array(); 826 if ( !isset($wp_meta_boxes[$page]) ) 827 $wp_meta_boxes[$page] = array(); 828 if ( !isset($wp_meta_boxes[$page][$context]) ) 829 $wp_meta_boxes[$page][$context] = array(); 830 831 foreach ( array_keys($wp_meta_boxes[$page]) as $a_context ) { 832 foreach ( array('high', 'core', 'default', 'low') as $a_priority ) { 833 if ( !isset($wp_meta_boxes[$page][$a_context][$a_priority][$id]) ) 834 continue; 835 836 // If a core box was previously added or removed by a plugin, don't add. 837 if ( 'core' == $priority ) { 838 // If core box previously deleted, don't add 839 if ( false === $wp_meta_boxes[$page][$a_context][$a_priority][$id] ) 840 return; 841 // If box was added with default priority, give it core priority to maintain sort order 842 if ( 'default' == $a_priority ) { 843 $wp_meta_boxes[$page][$a_context]['core'][$id] = $wp_meta_boxes[$page][$a_context]['default'][$id]; 844 unset($wp_meta_boxes[$page][$a_context]['default'][$id]); 845 } 846 return; 847 } 848 // If no priority given and id already present, use existing priority 849 if ( empty($priority) ) { 850 $priority = $a_priority; 851 // else if we're adding to the sorted priority, we don't know the title or callback. Grab them from the previously added context/priority. 852 } elseif ( 'sorted' == $priority ) { 853 $title = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['title']; 854 $callback = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['callback']; 855 $callback_args = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['args']; 856 } 857 // An id can be in only one priority and one context 858 if ( $priority != $a_priority || $context != $a_context ) 859 unset($wp_meta_boxes[$page][$a_context][$a_priority][$id]); 860 } 861 } 862 863 if ( empty($priority) ) 864 $priority = 'low'; 865 866 if ( !isset($wp_meta_boxes[$page][$context][$priority]) ) 867 $wp_meta_boxes[$page][$context][$priority] = array(); 868 869 $wp_meta_boxes[$page][$context][$priority][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $callback_args); 870 } 871 872 /** 873 * Meta-Box template function 874 * 875 * @since 2.5.0 876 * 877 * @param string|object $screen Screen identifier 878 * @param string $context box context 879 * @param mixed $object gets passed to the box callback function as first parameter 880 * @return int number of meta_boxes 881 */ 882 function do_meta_boxes( $screen, $context, $object ) { 883 global $wp_meta_boxes; 884 static $already_sorted = false; 885 886 if ( empty( $screen ) ) 887 $screen = get_current_screen(); 888 elseif ( is_string( $screen ) ) 889 $screen = convert_to_screen( $screen ); 890 891 $page = $screen->id; 892 893 $hidden = get_hidden_meta_boxes( $screen ); 894 895 printf('<div id="%s-sortables" class="meta-box-sortables">', htmlspecialchars($context)); 896 897 $i = 0; 898 do { 899 // Grab the ones the user has manually sorted. Pull them out of their previous context/priority and into the one the user chose 900 if ( !$already_sorted && $sorted = get_user_option( "meta-box-order_$page" ) ) { 901 foreach ( $sorted as $box_context => $ids ) { 902 foreach ( explode(',', $ids ) as $id ) { 903 if ( $id && 'dashboard_browser_nag' !== $id ) 904 add_meta_box( $id, null, null, $screen, $box_context, 'sorted' ); 905 } 906 } 907 } 908 $already_sorted = true; 909 910 if ( !isset($wp_meta_boxes) || !isset($wp_meta_boxes[$page]) || !isset($wp_meta_boxes[$page][$context]) ) 911 break; 912 913 foreach ( array('high', 'sorted', 'core', 'default', 'low') as $priority ) { 914 if ( isset($wp_meta_boxes[$page][$context][$priority]) ) { 915 foreach ( (array) $wp_meta_boxes[$page][$context][$priority] as $box ) { 916 if ( false == $box || ! $box['title'] ) 917 continue; 918 $i++; 919 $hidden_class = in_array($box['id'], $hidden) ? ' hide-if-js' : ''; 920 echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes($box['id'], $page) . $hidden_class . '" ' . '>' . "\n"; 921 if ( 'dashboard_browser_nag' != $box['id'] ) 922 echo '<div class="handlediv" title="' . esc_attr__('Click to toggle') . '"><br /></div>'; 923 echo "<h3 class='hndle'><span>{$box['title']}</span></h3>\n"; 924 echo '<div class="inside">' . "\n"; 925 call_user_func($box['callback'], $object, $box); 926 echo "</div>\n"; 927 echo "</div>\n"; 928 } 929 } 930 } 931 } while(0); 932 933 echo "</div>"; 934 935 return $i; 936 937 } 938 939 /** 940 * Remove a meta box from an edit form. 941 * 942 * @since 2.6.0 943 * 944 * @param string $id String for use in the 'id' attribute of tags. 945 * @param string|object $screen The screen on which to show the box (post, page, link). 946 * @param string $context The context within the page where the boxes should show ('normal', 'advanced'). 947 */ 948 function remove_meta_box($id, $screen, $context) { 949 global $wp_meta_boxes; 950 951 if ( empty( $screen ) ) 952 $screen = get_current_screen(); 953 elseif ( is_string( $screen ) ) 954 $screen = convert_to_screen( $screen ); 955 956 $page = $screen->id; 957 958 if ( !isset($wp_meta_boxes) ) 959 $wp_meta_boxes = array(); 960 if ( !isset($wp_meta_boxes[$page]) ) 961 $wp_meta_boxes[$page] = array(); 962 if ( !isset($wp_meta_boxes[$page][$context]) ) 963 $wp_meta_boxes[$page][$context] = array(); 964 965 foreach ( array('high', 'core', 'default', 'low') as $priority ) 966 $wp_meta_boxes[$page][$context][$priority][$id] = false; 967 } 968 969 /** 970 * Meta Box Accordion Template Function 971 * 972 * Largely made up of abstracted code from {@link do_meta_boxes()}, this 973 * function serves to build meta boxes as list items for display as 974 * a collapsible accordion. 975 * 976 * @since 3.6.0 977 * 978 * @uses global $wp_meta_boxes Used to retrieve registered meta boxes. 979 * 980 * @param string|object $screen The screen identifier. 981 * @param string $context The meta box context. 982 * @param mixed $object gets passed to the section callback function as first parameter. 983 * @return int number of meta boxes as accordion sections. 984 */ 985 function do_accordion_sections( $screen, $context, $object ) { 986 global $wp_meta_boxes; 987 988 if ( empty( $screen ) ) 989 $screen = get_current_screen(); 990 elseif ( is_string( $screen ) ) 991 $screen = convert_to_screen( $screen ); 992 993 $page = $screen->id; 994 995 $hidden = get_hidden_meta_boxes( $screen ); 996 ?> 997 <div id="side-sortables" class="accordion-container"> 998 <ul class="outer-border"> 999 <?php 1000 $i = 0; 1001 do { 1002 if ( ! isset( $wp_meta_boxes ) || ! isset( $wp_meta_boxes[$page] ) || ! isset( $wp_meta_boxes[$page][$context] ) ) 1003 break; 1004 1005 foreach ( array( 'high', 'sorted', 'core', 'default', 'low' ) as $priority ) { 1006 if ( isset( $wp_meta_boxes[$page][$context][$priority] ) ) { 1007 foreach ( $wp_meta_boxes[$page][$context][$priority] as $box ) { 1008 if ( false == $box || ! $box['title'] ) 1009 continue; 1010 $i++; 1011 $hidden_class = in_array( $box['id'], $hidden ) ? 'hide-if-js' : ''; 1012 ?> 1013 <li class="control-section accordion-section <?php echo $hidden_class; ?> <?php echo esc_attr( $box['id'] ); ?>" id="<?php echo esc_attr( $box['id'] ); ?>"> 1014 <h3 class="accordion-section-title hndle" tabindex="0" title="<?php echo esc_attr( $box['title'] ); ?>"><?php echo esc_html( $box['title'] ); ?></h3> 1015 <div class="accordion-section-content <?php postbox_classes( $box['id'], $page ); ?>"> 1016 <div class="inside"> 1017 <?php call_user_func( $box['callback'], $object, $box ); ?> 1018 </div><!-- .inside --> 1019 </div><!-- .accordion-section-content --> 1020 </li><!-- .accordion-section --> 1021 <?php 1022 } 1023 } 1024 } 1025 } while(0); 1026 ?> 1027 </ul><!-- .outer-border --> 1028 </div><!-- .accordion-container --> 1029 <?php 1030 return $i; 1031 } 1032 1033 /** 1034 * Add a new section to a settings page. 1035 * 1036 * Part of the Settings API. Use this to define new settings sections for an admin page. 1037 * Show settings sections in your admin page callback function with do_settings_sections(). 1038 * Add settings fields to your section with add_settings_field() 1039 * 1040 * The $callback argument should be the name of a function that echoes out any 1041 * content you want to show at the top of the settings section before the actual 1042 * fields. It can output nothing if you want. 1043 * 1044 * @since 2.7.0 1045 * 1046 * @global $wp_settings_sections Storage array of all settings sections added to admin pages 1047 * 1048 * @param string $id Slug-name to identify the section. Used in the 'id' attribute of tags. 1049 * @param string $title Formatted title of the section. Shown as the heading for the section. 1050 * @param string $callback Function that echos out any content at the top of the section (between heading and fields). 1051 * @param string $page The slug-name of the settings page on which to show the section. Built-in pages include 'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using add_options_page(); 1052 */ 1053 function add_settings_section($id, $title, $callback, $page) { 1054 global $wp_settings_sections; 1055 1056 if ( 'misc' == $page ) { 1057 _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) ); 1058 $page = 'general'; 1059 } 1060 1061 if ( 'privacy' == $page ) { 1062 _deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) ); 1063 $page = 'reading'; 1064 } 1065 1066 if ( !isset($wp_settings_sections) ) 1067 $wp_settings_sections = array(); 1068 if ( !isset($wp_settings_sections[$page]) ) 1069 $wp_settings_sections[$page] = array(); 1070 if ( !isset($wp_settings_sections[$page][$id]) ) 1071 $wp_settings_sections[$page][$id] = array(); 1072 1073 $wp_settings_sections[$page][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback); 1074 } 1075 1076 /** 1077 * Add a new field to a section of a settings page 1078 * 1079 * Part of the Settings API. Use this to define a settings field that will show 1080 * as part of a settings section inside a settings page. The fields are shown using 1081 * do_settings_fields() in do_settings-sections() 1082 * 1083 * The $callback argument should be the name of a function that echoes out the 1084 * html input tags for this setting field. Use get_option() to retrieve existing 1085 * values to show. 1086 * 1087 * @since 2.7.0 1088 * 1089 * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections 1090 * 1091 * @param string $id Slug-name to identify the field. Used in the 'id' attribute of tags. 1092 * @param string $title Formatted title of the field. Shown as the label for the field during output. 1093 * @param string $callback Function that fills the field with the desired form inputs. The function should echo its output. 1094 * @param string $page The slug-name of the settings page on which to show the section (general, reading, writing, ...). 1095 * @param string $section The slug-name of the section of the settings page in which to show the box (default, ...). 1096 * @param array $args Additional arguments 1097 */ 1098 function add_settings_field($id, $title, $callback, $page, $section = 'default', $args = array()) { 1099 global $wp_settings_fields; 1100 1101 if ( 'misc' == $page ) { 1102 _deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) ); 1103 $page = 'general'; 1104 } 1105 1106 if ( 'privacy' == $page ) { 1107 _deprecated_argument( __FUNCTION__, '3.5', __( 'The privacy options group has been removed. Use another settings group.' ) ); 1108 $page = 'reading'; 1109 } 1110 1111 if ( !isset($wp_settings_fields) ) 1112 $wp_settings_fields = array(); 1113 if ( !isset($wp_settings_fields[$page]) ) 1114 $wp_settings_fields[$page] = array(); 1115 if ( !isset($wp_settings_fields[$page][$section]) ) 1116 $wp_settings_fields[$page][$section] = array(); 1117 1118 $wp_settings_fields[$page][$section][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $args); 1119 } 1120 1121 /** 1122 * Prints out all settings sections added to a particular settings page 1123 * 1124 * Part of the Settings API. Use this in a settings page callback function 1125 * to output all the sections and fields that were added to that $page with 1126 * add_settings_section() and add_settings_field() 1127 * 1128 * @global $wp_settings_sections Storage array of all settings sections added to admin pages 1129 * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections 1130 * @since 2.7.0 1131 * 1132 * @param string $page The slug name of the page whos settings sections you want to output 1133 */ 1134 function do_settings_sections( $page ) { 1135 global $wp_settings_sections, $wp_settings_fields; 1136 1137 if ( ! isset( $wp_settings_sections ) || !isset( $wp_settings_sections[$page] ) ) 1138 return; 1139 1140 foreach ( (array) $wp_settings_sections[$page] as $section ) { 1141 if ( $section['title'] ) 1142 echo "<h3>{$section['title']}</h3>\n"; 1143 1144 if ( $section['callback'] ) 1145 call_user_func( $section['callback'], $section ); 1146 1147 if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) ) 1148 continue; 1149 echo '<table class="form-table">'; 1150 do_settings_fields( $page, $section['id'] ); 1151 echo '</table>'; 1152 } 1153 } 1154 1155 /** 1156 * Print out the settings fields for a particular settings section 1157 * 1158 * Part of the Settings API. Use this in a settings page to output 1159 * a specific section. Should normally be called by do_settings_sections() 1160 * rather than directly. 1161 * 1162 * @global $wp_settings_fields Storage array of settings fields and their pages/sections 1163 * 1164 * @since 2.7.0 1165 * 1166 * @param string $page Slug title of the admin page who's settings fields you want to show. 1167 * @param section $section Slug title of the settings section who's fields you want to show. 1168 */ 1169 function do_settings_fields($page, $section) { 1170 global $wp_settings_fields; 1171 1172 if ( !isset($wp_settings_fields) || !isset($wp_settings_fields[$page]) || !isset($wp_settings_fields[$page][$section]) ) 1173 return; 1174 1175 foreach ( (array) $wp_settings_fields[$page][$section] as $field ) { 1176 echo '<tr valign="top">'; 1177 if ( !empty($field['args']['label_for']) ) 1178 echo '<th scope="row"><label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label></th>'; 1179 else 1180 echo '<th scope="row">' . $field['title'] . '</th>'; 1181 echo '<td>'; 1182 call_user_func($field['callback'], $field['args']); 1183 echo '</td>'; 1184 echo '</tr>'; 1185 } 1186 } 1187 1188 /** 1189 * Register a settings error to be displayed to the user 1190 * 1191 * Part of the Settings API. Use this to show messages to users about settings validation 1192 * problems, missing settings or anything else. 1193 * 1194 * Settings errors should be added inside the $sanitize_callback function defined in 1195 * register_setting() for a given setting to give feedback about the submission. 1196 * 1197 * By default messages will show immediately after the submission that generated the error. 1198 * Additional calls to settings_errors() can be used to show errors even when the settings 1199 * page is first accessed. 1200 * 1201 * @since 3.0.0 1202 * 1203 * @global array $wp_settings_errors Storage array of errors registered during this pageload 1204 * 1205 * @param string $setting Slug title of the setting to which this error applies 1206 * @param string $code Slug-name to identify the error. Used as part of 'id' attribute in HTML output. 1207 * @param string $message The formatted message text to display to the user (will be shown inside styled <div> and <p>) 1208 * @param string $type The type of message it is, controls HTML class. Use 'error' or 'updated'. 1209 */ 1210 function add_settings_error( $setting, $code, $message, $type = 'error' ) { 1211 global $wp_settings_errors; 1212 1213 if ( !isset($wp_settings_errors) ) 1214 $wp_settings_errors = array(); 1215 1216 $new_error = array( 1217 'setting' => $setting, 1218 'code' => $code, 1219 'message' => $message, 1220 'type' => $type 1221 ); 1222 $wp_settings_errors[] = $new_error; 1223 } 1224 1225 /** 1226 * Fetch settings errors registered by add_settings_error() 1227 * 1228 * Checks the $wp_settings_errors array for any errors declared during the current 1229 * pageload and returns them. 1230 * 1231 * If changes were just submitted ($_GET['settings-updated']) and settings errors were saved 1232 * to the 'settings_errors' transient then those errors will be returned instead. This 1233 * is used to pass errors back across pageloads. 1234 * 1235 * Use the $sanitize argument to manually re-sanitize the option before returning errors. 1236 * This is useful if you have errors or notices you want to show even when the user 1237 * hasn't submitted data (i.e. when they first load an options page, or in admin_notices action hook) 1238 * 1239 * @since 3.0.0 1240 * 1241 * @global array $wp_settings_errors Storage array of errors registered during this pageload 1242 * 1243 * @param string $setting Optional slug title of a specific setting who's errors you want. 1244 * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors. 1245 * @return array Array of settings errors 1246 */ 1247 function get_settings_errors( $setting = '', $sanitize = false ) { 1248 global $wp_settings_errors; 1249 1250 // If $sanitize is true, manually re-run the sanitizisation for this option 1251 // This allows the $sanitize_callback from register_setting() to run, adding 1252 // any settings errors you want to show by default. 1253 if ( $sanitize ) 1254 sanitize_option( $setting, get_option( $setting ) ); 1255 1256 // If settings were passed back from options.php then use them 1257 if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && get_transient( 'settings_errors' ) ) { 1258 $wp_settings_errors = array_merge( (array) $wp_settings_errors, get_transient( 'settings_errors' ) ); 1259 delete_transient( 'settings_errors' ); 1260 } 1261 1262 // Check global in case errors have been added on this pageload 1263 if ( ! count( $wp_settings_errors ) ) 1264 return array(); 1265 1266 // Filter the results to those of a specific setting if one was set 1267 if ( $setting ) { 1268 $setting_errors = array(); 1269 foreach ( (array) $wp_settings_errors as $key => $details ) { 1270 if ( $setting == $details['setting'] ) 1271 $setting_errors[] = $wp_settings_errors[$key]; 1272 } 1273 return $setting_errors; 1274 } 1275 1276 return $wp_settings_errors; 1277 } 1278 1279 /** 1280 * Display settings errors registered by add_settings_error() 1281 * 1282 * Part of the Settings API. Outputs a <div> for each error retrieved by get_settings_errors(). 1283 * 1284 * This is called automatically after a settings page based on the Settings API is submitted. 1285 * Errors should be added during the validation callback function for a setting defined in register_setting() 1286 * 1287 * The $sanitize option is passed into get_settings_errors() and will re-run the setting sanitization 1288 * on its current value. 1289 * 1290 * The $hide_on_update option will cause errors to only show when the settings page is first loaded. 1291 * if the user has already saved new values it will be hidden to avoid repeating messages already 1292 * shown in the default error reporting after submission. This is useful to show general errors like missing 1293 * settings when the user arrives at the settings page. 1294 * 1295 * @since 3.0.0 1296 * 1297 * @param string $setting Optional slug title of a specific setting who's errors you want. 1298 * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors. 1299 * @param boolean $hide_on_update If set to true errors will not be shown if the settings page has already been submitted. 1300 */ 1301 function settings_errors( $setting = '', $sanitize = false, $hide_on_update = false ) { 1302 1303 if ( $hide_on_update && ! empty( $_GET['settings-updated'] ) ) 1304 return; 1305 1306 $settings_errors = get_settings_errors( $setting, $sanitize ); 1307 1308 if ( empty( $settings_errors ) ) 1309 return; 1310 1311 $output = ''; 1312 foreach ( $settings_errors as $key => $details ) { 1313 $css_id = 'setting-error-' . $details['code']; 1314 $css_class = $details['type'] . ' settings-error'; 1315 $output .= "<div id='$css_id' class='$css_class'> \n"; 1316 $output .= "<p><strong>{$details['message']}</strong></p>"; 1317 $output .= "</div> \n"; 1318 } 1319 echo $output; 1320 } 1321 1322 /** 1323 * {@internal Missing Short Description}} 1324 * 1325 * @since 2.7.0 1326 * 1327 * @param unknown_type $found_action 1328 */ 1329 function find_posts_div($found_action = '') { 1330 ?> 1331 <div id="find-posts" class="find-box" style="display:none;"> 1332 <div id="find-posts-head" class="find-box-head"><?php _e('Find Posts or Pages'); ?></div> 1333 <div class="find-box-inside"> 1334 <div class="find-box-search"> 1335 <?php if ( $found_action ) { ?> 1336 <input type="hidden" name="found_action" value="<?php echo esc_attr($found_action); ?>" /> 1337 <?php } ?> 1338 1339 <input type="hidden" name="affected" id="affected" value="" /> 1340 <?php wp_nonce_field( 'find-posts', '_ajax_nonce', false ); ?> 1341 <label class="screen-reader-text" for="find-posts-input"><?php _e( 'Search' ); ?></label> 1342 <input type="text" id="find-posts-input" name="ps" value="" /> 1343 <span class="spinner"></span> 1344 <input type="button" id="find-posts-search" value="<?php esc_attr_e( 'Search' ); ?>" class="button" /> 1345 </div> 1346 <div id="find-posts-response"></div> 1347 </div> 1348 <div class="find-box-buttons"> 1349 <input id="find-posts-close" type="button" class="button alignleft" value="<?php esc_attr_e('Close'); ?>" /> 1350 <?php submit_button( __( 'Select' ), 'button-primary alignright', 'find-posts-submit', false ); ?> 1351 </div> 1352 </div> 1353 <?php 1354 } 1355 1356 /** 1357 * Display the post password. 1358 * 1359 * The password is passed through {@link esc_attr()} to ensure that it 1360 * is safe for placing in an html attribute. 1361 * 1362 * @uses attr 1363 * @since 2.7.0 1364 */ 1365 function the_post_password() { 1366 $post = get_post(); 1367 if ( isset( $post->post_password ) ) 1368 echo esc_attr( $post->post_password ); 1369 } 1370 1371 /** 1372 * Get the post title. 1373 * 1374 * The post title is fetched and if it is blank then a default string is 1375 * returned. 1376 * 1377 * @since 2.7.0 1378 * @param mixed $post Post id or object. If not supplied the global $post is used. 1379 * @return string The post title if set 1380 */ 1381 function _draft_or_post_title( $post = 0 ) { 1382 $title = get_the_title( $post ); 1383 if ( empty( $title ) ) 1384 $title = __( '(no title)' ); 1385 return $title; 1386 } 1387 1388 /** 1389 * Display the search query. 1390 * 1391 * A simple wrapper to display the "s" parameter in a GET URI. This function 1392 * should only be used when {@link the_search_query()} cannot. 1393 * 1394 * @uses attr 1395 * @since 2.7.0 1396 * 1397 */ 1398 function _admin_search_query() { 1399 echo isset($_REQUEST['s']) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; 1400 } 1401 1402 /** 1403 * Generic Iframe header for use with Thickbox 1404 * 1405 * @since 2.7.0 1406 * @param string $title Title of the Iframe page. 1407 * @param bool $limit_styles Limit styles to colour-related styles only (unless others are enqueued). 1408 * 1409 */ 1410 function iframe_header( $title = '', $limit_styles = false ) { 1411 show_admin_bar( false ); 1412 global $hook_suffix, $current_user, $admin_body_class, $wp_locale; 1413 $admin_body_class = preg_replace('/[^a-z0-9_-]+/i', '-', $hook_suffix); 1414 1415 $current_screen = get_current_screen(); 1416 1417 @header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) ); 1418 _wp_admin_html_begin(); 1419 ?> 1420 <title><?php bloginfo('name') ?> › <?php echo $title ?> — <?php _e('WordPress'); ?></title> 1421 <?php 1422 wp_enqueue_style( 'colors' ); 1423 ?> 1424 <script type="text/javascript"> 1425 //<![CDATA[ 1426 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();}}}; 1427 function tb_close(){var win=window.dialogArguments||opener||parent||top;win.tb_remove();} 1428 var ajaxurl = '<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>', 1429 pagenow = '<?php echo $current_screen->id; ?>', 1430 typenow = '<?php echo $current_screen->post_type; ?>', 1431 adminpage = '<?php echo $admin_body_class; ?>', 1432 thousandsSeparator = '<?php echo addslashes( $wp_locale->number_format['thousands_sep'] ); ?>', 1433 decimalPoint = '<?php echo addslashes( $wp_locale->number_format['decimal_point'] ); ?>', 1434 isRtl = <?php echo (int) is_rtl(); ?>; 1435 //]]> 1436 </script> 1437 <?php 1438 do_action('admin_enqueue_scripts', $hook_suffix); 1439 do_action("admin_print_styles-$hook_suffix"); 1440 do_action('admin_print_styles'); 1441 do_action("admin_print_scripts-$hook_suffix"); 1442 do_action('admin_print_scripts'); 1443 do_action("admin_head-$hook_suffix"); 1444 do_action('admin_head'); 1445 1446 $admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); 1447 ?> 1448 </head> 1449 <body<?php if ( isset($GLOBALS['body_id']) ) echo ' id="' . $GLOBALS['body_id'] . '"'; ?> class="wp-admin wp-core-ui no-js iframe <?php echo apply_filters( 'admin_body_class', '' ) . ' ' . $admin_body_class; ?>"> 1450 <script type="text/javascript"> 1451 //<![CDATA[ 1452 (function(){ 1453 var c = document.body.className; 1454 c = c.replace(/no-js/, 'js'); 1455 document.body.className = c; 1456 })(); 1457 //]]> 1458 </script> 1459 <?php 1460 } 1461 1462 /** 1463 * Generic Iframe footer for use with Thickbox 1464 * 1465 * @since 2.7.0 1466 * 1467 */ 1468 function iframe_footer() { 1469 //We're going to hide any footer output on iframe pages, but run the hooks anyway since they output Javascript or other needed content. ?> 1470 <div class="hidden"> 1471 <?php 1472 do_action('admin_footer', ''); 1473 do_action('admin_print_footer_scripts'); ?> 1474 </div> 1475 <script type="text/javascript">if(typeof wpOnload=="function")wpOnload();</script> 1476 </body> 1477 </html> 1478 <?php 1479 } 1480 1481 function _post_states($post) { 1482 $post_states = array(); 1483 if ( isset( $_REQUEST['post_status'] ) ) 1484 $post_status = $_REQUEST['post_status']; 1485 else 1486 $post_status = ''; 1487 1488 if ( !empty($post->post_password) ) 1489 $post_states['protected'] = __('Password protected'); 1490 if ( 'private' == $post->post_status && 'private' != $post_status ) 1491 $post_states['private'] = __('Private'); 1492 if ( 'draft' == $post->post_status && 'draft' != $post_status ) 1493 $post_states['draft'] = __('Draft'); 1494 if ( 'pending' == $post->post_status && 'pending' != $post_status ) 1495 /* translators: post state */ 1496 $post_states['pending'] = _x('Pending', 'post state'); 1497 if ( is_sticky($post->ID) ) 1498 $post_states['sticky'] = __('Sticky'); 1499 1500 $post_states = apply_filters( 'display_post_states', $post_states, $post ); 1501 1502 if ( ! empty($post_states) ) { 1503 $state_count = count($post_states); 1504 $i = 0; 1505 echo ' - '; 1506 foreach ( $post_states as $state ) { 1507 ++$i; 1508 ( $i == $state_count ) ? $sep = '' : $sep = ', '; 1509 echo "<span class='post-state'>$state$sep</span>"; 1510 } 1511 } 1512 1513 } 1514 1515 function _media_states( $post ) { 1516 $media_states = array(); 1517 $stylesheet = get_option('stylesheet'); 1518 1519 if ( current_theme_supports( 'custom-header') ) { 1520 $meta_header = get_post_meta($post->ID, '_wp_attachment_is_custom_header', true ); 1521 if ( ! empty( $meta_header ) && $meta_header == $stylesheet ) 1522 $media_states[] = __( 'Header Image' ); 1523 } 1524 1525 if ( current_theme_supports( 'custom-background') ) { 1526 $meta_background = get_post_meta($post->ID, '_wp_attachment_is_custom_background', true ); 1527 if ( ! empty( $meta_background ) && $meta_background == $stylesheet ) 1528 $media_states[] = __( 'Background Image' ); 1529 } 1530 1531 $media_states = apply_filters( 'display_media_states', $media_states ); 1532 1533 if ( ! empty( $media_states ) ) { 1534 $state_count = count( $media_states ); 1535 $i = 0; 1536 echo ' - '; 1537 foreach ( $media_states as $state ) { 1538 ++$i; 1539 ( $i == $state_count ) ? $sep = '' : $sep = ', '; 1540 echo "<span class='post-state'>$state$sep</span>"; 1541 } 1542 } 1543 } 1544 1545 /** 1546 * Test support for compressing JavaScript from PHP 1547 * 1548 * Outputs JavaScript that tests if compression from PHP works as expected 1549 * and sets an option with the result. Has no effect when the current user 1550 * is not an administrator. To run the test again the option 'can_compress_scripts' 1551 * has to be deleted. 1552 * 1553 * @since 2.8.0 1554 */ 1555 function compression_test() { 1556 ?> 1557 <script type="text/javascript"> 1558 /* <![CDATA[ */ 1559 var testCompression = { 1560 get : function(test) { 1561 var x; 1562 if ( window.XMLHttpRequest ) { 1563 x = new XMLHttpRequest(); 1564 } else { 1565 try{x=new ActiveXObject('Msxml2.XMLHTTP');}catch(e){try{x=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){};} 1566 } 1567 1568 if (x) { 1569 x.onreadystatechange = function() { 1570 var r, h; 1571 if ( x.readyState == 4 ) { 1572 r = x.responseText.substr(0, 18); 1573 h = x.getResponseHeader('Content-Encoding'); 1574 testCompression.check(r, h, test); 1575 } 1576 } 1577 1578 x.open('GET', ajaxurl + '?action=wp-compression-test&test='+test+'&'+(new Date()).getTime(), true); 1579 x.send(''); 1580 } 1581 }, 1582 1583 check : function(r, h, test) { 1584 if ( ! r && ! test ) 1585 this.get(1); 1586 1587 if ( 1 == test ) { 1588 if ( h && ( h.match(/deflate/i) || h.match(/gzip/i) ) ) 1589 this.get('no'); 1590 else 1591 this.get(2); 1592 1593 return; 1594 } 1595 1596 if ( 2 == test ) { 1597 if ( '"wpCompressionTest' == r ) 1598 this.get('yes'); 1599 else 1600 this.get('no'); 1601 } 1602 } 1603 }; 1604 testCompression.check(); 1605 /* ]]> */ 1606 </script> 1607 <?php 1608 } 1609 1610 /** 1611 * Echos a submit button, with provided text and appropriate class 1612 * 1613 * @since 3.1.0 1614 * 1615 * @param string $text The text of the button (defaults to 'Save Changes') 1616 * @param string $type The type of button. One of: primary, secondary, delete 1617 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute 1618 * is given in $other_attributes below, $name will be used as the button's id. 1619 * @param bool $wrap True if the output button should be wrapped in a paragraph tag, 1620 * false otherwise. Defaults to true 1621 * @param array|string $other_attributes Other attributes that should be output with the button, 1622 * mapping attributes to their values, such as array( 'tabindex' => '1' ). 1623 * These attributes will be output as attribute="value", such as tabindex="1". 1624 * Defaults to no other attributes. Other attributes can also be provided as a 1625 * string such as 'tabindex="1"', though the array format is typically cleaner. 1626 */ 1627 function submit_button( $text = null, $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = null ) { 1628 echo get_submit_button( $text, $type, $name, $wrap, $other_attributes ); 1629 } 1630 1631 /** 1632 * Returns a submit button, with provided text and appropriate class 1633 * 1634 * @since 3.1.0 1635 * 1636 * @param string $text The text of the button (defaults to 'Save Changes') 1637 * @param string $type The type of button. One of: primary, secondary, delete 1638 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute 1639 * is given in $other_attributes below, $name will be used as the button's id. 1640 * @param bool $wrap True if the output button should be wrapped in a paragraph tag, 1641 * false otherwise. Defaults to true 1642 * @param array|string $other_attributes Other attributes that should be output with the button, 1643 * mapping attributes to their values, such as array( 'tabindex' => '1' ). 1644 * These attributes will be output as attribute="value", such as tabindex="1". 1645 * Defaults to no other attributes. Other attributes can also be provided as a 1646 * string such as 'tabindex="1"', though the array format is typically cleaner. 1647 */ 1648 function get_submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) { 1649 if ( ! is_array( $type ) ) 1650 $type = explode( ' ', $type ); 1651 1652 $button_shorthand = array( 'primary', 'small', 'large' ); 1653 $classes = array( 'button' ); 1654 foreach ( $type as $t ) { 1655 if ( 'secondary' === $t || 'button-secondary' === $t ) 1656 continue; 1657 $classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t; 1658 } 1659 $class = implode( ' ', array_unique( $classes ) ); 1660 1661 if ( 'delete' === $type ) 1662 $class = 'button-secondary delete'; 1663 1664 $text = $text ? $text : __( 'Save Changes' ); 1665 1666 // Default the id attribute to $name unless an id was specifically provided in $other_attributes 1667 $id = $name; 1668 if ( is_array( $other_attributes ) && isset( $other_attributes['id'] ) ) { 1669 $id = $other_attributes['id']; 1670 unset( $other_attributes['id'] ); 1671 } 1672 1673 $attributes = ''; 1674 if ( is_array( $other_attributes ) ) { 1675 foreach ( $other_attributes as $attribute => $value ) { 1676 $attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important 1677 } 1678 } else if ( !empty( $other_attributes ) ) { // Attributes provided as a string 1679 $attributes = $other_attributes; 1680 } 1681 1682 $button = '<input type="submit" name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ); 1683 $button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />'; 1684 1685 if ( $wrap ) { 1686 $button = '<p class="submit">' . $button . '</p>'; 1687 } 1688 1689 return $button; 1690 } 1691 1692 function _wp_admin_html_begin() { 1693 $admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : ''; 1694 ?> 1695 <!DOCTYPE html> 1696 <!--[if IE 8]> 1697 <html xmlns="http://www.w3.org/1999/xhtml" class="ie8 <?php echo $admin_html_class; ?>" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>> 1698 <![endif]--> 1699 <!--[if !(IE 8) ]><!--> 1700 <html xmlns="http://www.w3.org/1999/xhtml" class="<?php echo $admin_html_class; ?>" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>> 1701 <!--<![endif]--> 1702 <head> 1703 <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" /> 1704 <?php 1705 } 1706 1707 final class WP_Internal_Pointers { 1708 /** 1709 * Initializes the new feature pointers. 1710 * 1711 * @since 3.3.0 1712 * 1713 * All pointers can be disabled using the following: 1714 * remove_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) ); 1715 * 1716 * Individual pointers (e.g. wp330_toolbar) can be disabled using the following: 1717 * remove_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_wp330_toolbar' ) ); 1718 */ 1719 public static function enqueue_scripts( $hook_suffix ) { 1720 /* 1721 * Register feature pointers 1722 * Format: array( hook_suffix => pointer_id ) 1723 */ 1724 1725 $registered_pointers = array( 1726 'index.php' => 'wp330_toolbar', 1727 'post-new.php' => 'wp350_media', 1728 'post.php' => 'wp350_media', 1729 'themes.php' => array( 'wp330_saving_widgets', 'wp340_customize_current_theme_link' ), 1730 'appearance_page_custom-header' => 'wp340_choose_image_from_library', 1731 'appearance_page_custom-background' => 'wp340_choose_image_from_library', 1732 ); 1733 1734 // Check if screen related pointer is registered 1735 if ( empty( $registered_pointers[ $hook_suffix ] ) ) 1736 return; 1737 1738 $pointers = (array) $registered_pointers[ $hook_suffix ]; 1739 1740 $caps_required = array( 1741 'wp330_saving_widgets' => array( 'edit_theme_options', 'switch_themes' ), 1742 'wp340_customize_current_theme_link' => array( 'edit_theme_options' ), 1743 'wp340_choose_image_from_library' => array( 'edit_theme_options' ), 1744 'wp350_media' => array( 'upload_files' ), 1745 ); 1746 1747 // Get dismissed pointers 1748 $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); 1749 1750 $got_pointers = false; 1751 foreach ( array_diff( $pointers, $dismissed ) as $pointer ) { 1752 if ( isset( $caps_required[ $pointer ] ) ) { 1753 foreach ( $caps_required[ $pointer ] as $cap ) { 1754 if ( ! current_user_can( $cap ) ) 1755 continue 2; 1756 } 1757 } 1758 1759 // Bind pointer print function 1760 add_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_' . $pointer ) ); 1761 $got_pointers = true; 1762 } 1763 1764 if ( ! $got_pointers ) 1765 return; 1766 1767 // Add pointers script and style to queue 1768 wp_enqueue_style( 'wp-pointer' ); 1769 wp_enqueue_script( 'wp-pointer' ); 1770 } 1771 1772 /** 1773 * Print the pointer javascript data. 1774 * 1775 * @since 3.3.0 1776 * 1777 * @param string $pointer_id The pointer ID. 1778 * @param string $selector The HTML elements, on which the pointer should be attached. 1779 * @param array $args Arguments to be passed to the pointer JS (see wp-pointer.js). 1780 */ 1781 private static function print_js( $pointer_id, $selector, $args ) { 1782 if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) ) 1783 return; 1784 1785 ?> 1786 <script type="text/javascript"> 1787 //<![CDATA[ 1788 (function($){ 1789 var options = <?php echo json_encode( $args ); ?>, setup; 1790 1791 if ( ! options ) 1792 return; 1793 1794 options = $.extend( options, { 1795 close: function() { 1796 $.post( ajaxurl, { 1797 pointer: '<?php echo $pointer_id; ?>', 1798 action: 'dismiss-wp-pointer' 1799 }); 1800 } 1801 }); 1802 1803 setup = function() { 1804 $('<?php echo $selector; ?>').pointer( options ).pointer('open'); 1805 }; 1806 1807 if ( options.position && options.position.defer_loading ) 1808 $(window).bind( 'load.wp-pointers', setup ); 1809 else 1810 $(document).ready( setup ); 1811 1812 })( jQuery ); 1813 //]]> 1814 </script> 1815 <?php 1816 } 1817 1818 public static function pointer_wp330_toolbar() { 1819 $content = '<h3>' . __( 'New Feature: Toolbar' ) . '</h3>'; 1820 $content .= '<p>' . __( 'We’ve combined the admin bar and the old Dashboard header into one persistent toolbar. Hover over the toolbar items to see what’s new.' ) . '</p>'; 1821 1822 if ( is_multisite() && is_super_admin() ) 1823 $content .= '<p>' . __( 'Network Admin is now located in the My Sites menu.' ) . '</p>'; 1824 1825 WP_Internal_Pointers::print_js( 'wp330_toolbar', '#wpadminbar', array( 1826 'content' => $content, 1827 'position' => array( 'edge' => 'top', 'align' => 'center' ), 1828 ) ); 1829 } 1830 1831 /** 1832 * Print 'Updated Media Uploader' for 3.3.0. 1833 * 1834 * @since 3.3.0 1835 */ 1836 public static function pointer_wp330_media_uploader() {} 1837 1838 /** 1839 * Print 'New Feature: Saving Widgets' for 3.3.0. 1840 * 1841 * @since 3.3.0 1842 */ 1843 public static function pointer_wp330_saving_widgets() { 1844 $content = '<h3>' . __( 'New Feature: Saving Widgets' ) . '</h3>'; 1845 $content .= '<p>' . __( 'If you change your mind and revert to your previous theme, we’ll put the widgets back the way you had them.' ) . '</p>'; 1846 1847 WP_Internal_Pointers::print_js( 'wp330_saving_widgets', '#message2', array( 1848 'content' => $content, 1849 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left' ), 1850 ) ); 1851 } 1852 1853 /** 1854 * Print 'New Feature: Current Theme Customize Link' for 3.4.0. 1855 * 1856 * @since 3.4.0 1857 */ 1858 public static function pointer_wp340_customize_current_theme_link() { 1859 $content = '<h3>' . __( 'New Feature: Customizer' ) . '</h3>'; 1860 $content .= '<p>' . __( 'Click Customize to change the header, background, title and menus of the current theme, all in one place.' ) . '</p>'; 1861 $content .= '<p>' . __( 'Click the Live Preview links in the Available Themes list below to customize and preview another theme before activating it.' ) . '</p>'; 1862 1863 WP_Internal_Pointers::print_js( 'wp340_customize_current_theme_link', '#customize-current-theme-link', array( 1864 'content' => $content, 1865 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'offset' => is_rtl() ? '32 0' : '-32 0' ), 1866 ) ); 1867 } 1868 1869 /** 1870 * Print 'New Feature: Choose Image from Library' for 3.4.0. 1871 * 1872 * @since 3.4.0 1873 */ 1874 public static function pointer_wp340_choose_image_from_library() { 1875 $content = '<h3>' . __( 'New Feature: Choose Image from Library' ) . '</h3>'; 1876 $content .= '<p>' . __( 'Want to use an image you uploaded earlier? Select it from your media library instead of uploading it again.' ) . '</p>'; 1877 1878 WP_Internal_Pointers::print_js( 'wp340_choose_image_from_library', '#choose-from-library-link', array( 1879 'content' => $content, 1880 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'defer_loading' => true ), 1881 ) ); 1882 } 1883 1884 public static function pointer_wp350_media() { 1885 $content = '<h3>' . __( 'New Media Manager' ) . '</h3>'; 1886 $content .= '<p>' . __( 'Uploading files and creating image galleries has a whole new look. Check it out!' ) . '</p>'; 1887 1888 self::print_js( 'wp350_media', '.insert-media', array( 1889 'content' => $content, 1890 'position' => array( 'edge' => is_rtl() ? 'right' : 'left', 'align' => 'center' ), 1891 ) ); 1892 } 1893 1894 /** 1895 * Prevents new users from seeing existing 'new feature' pointers. 1896 * 1897 * @since 3.3.0 1898 */ 1899 public static function dismiss_pointers_for_new_users( $user_id ) { 1900 add_user_meta( $user_id, 'dismissed_wp_pointers', 'wp330_toolbar,wp330_saving_widgets,wp340_choose_image_from_library,wp340_customize_current_theme_link,wp350_media' ); 1901 } 1902 } 1903 1904 add_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) ); 1905 add_action( 'user_register', array( 'WP_Internal_Pointers', 'dismiss_pointers_for_new_users' ) ); 1906 1907 /** 1908 * Convert a screen string to a screen object 1909 * 1910 * @since 3.0.0 1911 * 1912 * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen. 1913 * @return WP_Screen Screen object. 1914 */ 1915 function convert_to_screen( $hook_name ) { 1916 if ( ! class_exists( 'WP_Screen' ) ) { 1917 _doing_it_wrong( 'convert_to_screen(), add_meta_box()', __( "Likely direct inclusion of wp-admin/includes/template.php in order to use add_meta_box(). This is very wrong. Hook the add_meta_box() call into the add_meta_boxes action instead." ), '3.3' ); 1918 return (object) array( 'id' => '_invalid', 'base' => '_are_belong_to_us' ); 1919 } 1920 1921 return WP_Screen::get( $hook_name ); 1922 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed May 22 03:56:25 2013 | Hosted by follow the white rabbit. |