[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Theme, template, and stylesheet functions. 4 * 5 * @package WordPress 6 * @subpackage Theme 7 */ 8 9 /** 10 * Returns an array of WP_Theme objects based on the arguments. 11 * 12 * Despite advances over get_themes(), this function is quite expensive, and grows 13 * linearly with additional themes. Stick to wp_get_theme() if possible. 14 * 15 * @since 3.4.0 16 * 17 * @param array $args The search arguments. Optional. 18 * - errors mixed True to return themes with errors, false to return themes without errors, null 19 * to return all themes. Defaults to false. 20 * - allowed mixed (Multisite) True to return only allowed themes for a site. False to return only 21 * disallowed themes for a site. 'site' to return only site-allowed themes. 'network' 22 * to return only network-allowed themes. Null to return all themes. Defaults to null. 23 * - blog_id int (Multisite) The blog ID used to calculate which themes are allowed. Defaults to 0, 24 * synonymous for the current blog. 25 * @return Array of WP_Theme objects. 26 */ 27 function wp_get_themes( $args = array() ) { 28 global $wp_theme_directories; 29 30 $defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 ); 31 $args = wp_parse_args( $args, $defaults ); 32 33 $theme_directories = search_theme_directories(); 34 35 if ( count( $wp_theme_directories ) > 1 ) { 36 // Make sure the current theme wins out, in case search_theme_directories() picks the wrong 37 // one in the case of a conflict. (Normally, last registered theme root wins.) 38 $current_theme = get_stylesheet(); 39 if ( isset( $theme_directories[ $current_theme ] ) ) { 40 $root_of_current_theme = get_raw_theme_root( $current_theme ); 41 if ( ! in_array( $root_of_current_theme, $wp_theme_directories ) ) 42 $root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme; 43 $theme_directories[ $current_theme ]['theme_root'] = $root_of_current_theme; 44 } 45 } 46 47 if ( empty( $theme_directories ) ) 48 return array(); 49 50 if ( is_multisite() && null !== $args['allowed'] ) { 51 $allowed = $args['allowed']; 52 if ( 'network' === $allowed ) 53 $theme_directories = array_intersect_key( $theme_directories, WP_Theme::get_allowed_on_network() ); 54 elseif ( 'site' === $allowed ) 55 $theme_directories = array_intersect_key( $theme_directories, WP_Theme::get_allowed_on_site( $args['blog_id'] ) ); 56 elseif ( $allowed ) 57 $theme_directories = array_intersect_key( $theme_directories, WP_Theme::get_allowed( $args['blog_id'] ) ); 58 else 59 $theme_directories = array_diff_key( $theme_directories, WP_Theme::get_allowed( $args['blog_id'] ) ); 60 } 61 62 $themes = array(); 63 static $_themes = array(); 64 65 foreach ( $theme_directories as $theme => $theme_root ) { 66 if ( isset( $_themes[ $theme_root['theme_root'] . '/' . $theme ] ) ) 67 $themes[ $theme ] = $_themes[ $theme_root['theme_root'] . '/' . $theme ]; 68 else 69 $themes[ $theme ] = $_themes[ $theme_root['theme_root'] . '/' . $theme ] = new WP_Theme( $theme, $theme_root['theme_root'] ); 70 } 71 72 if ( null !== $args['errors'] ) { 73 foreach ( $themes as $theme => $wp_theme ) { 74 if ( $wp_theme->errors() != $args['errors'] ) 75 unset( $themes[ $theme ] ); 76 } 77 } 78 79 return $themes; 80 } 81 82 /** 83 * Gets a WP_Theme object for a theme. 84 * 85 * @since 3.4.0 86 * 87 * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme. 88 * @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root() 89 * is used to calculate the theme root for the $stylesheet provided (or current theme). 90 * @return WP_Theme Theme object. Be sure to check the object's exists() method if you need to confirm the theme's existence. 91 */ 92 function wp_get_theme( $stylesheet = null, $theme_root = null ) { 93 global $wp_theme_directories; 94 95 if ( empty( $stylesheet ) ) 96 $stylesheet = get_stylesheet(); 97 98 if ( empty( $theme_root ) ) { 99 $theme_root = get_raw_theme_root( $stylesheet ); 100 if ( false === $theme_root ) 101 $theme_root = WP_CONTENT_DIR . '/themes'; 102 elseif ( ! in_array( $theme_root, (array) $wp_theme_directories ) ) 103 $theme_root = WP_CONTENT_DIR . $theme_root; 104 } 105 106 return new WP_Theme( $stylesheet, $theme_root ); 107 } 108 109 /** 110 * Clears the cache held by get_theme_roots() and WP_Theme. 111 * 112 * @since 3.5.0 113 * @param bool $clear_update_cache Whether to clear the Theme updates cache 114 */ 115 function wp_clean_themes_cache( $clear_update_cache = true ) { 116 if ( $clear_update_cache ) 117 delete_site_transient( 'update_themes' ); 118 search_theme_directories( true ); 119 foreach ( wp_get_themes( array( 'errors' => null ) ) as $theme ) 120 $theme->cache_delete(); 121 } 122 123 /** 124 * Whether a child theme is in use. 125 * 126 * @since 3.0.0 127 * 128 * @return bool true if a child theme is in use, false otherwise. 129 **/ 130 function is_child_theme() { 131 return ( TEMPLATEPATH !== STYLESHEETPATH ); 132 } 133 134 /** 135 * Retrieve name of the current stylesheet. 136 * 137 * The theme name that the administrator has currently set the front end theme 138 * as. 139 * 140 * For all extensive purposes, the template name and the stylesheet name are 141 * going to be the same for most cases. 142 * 143 * @since 1.5.0 144 * 145 * @return string Stylesheet name. 146 */ 147 function get_stylesheet() { 148 /** 149 * Filter the name of current stylesheet. 150 * 151 * @since 1.5.0 152 * 153 * @param string $stylesheet Name of the current stylesheet. 154 */ 155 return apply_filters( 'stylesheet', get_option( 'stylesheet' ) ); 156 } 157 158 /** 159 * Retrieve stylesheet directory path for current theme. 160 * 161 * @since 1.5.0 162 * 163 * @return string Path to current theme directory. 164 */ 165 function get_stylesheet_directory() { 166 $stylesheet = get_stylesheet(); 167 $theme_root = get_theme_root( $stylesheet ); 168 $stylesheet_dir = "$theme_root/$stylesheet"; 169 170 /** 171 * Filter the stylesheet directory path for current theme. 172 * 173 * @since 1.5.0 174 * 175 * @param string $stylesheet_dir Absolute path to the current them. 176 * @param string $stylesheet Directory name of the current theme. 177 * @param string $theme_root Absolute path to themes directory. 178 */ 179 return apply_filters( 'stylesheet_directory', $stylesheet_dir, $stylesheet, $theme_root ); 180 } 181 182 /** 183 * Retrieve stylesheet directory URI. 184 * 185 * @since 1.5.0 186 * 187 * @return string 188 */ 189 function get_stylesheet_directory_uri() { 190 $stylesheet = get_stylesheet(); 191 $theme_root_uri = get_theme_root_uri( $stylesheet ); 192 $stylesheet_dir_uri = "$theme_root_uri/$stylesheet"; 193 194 /** 195 * Filter the stylesheet directory URI. 196 * 197 * @since 1.5.0 198 * 199 * @param string $stylesheet_dir_uri Stylesheet directory URI. 200 * @param string $stylesheet Name of the activated theme's directory. 201 * @param string $theme_root_uri Themes root URI. 202 */ 203 return apply_filters( 'stylesheet_directory_uri', $stylesheet_dir_uri, $stylesheet, $theme_root_uri ); 204 } 205 206 /** 207 * Retrieve URI of current theme stylesheet. 208 * 209 * The stylesheet file name is 'style.css' which is appended to {@link 210 * get_stylesheet_directory_uri() stylesheet directory URI} path. 211 * 212 * @since 1.5.0 213 * 214 * @return string 215 */ 216 function get_stylesheet_uri() { 217 $stylesheet_dir_uri = get_stylesheet_directory_uri(); 218 $stylesheet_uri = $stylesheet_dir_uri . '/style.css'; 219 /** 220 * Filter the URI of the current theme stylesheet. 221 * 222 * @since 1.5.0 223 * 224 * @param string $stylesheet_uri Stylesheet URI for the current theme/child theme. 225 * @param string $stylesheet_dir_uri Stylesheet directory URI for the current theme/child theme. 226 */ 227 return apply_filters( 'stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri ); 228 } 229 230 /** 231 * Retrieve localized stylesheet URI. 232 * 233 * The stylesheet directory for the localized stylesheet files are located, by 234 * default, in the base theme directory. The name of the locale file will be the 235 * locale followed by '.css'. If that does not exist, then the text direction 236 * stylesheet will be checked for existence, for example 'ltr.css'. 237 * 238 * The theme may change the location of the stylesheet directory by either using 239 * the 'stylesheet_directory_uri' filter or the 'locale_stylesheet_uri' filter. 240 * If you want to change the location of the stylesheet files for the entire 241 * WordPress workflow, then change the former. If you just have the locale in a 242 * separate folder, then change the latter. 243 * 244 * @since 2.1.0 245 * 246 * @return string 247 */ 248 function get_locale_stylesheet_uri() { 249 global $wp_locale; 250 $stylesheet_dir_uri = get_stylesheet_directory_uri(); 251 $dir = get_stylesheet_directory(); 252 $locale = get_locale(); 253 if ( file_exists("$dir/$locale.css") ) 254 $stylesheet_uri = "$stylesheet_dir_uri/$locale.css"; 255 elseif ( !empty($wp_locale->text_direction) && file_exists("$dir/{$wp_locale->text_direction}.css") ) 256 $stylesheet_uri = "$stylesheet_dir_uri/{$wp_locale->text_direction}.css"; 257 else 258 $stylesheet_uri = ''; 259 /** 260 * Filter the localized stylesheet URI. 261 * 262 * @since 2.1.0 263 * 264 * @param string $stylesheet_uri Localized stylesheet URI. 265 * @param string $stylesheet_dir_uri Stylesheet directory URI. 266 */ 267 return apply_filters( 'locale_stylesheet_uri', $stylesheet_uri, $stylesheet_dir_uri ); 268 } 269 270 /** 271 * Retrieve name of the current theme. 272 * 273 * @since 1.5.0 274 * @uses apply_filters() Calls 'template' filter on template option. 275 * 276 * @return string Template name. 277 */ 278 function get_template() { 279 /** 280 * Filter the name of the current theme. 281 * 282 * @since 1.5.0 283 * 284 * @param string $template Current theme's directory name. 285 */ 286 return apply_filters( 'template', get_option( 'template' ) ); 287 } 288 289 /** 290 * Retrieve current theme directory. 291 * 292 * @since 1.5.0 293 * 294 * @return string Template directory path. 295 */ 296 function get_template_directory() { 297 $template = get_template(); 298 $theme_root = get_theme_root( $template ); 299 $template_dir = "$theme_root/$template"; 300 301 /** 302 * Filter the current theme directory path. 303 * 304 * @since 1.5.0 305 * 306 * @param string $template_dir The URI of the current theme directory. 307 * @param string $template Directory name of the current theme. 308 * @param string $theme_root Absolute path to the themes directory. 309 */ 310 return apply_filters( 'template_directory', $template_dir, $template, $theme_root ); 311 } 312 313 /** 314 * Retrieve theme directory URI. 315 * 316 * @since 1.5.0 317 * 318 * @return string Template directory URI. 319 */ 320 function get_template_directory_uri() { 321 $template = get_template(); 322 $theme_root_uri = get_theme_root_uri( $template ); 323 $template_dir_uri = "$theme_root_uri/$template"; 324 325 /** 326 * Filter the current theme directory URI. 327 * 328 * @since 1.5.0 329 * 330 * @param string $template_dir_uri The URI of the current theme directory. 331 * @param string $template Directory name of the current theme. 332 * @param string $theme_root_uri The themes root URI. 333 */ 334 return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri ); 335 } 336 337 /** 338 * Retrieve theme roots. 339 * 340 * @since 2.9.0 341 * 342 * @return array|string An array of theme roots keyed by template/stylesheet or a single theme root if all themes have the same root. 343 */ 344 function get_theme_roots() { 345 global $wp_theme_directories; 346 347 if ( count($wp_theme_directories) <= 1 ) 348 return '/themes'; 349 350 $theme_roots = get_site_transient( 'theme_roots' ); 351 if ( false === $theme_roots ) { 352 search_theme_directories( true ); // Regenerate the transient. 353 $theme_roots = get_site_transient( 'theme_roots' ); 354 } 355 return $theme_roots; 356 } 357 358 /** 359 * Register a directory that contains themes. 360 * 361 * @since 2.9.0 362 * 363 * @param string $directory Either the full filesystem path to a theme folder or a folder within WP_CONTENT_DIR 364 * @return bool 365 */ 366 function register_theme_directory( $directory ) { 367 global $wp_theme_directories; 368 369 if ( ! file_exists( $directory ) ) { 370 // Try prepending as the theme directory could be relative to the content directory 371 $directory = WP_CONTENT_DIR . '/' . $directory; 372 // If this directory does not exist, return and do not register 373 if ( ! file_exists( $directory ) ) 374 return false; 375 } 376 377 $wp_theme_directories[] = $directory; 378 379 return true; 380 } 381 382 /** 383 * Search all registered theme directories for complete and valid themes. 384 * 385 * @since 2.9.0 386 * 387 * @param bool $force Optional. Whether to force a new directory scan. Defaults to false. 388 * @return array Valid themes found 389 */ 390 function search_theme_directories( $force = false ) { 391 global $wp_theme_directories; 392 if ( empty( $wp_theme_directories ) ) 393 return false; 394 395 static $found_themes; 396 if ( ! $force && isset( $found_themes ) ) 397 return $found_themes; 398 399 $found_themes = array(); 400 401 $wp_theme_directories = (array) $wp_theme_directories; 402 403 // Set up maybe-relative, maybe-absolute array of theme directories. 404 // We always want to return absolute, but we need to cache relative 405 // to use in get_theme_root(). 406 foreach ( $wp_theme_directories as $theme_root ) { 407 if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) 408 $relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root; 409 else 410 $relative_theme_roots[ $theme_root ] = $theme_root; 411 } 412 413 /** 414 * Filter whether to get the cache of the registered theme directories. 415 * 416 * @since 3.4.0 417 * 418 * @param bool $cache_expiration Whether to get the cache of the theme directories. Default false. 419 * @param string $cache_directory Directory to be searched for the cache. 420 */ 421 if ( $cache_expiration = apply_filters( 'wp_cache_themes_persistently', false, 'search_theme_directories' ) ) { 422 $cached_roots = get_site_transient( 'theme_roots' ); 423 if ( is_array( $cached_roots ) ) { 424 foreach ( $cached_roots as $theme_dir => $theme_root ) { 425 // A cached theme root is no longer around, so skip it. 426 if ( ! isset( $relative_theme_roots[ $theme_root ] ) ) 427 continue; 428 $found_themes[ $theme_dir ] = array( 429 'theme_file' => $theme_dir . '/style.css', 430 'theme_root' => $relative_theme_roots[ $theme_root ], // Convert relative to absolute. 431 ); 432 } 433 return $found_themes; 434 } 435 if ( ! is_int( $cache_expiration ) ) 436 $cache_expiration = 1800; // half hour 437 } else { 438 $cache_expiration = 1800; // half hour 439 } 440 441 /* Loop the registered theme directories and extract all themes */ 442 foreach ( $wp_theme_directories as $theme_root ) { 443 444 // Start with directories in the root of the current theme directory. 445 $dirs = @ scandir( $theme_root ); 446 if ( ! $dirs ) { 447 trigger_error( "$theme_root is not readable", E_USER_NOTICE ); 448 continue; 449 } 450 foreach ( $dirs as $dir ) { 451 if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' ) 452 continue; 453 if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) { 454 // wp-content/themes/a-single-theme 455 // wp-content/themes is $theme_root, a-single-theme is $dir 456 $found_themes[ $dir ] = array( 457 'theme_file' => $dir . '/style.css', 458 'theme_root' => $theme_root, 459 ); 460 } else { 461 $found_theme = false; 462 // wp-content/themes/a-folder-of-themes/* 463 // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs 464 $sub_dirs = @ scandir( $theme_root . '/' . $dir ); 465 if ( ! $sub_dirs ) { 466 trigger_error( "$theme_root/$dir is not readable", E_USER_NOTICE ); 467 continue; 468 } 469 foreach ( $sub_dirs as $sub_dir ) { 470 if ( ! is_dir( $theme_root . '/' . $dir . '/' . $sub_dir ) || $dir[0] == '.' || $dir == 'CVS' ) 471 continue; 472 if ( ! file_exists( $theme_root . '/' . $dir . '/' . $sub_dir . '/style.css' ) ) 473 continue; 474 $found_themes[ $dir . '/' . $sub_dir ] = array( 475 'theme_file' => $dir . '/' . $sub_dir . '/style.css', 476 'theme_root' => $theme_root, 477 ); 478 $found_theme = true; 479 } 480 // Never mind the above, it's just a theme missing a style.css. 481 // Return it; WP_Theme will catch the error. 482 if ( ! $found_theme ) 483 $found_themes[ $dir ] = array( 484 'theme_file' => $dir . '/style.css', 485 'theme_root' => $theme_root, 486 ); 487 } 488 } 489 } 490 491 asort( $found_themes ); 492 493 $theme_roots = array(); 494 $relative_theme_roots = array_flip( $relative_theme_roots ); 495 496 foreach ( $found_themes as $theme_dir => $theme_data ) { 497 $theme_roots[ $theme_dir ] = $relative_theme_roots[ $theme_data['theme_root'] ]; // Convert absolute to relative. 498 } 499 500 if ( $theme_roots != get_site_transient( 'theme_roots' ) ) 501 set_site_transient( 'theme_roots', $theme_roots, $cache_expiration ); 502 503 return $found_themes; 504 } 505 506 /** 507 * Retrieve path to themes directory. 508 * 509 * Does not have trailing slash. 510 * 511 * @since 1.5.0 512 * 513 * @param string $stylesheet_or_template The stylesheet or template name of the theme 514 * @return string Theme path. 515 */ 516 function get_theme_root( $stylesheet_or_template = false ) { 517 global $wp_theme_directories; 518 519 if ( $stylesheet_or_template && $theme_root = get_raw_theme_root( $stylesheet_or_template ) ) { 520 // Always prepend WP_CONTENT_DIR unless the root currently registered as a theme directory. 521 // This gives relative theme roots the benefit of the doubt when things go haywire. 522 if ( ! in_array( $theme_root, (array) $wp_theme_directories ) ) 523 $theme_root = WP_CONTENT_DIR . $theme_root; 524 } else { 525 $theme_root = WP_CONTENT_DIR . '/themes'; 526 } 527 528 /** 529 * Filter the absolute path to the themes directory. 530 * 531 * @since 1.5.0 532 * 533 * @param string $theme_root Absolute path to themes directory. 534 */ 535 return apply_filters( 'theme_root', $theme_root ); 536 } 537 538 /** 539 * Retrieve URI for themes directory. 540 * 541 * Does not have trailing slash. 542 * 543 * @since 1.5.0 544 * 545 * @param string $stylesheet_or_template Optional. The stylesheet or template name of the theme. 546 * Default is to leverage the main theme root. 547 * @param string $theme_root Optional. The theme root for which calculations will be based, preventing 548 * the need for a get_raw_theme_root() call. 549 * @return string Themes URI. 550 */ 551 function get_theme_root_uri( $stylesheet_or_template = false, $theme_root = false ) { 552 global $wp_theme_directories; 553 554 if ( $stylesheet_or_template && ! $theme_root ) 555 $theme_root = get_raw_theme_root( $stylesheet_or_template ); 556 557 if ( $stylesheet_or_template && $theme_root ) { 558 if ( in_array( $theme_root, (array) $wp_theme_directories ) ) { 559 // Absolute path. Make an educated guess. YMMV -- but note the filter below. 560 if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) 561 $theme_root_uri = content_url( str_replace( WP_CONTENT_DIR, '', $theme_root ) ); 562 elseif ( 0 === strpos( $theme_root, ABSPATH ) ) 563 $theme_root_uri = site_url( str_replace( ABSPATH, '', $theme_root ) ); 564 elseif ( 0 === strpos( $theme_root, WP_PLUGIN_DIR ) || 0 === strpos( $theme_root, WPMU_PLUGIN_DIR ) ) 565 $theme_root_uri = plugins_url( basename( $theme_root ), $theme_root ); 566 else 567 $theme_root_uri = $theme_root; 568 } else { 569 $theme_root_uri = content_url( $theme_root ); 570 } 571 } else { 572 $theme_root_uri = content_url( 'themes' ); 573 } 574 575 /** 576 * Filter the URI for themes directory. 577 * 578 * @since 1.5.0 579 * 580 * @param string $theme_root_uri The URI for themes directory. 581 * @param string $siteurl WordPress web address which is set in General Options. 582 * @param string $stylesheet_or_template Stylesheet or template name of the theme. 583 */ 584 return apply_filters( 'theme_root_uri', $theme_root_uri, get_option( 'siteurl' ), $stylesheet_or_template ); 585 } 586 587 /** 588 * Get the raw theme root relative to the content directory with no filters applied. 589 * 590 * @since 3.1.0 591 * 592 * @param string $stylesheet_or_template The stylesheet or template name of the theme 593 * @param bool $skip_cache Optional. Whether to skip the cache. Defaults to false, meaning the cache is used. 594 * @return string Theme root 595 */ 596 function get_raw_theme_root( $stylesheet_or_template, $skip_cache = false ) { 597 global $wp_theme_directories; 598 599 if ( count($wp_theme_directories) <= 1 ) 600 return '/themes'; 601 602 $theme_root = false; 603 604 // If requesting the root for the current theme, consult options to avoid calling get_theme_roots() 605 if ( ! $skip_cache ) { 606 if ( get_option('stylesheet') == $stylesheet_or_template ) 607 $theme_root = get_option('stylesheet_root'); 608 elseif ( get_option('template') == $stylesheet_or_template ) 609 $theme_root = get_option('template_root'); 610 } 611 612 if ( empty($theme_root) ) { 613 $theme_roots = get_theme_roots(); 614 if ( !empty($theme_roots[$stylesheet_or_template]) ) 615 $theme_root = $theme_roots[$stylesheet_or_template]; 616 } 617 618 return $theme_root; 619 } 620 621 /** 622 * Display localized stylesheet link element. 623 * 624 * @since 2.1.0 625 */ 626 function locale_stylesheet() { 627 $stylesheet = get_locale_stylesheet_uri(); 628 if ( empty($stylesheet) ) 629 return; 630 echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />'; 631 } 632 633 /** 634 * Start preview theme output buffer. 635 * 636 * Will only perform task if the user has permissions and template and preview 637 * query variables exist. 638 * 639 * @since 2.6.0 640 */ 641 function preview_theme() { 642 if ( ! (isset($_GET['template']) && isset($_GET['preview'])) ) 643 return; 644 645 if ( !current_user_can( 'switch_themes' ) ) 646 return; 647 648 // Admin Thickbox requests 649 if ( isset( $_GET['preview_iframe'] ) ) 650 show_admin_bar( false ); 651 652 $_GET['template'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['template']); 653 654 if ( validate_file($_GET['template']) ) 655 return; 656 657 add_filter( 'template', '_preview_theme_template_filter' ); 658 659 if ( isset($_GET['stylesheet']) ) { 660 $_GET['stylesheet'] = preg_replace('|[^a-z0-9_./-]|i', '', $_GET['stylesheet']); 661 if ( validate_file($_GET['stylesheet']) ) 662 return; 663 add_filter( 'stylesheet', '_preview_theme_stylesheet_filter' ); 664 } 665 666 // Prevent theme mods to current theme being used on theme being previewed 667 add_filter( 'pre_option_theme_mods_' . get_option( 'stylesheet' ), '__return_empty_array' ); 668 669 ob_start( 'preview_theme_ob_filter' ); 670 } 671 add_action('setup_theme', 'preview_theme'); 672 673 /** 674 * Private function to modify the current template when previewing a theme 675 * 676 * @since 2.9.0 677 * @access private 678 * 679 * @return string 680 */ 681 function _preview_theme_template_filter() { 682 return isset($_GET['template']) ? $_GET['template'] : ''; 683 } 684 685 /** 686 * Private function to modify the current stylesheet when previewing a theme 687 * 688 * @since 2.9.0 689 * @access private 690 * 691 * @return string 692 */ 693 function _preview_theme_stylesheet_filter() { 694 return isset($_GET['stylesheet']) ? $_GET['stylesheet'] : ''; 695 } 696 697 /** 698 * Callback function for ob_start() to capture all links in the theme. 699 * 700 * @since 2.6.0 701 * @access private 702 * 703 * @param string $content 704 * @return string 705 */ 706 function preview_theme_ob_filter( $content ) { 707 return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content ); 708 } 709 710 /** 711 * Manipulates preview theme links in order to control and maintain location. 712 * 713 * Callback function for preg_replace_callback() to accept and filter matches. 714 * 715 * @since 2.6.0 716 * @access private 717 * 718 * @param array $matches 719 * @return string 720 */ 721 function preview_theme_ob_filter_callback( $matches ) { 722 if ( strpos($matches[4], 'onclick') !== false ) 723 $matches[4] = preg_replace('#onclick=([\'"]).*?(?<!\\\)\\1#i', '', $matches[4]); //Strip out any onclicks from rest of <a>. (?<!\\\) means to ignore the '" if it's escaped by \ to prevent breaking mid-attribute. 724 if ( 725 ( false !== strpos($matches[3], '/wp-admin/') ) 726 || 727 ( false !== strpos( $matches[3], '://' ) && 0 !== strpos( $matches[3], home_url() ) ) 728 || 729 ( false !== strpos($matches[3], '/feed/') ) 730 || 731 ( false !== strpos($matches[3], '/trackback/') ) 732 ) 733 return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4]; 734 735 $stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : ''; 736 $template = isset( $_GET['template'] ) ? $_GET['template'] : ''; 737 738 $link = add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => 1 ), $matches[3] ); 739 if ( 0 === strpos($link, 'preview=1') ) 740 $link = "?$link"; 741 return $matches[1] . esc_attr( $link ) . $matches[4]; 742 } 743 744 /** 745 * Switches the theme. 746 * 747 * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature 748 * of two arguments: $template then $stylesheet. This is for backwards compatibility. 749 * 750 * @since 2.5.0 751 * 752 * @param string $stylesheet Stylesheet name 753 */ 754 function switch_theme( $stylesheet ) { 755 global $wp_theme_directories, $sidebars_widgets; 756 757 if ( is_array( $sidebars_widgets ) ) 758 set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $sidebars_widgets ) ); 759 760 $old_theme = wp_get_theme(); 761 $new_theme = wp_get_theme( $stylesheet ); 762 763 if ( func_num_args() > 1 ) { 764 $template = $stylesheet; 765 $stylesheet = func_get_arg( 1 ); 766 } else { 767 $template = $new_theme->get_template(); 768 } 769 770 update_option( 'template', $template ); 771 update_option( 'stylesheet', $stylesheet ); 772 773 if ( count( $wp_theme_directories ) > 1 ) { 774 update_option( 'template_root', get_raw_theme_root( $template, true ) ); 775 update_option( 'stylesheet_root', get_raw_theme_root( $stylesheet, true ) ); 776 } else { 777 delete_option( 'template_root' ); 778 delete_option( 'stylesheet_root' ); 779 } 780 781 $new_name = $new_theme->get('Name'); 782 783 update_option( 'current_theme', $new_name ); 784 785 if ( is_admin() && false === get_option( 'theme_mods_' . $stylesheet ) ) { 786 $default_theme_mods = (array) get_option( 'mods_' . $new_name ); 787 add_option( "theme_mods_$stylesheet", $default_theme_mods ); 788 } 789 790 update_option( 'theme_switched', $old_theme->get_stylesheet() ); 791 /** 792 * Fires after the theme is switched. 793 * 794 * @since 1.5.0 795 * 796 * @param string $new_name Name of the new theme. 797 * @param WP_Theme $new_theme WP_Theme instance of the new theme. 798 */ 799 do_action( 'switch_theme', $new_name, $new_theme ); 800 } 801 802 /** 803 * Checks that current theme files 'index.php' and 'style.css' exists. 804 * 805 * Does not check the default theme, which is the fallback and should always exist. 806 * Will switch theme to the fallback theme if current theme does not validate. 807 * You can use the 'validate_current_theme' filter to return false to 808 * disable this functionality. 809 * 810 * @since 1.5.0 811 * @see WP_DEFAULT_THEME 812 * 813 * @return bool 814 */ 815 function validate_current_theme() { 816 /** 817 * Filter whether to validate the current theme. 818 * 819 * @since 2.7.0 820 * 821 * @param bool true Validation flag to check the current theme. 822 */ 823 if ( defined('WP_INSTALLING') || ! apply_filters( 'validate_current_theme', true ) ) 824 return true; 825 826 if ( get_template() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/index.php') ) { 827 switch_theme( WP_DEFAULT_THEME ); 828 return false; 829 } 830 831 if ( get_stylesheet() != WP_DEFAULT_THEME && !file_exists(get_template_directory() . '/style.css') ) { 832 switch_theme( WP_DEFAULT_THEME ); 833 return false; 834 } 835 836 if ( is_child_theme() && ! file_exists( get_stylesheet_directory() . '/style.css' ) ) { 837 switch_theme( WP_DEFAULT_THEME ); 838 return false; 839 } 840 841 return true; 842 } 843 844 /** 845 * Retrieve all theme modifications. 846 * 847 * @since 3.1.0 848 * 849 * @return array Theme modifications. 850 */ 851 function get_theme_mods() { 852 $theme_slug = get_option( 'stylesheet' ); 853 if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) { 854 $theme_name = get_option( 'current_theme' ); 855 if ( false === $theme_name ) 856 $theme_name = wp_get_theme()->get('Name'); 857 $mods = get_option( "mods_$theme_name" ); // Deprecated location. 858 if ( is_admin() && false !== $mods ) { 859 update_option( "theme_mods_$theme_slug", $mods ); 860 delete_option( "mods_$theme_name" ); 861 } 862 } 863 return $mods; 864 } 865 866 /** 867 * Retrieve theme modification value for the current theme. 868 * 869 * If the modification name does not exist, then the $default will be passed 870 * through {@link http://php.net/sprintf sprintf()} PHP function with the first 871 * string the template directory URI and the second string the stylesheet 872 * directory URI. 873 * 874 * @since 2.1.0 875 * 876 * @param string $name Theme modification name. 877 * @param bool|string $default 878 * @return string 879 */ 880 function get_theme_mod( $name, $default = false ) { 881 $mods = get_theme_mods(); 882 883 if ( isset( $mods[$name] ) ) { 884 /** 885 * Filter the theme modification, or 'theme_mod', value. 886 * 887 * The dynamic portion of the hook name, $name, refers to 888 * the key name of the modification array. For example, 889 * 'header_textcolor', 'header_image', and so on depending 890 * on the theme options. 891 * 892 * @since 2.2.0 893 * 894 * @param string $current_mod The value of the current theme modification. 895 */ 896 return apply_filters( "theme_mod_{$name}", $mods[$name] ); 897 } 898 899 if ( is_string( $default ) ) 900 $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ); 901 902 /** This filter is documented in wp-includes/theme.php */ 903 return apply_filters( "theme_mod_{$name}", $default ); 904 } 905 906 /** 907 * Update theme modification value for the current theme. 908 * 909 * @since 2.1.0 910 * 911 * @param string $name Theme modification name. 912 * @param string $value theme modification value. 913 */ 914 function set_theme_mod( $name, $value ) { 915 $mods = get_theme_mods(); 916 917 $mods[ $name ] = $value; 918 919 $theme = get_option( 'stylesheet' ); 920 update_option( "theme_mods_$theme", $mods ); 921 } 922 923 /** 924 * Remove theme modification name from current theme list. 925 * 926 * If removing the name also removes all elements, then the entire option will 927 * be removed. 928 * 929 * @since 2.1.0 930 * 931 * @param string $name Theme modification name. 932 * @return null 933 */ 934 function remove_theme_mod( $name ) { 935 $mods = get_theme_mods(); 936 937 if ( ! isset( $mods[ $name ] ) ) 938 return; 939 940 unset( $mods[ $name ] ); 941 942 if ( empty( $mods ) ) 943 return remove_theme_mods(); 944 945 $theme = get_option( 'stylesheet' ); 946 update_option( "theme_mods_$theme", $mods ); 947 } 948 949 /** 950 * Remove theme modifications option for current theme. 951 * 952 * @since 2.1.0 953 */ 954 function remove_theme_mods() { 955 delete_option( 'theme_mods_' . get_option( 'stylesheet' ) ); 956 957 // Old style. 958 $theme_name = get_option( 'current_theme' ); 959 if ( false === $theme_name ) 960 $theme_name = wp_get_theme()->get('Name'); 961 delete_option( 'mods_' . $theme_name ); 962 } 963 964 /** 965 * Retrieve text color for custom header. 966 * 967 * @since 2.1.0 968 * 969 * @return string 970 */ 971 function get_header_textcolor() { 972 return get_theme_mod('header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) ); 973 } 974 975 /** 976 * Display text color for custom header. 977 * 978 * @since 2.1.0 979 */ 980 function header_textcolor() { 981 echo get_header_textcolor(); 982 } 983 984 /** 985 * Whether to display the header text. 986 * 987 * @since 3.4.0 988 * 989 * @return bool 990 */ 991 function display_header_text() { 992 if ( ! current_theme_supports( 'custom-header', 'header-text' ) ) 993 return false; 994 995 $text_color = get_theme_mod( 'header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) ); 996 return 'blank' != $text_color; 997 } 998 999 /** 1000 * Retrieve header image for custom header. 1001 * 1002 * @since 2.1.0 1003 * 1004 * @return string 1005 */ 1006 function get_header_image() { 1007 $url = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) ); 1008 1009 if ( 'remove-header' == $url ) 1010 return false; 1011 1012 if ( is_random_header_image() ) 1013 $url = get_random_header_image(); 1014 1015 return esc_url_raw( set_url_scheme( $url ) ); 1016 } 1017 1018 /** 1019 * Get random header image data from registered images in theme. 1020 * 1021 * @since 3.4.0 1022 * 1023 * @access private 1024 * 1025 * @return string Path to header image 1026 */ 1027 1028 function _get_random_header_data() { 1029 static $_wp_random_header; 1030 1031 if ( empty( $_wp_random_header ) ) { 1032 global $_wp_default_headers; 1033 $header_image_mod = get_theme_mod( 'header_image', '' ); 1034 $headers = array(); 1035 1036 if ( 'random-uploaded-image' == $header_image_mod ) 1037 $headers = get_uploaded_header_images(); 1038 elseif ( ! empty( $_wp_default_headers ) ) { 1039 if ( 'random-default-image' == $header_image_mod ) { 1040 $headers = $_wp_default_headers; 1041 } else { 1042 if ( current_theme_supports( 'custom-header', 'random-default' ) ) 1043 $headers = $_wp_default_headers; 1044 } 1045 } 1046 1047 if ( empty( $headers ) ) 1048 return new stdClass; 1049 1050 $_wp_random_header = (object) $headers[ array_rand( $headers ) ]; 1051 1052 $_wp_random_header->url = sprintf( $_wp_random_header->url, get_template_directory_uri(), get_stylesheet_directory_uri() ); 1053 $_wp_random_header->thumbnail_url = sprintf( $_wp_random_header->thumbnail_url, get_template_directory_uri(), get_stylesheet_directory_uri() ); 1054 } 1055 return $_wp_random_header; 1056 } 1057 1058 /** 1059 * Get random header image url from registered images in theme. 1060 * 1061 * @since 3.2.0 1062 * 1063 * @return string Path to header image 1064 */ 1065 1066 function get_random_header_image() { 1067 $random_image = _get_random_header_data(); 1068 if ( empty( $random_image->url ) ) 1069 return ''; 1070 return $random_image->url; 1071 } 1072 1073 /** 1074 * Check if random header image is in use. 1075 * 1076 * Always true if user expressly chooses the option in Appearance > Header. 1077 * Also true if theme has multiple header images registered, no specific header image 1078 * is chosen, and theme turns on random headers with add_theme_support(). 1079 * 1080 * @since 3.2.0 1081 * 1082 * @param string $type The random pool to use. any|default|uploaded 1083 * @return boolean 1084 */ 1085 function is_random_header_image( $type = 'any' ) { 1086 $header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) ); 1087 1088 if ( 'any' == $type ) { 1089 if ( 'random-default-image' == $header_image_mod || 'random-uploaded-image' == $header_image_mod || ( '' != get_random_header_image() && empty( $header_image_mod ) ) ) 1090 return true; 1091 } else { 1092 if ( "random-$type-image" == $header_image_mod ) 1093 return true; 1094 elseif ( 'default' == $type && empty( $header_image_mod ) && '' != get_random_header_image() ) 1095 return true; 1096 } 1097 1098 return false; 1099 } 1100 1101 /** 1102 * Display header image URL. 1103 * 1104 * @since 2.1.0 1105 */ 1106 function header_image() { 1107 echo esc_url( get_header_image() ); 1108 } 1109 1110 /** 1111 * Get the header images uploaded for the current theme. 1112 * 1113 * @since 3.2.0 1114 * 1115 * @return array 1116 */ 1117 function get_uploaded_header_images() { 1118 $header_images = array(); 1119 1120 // @todo caching 1121 $headers = get_posts( array( 'post_type' => 'attachment', 'meta_key' => '_wp_attachment_is_custom_header', 'meta_value' => get_option('stylesheet'), 'orderby' => 'none', 'nopaging' => true ) ); 1122 1123 if ( empty( $headers ) ) 1124 return array(); 1125 1126 foreach ( (array) $headers as $header ) { 1127 $url = esc_url_raw( $header->guid ); 1128 $header_data = wp_get_attachment_metadata( $header->ID ); 1129 $header_index = basename($url); 1130 $header_images[$header_index] = array(); 1131 $header_images[$header_index]['attachment_id'] = $header->ID; 1132 $header_images[$header_index]['url'] = $url; 1133 $header_images[$header_index]['thumbnail_url'] = $url; 1134 if ( isset( $header_data['width'] ) ) 1135 $header_images[$header_index]['width'] = $header_data['width']; 1136 if ( isset( $header_data['height'] ) ) 1137 $header_images[$header_index]['height'] = $header_data['height']; 1138 } 1139 1140 return $header_images; 1141 } 1142 1143 /** 1144 * Get the header image data. 1145 * 1146 * @since 3.4.0 1147 * 1148 * @return object 1149 */ 1150 function get_custom_header() { 1151 global $_wp_default_headers; 1152 1153 if ( is_random_header_image() ) { 1154 $data = _get_random_header_data(); 1155 } else { 1156 $data = get_theme_mod( 'header_image_data' ); 1157 if ( ! $data && current_theme_supports( 'custom-header', 'default-image' ) ) { 1158 $directory_args = array( get_template_directory_uri(), get_stylesheet_directory_uri() ); 1159 $data = array(); 1160 $data['url'] = $data['thumbnail_url'] = vsprintf( get_theme_support( 'custom-header', 'default-image' ), $directory_args ); 1161 if ( ! empty( $_wp_default_headers ) ) { 1162 foreach ( (array) $_wp_default_headers as $default_header ) { 1163 $url = vsprintf( $default_header['url'], $directory_args ); 1164 if ( $data['url'] == $url ) { 1165 $data = $default_header; 1166 $data['url'] = $url; 1167 $data['thumbnail_url'] = vsprintf( $data['thumbnail_url'], $directory_args ); 1168 break; 1169 } 1170 } 1171 } 1172 } 1173 } 1174 1175 $default = array( 1176 'url' => '', 1177 'thumbnail_url' => '', 1178 'width' => get_theme_support( 'custom-header', 'width' ), 1179 'height' => get_theme_support( 'custom-header', 'height' ), 1180 ); 1181 return (object) wp_parse_args( $data, $default ); 1182 } 1183 1184 /** 1185 * Register a selection of default headers to be displayed by the custom header admin UI. 1186 * 1187 * @since 3.0.0 1188 * 1189 * @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys. 1190 */ 1191 function register_default_headers( $headers ) { 1192 global $_wp_default_headers; 1193 1194 $_wp_default_headers = array_merge( (array) $_wp_default_headers, (array) $headers ); 1195 } 1196 1197 /** 1198 * Unregister default headers. 1199 * 1200 * This function must be called after register_default_headers() has already added the 1201 * header you want to remove. 1202 * 1203 * @see register_default_headers() 1204 * @since 3.0.0 1205 * 1206 * @param string|array $header The header string id (key of array) to remove, or an array thereof. 1207 * @return True on success, false on failure. 1208 */ 1209 function unregister_default_headers( $header ) { 1210 global $_wp_default_headers; 1211 if ( is_array( $header ) ) { 1212 array_map( 'unregister_default_headers', $header ); 1213 } elseif ( isset( $_wp_default_headers[ $header ] ) ) { 1214 unset( $_wp_default_headers[ $header ] ); 1215 return true; 1216 } else { 1217 return false; 1218 } 1219 } 1220 1221 /** 1222 * Retrieve background image for custom background. 1223 * 1224 * @since 3.0.0 1225 * 1226 * @return string 1227 */ 1228 function get_background_image() { 1229 return get_theme_mod('background_image', get_theme_support( 'custom-background', 'default-image' ) ); 1230 } 1231 1232 /** 1233 * Display background image path. 1234 * 1235 * @since 3.0.0 1236 */ 1237 function background_image() { 1238 echo get_background_image(); 1239 } 1240 1241 /** 1242 * Retrieve value for custom background color. 1243 * 1244 * @since 3.0.0 1245 * 1246 * @return string 1247 */ 1248 function get_background_color() { 1249 return get_theme_mod('background_color', get_theme_support( 'custom-background', 'default-color' ) ); 1250 } 1251 1252 /** 1253 * Display background color value. 1254 * 1255 * @since 3.0.0 1256 */ 1257 function background_color() { 1258 echo get_background_color(); 1259 } 1260 1261 /** 1262 * Default custom background callback. 1263 * 1264 * @since 3.0.0 1265 * @access protected 1266 */ 1267 function _custom_background_cb() { 1268 // $background is the saved custom image, or the default image. 1269 $background = set_url_scheme( get_background_image() ); 1270 1271 // $color is the saved custom color. 1272 // A default has to be specified in style.css. It will not be printed here. 1273 $color = get_theme_mod( 'background_color' ); 1274 1275 if ( ! $background && ! $color ) 1276 return; 1277 1278 $style = $color ? "background-color: #$color;" : ''; 1279 1280 if ( $background ) { 1281 $image = " background-image: url('$background');"; 1282 1283 $repeat = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) ); 1284 if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) ) 1285 $repeat = 'repeat'; 1286 $repeat = " background-repeat: $repeat;"; 1287 1288 $position = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) ); 1289 if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) ) 1290 $position = 'left'; 1291 $position = " background-position: top $position;"; 1292 1293 $attachment = get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) ); 1294 if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) ) 1295 $attachment = 'scroll'; 1296 $attachment = " background-attachment: $attachment;"; 1297 1298 $style .= $image . $repeat . $position . $attachment; 1299 } 1300 ?> 1301 <style type="text/css" id="custom-background-css"> 1302 body.custom-background { <?php echo trim( $style ); ?> } 1303 </style> 1304 <?php 1305 } 1306 1307 /** 1308 * Add callback for custom TinyMCE editor stylesheets. 1309 * 1310 * The parameter $stylesheet is the name of the stylesheet, relative to 1311 * the theme root. It also accepts an array of stylesheets. 1312 * It is optional and defaults to 'editor-style.css'. 1313 * 1314 * This function automatically adds another stylesheet with -rtl prefix, e.g. editor-style-rtl.css. 1315 * If that file doesn't exist, it is removed before adding the stylesheet(s) to TinyMCE. 1316 * If an array of stylesheets is passed to add_editor_style(), 1317 * RTL is only added for the first stylesheet. 1318 * 1319 * Since version 3.4 the TinyMCE body has .rtl CSS class. 1320 * It is a better option to use that class and add any RTL styles to the main stylesheet. 1321 * 1322 * @since 3.0.0 1323 * 1324 * @param mixed $stylesheet Optional. Stylesheet name or array thereof, relative to theme root. 1325 * Defaults to 'editor-style.css' 1326 */ 1327 function add_editor_style( $stylesheet = 'editor-style.css' ) { 1328 1329 add_theme_support( 'editor-style' ); 1330 1331 if ( ! is_admin() ) 1332 return; 1333 1334 global $editor_styles; 1335 $editor_styles = (array) $editor_styles; 1336 $stylesheet = (array) $stylesheet; 1337 if ( is_rtl() ) { 1338 $rtl_stylesheet = str_replace('.css', '-rtl.css', $stylesheet[0]); 1339 $stylesheet[] = $rtl_stylesheet; 1340 } 1341 1342 $editor_styles = array_merge( $editor_styles, $stylesheet ); 1343 } 1344 1345 /** 1346 * Removes all visual editor stylesheets. 1347 * 1348 * @since 3.1.0 1349 * 1350 * @return bool True on success, false if there were no stylesheets to remove. 1351 */ 1352 function remove_editor_styles() { 1353 if ( ! current_theme_supports( 'editor-style' ) ) 1354 return false; 1355 _remove_theme_support( 'editor-style' ); 1356 if ( is_admin() ) 1357 $GLOBALS['editor_styles'] = array(); 1358 return true; 1359 } 1360 1361 /** 1362 * Allows a theme to register its support of a certain feature 1363 * 1364 * Must be called in the theme's functions.php file to work. 1365 * If attached to a hook, it must be after_setup_theme. 1366 * The init hook may be too late for some features. 1367 * 1368 * @since 2.9.0 1369 * @param string $feature the feature being added 1370 */ 1371 function add_theme_support( $feature ) { 1372 global $_wp_theme_features; 1373 1374 if ( func_num_args() == 1 ) 1375 $args = true; 1376 else 1377 $args = array_slice( func_get_args(), 1 ); 1378 1379 switch ( $feature ) { 1380 case 'post-formats' : 1381 if ( is_array( $args[0] ) ) 1382 $args[0] = array_intersect( $args[0], array_keys( get_post_format_slugs() ) ); 1383 break; 1384 1385 case 'html5' : 1386 // You can't just pass 'html5', you need to pass an array of types. 1387 if ( empty( $args[0] ) ) { 1388 $args = array( 0 => array( 'comment-list', 'comment-form', 'search-form' ) ); 1389 } elseif ( ! is_array( $args[0] ) ) { 1390 _doing_it_wrong( "add_theme_support( 'html5' )", 'You need to pass an array of types.', '3.6.1' ); 1391 return false; 1392 } 1393 1394 // Calling 'html5' again merges, rather than overwrites. 1395 if ( isset( $_wp_theme_features['html5'] ) ) 1396 $args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] ); 1397 break; 1398 1399 case 'custom-header-uploads' : 1400 return add_theme_support( 'custom-header', array( 'uploads' => true ) ); 1401 break; 1402 1403 case 'custom-header' : 1404 if ( ! is_array( $args ) ) 1405 $args = array( 0 => array() ); 1406 1407 $defaults = array( 1408 'default-image' => '', 1409 'random-default' => false, 1410 'width' => 0, 1411 'height' => 0, 1412 'flex-height' => false, 1413 'flex-width' => false, 1414 'default-text-color' => '', 1415 'header-text' => true, 1416 'uploads' => true, 1417 'wp-head-callback' => '', 1418 'admin-head-callback' => '', 1419 'admin-preview-callback' => '', 1420 ); 1421 1422 $jit = isset( $args[0]['__jit'] ); 1423 unset( $args[0]['__jit'] ); 1424 1425 // Merge in data from previous add_theme_support() calls. 1426 // The first value registered wins. (A child theme is set up first.) 1427 if ( isset( $_wp_theme_features['custom-header'] ) ) 1428 $args[0] = wp_parse_args( $_wp_theme_features['custom-header'][0], $args[0] ); 1429 1430 // Load in the defaults at the end, as we need to insure first one wins. 1431 // This will cause all constants to be defined, as each arg will then be set to the default. 1432 if ( $jit ) 1433 $args[0] = wp_parse_args( $args[0], $defaults ); 1434 1435 // If a constant was defined, use that value. Otherwise, define the constant to ensure 1436 // the constant is always accurate (and is not defined later, overriding our value). 1437 // As stated above, the first value wins. 1438 // Once we get to wp_loaded (just-in-time), define any constants we haven't already. 1439 // Constants are lame. Don't reference them. This is just for backwards compatibility. 1440 1441 if ( defined( 'NO_HEADER_TEXT' ) ) 1442 $args[0]['header-text'] = ! NO_HEADER_TEXT; 1443 elseif ( isset( $args[0]['header-text'] ) ) 1444 define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) ); 1445 1446 if ( defined( 'HEADER_IMAGE_WIDTH' ) ) 1447 $args[0]['width'] = (int) HEADER_IMAGE_WIDTH; 1448 elseif ( isset( $args[0]['width'] ) ) 1449 define( 'HEADER_IMAGE_WIDTH', (int) $args[0]['width'] ); 1450 1451 if ( defined( 'HEADER_IMAGE_HEIGHT' ) ) 1452 $args[0]['height'] = (int) HEADER_IMAGE_HEIGHT; 1453 elseif ( isset( $args[0]['height'] ) ) 1454 define( 'HEADER_IMAGE_HEIGHT', (int) $args[0]['height'] ); 1455 1456 if ( defined( 'HEADER_TEXTCOLOR' ) ) 1457 $args[0]['default-text-color'] = HEADER_TEXTCOLOR; 1458 elseif ( isset( $args[0]['default-text-color'] ) ) 1459 define( 'HEADER_TEXTCOLOR', $args[0]['default-text-color'] ); 1460 1461 if ( defined( 'HEADER_IMAGE' ) ) 1462 $args[0]['default-image'] = HEADER_IMAGE; 1463 elseif ( isset( $args[0]['default-image'] ) ) 1464 define( 'HEADER_IMAGE', $args[0]['default-image'] ); 1465 1466 if ( $jit && ! empty( $args[0]['default-image'] ) ) 1467 $args[0]['random-default'] = false; 1468 1469 // If headers are supported, and we still don't have a defined width or height, 1470 // we have implicit flex sizes. 1471 if ( $jit ) { 1472 if ( empty( $args[0]['width'] ) && empty( $args[0]['flex-width'] ) ) 1473 $args[0]['flex-width'] = true; 1474 if ( empty( $args[0]['height'] ) && empty( $args[0]['flex-height'] ) ) 1475 $args[0]['flex-height'] = true; 1476 } 1477 1478 break; 1479 1480 case 'custom-background' : 1481 if ( ! is_array( $args ) ) 1482 $args = array( 0 => array() ); 1483 1484 $defaults = array( 1485 'default-image' => '', 1486 'default-repeat' => 'repeat', 1487 'default-position-x' => 'left', 1488 'default-attachment' => 'scroll', 1489 'default-color' => '', 1490 'wp-head-callback' => '_custom_background_cb', 1491 'admin-head-callback' => '', 1492 'admin-preview-callback' => '', 1493 ); 1494 1495 $jit = isset( $args[0]['__jit'] ); 1496 unset( $args[0]['__jit'] ); 1497 1498 // Merge in data from previous add_theme_support() calls. The first value registered wins. 1499 if ( isset( $_wp_theme_features['custom-background'] ) ) 1500 $args[0] = wp_parse_args( $_wp_theme_features['custom-background'][0], $args[0] ); 1501 1502 if ( $jit ) 1503 $args[0] = wp_parse_args( $args[0], $defaults ); 1504 1505 if ( defined( 'BACKGROUND_COLOR' ) ) 1506 $args[0]['default-color'] = BACKGROUND_COLOR; 1507 elseif ( isset( $args[0]['default-color'] ) || $jit ) 1508 define( 'BACKGROUND_COLOR', $args[0]['default-color'] ); 1509 1510 if ( defined( 'BACKGROUND_IMAGE' ) ) 1511 $args[0]['default-image'] = BACKGROUND_IMAGE; 1512 elseif ( isset( $args[0]['default-image'] ) || $jit ) 1513 define( 'BACKGROUND_IMAGE', $args[0]['default-image'] ); 1514 1515 break; 1516 } 1517 1518 $_wp_theme_features[ $feature ] = $args; 1519 } 1520 1521 /** 1522 * Registers the internal custom header and background routines. 1523 * 1524 * @since 3.4.0 1525 * @access private 1526 */ 1527 function _custom_header_background_just_in_time() { 1528 global $custom_image_header, $custom_background; 1529 1530 if ( current_theme_supports( 'custom-header' ) ) { 1531 // In case any constants were defined after an add_custom_image_header() call, re-run. 1532 add_theme_support( 'custom-header', array( '__jit' => true ) ); 1533 1534 $args = get_theme_support( 'custom-header' ); 1535 if ( $args[0]['wp-head-callback'] ) 1536 add_action( 'wp_head', $args[0]['wp-head-callback'] ); 1537 1538 if ( is_admin() ) { 1539 require_once ( ABSPATH . 'wp-admin/custom-header.php' ); 1540 $custom_image_header = new Custom_Image_Header( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] ); 1541 } 1542 } 1543 1544 if ( current_theme_supports( 'custom-background' ) ) { 1545 // In case any constants were defined after an add_custom_background() call, re-run. 1546 add_theme_support( 'custom-background', array( '__jit' => true ) ); 1547 1548 $args = get_theme_support( 'custom-background' ); 1549 add_action( 'wp_head', $args[0]['wp-head-callback'] ); 1550 1551 if ( is_admin() ) { 1552 require_once ( ABSPATH . 'wp-admin/custom-background.php' ); 1553 $custom_background = new Custom_Background( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] ); 1554 } 1555 } 1556 } 1557 add_action( 'wp_loaded', '_custom_header_background_just_in_time' ); 1558 1559 /** 1560 * Gets the theme support arguments passed when registering that support 1561 * 1562 * @since 3.1 1563 * @param string $feature the feature to check 1564 * @return array The array of extra arguments 1565 */ 1566 function get_theme_support( $feature ) { 1567 global $_wp_theme_features; 1568 if ( ! isset( $_wp_theme_features[ $feature ] ) ) 1569 return false; 1570 1571 if ( func_num_args() <= 1 ) 1572 return $_wp_theme_features[ $feature ]; 1573 1574 $args = array_slice( func_get_args(), 1 ); 1575 switch ( $feature ) { 1576 case 'custom-header' : 1577 case 'custom-background' : 1578 if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) ) 1579 return $_wp_theme_features[ $feature ][0][ $args[0] ]; 1580 return false; 1581 break; 1582 default : 1583 return $_wp_theme_features[ $feature ]; 1584 break; 1585 } 1586 } 1587 1588 /** 1589 * Allows a theme to de-register its support of a certain feature 1590 * 1591 * Should be called in the theme's functions.php file. Generally would 1592 * be used for child themes to override support from the parent theme. 1593 * 1594 * @since 3.0.0 1595 * @see add_theme_support() 1596 * @param string $feature the feature being added 1597 * @return bool Whether feature was removed. 1598 */ 1599 function remove_theme_support( $feature ) { 1600 // Blacklist: for internal registrations not used directly by themes. 1601 if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) ) 1602 return false; 1603 1604 return _remove_theme_support( $feature ); 1605 } 1606 1607 /** 1608 * Do not use. Removes theme support internally, ignorant of the blacklist. 1609 * 1610 * @access private 1611 * @since 3.1.0 1612 */ 1613 function _remove_theme_support( $feature ) { 1614 global $_wp_theme_features; 1615 1616 switch ( $feature ) { 1617 case 'custom-header-uploads' : 1618 if ( ! isset( $_wp_theme_features['custom-header'] ) ) 1619 return false; 1620 add_theme_support( 'custom-header', array( 'uploads' => false ) ); 1621 return; // Do not continue - custom-header-uploads no longer exists. 1622 } 1623 1624 if ( ! isset( $_wp_theme_features[ $feature ] ) ) 1625 return false; 1626 1627 switch ( $feature ) { 1628 case 'custom-header' : 1629 if ( ! did_action( 'wp_loaded' ) ) 1630 break; 1631 $support = get_theme_support( 'custom-header' ); 1632 if ( $support[0]['wp-head-callback'] ) 1633 remove_action( 'wp_head', $support[0]['wp-head-callback'] ); 1634 remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) ); 1635 unset( $GLOBALS['custom_image_header'] ); 1636 break; 1637 1638 case 'custom-background' : 1639 if ( ! did_action( 'wp_loaded' ) ) 1640 break; 1641 $support = get_theme_support( 'custom-background' ); 1642 remove_action( 'wp_head', $support[0]['wp-head-callback'] ); 1643 remove_action( 'admin_menu', array( $GLOBALS['custom_background'], 'init' ) ); 1644 unset( $GLOBALS['custom_background'] ); 1645 break; 1646 } 1647 1648 unset( $_wp_theme_features[ $feature ] ); 1649 return true; 1650 } 1651 1652 /** 1653 * Checks a theme's support for a given feature 1654 * 1655 * @since 2.9.0 1656 * @param string $feature the feature being checked 1657 * @return boolean 1658 */ 1659 function current_theme_supports( $feature ) { 1660 global $_wp_theme_features; 1661 1662 if ( 'custom-header-uploads' == $feature ) 1663 return current_theme_supports( 'custom-header', 'uploads' ); 1664 1665 if ( !isset( $_wp_theme_features[$feature] ) ) 1666 return false; 1667 1668 // If no args passed then no extra checks need be performed 1669 if ( func_num_args() <= 1 ) 1670 return true; 1671 1672 $args = array_slice( func_get_args(), 1 ); 1673 1674 switch ( $feature ) { 1675 case 'post-thumbnails': 1676 // post-thumbnails can be registered for only certain content/post types by passing 1677 // an array of types to add_theme_support(). If no array was passed, then 1678 // any type is accepted 1679 if ( true === $_wp_theme_features[$feature] ) // Registered for all types 1680 return true; 1681 $content_type = $args[0]; 1682 return in_array( $content_type, $_wp_theme_features[$feature][0] ); 1683 break; 1684 1685 case 'html5': 1686 case 'post-formats': 1687 // specific post formats can be registered by passing an array of types to 1688 // add_theme_support() 1689 1690 // Specific areas of HTML5 support *must* be passed via an array to add_theme_support() 1691 1692 $type = $args[0]; 1693 return in_array( $type, $_wp_theme_features[$feature][0] ); 1694 break; 1695 1696 case 'custom-header': 1697 case 'custom-background' : 1698 // specific custom header and background capabilities can be registered by passing 1699 // an array to add_theme_support() 1700 $header_support = $args[0]; 1701 return ( isset( $_wp_theme_features[$feature][0][$header_support] ) && $_wp_theme_features[$feature][0][$header_support] ); 1702 break; 1703 } 1704 1705 /** 1706 * Filter whether the current theme supports a specific feature. 1707 * 1708 * The dynamic portion of the hook name, $feature, refers to 1709 * the specific theme feature. Possible values include 'post-formats', 1710 * 'post-thumbnails', 'custom-background', 'custom-header', 'menus', 1711 * 'automatic-feed-links', and 'html5'. 1712 * 1713 * @since 3.4.0 1714 * 1715 * @param bool true Whether the current theme supports the given feature. Default true. 1716 * @param array $args Array of arguments for the feature. 1717 * @param string $feature The theme feature. 1718 */ 1719 return apply_filters( "current_theme_supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); 1720 } 1721 1722 /** 1723 * Checks a theme's support for a given feature before loading the functions which implement it. 1724 * 1725 * @since 2.9.0 1726 * @param string $feature the feature being checked 1727 * @param string $include the file containing the functions that implement the feature 1728 */ 1729 function require_if_theme_supports( $feature, $include) { 1730 if ( current_theme_supports( $feature ) ) 1731 require ( $include ); 1732 } 1733 1734 /** 1735 * Checks an attachment being deleted to see if it's a header or background image. 1736 * 1737 * If true it removes the theme modification which would be pointing at the deleted 1738 * attachment 1739 * 1740 * @access private 1741 * @since 3.0.0 1742 * @param int $id the attachment id 1743 */ 1744 function _delete_attachment_theme_mod( $id ) { 1745 $attachment_image = wp_get_attachment_url( $id ); 1746 $header_image = get_header_image(); 1747 $background_image = get_background_image(); 1748 1749 if ( $header_image && $header_image == $attachment_image ) 1750 remove_theme_mod( 'header_image' ); 1751 1752 if ( $background_image && $background_image == $attachment_image ) 1753 remove_theme_mod( 'background_image' ); 1754 } 1755 1756 add_action( 'delete_attachment', '_delete_attachment_theme_mod' ); 1757 1758 /** 1759 * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load 1760 * 1761 * @since 3.3.0 1762 */ 1763 function check_theme_switched() { 1764 if ( $stylesheet = get_option( 'theme_switched' ) ) { 1765 $old_theme = wp_get_theme( $stylesheet ); 1766 1767 if ( $old_theme->exists() ) { 1768 /** 1769 * Fires on the first WP load after a theme switch if the old theme still exists. 1770 * 1771 * This action fires multiple times and the parameters differs 1772 * according to the context, if the old theme exists or not. 1773 * If the old theme is missing, the parameter will be the slug 1774 * of the old theme. 1775 * 1776 * @since 3.3.0 1777 * 1778 * @param string $old_name Old theme name. 1779 * @param WP_Theme $old_theme WP_Theme instance of the old theme. 1780 */ 1781 do_action( 'after_switch_theme', $old_theme->get( 'Name' ), $old_theme ); 1782 } else { 1783 /** This action is documented in wp-includes/theme.php */ 1784 do_action( 'after_switch_theme', $stylesheet ); 1785 } 1786 1787 update_option( 'theme_switched', false ); 1788 } 1789 } 1790 1791 /** 1792 * Includes and instantiates the WP_Customize_Manager class. 1793 * 1794 * Fires when ?wp_customize=on or on wp-admin/customize.php. 1795 * 1796 * @since 3.4.0 1797 */ 1798 function _wp_customize_include() { 1799 if ( ! ( ( isset( $_REQUEST['wp_customize'] ) && 'on' == $_REQUEST['wp_customize'] ) 1800 || ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) ) 1801 ) ) 1802 return; 1803 1804 require ( ABSPATH . WPINC . '/class-wp-customize-manager.php' ); 1805 // Init Customize class 1806 $GLOBALS['wp_customize'] = new WP_Customize_Manager; 1807 } 1808 add_action( 'plugins_loaded', '_wp_customize_include' ); 1809 1810 /** 1811 * Adds settings for the customize-loader script. 1812 * 1813 * @since 3.4.0 1814 */ 1815 function _wp_customize_loader_settings() { 1816 global $wp_scripts; 1817 1818 $admin_origin = parse_url( admin_url() ); 1819 $home_origin = parse_url( home_url() ); 1820 $cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) ); 1821 1822 $browser = array( 1823 'mobile' => wp_is_mobile(), 1824 'ios' => wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] ), 1825 ); 1826 1827 $settings = array( 1828 'url' => esc_url( admin_url( 'customize.php' ) ), 1829 'isCrossDomain' => $cross_domain, 1830 'browser' => $browser, 1831 ); 1832 1833 $script = 'var _wpCustomizeLoaderSettings = ' . json_encode( $settings ) . ';'; 1834 1835 $data = $wp_scripts->get_data( 'customize-loader', 'data' ); 1836 if ( $data ) 1837 $script = "$data\n$script"; 1838 1839 $wp_scripts->add_data( 'customize-loader', 'data', $script ); 1840 } 1841 add_action( 'admin_enqueue_scripts', '_wp_customize_loader_settings' ); 1842 1843 /** 1844 * Returns a URL to load the theme customizer. 1845 * 1846 * @since 3.4.0 1847 * 1848 * @param string $stylesheet Optional. Theme to customize. Defaults to current theme. 1849 * The theme's stylesheet will be urlencoded if necessary. 1850 */ 1851 function wp_customize_url( $stylesheet = null ) { 1852 $url = admin_url( 'customize.php' ); 1853 if ( $stylesheet ) 1854 $url .= '?theme=' . urlencode( $stylesheet ); 1855 return esc_url( $url ); 1856 } 1857 1858 /** 1859 * Prints a script to check whether or not the customizer is supported, 1860 * and apply either the no-customize-support or customize-support class 1861 * to the body. 1862 * 1863 * This function MUST be called inside the body tag. 1864 * 1865 * Ideally, call this function immediately after the body tag is opened. 1866 * This prevents a flash of unstyled content. 1867 * 1868 * It is also recommended that you add the "no-customize-support" class 1869 * to the body tag by default. 1870 * 1871 * @since 3.4.0 1872 */ 1873 function wp_customize_support_script() { 1874 $admin_origin = parse_url( admin_url() ); 1875 $home_origin = parse_url( home_url() ); 1876 $cross_domain = ( strtolower( $admin_origin[ 'host' ] ) != strtolower( $home_origin[ 'host' ] ) ); 1877 1878 ?> 1879 <script type="text/javascript"> 1880 (function() { 1881 var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)'); 1882 1883 <?php if ( $cross_domain ): ?> 1884 request = (function(){ var xhr = new XMLHttpRequest(); return ('withCredentials' in xhr); })(); 1885 <?php else: ?> 1886 request = true; 1887 <?php endif; ?> 1888 1889 b[c] = b[c].replace( rcs, ' ' ); 1890 b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs; 1891 }()); 1892 </script> 1893 <?php 1894 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |