Ticket #20103: wp_theme.diff
| File wp_theme.diff, 98.7 KB (added by nacin, 15 months ago) |
|---|
-
wp-includes/class-wp-customize.php
81 81 82 82 add_filter( 'template', array( $this, 'get_template' ) ); 83 83 add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) ); 84 add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) );85 84 86 85 // @link: http://core.trac.wordpress.org/ticket/20027 87 86 add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) ); … … 235 234 } 236 235 237 236 /** 238 * Filter the current theme and return the name of the previewed theme.239 *240 * @since 3.4.0241 *242 * @return string Theme name.243 */244 public function current_theme( $current_theme ) {245 $themes = get_themes();246 247 if ( ! $themes )248 return $current_theme;249 250 foreach ( $themes as $theme ) {251 if ( $theme['Stylesheet'] == $this->stylesheet && $theme['Template'] == $this->template )252 return $theme['Name'];253 }254 255 return $current_theme;256 }257 258 /**259 237 * Trigger save action and load customize controls. 260 238 * 261 239 * @since 3.4.0 -
wp-includes/update.php
235 235 if ( defined( 'WP_INSTALLING' ) ) 236 236 return false; 237 237 238 if ( !function_exists( 'get_themes' ) ) 239 require_once( ABSPATH . 'wp-includes/theme.php' ); 240 241 $installed_themes = get_themes( ); 238 $installed_themes = wp_get_themes(); 242 239 $last_update = get_site_transient( 'update_themes' ); 243 240 if ( ! is_object($last_update) ) 244 241 $last_update = new stdClass; 245 242 246 243 $themes = array(); 247 244 $checked = array(); 248 $exclude_fields = array('Template Files', 'Stylesheet Files', 'Status', 'Theme Root', 'Theme Root URI', 'Template Dir', 'Stylesheet Dir', 'Description', 'Tags', 'Screenshot');249 245 250 246 // Put slug of current theme into request. 251 247 $themes['current_theme'] = get_option( 'stylesheet' ); 252 248 253 foreach ( (array) $installed_themes as $theme_title => $theme ) { 254 $themes[$theme['Stylesheet']] = array(); 255 $checked[$theme['Stylesheet']] = $theme['Version']; 249 foreach ( $installed_themes as $theme ) { 250 $checked[ $theme->get_stylesheet() ] = $theme->get('Version'); 256 251 257 $themes[$theme['Stylesheet']]['Name'] = $theme['Name']; 258 $themes[$theme['Stylesheet']]['Version'] = $theme['Version']; 259 260 foreach ( (array) $theme as $key => $value ) { 261 if ( !in_array($key, $exclude_fields) ) 262 $themes[$theme['Stylesheet']][$key] = $value; 263 } 252 $themes[ $theme->get_stylesheet() ] = array( 253 'Name' => $theme->get('Name'), 254 'Title' => $theme->get('Name'), 255 'Version' => $theme->get('Version'), 256 'Author' => $theme->get('Author'), 257 'Author URI' => $theme->get('AuthorURI'), 258 'Template' => $theme->get_template(), 259 'Stylesheet' => $theme->get_stylesheet(), 260 ); 264 261 } 265 262 266 263 // Check for update on a different schedule, depending on the page. -
wp-includes/class-wp-theme.php
1 <?php 2 /** 3 * WP_Theme Class 4 * 5 * @package WordPress 6 * @subpackage Theme 7 */ 8 9 final class WP_Theme implements ArrayAccess { 10 11 /** 12 * Headers for style.css files. 13 * 14 * @static 15 * @access private 16 * @var array 17 */ 18 private static $file_headers = array( 19 'Name' => 'Theme Name', 20 'ThemeURI' => 'Theme URI', 21 'Description' => 'Description', 22 'Author' => 'Author', 23 'AuthorURI' => 'Author URI', 24 'Version' => 'Version', 25 'Template' => 'Template', 26 'Status' => 'Status', 27 'Tags' => 'Tags', 28 'TextDomain' => 'Text Domain', 29 'DomainPath' => 'Domain Path', 30 ); 31 32 /** 33 * Absolute path to the theme root, usually wp-content/themes 34 * 35 * @access private 36 * @var string 37 */ 38 private $theme_root; 39 40 /** 41 * Header data from the theme's style.css file. 42 * 43 * @access private 44 * @var array 45 */ 46 private $headers = array(); 47 48 /** 49 * Header data from the theme's style.css file after being sanitized. 50 * 51 * @access private 52 * @var array 53 */ 54 private $headers_sanitized; 55 56 /** 57 * Header name from the theme's style.css after being translated. 58 * 59 * Cached due to sorting functions running over the translated name. 60 */ 61 private $name_translated; 62 63 /** 64 * Errors encountered when initializing the theme. 65 * 66 * @access private 67 * @var WP_Error 68 */ 69 private $errors; 70 71 /** 72 * The directory name of the theme's files, inside the theme root. 73 * 74 * In the case of a child theme, this is directory name of the the child theme. 75 * Otherwise, 'stylesheet' is the same as 'template'. 76 * 77 * @access private 78 * @var string 79 */ 80 private $stylesheet; 81 82 /** 83 * The directory name of the theme's files, inside the theme root. 84 * 85 * In the case of a child theme, this is the directory name of the parent theme. 86 * Otherwise, 'template' is the same as 'stylesheet'. 87 * 88 * @access private 89 * @var string 90 */ 91 private $template; 92 93 /** 94 * A reference to the parent theme, in the case of a child theme. 95 * 96 * @access private 97 * @var WP_Theme 98 */ 99 private $parent; 100 101 /** 102 * Flag for whether the theme's textdomain is loaded. 103 * 104 * @access private 105 * @var bool 106 */ 107 private $textdomain_loaded; 108 109 /** 110 * Flag for whether the themes cache bucket should be persistently cached. 111 * 112 * Default is false. Can be set with the wp_cache_themes_persistent filter. 113 * 114 * @access private 115 * @var bool 116 */ 117 private static $persistently_cache; 118 119 /** 120 * Expiration time for the themes cache bucket. 121 * 122 * By default the bucket is not cached, so this value is useless. 123 * 124 * @access private 125 * @var bool 126 */ 127 private static $cache_expiration = 7200; 128 129 /** 130 * Constructor for WP_Theme. 131 * 132 * @param string $theme_dir Directory of the theme within the theme_root. 133 * @param string $theme_root Theme root. 134 * @param WP_Error|null $child If this theme is a parent theme, the child may be passed for validation purposes. 135 */ 136 public function __construct( $theme_dir, $theme_root, $child = null ) { 137 // Initialize caching on first run. 138 if ( ! isset( self::$persistently_cache ) ) { 139 self::$persistently_cache = apply_filters( 'wp_cache_themes_persistently', false ); 140 if ( is_int( self::$persistently_cache ) ) 141 self::$cache_expiration = self::$persistently_cache; 142 elseif ( ! self::$persistently_cache ) 143 wp_cache_add_non_persistent_groups( 'themes' ); 144 } 145 146 $this->theme_root = $theme_root; 147 $this->stylesheet = $theme_dir; 148 $theme_file = $this->stylesheet . '/style.css'; 149 150 $cache = $this->cache_get( 'theme' ); 151 152 if ( is_array( $cache ) ) { 153 foreach ( array( 'errors', 'headers', 'template', 'stylesheet' ) as $key ) { 154 if ( isset( $cache[ $key ] ) ) 155 $this->$key = $cache[ $key ]; 156 } 157 if ( $this->errors ) 158 return; 159 } elseif ( ! file_exists( $this->theme_root . '/' . $theme_file ) ) { 160 $this->headers['Name'] = $this->stylesheet; 161 $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) ); 162 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) ); 163 if ( ! file_exists( $this->theme_root ) ) // Don't cache this one. 164 $this->errors->add( 'theme_root_missing', __( 'ERROR: The themes directory is either empty or doesn’t exist. Please check your installation.' ) ); 165 return; 166 } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) { 167 $this->headers['Name'] = $this->stylesheet; 168 $this->errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) ); 169 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) ); 170 return; 171 } else { 172 $this->headers = get_file_data( $this->theme_root . '/' . $theme_file, self::$file_headers, 'theme' ); 173 } 174 175 if ( ! $this->template = $this->get('Template') ) { 176 if ( file_exists( $this->theme_root . '/' . $this->stylesheet . '/index.php' ) ) { 177 $this->template = $this->stylesheet; 178 } else { 179 $this->errors = new WP_Error( 'theme_no_index', __( 'Template is missing.' ) ); 180 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet ) ); 181 return; 182 } 183 } 184 185 if ( $this->template != $this->stylesheet && ! file_exists( $this->theme_root . '/' . $this->template . '/index.php' ) ) { 186 // If we're in a directory of themes inside /themes, look for the parent nearby. 187 // wp-content/themes/directory-of-themes/* 188 $parent_dir = dirname( $this->stylesheet ); 189 if ( '.' != $parent_dir && file_exists( $this->theme_root . '/' . $parent_dir . '/' . $this->template . '/index.php' ) ) { 190 $this->template = $parent_dir . '/' . $this->template; 191 } elseif ( ( $directories = search_theme_directories() ) && isset( $directories[ $this->template ] ) ) { 192 // Look for the template in the search_theme_directories() results, in case it is in another theme root. 193 // We don't look into directories of themes, just the theme root. 194 $theme_root_template = $directories[ $this->template ]['theme_root']; 195 } else { 196 // Parent theme is missing. 197 $this->errors = new WP_Error( 'theme_no_parent', sprintf( __( 'The parent theme is missing. Please install the "%s" parent theme.' ), $this->template ) ); 198 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); 199 return; 200 } 201 } 202 203 // @TODO Check for theme name collision. But guess what? We don't care anymore! We only care about clashing matches found in search_theme_directories(). 204 205 // Set the parent, if we're a child theme. 206 if ( $this->template != $this->stylesheet ) { 207 // If we are a parent, then there is a problem. Only two generations allowed! Cancel things out. 208 if ( is_a( $child, 'WP_Theme' ) && $child->template == $this->stylesheet ) { 209 $child->parent = null; 210 $child->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $child->template ) ); 211 $child->cache_add( 'theme', array( 'headers' => $child->headers, 'errors' => $child->errors, 'stylesheet' => $child->stylesheet, 'template' => $child->template ) ); 212 // The two themes actually reference each other with the Template header. 213 if ( $child->stylesheet == $this->template ) { 214 $this->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $this->template ) ); 215 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); 216 } 217 return; 218 } 219 // Set the parent. Pass the current instance so we can do the crazy checks above and assess errors. 220 $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this ); 221 } 222 223 // We're good. If we didn't retrieve from cache, set it. 224 if ( ! is_array( $cache ) ) 225 $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); 226 } 227 228 /** 229 * __isset() magic method for properties formerly returned by current_theme_info() 230 */ 231 public function __isset( $offset ) { 232 static $properties = array( 233 'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet', 234 'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri', 235 ); 236 237 return in_array( $offset, $properties ); 238 } 239 240 /** 241 * __get() magic method for properties formerly returned by current_theme_info() 242 */ 243 public function __get( $offset ) { 244 switch ( $offset ) { 245 case 'name' : 246 case 'title' : 247 return $this->get('Name'); 248 case 'version' : 249 return $this->get('Version'); 250 case 'parent_theme' : 251 return $this->parent ? $this->parent->get('Name') : ''; 252 case 'template_dir' : 253 return $this->get_template_directory(); 254 case 'stylesheet_dir' : 255 return $this->get_stylesheet_directory(); 256 case 'template' : 257 return $this->get_template(); 258 case 'stylesheet' : 259 return $this->get_stylesheet(); 260 case 'screenshot' : 261 return $this->get_screenshot(); 262 // 'author' and 'description' did not previously return translated data. 263 case 'description' : 264 return $this->display('Description'); 265 case 'author' : 266 return $this->display('Author'); 267 case 'tags' : 268 return $this->get( 'Tags' ); 269 case 'theme_root' : 270 return $this->get_theme_root(); 271 case 'theme_root_uri' : 272 return $this->get_theme_root_uri(); 273 } 274 } 275 276 /** 277 * Method to implement ArrayAccess for keys formerly returned by get_themes() 278 */ 279 public function offsetSet( $offset, $value ) {} 280 281 /** 282 * Method to implement ArrayAccess for keys formerly returned by get_themes() 283 */ 284 public function offsetUnset( $offset ) {} 285 286 /** 287 * Method to implement ArrayAccess for keys formerly returned by get_themes() 288 */ 289 public function offsetExists( $offset ) { 290 static $keys = array( 291 'Name', 'Version', 'Status', 'Title', 'Author', 'Author Name', 'Author URI', 'Description', 292 'Template', 'Stylesheet', 'Template Files', 'Stylesheet Files', 'Template Dir', 'Stylesheet Dir', 293 'Screenshot', 'Tags', 'Theme Root', 'Theme Root URI', 'Parent Theme', 294 ); 295 296 return in_array( $offset, $keys ); 297 } 298 299 /** 300 * Method to implement ArrayAccess for keys formerly returned by get_themes() 301 */ 302 public function offsetGet( $offset ) { 303 switch ( $offset ) { 304 case 'Name' : 305 case 'Version' : 306 case 'Status' : 307 return $this->get( $offset ); 308 case 'Title' : 309 return $this->get('Name'); 310 // Author, Author Name, Author URI, and Description did not 311 // previously return translated data. We are doing so now. 312 // Title and Name could have been used as the key for get_themes(), 313 // so both to remain untranslated for back compatibility. 314 case 'Author' : 315 return $this->display( 'Author'); 316 case 'Author Name' : 317 return $this->display( 'Author', false); 318 case 'Author URI' : 319 return $this->display('AuthorURI'); 320 case 'Description' : 321 return $this->display( 'Description'); 322 case 'Template' : 323 return $this->get_template(); 324 case 'Stylesheet' : 325 return $this->get_stylesheet(); 326 case 'Template Files' : 327 $files = $this->get_files('php'); 328 foreach ( $files as &$file ) 329 $file = $this->theme_root . '/' . $file; 330 return $files; 331 case 'Stylesheet Files' : 332 $files = $this->get_files('css'); 333 foreach ( $files as &$file ) 334 $file = $this->theme_root . '/' . $file; 335 return $files; 336 case 'Template Dir' : 337 return $this->get_template_directory(); 338 case 'Stylesheet Dir' : 339 return $this->get_stylesheet_directory(); 340 case 'Screenshot' : 341 return $this->get_screenshot(); 342 case 'Tags' : 343 return $this->get('Tags'); 344 case 'Theme Root' : 345 return $this->get_theme_root(); 346 case 'Theme Root URI' : 347 return $this->get_theme_root_uri(); 348 case 'Parent Theme' : 349 return $this->parent ? $this->parent->get('Name') : ''; 350 default : 351 return null; 352 } 353 } 354 355 /** 356 * Returns errors property. 357 * 358 * @since 3.4.0 359 * @access public 360 * 361 * @return WP_Error|bool WP_Error if there are errors, or false. 362 */ 363 public function errors() { 364 return is_wp_error( $this->errors ) ? $this->errors : false; 365 } 366 367 /** 368 * Returns reference to the parent theme. 369 * 370 * @since 3.4.0 371 * @access public 372 * 373 * @return WP_Theme|bool Parent theme, or false if the current theme is not a child theme. 374 */ 375 public function parent() { 376 return isset( $this->parent ) ? $this->parent : false; 377 } 378 379 /** 380 * Adds theme data to cache. 381 * 382 * Cache entries keyed by the theme and the type of data. 383 * 384 * @access private 385 * @since 3.4.0 386 * 387 * @param string $key Type of data to store (theme, screenshot, screenshot_count, files, headers) 388 * @param string $data Data to store 389 * @return bool Return value from wp_cache_add() 390 */ 391 private function cache_add( $key, $data ) { 392 return wp_cache_add( $key . '-' . $this->theme_root . '/' . $this->stylesheet, $data, 'themes', self::$cache_expiration ); 393 } 394 395 /** 396 * Gets theme data from cache. 397 * 398 * Cache entries are keyed by the theme and the type of data. 399 * 400 * @access private 401 * @since 3.4.0 402 * 403 * @param string $key Type of data to retrieve (theme, screenshot, screenshot_count, files, headers) 404 * @return mixed Retrieved data 405 */ 406 private function cache_get( $key ) { 407 return wp_cache_get( $key . '-' . $this->theme_root . '/' . $this->stylesheet, 'themes' ); 408 } 409 410 /** 411 * Clears the cache for the theme. 412 * 413 * @access public 414 * @since 3.4.0 415 */ 416 public function clear_cache() { 417 wp_cache_delete( 'theme-' . $this->cache_key, 'themes' ); 418 wp_cache_delete( 'screenshot-' . $this->cache_key, 'themes' ); 419 wp_cache_delete( 'screenshot_count-' . $this->cache_key, 'themes' ); 420 wp_cache_delete( 'files-' . $this->cache_key, 'themes' ); 421 wp_cache_delete( 'headers-' . $this->cache_key, 'themes' ); 422 } 423 424 /** 425 * Gets a theme header. 426 * 427 * The header is sanitized. 428 * 429 * @access public 430 * @since 3.4.0 431 * 432 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status. 433 * @return string String on success, false on failure. 434 */ 435 public function get( $header ) { 436 if ( ! isset( $this->headers[ $header ] ) ) 437 return false; 438 439 if ( ! isset( $this->headers_sanitized ) ) { 440 $this->headers_sanitized = $this->cache_get( 'headers' ); 441 if ( ! is_array( $this->headers_sanitized ) ) 442 $headers = array(); 443 } 444 445 if ( isset( $this->headers_sanitized[ $header ] ) ) 446 return $this->headers_sanitized[ $header ]; 447 448 // If an external object cache does not consider themes to be a persistent group, sanitize everything and cache it. 449 if ( self::$persistently_cache ) { 450 foreach ( array_keys( $this->headers ) as $header ) 451 $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] ); 452 $this->cache_add( 'headers', $this->headers_sanitized ); 453 } else { 454 $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] ); 455 } 456 457 return $this->headers_sanitized[ $header ]; 458 } 459 460 /** 461 * Gets a theme header ready for display (marked up, translated). 462 * 463 * @access public 464 * @since 3.4.0 465 * 466 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status. 467 * @param bool $markup Optional. Whether to mark up the header. Defaults to true. 468 * @param bool $translate Optional. Whether to translate the header. Defaults to true. 469 * @return string Processed header, false on failure. 470 */ 471 public function display( $header, $markup = true, $translate = true ) { 472 $value = $this->get( $header ); 473 if ( false === $value || '' === $value ) 474 return $value; 475 476 if ( ! $this->load_textdomain() ) 477 $translate = false; 478 479 if ( $translate ) 480 $value = $this->translate_header( $header, $value ); 481 482 if ( $markup ) 483 $value = $this->markup_header( $header, $value, $translate ); 484 485 return $value; 486 } 487 488 /** 489 * Sanitize a theme header. 490 * 491 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status. 492 * @param string $value Value to sanitize. 493 */ 494 private function sanitize_header( $header, $value ) { 495 switch ( $header ) { 496 case 'Status' : 497 if ( ! $value ) { 498 $value = 'public'; 499 break; 500 } 501 // Fall through otherwise. 502 case 'Name' : 503 case 'Author' : 504 static $header_tags = array( 505 'abbr' => array( 'title' => true ), 506 'acronym' => array( 'title' => true ), 507 'code' => true, 508 'em' => true, 509 'strong' => true, 510 ); 511 $value = wp_kses( $value, $header_tags ); 512 break; 513 case 'Description' : 514 static $header_tags_with_a = array( 515 'a' => array( 'href' => true, 'title' => true ), 516 'abbr' => array( 'title' => true ), 517 'acronym' => array( 'title' => true ), 518 'code' => true, 519 'em' => true, 520 'strong' => true, 521 ); 522 $value = wp_kses( $value, $header_tags_with_a ); 523 break; 524 case 'ThemeURI' : 525 case 'AuthorURI' : 526 $value = esc_url( $value ); 527 break; 528 case 'Tags' : 529 $value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) ); 530 break; 531 } 532 533 return $value; 534 } 535 536 /** 537 * Mark up a theme header. 538 * 539 * @access private 540 * @since 3.4.0 541 * 542 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status. 543 * @param string $value Value to mark up. 544 * @param string $translate Whether the header has been translated. 545 * @return string Value, marked up. 546 */ 547 private function markup_header( $header, $value, $translate ) { 548 switch ( $header ) { 549 case 'Description' : 550 $value = wptexturize( $value ); 551 break; 552 case 'Author' : 553 if ( $this->get('AuthorURI') ) { 554 static $attr = null; 555 if ( ! isset( $attr ) ) 556 $attr = esc_attr__( 'Visit author homepage' ); 557 $value = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $this->display( 'AuthorURI', true, $translate ), $attr, $value ); 558 } elseif ( ! $value ) { 559 $value = __( 'Anonymous' ); 560 } 561 break; 562 case 'Tags' : 563 static $comma = null; 564 if ( ! isset( $comma ) ) { 565 /* translators: used between list items, there is a space after the comma */ 566 $comma = __( ', ' ); 567 } 568 $value = implode( $comma, $value ); 569 break; 570 } 571 572 return $value; 573 } 574 575 /** 576 * Translate a theme header. 577 * 578 * @access private 579 * @since 3.4.0 580 * 581 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status. 582 * @param string $value Value to translate. 583 * @return string Translated value. 584 */ 585 private function translate_header( $header, $value ) { 586 switch ( $header ) { 587 case 'Name' : 588 // Cached for sorting reasons. 589 if ( isset( $this->name_translated ) ) 590 return $this->name_translated; 591 $this->name_translated = translate( $value, $this->get('TextDomain' ) ); 592 return $this->name_translated; 593 case 'Tags' : 594 if ( empty( $value ) ) 595 return $value; 596 597 static $tags_list; 598 if ( ! isset( $tags_list ) ) { 599 $tags_list = array(); 600 $feature_list = get_theme_feature_list( false ); // No API 601 foreach ( $feature_list as $tags ) 602 $tags_list += $tags; 603 } 604 605 foreach ( $value as &$tag ) { 606 if ( isset( $tags_list[ $tag ] ) ) 607 $tag = $tags_list[ $tag ]; 608 } 609 610 return $value; 611 break; 612 default : 613 $value = translate( $value, $this->get('TextDomain') ); 614 } 615 return $value; 616 } 617 618 /** 619 * The directory name of the theme's "stylesheet" files, inside the theme root. 620 * 621 * In the case of a child theme, this is directory name of the the child theme. 622 * Otherwise, get_stylesheet() is the same as get_template(). 623 * 624 * @since 3.4.0 625 * @access public 626 * 627 * @return string Stylesheet 628 */ 629 public function get_stylesheet() { 630 return $this->stylesheet; 631 } 632 633 /** 634 * The directory name of the theme's "template" files, inside the theme root. 635 * 636 * In the case of a child theme, this is the directory name of the parent theme. 637 * Otherwise, the get_template() is the same as get_stylesheet(). 638 * 639 * @since 3.4.0 640 * @access public 641 * 642 * @return string Template 643 */ 644 public function get_template() { 645 return $this->template; 646 } 647 648 /** 649 * Whether a theme is a child theme. 650 * 651 * @since 3.4.0 652 * @access public 653 * 654 * @return bool True if a theme is a child theme, false otherwise. 655 */ 656 public function is_child_theme() { 657 return $this->template !== $this->stylesheet; 658 } 659 660 /** 661 * Returns the absolute path to the directory of a theme's "stylesheet" files. 662 * 663 * In the case of a child theme, this is the absolute path to the directory 664 * of the child theme's files. 665 * 666 * @since 3.4.0 667 * @access public 668 * 669 * @return string Absolute path of the stylesheet directory. 670 */ 671 public function get_stylesheet_directory() { 672 if ( $this->errors && in_array( 'theme_root_missing', $this->errors->get_error_codes() ) ) 673 return ''; 674 675 return $this->theme_root . '/' . $this->stylesheet; 676 } 677 678 /** 679 * Returns the absolute path to the directory of a theme's "template" files. 680 * 681 * In the case of a child theme, this is the absolute path to the directory 682 * of the parent theme's files. 683 * 684 * @since 3.4.0 685 * @access public 686 * 687 * @return string Absolute path of the template directory. 688 */ 689 public function get_template_directory() { 690 if ( $this->parent ) 691 $theme_root = $this->parent->theme_root; 692 else 693 $theme_root = $this->theme_root; 694 695 return $theme_root . '/' . $this->template; 696 } 697 698 /** 699 * Returns the URL to the directory of a theme's "stylesheet" files. 700 * 701 * In the case of a child theme, this is the URL to the directory of the 702 * child theme's files. 703 * 704 * @since 3.4.0 705 * @access public 706 * 707 * @return string URL to the stylesheet directory. 708 */ 709 public function get_stylesheet_directory_uri() { 710 return $this->theme_root_uri . '/' . $this->stylesheet; 711 } 712 713 /** 714 * Returns the URL to the directory of a theme's "template" files. 715 * 716 * In the case of a child theme, this is the URL to the directory of the 717 * parent theme's files. 718 * 719 * @since 3.4.0 720 * @access public 721 * 722 * @return string URL to the template directory. 723 */ 724 public function get_template_directory_uri() { 725 if ( $this->parent ) 726 $theme_root_uri = $this->parent->theme_root_uri; 727 else 728 $theme_root_uri = $this->theme_root; 729 730 return $theme_root . '/' . $this->template; 731 } 732 733 /** 734 * The absolute path to the directory of the theme root. 735 * 736 * This is typically the absolute path to wp-content/themes. 737 * 738 * @since 3.4.0 739 * @access public 740 * 741 * @return string Theme root. 742 */ 743 public function get_theme_root() { 744 return $this->theme_root; 745 } 746 747 /** 748 * Returns the URL to the directory of the theme root. 749 * 750 * This is typically the absolute path to wp-content/themes. 751 * 752 * @since 3.4.0 753 * @access public 754 * 755 * @return string Theme root URI. 756 */ 757 public function get_theme_root_uri() { 758 return str_replace( WP_CONTENT_DIR, content_url(), $this->theme_root ); 759 } 760 761 /** 762 * Returns the main screenshot file for the theme. 763 * 764 * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed. 765 * 766 * Screenshots for a theme must be in the stylesheet directory. (In the case of a child 767 * theme, a parent theme's screenshots are inherited.) 768 * 769 * @since 3.4.0 770 * @access public 771 * 772 * @param string $uri Type of URL to include, either relative or absolute. Defaults to relative. 773 * @return mixed Screenshot file. False if the theme does not have a screenshot. 774 */ 775 public function get_screenshot( $uri = 'relative' ) { 776 $screenshot = $this->cache_get( 'screenshot' ); 777 if ( $screenshot ) { 778 if ( 'absolute' == $uri ) 779 return $this->get_stylesheet_directory_uri() . '/' . $screenshot; 780 return $screenshot; 781 } elseif ( 0 === $screenshot ) { 782 return false; 783 } 784 785 foreach ( array( 'png', 'gif', 'jpg', 'jpeg' ) as $ext ) { 786 if ( file_exists( $this->get_stylesheet_directory() . "/screenshot.$ext" ) ) { 787 $this->cache_add( 'screenshot', 'screenshot.' . $ext ); 788 if ( 'absolute' == $uri ) 789 return $this->get_stylesheet_directory_uri() . '/' . 'screenshot.' . $ext; 790 return 'screenshot.' . $ext; 791 } 792 } 793 794 $this->cache_add( 'screenshot', 0 ); 795 $this->cache_add( 'screenshot_count', 0 ); 796 return false; 797 } 798 799 /** 800 * Returns the number of screenshots for a theme. 801 * 802 * The first screenshot may be called screenshot.png, .gif, or .jpg. Subsequent 803 * screenshots can be screenshot-2.png, screenshot-3.png, etc. The count must 804 * be consecutive for screenshots to be counted, and all screenshots beyond the 805 * initial one must be image/png files. 806 * 807 * @see WP_Theme::get_screenshot() 808 * @since 3.4.0 809 * @access public 810 * 811 * @return int Number of screenshots. Can be 0. 812 */ 813 public function get_screenshot_count() { 814 $screenshot_count = $this->cache_get( 'screenshot_count' ); 815 if ( is_numeric( $screenshot_count ) ) 816 return $screenshot_count; 817 818 // This will set the screenshot cache. 819 // If there is no screenshot, the screenshot_count cache will also be set. 820 if ( ! $screenshot = $this->get_screenshot() ) 821 return 0; 822 823 $prefix = $this->get_stylesheet() . '/screenshot-'; 824 $files = self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), 'png', 0 ); 825 826 $screenshot_count = 1; 827 while ( in_array( $prefix . ( $screenshot_count + 1 ) . '.png', $files['png'] ) ) 828 $screenshot_count++; 829 830 $this->cache_add( 'screenshot_count', $screenshot_count ); 831 return $screenshot_count; 832 } 833 834 /** 835 * Returns an array of screenshot filenames. 836 * 837 * @see WP_Theme::get_screenshot() 838 * @see WP_Theme::get_screenshot_count() 839 * @since 3.4.0 840 * @access public 841 * 842 * @return array Screenshots. 843 */ 844 public function get_screenshots() { 845 if ( ! $count = $this->get_screenshot_count() ) 846 return array(); 847 848 $screenshots = array( $this->get_screenshot() ); 849 for ( $i = 2; $i <= $count; $i++ ) 850 $screenshots[] = 'screenshot-' . $i . '.png'; 851 return $screenshots; 852 } 853 854 /** 855 * Return files in the template and stylesheet directories. 856 * 857 * @since 3.4.0 858 * @access public 859 * 860 * @param string|null $type Optional. Type of files to return, either 'php' or 'css'. Defaults to null, for both. 861 * @return array If a specific $type is requested, returns an array of PHP files. If no $type is requested, 862 * returns an array, with the keys being the file types, and the values being an array of files for those type. 863 */ 864 public function get_files( $type = null, $include_parent_files = false ) { 865 $files = $this->cache_get( 'files' ); 866 if ( ! is_array( $files ) ) { 867 if ( $include_parent_files || ! $this->is_child_theme() ) 868 // Template files can be one level down for the purposes of the theme editor, so this should be $depth = 1. 869 // Todo: We ignore this for now, but this is why the branching is weird. 870 $files = (array) self::scandir( $this->get_template_directory(), $this->get_template(), array( 'php', 'css' ) ); 871 if ( $this->is_child_theme() ) 872 $files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet(), array( 'php', 'css' ) ) ); 873 foreach ( $files as &$group ) 874 sort( $group ); 875 $this->cache_add( 'files', $files ); 876 } 877 878 if ( null === $type ) 879 return $files; 880 elseif ( isset( $files[ $type ] ) ) 881 return $files[ $type ]; 882 883 return array(); 884 } 885 886 public function get_page_templates() { 887 // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide. 888 if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) 889 return array(); 890 891 $page_templates = $this->cache_get( 'page_templates' ); 892 if ( is_array( $page_templates ) ) 893 return $page_templates; 894 $page_templates = array(); 895 896 $files = (array) self::scandir( $this->get_template_directory(), $this->get_template_directory(), 'php' ); 897 if ( $this->is_child_theme() ) 898 $files = array_merge_recursive( $files, (array) self::scandir( $this->get_stylesheet_directory(), $this->get_stylesheet_directory(), 'php' ) ); 899 900 foreach ( $files['php'] as $file ) { 901 $headers = get_file_data( $file, array( 'Name' => 'Template Name' ) ); 902 if ( empty( $headers['Name'] ) ) 903 continue; 904 $page_templates[ $headers['Name'] ] = basename( $file ); 905 } 906 907 $this->cache_add( 'page_templates', $page_templates ); 908 return $page_templates; 909 } 910 911 /** 912 * Scans a directory for files of a certain extension. 913 * 914 * @since 3.4.0 915 * @access public 916 * 917 * @param string $path Absolute path to search. 918 * @param string $relative_path The basename of the absolute path. Used to control the returned path 919 * for the found files, particularly when this function recurses to lower depths. 920 * @param array|string $extensions Array of extensions to find, or string of a single extension. 921 * @depth int How deep to search for files. Optional, defaults to a flat scan (0 depth). 922 */ 923 private static function scandir( $path, $relative_path, $extensions, $depth = 0 ) { 924 if ( is_array( $extensions ) ) 925 $extensions = implode( '|', $extensions ); 926 927 if ( ! is_dir( $path ) ) 928 return false; 929 930 $results = scandir( $path ); 931 $files = array(); 932 933 foreach ( $results as $result ) { 934 if ( '.' == $result || '..' == $result ) 935 continue; 936 if ( is_dir( $path . '/' . $result ) ) { 937 if ( ! $depth ) 938 continue; 939 $found = self::scandir( $path . '/' . $result, $relative_path . '/' . $result, $extensions, $depth - 1 ); 940 $files = array_merge_recursive( $files, $found ); 941 } elseif ( preg_match( '~\.(' . $extensions . ')$~', $result, $match ) ) { 942 if ( ! isset( $files[ $match[1] ] ) ) 943 $files[ $match[1] ] = array( $relative_path . '/'. $result ); 944 else 945 $files[ $match[1] ][] = $relative_path . '/' . $result; 946 } 947 } 948 return $files; 949 } 950 951 /** 952 * Loads the theme's textdomain. 953 * 954 * Translation files are not inherited from the parent theme. Todo: if this fails for the 955 * child theme, it should probably try to load the parent theme's translations. 956 * 957 * @since 3.4.0 958 * @access public 959 * 960 * @return True if the textdomain was successfully loaded or has already been loaded. False if 961 * no textdomain was specified in the file headers, or if the domain could not be loaded. 962 */ 963 public function load_textdomain() { 964 if ( isset( $this->textdomain_loaded ) ) 965 return $this->textdomain_loaded; 966 967 $textdomain = $this->get('TextDomain'); 968 if ( ! $textdomain ) { 969 $this->textdomain_loaded = false; 970 return false; 971 } 972 973 if ( is_textdomain_loaded( $textdomain ) ) { 974 $this->textdomain_loaded = true; 975 return true; 976 } 977 978 $path = $this->get_stylesheet_directory(); 979 if ( $domainpath = $this->get('DomainPath') ) 980 $path .= $domainpath; 981 982 $this->textdomain_loaded = load_theme_textdomain( $textdomain, $path ); 983 return $this->textdomain_loaded; 984 } 985 986 /** 987 * Whether the theme is allowed (multisite only). 988 * 989 * @since 3.4.0 990 * @access public 991 * 992 * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site' 993 * settings, or 'both'. Defaults to 'both'. 994 * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current blog. 995 * @return bool Whether the theme is allowed for the network. Returns true in single-site. 996 */ 997 public function is_allowed( $check = 'both', $blog_id = null ) { 998 if ( ! is_multisite() ) 999 return true; 1000 1001 if ( 'both' == $check || 'network' == $check ) { 1002 $allowed = self::get_allowed_on_network(); 1003 if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) 1004 return true; 1005 } 1006 1007 if ( 'both' == $check || 'site' == $check ) { 1008 $allowed = self::get_allowed_on_site( $blog_id ); 1009 if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) 1010 return true; 1011 } 1012 1013 return false; 1014 } 1015 1016 /** 1017 * Returns array of stylesheet names of themes allowed on the site or network. 1018 * 1019 * @since 3.4.0 1020 * @access public 1021 * 1022 * @param int $blog_id Optional. Defaults to current blog. 1023 * @return array Array of stylesheet names. 1024 */ 1025 public static function get_allowed( $blog_id = null ) { 1026 return array_merge( self::get_allowed_on_network(), self::get_allowed_on_site( $blog_id ) ); 1027 } 1028 1029 /** 1030 * Returns array of stylesheet names of themes allowed on the network. 1031 * 1032 * @since 3.4.0 1033 * @access public 1034 * 1035 * @return array Array of stylesheet names. 1036 */ 1037 public static function get_allowed_on_network() { 1038 static $allowed_themes; 1039 if ( ! isset( $allowed_themes ) ) 1040 $allowed_themes = (array) get_site_option( 'allowedthemes' ); 1041 return $allowed_themes; 1042 } 1043 1044 /** 1045 * Returns array of stylesheet names of themes allowed on the site. 1046 * 1047 * @since 3.4.0 1048 * @access public 1049 * 1050 * @param int $blog_id Optional. Defaults to current blog. 1051 * @return array Array of stylesheet names. 1052 */ 1053 public static function get_allowed_on_site( $blog_id = null ) { 1054 static $allowed_themes = array(); 1055 if ( ! $blog_id ) 1056 $blog_id = get_current_blog_id(); 1057 1058 if ( ! isset( $allowed_themes[ $blog_id ] ) ) { 1059 if ( $blog_id == get_current_blog_id() ) 1060 $allowed_themes[ $blog_id ] = (array) get_option( 'allowedthemes' ); 1061 else 1062 $allowed_themes[ $blog_id ] = (array) get_blog_option( $blog_id, 'allowedthemes' ); 1063 } 1064 1065 return $allowed_themes[ $blog_id ]; 1066 } 1067 1068 /** 1069 * Sort themes by name. 1070 */ 1071 public static function sort_by_name( &$themes ) { 1072 if ( 0 === strpos( get_locale(), 'en_' ) ) { 1073 uasort( $themes, array( 'WP_Theme', '_name_sort' ) ); 1074 } else { 1075 uasort( $themes, array( 'WP_Theme', '_name_sort_i18n' ) ); 1076 } 1077 } 1078 1079 /** 1080 * Callback function for usort() to naturally sort themes by name. 1081 * 1082 * Accesses the Name header directly from the class for maximum speed. 1083 * Would choke on HTML but we don't care enough to slow it down with strip_tags(). 1084 * 1085 * @since 3.4.0 1086 * @access public 1087 */ 1088 private static function _name_sort( $a, $b ) { 1089 return strnatcasecmp( $a->headers['Name'], $b->headers['Name'] ); 1090 } 1091 1092 /** 1093 * Name sort (with translation). 1094 * 1095 * @since 3.4.0 1096 * @access public 1097 */ 1098 private static function _name_sort_i18n( $a, $b ) { 1099 // Don't mark up; Do translate. 1100 return strnatcasecmp( $a->display( 'Name', false, true ), $b->display( 'Name', false, true ) ); 1101 } 1102 } 1103 1104 /** 1105 * Returns an array of WP_Theme objects based on the arguments. 1106 * 1107 * Despite advances over get_themes(), this function is still quite expensive, and grows 1108 * linearly with additional themes. Stick to wp_get_theme() if possible. 1109 * 1110 * @since 3.4.0 1111 * 1112 * @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed' 1113 * (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id' 1114 * (defaults to current blog; used to find allowed themes; only applies to multisite). 1115 * @return Array of WP_Theme objects. 1116 */ 1117 function wp_get_themes( $args = array() ) { 1118 $defaults = array( 'errors' => false, 'allowed' => null, 'blog_id' => 0 ); 1119 $args = wp_parse_args( $args, $defaults ); 1120 1121 static $_themes; 1122 if ( ! isset( $_themes ) ) { 1123 $theme_data = search_theme_directories(); 1124 // Make sure the current theme wins out, in case search_theme_directories() picks the wrong 1125 // one in the case of a conflict. (Normally, last registered theme root wins.) 1126 $current_theme = get_stylesheet(); 1127 $current_theme_root = WP_CONTENT_DIR . get_raw_theme_root( $current_theme ); 1128 foreach ( $theme_data as $theme_slug => $data ) { 1129 if ( $current_theme == $theme_slug && $current_theme_root != $data['theme_root'] ) 1130 $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $current_theme_root ); 1131 else 1132 $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $data['theme_root'] ); 1133 } 1134 } 1135 1136 $themes = $_themes; 1137 1138 if ( null !== $args['errors'] ) { 1139 foreach ( $themes as $theme_slug => $theme ) { 1140 if ( $theme->errors() != $args['errors'] ) 1141 unset( $themes[ $theme_slug ] ); 1142 } 1143 } 1144 1145 if ( is_multisite() && null !== $args['allowed'] ) { 1146 if ( $allowed = $args['allowed'] ) { 1147 $allowed = 'network' == $allowed || 'site' == $allowed ? $allowed : 'both'; 1148 $themes = array_intersect_key( $themes, WP_Theme::get_allowed( $allowed, $args['blog_id'] ) ); 1149 } else { 1150 $themes = array_diff_key( $themes, WP_Theme::get_allowed( 'both', $args['blog_id'] ) ); 1151 } 1152 } 1153 1154 return $themes; 1155 } 1156 1157 /** 1158 * Gets a WP_Theme object for a theme. 1159 * 1160 * @since 3.4.0 1161 * 1162 * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme. 1163 * @param string $theme_root Theme root to look in. Optional. If not specified, get_raw_theme_root() 1164 * is used for the $stylesheet provided (or current theme). 1165 * @return WP_Theme 1166 */ 1167 function wp_get_theme( $stylesheet = null, $theme_root = null ) { 1168 if ( empty( $stylesheet ) ) 1169 $stylesheet = get_stylesheet(); 1170 1171 if ( empty( $theme_root ) ) 1172 $theme_root = WP_CONTENT_DIR . get_raw_theme_root( $stylesheet ); 1173 1174 return new WP_Theme( $stylesheet, $theme_root ); 1175 } 1176 No newline at end of file -
wp-includes/theme.php
247 247 } 248 248 249 249 /** 250 * Retrieve list of themes with theme data in theme directory.251 *252 * The theme is broken, if it doesn't have a parent theme and is missing either253 * style.css and, or index.php. If the theme has a parent theme then it is254 * broken, if it is missing style.css; index.php is optional. The broken theme255 * list is saved in the {@link $wp_broken_themes} global, which is displayed on256 * the theme list in the administration panels.257 *258 * @since 1.5.0259 * @global array $wp_broken_themes Stores the broken themes.260 * @global array $wp_themes Stores the working themes.261 *262 * @return array Theme list with theme data.263 */264 function get_themes() {265 global $wp_themes, $wp_broken_themes;266 267 if ( isset($wp_themes) )268 return $wp_themes;269 270 if ( !$theme_files = search_theme_directories() )271 return false;272 273 asort( $theme_files );274 275 $wp_themes = array();276 277 foreach ( (array) $theme_files as $theme_file ) {278 $theme_root = $theme_file['theme_root'];279 $theme_file = $theme_file['theme_file'];280 281 if ( !is_readable("$theme_root/$theme_file") ) {282 $wp_broken_themes[$theme_file] = array('Name' => $theme_file, 'Title' => $theme_file, 'Description' => __('File not readable.'));283 continue;284 }285 286 $theme_data = get_theme_data("$theme_root/$theme_file");287 288 $name = $theme_data['Name'];289 $title = $theme_data['Title'];290 $description = wptexturize($theme_data['Description']);291 $version = $theme_data['Version'];292 $author = $theme_data['Author'];293 $template = $theme_data['Template'];294 $stylesheet = dirname($theme_file);295 296 $screenshot = false;297 foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) {298 if (file_exists("$theme_root/$stylesheet/screenshot.$ext")) {299 $screenshot = "screenshot.$ext";300 break;301 }302 }303 304 if ( empty($name) ) {305 $name = dirname($theme_file);306 $title = $name;307 }308 309 $parent_template = $template;310 311 if ( empty($template) ) {312 if ( file_exists("$theme_root/$stylesheet/index.php") )313 $template = $stylesheet;314 else315 continue;316 }317 318 $template = trim( $template );319 320 if ( !file_exists("$theme_root/$template/index.php") ) {321 $parent_dir = dirname(dirname($theme_file));322 if ( file_exists("$theme_root/$parent_dir/$template/index.php") ) {323 $template = "$parent_dir/$template";324 $template_directory = "$theme_root/$template";325 } else {326 /**327 * The parent theme doesn't exist in the current theme's folder or sub folder328 * so lets use the theme root for the parent template.329 */330 if ( isset($theme_files[$template]) && file_exists( $theme_files[$template]['theme_root'] . "/$template/index.php" ) ) {331 $template_directory = $theme_files[$template]['theme_root'] . "/$template";332 } else {333 if ( empty( $parent_template) )334 $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => __('Template is missing.'), 'error' => 'no_template');335 else336 $wp_broken_themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => sprintf( __('The parent theme is missing. Please install the "%s" parent theme.'), $parent_template ), 'error' => 'no_parent', 'parent' => $parent_template );337 continue;338 }339 340 }341 } else {342 $template_directory = trim( $theme_root . '/' . $template );343 }344 345 $stylesheet_files = array();346 $template_files = array();347 348 $stylesheet_dir = @ dir("$theme_root/$stylesheet");349 if ( $stylesheet_dir ) {350 while ( ($file = $stylesheet_dir->read()) !== false ) {351 if ( !preg_match('|^\.+$|', $file) ) {352 if ( preg_match('|\.css$|', $file) )353 $stylesheet_files[] = "$theme_root/$stylesheet/$file";354 elseif ( preg_match('|\.php$|', $file) )355 $template_files[] = "$theme_root/$stylesheet/$file";356 }357 }358 @ $stylesheet_dir->close();359 }360 361 $template_dir = @ dir("$template_directory");362 if ( $template_dir ) {363 while ( ($file = $template_dir->read()) !== false ) {364 if ( preg_match('|^\.+$|', $file) )365 continue;366 if ( preg_match('|\.php$|', $file) ) {367 $template_files[] = "$template_directory/$file";368 } elseif ( is_dir("$template_directory/$file") ) {369 $template_subdir = @ dir("$template_directory/$file");370 if ( !$template_subdir )371 continue;372 while ( ($subfile = $template_subdir->read()) !== false ) {373 if ( preg_match('|^\.+$|', $subfile) )374 continue;375 if ( preg_match('|\.php$|', $subfile) )376 $template_files[] = "$template_directory/$file/$subfile";377 }378 @ $template_subdir->close();379 }380 }381 @ $template_dir->close();382 }383 384 //Make unique and remove duplicates when stylesheet and template are the same i.e. most themes385 $template_files = array_unique($template_files);386 $stylesheet_files = array_unique($stylesheet_files);387 388 $template_dir = $template_directory;389 $stylesheet_dir = $theme_root . '/' . $stylesheet;390 391 if ( empty($template_dir) )392 $template_dir = '/';393 if ( empty($stylesheet_dir) )394 $stylesheet_dir = '/';395 396 // Check for theme name collision. This occurs if a theme is copied to397 // a new theme directory and the theme header is not updated. Whichever398 // theme is first keeps the name. Subsequent themes get a suffix applied.399 // Default themes themes always trump their pretenders.400 if ( isset($wp_themes[$name]) ) {401 $trump_cards = array(402 'classic' => 'WordPress Classic',403 'default' => 'WordPress Default',404 'twentyten' => 'Twenty Ten',405 'twentyeleven' => 'Twenty Eleven',406 'twentytwelve' => 'Twenty Twelve',407 );408 if ( isset( $trump_cards[ $stylesheet ] ) && $name == $trump_cards[ $stylesheet ] ) {409 // If another theme has claimed to be one of our default themes, move410 // them aside.411 $suffix = $wp_themes[$name]['Stylesheet'];412 $new_name = "$name/$suffix";413 $wp_themes[$new_name] = $wp_themes[$name];414 $wp_themes[$new_name]['Name'] = $new_name;415 } else {416 $name = "$name/$stylesheet";417 }418 }419 420 $theme_roots[$stylesheet] = str_replace( WP_CONTENT_DIR, '', $theme_root );421 $wp_themes[$name] = array(422 'Name' => $name,423 'Title' => $title,424 'Description' => $description,425 'Author' => $author,426 'Author Name' => $theme_data['AuthorName'],427 'Author URI' => $theme_data['AuthorURI'],428 'Version' => $version,429 'Template' => $template,430 'Stylesheet' => $stylesheet,431 'Template Files' => $template_files,432 'Stylesheet Files' => $stylesheet_files,433 'Template Dir' => $template_dir,434 'Stylesheet Dir' => $stylesheet_dir,435 'Status' => $theme_data['Status'],436 'Screenshot' => $screenshot,437 'Tags' => $theme_data['Tags'],438 'Theme Root' => $theme_root,439 'Theme Root URI' => str_replace( WP_CONTENT_DIR, content_url(), $theme_root ),440 );441 }442 443 unset($theme_files);444 445 /* Store theme roots in the DB */446 if ( get_site_transient( 'theme_roots' ) != $theme_roots )447 set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours448 unset($theme_roots);449 450 /* Resolve theme dependencies. */451 $theme_names = array_keys( $wp_themes );452 foreach ( (array) $theme_names as $theme_name ) {453 $wp_themes[$theme_name]['Parent Theme'] = '';454 if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {455 foreach ( (array) $theme_names as $parent_theme_name ) {456 if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) && ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {457 $wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];458 break;459 }460 }461 }462 }463 464 return $wp_themes;465 }466 467 /**468 250 * Retrieve theme roots. 469 251 * 470 252 * @since 2.9.0 … … 479 261 480 262 $theme_roots = get_site_transient( 'theme_roots' ); 481 263 if ( false === $theme_roots ) { 482 get_themes();483 $theme_roots = get_site_transient( 'theme_roots' ); // this is set in get_theme()264 search_theme_directories(); // Regenerated the transient. 265 $theme_roots = get_site_transient( 'theme_roots' ); 484 266 } 485 267 return $theme_roots; 486 268 } 487 269 488 270 /** 489 * Retrieve theme data.490 *491 * @since 1.5.0492 *493 * @param string $theme Theme name.494 * @return array|null Null, if theme name does not exist. Theme data, if exists.495 */496 function get_theme($theme) {497 $themes = get_themes();498 499 if ( is_array( $themes ) && array_key_exists( $theme, $themes ) )500 return $themes[$theme];501 502 return null;503 }504 505 /**506 271 * Retrieve current theme display name. 507 272 * 508 * If the 'current_theme' option has already been set, then it will be returned509 * instead. If it is not set, then each theme will be iterated over until both510 * the current stylesheet and current template name.511 *512 273 * @since 1.5.0 513 274 * 514 275 * @return string 515 276 */ 516 277 function get_current_theme() { 517 if ( $theme = get_option('current_theme') ) 518 return $theme; 519 520 $themes = get_themes(); 521 $current_theme = 'Twenty Eleven'; 522 523 if ( $themes ) { 524 $theme_names = array_keys( $themes ); 525 $current_template = get_option( 'template' ); 526 $current_stylesheet = get_option( 'stylesheet' ); 527 528 foreach ( (array) $theme_names as $theme_name ) { 529 if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet && 530 $themes[$theme_name]['Template'] == $current_template ) { 531 $current_theme = $themes[$theme_name]['Name']; 532 break; 533 } 534 } 535 } 536 537 update_option('current_theme', $current_theme); 538 539 return $current_theme; 278 $theme = wp_get_theme(); 279 return $theme->get('Name'); 540 280 } 541 281 542 282 /** … … 574 314 * @return array Valid themes found 575 315 */ 576 316 function search_theme_directories() { 577 global $wp_theme_directories , $wp_broken_themes;317 global $wp_theme_directories; 578 318 if ( empty( $wp_theme_directories ) ) 579 319 return false; 580 320 581 $theme_files = array(); 582 $wp_broken_themes = array(); 321 static $found_themes; 322 if ( isset( $found_themes ) ) 323 return $found_themes; 324 $found_themes = array(); 583 325 326 if ( apply_filters( 'wp_cache_themes_persistently', false ) ) { 327 $cached_roots = get_site_transient( 'theme_roots' ); 328 if ( is_array( $cached_roots ) ) { 329 foreach ( $cached_roots as $theme_dir => $theme_root ) { 330 $found_themes[ $theme_dir ] = array( 331 'theme_file' => $theme_dir . '/style.css', 332 'theme_root' => $theme_root, 333 ); 334 } 335 return $found_themes; 336 } 337 } 338 584 339 /* Loop the registered theme directories and extract all themes */ 585 340 foreach ( (array) $wp_theme_directories as $theme_root ) { 586 341 $theme_loc = $theme_root; 587 342 588 343 /* We don't want to replace all forward slashes, see Trac #4541 */ 589 344 if ( '/' != WP_CONTENT_DIR ) 590 $theme_loc = str_replace( WP_CONTENT_DIR, '', $theme_root);345 $theme_loc = str_replace( WP_CONTENT_DIR, '', $theme_root ); 591 346 592 347 /* Files in the root of the current theme directory and one subdir down */ 593 $themes_dir = @ opendir($theme_root); 594 595 if ( !$themes_dir ) 348 $dirs = @ scandir( $theme_root ); 349 if ( ! $dirs ) 596 350 return false; 597 598 while ( ($theme_dir = readdir($themes_dir)) !== false ) { 599 if ( is_dir($theme_root . '/' . $theme_dir) && is_readable($theme_root . '/' . $theme_dir) ) { 600 if ( $theme_dir[0] == '.' || $theme_dir == 'CVS' ) 601 continue; 602 603 $stylish_dir = @opendir($theme_root . '/' . $theme_dir); 604 $found_stylesheet = false; 605 606 while ( ($theme_file = readdir($stylish_dir)) !== false ) { 607 if ( $theme_file == 'style.css' ) { 608 $theme_files[$theme_dir] = array( 'theme_file' => $theme_dir . '/' . $theme_file, 'theme_root' => $theme_root ); 609 $found_stylesheet = true; 610 break; 611 } 351 foreach ( $dirs as $dir ) { 352 if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' ) 353 continue; 354 if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) { 355 // wp-content/themes/a-single-theme 356 // wp-content/themes is $theme_root, a-single-theme is $dir 357 $found_themes[ $dir ] = array( 358 'theme_file' => $dir . '/style.css', 359 'theme_root' => $theme_root, 360 ); 361 } else { 362 $found_theme = false; 363 // wp-content/themes/a-folder-of-themes/* 364 // wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs 365 $sub_dirs = @ scandir( $theme_root . '/' . $dir ); 366 if ( ! $sub_dirs ) 367 return false; 368 foreach ( $sub_dirs as $sub_dir ) { 369 if ( ! is_dir( $theme_root . '/' . $dir ) || $dir[0] == '.' || $dir == 'CVS' ) 370 continue; 371 if ( ! file_exists( $theme_root . '/' . $dir . '/' . $sub_dir . '/style.css' ) ) 372 continue; 373 $found_themes[ $dir . '/' . $sub_dir ] = array( 374 'theme_file' => $dir . '/' . $sub_dir . '/style.css', 375 'theme_root' => $theme_root, 376 ); 377 $found_theme = true; 612 378 } 613 @closedir($stylish_dir); 379 // Never mind the above, it's just a theme missing a style.css. 380 // Return it; WP_Theme will catch the error. 381 if ( ! $found_theme ) 382 $found_themes[ $dir ] = array( 383 'theme_file' => $dir . '/style.css', 384 'theme_root' => $theme_root, 385 ); 386 } 387 } 388 } 614 389 615 if ( !$found_stylesheet ) { // look for themes in that dir 616 $subdir = "$theme_root/$theme_dir"; 617 $subdir_name = $theme_dir; 618 $theme_subdirs = @opendir( $subdir ); 390 asort( $found_themes ); 619 391 620 $found_subdir_themes = false; 621 while ( ($theme_subdir = readdir($theme_subdirs)) !== false ) { 622 if ( is_dir( $subdir . '/' . $theme_subdir) && is_readable($subdir . '/' . $theme_subdir) ) { 623 if ( $theme_subdir[0] == '.' || $theme_subdir == 'CVS' ) 624 continue; 392 $theme_roots = array(); 393 foreach ( $found_themes as $theme_dir => $theme_data ) { 394 $theme_roots[ $theme_dir ] = $theme_data['theme_root']; 395 } 625 396 626 $stylish_dir = @opendir($subdir . '/' . $theme_subdir);627 $found_stylesheet = false;397 if ( $theme_roots != get_site_transient( 'theme_roots' ) ) 398 set_site_transient( 'theme_roots', $theme_roots, 7200 ); // cache for two hours 628 399 629 while ( ($theme_file = readdir($stylish_dir)) !== false ) { 630 if ( $theme_file == 'style.css' ) { 631 $theme_files["$theme_dir/$theme_subdir"] = array( 'theme_file' => $subdir_name . '/' . $theme_subdir . '/' . $theme_file, 'theme_root' => $theme_root ); 632 $found_stylesheet = true; 633 $found_subdir_themes = true; 634 break; 635 } 636 } 637 @closedir($stylish_dir); 638 } 639 } 640 @closedir($theme_subdirs); 641 if ( !$found_subdir_themes ) 642 $wp_broken_themes[$theme_dir] = array('Name' => $theme_dir, 'Title' => $theme_dir, 'Description' => __('Stylesheet is missing.')); 643 } 644 } 645 } 646 @closedir( $themes_dir ); 647 } 648 return $theme_files; 400 return $found_themes; 649 401 } 650 402 651 403 /** … … 725 477 $theme_root = $theme_roots[$stylesheet_or_template]; 726 478 } 727 479 728 return $theme_root;480 return str_replace( WP_CONTENT_DIR, '', $theme_root ); 729 481 } 730 482 731 483 /** -
wp-includes/deprecated.php
2906 2906 */ 2907 2907 function debug_fclose( $fp ) { 2908 2908 _deprecated_function( __FUNCTION__, 'error_log()' ); 2909 } 2910 2911 /** 2912 * Retrieve list of themes with theme data in theme directory. 2913 * 2914 * The theme is broken, if it doesn't have a parent theme and is missing either 2915 * style.css and, or index.php. If the theme has a parent theme then it is 2916 * broken, if it is missing style.css; index.php is optional. 2917 * 2918 * @since 1.5.0 2919 * @global array $wp_themes Stores the working themes. 2920 * 2921 * @return array Theme list with theme data. 2922 */ 2923 function get_themes() { 2924 _deprecated_function( __FUNCTION__, '3.4', 'wp_get_themes()' ); 2925 2926 global $wp_themes; 2927 if ( isset( $wp_themes ) ) 2928 return $wp_themes; 2929 2930 $themes = wp_get_themes(); 2931 $wp_themes = array(); 2932 2933 foreach ( $themes as $theme ) { 2934 $wp_themes[ $theme->get('Name') ] = $theme; 2935 } 2936 2937 return $wp_themes; 2938 } 2939 2940 /** 2941 * Retrieve theme data. 2942 * 2943 * @since 1.5.0 2944 * 2945 * @param string $theme Theme name. 2946 * @return array|null Null, if theme name does not exist. Theme data, if exists. 2947 */ 2948 function get_theme( $theme ) { 2949 _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme($stylesheet)' ); 2950 2951 $themes = get_themes(); 2952 if ( is_array( $themes ) && array_key_exists( $theme, $themes ) ) 2953 return $themes[$theme]; 2954 return null; 2909 2955 } 2956 No newline at end of file -
wp-settings.php
112 112 require( ABSPATH . WPINC . '/capabilities.php' ); 113 113 require( ABSPATH . WPINC . '/query.php' ); 114 114 require( ABSPATH . WPINC . '/theme.php' ); 115 require( ABSPATH . WPINC . '/class-wp-theme.php' ); 115 116 require( ABSPATH . WPINC . '/user.php' ); 116 117 require( ABSPATH . WPINC . '/meta.php' ); 117 118 require( ABSPATH . WPINC . '/general-template.php' ); -
wp-admin/includes/ms-deprecated.php
64 64 _deprecated_function(__FUNCTION__, '3.0', 'is_network_only_plugin()' ); 65 65 return is_network_only_plugin( $file ); 66 66 } 67 68 function get_site_allowed_themes() { 69 _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_network()' ); 70 return array_map( 'intval', WP_Theme::get_allowed_on_network() ); 71 } 72 73 function wpmu_get_blog_allowedthemes( $blog_id = 0 ) { 74 _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_site()' ); 75 return array_map( 'intval', WP_Theme::get_allowed_on_site( $blog_id ) ); 76 } 77 No newline at end of file -
wp-admin/includes/update.php
217 217 } 218 218 219 219 function get_theme_updates() { 220 $themes = get_themes();220 $themes = wp_get_themes(); 221 221 $current = get_site_transient('update_themes'); 222 222 $update_themes = array(); 223 223 224 foreach ( $themes as $theme ) { 225 $theme = (object) $theme; 226 if ( isset($current->response[ $theme->Stylesheet ]) ) { 227 $update_themes[$theme->Stylesheet] = $theme; 228 $update_themes[$theme->Stylesheet]->update = $current->response[ $theme->Stylesheet ]; 229 } 224 foreach ( $current->response as $stylesheet => $data ) { 225 $update_themes[ $stylesheet ] = wp_get_theme( $stylesheet ); 226 $update_themes[ $stylesheet ]->update = $data; 230 227 } 231 228 232 229 return $update_themes; -
wp-admin/includes/upgrade.php
1154 1154 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" ); 1155 1155 } 1156 1156 1157 // 3.3-beta. Can remove before release.1158 if ( $wp_current_db_version > 18715 && $wp_current_db_version < 193891159 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) )1160 delete_metadata( 'user', 0, 'dismissed_wp_pointers', '', true );1161 1162 1157 if ( $wp_current_db_version >= 11548 ) 1163 1158 return; 1164 1159 … … 1235 1230 $wpdb->query("ALTER TABLE $wpdb->comments DROP INDEX comment_approved"); 1236 1231 $wpdb->show_errors(); 1237 1232 } 1233 1234 if ( $wp_current_db_version < 20000 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) { 1235 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" ); 1236 } 1238 1237 } 1239 1238 1240 1239 /** -
wp-admin/includes/class-wp-ms-themes-list-table.php
15 15 function __construct() { 16 16 global $status, $page; 17 17 18 $default_status = get_user_option( 'themes_last_view' ); 19 if ( empty( $default_status ) ) 20 $default_status = 'all'; 21 $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : $default_status; 22 if ( !in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search' ) ) ) 18 $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all'; 19 if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search' ) ) ) 23 20 $status = 'all'; 24 if ( $status != $default_status && 'search' != $status )25 update_user_meta( get_current_user_id(), 'themes_last_view', $status );26 21 27 22 $page = $this->get_pagenum(); 28 23 … … 55 50 } 56 51 57 52 function prepare_items() { 58 global $status, $t hemes, $totals, $page, $orderby, $order, $s;53 global $status, $totals, $page, $orderby, $order, $s; 59 54 60 55 wp_reset_vars( array( 'orderby', 'order', 's' ) ); 61 56 62 57 $themes = array( 63 'all' => apply_filters( 'all_themes', get_themes() ),58 'all' => apply_filters( 'all_themes', wp_get_themes() ), 64 59 'search' => array(), 65 60 'enabled' => array(), 66 61 'disabled' => array(), 67 62 'upgrade' => array() 68 63 ); 69 64 70 $site_allowed_themes = get_site_allowed_themes(); 71 if ( !$this->is_site_themes ) { 72 $allowed_themes = $site_allowed_themes; 73 $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' ); 74 } else { 75 $allowed_themes = wpmu_get_blog_allowedthemes( $this->site_id ); 65 if ( $this->is_site_themes ) { 76 66 $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' ); 67 $allowed_where = 'site'; 68 } else { 69 $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' ); 70 $allowed_where = 'network'; 77 71 } 78 72 79 $current = get_site_transient( 'update_themes' );73 $current = current_user_can( 'update_themes' ) && ! $this->is_site_themes && get_site_transient( 'update_themes' ); 80 74 81 75 foreach ( (array) $themes['all'] as $key => $theme ) { 82 $theme_key = $theme['Stylesheet']; 83 84 if ( isset( $allowed_themes [ $theme_key ] ) ) { 85 $themes['all'][$key]['enabled'] = true; 86 $themes['enabled'][$key] = $themes['all'][$key]; 76 if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) { 77 unset( $themes['all'][ $key ] ); 78 continue; 87 79 } 88 else {89 $themes['all'][$key]['enabled'] = false;90 $themes['disabled'][$key] = $themes['all'][$key];91 }92 if ( isset( $current->response[ $theme['Template'] ] ) )93 $themes['upgrade'][$key] = $themes['all'][$key];94 80 95 if ( $this->is_site_themes && isset( $site_allowed_themes[$theme_key] ) ) {96 unset( $themes['all'][$key] );97 unset( $themes['enabled'][$key] ); 98 unset( $themes['disabled'][$key] );99 }81 $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled'; 82 $themes[ $filter ][ $key ] = $themes['all'][ $key ]; 83 84 if ( $current && isset( $current->response[ $key ] ) ) 85 $themes['upgrade'][ $key ] = $themes['all'][ $key ]; 100 86 } 101 87 102 if ( !current_user_can( 'update_themes' ) || $this->is_site_themes )103 $themes['upgrade'] = array();104 105 88 if ( $s ) { 106 89 $status = 'search'; 107 90 $themes['search'] = array_filter( $themes['all'], array( &$this, '_search_callback' ) ); … … 115 98 $status = 'all'; 116 99 117 100 $this->items = $themes[ $status ]; 101 WP_Theme::sort_by_name( $this->items ); 102 103 $this->has_items = ! empty( $themes['all'] ); 118 104 $total_this_page = $totals[ $status ]; 119 105 120 106 if ( $orderby ) { 121 107 $orderby = ucfirst( $orderby ); 122 108 $order = strtoupper( $order ); 123 109 124 uasort( $this->items, array( &$this, '_order_callback' ) ); 110 if ( $orderby == 'Name' ) { 111 if ( 'ASC' == $order ) 112 $this->items = array_reverse( $this->items ); 113 } else { 114 uasort( $this->items, array( &$this, '_order_callback' ) ); 115 } 125 116 } 126 117 127 118 $start = ( $page - 1 ) * $themes_per_page; 128 119 129 120 if ( $total_this_page > $themes_per_page ) 130 $this->items = array_slice( $this->items, $start, $themes_per_page );121 $this->items = array_slice( $this->items, $start, $themes_per_page, true ); 131 122 132 123 $this->set_pagination_args( array( 133 124 'total_items' => $total_this_page, … … 140 131 if ( is_null( $term ) ) 141 132 $term = stripslashes( $_REQUEST['s'] ); 142 133 143 $search_fields = array( 'Name', 'Title', 'Description', 'Author', 'Author Name', 'Author URI', 'Template', 'Stylesheet' );144 foreach ( $search_fields as $field )145 if ( stripos( $theme[ $field ], $term ) !== false)134 foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) { 135 // Don't mark up; Do translate. 136 if ( false !== stripos( $theme->display( $field, false, true ), $term ) ) 146 137 return true; 138 } 147 139 140 if ( false !== stripos( $theme->get_stylesheet(), $term ) ) 141 return true; 142 143 if ( false !== stripos( $theme->get_template(), $term ) ) 144 return true; 145 148 146 return false; 149 147 } 150 148 149 // Not used by any core columns. 151 150 function _order_callback( $theme_a, $theme_b ) { 152 151 global $orderby, $order; 153 152 154 $a = $theme_a[ $orderby];155 $b = $theme_b[ $orderby];153 $a = $theme_a[ $orderby ]; 154 $b = $theme_b[ $orderby ]; 156 155 157 156 if ( $a == $b ) 158 157 return 0; … … 164 163 } 165 164 166 165 function no_items() { 167 global $themes; 168 169 if ( !empty( $themes['all'] ) ) 166 if ( ! $$this->has_items ) 170 167 _e( 'No themes found.' ); 171 168 else 172 169 _e( 'You do not appear to have any themes available at this time.' ); … … 264 261 265 262 $context = $status; 266 263 267 if ( $this->is_site_themes ) 264 if ( $this->is_site_themes ) { 268 265 $url = "site-themes.php?id={$this->site_id}&"; 269 else 266 $allowed = $theme->is_allowed( 'site', $this->site_id ); 267 } else { 270 268 $url = 'themes.php?'; 269 $allowed = $theme->is_allowed( 'network' ); 270 } 271 271 272 272 // preorder 273 273 $actions = array( … … 277 277 'delete' => '' 278 278 ); 279 279 280 $theme_key = $theme ['Stylesheet'];280 $theme_key = $theme->get_stylesheet(); 281 281 282 if ( empty( $theme['enabled'] ))282 if ( ! $allowed ) 283 283 $actions['enable'] = '<a href="' . esc_url( wp_nonce_url($url . 'action=enable&theme=' . $theme_key . '&paged=' . $page . '&s=' . $s, 'enable-theme_' . $theme_key) ) . '" title="' . esc_attr__('Enable this theme') . '" class="edit">' . ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . '</a>'; 284 284 else 285 285 $actions['disable'] = '<a href="' . esc_url( wp_nonce_url($url . 'action=disable&theme=' . $theme_key . '&paged=' . $page . '&s=' . $s, 'disable-theme_' . $theme_key) ) . '" title="' . esc_attr__('Disable this theme') . '">' . ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . '</a>'; 286 286 287 287 if ( current_user_can('edit_themes') ) 288 $actions['edit'] = '<a href="' . esc_url('theme-editor.php?theme=' . urlencode( $theme['Name'] )) . '" title="' . esc_attr__('Open this theme in the Theme Editor') . '" class="edit">' . __('Edit') . '</a>';288 $actions['edit'] = '<a href="' . esc_url('theme-editor.php?theme=' . $theme_key ) . '" title="' . esc_attr__('Open this theme in the Theme Editor') . '" class="edit">' . __('Edit') . '</a>'; 289 289 290 if ( empty( $theme['enabled'] )&& current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $theme_key != get_option( 'stylesheet' ) && $theme_key != get_option( 'template' ) )290 if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $theme_key != get_option( 'stylesheet' ) && $theme_key != get_option( 'template' ) ) 291 291 $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( 'themes.php?action=delete-selected&checked[]=' . $theme_key . '&theme_status=' . $context . '&paged=' . $page . '&s=' . $s, 'bulk-themes' ) ) . '" title="' . esc_attr__( 'Delete this theme' ) . '" class="delete">' . __( 'Delete' ) . '</a>'; 292 292 293 293 $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme_key, $theme, $context ); 294 294 $actions = apply_filters( "theme_action_links_$theme_key", $actions, $theme_key, $theme, $context ); 295 295 296 $class = empty( $theme['enabled'] )? 'inactive' : 'active';297 $checkbox_id = "checkbox_" . md5( $theme['Name']);298 $checkbox = "<input type='checkbox' name='checked[]' value='" . esc_attr( $theme_key ) . "' id='" . $checkbox_id . "' /><label class='screen-reader-text' for='" . $checkbox_id . "' >" . __('Select') . " " . $theme ['Name']. "</label>";296 $class = ! $allowed ? 'inactive' : 'active'; 297 $checkbox_id = "checkbox_" . md5( $theme->get('Name') ); 298 $checkbox = "<input type='checkbox' name='checked[]' value='" . esc_attr( $theme_key ) . "' id='" . $checkbox_id . "' /><label class='screen-reader-text' for='" . $checkbox_id . "' >" . __('Select') . " " . $theme->display('Name') . "</label>"; 299 299 300 $description = '<p>' . $theme['Description'] . '</p>'; 301 $theme_name = $theme['Name']; 300 $description = '<p>' . $theme->display( 'Description' ) . '</p>'; 302 301 303 $id = sanitize_ title( $theme_name);302 $id = sanitize_html_class( $theme->get_stylesheet() ); 304 303 305 304 echo "<tr id='$id' class='$class'>"; 306 305 … … 316 315 echo "<th scope='row' class='check-column'>$checkbox</th>"; 317 316 break; 318 317 case 'name': 319 echo "<td class='theme-title'$style><strong> $theme_name</strong>";318 echo "<td class='theme-title'$style><strong>" . $theme->display('Name') . "</strong>"; 320 319 echo $this->row_actions( $actions, true ); 321 320 echo "</td>"; 322 321 break; 323 322 case 'description': 324 323 echo "<td class='column-description desc'$style> 325 <div class='theme-description'> $description</div>324 <div class='theme-description'>" . $theme->display( 'Description' ) . "</div> 326 325 <div class='$class second theme-version-author-uri'>"; 327 326 328 327 $theme_meta = array(); 329 328 330 if ( !empty( $theme['Version']) )331 $theme_meta[] = sprintf( __( 'Version %s' ), $theme ['Version']);329 if ( $theme->get('Version') ) 330 $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display('Version') ); 332 331 333 if ( !empty( $theme['Author']) )334 $theme_meta[] = sprintf( __( 'By %s' ), $theme ['Author']);332 if ( $theme->get('Author') ) 333 $theme_meta[] = sprintf( __( 'By %s' ), $theme->display('Author') ); 335 334 336 if ( !empty( $theme['Theme URI']) )337 $theme_meta[] = '<a href="' . $theme ['Theme URI']. '" title="' . esc_attr__( 'Visit theme homepage' ) . '">' . __( 'Visit Theme Site' ) . '</a>';335 if ( $theme->get('ThemeURI') ) 336 $theme_meta[] = '<a href="' . $theme->display('ThemeURI') . '" title="' . esc_attr__( 'Visit theme homepage' ) . '">' . __( 'Visit Theme Site' ) . '</a>'; 338 337 339 338 $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $theme_key, $theme, $status ); 340 339 echo implode( ' | ', $theme_meta ); -
wp-admin/includes/dashboard.php
383 383 echo "\n\t</table>\n\t</div>"; 384 384 385 385 echo "\n\t".'<div class="versions">'; 386 $ ct = current_theme_info();386 $theme = wp_get_theme(); 387 387 388 388 echo "\n\t<p>"; 389 389 390 if ( empty( $ct->stylesheet_dir) ) {390 if ( $theme->errors() ) { 391 391 if ( ! is_multisite() || is_super_admin() ) 392 392 echo '<span class="error-message">' . __('ERROR: The themes directory is either empty or doesn’t exist. Please check your installation.') . '</span>'; 393 393 } elseif ( ! empty($wp_registered_sidebars) ) { … … 401 401 } 402 402 $num = number_format_i18n( $num_widgets ); 403 403 404 $switch_themes = $ ct->title;404 $switch_themes = $theme->display('Name'); 405 405 if ( current_user_can( 'switch_themes') ) 406 406 $switch_themes = '<a href="themes.php">' . $switch_themes . '</a>'; 407 407 if ( current_user_can( 'edit_theme_options' ) ) { … … 411 411 } 412 412 } else { 413 413 if ( current_user_can( 'switch_themes' ) ) 414 printf( __('Theme <span class="b"><a href="themes.php">%1$s</a></span>'), $ ct->title);414 printf( __('Theme <span class="b"><a href="themes.php">%1$s</a></span>'), $theme->display('Name') ); 415 415 else 416 printf( __('Theme <span class="b">%1$s</span>'), $ ct->title);416 printf( __('Theme <span class="b">%1$s</span>'), $theme->display('Name') ); 417 417 } 418 418 echo '</p>'; 419 419 … … 1313 1313 <div class="welcome-panel-column welcome-panel-last"> 1314 1314 <h4><span class="icon16 icon-appearance"></span> <?php _e( 'Customize Your Site' ); ?></h4> 1315 1315 <?php 1316 $ ct = current_theme_info();1317 if ( empty ( $ct->stylesheet_dir) ) :1316 $theme = wp_get_theme(); 1317 if ( $theme->errors() ) : 1318 1318 echo '<p>'; 1319 1319 printf( __( '<a href="%s">Install a theme</a> to get started customizing your site.' ), esc_url( admin_url( 'themes.php' ) ) ); 1320 1320 echo '</p>'; 1321 1321 else: 1322 1322 $customize_links = array(); 1323 if ( 'twentyeleven' == $ ct->stylesheet)1323 if ( 'twentyeleven' == $theme->get_stylesheet() ) 1324 1324 $customize_links[] = sprintf( __( '<a href="%s">Choose light or dark</a>' ), esc_url( admin_url( 'themes.php?page=theme_options' ) ) ); 1325 1325 1326 1326 if ( current_theme_supports( 'custom-background' ) ) … … 1334 1334 1335 1335 if ( ! empty( $customize_links ) ) { 1336 1336 echo '<p>'; 1337 printf( __( 'Use the current theme — %1$s — or <a href="%2$s">choose a new one</a>. If you stick with % 3$s, here are a few ways to make your site look unique.' ), $ct->title, esc_url( admin_url( 'themes.php' ) ), $ct->title);1337 printf( __( 'Use the current theme — %1$s — or <a href="%2$s">choose a new one</a>. If you stick with %1$s, here are a few ways to make your site look unique.' ), $theme->display('Name'), esc_url( admin_url( 'themes.php' ) ) ); 1338 1338 echo '</p>'; 1339 1339 ?> 1340 1340 <ul> … … 1345 1345 <?php 1346 1346 } else { 1347 1347 echo '<p>'; 1348 printf( __( 'Use the current theme — %1$s — or <a href="%2$s">choose a new one</a>.' ), $ ct->title, esc_url( admin_url( 'themes.php' ) ) );1348 printf( __( 'Use the current theme — %1$s — or <a href="%2$s">choose a new one</a>.' ), $this->display('Name'), esc_url( admin_url( 'themes.php' ) ) ); 1349 1349 echo '</p>'; 1350 1350 } 1351 1351 endif; ?> -
wp-admin/includes/deprecated.php
879 879 $screen = convert_to_screen( $screen ); 880 880 881 881 WP_Screen::add_old_compat_help( $screen, $help ); 882 } 883 884 /** 885 * Get the allowed themes for the current blog. 886 * 887 * @since 3.0.0 888 * @deprecated 3.4.0 889 * @deprecated Use wp_get_themes() 890 * @see wp_get_themes() 891 * 892 * @return array $themes Array of allowed themes. 893 */ 894 function get_allowed_themes() { 895 _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'allowed' => true ) )" ); 896 897 $themes = wp_get_themes( array( 'allowed' => true ) ); 898 899 $wp_themes = array(); 900 foreach ( $themes as $theme ) { 901 $wp_themes[ $theme->get('Name') ] = $theme; 902 } 903 904 return $wp_themes; 905 } 906 907 /** 908 * {@internal Missing Short Description}} 909 * 910 * @since 1.5.0 911 * 912 * @return unknown 913 */ 914 function get_broken_themes() { 915 _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'errors' => true )" ); 916 917 $themes = wp_get_themes( array( 'errors' => true ) ); 918 $broken = array(); 919 foreach ( $themes as $theme ) { 920 $broken[ $theme->get('Name') ] = array( 921 'Title' => $theme->get('Name'), 922 'Description' => $theme->errors()->get_error_message(), 923 ); 924 } 925 return $broken; 926 } 927 928 /** 929 * {@internal Missing Short Description}} 930 * 931 * @since 2.0.0 932 * 933 * @return unknown 934 */ 935 function current_theme_info() { 936 _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' ); 937 938 return wp_get_theme(); 882 939 } 940 No newline at end of file -
wp-admin/includes/schema.php
343 343 344 344 $template = WP_DEFAULT_THEME; 345 345 // If default theme is a child theme, we need to get its template 346 foreach ( (array) get_themes() as $theme ) { 347 if ( WP_DEFAULT_THEME == $theme['Stylesheet'] ) { 348 $template = $theme['Template']; 349 break; 350 } 351 } 346 $theme = wp_get_theme( $template ); 347 if ( ! $theme->errors() ) 348 $template = $theme->get_template(); 352 349 353 350 $timezone_string = ''; 354 351 $gmt_offset = 0; -
wp-admin/includes/theme.php
7 7 */ 8 8 9 9 /** 10 * {@internal Missing Short Description}}11 *12 * @since 2.0.013 *14 * @return unknown15 */16 function current_theme_info() {17 $themes = get_themes();18 $current_theme = get_current_theme();19 20 if ( ! $themes ) {21 $ct = new stdClass;22 $ct->name = $current_theme;23 return $ct;24 }25 26 if ( ! isset( $themes[$current_theme] ) ) {27 delete_option( 'current_theme' );28 $current_theme = get_current_theme();29 }30 31 $ct = new stdClass;32 $ct->name = $current_theme;33 $ct->title = $themes[$current_theme]['Title'];34 $ct->version = $themes[$current_theme]['Version'];35 $ct->parent_theme = $themes[$current_theme]['Parent Theme'];36 $ct->template_dir = $themes[$current_theme]['Template Dir'];37 $ct->stylesheet_dir = $themes[$current_theme]['Stylesheet Dir'];38 $ct->template = $themes[$current_theme]['Template'];39 $ct->stylesheet = $themes[$current_theme]['Stylesheet'];40 $ct->screenshot = $themes[$current_theme]['Screenshot'];41 $ct->description = $themes[$current_theme]['Description'];42 $ct->author = $themes[$current_theme]['Author'];43 $ct->tags = $themes[$current_theme]['Tags'];44 $ct->theme_root = $themes[$current_theme]['Theme Root'];45 $ct->theme_root_uri = $themes[$current_theme]['Theme Root URI'];46 return $ct;47 }48 49 /**50 10 * Remove a theme 51 11 * 52 12 * @since 2.8.0 … … 114 74 } 115 75 116 76 /** 117 * {@internal Missing Short Description}}118 *119 * @since 1.5.0120 *121 * @return unknown122 */123 function get_broken_themes() {124 global $wp_broken_themes;125 126 get_themes();127 return $wp_broken_themes;128 }129 130 /**131 * Get the allowed themes for the current blog.132 *133 * @since 3.0.0134 *135 * @uses get_themes()136 * @uses current_theme_info()137 * @uses get_site_allowed_themes()138 * @uses wpmu_get_blog_allowedthemes139 *140 * @return array $themes Array of allowed themes.141 */142 function get_allowed_themes() {143 if ( !is_multisite() )144 return get_themes();145 146 $themes = get_themes();147 $ct = current_theme_info();148 $allowed_themes = apply_filters("allowed_themes", get_site_allowed_themes() );149 if ( $allowed_themes == false )150 $allowed_themes = array();151 152 $blog_allowed_themes = wpmu_get_blog_allowedthemes();153 if ( is_array( $blog_allowed_themes ) )154 $allowed_themes = array_merge( $allowed_themes, $blog_allowed_themes );155 156 if ( isset( $allowed_themes[ esc_html( $ct->stylesheet ) ] ) == false )157 $allowed_themes[ esc_html( $ct->stylesheet ) ] = true;158 159 reset( $themes );160 foreach ( $themes as $key => $theme ) {161 if ( isset( $allowed_themes[ esc_html( $theme[ 'Stylesheet' ] ) ] ) == false )162 unset( $themes[ $key ] );163 }164 reset( $themes );165 166 return $themes;167 }168 169 /**170 77 * Get the Page Templates available in this theme 171 78 * 172 79 * @since 1.5.0 … … 174 81 * @return array Key is the template name, value is the filename of the template 175 82 */ 176 83 function get_page_templates() { 177 $themes = get_themes(); 178 $theme = get_current_theme(); 179 $templates = $themes[$theme]['Template Files']; 180 $page_templates = array(); 181 182 if ( is_array( $templates ) ) { 183 $base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) ); 184 185 foreach ( $templates as $template ) { 186 $basename = str_replace($base, '', $template); 187 188 // don't allow template files in subdirectories 189 if ( false !== strpos($basename, '/') ) 190 continue; 191 192 if ( 'functions.php' == $basename ) 193 continue; 194 195 $template_data = implode( '', file( $template )); 196 197 $name = ''; 198 if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name ) ) 199 $name = _cleanup_header_comment($name[1]); 200 201 if ( !empty( $name ) ) { 202 $page_templates[trim( $name )] = $basename; 203 } 204 } 205 } 206 207 return $page_templates; 84 return wp_get_theme()->get_page_templates(); 208 85 } 209 86 210 87 /** … … 240 117 if ( !isset($themes_update) ) 241 118 $themes_update = get_site_transient('update_themes'); 242 119 243 if ( is_object($theme) && isset($theme->stylesheet) ) 244 $stylesheet = $theme->stylesheet; 245 elseif ( is_array($theme) && isset($theme['Stylesheet']) ) 246 $stylesheet = $theme['Stylesheet']; 247 else 248 return false; //No valid info passed. 120 if ( ! is_a( $theme, 'WP_Theme' ) ) 121 return; 249 122 123 $stylesheet = $theme->get_stylesheet(); 124 250 125 if ( isset($themes_update->response[ $stylesheet ]) ) { 251 126 $update = $themes_update->response[ $stylesheet ]; 252 $theme_name = is_object($theme) ? $theme->name : (is_array($theme) ? $theme['Name'] : '');127 $theme_name = $theme->get('Name'); 253 128 $details_url = add_query_arg(array('TB_iframe' => 'true', 'width' => 1024, 'height' => 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list. 254 129 $update_url = wp_nonce_url('update.php?action=upgrade-theme&theme=' . urlencode($stylesheet), 'upgrade-theme_' . $stylesheet); 255 130 $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __("Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.") ) . '\') ) {return true;}return false;"'; … … 270 145 * 271 146 * @since 3.1.0 272 147 * 148 * @param bool $api Optional. Whether to hit the API for tags. Defaults to true. 273 149 * @return array Array of features keyed by category with translations keyed by slug. 274 150 */ 275 function get_theme_feature_list( ) {151 function get_theme_feature_list( $api = true ) { 276 152 // Hard-coded list is used if api not accessible. 277 153 $features = array( 278 154 __('Colors') => array( … … 290 166 'white' => __( 'White' ), 291 167 'yellow' => __( 'Yellow' ), 292 168 'dark' => __( 'Dark' ), 293 'light' => __( 'Light ')169 'light' => __( 'Light' ) 294 170 ), 295 171 296 172 __('Columns') => array( … … 335 211 ) 336 212 ); 337 213 338 if ( ! current_user_can('install_themes') )214 if ( ! $api || !current_user_can('install_themes') ) 339 215 return $features; 340 216 341 217 if ( !$feature_list = get_site_transient( 'wporg_theme_feature_list' ) ) -
wp-admin/includes/theme-install.php
265 265 } 266 266 } 267 267 268 $theme s = get_themes();269 foreach ( (array) $themes as $this_theme) {270 if ( is_array($this_theme) && $this_theme['Stylesheet'] == $api->slug) {271 if ( version_compare( $this_theme['Version'], $api->version, '=' ) ) {268 $theme = wp_get_theme( $api->slug ); 269 if ( is_a( $theme, 'WP_Theme' ) ) { 270 switch ( version_compare( $theme->get('Version'), $api->version ) ) { 271 case 0; // equal 272 272 $type = 'latest_installed'; 273 } elseif ( version_compare( $this_theme['Version'], $api->version, '>' ) ) {273 case 1: // installed theme > api version 274 274 $type = 'newer_installed'; 275 $newer_version = $this_theme['Version']; 276 } 277 break; 275 $newer_version = $theme->get('Version'); 278 276 } 279 277 } 280 278 ?> -
wp-admin/includes/class-wp-themes-list-table.php
24 24 } 25 25 26 26 function prepare_items() { 27 global $ct;27 $themes = wp_get_themes( array( 'allowed' => true ) ); 28 28 29 $ct = current_theme_info();30 31 $themes = get_allowed_themes();32 33 29 if ( ! empty( $_REQUEST['s'] ) ) { 34 30 $search = strtolower( stripslashes( $_REQUEST['s'] ) ); 35 31 $this->search = array_merge( $this->search, array_filter( array_map( 'trim', explode( ',', $search ) ) ) ); … … 45 41 46 42 if ( $this->search || $this->features ) { 47 43 foreach ( $themes as $key => $theme ) { 48 if ( ! $this->search_theme( $theme ) )44 if ( ! $this->search_theme( $theme ) ) 49 45 unset( $themes[ $key ] ); 50 46 } 51 47 } 52 48 53 unset( $themes[ $ct->name] );54 uksort( $themes, "strnatcasecmp");49 unset( $themes[ get_option( 'stylesheet' ) ] ); 50 WP_Theme::sort_by_name( $themes ); 55 51 56 52 $per_page = 999; 57 53 $page = $this->get_pagenum(); … … 125 121 126 122 function display_rows() { 127 123 $themes = $this->items; 128 $theme_names = array_keys( $themes );129 natcasesort( $theme_names );130 124 131 foreach ( $theme_names as $theme_name ) { 132 $class = array( 'available-theme' ); 133 ?> 134 <div class="<?php echo join( ' ', $class ); ?>"> 135 <?php if ( !empty( $theme_name ) ) : 136 $template = $themes[$theme_name]['Template']; 137 $stylesheet = $themes[$theme_name]['Stylesheet']; 138 $title = $themes[$theme_name]['Title']; 139 $version = $themes[$theme_name]['Version']; 140 $description = $themes[$theme_name]['Description']; 141 $author = $themes[$theme_name]['Author']; 142 $screenshot = $themes[$theme_name]['Screenshot']; 143 $stylesheet_dir = $themes[$theme_name]['Stylesheet Dir']; 144 $template_dir = $themes[$theme_name]['Template Dir']; 145 $parent_theme = $themes[$theme_name]['Parent Theme']; 146 $theme_root = $themes[$theme_name]['Theme Root']; 147 $theme_root_uri = $themes[$theme_name]['Theme Root URI']; 148 $preview_link = esc_url( add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => true, 'TB_iframe' => 'true' ), home_url( '/' ) ) ); 149 $preview_text = esc_attr( sprintf( __( 'Preview of “%s”' ), $title ) ); 150 $tags = $themes[$theme_name]['Tags']; 151 $thickbox_class = 'thickbox thickbox-preview'; 152 $activate_link = wp_nonce_url( "themes.php?action=activate&template=" . urlencode( $template ) . "&stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $template ); 153 $activate_text = esc_attr( sprintf( __( 'Activate “%s”' ), $title ) ); 154 $actions = array(); 155 $actions[] = '<a href="' . $activate_link . '" class="activatelink" title="' . $activate_text . '">' . __( 'Activate' ) . '</a>'; 156 $actions[] = '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' . esc_attr( sprintf( __( 'Preview “%s”' ), $theme_name ) ) . '">' . __( 'Preview' ) . '</a>'; 157 if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) 158 $actions[] = '<a class="submitdelete deletion" href="' . wp_nonce_url( "themes.php?action=delete&template=$stylesheet", 'delete-theme_' . $stylesheet ) . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n 'Cancel' to stop, 'OK' to delete." ), $theme_name ) ) . "' );" . '">' . __( 'Delete' ) . '</a>'; 159 $actions = apply_filters( 'theme_action_links', $actions, $themes[$theme_name] ); 125 foreach ( $themes as $theme ) { 126 echo '<div class="available-theme">'; 160 127 161 $actions = implode ( ' | ', $actions ); 162 ?> 163 <a href="<?php echo $preview_link; ?>" class="<?php echo $thickbox_class; ?> screenshot"> 164 <?php if ( $screenshot ) : ?> 165 <img src="<?php echo $theme_root_uri . '/' . $stylesheet . '/' . $screenshot; ?>" alt="" /> 166 <?php endif; ?> 167 </a> 168 <h3><?php 169 /* translators: 1: theme title, 2: theme version, 3: theme author */ 170 printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?></h3> 128 $template = $theme->get_template(); 129 $stylesheet = $theme->get_stylesheet(); 171 130 172 <span class='action-links'><?php echo $actions ?></span> 173 <span class="separator hide-if-no-js">| </span><a href="#" class="theme-detail hide-if-no-js" tabindex='4'><?php _e('Details') ?></a> 174 <div class="themedetaildiv hide-if-js"> 175 <p><?php echo $description; ?></p> 176 <?php if ( current_user_can( 'edit_themes' ) && $parent_theme ) { 177 /* translators: 1: theme title, 2: template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?> 178 <p><?php printf( __( 'The template files are located in <code>%2$s</code>. The stylesheet files are located in <code>%3$s</code>. <strong>%4$s</strong> uses templates from <strong>%5$s</strong>. Changes made to the templates will affect both themes.' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ), $title, $parent_theme ); ?></p> 179 <?php } else { ?> 180 <p><?php printf( __( 'All of this theme’s files are located in <code>%2$s</code>.' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ); ?></p> 181 <?php } ?> 182 <?php if ( $tags ) : ?> 183 <p><?php _e( 'Tags:' ); ?> <?php echo join( ', ', $tags ); ?></p> 184 <?php endif; ?> 185 <?php endif; // end if not empty theme_name ?> 186 </div> 187 <?php theme_update_available( $themes[$theme_name] ); ?> 188 </div> 189 <?php } // end foreach $theme_names 131 $title = $theme->display('Name'); 132 $version = $theme->display('Version'); 133 $author = $theme->display('Author'); 134 135 $activate_link = wp_nonce_url( "themes.php?action=activate&template=" . urlencode( $template ) . "&stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $template ); 136 $preview_link = esc_url( add_query_arg( 137 array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => true, 'TB_iframe' => 'true' ), 138 home_url( '/' ) ) ); 139 140 $actions = array(); 141 $actions[] = '<a href="' . $activate_link . '" class="activatelink" title="' 142 . esc_attr( sprintf( __( 'Activate “%s”' ), $title ) ) . '">' . __( 'Activate' ) . '</a>'; 143 $actions[] = '<a href="' . $preview_link . '" class="thickbox thickbox-preview" title="' 144 . esc_attr( sprintf( __( 'Preview “%s”' ), $title ) ) . '">' . __( 'Preview' ) . '</a>'; 145 if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) 146 $actions[] = '<a class="submitdelete deletion" href="' . wp_nonce_url( "themes.php?action=delete&template=$stylesheet", 'delete-theme_' . $stylesheet ) 147 . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n 'Cancel' to stop, 'OK' to delete." ), $title ) ) 148 . "' );" . '">' . __( 'Delete' ) . '</a>'; 149 150 $actions = apply_filters( 'theme_action_links', $actions, $theme ); 151 152 $actions = implode ( ' | ', $actions ); 153 ?> 154 <a href="<?php echo $preview_link; ?>" class="thickbox thickbox-preview screenshot"> 155 <?php if ( $theme->get_screenshot() ) : ?> 156 <img src="<?php echo esc_url( $theme->get_screenshot( 'absolute' ) ); ?>" alt="" /> 157 <?php endif; ?> 158 </a> 159 <h3><?php 160 /* translators: 1: theme title, 2: theme version, 3: theme author */ 161 printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?></h3> 162 163 <span class='action-links'><?php echo $actions ?></span> 164 <span class="separator hide-if-no-js">| </span><a href="#" class="theme-detail hide-if-no-js" tabindex='4'><?php _e('Details') ?></a> 165 <div class="themedetaildiv hide-if-js"> 166 <p><?php echo $theme->display('Description'); ?></p> 167 <?php if ( current_user_can( 'edit_themes' ) && $theme->parent() ) : 168 /* translators: 1: theme title, 2: template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?> 169 <p><?php printf( __( 'The template files are located in <code>%2$s</code>. The stylesheet files are located in <code>%3$s</code>. <strong>%4$s</strong> uses templates from <strong>%5$s</strong>. Changes made to the templates will affect both themes.' ), 170 $title, str_replace( WP_CONTENT_DIR, '', $theme->get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme->get_stylesheet_directory() ), $title, $theme->parent()->display('Name') ); ?></p> 171 <?php else : 172 /* translators: 1: theme title, 2: template dir, 3: stylesheet_dir */ ?> 173 <p><?php printf( __( 'All of this theme’s files are located in <code>%2$s</code>.' ), 174 $title, str_replace( WP_CONTENT_DIR, '', $theme->get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme->get_stylesheet_directory() ) ); ?></p> 175 <?php endif; ?> 176 <?php 177 if ( $theme->get('Tags') ) 178 printf( '<p>' . __( 'Tags: %s.' ) . '</p>', $theme->display('Tags') ); 179 ?> 180 </div> 181 <?php theme_update_available( $theme ); ?> 182 </div> 183 <?php 184 } 190 185 } 191 186 192 187 function search_theme( $theme ) { 193 $matched = 0; 188 // Search the features 189 if ( $this->features ) { 190 foreach ( $this->features as $word ) { 191 if ( ! in_array( $word, $theme->get('Tags') ) ) 192 return false; 193 } 194 } 194 195 195 196 // Match all phrases 196 if ( count( $this->search ) > 0) {197 if ( $this->search ) { 197 198 foreach ( $this->search as $word ) { 198 $matched = 0; 199 if ( in_array( $word, $theme->get('Tags') ) ) 200 continue; 199 201 200 // In a tag? 201 if ( in_array( $word, array_map( 'sanitize_title_with_dashes', $theme['Tags'] ) ) ) 202 $matched = 1; 203 204 // In one of the fields? 205 foreach ( array( 'Name', 'Title', 'Description', 'Author', 'Template', 'Stylesheet' ) AS $field ) { 206 if ( stripos( $theme[$field], $word ) !== false ) 207 $matched++; 202 foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) { 203 // Don't mark up; Do translate. 204 if ( false !== stripos( $theme->display( $header, false, true ), $word ) ) 205 continue 2; 208 206 } 209 207 210 if ( $matched == 0 ) 211 return false; 212 } 213 } 208 if ( false !== stripos( $theme->get_stylesheet(), $word ) ) 209 continue; 214 210 215 // Now search the features 216 if ( count( $this->features ) > 0 ) { 217 foreach ( $this->features as $word ) { 218 // In a tag? 219 if ( !in_array( $word, array_map( 'sanitize_title_with_dashes', $theme['Tags'] ) ) ) 220 return false; 211 if ( false !== stripos( $theme->get_template(), $word ) ) 212 continue; 213 214 return false; 221 215 } 222 216 } 223 217 224 // Only get here if each word exists in the tags or one of the fields225 218 return true; 226 219 } 227 220 } -
wp-admin/includes/ms.php
169 169 return true; 170 170 } 171 171 172 function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {173 $themes = get_themes();174 175 if ( $blog_id != 0 )176 switch_to_blog( $blog_id );177 178 $blog_allowed_themes = get_option( 'allowedthemes' );179 if ( !is_array( $blog_allowed_themes ) || empty( $blog_allowed_themes ) ) { // convert old allowed_themes to new allowedthemes180 $blog_allowed_themes = get_option( 'allowed_themes' );181 182 if ( is_array( $blog_allowed_themes ) ) {183 foreach( (array) $themes as $key => $theme ) {184 $theme_key = esc_html( $theme['Stylesheet'] );185 if ( isset( $blog_allowed_themes[$key] ) == true ) {186 $blog_allowedthemes[$theme_key] = 1;187 }188 }189 $blog_allowed_themes = $blog_allowedthemes;190 add_option( 'allowedthemes', $blog_allowed_themes );191 delete_option( 'allowed_themes' );192 }193 }194 195 if ( $blog_id != 0 )196 restore_current_blog();197 198 return $blog_allowed_themes;199 }200 201 172 function update_option_new_admin_email( $old_value, $value ) { 202 173 $email = get_option( 'admin_email' ); 203 174 if ( $value == get_option( 'admin_email' ) || !is_email( $value ) ) … … 296 267 } 297 268 add_action( 'admin_notices', 'new_user_email_admin_notice' ); 298 269 299 function get_site_allowed_themes() {300 $themes = get_themes();301 $allowed_themes = get_site_option( 'allowedthemes' );302 if ( !is_array( $allowed_themes ) || empty( $allowed_themes ) ) {303 $allowed_themes = get_site_option( 'allowed_themes' ); // convert old allowed_themes format304 if ( !is_array( $allowed_themes ) ) {305 $allowed_themes = array();306 } else {307 foreach( (array) $themes as $key => $theme ) {308 $theme_key = esc_html( $theme['Stylesheet'] );309 if ( isset( $allowed_themes[ $key ] ) == true ) {310 $allowedthemes[ $theme_key ] = 1;311 }312 }313 $allowed_themes = $allowedthemes;314 }315 }316 return $allowed_themes;317 }318 319 270 /** 320 271 * Determines if there is any upload space left in the current blog's quota. 321 272 * -
wp-admin/themes.php
96 96 <h2><?php echo esc_html( $title ); ?> 97 97 <?php endif; ?> 98 98 </h2> 99 100 <h3><?php _e( 'Current Theme'); ?></h3>99 <?php $ct = wp_get_theme(); ?> 100 <h3><?php _e( 'Current Theme' ); ?></h3> 101 101 <div id="current-theme"> 102 <?php if ( $ct-> screenshot) : ?>103 <img src="<?php echo $ct-> theme_root_uri . '/' . $ct->stylesheet . '/' . $ct->screenshot; ?>" alt="<?php esc_attr_e('Current theme preview'); ?>" />102 <?php if ( $ct->get_screenshot() ) : ?> 103 <img src="<?php echo $ct->get_screenshot( 'absolute' ); ?>" alt="<?php esc_attr_e( 'Current theme preview'); ?>" /> 104 104 <?php endif; ?> 105 105 <h4><?php 106 106 /* translators: 1: theme title, 2: theme version, 3: theme author */ 107 printf( __('%1$s %2$s by %3$s'), $ct->title, $ct->version, $ct->author) ; ?></h4>108 <p class="theme-description"><?php echo $ct->d escription; ?></p>107 printf( __( '%1$s %2$s by %3$s' ), $ct->display('Name'), $ct->display('Version'), $ct->display('Author') ) ; ?></h4> 108 <p class="theme-description"><?php echo $ct->display('Description'); ?></p> 109 109 <div class="theme-options"> 110 110 <span><?php _e( 'Options:' )?></span> 111 111 <?php … … 117 117 if ( 'themes.php' == $item[2] || 'theme-editor.php' == $item[2] ) 118 118 continue; 119 119 // 0 = name, 1 = capability, 2 = file 120 if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) ) $class = ' class="current"';121 120 if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) ) 121 $class = ' class="current"'; 122 122 if ( !empty($submenu[$item[2]]) ) { 123 123 $submenu[$item[2]] = array_values($submenu[$item[2]]); // Re-index. 124 124 $menu_hook = get_plugin_page_hook($submenu[$item[2]][0][2], $item[2]); … … 137 137 } 138 138 echo implode ( ' | ', $options ); 139 139 140 if ( $ct-> tags) : ?>141 <p><?php _e('Tags:'); ?> <?php echo join(', ', $ct->tags); ?></p>140 if ( $ct->get('Tags') ) : ?> 141 <p><?php _e('Tags:'); ?> <?php echo $ct->display('Tags'); ?></p> 142 142 <?php endif; ?> 143 143 </div> 144 144 <?php theme_update_available($ct); ?> … … 218 218 219 219 <?php 220 220 // List broken themes, if any. 221 $broken_themes = get_broken_themes(); 222 if ( current_user_can('edit_themes') && count( $broken_themes ) ) { 221 if ( current_user_can('edit_themes') && $broken_themes = wp_get_themes( array( 'errors' => true ) ) ) { 223 222 ?> 224 223 225 224 <h3><?php _e('Broken Themes'); ?></h3> … … 231 230 <th><?php _e('Description'); ?></th> 232 231 </tr> 233 232 <?php 234 $theme = ''; 235 236 $theme_names = array_keys($broken_themes); 237 natcasesort($theme_names); 238 239 foreach ($theme_names as $theme_name) { 240 $name = $broken_themes[$theme_name]['Title']; 241 $description = $broken_themes[$theme_name]['Description']; 242 243 $theme = ('class="alternate"' == $theme) ? '' : 'class="alternate"'; 233 $alt = ''; 234 foreach ( $broken_themes as $broken_theme ) { 235 $alt = ('class="alternate"' == $alt) ? '' : 'class="alternate"'; 244 236 echo " 245 <tr $ theme>246 <td> $name</td>247 <td> $description</td>237 <tr $alt> 238 <td>" . $broken_theme->get('Name') ."</td> 239 <td>" . $broken_theme->errors()->get_error_message() . "</td> 248 240 </tr>"; 249 241 } 250 242 ?> … … 254 246 ?> 255 247 </div> 256 248 257 <?php require('./admin-footer.php'); ?> 249 <?php require('./admin-footer.php'); ?> 250 No newline at end of file
