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