| [ XREF Home ] [ Index ] |
PHP Cross Reference of WordPress TrunkProvided by Yoast |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Theme, template, and stylesheet functions. 4 * 5 * @package WordPress 6 * @subpackage Template 7 */ 8 9 /** 10 * Whether a child theme is in use. 11 * 12 * @since 3.0.0 13 * 14 * @return bool true if a child theme is in use, false otherwise. 15 **/ 16 function is_child_theme() { 17 return ( TEMPLATEPATH !== STYLESHEETPATH ); 18 } 19 20 /** 21 * Retrieve name of the current stylesheet. 22 * 23 * The theme name that the administrator has currently set the front end theme 24 * as. 25 * 26 * For all extensive purposes, the template name and the stylesheet name are 27 * going to be the same for most cases. 28 * 29 * @since 1.5.0 30 * @uses apply_filters() Calls 'stylesheet' filter on stylesheet name. 31 * 32 * @return string Stylesheet name. 33 */ 34 function get_stylesheet() { 35 return apply_filters('stylesheet', get_option('stylesheet')); 36 } 37 38 /** 39 * Retrieve stylesheet directory path for current theme. 40 * 41 * @since 1.5.0 42 * @uses apply_filters() Calls 'stylesheet_directory' filter on stylesheet directory and theme name. 43 * 44 * @return string Path to current theme directory. 45 */ 46 function get_stylesheet_directory() { 47 $stylesheet = get_stylesheet(); 48 $theme_root = get_theme_root( $stylesheet ); 49 $stylesheet_dir = "$theme_root/$stylesheet"; 50 51 return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root ); 52 } 53 54 /** 55 * Retrieve stylesheet directory URI. 56 * 57 * @since 1.5.0 58 * 59 * @return string 60 */ 61 function get_stylesheet_directory_uri() { 62 $stylesheet = get_stylesheet(); 63 $theme_root_uri = get_theme_root_uri( $stylesheet ); 64 $stylesheet_dir_uri = "$theme_root_uri/$stylesheet"; 65 66 return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri ); 67 } 68 69 /** 70 * Retrieve URI of current theme stylesheet. 71 * 72 * The stylesheet file name is 'style.css' which is appended to {@link 73 * get_stylesheet_directory_uri() stylesheet directory URI} path. 74 * 75 * @since 1.5.0 76 * @uses apply_filters() Calls 'stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI. 77 * 78 * @return string 79 */ 80 function get_stylesheet_uri() { 81 $stylesheet_dir_uri = get_stylesheet_directory_uri(); 82 $stylesheet_uri = $stylesheet_dir_uri . '/style.css'; 83 return apply_filters('stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri); 84 } 85 86 /** 87 * Retrieve localized stylesheet URI. 88 * 89 * The stylesheet directory for the localized stylesheet files are located, by 90 * default, in the base theme directory. The name of the locale file will be the 91 * locale followed by '.css'. If that does not exist, then the text direction 92 * stylesheet will be checked for existence, for example 'ltr.css'. 93 * 94 * The theme may change the location of the stylesheet directory by either using 95 * the 'stylesheet_directory_uri' filter or the 'locale_stylesheet_uri' filter. 96 * If you want to change the location of the stylesheet files for the entire 97 * WordPress workflow, then change the former. If you just have the locale in a 98 * separate folder, then change the latter. 99 * 100 * @since 2.1.0 101 * @uses apply_filters() Calls 'locale_stylesheet_uri' filter on stylesheet URI path and stylesheet directory URI. 102 * 103 * @return string 104 */ 105 function get_locale_stylesheet_uri() { 106 global $wp_locale; 107 $stylesheet_dir_uri = get_stylesheet_directory_uri(); 108 $dir = get_stylesheet_directory(); 109 $locale = get_locale(); 110 if ( file_exists("$dir/$locale.css") ) 111 $stylesheet_uri = "$stylesheet_dir_uri/$locale.css"; 112 elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") ) 113 $stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css"; 114 else 115 $stylesheet_uri = ''; 116 return apply_filters('locale_stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri); 117 } 118 119 /** 120 * Retrieve name of the current theme. 121 * 122 * @since 1.5.0 123 * @uses apply_filters() Calls 'template' filter on template option. 124 * 125 * @return string Template name. 126 */ 127 function get_template() { 128 return apply_filters('template', get_option('template')); 129 } 130 131 /** 132 * Retrieve current theme directory. 133 * 134 * @since 1.5.0 135 * @uses apply_filters() Calls 'template_directory' filter on template directory path and template name. 136 * 137 * @return string Template directory path. 138 */ 139 function get_template_directory() { 140 $template = get_template(); 141 $theme_root = get_theme_root( $template ); 142 $template_dir = "$theme_root/$template"; 143 144 return apply_filters( 'template_directory', $template_dir, $template, $theme_root ); 145 } 146 147 /** 148 * Retrieve theme directory URI. 149 * 150 * @since 1.5.0 151 * @uses apply_filters() Calls 'template_directory_uri' filter on template directory URI path and template name. 152 * 153 * @return string Template directory URI. 154 */ 155 function get_template_directory_uri() { 156 $template = get_template(); 157 $theme_root_uri = get_theme_root_uri( $template ); 158 $template_dir_uri = "$theme_root_uri/$template"; 159 160 return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri ); 161 } 162 163 /** 164 * Retrieve theme data from parsed theme file. 165 * 166 * The description will have the tags filtered with the following HTML elements 167 * whitelisted. The <b>'a'</b> element with the <em>href</em> and <em>title</em> 168 * attributes. The <b>abbr</b> element with the <em>title</em> attribute. The 169 * <b>acronym</b> element with the <em>title</em> attribute allowed. The 170 * <b>code</b>, <b>em</b>, and <b>strong</b> elements also allowed. 171 * 172 * The style.css file must contain theme name, theme URI, and description. The 173 * data can also contain author URI, author, template (parent template), 174 * version, status, and finally tags. Some of these are not used by WordPress 175 * administration panels, but are used by theme directory web sites which list 176 * the theme. 177 * 178 * @since 1.5.0 179 * 180 * @param string $theme_file Theme file path. 181 * @return array Theme data. 182 */ 183 function get_theme_data( $theme_file ) { 184 $default_headers = array( 185 'Name' => 'Theme Name', 186 'URI' => 'Theme URI', 187 'Description' => 'Description', 188 'Author' => 'Author', 189 'AuthorURI' => 'Author URI', 190 'Version' => 'Version', 191 'Template' => 'Template', 192 'Status' => 'Status', 193 'Tags' => 'Tags' 194 ); 195 196 $themes_allowed_tags = array( 197 'a' => array( 198 'href' => array(),'title' => array() 199 ), 200 'abbr' => array( 201 'title' => array() 202 ), 203 'acronym' => array( 204 'title' => array() 205 ), 206 'code' => array(), 207 'em' => array(), 208 'strong' => array() 209 ); 210 211 $theme_data = get_file_data( $theme_file, $default_headers, 'theme' ); 212 213 $theme_data['Name'] = $theme_data['Title'] = wp_kses( $theme_data['Name'], $themes_allowed_tags ); 214 215 $theme_data['URI'] = esc_url( $theme_data['URI'] ); 216 217 $theme_data['Description'] = wptexturize( wp_kses( $theme_data['Description'], $themes_allowed_tags ) ); 218 219 $theme_data['AuthorURI'] = esc_url( $theme_data['AuthorURI'] ); 220 221 $theme_data['Template'] = wp_kses( $theme_data['Template'], $themes_allowed_tags ); 222 223 $theme_data['Version'] = wp_kses( $theme_data['Version'], $themes_allowed_tags ); 224 225 if ( $theme_data['Status'] == '' ) 226 $theme_data['Status'] = 'publish'; 227 else 228 $theme_data['Status'] = wp_kses( $theme_data['Status'], $themes_allowed_tags ); 229 230 if ( $theme_data['Tags'] == '' ) 231 $theme_data['Tags'] = array(); 232 else 233 $theme_data['Tags'] = array_map( 'trim', explode( ',', wp_kses( $theme_data['Tags'], array() ) ) ); 234 235 if ( $theme_data['Author'] == '' ) { 236 $theme_data['Author'] = $theme_data['AuthorName'] = __('Anonymous'); 237 } else { 238 $theme_data['AuthorName'] = wp_kses( $theme_data['Author'], $themes_allowed_tags ); 239 if ( empty( $theme_data['AuthorURI'] ) ) { 240 $theme_data['Author'] = $theme_data['AuthorName']; 241 } else { 242 $theme_data['Author'] = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $theme_data['AuthorURI'], esc_attr__( 'Visit author homepage' ), $theme_data['AuthorName'] ); 243 } 244 } 245 246 return $theme_data; 247 } 248 249 /** 250 * Retrieve list of themes with theme data in theme directory. 251 * 252 * The theme is broken, if it doesn't have a parent theme and is missing either 253 * style.css and, or index.php. If the theme has a parent theme then it is 254 * broken, if it is missing style.css; index.php is optional. The broken theme 255 * list is saved in the {@link $wp_broken_themes} global, which is displayed on 256 * the theme list in the administration panels. 257 * 258 * @since 1.5.0 259 * @global array $wp_broken_themes Stores the broken themes. 260 * @global array $wp_themes Stores the working themes. 261 * 262 * @return array Theme list with theme data. 263 */ 264 function get_themes() { 265 global $wp_themes, $wp_broken_themes; 266 267 if ( isset($wp_themes) ) 268 return $wp_themes; 269 270 if ( !$theme_files = search_theme_directories() ) 271 return false; 272 273 asort( $theme_files ); 274 275 $wp_themes = array(); 276 277 foreach ( (array) $theme_files as $theme_file ) { 278 $theme_root = $theme_file['theme_root']; 279 $theme_file = $theme_file['theme_file']; 280 281 if ( !is_readable("$theme_root/$theme_file") ) { 282 $wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.')); 283 continue; 284 } 285 286 $theme_data = get_theme_data("$theme_root/$theme_file"); 287 288 $name = $theme_data['Name']; 289 $title = $theme_data['Title']; 290 $description = wptexturize($theme_data['Description']); 291 $version = $theme_data['Version']; 292 $author = $theme_data['Author']; 293 $template = $theme_data['Template']; 294 $stylesheet = dirname($theme_file); 295 296 $screenshot = false; 297 foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) { 298 if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) { 299 $screenshot = "screenshot.$ext"; 300 break; 301 } 302 } 303 304 if ( empty($name) ) { 305 $name = dirname($theme_file); 306 $title = $name; 307 } 308 309 $parent_template = $template; 310 311 if ( empty($template) ) { 312 if ( file_exists("$theme_root/$stylesheet/index.php") ) 313 $template = $stylesheet; 314 else 315 continue; 316 } 317 318 $template = trim( $template ); 319 320 if ( !file_exists("$theme_root/$template/index.php") ) { 321 $parent_dir = dirname(dirname($theme_file)); 322 if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) { 323 $template = "$parent_dir/$template"; 324 $template_directory = "$theme_root/$template"; 325 } else { 326 /** 327 * The parent theme doesn't exist in the current theme's folder or sub folder 328 * so lets use the theme root for the parent template. 329 */ 330 if ( isset($theme_files[$template]) && file_exists( $theme_files[$template]['theme_root'] . "/$template/index.php" ) ) { 331 $template_directory = $theme_files[$template]['theme_root'] . "/$template"; 332 } else { 333 if ( empty( $parent_template) ) 334 $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'), 'error' => 'no_template'); 335 else 336 $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => sprintf( __('The parent theme is missing. Please install the "%s" parent theme.'), $parent_template ), 'error' => 'no_parent', 'parent' => $parent_template ); 337 continue; 338 } 339 340 } 341 } else { 342 $template_directory = trim( $theme_root . '/' . $template ); 343 } 344 345 $stylesheet_files = array(); 346 $template_files = array(); 347 348 $stylesheet_dir = @ dir("$theme_root/$stylesheet"); 349 if ( $stylesheet_dir ) { 350 while ( ($file = $stylesheet_dir->read()) !== false ) { 351 if ( !preg_match('|^\.+$|', $file) ) { 352 if ( preg_match('|\.css$|', $file) ) 353 $stylesheet_files[] = "$theme_root/$stylesheet/$file"; 354 elseif ( preg_match('|\.php$|', $file) ) 355 $template_files[] = "$theme_root/$stylesheet/$file"; 356 } 357 } 358 @ $stylesheet_dir->close(); 359 } 360 361 $template_dir = @ dir("$template_directory"); 362 if ( $template_dir ) { 363 while ( ($file = $template_dir->read()) !== false ) { 364 if ( preg_match('|^\.+$|', $file) ) 365 continue; 366 if ( preg_match('|\.php$|', $file) ) { 367 $template_files[] = "$template_directory/$file"; 368 } elseif ( is_dir("$template_directory/$file") ) { 369 $template_subdir = @ dir("$template_directory/$file"); 370 if ( !$template_subdir ) 371 continue; 372 while ( ($subfile = $template_subdir->read()) !== false ) { 373 if ( preg_match('|^\.+$|', $subfile) ) 374 continue; 375 if ( preg_match('|\.php$|', $subfile) ) 376 $template_files[] = "$template_directory/$file/$subfile"; 377 } 378 @ $template_subdir->close(); 379 } 380 } 381 @ $template_dir->close(); 382 } 383 384 //Make unique and remove duplicates when stylesheet and template are the same i.e. most themes 385 $template_files = array_unique($template_files); 386 $stylesheet_files = array_unique($stylesheet_files); 387 388 $template_dir = $template_directory; 389 $stylesheet_dir = $theme_root . '/' . $stylesheet; 390 391 if ( empty($template_dir) ) 392 $template_dir = '/'; 393 if ( empty($stylesheet_dir) ) 394 $stylesheet_dir = '/'; 395 396 // Check for theme name collision. This occurs if a theme is copied to 397 // a new theme directory and the theme header is not updated. Whichever 398 // theme is first keeps the name. Subsequent themes get a suffix applied. 399 // The Twenty Ten, Default and Classic themes always trump their pretenders. 400 if ( isset($wp_themes[$name]) ) { 401 $trump_cards = array( 402 'classic' => 'WordPress Classic', 403 'default' => 'WordPress Default', 404 'twentyten' => 'Twenty Ten', 405 ); 406 if ( isset( $trump_cards[ $stylesheet ] ) && $name == $trump_cards[ $stylesheet ] ) { 407 // If another theme has claimed to be one of our default themes, move 408 // them aside. 409 $suffix = $wp_themes[$name]['Stylesheet']; 410 $new_name = "$name/$suffix"; 411 $wp_themes[$new_name] = $wp_themes[$name]; 412 $wp_themes[$new_name]['Name'] = $new_name; 413 } else { 414 $name = "$name/$stylesheet"; 415 } 416 } 417 418 $theme_roots[$stylesheet] = str_replace( WP_CONTENT_DIR, '', $theme_root ); 419 $wp_themes[$name] = array( 420 'Name' => $name, 421 'Title' => $title, 422 'Description' => $description, 423 'Author' => $author, 424 'Author Name' => $theme_data['AuthorName'], 425 'Author URI' => $theme_data['AuthorURI'], 426 'Version' => $version, 427 'Template' => $template, 428 'Stylesheet' => $stylesheet, 429 'Template Files' => $template_files, 430 'Stylesheet Files' => $stylesheet_files, 431 'Template Dir' => $template_dir, 432 'Stylesheet Dir' => $stylesheet_dir, 433 'Status' => $theme_data['Status'], 434 'Screenshot' => $screenshot, 435 'Tags' => $theme_data['Tags'], 436 'Theme Root' => $theme_root, 437 'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ), 438 ); 439 } 440 441 unset($theme_files); 442 443 /* Store theme roots in the DB */ 444 if ( get_site_transient( 'theme_roots' ) != $theme_roots ) 445 set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours 446 unset($theme_roots); 447 448 /* Resolve theme dependencies. */ 449 $theme_names = array_keys( $wp_themes ); 450 foreach ( (array) $theme_names as $theme_name ) { 451 $wp_themes[$theme_name]['Parent Theme'] = ''; 452 if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) { 453 foreach ( (array) $theme_names as $parent_theme_name ) { 454 if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) { 455 $wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name']; 456 break; 457 } 458 } 459 } 460 } 461 462 return $wp_themes; 463 } 464 465 /** 466 * Retrieve theme roots. 467 * 468 * @since 2.9.0 469 * 470 * @return array|string An arry of theme roots keyed by template/stylesheet or a single theme root if all themes have the same root. 471 */ 472 function get_theme_roots() { 473 global $wp_theme_directories; 474 475 if ( count($wp_theme_directories) <= 1 ) 476 return '/themes'; 477 478 $theme_roots = get_site_transient( 'theme_roots' ); 479 if ( false === $theme_roots ) { 480 get_themes(); 481 $theme_roots = get_site_transient( 'theme_roots' ); // this is set in get_theme() 482 } 483 return $theme_roots; 484 } 485 486 /** 487 * Retrieve theme data. 488 * 489 * @since 1.5.0 490 * 491 * @param string $theme Theme name. 492 * @return array|null Null, if theme name does not exist. Theme data, if exists. 493 */ 494 function get_theme($theme) { 495 $themes = get_themes(); 496 497 if ( array_key_exists($theme, $themes) ) 498 return $themes[$theme]; 499 500 return null; 501 } 502 503 /** 504 * Retrieve current theme display name. 505 * 506 * If the 'current_theme' option has already been set, then it will be returned 507 * instead. If it is not set, then each theme will be iterated over until both 508 * the current stylesheet and current template name. 509 * 510 * @since 1.5.0 511 * 512 * @return string 513 */ 514 function get_current_theme() { 515 if ( $theme = get_option('current_theme') ) 516 return $theme; 517 518 $themes = get_themes(); 519 $theme_names = array_keys($themes); 520 $current_template = get_option('template'); 521 $current_stylesheet = get_option('stylesheet'); 522 $current_theme = 'Twenty Ten'; 523 524 if ( $themes ) { 525 foreach ( (array) $theme_names as $theme_name ) { 526 if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet && 527 $themes[$theme_name]['Template'] == $current_template ) { 528 $current_theme = $themes[$theme_name]['Name']; 529 break; 530 } 531 } 532 } 533 534 update_option('current_theme', $current_theme); 535 536 return $current_theme; 537 } 538 539 /** 540 * Register a directory that contains themes. 541 * 542 * @since 2.9.0 543 * 544 * @param string $directory Either the full filesystem path to a theme folder or a folder within WP_CONTENT_DIR 545 * @return bool 546 */ 547 function register_theme_directory( $directory) { 548 global $wp_theme_directories; 549 550 /* If this folder does not exist, return and do not register */ 551 if ( !file_exists( $directory ) ) 552 /* Try prepending as the theme directory could be relative to the content directory */ 553 $registered_directory = WP_CONTENT_DIR . '/' . $directory; 554 else 555 $registered_directory = $directory; 556 557 /* If this folder does not exist, return and do not register */ 558 if ( !file_exists( $registered_directory ) ) 559 return false; 560 561 $wp_theme_directories[] = $registered_directory; 562 563 return true; 564 } 565 566 /** 567 * Search all registered theme directories for complete and valid themes. 568 * 569 * @since 2.9.0 570 * 571 * @return array Valid themes found 572 */ 573 function search_theme_directories() { 574 global $wp_theme_directories, $wp_broken_themes; 575 if ( empty( $wp_theme_directories ) ) 576 return false; 577 578 $theme_files = array(); 579 $wp_broken_themes = array(); 580 581 /* Loop the registered theme directories and extract all themes */ 582 foreach ( (array) $wp_theme_directories as $theme_root ) { 583 $theme_loc = $theme_root; 584 585 /* We don't want to replace all forward slashes, see Trac #4541 */ 586 if ( '/' != WP_CONTENT_DIR ) 587 $theme_loc = str_replace(WP_CONTENT_DIR, '', $theme_root); 588 589 /* Files in the root of the current theme directory and one subdir down */ 590 $themes_dir = @ opendir($theme_root); 591 592 if ( !$themes_dir ) 593 return false; 594 595 while ( ($theme_dir = readdir($themes_dir)) !== false ) { 596 if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { 597 if ( $theme_dir[0] == '.' || $theme_dir == 'CVS' ) 598 continue; 599 600 $stylish_dir = @opendir($theme_root . '/' . $theme_dir); 601 $found_stylesheet = false; 602 603 while ( ($theme_file = readdir($stylish_dir)) !== false ) { 604 if ( $theme_file == 'style.css' ) { 605 $theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root ); 606 $found_stylesheet = true; 607 break; 608 } 609 } 610 @closedir($stylish_dir); 611 612 if ( !$found_stylesheet ) { // look for themes in that dir 613 $subdir = "$theme_root/$theme_dir"; 614 $subdir_name = $theme_dir; 615 $theme_subdirs = @opendir( $subdir ); 616 617 $found_subdir_themes = false; 618 while ( ($theme_subdir = readdir($theme_subdirs)) !== false ) { 619 if ( is_dir( $subdir . '/' . $theme_subdir) && is_readable($subdir . '/' . $theme_subdir) ) { 620 if ( $theme_subdir[0] == '.' || $theme_subdir == 'CVS' ) 621 continue; 622 623 $stylish_dir = @opendir($subdir . '/' . $theme_subdir); 624 $found_stylesheet = false; 625 626 while ( ($theme_file = readdir($stylish_dir)) !== false ) { 627 if ( $theme_file == 'style.css' ) { 628 $theme_files["$theme_dir/$theme_subdir"] = array( 'theme_file' => $subdir_name . '/' . $theme_subdir . '/' . $theme_file, 'theme_root' => $theme_root ); 629 $found_stylesheet = true; 630 $found_subdir_themes = true; 631 break; 632 } 633 } 634 @closedir($stylish_dir); 635 } 636 } 637 @closedir($theme_subdirs); 638 if ( !$found_subdir_themes ) 639 $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); 640 } 641 } 642 } 643 @closedir( $themes_dir ); 644 } 645 return $theme_files; 646 } 647 648 /** 649 * Retrieve path to themes directory. 650 * 651 * Does not have trailing slash. 652 * 653 * @since 1.5.0 654 * @uses apply_filters() Calls 'theme_root' filter on path. 655 * 656 * @param string $stylesheet_or_template The stylesheet or template name of the theme 657 * @return string Theme path. 658 */ 659 function get_theme_root( $stylesheet_or_template = false ) { 660 if ( $stylesheet_or_template ) { 661 if ( $theme_root = get_raw_theme_root($stylesheet_or_template) ) 662 $theme_root = WP_CONTENT_DIR . $theme_root; 663 else 664 $theme_root = WP_CONTENT_DIR . '/themes'; 665 } else { 666 $theme_root = WP_CONTENT_DIR . '/themes'; 667 } 668 669 return apply_filters( 'theme_root', $theme_root ); 670 } 671 672 /** 673 * Retrieve URI for themes directory. 674 * 675 * Does not have trailing slash. 676 * 677 * @since 1.5.0 678 * 679 * @param string $stylesheet_or_template The stylesheet or template name of the theme 680 * @return string Themes URI. 681 */ 682 function get_theme_root_uri( $stylesheet_or_template = false ) { 683 if ( $stylesheet_or_template ) { 684 if ( $theme_root = get_raw_theme_root($stylesheet_or_template) ) 685 $theme_root_uri = content_url( $theme_root ); 686 else 687 $theme_root_uri = content_url( 'themes' ); 688 } else { 689 $theme_root_uri = content_url( 'themes' ); 690 } 691 692 return apply_filters( 'theme_root_uri', $theme_root_uri, get_option('siteurl'), $stylesheet_or_template ); 693 } 694 695 /** 696 * Get the raw theme root relative to the content directory with no filters applied. 697 * 698 * @since 3.1.0 699 * 700 * @param string $stylesheet_or_template The stylesheet or template name of the theme 701 * @return string Theme root 702 */ 703 function get_raw_theme_root( $stylesheet_or_template, $no_cache = false ) { 704 global $wp_theme_directories; 705 706 if ( count($wp_theme_directories) <= 1 ) 707 return '/themes'; 708 709 $theme_root = false; 710 711 // If requesting the root for the current theme, consult options to avoid calling get_theme_roots() 712 if ( !$no_cache ) { 713 if ( get_option('stylesheet') == $stylesheet_or_template ) 714 $theme_root = get_option('stylesheet_root'); 715 elseif ( get_option('template') == $stylesheet_or_template ) 716 $theme_root = get_option('template_root'); 717 } 718 719 if ( empty($theme_root) ) { 720 $theme_roots = get_theme_roots(); 721 if ( !empty($theme_roots[$stylesheet_or_template]) ) 722 $theme_root = $theme_roots[$stylesheet_or_template]; 723 } 724 725 return $theme_root; 726 } 727 728 /** 729 * Retrieve path to a template 730 * 731 * Used to quickly retrieve the path of a template without including the file 732 * extension. It will also check the parent theme, if the file exists, with 733 * the use of {@link locate_template()}. Allows for more generic template location 734 * without the use of the other get_*_template() functions. 735 * 736 * @since 1.5.0 737 * 738 * @param string $type Filename without extension. 739 * @param array $templates An optional list of template candidates 740 * @return string Full path to file. 741 */ 742 function get_query_template( $type, $templates = array() ) { 743 $type = preg_replace( '|[^a-z0-9-]+|', '', $type ); 744 745 if ( empty( $templates ) ) 746 $templates = array("{$type}.php"); 747 748 return apply_filters( "{$type}_template", locate_template( $templates ) ); 749 } 750 751 /** 752 * Retrieve path of index template in current or parent template. 753 * 754 * @since 3.0.0 755 * 756 * @return string 757 */ 758 function get_index_template() { 759 return get_query_template('index'); 760 } 761 762 /** 763 * Retrieve path of 404 template in current or parent template. 764 * 765 * @since 1.5.0 766 * 767 * @return string 768 */ 769 function get_404_template() { 770 return get_query_template('404'); 771 } 772 773 /** 774 * Retrieve path of archive template in current or parent template. 775 * 776 * @since 1.5.0 777 * 778 * @return string 779 */ 780 function get_archive_template() { 781 $post_type = get_query_var( 'post_type' ); 782 783 $templates = array(); 784 785 if ( $post_type ) 786 $templates[] = "archive-{$post_type}.php"; 787 $templates[] = 'archive.php'; 788 789 return get_query_template( 'archive', $templates ); 790 } 791 792 /** 793 * Retrieve path of author template in current or parent template. 794 * 795 * @since 1.5.0 796 * 797 * @return string 798 */ 799 function get_author_template() { 800 $author = get_queried_object(); 801 802 $templates = array(); 803 804 $templates[] = "author-{$author->user_nicename}.php"; 805 $templates[] = "author-{$author->ID}.php"; 806 $templates[] = 'author.php'; 807 808 return get_query_template( 'author', $templates ); 809 } 810 811 /** 812 * Retrieve path of category template in current or parent template. 813 * 814 * Works by first retrieving the current slug for example 'category-default.php' and then 815 * trying category ID, for example 'category-1.php' and will finally fallback to category.php 816 * template, if those files don't exist. 817 * 818 * @since 1.5.0 819 * @uses apply_filters() Calls 'category_template' on file path of category template. 820 * 821 * @return string 822 */ 823 function get_category_template() { 824 $category = get_queried_object(); 825 826 $templates = array(); 827 828 $templates[] = "category-{$category->slug}.php"; 829 $templates[] = "category-{$category->term_id}.php"; 830 $templates[] = 'category.php'; 831 832 return get_query_template( 'category', $templates ); 833 } 834 835 /** 836 * Retrieve path of tag template in current or parent template. 837 * 838 * Works by first retrieving the current tag name, for example 'tag-wordpress.php' and then 839 * trying tag ID, for example 'tag-1.php' and will finally fallback to tag.php 840 * template, if those files don't exist. 841 * 842 * @since 2.3.0 843 * @uses apply_filters() Calls 'tag_template' on file path of tag template. 844 * 845 * @return string 846 */ 847 function get_tag_template() { 848 $tag = get_queried_object(); 849 850 $templates = array(); 851 852 $templates[] = "tag-{$tag->slug}.php"; 853 $templates[] = "tag-{$tag->term_id}.php"; 854 $templates[] = 'tag.php'; 855 856 return get_query_template( 'tag', $templates ); 857 } 858 859 /** 860 * Retrieve path of taxonomy template in current or parent template. 861 * 862 * Retrieves the taxonomy and term, if term is available. The template is 863 * prepended with 'taxonomy-' and followed by both the taxonomy string and 864 * the taxonomy string followed by a dash and then followed by the term. 865 * 866 * The taxonomy and term template is checked and used first, if it exists. 867 * Second, just the taxonomy template is checked, and then finally, taxonomy.php 868 * template is used. If none of the files exist, then it will fall back on to 869 * index.php. 870 * 871 * @since 2.5.0 872 * @uses apply_filters() Calls 'taxonomy_template' filter on found path. 873 * 874 * @return string 875 */ 876 function get_taxonomy_template() { 877 $term = get_queried_object(); 878 $taxonomy = $term->taxonomy; 879 880 $templates = array(); 881 882 $templates[] = "taxonomy-$taxonomy-{$term->slug}.php"; 883 $templates[] = "taxonomy-$taxonomy.php"; 884 $templates[] = 'taxonomy.php'; 885 886 return get_query_template( 'taxonomy', $templates ); 887 } 888 889 /** 890 * Retrieve path of date template in current or parent template. 891 * 892 * @since 1.5.0 893 * 894 * @return string 895 */ 896 function get_date_template() { 897 return get_query_template('date'); 898 } 899 900 /** 901 * Retrieve path of home template in current or parent template. 902 * 903 * This is the template used for the page containing the blog posts 904 * 905 * Attempts to locate 'home.php' first before falling back to 'index.php'. 906 * 907 * @since 1.5.0 908 * @uses apply_filters() Calls 'home_template' on file path of home template. 909 * 910 * @return string 911 */ 912 function get_home_template() { 913 $templates = array( 'home.php', 'index.php' ); 914 915 return get_query_template( 'home', $templates ); 916 } 917 918 /** 919 * Retrieve path of front-page template in current or parent template. 920 * 921 * Looks for 'front-page.php'. 922 * 923 * @since 3.0.0 924 * @uses apply_filters() Calls 'front_page_template' on file path of template. 925 * 926 * @return string 927 */ 928 function get_front_page_template() { 929 $templates = array('front-page.php'); 930 931 return get_query_template( 'front_page', $templates ); 932 } 933 934 /** 935 * Retrieve path of page template in current or parent template. 936 * 937 * Will first look for the specifically assigned page template 938 * The will search for 'page-{slug}.php' followed by 'page-id.php' 939 * and finally 'page.php' 940 * 941 * @since 1.5.0 942 * 943 * @return string 944 */ 945 function get_page_template() { 946 $id = get_queried_object_id(); 947 $template = get_post_meta($id, '_wp_page_template', true); 948 $pagename = get_query_var('pagename'); 949 950 if ( !$pagename && $id > 0 ) { 951 // If a static page is set as the front page, $pagename will not be set. Retrieve it from the queried object 952 $post = get_queried_object(); 953 $pagename = $post->post_name; 954 } 955 956 if ( 'default' == $template ) 957 $template = ''; 958 959 $templates = array(); 960 if ( !empty($template) && !validate_file($template) ) 961 $templates[] = $template; 962 if ( $pagename ) 963 $templates[] = "page-$pagename.php"; 964 if ( $id ) 965 $templates[] = "page-$id.php"; 966 $templates[] = 'page.php'; 967 968 return get_query_template( 'page', $templates ); 969 } 970 971 /** 972 * Retrieve path of paged template in current or parent template. 973 * 974 * @since 1.5.0 975 * 976 * @return string 977 */ 978 function get_paged_template() { 979 return get_query_template('paged'); 980 } 981 982 /** 983 * Retrieve path of search template in current or parent template. 984 * 985 * @since 1.5.0 986 * 987 * @return string 988 */ 989 function get_search_template() { 990 return get_query_template('search'); 991 } 992 993 /** 994 * Retrieve path of single template in current or parent template. 995 * 996 * @since 1.5.0 997 * 998 * @return string 999 */ 1000 function get_single_template() { 1001 $object = get_queried_object(); 1002 1003 $templates = array(); 1004 1005 $templates[] = "single-{$object->post_type}.php"; 1006 $templates[] = "single.php"; 1007 1008 return get_query_template( 'single', $templates ); 1009 } 1010 1011 /** 1012 * Retrieve path of attachment template in current or parent template. 1013 * 1014 * The attachment path first checks if the first part of the mime type exists. 1015 * The second check is for the second part of the mime type. The last check is 1016 * for both types separated by an underscore. If neither are found then the file 1017 * 'attachment.php' is checked and returned. 1018 * 1019 * Some examples for the 'text/plain' mime type are 'text.php', 'plain.php', and 1020 * finally 'text_plain.php'. 1021 * 1022 * @since 2.0.0 1023 * 1024 * @return string 1025 */ 1026 function get_attachment_template() { 1027 global $posts; 1028 $type = explode('/', $posts[0]->post_mime_type); 1029 if ( $template = get_query_template($type[0]) ) 1030 return $template; 1031 elseif ( $template = get_query_template($type[1]) ) 1032 return $template; 1033 elseif ( $template = get_query_template("$type[0]_$type[1]") ) 1034 return $template; 1035 else 1036 return get_query_template('attachment'); 1037 } 1038 1039 /** 1040 * Retrieve path of comment popup template in current or parent template. 1041 * 1042 * Checks for comment popup template in current template, if it exists or in the 1043 * parent template. 1044 * 1045 * @since 1.5.0 1046 * @uses apply_filters() Calls 'comments_popup_template' filter on path. 1047 * 1048 * @return string 1049 */ 1050 function get_comments_popup_template() { 1051 $template = get_query_template( 'comments_popup', array( 'comments-popup.php' ) ); 1052 1053 // Backward compat code will be removed in a future release 1054 if ('' == $template) 1055 $template = ABSPATH . WPINC . '/theme-compat/comments-popup.php'; 1056 1057 return $template; 1058 } 1059 1060 /** 1061 * Retrieve the name of the highest priority template file that exists. 1062 * 1063 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which 1064 * inherit from a parent theme can just overload one file. 1065 * 1066 * @since 2.7.0 1067 * 1068 * @param string|array $template_names Template file(s) to search for, in order. 1069 * @param bool $load If true the template file will be loaded if it is found. 1070 * @param bool $require_once Whether to require_once or require. Default true. Has no effect if $load is false. 1071 * @return string The template filename if one is located. 1072 */ 1073 function locate_template($template_names, $load = false, $require_once = true ) { 1074 $located = ''; 1075 foreach ( (array) $template_names as $template_name ) { 1076 if ( !$template_name ) 1077 continue; 1078 if ( file_exists(STYLESHEETPATH . '/' . $template_name)) { 1079 $located = STYLESHEETPATH . '/' . $template_name; 1080 break; 1081 } else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) { 1082 $located = TEMPLATEPATH . '/' . $template_name; 1083 break; 1084 } 1085 } 1086 1087 if ( $load && '' != $located ) 1088 load_template( $located, $require_once ); 1089 1090 return $located; 1091 } 1092 1093 /** 1094 * Require the template file with WordPress environment. 1095 * 1096 * The globals are set up for the template file to ensure that the WordPress 1097 * environment is available from within the function. The query variables are 1098 * also available. 1099 * 1100 * @since 1.5.0 1101 * 1102 * @param string $_template_file Path to template file. 1103 * @param bool $require_once Whether to require_once or require. Default true. 1104 */ 1105 function load_template( $_template_file, $require_once = true ) { 1106 global $posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID; 1107 1108 if ( is_array( $wp_query->query_vars ) ) 1109 extract( $wp_query->query_vars, EXTR_SKIP ); 1110 1111 if ( $require_once ) 1112 require_once( $_template_file ); 1113 else 1114 require( $_template_file ); 1115 } 1116 1117 /** 1118 * Display localized stylesheet link element. 1119 * 1120 * @since 2.1.0 1121 */ 1122 function locale_stylesheet() { 1123 $stylesheet = get_locale_stylesheet_uri(); 1124 if ( empty($stylesheet) ) 1125 return; 1126 echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />'; 1127 } 1128 1129 /** 1130 * Start preview theme output buffer. 1131 * 1132 * Will only preform task if the user has permissions and template and preview 1133 * query variables exist. 1134 * 1135 * @since 2.6.0 1136 */ 1137 function preview_theme() { 1138 if ( ! (isset($_GET['template']) && isset($_GET['preview'])) ) 1139 return; 1140 1141 if ( !current_user_can( 'switch_themes' ) ) 1142 return; 1143 1144 // Admin Thickbox requests 1145 if ( isset( $_GET['preview_iframe'] ) ) 1146 show_admin_bar( false ); 1147 1148 $_GET['template'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['template']); 1149 1150 if ( validate_file($_GET['template']) ) 1151 return; 1152 1153 add_filter( 'template', '_preview_theme_template_filter' ); 1154 1155 if ( isset($_GET['stylesheet']) ) { 1156 $_GET['stylesheet'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['stylesheet']); 1157 if ( validate_file($_GET['stylesheet']) ) 1158 return; 1159 add_filter( 'stylesheet', '_preview_theme_stylesheet_filter' ); 1160 } 1161 1162 // Prevent theme mods to current theme being used on theme being previewed 1163 add_filter( 'pre_option_mods_' . get_current_theme(), '__return_empty_array' ); 1164 1165 ob_start( 'preview_theme_ob_filter' ); 1166 } 1167 add_action('setup_theme', 'preview_theme'); 1168 1169 /** 1170 * Private function to modify the current template when previewing a theme 1171 * 1172 * @since 2.9.0 1173 * @access private 1174 * 1175 * @return string 1176 */ 1177 function _preview_theme_template_filter() { 1178 return isset($_GET['template']) ? $_GET['template'] : ''; 1179 } 1180 1181 /** 1182 * Private function to modify the current stylesheet when previewing a theme 1183 * 1184 * @since 2.9.0 1185 * @access private 1186 * 1187 * @return string 1188 */ 1189 function _preview_theme_stylesheet_filter() { 1190 return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : ''; 1191 } 1192 1193 /** 1194 * Callback function for ob_start() to capture all links in the theme. 1195 * 1196 * @since 2.6.0 1197 * @access private 1198 * 1199 * @param string $content 1200 * @return string 1201 */ 1202 function preview_theme_ob_filter( $content ) { 1203 return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content ); 1204 } 1205 1206 /** 1207 * Manipulates preview theme links in order to control and maintain location. 1208 * 1209 * Callback function for preg_replace_callback() to accept and filter matches. 1210 * 1211 * @since 2.6.0 1212 * @access private 1213 * 1214 * @param array $matches 1215 * @return string 1216 */ 1217 function preview_theme_ob_filter_callback( $matches ) { 1218 if ( strpos($matches[4], 'onclick') !== false ) 1219 $matches[4] = preg_replace('#onclick=([\'"]).*?(?<!\\\)\\1#i', '', $matches[4]); //Strip out any onclicks from rest of <a>. (?<!\\\) means to ignore the '" if its escaped by \ to prevent breaking mid-attribute. 1220 if ( 1221 ( false !== strpos($matches[3], '/wp-admin/') ) 1222 || 1223 ( false !== strpos( $matches[3], '://' ) && 0 !== strpos( $matches[3], home_url() ) ) 1224 || 1225 ( false !== strpos($matches[3], '/feed/') ) 1226 || 1227 ( false !== strpos($matches[3], '/trackback/') ) 1228 ) 1229 return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4]; 1230 1231 $link = add_query_arg( array('preview' => 1, 'template' => $_GET['template'], 'stylesheet' => @$_GET['stylesheet'] ), $matches[3] ); 1232 if ( 0 === strpos($link, 'preview=1') ) 1233 $link = "?$link"; 1234 return $matches[1] . esc_attr( $link ) . $matches[4]; 1235 } 1236 1237 /** 1238 * Switches current theme to new template and stylesheet names. 1239 * 1240 * @since 2.5.0 1241 * @uses do_action() Calls 'switch_theme' action on updated theme display name. 1242 * 1243 * @param string $template Template name 1244 * @param string $stylesheet Stylesheet name. 1245 */ 1246 function switch_theme($template, $stylesheet) { 1247 global $wp_theme_directories; 1248 1249 update_option('template', $template); 1250 update_option('stylesheet', $stylesheet); 1251 if ( count($wp_theme_directories) > 1 ) { 1252 update_option('template_root', get_raw_theme_root($template, true)); 1253 update_option('stylesheet_root', get_raw_theme_root($stylesheet, true)); 1254 } 1255 delete_option('current_theme'); 1256 $theme = get_current_theme(); 1257 if ( is_admin() && false === get_option( "theme_mods_$stylesheet" ) ) { 1258 $default_theme_mods = (array) get_option( "mods_$theme" ); 1259 add_option( "theme_mods_$stylesheet", $default_theme_mods ); 1260 } 1261 do_action('switch_theme', $theme); 1262 } 1263 1264 /** 1265 * Checks that current theme files 'index.php' and 'style.css' exists. 1266 * 1267 * Does not check the default theme, which is the fallback and should always exist. 1268 * Will switch theme to the fallback theme if current theme does not validate. 1269 * You can use the 'validate_current_theme' filter to return FALSE to 1270 * disable this functionality. 1271 * 1272 * @since 1.5.0 1273 * @see WP_DEFAULT_THEME 1274 * 1275 * @return bool 1276 */ 1277 function validate_current_theme() { 1278 // Don't validate during an install/upgrade. 1279 if ( defined('WP_INSTALLING') || !apply_filters( 'validate_current_theme', true ) ) 1280 return true; 1281 1282 if ( get_template() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/index.php') ) { 1283 switch_theme( WP_DEFAULT_THEME, WP_DEFAULT_THEME ); 1284 return false; 1285 } 1286 1287 if ( get_stylesheet() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/style.css') ) { 1288 switch_theme( WP_DEFAULT_THEME, WP_DEFAULT_THEME ); 1289 return false; 1290 } 1291 1292 if ( is_child_theme() && ! file_exists( get_stylesheet_directory() . '/style.css' ) ) { 1293 switch_theme( WP_DEFAULT_THEME, WP_DEFAULT_THEME ); 1294 return false; 1295 } 1296 1297 return true; 1298 } 1299 1300 /** 1301 * Retrieve all theme modifications. 1302 * 1303 * @since 3.1.0 1304 * 1305 * @return array Theme modifications. 1306 */ 1307 function get_theme_mods() { 1308 $theme_slug = get_option( 'stylesheet' ); 1309 if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) { 1310 $theme_name = get_current_theme(); 1311 $mods = get_option( "mods_$theme_name" ); // Deprecated location. 1312 if ( is_admin() && false !== $mods ) { 1313 update_option( "theme_mods_$theme_slug", $mods ); 1314 delete_option( "mods_$theme_name" ); 1315 } 1316 } 1317 return $mods; 1318 } 1319 1320 /** 1321 * Retrieve theme modification value for the current theme. 1322 * 1323 * If the modification name does not exist, then the $default will be passed 1324 * through {@link http://php.net/sprintf sprintf()} PHP function with the first 1325 * string the template directory URI and the second string the stylesheet 1326 * directory URI. 1327 * 1328 * @since 2.1.0 1329 * @uses apply_filters() Calls 'theme_mod_$name' filter on the value. 1330 * 1331 * @param string $name Theme modification name. 1332 * @param bool|string $default 1333 * @return string 1334 */ 1335 function get_theme_mod( $name, $default = false ) { 1336 $mods = get_theme_mods(); 1337 1338 if ( isset( $mods[ $name ] ) ) 1339 return apply_filters( "theme_mod_$name", $mods[ $name ] ); 1340 1341 return apply_filters( "theme_mod_$name", sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ) ); 1342 } 1343 1344 /** 1345 * Update theme modification value for the current theme. 1346 * 1347 * @since 2.1.0 1348 * 1349 * @param string $name Theme modification name. 1350 * @param string $value theme modification value. 1351 */ 1352 function set_theme_mod( $name, $value ) { 1353 $mods = get_theme_mods(); 1354 1355 $mods[ $name ] = $value; 1356 1357 $theme = get_option( 'stylesheet' ); 1358 update_option( "theme_mods_$theme", $mods ); 1359 } 1360 1361 /** 1362 * Remove theme modification name from current theme list. 1363 * 1364 * If removing the name also removes all elements, then the entire option will 1365 * be removed. 1366 * 1367 * @since 2.1.0 1368 * 1369 * @param string $name Theme modification name. 1370 * @return null 1371 */ 1372 function remove_theme_mod( $name ) { 1373 $mods = get_theme_mods(); 1374 1375 if ( ! isset( $mods[ $name ] ) ) 1376 return; 1377 1378 unset( $mods[ $name ] ); 1379 1380 if ( empty( $mods ) ) 1381 return remove_theme_mods(); 1382 1383 $theme = get_option( 'stylesheet' ); 1384 update_option( "theme_mods_$theme", $mods ); 1385 } 1386 1387 /** 1388 * Remove theme modifications option for current theme. 1389 * 1390 * @since 2.1.0 1391 */ 1392 function remove_theme_mods() { 1393 delete_option( 'theme_mods_' . get_option( 'stylesheet' ) ); 1394 delete_option( 'mods_' . get_current_theme() ); 1395 } 1396 1397 /** 1398 * Retrieve text color for custom header. 1399 * 1400 * @since 2.1.0 1401 * @uses HEADER_TEXTCOLOR 1402 * 1403 * @return string 1404 */ 1405 function get_header_textcolor() { 1406 $default = defined('HEADER_TEXTCOLOR') ? HEADER_TEXTCOLOR : ''; 1407 1408 return get_theme_mod('header_textcolor', $default); 1409 } 1410 1411 /** 1412 * Display text color for custom header. 1413 * 1414 * @since 2.1.0 1415 */ 1416 function header_textcolor() { 1417 echo get_header_textcolor(); 1418 } 1419 1420 /** 1421 * Retrieve header image for custom header. 1422 * 1423 * @since 2.1.0 1424 * @uses HEADER_IMAGE 1425 * 1426 * @return string 1427 */ 1428 function get_header_image() { 1429 $default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : ''; 1430 $url = get_theme_mod( 'header_image', $default ); 1431 1432 if ( 'remove-header' == $url ) 1433 return false; 1434 1435 if ( is_random_header_image() ) 1436 $url = get_random_header_image(); 1437 1438 if ( is_ssl() ) 1439 $url = str_replace( 'http://', 'https://', $url ); 1440 else 1441 $url = str_replace( 'https://', 'http://', $url ); 1442 1443 return esc_url_raw( $url ); 1444 } 1445 1446 /** 1447 * Get random header image from registered images in theme. 1448 * 1449 * @since 3.2 1450 * 1451 * @return string Path to header image 1452 */ 1453 function get_random_header_image() { 1454 global $_wp_default_headers; 1455 1456 $header_image_mod = get_theme_mod( 'header_image', '' ); 1457 $headers = array(); 1458 1459 if ( 'random-uploaded-image' == $header_image_mod ) 1460 $headers = get_uploaded_header_images(); 1461 elseif ( ! empty( $_wp_default_headers ) ) 1462 $headers = $_wp_default_headers; 1463 1464 if ( empty( $headers ) ) 1465 return ''; 1466 1467 $random_image = array_rand( $headers ); 1468 $header_url = sprintf( $headers[$random_image]['url'], get_template_directory_uri(), get_stylesheet_directory_uri() ); 1469 1470 return $header_url; 1471 } 1472 1473 /** 1474 * Check if random header image is in use. 1475 * 1476 * Always true if user expressly chooses the option in Appearance > Header. 1477 * Also true if theme has multiple header images registered and no specific header image is chosen. 1478 * 1479 * @since 3.2 1480 * @uses HEADER_IMAGE 1481 * 1482 * @param string $type The random pool to use. any|default|uploaded 1483 * @return boolean 1484 */ 1485 function is_random_header_image( $type = 'any' ) { 1486 $default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : ''; 1487 $header_image_mod = get_theme_mod( 'header_image', $default ); 1488 1489 if ( 'any' == $type ) { 1490 if ( 'random-default-image' == $header_image_mod || 'random-uploaded-image' == $header_image_mod || ( '' != get_random_header_image() && empty( $header_image_mod ) ) ) 1491 return true; 1492 } else { 1493 if ( "random-$type-image" == $header_image_mod ) 1494 return true; 1495 elseif ( 'default' == $type && empty( $header_image_mod ) && '' != get_random_header_image() ) 1496 return true; 1497 } 1498 1499 return false; 1500 } 1501 1502 /** 1503 * Display header image path. 1504 * 1505 * @since 2.1.0 1506 */ 1507 function header_image() { 1508 echo get_header_image(); 1509 } 1510 1511 /** 1512 * Get the header images uploaded for the current theme. 1513 * 1514 * @since 3.2.0 1515 * 1516 * @return array 1517 */ 1518 function get_uploaded_header_images() { 1519 $header_images = array(); 1520 1521 // @todo caching 1522 $headers = get_posts( array( 'post_type' => 'attachment', 'meta_key' => '_wp_attachment_is_custom_header', 'meta_value' => get_option('stylesheet'), 'orderby' => 'none', 'nopaging' => true ) ); 1523 1524 if ( empty( $headers ) ) 1525 return array(); 1526 1527 foreach ( (array) $headers as $header ) { 1528 $url = esc_url_raw( $header->guid ); 1529 $header = basename($url); 1530 $header_images[$header] = array(); 1531 $header_images[$header]['url'] = $url; 1532 $header_images[$header]['thumbnail_url'] = $url; 1533 $header_images[$header]['uploaded'] = true; 1534 } 1535 1536 return $header_images; 1537 } 1538 1539 /** 1540 * Add callbacks for image header display. 1541 * 1542 * The parameter $header_callback callback will be required to display the 1543 * content for the 'wp_head' action. The parameter $admin_header_callback 1544 * callback will be added to Custom_Image_Header class and that will be added 1545 * to the 'admin_menu' action. 1546 * 1547 * @since 2.1.0 1548 * @uses Custom_Image_Header Sets up for $admin_header_callback for administration panel display. 1549 * 1550 * @param callback $header_callback Call on 'wp_head' action. 1551 * @param callback $admin_header_callback Call on custom header administration screen. 1552 * @param callback $admin_image_div_callback Output a custom header image div on the custom header administration screen. Optional. 1553 */ 1554 function add_custom_image_header( $header_callback, $admin_header_callback, $admin_image_div_callback = '' ) { 1555 if ( ! empty( $header_callback ) ) 1556 add_action('wp_head', $header_callback); 1557 1558 add_theme_support( 'custom-header', array( 'callback' => $header_callback ) ); 1559 add_theme_support( 'custom-header-uploads' ); 1560 1561 if ( ! is_admin() ) 1562 return; 1563 1564 global $custom_image_header; 1565 1566 require_once ( ABSPATH . 'wp-admin/custom-header.php' ); 1567 $custom_image_header = new Custom_Image_Header( $admin_header_callback, $admin_image_div_callback ); 1568 add_action( 'admin_menu', array( &$custom_image_header, 'init' ) ); 1569 } 1570 1571 /** 1572 * Remove image header support. 1573 * 1574 * @since 3.1.0 1575 * @see add_custom_image_header() 1576 * 1577 * @return bool Whether support was removed. 1578 */ 1579 function remove_custom_image_header() { 1580 if ( ! current_theme_supports( 'custom-header' ) ) 1581 return false; 1582 1583 $callback = get_theme_support( 'custom-header' ); 1584 remove_action( 'wp_head', $callback[0]['callback'] ); 1585 _remove_theme_support( 'custom-header' ); 1586 remove_theme_support( 'custom-header-uploads' ); 1587 1588 if ( is_admin() ) { 1589 remove_action( 'admin_menu', array( &$GLOBALS['custom_image_header'], 'init' ) ); 1590 unset( $GLOBALS['custom_image_header'] ); 1591 } 1592 1593 return true; 1594 } 1595 1596 /** 1597 * Register a selection of default headers to be displayed by the custom header admin UI. 1598 * 1599 * @since 3.0.0 1600 * 1601 * @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys. 1602 */ 1603 function register_default_headers( $headers ) { 1604 global $_wp_default_headers; 1605 1606 $_wp_default_headers = array_merge( (array) $_wp_default_headers, (array) $headers ); 1607 } 1608 1609 /** 1610 * Unregister default headers. 1611 * 1612 * This function must be called after register_default_headers() has already added the 1613 * header you want to remove. 1614 * 1615 * @see register_default_headers() 1616 * @since 3.0.0 1617 * 1618 * @param string|array $header The header string id (key of array) to remove, or an array thereof. 1619 * @return True on success, false on failure. 1620 */ 1621 function unregister_default_headers( $header ) { 1622 global $_wp_default_headers; 1623 if ( is_array( $header ) ) { 1624 array_map( 'unregister_default_headers', $header ); 1625 } elseif ( isset( $_wp_default_headers[ $header ] ) ) { 1626 unset( $_wp_default_headers[ $header ] ); 1627 return true; 1628 } else { 1629 return false; 1630 } 1631 } 1632 1633 /** 1634 * Retrieve background image for custom background. 1635 * 1636 * @since 3.0.0 1637 * 1638 * @return string 1639 */ 1640 function get_background_image() { 1641 $default = defined('BACKGROUND_IMAGE') ? BACKGROUND_IMAGE : ''; 1642 1643 return get_theme_mod('background_image', $default); 1644 } 1645 1646 /** 1647 * Display background image path. 1648 * 1649 * @since 3.0.0 1650 */ 1651 function background_image() { 1652 echo get_background_image(); 1653 } 1654 1655 /** 1656 * Retrieve value for custom background color. 1657 * 1658 * @since 3.0.0 1659 * @uses BACKGROUND_COLOR 1660 * 1661 * @return string 1662 */ 1663 function get_background_color() { 1664 $default = defined('BACKGROUND_COLOR') ? BACKGROUND_COLOR : ''; 1665 1666 return get_theme_mod('background_color', $default); 1667 } 1668 1669 /** 1670 * Display background color value. 1671 * 1672 * @since 3.0.0 1673 */ 1674 function background_color() { 1675 echo get_background_color(); 1676 } 1677 1678 /** 1679 * Add callbacks for background image display. 1680 * 1681 * The parameter $header_callback callback will be required to display the 1682 * content for the 'wp_head' action. The parameter $admin_header_callback 1683 * callback will be added to Custom_Background class and that will be added 1684 * to the 'admin_menu' action. 1685 * 1686 * @since 3.0.0 1687 * @uses Custom_Background Sets up for $admin_header_callback for administration panel display. 1688 * 1689 * @param callback $header_callback Call on 'wp_head' action. 1690 * @param callback $admin_header_callback Call on custom background administration screen. 1691 * @param callback $admin_image_div_callback Output a custom background image div on the custom background administration screen. Optional. 1692 */ 1693 function add_custom_background( $header_callback = '', $admin_header_callback = '', $admin_image_div_callback = '' ) { 1694 if ( isset( $GLOBALS['custom_background'] ) ) 1695 return; 1696 1697 if ( empty( $header_callback ) ) 1698 $header_callback = '_custom_background_cb'; 1699 1700 add_action( 'wp_head', $header_callback ); 1701 1702 add_theme_support( 'custom-background', array( 'callback' => $header_callback ) ); 1703 1704 if ( ! is_admin() ) 1705 return; 1706 require_once ( ABSPATH . 'wp-admin/custom-background.php' ); 1707 $GLOBALS['custom_background'] =& new Custom_Background( $admin_header_callback, $admin_image_div_callback ); 1708 add_action( 'admin_menu', array( &$GLOBALS['custom_background'], 'init' ) ); 1709 } 1710 1711 /** 1712 * Remove custom background support. 1713 * 1714 * @since 3.1.0 1715 * @see add_custom_background() 1716 * 1717 * @return bool Whether support was removed. 1718 */ 1719 function remove_custom_background() { 1720 if ( ! current_theme_supports( 'custom-background' ) ) 1721 return false; 1722 1723 $callback = get_theme_support( 'custom-background' ); 1724 remove_action( 'wp_head', $callback[0]['callback'] ); 1725 _remove_theme_support( 'custom-background' ); 1726 1727 if ( is_admin() ) { 1728 remove_action( 'admin_menu', array( &$GLOBALS['custom_background'], 'init' ) ); 1729 unset( $GLOBALS['custom_background'] ); 1730 } 1731 1732 return true; 1733 } 1734 1735 /** 1736 * Default custom background callback. 1737 * 1738 * @since 3.0.0 1739 * @see add_custom_background() 1740 * @access protected 1741 */ 1742 function _custom_background_cb() { 1743 $background = get_background_image(); 1744 $color = get_background_color(); 1745 if ( ! $background && ! $color ) 1746 return; 1747 1748 $style = $color ? "background-color: #$color;" : ''; 1749 1750 if ( $background ) { 1751 $image = " background-image: url('$background');"; 1752 1753 $repeat = get_theme_mod( 'background_repeat', 'repeat' ); 1754 if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) ) 1755 $repeat = 'repeat'; 1756 $repeat = " background-repeat: $repeat;"; 1757 1758 $position = get_theme_mod( 'background_position_x', 'left' ); 1759 if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) ) 1760 $position = 'left'; 1761 $position = " background-position: top $position;"; 1762 1763 $attachment = get_theme_mod( 'background_attachment', 'scroll' ); 1764 if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) ) 1765 $attachment = 'scroll'; 1766 $attachment = " background-attachment: $attachment;"; 1767 1768 $style .= $image . $repeat . $position . $attachment; 1769 } 1770 ?> 1771 <style type="text/css"> 1772 body { <?php echo trim( $style ); ?> } 1773 </style> 1774 <?php 1775 } 1776 1777 /** 1778 * Add callback for custom TinyMCE editor stylesheets. 1779 * 1780 * The parameter $stylesheet is the name of the stylesheet, relative to 1781 * the theme root. It also accepts an array of stylesheets. 1782 * It is optional and defaults to 'editor-style.css'. 1783 * 1784 * Supports RTL stylesheets automatically by searching for the -rtl prefix, e.g. 1785 * editor-style-rtl.css. If an array of stylesheets is passed to add_editor_style(), 1786 * RTL is only added for the first stylesheet. 1787 * 1788 * @since 3.0.0 1789 * 1790 * @param mixed $stylesheet Optional. Stylesheet name or array thereof, relative to theme root. 1791 * Defaults to 'editor-style.css' 1792 */ 1793 function add_editor_style( $stylesheet = 'editor-style.css' ) { 1794 1795 add_theme_support( 'editor-style' ); 1796 1797 if ( ! is_admin() ) 1798 return; 1799 1800 global $editor_styles; 1801 $editor_styles = (array) $editor_styles; 1802 $stylesheet = (array) $stylesheet; 1803 if ( is_rtl() ) { 1804 $rtl_stylesheet = str_replace('.css', '-rtl.css', $stylesheet[0]); 1805 $stylesheet[] = $rtl_stylesheet; 1806 } 1807 1808 $editor_styles = array_merge( $editor_styles, $stylesheet ); 1809 } 1810 1811 /** 1812 * Removes all visual editor stylesheets. 1813 * 1814 * @since 3.1.0 1815 * 1816 * @return bool True on success, false if there were no stylesheets to remove. 1817 */ 1818 function remove_editor_styles() { 1819 if ( ! current_theme_supports( 'editor-style' ) ) 1820 return false; 1821 _remove_theme_support( 'editor-style' ); 1822 if ( is_admin() ) 1823 $GLOBALS['editor_styles'] = array(); 1824 return true; 1825 } 1826 1827 /** 1828 * Allows a theme to register its support of a certain feature 1829 * 1830 * Must be called in the theme's functions.php file to work. 1831 * If attached to a hook, it must be after_setup_theme. 1832 * The init hook may be too late for some features. 1833 * 1834 * @since 2.9.0 1835 * @param string $feature the feature being added 1836 */ 1837 function add_theme_support( $feature ) { 1838 global $_wp_theme_features; 1839 1840 if ( func_num_args() == 1 ) 1841 $_wp_theme_features[$feature] = true; 1842 else 1843 $_wp_theme_features[$feature] = array_slice( func_get_args(), 1 ); 1844 1845 if ( $feature == 'post-formats' && is_array( $_wp_theme_features[$feature][0] ) ) 1846 $_wp_theme_features[$feature][0] = array_intersect( $_wp_theme_features[$feature][0], array_keys( get_post_format_slugs() ) ); 1847 } 1848 1849 /** 1850 * Gets the theme support arguments passed when registering that support 1851 * 1852 * @since 3.1 1853 * @param string $feature the feature to check 1854 * @return array The array of extra arguments 1855 */ 1856 function get_theme_support( $feature ) { 1857 global $_wp_theme_features; 1858 if ( !isset( $_wp_theme_features[$feature] ) ) 1859 return false; 1860 else 1861 return $_wp_theme_features[$feature]; 1862 } 1863 1864 /** 1865 * Allows a theme to de-register its support of a certain feature 1866 * 1867 * Should be called in the theme's functions.php file. Generally would 1868 * be used for child themes to override support from the parent theme. 1869 * 1870 * @since 3.0.0 1871 * @see add_theme_support() 1872 * @param string $feature the feature being added 1873 * @return bool Whether feature was removed. 1874 */ 1875 function remove_theme_support( $feature ) { 1876 // Blacklist: for internal registrations not used directly by themes. 1877 if ( in_array( $feature, array( 'custom-background', 'custom-header', 'editor-style', 'widgets', 'menus' ) ) ) 1878 return false; 1879 return _remove_theme_support( $feature ); 1880 } 1881 1882 /** 1883 * Do not use. Removes theme support internally, ignorant of the blacklist. 1884 * 1885 * @access private 1886 * @since 3.1.0 1887 */ 1888 function _remove_theme_support( $feature ) { 1889 global $_wp_theme_features; 1890 1891 if ( ! isset( $_wp_theme_features[$feature] ) ) 1892 return false; 1893 unset( $_wp_theme_features[$feature] ); 1894 return true; 1895 } 1896 1897 /** 1898 * Checks a theme's support for a given feature 1899 * 1900 * @since 2.9.0 1901 * @param string $feature the feature being checked 1902 * @return boolean 1903 */ 1904 function current_theme_supports( $feature ) { 1905 global $_wp_theme_features; 1906 1907 if ( !isset( $_wp_theme_features[$feature] ) ) 1908 return false; 1909 1910 // If no args passed then no extra checks need be performed 1911 if ( func_num_args() <= 1 ) 1912 return true; 1913 1914 $args = array_slice( func_get_args(), 1 ); 1915 1916 // @todo Allow pluggable arg checking 1917 switch ( $feature ) { 1918 case 'post-thumbnails': 1919 // post-thumbnails can be registered for only certain content/post types by passing 1920 // an array of types to add_theme_support(). If no array was passed, then 1921 // any type is accepted 1922 if ( true === $_wp_theme_features[$feature] ) // Registered for all types 1923 return true; 1924 $content_type = $args[0]; 1925 if ( in_array($content_type, $_wp_theme_features[$feature][0]) ) 1926 return true; 1927 else 1928 return false; 1929 break; 1930 } 1931 1932 return true; 1933 } 1934 1935 /** 1936 * Checks a theme's support for a given feature before loading the functions which implement it. 1937 * 1938 * @since 2.9.0 1939 * @param string $feature the feature being checked 1940 * @param string $include the file containing the functions that implement the feature 1941 */ 1942 function require_if_theme_supports( $feature, $include) { 1943 if ( current_theme_supports( $feature ) ) 1944 require ( $include ); 1945 } 1946 1947 /** 1948 * Checks an attachment being deleted to see if it's a header or background image. 1949 * 1950 * If true it removes the theme modification which would be pointing at the deleted 1951 * attachment 1952 * 1953 * @access private 1954 * @since 3.0.0 1955 * @param int $id the attachment id 1956 */ 1957 function _delete_attachment_theme_mod( $id ) { 1958 $attachment_image = wp_get_attachment_url( $id ); 1959 $header_image = get_header_image(); 1960 $background_image = get_background_image(); 1961 1962 if ( $header_image && $header_image == $attachment_image ) 1963 remove_theme_mod( 'header_image' ); 1964 1965 if ( $background_image && $background_image == $attachment_image ) 1966 remove_theme_mod( 'background_image' ); 1967 } 1968 1969 add_action( 'delete_attachment', '_delete_attachment_theme_mod' ); 1970 1971 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jun 1 08:30:02 2011 |
Cross-referenced by PHPXref 0.7 Provided by Yoast and awesome WordPress Hosting |