[ Index ]

PHP Cross Reference of WordPress 3.0 beta 1

[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/wp-includes/ -> theme.php (source)

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


Generated: Mon Apr 5 14:26:09 2010 Cross-referenced by PHPXref 0.7