<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[20029] trunk: Introduce WP_Theme, wp_get_themes(), and wp_get_theme() to replace get_themes(), get_theme(), get_theme_data(), current_theme_info(), and others.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/20029">20029</a></dd>
<dt>Author</dt> <dd>nacin</dd>
<dt>Date</dt> <dd>2012-02-28 21:24:44 +0000 (Tue, 28 Feb 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Introduce WP_Theme, wp_get_themes(), and wp_get_theme() to replace get_themes(), get_theme(), get_theme_data(), current_theme_info(), and others.
 * Getters and Helpers: Introduces a series of methods to allow for easy generation of headers for display, and other theme metadata, including page templates.
 * Screenshots: Handles support for multiple screenshots. (see # Additional screenshots must be PNG and start with screenshot-2.png, and be sequential to be counted. see <a href="http://core.trac.wordpress.org/ticket/19816">#19816</a>.
 * Error Handling: Broken themes have a WP_Error object attached to them.
 * Caching: Introduces a wp_cache_themes_persistently filter (also in <a href="http://core.trac.wordpress.org/changeset/20020">[20020]</a>) to enable persistent caching of all filesystem and sanitization operations normally handled by WP_Theme (and formerly get_file_data() and get_themes()). Themes are cached individually and across five different cache keys for different data pieces.
 * Compatibility: A WP_Theme object is backwards compatible with a theme's array formerly returned by get_themes() and get_theme(), and an stdClass object formerly returned by current_theme_info().
 * i18n/L10n: Theme headers are now localizable with proper Text Domain and Domain Path headers, like plugins. (Language packs may remove the requirement for headers.) For page templates, see <a href="http://core.trac.wordpress.org/ticket/6007">#6007</a> (not fixed yet, but will be easy now). For headers, fixes <a href="http://core.trac.wordpress.org/ticket/15858">#15858</a>.
 * PHP and CSS files: New methods that fetch a list of theme files (for the theme editor) only on demand, rather than only loading them into memory. fixes <a href="http://core.trac.wordpress.org/ticket/11214">#11214</a>.

Functions deprecated:
 * get_themes(), get_allowed_themes() and get_broken_themes() -- use wp_get_themes()
 * get_theme() and current_theme_info() -- use wp_get_theme()
 * get_site_allowed_themes() -- use WP_Theme::get_allowed_on_network()
 * wpmu_get_blog_allowedthemes() -- use WP_theme::get_allowed_on_site()

see also <a href="http://core.trac.wordpress.org/changeset/20016">[20016]</a>, <a href="http://core.trac.wordpress.org/changeset/20018">[20018]</a>, <a href="http://core.trac.wordpress.org/changeset/20019">[20019]</a>, <a href="http://core.trac.wordpress.org/changeset/20020">[20020]</a>, <a href="http://core.trac.wordpress.org/changeset/20021">[20021]</a>, <a href="http://core.trac.wordpress.org/changeset/20022">[20022]</a>, <a href="http://core.trac.wordpress.org/changeset/20025">[20025]</a>, <a href="http://core.trac.wordpress.org/changeset/20026">[20026]</a>, <a href="http://core.trac.wordpress.org/changeset/20027">[20027]</a>. also fixes <a href="http://core.trac.wordpress.org/ticket/19244">#19244</a>.

see <a href="http://core.trac.wordpress.org/ticket/20103">#20103</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminincludesclasswpmsthemeslisttablephp">trunk/wp-admin/includes/class-wp-ms-themes-list-table.php</a></li>
<li><a href="#trunkwpadminincludesclasswpthemeslisttablephp">trunk/wp-admin/includes/class-wp-themes-list-table.php</a></li>
<li><a href="#trunkwpadminincludesdashboardphp">trunk/wp-admin/includes/dashboard.php</a></li>
<li><a href="#trunkwpadminincludesdeprecatedphp">trunk/wp-admin/includes/deprecated.php</a></li>
<li><a href="#trunkwpadminincludesmsdeprecatedphp">trunk/wp-admin/includes/ms-deprecated.php</a></li>
<li><a href="#trunkwpadminincludesmsphp">trunk/wp-admin/includes/ms.php</a></li>
<li><a href="#trunkwpadminincludesschemaphp">trunk/wp-admin/includes/schema.php</a></li>
<li><a href="#trunkwpadminincludesthemeinstallphp">trunk/wp-admin/includes/theme-install.php</a></li>
<li><a href="#trunkwpadminincludesthemephp">trunk/wp-admin/includes/theme.php</a></li>
<li><a href="#trunkwpadminincludesupdatephp">trunk/wp-admin/includes/update.php</a></li>
<li><a href="#trunkwpadminthemesphp">trunk/wp-admin/themes.php</a></li>
<li><a href="#trunkwpincludesclasswpcustomizephp">trunk/wp-includes/class-wp-customize.php</a></li>
<li><a href="#trunkwpincludesdeprecatedphp">trunk/wp-includes/deprecated.php</a></li>
<li><a href="#trunkwpincludesthemephp">trunk/wp-includes/theme.php</a></li>
<li><a href="#trunkwpincludesupdatephp">trunk/wp-includes/update.php</a></li>
<li><a href="#trunkwpsettingsphp">trunk/wp-settings.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkwpincludesclasswpthemephp">trunk/wp-includes/class-wp-theme.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminincludesclasswpmsthemeslisttablephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/class-wp-ms-themes-list-table.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/class-wp-ms-themes-list-table.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/class-wp-ms-themes-list-table.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -50,53 +50,41 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         function prepare_items() {
</span><del>-                global $status, $themes, $totals, $page, $orderby, $order, $s;
</del><ins>+                global $status, $totals, $page, $orderby, $order, $s;
</ins><span class="cx"> 
</span><span class="cx">                 wp_reset_vars( array( 'orderby', 'order', 's' ) );
</span><span class="cx"> 
</span><span class="cx">                 $themes = array(
</span><del>-                        'all' =&gt; apply_filters( 'all_themes', get_themes() ),
</del><ins>+                        'all' =&gt; apply_filters( 'all_themes', wp_get_themes() ),
</ins><span class="cx">                         'search' =&gt; array(),
</span><span class="cx">                         'enabled' =&gt; array(),
</span><span class="cx">                         'disabled' =&gt; array(),
</span><span class="cx">                         'upgrade' =&gt; array()
</span><span class="cx">                 );
</span><span class="cx"> 
</span><del>-                $site_allowed_themes = get_site_allowed_themes();
-                if ( !$this-&gt;is_site_themes ) {
-                        $allowed_themes = $site_allowed_themes;
</del><ins>+                if ( $this-&gt;is_site_themes ) {
+                        $themes_per_page = $this-&gt;get_items_per_page( 'site_themes_network_per_page' );
+                        $allowed_where = 'site';
+                } else {
</ins><span class="cx">                         $themes_per_page = $this-&gt;get_items_per_page( 'themes_network_per_page' );
</span><del>-                } else {
-                        $allowed_themes = wpmu_get_blog_allowedthemes( $this-&gt;site_id );
-                        $themes_per_page = $this-&gt;get_items_per_page( 'site_themes_network_per_page' );
</del><ins>+                        $allowed_where = 'network';
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                $current = get_site_transient( 'update_themes' );
</del><ins>+                $current = current_user_can( 'update_themes' ) &amp;&amp; ! $this-&gt;is_site_themes &amp;&amp; get_site_transient( 'update_themes' );
</ins><span class="cx"> 
</span><span class="cx">                 foreach ( (array) $themes['all'] as $key =&gt; $theme ) {
</span><del>-                        $theme_key = $theme['Stylesheet'];
-
-                        if ( isset( $allowed_themes [ $theme_key ] ) )  {
-                                $themes['all'][$key]['enabled'] = true;
-                                $themes['enabled'][$key] = $themes['all'][$key];
</del><ins>+                        if ( $this-&gt;is_site_themes &amp;&amp; $theme-&gt;is_allowed( 'network' ) ) {
+                                unset( $themes['all'][ $key ] );
+                                continue;
</ins><span class="cx">                         }
</span><del>-                        else {
-                                $themes['all'][$key]['enabled'] = false;
-                                $themes['disabled'][$key] = $themes['all'][$key];
-                        }
-                        if ( isset( $current-&gt;response[ $theme['Template'] ] ) )
-                                $themes['upgrade'][$key] = $themes['all'][$key];
</del><span class="cx"> 
</span><del>-                        if ( $this-&gt;is_site_themes &amp;&amp; isset( $site_allowed_themes[$theme_key] ) ) {
-                                unset( $themes['all'][$key] );
-                                unset( $themes['enabled'][$key] );
-                                unset( $themes['disabled'][$key] );
-                        }
</del><ins>+                        $filter = $theme-&gt;is_allowed( $allowed_where, $this-&gt;site_id ) ? 'enabled' : 'disabled';
+                        $themes[ $filter ][ $key ] = $themes['all'][ $key ];
+
+                        if ( $current &amp;&amp; isset( $current-&gt;response[ $key ] ) )
+                                $themes['upgrade'][ $key ] = $themes['all'][ $key ];
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if ( !current_user_can( 'update_themes' ) || $this-&gt;is_site_themes )
-                        $themes['upgrade'] = array();
-
</del><span class="cx">                 if ( $s ) {
</span><span class="cx">                         $status = 'search';
</span><span class="cx">                         $themes['search'] = array_filter( $themes['all'], array( &amp;$this, '_search_callback' ) );
</span><span class="lines">@@ -110,19 +98,27 @@
</span><span class="cx">                         $status = 'all';
</span><span class="cx"> 
</span><span class="cx">                 $this-&gt;items = $themes[ $status ];
</span><ins>+                WP_Theme::sort_by_name( $this-&gt;items );
+
+                $this-&gt;has_items = ! empty( $themes['all'] );
</ins><span class="cx">                 $total_this_page = $totals[ $status ];
</span><span class="cx"> 
</span><span class="cx">                 if ( $orderby ) {
</span><span class="cx">                         $orderby = ucfirst( $orderby );
</span><span class="cx">                         $order = strtoupper( $order );
</span><span class="cx"> 
</span><del>-                        uasort( $this-&gt;items, array( &amp;$this, '_order_callback' ) );
</del><ins>+                        if ( $orderby == 'Name' ) {
+                                if ( 'ASC' == $order )
+                                        $this-&gt;items = array_reverse( $this-&gt;items );
+                        } else {
+                                uasort( $this-&gt;items, array( &amp;$this, '_order_callback' ) );
+                        }
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 $start = ( $page - 1 ) * $themes_per_page;
</span><span class="cx"> 
</span><span class="cx">                 if ( $total_this_page &gt; $themes_per_page )
</span><del>-                        $this-&gt;items = array_slice( $this-&gt;items, $start, $themes_per_page );
</del><ins>+                        $this-&gt;items = array_slice( $this-&gt;items, $start, $themes_per_page, true );
</ins><span class="cx"> 
</span><span class="cx">                 $this-&gt;set_pagination_args( array(
</span><span class="cx">                         'total_items' =&gt; $total_this_page,
</span><span class="lines">@@ -135,19 +131,27 @@
</span><span class="cx">                 if ( is_null( $term ) )
</span><span class="cx">                         $term = stripslashes( $_REQUEST['s'] );
</span><span class="cx"> 
</span><del>-                $search_fields = array( 'Name', 'Title', 'Description', 'Author', 'Author Name', 'Author URI', 'Template', 'Stylesheet' );
-                foreach ( $search_fields as $field )
-                        if ( stripos( $theme[ $field ], $term ) !== false )
</del><ins>+                foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
+                        // Don't mark up; Do translate.
+                        if ( false !== stripos( $theme-&gt;display( $field, false, true ), $term ) )
</ins><span class="cx">                                 return true;
</span><ins>+                }
</ins><span class="cx"> 
</span><ins>+                if ( false !== stripos( $theme-&gt;get_stylesheet(), $term ) )
+                        return true;
+
+                if ( false !== stripos( $theme-&gt;get_template(), $term ) )
+                        return true;
+
</ins><span class="cx">                 return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        // Not used by any core columns.
</ins><span class="cx">         function _order_callback( $theme_a, $theme_b ) {
</span><span class="cx">                 global $orderby, $order;
</span><span class="cx"> 
</span><del>-                $a = $theme_a[$orderby];
-                $b = $theme_b[$orderby];
</del><ins>+                $a = $theme_a[ $orderby ];
+                $b = $theme_b[ $orderby ];
</ins><span class="cx"> 
</span><span class="cx">                 if ( $a == $b )
</span><span class="cx">                         return 0;
</span><span class="lines">@@ -159,9 +163,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         function no_items() {
</span><del>-                global $themes;
-
-                if ( !empty( $themes['all'] ) )
</del><ins>+                if ( ! $$this-&gt;has_items )
</ins><span class="cx">                         _e( 'No themes found.' );
</span><span class="cx">                 else
</span><span class="cx">                         _e( 'You do not appear to have any themes available at this time.' );
</span><span class="lines">@@ -259,10 +261,13 @@
</span><span class="cx"> 
</span><span class="cx">                 $context = $status;
</span><span class="cx"> 
</span><del>-                if ( $this-&gt;is_site_themes )
</del><ins>+                if ( $this-&gt;is_site_themes ) {
</ins><span class="cx">                         $url = &quot;site-themes.php?id={$this-&gt;site_id}&amp;amp;&quot;;
</span><del>-                else
</del><ins>+                        $allowed = $theme-&gt;is_allowed( 'site', $this-&gt;site_id );
+                } else {
</ins><span class="cx">                         $url = 'themes.php?';
</span><ins>+                        $allowed = $theme-&gt;is_allowed( 'network' );
+                }
</ins><span class="cx"> 
</span><span class="cx">                 // preorder
</span><span class="cx">                 $actions = array(
</span><span class="lines">@@ -272,30 +277,29 @@
</span><span class="cx">                         'delete' =&gt; ''
</span><span class="cx">                 );
</span><span class="cx"> 
</span><del>-                $theme_key = $theme['Stylesheet'];
</del><ins>+                $theme_key = $theme-&gt;get_stylesheet();
</ins><span class="cx"> 
</span><del>-                if ( empty( $theme['enabled'] ) )
</del><ins>+                if ( ! $allowed )
</ins><span class="cx">                         $actions['enable'] = '&lt;a href=&quot;' . esc_url( wp_nonce_url($url . 'action=enable&amp;amp;theme=' . $theme_key . '&amp;amp;paged=' . $page . '&amp;amp;s=' . $s, 'enable-theme_' . $theme_key) ) . '&quot; title=&quot;' . esc_attr__('Enable this theme') . '&quot; class=&quot;edit&quot;&gt;' . ( $this-&gt;is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . '&lt;/a&gt;';
</span><span class="cx">                 else
</span><span class="cx">                         $actions['disable'] = '&lt;a href=&quot;' . esc_url( wp_nonce_url($url . 'action=disable&amp;amp;theme=' . $theme_key . '&amp;amp;paged=' . $page . '&amp;amp;s=' . $s, 'disable-theme_' . $theme_key) ) . '&quot; title=&quot;' . esc_attr__('Disable this theme') . '&quot;&gt;' . ( $this-&gt;is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . '&lt;/a&gt;';
</span><span class="cx"> 
</span><span class="cx">                 if ( current_user_can('edit_themes') )
</span><del>-                        $actions['edit'] = '&lt;a href=&quot;' . esc_url('theme-editor.php?theme=' . urlencode( $theme['Name'] )) . '&quot; title=&quot;' . esc_attr__('Open this theme in the Theme Editor') . '&quot; class=&quot;edit&quot;&gt;' . __('Edit') . '&lt;/a&gt;';
</del><ins>+                        $actions['edit'] = '&lt;a href=&quot;' . esc_url('theme-editor.php?theme=' .  $theme_key ) . '&quot; title=&quot;' . esc_attr__('Open this theme in the Theme Editor') . '&quot; class=&quot;edit&quot;&gt;' . __('Edit') . '&lt;/a&gt;';
</ins><span class="cx"> 
</span><del>-                if ( empty( $theme['enabled'] ) &amp;&amp; current_user_can( 'delete_themes' ) &amp;&amp; ! $this-&gt;is_site_themes &amp;&amp; $theme_key != get_option( 'stylesheet' ) &amp;&amp; $theme_key != get_option( 'template' ) )
</del><ins>+                if ( ! $allowed &amp;&amp; current_user_can( 'delete_themes' ) &amp;&amp; ! $this-&gt;is_site_themes &amp;&amp; $theme_key != get_option( 'stylesheet' ) &amp;&amp; $theme_key != get_option( 'template' ) )
</ins><span class="cx">                         $actions['delete'] = '&lt;a href=&quot;' . esc_url( wp_nonce_url( 'themes.php?action=delete-selected&amp;amp;checked[]=' . $theme_key . '&amp;amp;theme_status=' . $context . '&amp;amp;paged=' . $page . '&amp;amp;s=' . $s, 'bulk-themes' ) ) . '&quot; title=&quot;' . esc_attr__( 'Delete this theme' ) . '&quot; class=&quot;delete&quot;&gt;' . __( 'Delete' ) . '&lt;/a&gt;';
</span><span class="cx"> 
</span><span class="cx">                 $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme_key, $theme, $context );
</span><span class="cx">                 $actions = apply_filters( &quot;theme_action_links_$theme_key&quot;, $actions, $theme_key, $theme, $context );
</span><span class="cx"> 
</span><del>-                $class = empty( $theme['enabled'] ) ? 'inactive' : 'active';
-                $checkbox_id = &quot;checkbox_&quot; . md5($theme['Name']);
-                $checkbox = &quot;&lt;input type='checkbox' name='checked[]' value='&quot; . esc_attr( $theme_key ) . &quot;' id='&quot; . $checkbox_id . &quot;' /&gt;&lt;label class='screen-reader-text' for='&quot; . $checkbox_id . &quot;' &gt;&quot; . __('Select') . &quot; &quot; . $theme['Name'] . &quot;&lt;/label&gt;&quot;;
</del><ins>+                $class = ! $allowed ? 'inactive' : 'active';
+                $checkbox_id = &quot;checkbox_&quot; . md5( $theme-&gt;get('Name') );
+                $checkbox = &quot;&lt;input type='checkbox' name='checked[]' value='&quot; . esc_attr( $theme_key ) . &quot;' id='&quot; . $checkbox_id . &quot;' /&gt;&lt;label class='screen-reader-text' for='&quot; . $checkbox_id . &quot;' &gt;&quot; . __('Select') . &quot; &quot; . $theme-&gt;display('Name') . &quot;&lt;/label&gt;&quot;;
</ins><span class="cx"> 
</span><del>-                $description = '&lt;p&gt;' . $theme['Description'] . '&lt;/p&gt;';
-                $theme_name = $theme['Name'];
</del><ins>+                $description = '&lt;p&gt;' . $theme-&gt;display( 'Description' ) . '&lt;/p&gt;';
</ins><span class="cx"> 
</span><del>-                $id = sanitize_title( $theme_name );
</del><ins>+                $id = sanitize_html_class( $theme-&gt;get_stylesheet() );
</ins><span class="cx"> 
</span><span class="cx">                 echo &quot;&lt;tr id='$id' class='$class'&gt;&quot;;
</span><span class="cx"> 
</span><span class="lines">@@ -311,25 +315,25 @@
</span><span class="cx">                                         echo &quot;&lt;th scope='row' class='check-column'&gt;$checkbox&lt;/th&gt;&quot;;
</span><span class="cx">                                         break;
</span><span class="cx">                                 case 'name':
</span><del>-                                        echo &quot;&lt;td class='theme-title'$style&gt;&lt;strong&gt;$theme_name&lt;/strong&gt;&quot;;
</del><ins>+                                        echo &quot;&lt;td class='theme-title'$style&gt;&lt;strong&gt;&quot; . $theme-&gt;display('Name') . &quot;&lt;/strong&gt;&quot;;
</ins><span class="cx">                                         echo $this-&gt;row_actions( $actions, true );
</span><span class="cx">                                         echo &quot;&lt;/td&gt;&quot;;
</span><span class="cx">                                         break;
</span><span class="cx">                                 case 'description':
</span><span class="cx">                                         echo &quot;&lt;td class='column-description desc'$style&gt;
</span><del>-                                                &lt;div class='theme-description'&gt;$description&lt;/div&gt;
</del><ins>+                                                &lt;div class='theme-description'&gt;&quot; . $theme-&gt;display( 'Description' ) . &quot;&lt;/div&gt;
</ins><span class="cx">                                                 &lt;div class='$class second theme-version-author-uri'&gt;&quot;;
</span><span class="cx"> 
</span><span class="cx">                                         $theme_meta = array();
</span><span class="cx"> 
</span><del>-                                        if ( !empty( $theme['Version'] ) )
-                                                $theme_meta[] = sprintf( __( 'Version %s' ), $theme['Version'] );
</del><ins>+                                        if ( $theme-&gt;get('Version') )
+                                                $theme_meta[] = sprintf( __( 'Version %s' ), $theme-&gt;display('Version') );
</ins><span class="cx"> 
</span><del>-                                        if ( !empty( $theme['Author'] ) )
-                                                $theme_meta[] = sprintf( __( 'By %s' ), $theme['Author'] );
</del><ins>+                                        if ( $theme-&gt;get('Author') )
+                                                $theme_meta[] = sprintf( __( 'By %s' ), $theme-&gt;display('Author') );
</ins><span class="cx"> 
</span><del>-                                        if ( !empty( $theme['Theme URI'] ) )
-                                                $theme_meta[] = '&lt;a href=&quot;' . $theme['Theme URI'] . '&quot; title=&quot;' . esc_attr__( 'Visit theme homepage' ) . '&quot;&gt;' . __( 'Visit Theme Site' ) . '&lt;/a&gt;';
</del><ins>+                                        if ( $theme-&gt;get('ThemeURI') )
+                                                $theme_meta[] = '&lt;a href=&quot;' . $theme-&gt;display('ThemeURI') . '&quot; title=&quot;' . esc_attr__( 'Visit theme homepage' ) . '&quot;&gt;' . __( 'Visit Theme Site' ) . '&lt;/a&gt;';
</ins><span class="cx"> 
</span><span class="cx">                                         $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $theme_key, $theme, $status );
</span><span class="cx">                                         echo implode( ' | ', $theme_meta );
</span></span></pre></div>
<a id="trunkwpadminincludesclasswpthemeslisttablephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/class-wp-themes-list-table.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/class-wp-themes-list-table.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/class-wp-themes-list-table.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -24,12 +24,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         function prepare_items() {
</span><del>-                global $ct;
</del><ins>+                $themes = wp_get_themes( array( 'allowed' =&gt; true ) );
</ins><span class="cx"> 
</span><del>-                $ct = current_theme_info();
-
-                $themes = get_allowed_themes();
-
</del><span class="cx">                 if ( ! empty( $_REQUEST['s'] ) ) {
</span><span class="cx">                         $search = strtolower( stripslashes( $_REQUEST['s'] ) );
</span><span class="cx">                         $this-&gt;search = array_merge( $this-&gt;search, array_filter( array_map( 'trim', explode( ',', $search ) ) ) );
</span><span class="lines">@@ -45,13 +41,13 @@
</span><span class="cx"> 
</span><span class="cx">                 if ( $this-&gt;search || $this-&gt;features ) {
</span><span class="cx">                         foreach ( $themes as $key =&gt; $theme ) {
</span><del>-                                if ( !$this-&gt;search_theme( $theme ) )
</del><ins>+                                if ( ! $this-&gt;search_theme( $theme ) )
</ins><span class="cx">                                         unset( $themes[ $key ] );
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                unset( $themes[$ct-&gt;name] );
-                uksort( $themes, &quot;strnatcasecmp&quot; );
</del><ins>+                unset( $themes[ get_option( 'stylesheet' ) ] );
+                WP_Theme::sort_by_name( $themes );
</ins><span class="cx"> 
</span><span class="cx">                 $per_page = 999;
</span><span class="cx">                 $page = $this-&gt;get_pagenum();
</span><span class="lines">@@ -125,75 +121,74 @@
</span><span class="cx"> 
</span><span class="cx">         function display_rows() {
</span><span class="cx">                 $themes = $this-&gt;items;
</span><del>-                $theme_names = array_keys( $themes );
-                natcasesort( $theme_names );
</del><span class="cx"> 
</span><del>-        foreach ( $theme_names as $theme_name ) {
-                $class = array( 'available-theme' );
-        ?&gt;
-        &lt;div class=&quot;&lt;?php echo join( ' ', $class ); ?&gt;&quot;&gt;
-        &lt;?php if ( !empty( $theme_name ) ) :
-        $template = $themes[$theme_name]['Template'];
-        $stylesheet = $themes[$theme_name]['Stylesheet'];
-        $title = $themes[$theme_name]['Title'];
-        $version = $themes[$theme_name]['Version'];
-        $description = $themes[$theme_name]['Description'];
-        $author = $themes[$theme_name]['Author'];
-        $screenshot = $themes[$theme_name]['Screenshot'];
-        $stylesheet_dir = $themes[$theme_name]['Stylesheet Dir'];
-        $template_dir = $themes[$theme_name]['Template Dir'];
-        $parent_theme = $themes[$theme_name]['Parent Theme'];
-        $theme_root = $themes[$theme_name]['Theme Root'];
-        $theme_root_uri = $themes[$theme_name]['Theme Root URI'];
-        $preview_link = esc_url( add_query_arg( array( 'preview' =&gt; 1, 'template' =&gt; $template, 'stylesheet' =&gt; $stylesheet, 'preview_iframe' =&gt; true, 'TB_iframe' =&gt; 'true' ), home_url( '/' ) ) );
-        $preview_text = esc_attr( sprintf( __( 'Preview of &amp;#8220;%s&amp;#8221;' ), $title ) );
-        $tags = $themes[$theme_name]['Tags'];
-        $thickbox_class = 'thickbox thickbox-preview';
-        $activate_link = wp_nonce_url( &quot;themes.php?action=activate&amp;amp;template=&quot; . urlencode( $template ) . &quot;&amp;amp;stylesheet=&quot; . urlencode( $stylesheet ), 'switch-theme_' . $template );
-        $activate_text = esc_attr( sprintf( __( 'Activate &amp;#8220;%s&amp;#8221;' ), $title ) );
-        $actions = array();
-        $actions[] = '&lt;a href=&quot;' . $activate_link . '&quot; class=&quot;activatelink&quot; title=&quot;' . $activate_text . '&quot;&gt;' . __( 'Activate' ) . '&lt;/a&gt;';
-        $actions[] = '&lt;a href=&quot;' . $preview_link . '&quot; class=&quot;thickbox thickbox-preview&quot; title=&quot;' . esc_attr( sprintf( __( 'Preview &amp;#8220;%s&amp;#8221;' ), $theme_name ) ) . '&quot;&gt;' . __( 'Preview' ) . '&lt;/a&gt;';
-        if ( ! is_multisite() &amp;&amp; current_user_can( 'delete_themes' ) )
-                $actions[] = '&lt;a class=&quot;submitdelete deletion&quot; href=&quot;' . wp_nonce_url( &quot;themes.php?action=delete&amp;amp;template=$stylesheet&quot;, 'delete-theme_' . $stylesheet ) . '&quot; onclick=&quot;' . &quot;return confirm( '&quot; . esc_js( sprintf( __( &quot;You are about to delete this theme '%s'\n  'Cancel' to stop, 'OK' to delete.&quot; ), $theme_name ) ) . &quot;' );&quot; . '&quot;&gt;' . __( 'Delete' ) . '&lt;/a&gt;';
-        $actions = apply_filters( 'theme_action_links', $actions, $themes[$theme_name] );
</del><ins>+                foreach ( $themes as $theme ) {
+                        echo '&lt;div class=&quot;available-theme&quot;&gt;';
</ins><span class="cx"> 
</span><del>-        $actions = implode ( ' | ', $actions );
-?&gt;
-                &lt;a href=&quot;&lt;?php echo $preview_link; ?&gt;&quot; class=&quot;&lt;?php echo $thickbox_class; ?&gt; screenshot&quot;&gt;
-&lt;?php if ( $screenshot ) : ?&gt;
-                        &lt;img src=&quot;&lt;?php echo $theme_root_uri . '/' . $stylesheet . '/' . $screenshot; ?&gt;&quot; alt=&quot;&quot; /&gt;
-&lt;?php endif; ?&gt;
-                &lt;/a&gt;
-&lt;h3&gt;&lt;?php
-        /* translators: 1: theme title, 2: theme version, 3: theme author */
-        printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?&gt;&lt;/h3&gt;
</del><ins>+                        $template = $theme-&gt;get_template();
+                        $stylesheet = $theme-&gt;get_stylesheet();
</ins><span class="cx"> 
</span><del>-&lt;span class='action-links'&gt;&lt;?php echo $actions ?&gt;&lt;/span&gt;
-&lt;span class=&quot;separator hide-if-no-js&quot;&gt;| &lt;/span&gt;&lt;a href=&quot;#&quot; class=&quot;theme-detail hide-if-no-js&quot; tabindex='4'&gt;&lt;?php _e('Details') ?&gt;&lt;/a&gt;
-&lt;div class=&quot;themedetaildiv hide-if-js&quot;&gt;
-&lt;p&gt;&lt;?php echo $description; ?&gt;&lt;/p&gt;
-        &lt;?php if ( current_user_can( 'edit_themes' ) &amp;&amp; $parent_theme ) {
-        /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?&gt;
-        &lt;p&gt;&lt;?php printf( __( 'The template files are located in &lt;code&gt;%2$s&lt;/code&gt;. The stylesheet files are located in &lt;code&gt;%3$s&lt;/code&gt;. &lt;strong&gt;%4$s&lt;/strong&gt; uses templates from &lt;strong&gt;%5$s&lt;/strong&gt;. 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 ); ?&gt;&lt;/p&gt;
-&lt;?php } else { ?&gt;
-        &lt;p&gt;&lt;?php printf( __( 'All of this theme&amp;#8217;s files are located in &lt;code&gt;%2$s&lt;/code&gt;.' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ); ?&gt;&lt;/p&gt;
-&lt;?php } ?&gt;
-&lt;?php if ( $tags ) : ?&gt;
-&lt;p&gt;&lt;?php _e( 'Tags:' ); ?&gt; &lt;?php echo join( ', ', $tags ); ?&gt;&lt;/p&gt;
-&lt;?php endif; ?&gt;
-&lt;?php endif; // end if not empty theme_name ?&gt;
-&lt;/div&gt;
-        &lt;?php theme_update_available( $themes[$theme_name] ); ?&gt;
-        &lt;/div&gt;
-&lt;?php } // end foreach $theme_names
</del><ins>+                        $title = $theme-&gt;display('Name');
+                        $version = $theme-&gt;display('Version');
+                        $author = $theme-&gt;display('Author');

+                        $activate_link = wp_nonce_url( &quot;themes.php?action=activate&amp;amp;template=&quot; . urlencode( $template ) . &quot;&amp;amp;stylesheet=&quot; . urlencode( $stylesheet ), 'switch-theme_' . $template );
+                        $preview_link = esc_url( add_query_arg(
+                                array( 'preview' =&gt; 1, 'template' =&gt; $template, 'stylesheet' =&gt; $stylesheet, 'preview_iframe' =&gt; true, 'TB_iframe' =&gt; 'true' ),
+                                home_url( '/' ) ) );

+                        $actions = array();
+                        $actions[] = '&lt;a href=&quot;' . $activate_link . '&quot; class=&quot;activatelink&quot; title=&quot;'
+                                . esc_attr( sprintf( __( 'Activate &amp;#8220;%s&amp;#8221;' ), $title ) ) . '&quot;&gt;' . __( 'Activate' ) . '&lt;/a&gt;';
+                        $actions[] = '&lt;a href=&quot;' . $preview_link . '&quot; class=&quot;thickbox thickbox-preview&quot; title=&quot;'
+                                . esc_attr( sprintf( __( 'Preview &amp;#8220;%s&amp;#8221;' ), $title ) ) . '&quot;&gt;' . __( 'Preview' ) . '&lt;/a&gt;';
+                        if ( ! is_multisite() &amp;&amp; current_user_can( 'delete_themes' ) )
+                                $actions[] = '&lt;a class=&quot;submitdelete deletion&quot; href=&quot;' . wp_nonce_url( &quot;themes.php?action=delete&amp;amp;template=$stylesheet&quot;, 'delete-theme_' . $stylesheet )
+                                        . '&quot; onclick=&quot;' . &quot;return confirm( '&quot; . esc_js( sprintf( __( &quot;You are about to delete this theme '%s'\n  'Cancel' to stop, 'OK' to delete.&quot; ), $title ) )
+                                        . &quot;' );&quot; . '&quot;&gt;' . __( 'Delete' ) . '&lt;/a&gt;';

+                        $actions = apply_filters( 'theme_action_links', $actions, $theme );

+                        $actions = implode ( ' | ', $actions );
+                        ?&gt;
+                        &lt;a href=&quot;&lt;?php echo $preview_link; ?&gt;&quot; class=&quot;thickbox thickbox-preview screenshot&quot;&gt;
+                        &lt;?php if ( $theme-&gt;get_screenshot() ) : ?&gt;
+                                &lt;img src=&quot;&lt;?php echo esc_url( $theme-&gt;get_screenshot( 'absolute' ) ); ?&gt;&quot; alt=&quot;&quot; /&gt;
+                        &lt;?php endif; ?&gt;
+                        &lt;/a&gt;
+                        &lt;h3&gt;&lt;?php
+                        /* translators: 1: theme title, 2: theme version, 3: theme author */
+                        printf( __( '%1$s %2$s by %3$s' ), $title, $version, $author ) ; ?&gt;&lt;/h3&gt;

+                        &lt;span class='action-links'&gt;&lt;?php echo $actions ?&gt;&lt;/span&gt;
+                        &lt;span class=&quot;separator hide-if-no-js&quot;&gt;| &lt;/span&gt;&lt;a href=&quot;#&quot; class=&quot;theme-detail hide-if-no-js&quot; tabindex='4'&gt;&lt;?php _e('Details') ?&gt;&lt;/a&gt;
+                        &lt;div class=&quot;themedetaildiv hide-if-js&quot;&gt;
+                        &lt;p&gt;&lt;?php echo $theme-&gt;display('Description'); ?&gt;&lt;/p&gt;
+                        &lt;?php if ( current_user_can( 'edit_themes' ) &amp;&amp; $theme-&gt;parent() ) :
+                                /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir, 4: theme title, 5: parent_theme */ ?&gt;
+                                &lt;p&gt;&lt;?php printf( __( 'The template files are located in &lt;code&gt;%2$s&lt;/code&gt;. The stylesheet files are located in &lt;code&gt;%3$s&lt;/code&gt;. &lt;strong&gt;%4$s&lt;/strong&gt; uses templates from &lt;strong&gt;%5$s&lt;/strong&gt;. Changes made to the templates will affect both themes.' ),
+                                        $title, str_replace( WP_CONTENT_DIR, '', $theme-&gt;get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme-&gt;get_stylesheet_directory() ), $title, $theme-&gt;parent()-&gt;display('Name') ); ?&gt;&lt;/p&gt;
+                        &lt;?php else :
+                                        /* translators: 1: theme title, 2:  template dir, 3: stylesheet_dir */ ?&gt;
+                                &lt;p&gt;&lt;?php printf( __( 'All of this theme&amp;#8217;s files are located in &lt;code&gt;%2$s&lt;/code&gt;.' ),
+                                        $title, str_replace( WP_CONTENT_DIR, '', $theme-&gt;get_template_directory() ), str_replace( WP_CONTENT_DIR, '', $theme-&gt;get_stylesheet_directory() ) ); ?&gt;&lt;/p&gt;
+                        &lt;?php endif; ?&gt;
+                        &lt;?php
+                        if ( $theme-&gt;get('Tags') )
+                                printf( '&lt;p&gt;' . __( 'Tags: %s.' ) . '&lt;/p&gt;', $theme-&gt;display('Tags') );
+                        ?&gt;
+                        &lt;/div&gt;
+                        &lt;?php theme_update_available( $theme ); ?&gt;
+                        &lt;/div&gt;
+                &lt;?php
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         function search_theme( $theme ) {
</span><span class="cx">                 // Search the features
</span><span class="cx">                 if ( $this-&gt;features ) {
</span><span class="cx">                         foreach ( $this-&gt;features as $word ) {
</span><del>-                                if ( ! in_array( $word, $theme['Tags'] ) )
</del><ins>+                                if ( ! in_array( $word, $theme-&gt;get('Tags') ) )
</ins><span class="cx">                                         return false;
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="lines">@@ -201,16 +196,23 @@
</span><span class="cx">                 // Match all phrases
</span><span class="cx">                 if ( $this-&gt;search ) {
</span><span class="cx">                         foreach ( $this-&gt;search as $word ) {
</span><del>-                                if ( in_array( $word, $theme['Tags'] ) )
</del><ins>+                                if ( in_array( $word, $theme-&gt;get('Tags') ) )
</ins><span class="cx">                                         continue;
</span><del>-                        }
</del><span class="cx"> 
</span><del>-                        foreach ( array( 'Name', 'Title', 'Description', 'Author', 'Template', 'Stylesheet' ) as $header ) {
-                                if ( false !== stripos( $theme[ $header ], $word ) )
-                                        continue 2;
</del><ins>+                                foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) {
+                                        // Don't mark up; Do translate.
+                                        if ( false !== stripos( $theme-&gt;display( $header, false, true ), $word ) )
+                                                continue 2;
+                                }
+
+                                if ( false !== stripos( $theme-&gt;get_stylesheet(), $word ) )
+                                        continue;
+
+                                if ( false !== stripos( $theme-&gt;get_template(), $word ) )
+                                        continue;

+                                return false;
</ins><span class="cx">                         }
</span><del>-
-                        return false;
</del><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 return true;
</span></span></pre></div>
<a id="trunkwpadminincludesdashboardphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/dashboard.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/dashboard.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/dashboard.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -383,11 +383,11 @@
</span><span class="cx">         echo &quot;\n\t&lt;/table&gt;\n\t&lt;/div&gt;&quot;;
</span><span class="cx"> 
</span><span class="cx">         echo &quot;\n\t&quot;.'&lt;div class=&quot;versions&quot;&gt;';
</span><del>-        $ct = current_theme_info();
</del><ins>+        $theme = wp_get_theme();
</ins><span class="cx"> 
</span><span class="cx">         echo &quot;\n\t&lt;p&gt;&quot;;
</span><span class="cx"> 
</span><del>-        if ( empty( $ct-&gt;stylesheet_dir ) ) {
</del><ins>+        if ( $theme-&gt;errors() ) {
</ins><span class="cx">                 if ( ! is_multisite() || is_super_admin() )
</span><span class="cx">                         echo '&lt;span class=&quot;error-message&quot;&gt;' . __('ERROR: The themes directory is either empty or doesn&amp;#8217;t exist. Please check your installation.') . '&lt;/span&gt;';
</span><span class="cx">         } elseif ( ! empty($wp_registered_sidebars) ) {
</span><span class="lines">@@ -401,7 +401,7 @@
</span><span class="cx">                 }
</span><span class="cx">                 $num = number_format_i18n( $num_widgets );
</span><span class="cx"> 
</span><del>-                $switch_themes = $ct-&gt;title;
</del><ins>+                $switch_themes = $theme-&gt;display('Name');
</ins><span class="cx">                 if ( current_user_can( 'switch_themes') )
</span><span class="cx">                         $switch_themes = '&lt;a href=&quot;themes.php&quot;&gt;' . $switch_themes . '&lt;/a&gt;';
</span><span class="cx">                 if ( current_user_can( 'edit_theme_options' ) ) {
</span><span class="lines">@@ -411,9 +411,9 @@
</span><span class="cx">                 }
</span><span class="cx">         } else {
</span><span class="cx">                 if ( current_user_can( 'switch_themes' ) )
</span><del>-                        printf( __('Theme &lt;span class=&quot;b&quot;&gt;&lt;a href=&quot;themes.php&quot;&gt;%1$s&lt;/a&gt;&lt;/span&gt;'), $ct-&gt;title );
</del><ins>+                        printf( __('Theme &lt;span class=&quot;b&quot;&gt;&lt;a href=&quot;themes.php&quot;&gt;%1$s&lt;/a&gt;&lt;/span&gt;'), $theme-&gt;display('Name') );
</ins><span class="cx">                 else
</span><del>-                        printf( __('Theme &lt;span class=&quot;b&quot;&gt;%1$s&lt;/span&gt;'), $ct-&gt;title );
</del><ins>+                        printf( __('Theme &lt;span class=&quot;b&quot;&gt;%1$s&lt;/span&gt;'), $theme-&gt;display('Name') );
</ins><span class="cx">         }
</span><span class="cx">         echo '&lt;/p&gt;';
</span><span class="cx"> 
</span><span class="lines">@@ -1313,14 +1313,14 @@
</span><span class="cx">         &lt;div class=&quot;welcome-panel-column welcome-panel-last&quot;&gt;
</span><span class="cx">                 &lt;h4&gt;&lt;span class=&quot;icon16 icon-appearance&quot;&gt;&lt;/span&gt; &lt;?php _e( 'Customize Your Site' ); ?&gt;&lt;/h4&gt;
</span><span class="cx">                 &lt;?php
</span><del>-                $ct = current_theme_info();
-                if ( empty ( $ct-&gt;stylesheet_dir ) ) :
</del><ins>+                $theme = wp_get_theme();
+                if ( $theme-&gt;errors() ) :
</ins><span class="cx">                         echo '&lt;p&gt;';
</span><span class="cx">                         printf( __( '&lt;a href=&quot;%s&quot;&gt;Install a theme&lt;/a&gt; to get started customizing your site.' ), esc_url( admin_url( 'themes.php' ) ) );
</span><span class="cx">                         echo '&lt;/p&gt;';
</span><span class="cx">                 else:
</span><span class="cx">                         $customize_links = array();
</span><del>-                        if ( 'twentyeleven' == $ct-&gt;stylesheet )
</del><ins>+                        if ( 'twentyeleven' == $theme-&gt;get_stylesheet() )
</ins><span class="cx">                                 $customize_links[] = sprintf( __( '&lt;a href=&quot;%s&quot;&gt;Choose light or dark&lt;/a&gt;' ), esc_url( admin_url( 'themes.php?page=theme_options' ) ) );
</span><span class="cx"> 
</span><span class="cx">                         if ( current_theme_supports( 'custom-background' ) )
</span><span class="lines">@@ -1334,7 +1334,7 @@
</span><span class="cx"> 
</span><span class="cx">                         if ( ! empty( $customize_links ) ) {
</span><span class="cx">                                 echo '&lt;p&gt;';
</span><del>-                                printf( __( 'Use the current theme &amp;mdash; %1$s &amp;mdash; or &lt;a href=&quot;%2$s&quot;&gt;choose a new one&lt;/a&gt;. If you stick with %3$s, here are a few ways to make your site look unique.' ), $ct-&gt;title, esc_url( admin_url( 'themes.php' ) ), $ct-&gt;title );
</del><ins>+                                printf( __( 'Use the current theme &amp;mdash; %1$s &amp;mdash; or &lt;a href=&quot;%2$s&quot;&gt;choose a new one&lt;/a&gt;. If you stick with %1$s, here are a few ways to make your site look unique.' ), $theme-&gt;display('Name'), esc_url( admin_url( 'themes.php' ) ) );
</ins><span class="cx">                                 echo '&lt;/p&gt;';
</span><span class="cx">                         ?&gt;
</span><span class="cx">                         &lt;ul&gt;
</span><span class="lines">@@ -1345,7 +1345,7 @@
</span><span class="cx">                         &lt;?php
</span><span class="cx">                         } else {
</span><span class="cx">                                 echo '&lt;p&gt;';
</span><del>-                                printf( __( 'Use the current theme &amp;mdash; %1$s &amp;mdash; or &lt;a href=&quot;%2$s&quot;&gt;choose a new one&lt;/a&gt;.' ), $ct-&gt;title, esc_url( admin_url( 'themes.php' ) ) );
</del><ins>+                                printf( __( 'Use the current theme &amp;mdash; %1$s &amp;mdash; or &lt;a href=&quot;%2$s&quot;&gt;choose a new one&lt;/a&gt;.' ), $this-&gt;display('Name'), esc_url( admin_url( 'themes.php' ) ) );
</ins><span class="cx">                                 echo '&lt;/p&gt;';
</span><span class="cx">                         }
</span><span class="cx">                 endif; ?&gt;
</span></span></pre></div>
<a id="trunkwpadminincludesdeprecatedphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/deprecated.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/deprecated.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/deprecated.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -879,4 +879,61 @@
</span><span class="cx">                 $screen = convert_to_screen( $screen );
</span><span class="cx"> 
</span><span class="cx">         WP_Screen::add_old_compat_help( $screen, $help );
</span><ins>+}
+
+/**
+ * Get the allowed themes for the current blog.
+ *
+ * @since 3.0.0
+ * @deprecated 3.4.0
+ * @deprecated Use wp_get_themes()
+ * @see wp_get_themes()
+ *
+ * @return array $themes Array of allowed themes.
+ */
+function get_allowed_themes() {
+        _deprecated_function( __FUNCTION__, '3.4', &quot;wp_get_themes( array( 'allowed' =&gt; true ) )&quot; );
+
+        $themes = wp_get_themes( array( 'allowed' =&gt; true ) );
+
+        $wp_themes = array();
+        foreach ( $themes as $theme ) {
+                $wp_themes[ $theme-&gt;get('Name') ] = $theme;
+        }
+
+        return $wp_themes;
+}
+
+/**
+ * {@internal Missing Short Description}}
+ *
+ * @since 1.5.0
+ *
+ * @return unknown
+ */
+function get_broken_themes() {
+        _deprecated_function( __FUNCTION__, '3.4', &quot;wp_get_themes( array( 'errors' =&gt; true )&quot; );
+
+        $themes = wp_get_themes( array( 'errors' =&gt; true ) );
+        $broken = array();
+        foreach ( $themes as $theme ) {
+                $broken[ $theme-&gt;get('Name') ] = array(
+                        'Title' =&gt; $theme-&gt;get('Name'),
+                        'Description' =&gt; $theme-&gt;errors()-&gt;get_error_message(),
+                );
+        }
+        return $broken;
+}
+
+/**
+ * {@internal Missing Short Description}}
+ *
+ * @since 2.0.0
+ *
+ * @return unknown
+ */
+function current_theme_info() {
+        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' );
+
+        return wp_get_theme();
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpadminincludesmsdeprecatedphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/ms-deprecated.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/ms-deprecated.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/ms-deprecated.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -64,3 +64,13 @@
</span><span class="cx">         _deprecated_function(__FUNCTION__, '3.0', 'is_network_only_plugin()' );
</span><span class="cx">         return is_network_only_plugin( $file );
</span><span class="cx"> }
</span><ins>+
+function get_site_allowed_themes() {
+        _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_network()' );
+        return array_map( 'intval', WP_Theme::get_allowed_on_network() );
+}
+
+function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
+        _deprecated_function( __FUNCTION__, '3.4', 'WP_Theme::get_allowed_on_site()' );
+        return array_map( 'intval', WP_Theme::get_allowed_on_site( $blog_id ) );
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpadminincludesmsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/ms.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/ms.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/ms.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -169,35 +169,6 @@
</span><span class="cx">         return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
-        $themes = get_themes();
-
-        if ( $blog_id != 0 )
-                switch_to_blog( $blog_id );
-
-        $blog_allowed_themes = get_option( 'allowedthemes' );
-        if ( !is_array( $blog_allowed_themes ) || empty( $blog_allowed_themes ) ) { // convert old allowed_themes to new allowedthemes
-                $blog_allowed_themes = get_option( 'allowed_themes' );
-
-                if ( is_array( $blog_allowed_themes ) ) {
-                        foreach( (array) $themes as $key =&gt; $theme ) {
-                                $theme_key = esc_html( $theme['Stylesheet'] );
-                                if ( isset( $blog_allowed_themes[$key] ) == true ) {
-                                        $blog_allowedthemes[$theme_key] = 1;
-                                }
-                        }
-                        $blog_allowed_themes = $blog_allowedthemes;
-                        add_option( 'allowedthemes', $blog_allowed_themes );
-                        delete_option( 'allowed_themes' );
-                }
-        }
-
-        if ( $blog_id != 0 )
-                restore_current_blog();
-
-        return $blog_allowed_themes;
-}
-
</del><span class="cx"> function update_option_new_admin_email( $old_value, $value ) {
</span><span class="cx">         $email = get_option( 'admin_email' );
</span><span class="cx">         if ( $value == get_option( 'admin_email' ) || !is_email( $value ) )
</span><span class="lines">@@ -296,26 +267,6 @@
</span><span class="cx"> }
</span><span class="cx"> add_action( 'admin_notices', 'new_user_email_admin_notice' );
</span><span class="cx"> 
</span><del>-function get_site_allowed_themes() {
-        $themes = get_themes();
-        $allowed_themes = get_site_option( 'allowedthemes' );
-        if ( !is_array( $allowed_themes ) || empty( $allowed_themes ) ) {
-                $allowed_themes = get_site_option( 'allowed_themes' ); // convert old allowed_themes format
-                if ( !is_array( $allowed_themes ) ) {
-                        $allowed_themes = array();
-                } else {
-                        foreach( (array) $themes as $key =&gt; $theme ) {
-                                $theme_key = esc_html( $theme['Stylesheet'] );
-                                if ( isset( $allowed_themes[ $key ] ) == true ) {
-                                        $allowedthemes[ $theme_key ] = 1;
-                                }
-                        }
-                        $allowed_themes = $allowedthemes;
-                }
-        }
-        return $allowed_themes;
-}
-
</del><span class="cx"> /**
</span><span class="cx">  * Determines if there is any upload space left in the current blog's quota.
</span><span class="cx">  *
</span></span></pre></div>
<a id="trunkwpadminincludesschemaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/schema.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/schema.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/schema.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -343,12 +343,9 @@
</span><span class="cx"> 
</span><span class="cx">         $template = WP_DEFAULT_THEME;
</span><span class="cx">         // If default theme is a child theme, we need to get its template
</span><del>-        foreach ( (array) get_themes() as $theme ) {
-                if ( WP_DEFAULT_THEME == $theme['Stylesheet'] ) {
-                        $template = $theme['Template'];
-                        break;
-                }
-        }
</del><ins>+        $theme = wp_get_theme( $template );
+        if ( ! $theme-&gt;errors() )
+                $template = $theme-&gt;get_template();
</ins><span class="cx"> 
</span><span class="cx">         $timezone_string = '';
</span><span class="cx">         $gmt_offset = 0;
</span></span></pre></div>
<a id="trunkwpadminincludesthemeinstallphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/theme-install.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/theme-install.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/theme-install.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -265,16 +265,14 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $themes = get_themes();
-        foreach ( (array) $themes as $this_theme ) {
-                if ( is_array($this_theme) &amp;&amp; $this_theme['Stylesheet'] == $api-&gt;slug ) {
-                        if ( version_compare( $this_theme['Version'], $api-&gt;version, '=' ) ) {
</del><ins>+        $theme = wp_get_theme( $api-&gt;slug );
+        if ( is_a( $theme, 'WP_Theme' ) ) {
+                switch ( version_compare( $theme-&gt;get('Version'), $api-&gt;version ) ) {
+                        case 0; // equal
</ins><span class="cx">                                 $type = 'latest_installed';
</span><del>-                        } elseif ( version_compare( $this_theme['Version'], $api-&gt;version, '&gt;' ) ) {
</del><ins>+                        case 1: // installed theme &gt; api version
</ins><span class="cx">                                 $type = 'newer_installed';
</span><del>-                                $newer_version = $this_theme['Version'];
-                        }
-                        break;
</del><ins>+                                $newer_version = $theme-&gt;get('Version');
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> ?&gt;
</span></span></pre></div>
<a id="trunkwpadminincludesthemephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/theme.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/theme.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/theme.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -7,46 +7,6 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * {@internal Missing Short Description}}
- *
- * @since 2.0.0
- *
- * @return unknown
- */
-function current_theme_info() {
-        $themes = get_themes();
-        $current_theme = get_current_theme();
-
-        if ( ! $themes ) {
-                $ct = new stdClass;
-                $ct-&gt;name = $current_theme;
-                return $ct;
-        }
-
-        if ( ! isset( $themes[$current_theme] ) ) {
-                delete_option( 'current_theme' );
-                $current_theme = get_current_theme();
-        }
-
-        $ct = new stdClass;
-        $ct-&gt;name = $current_theme;
-        $ct-&gt;title = $themes[$current_theme]['Title'];
-        $ct-&gt;version = $themes[$current_theme]['Version'];
-        $ct-&gt;parent_theme = $themes[$current_theme]['Parent Theme'];
-        $ct-&gt;template_dir = $themes[$current_theme]['Template Dir'];
-        $ct-&gt;stylesheet_dir = $themes[$current_theme]['Stylesheet Dir'];
-        $ct-&gt;template = $themes[$current_theme]['Template'];
-        $ct-&gt;stylesheet = $themes[$current_theme]['Stylesheet'];
-        $ct-&gt;screenshot = $themes[$current_theme]['Screenshot'];
-        $ct-&gt;description = $themes[$current_theme]['Description'];
-        $ct-&gt;author = $themes[$current_theme]['Author'];
-        $ct-&gt;tags = $themes[$current_theme]['Tags'];
-        $ct-&gt;theme_root = $themes[$current_theme]['Theme Root'];
-        $ct-&gt;theme_root_uri = $themes[$current_theme]['Theme Root URI'];
-        return $ct;
-}
-
-/**
</del><span class="cx">  * Remove a theme
</span><span class="cx">  *
</span><span class="cx">  * @since 2.8.0
</span><span class="lines">@@ -114,59 +74,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * {@internal Missing Short Description}}
- *
- * @since 1.5.0
- *
- * @return unknown
- */
-function get_broken_themes() {
-        global $wp_broken_themes;
-
-        get_themes();
-        return $wp_broken_themes;
-}
-
-/**
- * Get the allowed themes for the current blog.
- *
- * @since 3.0.0
- *
- * @uses get_themes()
- * @uses current_theme_info()
- * @uses get_site_allowed_themes()
- * @uses wpmu_get_blog_allowedthemes
- *
- * @return array $themes Array of allowed themes.
- */
-function get_allowed_themes() {
-        if ( !is_multisite() )
-                return get_themes();
-
-        $themes = get_themes();
-        $ct = current_theme_info();
-        $allowed_themes = apply_filters(&quot;allowed_themes&quot;, get_site_allowed_themes() );
-        if ( $allowed_themes == false )
-                $allowed_themes = array();
-
-        $blog_allowed_themes = wpmu_get_blog_allowedthemes();
-        if ( is_array( $blog_allowed_themes ) )
-                $allowed_themes = array_merge( $allowed_themes, $blog_allowed_themes );
-
-        if ( isset( $allowed_themes[ esc_html( $ct-&gt;stylesheet ) ] ) == false )
-                $allowed_themes[ esc_html( $ct-&gt;stylesheet ) ] = true;
-
-        reset( $themes );
-        foreach ( $themes as $key =&gt; $theme ) {
-                if ( isset( $allowed_themes[ esc_html( $theme[ 'Stylesheet' ] ) ] ) == false )
-                        unset( $themes[ $key ] );
-        }
-        reset( $themes );
-
-        return $themes;
-}
-
-/**
</del><span class="cx">  * Get the Page Templates available in this theme
</span><span class="cx">  *
</span><span class="cx">  * @since 1.5.0
</span><span class="lines">@@ -174,37 +81,7 @@
</span><span class="cx">  * @return array Key is the template name, value is the filename of the template
</span><span class="cx">  */
</span><span class="cx"> function get_page_templates() {
</span><del>-        $themes = get_themes();
-        $theme = get_current_theme();
-        $templates = $themes[$theme]['Template Files'];
-        $page_templates = array();
-
-        if ( is_array( $templates ) ) {
-                $base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );
-
-                foreach ( $templates as $template ) {
-                        $basename = str_replace($base, '', $template);
-
-                        // don't allow template files in subdirectories
-                        if ( false !== strpos($basename, '/') )
-                                continue;
-
-                        if ( 'functions.php' == $basename )
-                                continue;
-
-                        $template_data = implode( '', file( $template ));
-
-                        $name = '';
-                        if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name ) )
-                                $name = _cleanup_header_comment($name[1]);
-
-                        if ( !empty( $name ) ) {
-                                $page_templates[trim( $name )] = $basename;
-                        }
-                }
-        }
-
-        return $page_templates;
</del><ins>+        return wp_get_theme()-&gt;get_page_templates();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -240,16 +117,14 @@
</span><span class="cx">         if ( !isset($themes_update) )
</span><span class="cx">                 $themes_update = get_site_transient('update_themes');
</span><span class="cx"> 
</span><del>-        if ( is_object($theme) &amp;&amp; isset($theme-&gt;stylesheet) )
-                $stylesheet = $theme-&gt;stylesheet;
-        elseif ( is_array($theme) &amp;&amp; isset($theme['Stylesheet']) )
-                $stylesheet = $theme['Stylesheet'];
-        else
-                return false; //No valid info passed.
</del><ins>+        if ( ! is_a( $theme, 'WP_Theme' ) )
+                return;
</ins><span class="cx"> 
</span><ins>+        $stylesheet = $theme-&gt;get_stylesheet();
+
</ins><span class="cx">         if ( isset($themes_update-&gt;response[ $stylesheet ]) ) {
</span><span class="cx">                 $update = $themes_update-&gt;response[ $stylesheet ];
</span><del>-                $theme_name = is_object($theme) ? $theme-&gt;name : (is_array($theme) ? $theme['Name'] : '');
</del><ins>+                $theme_name = $theme-&gt;get('Name');
</ins><span class="cx">                 $details_url = add_query_arg(array('TB_iframe' =&gt; 'true', 'width' =&gt; 1024, 'height' =&gt; 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list.
</span><span class="cx">                 $update_url = wp_nonce_url('update.php?action=upgrade-theme&amp;amp;theme=' . urlencode($stylesheet), 'upgrade-theme_' . $stylesheet);
</span><span class="cx">                 $update_onclick = 'onclick=&quot;if ( confirm(\'' . esc_js( __(&quot;Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.&quot;) ) . '\') ) {return true;}return false;&quot;';
</span></span></pre></div>
<a id="trunkwpadminincludesupdatephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/update.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/update.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/includes/update.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -217,16 +217,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function get_theme_updates() {
</span><del>-        $themes = get_themes();
</del><ins>+        $themes = wp_get_themes();
</ins><span class="cx">         $current = get_site_transient('update_themes');
</span><span class="cx">         $update_themes = array();
</span><span class="cx"> 
</span><del>-        foreach ( $themes as $theme ) {
-                $theme = (object) $theme;
-                if ( isset($current-&gt;response[ $theme-&gt;Stylesheet ]) ) {
-                        $update_themes[$theme-&gt;Stylesheet] = $theme;
-                        $update_themes[$theme-&gt;Stylesheet]-&gt;update = $current-&gt;response[ $theme-&gt;Stylesheet ];
-                }
</del><ins>+        foreach ( $current-&gt;response as $stylesheet =&gt; $data ) {
+                $update_themes[ $stylesheet ] = wp_get_theme( $stylesheet );
+                $update_themes[ $stylesheet ]-&gt;update = $data;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return $update_themes;
</span></span></pre></div>
<a id="trunkwpadminthemesphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/themes.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/themes.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-admin/themes.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -96,16 +96,16 @@
</span><span class="cx"> &lt;h2&gt;&lt;?php echo esc_html( $title ); ?&gt;
</span><span class="cx"> &lt;?php endif; ?&gt;
</span><span class="cx"> &lt;/h2&gt;
</span><del>-
-&lt;h3&gt;&lt;?php _e('Current Theme'); ?&gt;&lt;/h3&gt;
</del><ins>+&lt;?php $ct = wp_get_theme(); ?&gt;
+&lt;h3&gt;&lt;?php _e( 'Current Theme' ); ?&gt;&lt;/h3&gt;
</ins><span class="cx"> &lt;div id=&quot;current-theme&quot;&gt;
</span><del>-&lt;?php if ( $ct-&gt;screenshot ) : ?&gt;
-&lt;img src=&quot;&lt;?php echo $ct-&gt;theme_root_uri . '/' . $ct-&gt;stylesheet . '/' . $ct-&gt;screenshot; ?&gt;&quot; alt=&quot;&lt;?php esc_attr_e('Current theme preview'); ?&gt;&quot; /&gt;
</del><ins>+&lt;?php if ( $ct-&gt;get_screenshot() ) : ?&gt;
+&lt;img src=&quot;&lt;?php echo $ct-&gt;get_screenshot( 'absolute' ); ?&gt;&quot; alt=&quot;&lt;?php esc_attr_e( 'Current theme preview'); ?&gt;&quot; /&gt;
</ins><span class="cx"> &lt;?php endif; ?&gt;
</span><span class="cx"> &lt;h4&gt;&lt;?php
</span><span class="cx">         /* translators: 1: theme title, 2: theme version, 3: theme author */
</span><del>-        printf(__('%1$s %2$s by %3$s'), $ct-&gt;title, $ct-&gt;version, $ct-&gt;author) ; ?&gt;&lt;/h4&gt;
-&lt;p class=&quot;theme-description&quot;&gt;&lt;?php echo $ct-&gt;description; ?&gt;&lt;/p&gt;
</del><ins>+        printf( __( '%1$s %2$s by %3$s' ), $ct-&gt;display('Name'), $ct-&gt;display('Version'), $ct-&gt;display('Author') ) ; ?&gt;&lt;/h4&gt;
+&lt;p class=&quot;theme-description&quot;&gt;&lt;?php echo $ct-&gt;display('Description'); ?&gt;&lt;/p&gt;
</ins><span class="cx"> &lt;div class=&quot;theme-options&quot;&gt;
</span><span class="cx">         &lt;span&gt;&lt;?php _e( 'Options:' )?&gt;&lt;/span&gt;
</span><span class="cx">         &lt;?php
</span><span class="lines">@@ -117,8 +117,8 @@
</span><span class="cx">                         if ( 'themes.php' == $item[2] || 'theme-editor.php' == $item[2] )
</span><span class="cx">                                 continue;
</span><span class="cx">                         // 0 = name, 1 = capability, 2 = file
</span><del>-                        if ( ( strcmp($self, $item[2]) == 0 &amp;&amp; empty($parent_file)) || ($parent_file &amp;&amp; ($item[2] == $parent_file)) ) $class = ' class=&quot;current&quot;';
-
</del><ins>+                        if ( ( strcmp($self, $item[2]) == 0 &amp;&amp; empty($parent_file)) || ($parent_file &amp;&amp; ($item[2] == $parent_file)) )
+                                $class = ' class=&quot;current&quot;';
</ins><span class="cx">                         if ( !empty($submenu[$item[2]]) ) {
</span><span class="cx">                                 $submenu[$item[2]] = array_values($submenu[$item[2]]); // Re-index.
</span><span class="cx">                                 $menu_hook = get_plugin_page_hook($submenu[$item[2]][0][2], $item[2]);
</span><span class="lines">@@ -137,8 +137,8 @@
</span><span class="cx">         }
</span><span class="cx">         echo implode ( ' | ', $options );
</span><span class="cx"> 
</span><del>-        if ( $ct-&gt;tags ) : ?&gt;
-        &lt;p&gt;&lt;?php _e('Tags:'); ?&gt; &lt;?php echo join(', ', $ct-&gt;tags); ?&gt;&lt;/p&gt;
</del><ins>+        if ( $ct-&gt;get('Tags') ) : ?&gt;
+        &lt;p&gt;&lt;?php _e('Tags:'); ?&gt; &lt;?php echo $ct-&gt;display('Tags'); ?&gt;&lt;/p&gt;
</ins><span class="cx">         &lt;?php endif; ?&gt;
</span><span class="cx"> &lt;/div&gt;
</span><span class="cx"> &lt;?php theme_update_available($ct); ?&gt;
</span><span class="lines">@@ -218,8 +218,7 @@
</span><span class="cx"> 
</span><span class="cx"> &lt;?php
</span><span class="cx"> // List broken themes, if any.
</span><del>-$broken_themes = get_broken_themes();
-if ( current_user_can('edit_themes') &amp;&amp; count( $broken_themes ) ) {
</del><ins>+if ( current_user_can('edit_themes') &amp;&amp; $broken_themes = wp_get_themes( array( 'errors' =&gt; true ) ) ) {
</ins><span class="cx"> ?&gt;
</span><span class="cx"> 
</span><span class="cx"> &lt;h3&gt;&lt;?php _e('Broken Themes'); ?&gt;&lt;/h3&gt;
</span><span class="lines">@@ -231,20 +230,13 @@
</span><span class="cx">                 &lt;th&gt;&lt;?php _e('Description'); ?&gt;&lt;/th&gt;
</span><span class="cx">         &lt;/tr&gt;
</span><span class="cx"> &lt;?php
</span><del>-        $theme = '';
-
-        $theme_names = array_keys($broken_themes);
-        natcasesort($theme_names);
-
-        foreach ($theme_names as $theme_name) {
-                $name = $broken_themes[$theme_name]['Title'];
-                $description = $broken_themes[$theme_name]['Description'];
-
-                $theme = ('class=&quot;alternate&quot;' == $theme) ? '' : 'class=&quot;alternate&quot;';
</del><ins>+        $alt = '';
+        foreach ( $broken_themes as $broken_theme ) {
+                $alt = ('class=&quot;alternate&quot;' == $alt) ? '' : 'class=&quot;alternate&quot;';
</ins><span class="cx">                 echo &quot;
</span><del>-                &lt;tr $theme&gt;
-                         &lt;td&gt;$name&lt;/td&gt;
-                         &lt;td&gt;$description&lt;/td&gt;
</del><ins>+                &lt;tr $alt&gt;
+                         &lt;td&gt;&quot; . $broken_theme-&gt;get('Name') .&quot;&lt;/td&gt;
+                         &lt;td&gt;&quot; . $broken_theme-&gt;errors()-&gt;get_error_message() . &quot;&lt;/td&gt;
</ins><span class="cx">                 &lt;/tr&gt;&quot;;
</span><span class="cx">         }
</span><span class="cx"> ?&gt;
</span><span class="lines">@@ -254,4 +246,4 @@
</span><span class="cx"> ?&gt;
</span><span class="cx"> &lt;/div&gt;
</span><span class="cx"> 
</span><del>-&lt;?php require('./admin-footer.php'); ?&gt;
</del><ins>+&lt;?php require('./admin-footer.php'); ?&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesclasswpcustomizephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-customize.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-customize.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-includes/class-wp-customize.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -242,17 +242,7 @@
</span><span class="cx">          * @return string Theme name.
</span><span class="cx">          */
</span><span class="cx">         public function current_theme( $current_theme ) {
</span><del>-                $themes = get_themes();
-
-                if ( ! $themes )
-                        return $current_theme;
-
-                foreach ( $themes as $theme ) {
-                        if ( $theme['Stylesheet'] == $this-&gt;stylesheet &amp;&amp; $theme['Template'] == $this-&gt;template )
-                                return $theme['Name'];
-                }
-
-                return $current_theme;
</del><ins>+                return wp_get_theme( $this-&gt;stylesheet )-&gt;get('Name');
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /**
</span></span></pre></div>
<a id="trunkwpincludesclasswpthemephp"></a>
<div class="addfile"><h4>Added: trunk/wp-includes/class-wp-theme.php (0 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-theme.php                                (rev 0)
+++ trunk/wp-includes/class-wp-theme.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -0,0 +1,1116 @@
</span><ins>+&lt;?php
+/**
+ * WP_Theme Class
+ *
+ * @package WordPress
+ * @subpackage Theme
+ */
+
+final class WP_Theme implements ArrayAccess {
+
+        /**
+         * Headers for style.css files.
+         *
+         * @static
+         * @access private
+         * @var array
+         */
+        private static $file_headers = array(
+                'Name'        =&gt; 'Theme Name',
+                'ThemeURI'    =&gt; 'Theme URI',
+                'Description' =&gt; 'Description',
+                'Author'      =&gt; 'Author',
+                'AuthorURI'   =&gt; 'Author URI',
+                'Version'     =&gt; 'Version',
+                'Template'    =&gt; 'Template',
+                'Status'      =&gt; 'Status',
+                'Tags'        =&gt; 'Tags',
+                'TextDomain'  =&gt; 'Text Domain',
+                'DomainPath'  =&gt; 'Domain Path',
+        );
+
+        /**
+         * Absolute path to the theme root, usually wp-content/themes
+         *
+         * @access private
+         * @var string
+         */
+        private $theme_root;
+
+        /**
+         * Header data from the theme's style.css file.
+         *
+         * @access private
+         * @var array
+         */
+        private $headers = array();
+
+        /**
+         * Header data from the theme's style.css file after being sanitized.
+         *
+         * @access private
+         * @var array
+         */
+        private $headers_sanitized;
+
+        /**
+         * Header name from the theme's style.css after being translated.
+         *
+         * Cached due to sorting functions running over the translated name.
+         */
+        private $name_translated;
+
+        /**
+         * Errors encountered when initializing the theme.
+         *
+         * @access private
+         * @var WP_Error
+         */
+        private $errors;
+
+        /**
+         * The directory name of the theme's files, inside the theme root.
+         *
+         * In the case of a child theme, this is directory name of the the child theme.
+         * Otherwise, 'stylesheet' is the same as 'template'.
+         *
+         * @access private
+         * @var string
+         */
+        private $stylesheet;
+
+        /**
+         * The directory name of the theme's files, inside the theme root.
+         *
+         * In the case of a child theme, this is the directory name of the parent theme.
+         * Otherwise, 'template' is the same as 'stylesheet'.
+         *
+         * @access private
+         * @var string
+         */
+        private $template;
+
+        /**
+         * A reference to the parent theme, in the case of a child theme.
+         *
+         * @access private
+         * @var WP_Theme
+         */
+        private $parent;
+
+        /**
+         * Flag for whether the theme's textdomain is loaded.
+         *
+         * @access private
+         * @var bool
+         */
+        private $textdomain_loaded;
+
+        /**
+         * Flag for whether the themes cache bucket should be persistently cached.
+         *
+         * Default is false. Can be set with the wp_cache_themes_persistently filter.
+         *
+         * @access private
+         * @var bool
+         */
+        private static $persistently_cache;
+
+        /**
+         * Expiration time for the themes cache bucket.
+         *
+         * By default the bucket is not cached, so this value is useless.
+         *
+         * @access private
+         * @var bool
+         */
+        private static $cache_expiration = 7200;
+
+        /**
+         * Constructor for WP_Theme.
+         *
+         * @param string $theme_dir Directory of the theme within the theme_root.
+         * @param string $theme_root Theme root.
+         * @param WP_Error|null $child If this theme is a parent theme, the child may be passed for validation purposes.
+         */
+        public function __construct( $theme_dir, $theme_root, $child = null ) {
+
+                // Initialize caching on first run.
+                if ( ! isset( self::$persistently_cache ) ) {
+                        self::$persistently_cache = apply_filters( 'wp_cache_themes_persistently', false, 'WP_Theme' );
+                        if ( self::$persistently_cache ) {
+                                wp_cache_add_global_groups( 'themes' );
+                                if ( is_int( self::$persistently_cache ) )
+                                        self::$cache_expiration = self::$persistently_cache;
+                        } else {
+                                wp_cache_add_non_persistent_groups( 'themes' );
+                        }
+                }
+
+                $this-&gt;theme_root = $theme_root;
+                $this-&gt;stylesheet = $theme_dir;
+                $theme_file = $this-&gt;stylesheet . '/style.css';
+
+                $cache = $this-&gt;cache_get( 'theme' );
+
+                if ( is_array( $cache ) ) {
+                        foreach ( array( 'errors', 'headers', 'template' ) as $key ) {
+                                if ( isset( $cache[ $key ] ) )
+                                        $this-&gt;$key = $cache[ $key ];
+                        }
+                        if ( $this-&gt;errors )
+                                return;
+                        if ( isset( $cache['theme_root_template'] ) )
+                                $theme_root_template = $cache['theme_root_template'];
+                } elseif ( ! file_exists( $this-&gt;theme_root . '/' . $theme_file ) ) {
+                        $this-&gt;headers['Name'] = $this-&gt;stylesheet;
+                        $this-&gt;errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) );
+                        $this-&gt;cache_add( 'theme', array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet ) );
+                        if ( ! file_exists( $this-&gt;theme_root ) ) // Don't cache this one.
+                                $this-&gt;errors-&gt;add( 'theme_root_missing', __( 'ERROR: The themes directory is either empty or doesn&amp;#8217;t exist. Please check your installation.' ) );
+                        return;
+                } elseif ( ! is_readable( $this-&gt;theme_root . '/' . $theme_file ) ) {
+                        $this-&gt;headers['Name'] = $this-&gt;stylesheet;
+                        $this-&gt;errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
+                        $this-&gt;cache_add( 'theme', array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet ) );
+                        return;
+                } else {
+                        $this-&gt;headers = get_file_data( $this-&gt;theme_root . '/' . $theme_file, self::$file_headers, 'theme' );
+                }
+
+                // (If template is set from cache, we know it's good.)
+                if ( ! $this-&gt;template &amp;&amp; ! ( $this-&gt;template = $this-&gt;get('Template') ) ) {
+                        if ( file_exists( $this-&gt;theme_root . '/' . $this-&gt;stylesheet . '/index.php' ) ) {
+                                $this-&gt;template = $this-&gt;stylesheet;
+                        } else {
+                                $this-&gt;errors = new WP_Error( 'theme_no_index', __( 'Template is missing.' ) );
+                                $this-&gt;cache_add( 'theme', array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet ) );
+                                return;
+                        }
+                }
+
+                // If we got our data from cache, we can assume that 'template' is pointing to the right place.
+                if ( ! is_array( $cache ) &amp;&amp; $this-&gt;template != $this-&gt;stylesheet &amp;&amp; ! file_exists( $this-&gt;theme_root . '/' . $this-&gt;template . '/index.php' ) ) {
+                        // If we're in a directory of themes inside /themes, look for the parent nearby.
+                        // wp-content/themes/directory-of-themes/*
+                        $parent_dir = dirname( $this-&gt;stylesheet );
+                        if ( '.' != $parent_dir &amp;&amp; file_exists( $this-&gt;theme_root . '/' . $parent_dir . '/' . $this-&gt;template . '/index.php' ) ) {
+                                $this-&gt;template = $parent_dir . '/' . $this-&gt;template;
+                        } elseif ( ( $directories = search_theme_directories() ) &amp;&amp; isset( $directories[ $this-&gt;template ] ) ) {
+                                // Look for the template in the search_theme_directories() results, in case it is in another theme root.
+                                // We don't look into directories of themes, just the theme root.
+                                $theme_root_template = $directories[ $this-&gt;template ]['theme_root'];
+                        } else {
+                                // Parent theme is missing.
+                                $this-&gt;errors = new WP_Error( 'theme_no_parent', sprintf( __( 'The parent theme is missing. Please install the &quot;%s&quot; parent theme.' ), $this-&gt;template ) );
+                                $this-&gt;cache_add( 'theme', array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet, 'template' =&gt; $this-&gt;template ) );
+                                return;
+                        }
+                }
+
+                // @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().
+
+                // Set the parent, if we're a child theme.
+                if ( $this-&gt;template != $this-&gt;stylesheet ) {
+                        // If we are a parent, then there is a problem. Only two generations allowed! Cancel things out.
+                        if ( is_a( $child, 'WP_Theme' ) &amp;&amp; $child-&gt;template == $this-&gt;stylesheet ) {
+                                $child-&gt;parent = null;
+                                $child-&gt;errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The &quot;%s&quot; theme is not a valid parent theme.' ), $child-&gt;template ) );
+                                $child-&gt;cache_add( 'theme', array( 'headers' =&gt; $child-&gt;headers, 'errors' =&gt; $child-&gt;errors, 'stylesheet' =&gt; $child-&gt;stylesheet, 'template' =&gt; $child-&gt;template ) );
+                                // The two themes actually reference each other with the Template header.
+                                if ( $child-&gt;stylesheet == $this-&gt;template ) {
+                                        $this-&gt;errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The &quot;%s&quot; theme is not a valid parent theme.' ), $this-&gt;template ) );
+                                        $this-&gt;cache_add( 'theme', array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet, 'template' =&gt; $this-&gt;template ) );
+                                }
+                                return;
+                        }
+                        // Set the parent. Pass the current instance so we can do the crazy checks above and assess errors.
+                        $this-&gt;parent = new WP_Theme( $this-&gt;template, isset( $theme_root_template ) ? $theme_root_template : $this-&gt;theme_root, $this );
+                }
+
+                // We're good. If we didn't retrieve from cache, set it.
+                if ( ! is_array( $cache ) ) {
+                        $cache = array( 'headers' =&gt; $this-&gt;headers, 'errors' =&gt; $this-&gt;errors, 'stylesheet' =&gt; $this-&gt;stylesheet, 'template' =&gt; $this-&gt;template );
+                        // If the parent theme is in another root, we'll want to cache this. Avoids an entire branch of filesystem calls above.
+                        if ( isset( $theme_root_template ) )
+                                $cache['theme_root_template'] = $theme_root_template;
+                        $this-&gt;cache_add( 'theme', $cache );
+                }
+        }
+
+        /**
+         * __isset() magic method for properties formerly returned by current_theme_info()
+         */
+        public function __isset( $offset ) {
+                static $properties = array(
+                        'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet',
+                        'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri',
+                );
+
+                return in_array( $offset, $properties );
+        }
+
+        /**
+         * __get() magic method for properties formerly returned by current_theme_info()
+         */
+        public function __get( $offset ) {
+                switch ( $offset ) {
+                        case 'name' :
+                        case 'title' :
+                                return $this-&gt;get('Name');
+                        case 'version' :
+                                return $this-&gt;get('Version');
+                        case 'parent_theme' :
+                                return $this-&gt;parent ? $this-&gt;parent-&gt;get('Name') : '';
+                        case 'template_dir' :
+                                return $this-&gt;get_template_directory();
+                        case 'stylesheet_dir' :
+                                return $this-&gt;get_stylesheet_directory();
+                        case 'template' :
+                                return $this-&gt;get_template();
+                        case 'stylesheet' :
+                                return $this-&gt;get_stylesheet();
+                        case 'screenshot' :
+                                return $this-&gt;get_screenshot();
+                        // 'author' and 'description' did not previously return translated data.
+                        case 'description' :
+                                return $this-&gt;display('Description');
+                        case 'author' :
+                                return $this-&gt;display('Author');
+                        case 'tags' :
+                                return $this-&gt;get( 'Tags' );
+                        case 'theme_root' :
+                                return $this-&gt;get_theme_root();
+                        case 'theme_root_uri' :
+                                return $this-&gt;get_theme_root_uri();
+                }
+        }
+
+        /**
+         * Method to implement ArrayAccess for keys formerly returned by get_themes()
+         */
+        public function offsetSet( $offset, $value ) {}
+
+        /**
+         * Method to implement ArrayAccess for keys formerly returned by get_themes()
+         */
+        public function offsetUnset( $offset ) {}
+
+        /**
+         * Method to implement ArrayAccess for keys formerly returned by get_themes()
+         */
+        public function offsetExists( $offset ) {
+                static $keys = array(
+                        'Name', 'Version', 'Status', 'Title', 'Author', 'Author Name', 'Author URI', 'Description',
+                        'Template', 'Stylesheet', 'Template Files', 'Stylesheet Files', 'Template Dir', 'Stylesheet Dir',
+                         'Screenshot', 'Tags', 'Theme Root', 'Theme Root URI', 'Parent Theme',
+                );
+
+                return in_array( $offset, $keys );
+        }
+
+        /**
+         * Method to implement ArrayAccess for keys formerly returned by get_themes()
+         */
+        public function offsetGet( $offset ) {
+                switch ( $offset ) {
+                        case 'Name' :
+                        case 'Version' :
+                        case 'Status' :
+                                return $this-&gt;get( $offset );
+                        case 'Title' :
+                                return $this-&gt;get('Name');
+                        // Author, Author Name, Author URI, and Description did not
+                        // previously return translated data. We are doing so now.
+                        // Title and Name could have been used as the key for get_themes(),
+                        // so both to remain untranslated for back compatibility.
+                        case 'Author' :
+                                return $this-&gt;display( 'Author');
+                        case 'Author Name' :
+                                return $this-&gt;display( 'Author', false);
+                        case 'Author URI' :
+                                return $this-&gt;display('AuthorURI');
+                        case 'Description' :
+                                return $this-&gt;display( 'Description');
+                        case 'Template' :
+                                return $this-&gt;get_template();
+                        case 'Stylesheet' :
+                                return $this-&gt;get_stylesheet();
+                        case 'Template Files' :
+                                $files = $this-&gt;get_files('php');
+                                foreach ( $files as &amp;$file )
+                                        $file = $this-&gt;theme_root . '/' . $file;
+                                return $files;
+                        case 'Stylesheet Files' :
+                                $files = $this-&gt;get_files('css');
+                                foreach ( $files as &amp;$file )
+                                        $file = $this-&gt;theme_root . '/' . $file;
+                                return $files;
+                        case 'Template Dir' :
+                                return $this-&gt;get_template_directory();
+                        case 'Stylesheet Dir' :
+                                return $this-&gt;get_stylesheet_directory();
+                        case 'Screenshot' :
+                                return $this-&gt;get_screenshot();
+                        case 'Tags' :
+                                return $this-&gt;get('Tags');
+                        case 'Theme Root' :
+                                return $this-&gt;get_theme_root();
+                        case 'Theme Root URI' :
+                                return $this-&gt;get_theme_root_uri();
+                        case 'Parent Theme' :
+                                return $this-&gt;parent ? $this-&gt;parent-&gt;get('Name') : '';
+                        default :
+                                return null;
+                }
+        }
+
+        /**
+         * Returns errors property.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return WP_Error|bool WP_Error if there are errors, or false.
+         */
+        public function errors() {
+                return is_wp_error( $this-&gt;errors ) ? $this-&gt;errors : false;
+        }
+
+        /**
+         * Returns reference to the parent theme.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return WP_Theme|bool Parent theme, or false if the current theme is not a child theme.
+         */
+        public function parent() {
+                return isset( $this-&gt;parent ) ? $this-&gt;parent : false;
+        }
+
+        /**
+         * Adds theme data to cache.
+         *
+         * Cache entries keyed by the theme and the type of data.
+         *
+         * @access private
+         * @since 3.4.0
+         *
+         * @param string $key Type of data to store (theme, screenshot, screenshot_count, files, headers)
+         * @param string $data Data to store
+         * @return bool Return value from wp_cache_add()
+         */
+        private function cache_add( $key, $data ) {
+                return wp_cache_add( $key . '-' . $this-&gt;theme_root . '/' . $this-&gt;stylesheet, $data, 'themes', self::$cache_expiration );
+        }
+
+        /**
+         * Gets theme data from cache.
+         *
+         * Cache entries are keyed by the theme and the type of data.
+         *
+         * @access private
+         * @since 3.4.0
+         *
+         * @param string $key Type of data to retrieve (theme, screenshot, screenshot_count, files, headers)
+         * @return mixed Retrieved data
+         */
+        private function cache_get( $key ) {
+                return wp_cache_get( $key . '-' . $this-&gt;theme_root . '/' . $this-&gt;stylesheet, 'themes' );
+        }
+
+        /**
+         * Clears the cache for the theme.
+         *
+         * @access public
+         * @since 3.4.0
+         */
+        public function cache_delete() {
+                foreach ( array( 'theme', 'screenshot', 'screenshot_count', 'files', 'headers' ) as $key )
+                        wp_cache_delete( $key . '-' . $this-&gt;theme_root . '/' . $this-&gt;stylesheet, 'themes' );
+        }
+
+        /**
+         * Gets a theme header.
+         *
+         * The header is sanitized.
+         *
+         * @access public
+         * @since 3.4.0
+         *
+         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
+         * @return string String on success, false on failure.
+         */
+        public function get( $header ) {
+                if ( ! isset( $this-&gt;headers[ $header ] ) )
+                        return false;
+                return $this-&gt;sanitize_header( $header, $this-&gt;headers[ $header ] );
+
+                if ( ! isset( $this-&gt;headers_sanitized ) ) {
+                        $this-&gt;headers_sanitized = $this-&gt;cache_get( 'headers' );
+                        if ( ! is_array( $this-&gt;headers_sanitized ) )
+                                $headers = array();
+                }
+
+                if ( isset( $this-&gt;headers_sanitized[ $header ] ) )
+                        return $this-&gt;headers_sanitized[ $header ];
+
+                // If an external object cache does not consider themes to be a persistent group, sanitize everything and cache it.
+                if ( self::$persistently_cache ) {
+                        foreach ( array_keys( $this-&gt;headers ) as $header )
+                                $this-&gt;headers_sanitized[ $header ] = $this-&gt;sanitize_header( $header, $this-&gt;headers[ $header ] );
+                        $this-&gt;cache_add( 'headers', $this-&gt;headers_sanitized );
+                } else {
+                        $this-&gt;headers_sanitized[ $header ] = $this-&gt;sanitize_header( $header, $this-&gt;headers[ $header ] );
+                }
+
+                return $this-&gt;headers_sanitized[ $header ];
+        }
+
+        /**
+         * Gets a theme header ready for display (marked up, translated).
+         *
+         * @access public
+         * @since 3.4.0
+         *
+         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
+         * @param bool $markup Optional. Whether to mark up the header. Defaults to true.
+         * @param bool $translate Optional. Whether to translate the header. Defaults to true.
+         * @return string Processed header, false on failure.
+         */
+        public function display( $header, $markup = true, $translate = true ) {
+                $value = $this-&gt;get( $header );
+                if ( false === $value || '' === $value )
+                        return $value;
+
+                if ( ! $this-&gt;load_textdomain() )
+                        $translate = false;
+
+                if ( $translate )
+                        $value = $this-&gt;translate_header( $header, $value );
+
+                if ( $markup )
+                        $value = $this-&gt;markup_header( $header, $value, $translate );
+
+                return $value;
+        }
+
+        /**
+         * Sanitize a theme header.
+         *
+         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
+         * @param string $value Value to sanitize.
+         */
+        private function sanitize_header( $header, $value ) {
+                switch ( $header ) {
+                        case 'Status' :
+                                if ( ! $value ) {
+                                        $value = 'public';
+                                        break;
+                                }
+                                // Fall through otherwise.
+                        case 'Name' :
+                        case 'Author' :
+                                static $header_tags = array(
+                                        'abbr'    =&gt; array( 'title' =&gt; true ),
+                                        'acronym' =&gt; array( 'title' =&gt; true ),
+                                        'code'    =&gt; true,
+                                        'em'      =&gt; true,
+                                        'strong'  =&gt; true,
+                                );
+                                $value = wp_kses( $value, $header_tags );
+                                break;
+                        case 'Description' :
+                                static $header_tags_with_a = array(
+                                        'a'       =&gt; array( 'href' =&gt; true, 'title' =&gt; true ),
+                                        'abbr'    =&gt; array( 'title' =&gt; true ),
+                                        'acronym' =&gt; array( 'title' =&gt; true ),
+                                        'code'    =&gt; true,
+                                        'em'      =&gt; true,
+                                        'strong'  =&gt; true,
+                                );
+                                $value = wp_kses( $value, $header_tags_with_a );
+                                break;
+                        case 'ThemeURI' :
+                        case 'AuthorURI' :
+                                $value = esc_url( $value );
+                                break;
+                        case 'Tags' :
+                                $value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) );
+                                break;
+                }
+
+                return $value;
+        }
+
+        /**
+         * Mark up a theme header.
+         *
+         * @access private
+         * @since 3.4.0
+         *
+         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
+         * @param string $value Value to mark up.
+         * @param string $translate Whether the header has been translated.
+         * @return string Value, marked up.
+         */
+        private function markup_header( $header, $value, $translate ) {
+                switch ( $header ) {
+                        case 'Description' :
+                                $value = wptexturize( $value );
+                                break;
+                        case 'Author' :
+                                if ( $this-&gt;get('AuthorURI') ) {
+                                        static $attr = null;
+                                        if ( ! isset( $attr ) )
+                                                $attr = esc_attr__( 'Visit author homepage' );
+                                        $value = sprintf( '&lt;a href=&quot;%1$s&quot; title=&quot;%2$s&quot;&gt;%3$s&lt;/a&gt;', $this-&gt;display( 'AuthorURI', true, $translate ), $attr, $value );
+                                } elseif ( ! $value ) {
+                                        $value = __( 'Anonymous' );
+                                }
+                                break;
+                        case 'Tags' :
+                                static $comma = null;
+                                if ( ! isset( $comma ) ) {
+                                        /* translators: used between list items, there is a space after the comma */
+                                        $comma = __( ', ' );
+                                }
+                                $value = implode( $comma, $value );
+                                break;
+                }
+
+                return $value;
+        }
+
+        /**
+         * Translate a theme header.
+         *
+         * @access private
+         * @since 3.4.0
+         *
+         * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status.
+         * @param string $value Value to translate.
+         * @return string Translated value.
+         */
+        private function translate_header( $header, $value ) {
+                switch ( $header ) {
+                        case 'Name' :
+                                // Cached for sorting reasons.
+                                if ( isset( $this-&gt;name_translated ) )
+                                        return $this-&gt;name_translated;
+                                $this-&gt;name_translated = translate( $value, $this-&gt;get('TextDomain' ) );
+                                return $this-&gt;name_translated;
+                        case 'Tags' :
+                                if ( empty( $value ) )
+                                        return $value;
+
+                                static $tags_list;
+                                if ( ! isset( $tags_list ) ) {
+                                        $tags_list = array();
+                                        $feature_list = get_theme_feature_list( false ); // No API
+                                        foreach ( $feature_list as $tags )
+                                                $tags_list += $tags;
+                                }
+
+                                foreach ( $value as &amp;$tag ) {
+                                        if ( isset( $tags_list[ $tag ] ) )
+                                                $tag = $tags_list[ $tag ];
+                                }
+
+                                return $value;
+                                break;
+                        default :
+                                $value = translate( $value, $this-&gt;get('TextDomain') );
+                }
+                return $value;
+        }
+
+        /**
+         * The directory name of the theme's &quot;stylesheet&quot; files, inside the theme root.
+         *
+         * In the case of a child theme, this is directory name of the the child theme.
+         * Otherwise, get_stylesheet() is the same as get_template().
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Stylesheet
+         */
+        public function get_stylesheet() {
+                return $this-&gt;stylesheet;
+        }
+
+        /**
+         * The directory name of the theme's &quot;template&quot; files, inside the theme root.
+         *
+         * In the case of a child theme, this is the directory name of the parent theme.
+         * Otherwise, the get_template() is the same as get_stylesheet().
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Template
+         */
+        public function get_template() {
+                return $this-&gt;template;
+        }
+
+        /**
+         * Whether a theme is a child theme.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return bool True if a theme is a child theme, false otherwise.
+         */
+        public function is_child_theme() {
+                return $this-&gt;template !== $this-&gt;stylesheet;
+        }
+
+        /**
+         * Returns the absolute path to the directory of a theme's &quot;stylesheet&quot; files.
+         *
+         * In the case of a child theme, this is the absolute path to the directory
+         * of the child theme's files.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Absolute path of the stylesheet directory.
+         */
+        public function get_stylesheet_directory() {
+                if ( $this-&gt;errors &amp;&amp; in_array( 'theme_root_missing', $this-&gt;errors-&gt;get_error_codes() ) )
+                        return '';
+
+                return $this-&gt;theme_root . '/' . $this-&gt;stylesheet;
+        }
+
+        /**
+         * Returns the absolute path to the directory of a theme's &quot;template&quot; files.
+         *
+         * In the case of a child theme, this is the absolute path to the directory
+         * of the parent theme's files.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Absolute path of the template directory.
+         */
+        public function get_template_directory() {
+                if ( $this-&gt;parent )
+                        $theme_root = $this-&gt;parent-&gt;theme_root;
+                else
+                        $theme_root = $this-&gt;theme_root;
+
+                return $theme_root . '/' . $this-&gt;template;
+        }
+
+        /**
+         * Returns the URL to the directory of a theme's &quot;stylesheet&quot; files.
+         *
+         * In the case of a child theme, this is the URL to the directory of the
+         * child theme's files.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string URL to the stylesheet directory.
+         */
+        public function get_stylesheet_directory_uri() {
+                return $this-&gt;get_theme_root_uri() . '/' . $this-&gt;stylesheet;
+        }
+
+        /**
+         * Returns the URL to the directory of a theme's &quot;template&quot; files.
+         *
+         * In the case of a child theme, this is the URL to the directory of the
+         * parent theme's files.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string URL to the template directory.
+         */
+        public function get_template_directory_uri() {
+                if ( $this-&gt;parent )
+                        $theme_root_uri = $this-&gt;parent-&gt;get_theme_root_uri();
+                else
+                        $theme_root_uri = $this-&gt;get_theme_root_uri();
+
+                return $theme_root . '/' . $this-&gt;template;
+        }
+
+        /**
+         * The absolute path to the directory of the theme root.
+         *
+         * This is typically the absolute path to wp-content/themes.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Theme root.
+         */
+        public function get_theme_root() {
+                return $this-&gt;theme_root;
+        }
+
+        /**
+         * Returns the URL to the directory of the theme root.
+         *
+         * This is typically the absolute path to wp-content/themes.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return string Theme root URI.
+         */
+        public function get_theme_root_uri() {
+                if ( 0 === strpos( WP_CONTENT_DIR, $this-&gt;theme_root ) )
+                        return str_replace( WP_CONTENT_DIR, content_url(), $this-&gt;theme_root );
+                // Give up, send it off to the filter.
+                return get_theme_root_uri( $this-&gt;stylesheet );
+        }
+
+        /**
+         * Returns the main screenshot file for the theme.
+         *
+         * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed.
+         *
+         * Screenshots for a theme must be in the stylesheet directory. (In the case of a child
+         * theme, a parent theme's screenshots are inherited.)
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param string $uri Type of URL to include, either relative or absolute. Defaults to relative.
+         * @return mixed Screenshot file. False if the theme does not have a screenshot.
+         */
+        public function get_screenshot( $uri = 'relative' ) {
+                $screenshot = $this-&gt;cache_get( 'screenshot' );
+                if ( $screenshot ) {
+                        if ( 'absolute' == $uri )
+                                return $this-&gt;get_stylesheet_directory_uri() . '/' . $screenshot;
+                        return $screenshot;
+                } elseif ( 0 === $screenshot ) {
+                        return false;
+                }
+
+                foreach ( array( 'png', 'gif', 'jpg', 'jpeg' ) as $ext ) {
+                        if ( file_exists( $this-&gt;get_stylesheet_directory() . &quot;/screenshot.$ext&quot; ) ) {
+                                $this-&gt;cache_add( 'screenshot', 'screenshot.' . $ext );
+                                if ( 'absolute' == $uri )
+                                        return $this-&gt;get_stylesheet_directory_uri() . '/' . 'screenshot.' . $ext;
+                                return 'screenshot.' . $ext;
+                        }
+                }
+
+                $this-&gt;cache_add( 'screenshot', 0 );
+                $this-&gt;cache_add( 'screenshot_count', 0 );
+                return false;
+        }
+
+        /**
+         * Returns the number of screenshots for a theme.
+         *
+         * The first screenshot may be called screenshot.png, .gif, or .jpg. Subsequent
+         * screenshots can be screenshot-2.png, screenshot-3.png, etc. The count must
+         * be consecutive for screenshots to be counted, and all screenshots beyond the
+         * initial one must be image/png files.
+         *
+         * @see WP_Theme::get_screenshot()
+         * @since 3.4.0
+         * @access public
+         *
+         * @return int Number of screenshots. Can be 0.
+         */
+        public function get_screenshot_count() {
+                $screenshot_count = $this-&gt;cache_get( 'screenshot_count' );
+                if ( is_numeric( $screenshot_count ) )
+                        return $screenshot_count;
+
+                // This will set the screenshot cache.
+                // If there is no screenshot, the screenshot_count cache will also be set.
+                if ( ! $screenshot = $this-&gt;get_screenshot() )
+                        return 0;
+
+                $prefix = $this-&gt;get_stylesheet() . '/screenshot-';
+                $files = self::scandir( $this-&gt;get_stylesheet_directory(), $this-&gt;get_stylesheet(), 'png', 0 );
+
+                $screenshot_count = 1;
+                while ( in_array( $prefix . ( $screenshot_count + 1 ) . '.png', $files['png'] ) )
+                        $screenshot_count++;
+
+                $this-&gt;cache_add( 'screenshot_count', $screenshot_count );
+                return $screenshot_count;
+        }
+
+        /**
+         * Returns an array of screenshot filenames.
+         *
+         * @see WP_Theme::get_screenshot()
+         * @see WP_Theme::get_screenshot_count()
+         * @since 3.4.0
+         * @access public
+         *
+         * @return array Screenshots.
+         */
+        public function get_screenshots() {
+                if ( ! $count = $this-&gt;get_screenshot_count() )
+                        return array();
+
+                $screenshots = array( $this-&gt;get_screenshot() );
+                for ( $i = 2; $i &lt;= $count; $i++ )
+                        $screenshots[] = 'screenshot-' . $i . '.png';
+                return $screenshots;
+        }
+
+        /**
+         * Return files in the template and stylesheet directories.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param string|null $type Optional. Type of files to return, either 'php' or 'css'. Defaults to null, for both.
+         * @return array If a specific $type is requested, returns an array of PHP files. If no $type is requested,
+         *         returns an array, with the keys being the file types, and the values being an array of files for those type.
+         */
+        public function get_files( $type = null, $include_parent_files = false ) {
+                $files = $this-&gt;cache_get( 'files' );
+                if ( ! is_array( $files ) ) {
+                        if ( $include_parent_files || ! $this-&gt;is_child_theme() )
+                                // Template files can be one level down for the purposes of the theme editor, so this should be $depth = 1.
+                                // Todo: We ignore this for now, but this is why the branching is weird.
+                                $files = (array) self::scandir( $this-&gt;get_template_directory(), $this-&gt;get_template(), array( 'php', 'css' ) );
+                        if ( $this-&gt;is_child_theme() )
+                                $files = array_merge_recursive( $files, (array) self::scandir( $this-&gt;get_stylesheet_directory(), $this-&gt;get_stylesheet(), array( 'php', 'css' ) ) );
+                        foreach ( $files as &amp;$group )
+                                sort( $group );
+                        $this-&gt;cache_add( 'files', $files );
+                }
+
+                if ( null === $type )
+                        return $files;
+                elseif ( isset( $files[ $type ] ) )
+                        return $files[ $type ];
+
+                return array();
+        }
+
+        public function get_page_templates() {
+                // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide.
+                if ( $this-&gt;errors() &amp;&amp; $this-&gt;errors()-&gt;get_error_codes() !== array( 'theme_parent_invalid' ) )
+                        return array();
+
+                $page_templates = $this-&gt;cache_get( 'page_templates' );
+                if ( is_array( $page_templates ) )
+                        return $page_templates;
+                $page_templates = array();
+
+                $files = (array) self::scandir( $this-&gt;get_template_directory(), $this-&gt;get_template_directory(), 'php' );
+                if ( $this-&gt;is_child_theme() )
+                        $files = array_merge_recursive( $files, (array) self::scandir( $this-&gt;get_stylesheet_directory(), $this-&gt;get_stylesheet_directory(), 'php' ) );
+
+                foreach ( $files['php'] as $file ) {
+                        $headers = get_file_data( $file, array( 'Name' =&gt; 'Template Name' ) );
+                        if ( empty( $headers['Name'] ) )
+                                continue;
+                        $page_templates[ $headers['Name'] ] = basename( $file );
+                }
+
+                $this-&gt;cache_add( 'page_templates', $page_templates );
+                return $page_templates;
+        }
+
+        /**
+         * Scans a directory for files of a certain extension.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param string $path Absolute path to search.
+         * @param string $relative_path The basename of the absolute path. Used to control the returned path
+         *         for the found files, particularly when this function recurses to lower depths.
+         * @param array|string $extensions Array of extensions to find, or string of a single extension.
+         * @depth int How deep to search for files. Optional, defaults to a flat scan (0 depth).
+         */
+        private static function scandir( $path, $relative_path, $extensions, $depth = 0 ) {
+                if ( is_array( $extensions ) )
+                        $extensions = implode( '|', $extensions );
+
+                if ( ! is_dir( $path ) )
+                        return false;
+
+                $results = scandir( $path );
+                $files = array();
+
+                foreach ( $results as $result ) {
+                        if ( '.' == $result || '..' == $result )
+                                continue;
+                        if ( is_dir( $path . '/' . $result ) ) {
+                                if ( ! $depth )
+                                        continue;
+                                $found = self::scandir( $path . '/' . $result, $relative_path . '/' . $result, $extensions, $depth - 1 );
+                                $files = array_merge_recursive( $files, $found );
+                        } elseif ( preg_match( '~\.(' . $extensions . ')$~', $result, $match ) ) {
+                                if ( ! isset( $files[ $match[1] ] ) )
+                                        $files[ $match[1] ] = array( $relative_path . '/'. $result );
+                                else
+                                        $files[ $match[1] ][] = $relative_path . '/' . $result;
+                        }
+                }
+                return $files;
+        }
+
+        /**
+         * Loads the theme's textdomain.
+         *
+         * Translation files are not inherited from the parent theme. Todo: if this fails for the
+         * child theme, it should probably try to load the parent theme's translations.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return True if the textdomain was successfully loaded or has already been loaded. False if
+         *         no textdomain was specified in the file headers, or if the domain could not be loaded.
+         */
+        public function load_textdomain() {
+                if ( isset( $this-&gt;textdomain_loaded ) )
+                        return $this-&gt;textdomain_loaded;
+
+                $textdomain = $this-&gt;get('TextDomain');
+                if ( ! $textdomain ) {
+                        $this-&gt;textdomain_loaded = false;
+                        return false;
+                }
+
+                if ( is_textdomain_loaded( $textdomain ) ) {
+                        $this-&gt;textdomain_loaded = true;
+                        return true;
+                }
+
+                $path = $this-&gt;get_stylesheet_directory();
+                if ( $domainpath = $this-&gt;get('DomainPath') )
+                        $path .= $domainpath;
+
+                $this-&gt;textdomain_loaded = load_theme_textdomain( $textdomain, $path );
+                return $this-&gt;textdomain_loaded;
+        }
+
+        /**
+         * Whether the theme is allowed (multisite only).
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site'
+         *         settings, or 'both'. Defaults to 'both'.
+         * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current blog.
+         * @return bool Whether the theme is allowed for the network. Returns true in single-site.
+         */
+        public function is_allowed( $check = 'both', $blog_id = null ) {
+                if ( ! is_multisite() )
+                        return true;
+
+                if ( 'both' == $check || 'network' == $check ) {
+                        $allowed = self::get_allowed_on_network();
+                        if ( ! empty( $allowed[ $this-&gt;get_stylesheet() ] ) )
+                                return true;
+                }
+
+                if ( 'both' == $check || 'site' == $check ) {
+                        $allowed = self::get_allowed_on_site( $blog_id );
+                        if ( ! empty( $allowed[ $this-&gt;get_stylesheet() ] ) )
+                                return true;
+                }
+
+                return false;
+        }
+
+        /**
+         * Returns array of stylesheet names of themes allowed on the site or network.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param int $blog_id Optional. Defaults to current blog.
+         * @return array Array of stylesheet names.
+         */
+        public static function get_allowed( $blog_id = null ) {
+                return array_merge( self::get_allowed_on_network(), self::get_allowed_on_site( $blog_id ) );
+        }
+
+        /**
+         * Returns array of stylesheet names of themes allowed on the network.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @return array Array of stylesheet names.
+         */
+        public static function get_allowed_on_network() {
+                static $allowed_themes;
+                if ( ! isset( $allowed_themes ) )
+                        $allowed_themes = (array) get_site_option( 'allowedthemes' );
+                return $allowed_themes;
+        }
+
+        /**
+         * Returns array of stylesheet names of themes allowed on the site.
+         *
+         * @since 3.4.0
+         * @access public
+         *
+         * @param int $blog_id Optional. Defaults to current blog.
+         * @return array Array of stylesheet names.
+         */
+        public static function get_allowed_on_site( $blog_id = null ) {
+                static $allowed_themes = array();
+                if ( ! $blog_id )
+                        $blog_id = get_current_blog_id();
+
+                if ( ! isset( $allowed_themes[ $blog_id ] ) ) {
+                        if ( $blog_id == get_current_blog_id() )
+                                $allowed_themes[ $blog_id ] = (array) get_option( 'allowedthemes' );
+                        else
+                                $allowed_themes[ $blog_id ] = (array) get_blog_option( $blog_id, 'allowedthemes' );
+                }
+
+                return $allowed_themes[ $blog_id ];
+        }
+
+        /**
+         * Sort themes by name.
+         */
+        public static function sort_by_name( &amp;$themes ) {
+                if ( 0 === strpos( get_locale(), 'en_' ) ) {
+                        uasort( $themes, array( 'WP_Theme', '_name_sort' ) );
+                } else {
+                        uasort( $themes, array( 'WP_Theme', '_name_sort_i18n' ) );
+                }
+        }
+
+        /**
+         * Callback function for usort() to naturally sort themes by name.
+         *
+         * Accesses the Name header directly from the class for maximum speed.
+         * Would choke on HTML but we don't care enough to slow it down with strip_tags().
+         *
+         * @since 3.4.0
+         * @access public
+         */
+        private static function _name_sort( $a, $b ) {
+                return strnatcasecmp( $a-&gt;headers['Name'], $b-&gt;headers['Name'] );
+        }
+
+        /**
+         * Name sort (with translation).
+         *
+         * @since 3.4.0
+         * @access public
+         */
+        private static function _name_sort_i18n( $a, $b ) {
+                // Don't mark up; Do translate.
+                return strnatcasecmp( $a-&gt;display( 'Name', false, true ), $b-&gt;display( 'Name', false, true ) );
+        }
+}
</ins></span></pre></div>
<a id="trunkwpincludesdeprecatedphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/deprecated.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/deprecated.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-includes/deprecated.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -2906,4 +2906,50 @@
</span><span class="cx">  */
</span><span class="cx"> function debug_fclose( $fp ) {
</span><span class="cx">         _deprecated_function( __FUNCTION__, 'error_log()' );
</span><ins>+}
+
+/**
+ * Retrieve list of themes with theme data in theme directory.
+ *
+ * The theme is broken, if it doesn't have a parent theme and is missing either
+ * style.css and, or index.php. If the theme has a parent theme then it is
+ * broken, if it is missing style.css; index.php is optional.
+ *
+ * @since 1.5.0
+ * @global array $wp_themes Stores the working themes.
+ *
+ * @return array Theme list with theme data.
+ */
+function get_themes() {
+        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_themes()' );
+
+        global $wp_themes;
+        if ( isset( $wp_themes ) )
+                return $wp_themes;
+
+        $themes = wp_get_themes();
+        $wp_themes = array();
+
+        foreach ( $themes as $theme ) {
+                $wp_themes[ $theme-&gt;get('Name') ] = $theme;
+        }
+
+        return $wp_themes;
+}
+
+/**
+ * Retrieve theme data.
+ *
+ * @since 1.5.0
+ *
+ * @param string $theme Theme name.
+ * @return array|null Null, if theme name does not exist. Theme data, if exists.
+ */
+function get_theme( $theme ) {
+        _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme($stylesheet)' );
+
+        $themes = get_themes();
+        if ( is_array( $themes ) &amp;&amp; array_key_exists( $theme, $themes ) )
+                return $themes[$theme];
+        return null;
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesthemephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/theme.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/theme.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-includes/theme.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -7,6 +7,95 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Returns an array of WP_Theme objects based on the arguments.
+ *
+ * Despite advances over get_themes(), this function is still quite expensive, and grows
+ * linearly with additional themes. Stick to wp_get_theme() if possible.
+ *
+ * @since 3.4.0
+ *
+ * @param array $args Arguments. Currently 'errors' (defaults to false), 'allowed'
+ *         (true, false; null for either; defaults to null; only applies to multisite), and 'blog_id'
+ *         (defaults to current blog; used to find allowed themes; only applies to multisite).
+ * @return Array of WP_Theme objects.
+ */
+function wp_get_themes( $args = array() ) {
+        global $wp_theme_directories;
+
+        $defaults = array( 'errors' =&gt; false, 'allowed' =&gt; null, 'blog_id' =&gt; 0 );
+        $args = wp_parse_args( $args, $defaults );
+
+        static $_themes;
+        if ( ! isset( $_themes ) ) {
+                $_themes = array();
+                $theme_data = search_theme_directories();
+                // Make sure the current theme wins out, in case search_theme_directories() picks the wrong
+                // one in the case of a conflict. (Normally, last registered theme root wins.)
+                $current_theme = get_stylesheet();
+                $current_theme_root = get_raw_theme_root( $current_theme );
+                if ( ! in_array( $current_theme_root, $wp_theme_directories ) )
+                        $current_theme_root = WP_CONTENT_DIR . $current_theme_root;
+                foreach ( (array) $theme_data as $theme_slug =&gt; $data ) {
+                        if ( $current_theme == $theme_slug &amp;&amp; $current_theme_root != $data['theme_root'] )
+                                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $current_theme_root );
+                        else
+                                $_themes[ $theme_slug ] = new WP_Theme( $theme_slug, $data['theme_root'] );
+                }
+        }
+
+        $themes = $_themes;
+        if ( empty( $themes ) )
+                return $themes;
+
+        if ( null !== $args['errors'] ) {
+                foreach ( $themes as $theme_slug =&gt; $theme ) {
+                        if ( $theme-&gt;errors() != $args['errors'] )
+                                unset( $themes[ $theme_slug ] );
+                }
+        }
+
+        if ( is_multisite() &amp;&amp; null !== $args['allowed'] ) {
+                if ( $allowed = $args['allowed'] ) {
+                        if ( 'network' == $allowed )
+                                $themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_network( $args['blog_id'] ) );
+                        elseif ( 'site' == $allowed )
+                                $themes = array_intersect_key( $themes, WP_Theme::get_allowed_on_site( $args['blog_id'] ) );
+                        else
+                                $themes = array_intersect_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
+                } else {
+                        $themes = array_diff_key( $themes, WP_Theme::get_allowed( $args['blog_id'] ) );
+                }
+        }
+
+        return $themes;
+}
+
+/**
+ * Gets a WP_Theme object for a theme.
+ *
+ * @since 3.4.0
+ *
+ * @param string $stylesheet Directory name for the theme. Optional. Defaults to current theme.
+ * @param string $theme_root Absolute path of the theme root to look in. Optional. If not specified, get_raw_theme_root()
+ *         is used to calculate the theme root for the $stylesheet provided (or current theme).
+ * @return WP_Theme
+ */
+function wp_get_theme( $stylesheet = null, $theme_root = null ) {
+        global $wp_theme_directories;
+
+        if ( empty( $stylesheet ) )
+                $stylesheet = get_stylesheet();
+
+        if ( empty( $theme_root ) ) {
+                $theme_root = get_raw_theme_root( $stylesheet );
+                if ( ! in_array( $theme_root, $wp_theme_directories ) )
+                        $theme_root = WP_CONTENT_DIR . $theme_root;
+        }
+
+        return new WP_Theme( $stylesheet, $theme_root );
+}
+
+/**
</ins><span class="cx">  * Whether a child theme is in use.
</span><span class="cx">  *
</span><span class="cx">  * @since 3.0.0
</span><span class="lines">@@ -247,218 +336,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Retrieve list of themes with theme data in theme directory.
- *
- * The theme is broken, if it doesn't have a parent theme and is missing either
- * style.css and, or index.php. If the theme has a parent theme then it is
- * broken, if it is missing style.css; index.php is optional. The broken theme
- * list is saved in the {@link $wp_broken_themes} global, which is displayed on
- * the theme list in the administration panels.
- *
- * @since 1.5.0
- * @global array $wp_broken_themes Stores the broken themes.
- * @global array $wp_themes Stores the working themes.
- *
- * @return array Theme list with theme data.
- */
-function get_themes() {
-        global $wp_themes, $wp_broken_themes;
-
-        if ( isset($wp_themes) )
-                return $wp_themes;
-
-        if ( !$theme_files = search_theme_directories() )
-                return false;
-
-        asort( $theme_files );
-
-        $wp_themes = array();
-
-        foreach ( (array) $theme_files as $theme_file ) {
-                $theme_root = $theme_file['theme_root'];
-                $theme_file = $theme_file['theme_file'];
-
-                if ( !is_readable(&quot;$theme_root/$theme_file&quot;) ) {
-                        $wp_broken_themes[$theme_file] = array('Name' =&gt; $theme_file, 'Title' =&gt; $theme_file, 'Description' =&gt; __('File not readable.'));
-                        continue;
-                }
-
-                $theme_data = get_theme_data(&quot;$theme_root/$theme_file&quot;);
-
-                $name        = $theme_data['Name'];
-                $title       = $theme_data['Title'];
-                $description = wptexturize($theme_data['Description']);
-                $version     = $theme_data['Version'];
-                $author      = $theme_data['Author'];
-                $template    = $theme_data['Template'];
-                $stylesheet  = dirname($theme_file);
-
-                $screenshot = false;
-                foreach ( array('png', 'gif', 'jpg', 'jpeg') as $ext ) {
-                        if (file_exists(&quot;$theme_root/$stylesheet/screenshot.$ext&quot;)) {
-                                $screenshot = &quot;screenshot.$ext&quot;;
-                                break;
-                        }
-                }
-
-                if ( empty($name) ) {
-                        $name = dirname($theme_file);
-                        $title = $name;
-                }
-
-                $parent_template = $template;
-
-                if ( empty($template) ) {
-                        if ( file_exists(&quot;$theme_root/$stylesheet/index.php&quot;) )
-                                $template = $stylesheet;
-                        else
-                                continue;
-                }
-
-                $template = trim( $template );
-
-                if ( !file_exists(&quot;$theme_root/$template/index.php&quot;) ) {
-                        $parent_dir = dirname(dirname($theme_file));
-                        if ( file_exists(&quot;$theme_root/$parent_dir/$template/index.php&quot;) ) {
-                                $template = &quot;$parent_dir/$template&quot;;
-                                $template_directory = &quot;$theme_root/$template&quot;;
-                        } else {
-                                /**
-                                 * The parent theme doesn't exist in the current theme's folder or sub folder
-                                 * so lets use the theme root for the parent template.
-                                 */
-                                if ( isset($theme_files[$template]) &amp;&amp; file_exists( $theme_files[$template]['theme_root'] . &quot;/$template/index.php&quot; ) ) {
-                                        $template_directory = $theme_files[$template]['theme_root'] . &quot;/$template&quot;;
-                                } else {
-                                        if ( empty( $parent_template) )
-                                                $wp_broken_themes[$name] = array('Name' =&gt; $name, 'Title' =&gt; $title, 'Description' =&gt; __('Template is missing.'), 'error' =&gt; 'no_template');
-                                        else
-                                                $wp_broken_themes[$name] = array('Name' =&gt; $name, 'Title' =&gt; $title, 'Description' =&gt; sprintf( __('The parent theme is missing. Please install the &quot;%s&quot; parent theme.'),  $parent_template ), 'error' =&gt; 'no_parent', 'parent' =&gt; $parent_template );
-                                        continue;
-                                }
-
-                        }
-                } else {
-                        $template_directory = trim( $theme_root . '/' . $template );
-                }
-
-                $stylesheet_files = array();
-                $template_files = array();
-
-                $stylesheet_dir = @ dir(&quot;$theme_root/$stylesheet&quot;);
-                if ( $stylesheet_dir ) {
-                        while ( ($file = $stylesheet_dir-&gt;read()) !== false ) {
-                                if ( !preg_match('|^\.+$|', $file) ) {
-                                        if ( preg_match('|\.css$|', $file) )
-                                                $stylesheet_files[] = &quot;$theme_root/$stylesheet/$file&quot;;
-                                        elseif ( preg_match('|\.php$|', $file) )
-                                                $template_files[] = &quot;$theme_root/$stylesheet/$file&quot;;
-                                }
-                        }
-                        @ $stylesheet_dir-&gt;close();
-                }
-
-                $template_dir = @ dir(&quot;$template_directory&quot;);
-                if ( $template_dir ) {
-                        while ( ($file = $template_dir-&gt;read()) !== false ) {
-                                if ( preg_match('|^\.+$|', $file) )
-                                        continue;
-                                if ( preg_match('|\.php$|', $file) ) {
-                                        $template_files[] = &quot;$template_directory/$file&quot;;
-                                } elseif ( is_dir(&quot;$template_directory/$file&quot;) ) {
-                                        $template_subdir = @ dir(&quot;$template_directory/$file&quot;);
-                                        if ( !$template_subdir )
-                                                continue;
-                                        while ( ($subfile = $template_subdir-&gt;read()) !== false ) {
-                                                if ( preg_match('|^\.+$|', $subfile) )
-                                                        continue;
-                                                if ( preg_match('|\.php$|', $subfile) )
-                                                        $template_files[] = &quot;$template_directory/$file/$subfile&quot;;
-                                        }
-                                        @ $template_subdir-&gt;close();
-                                }
-                        }
-                        @ $template_dir-&gt;close();
-                }
-
-                //Make unique and remove duplicates when stylesheet and template are the same i.e. most themes
-                $template_files = array_unique($template_files);
-                $stylesheet_files = array_unique($stylesheet_files);
-
-                $template_dir = $template_directory;
-                $stylesheet_dir = $theme_root . '/' . $stylesheet;
-
-                if ( empty($template_dir) )
-                        $template_dir = '/';
-                if ( empty($stylesheet_dir) )
-                        $stylesheet_dir = '/';
-
-                // Check for theme name collision. This occurs if a theme is copied to
-                // a new theme directory and the theme header is not updated. Whichever
-                // theme is first keeps the name. Subsequent themes get a suffix applied.
-                // Default themes themes always trump their pretenders.
-                if ( isset($wp_themes[$name]) ) {
-                        $trump_cards = array(
-                                'classic'      =&gt; 'WordPress Classic',
-                                'default'      =&gt; 'WordPress Default',
-                                'twentyten'    =&gt; 'Twenty Ten',
-                                'twentyeleven' =&gt; 'Twenty Eleven',
-                                'twentytwelve' =&gt; 'Twenty Twelve',
-                        );
-                        if ( isset( $trump_cards[ $stylesheet ] ) &amp;&amp; $name == $trump_cards[ $stylesheet ] ) {
-                                // If another theme has claimed to be one of our default themes, move
-                                // them aside.
-                                $suffix = $wp_themes[$name]['Stylesheet'];
-                                $new_name = &quot;$name/$suffix&quot;;
-                                $wp_themes[$new_name] = $wp_themes[$name];
-                                $wp_themes[$new_name]['Name'] = $new_name;
-                        } else {
-                                $name = &quot;$name/$stylesheet&quot;;
-                        }
-                }
-
-                $wp_themes[$name] = array(
-                        'Name' =&gt; $name,
-                        'Title' =&gt; $title,
-                        'Description' =&gt; $description,
-                        'Author' =&gt; $author,
-                        'Author Name' =&gt; $theme_data['AuthorName'],
-                        'Author URI' =&gt; $theme_data['AuthorURI'],
-                        'Version' =&gt; $version,
-                        'Template' =&gt; $template,
-                        'Stylesheet' =&gt; $stylesheet,
-                        'Template Files' =&gt; $template_files,
-                        'Stylesheet Files' =&gt; $stylesheet_files,
-                        'Template Dir' =&gt; $template_dir,
-                        'Stylesheet Dir' =&gt; $stylesheet_dir,
-                        'Status' =&gt; $theme_data['Status'],
-                        'Screenshot' =&gt; $screenshot,
-                        'Tags' =&gt; $theme_data['Tags'],
-                        'Theme Root' =&gt; $theme_root,
-                        'Theme Root URI' =&gt; str_replace( WP_CONTENT_DIR, content_url(), $theme_root ),
-                );
-        }
-
-        unset($theme_files);
-
-        /* Resolve theme dependencies. */
-        $theme_names = array_keys( $wp_themes );
-        foreach ( (array) $theme_names as $theme_name ) {
-                $wp_themes[$theme_name]['Parent Theme'] = '';
-                if ( $wp_themes[$theme_name]['Stylesheet'] != $wp_themes[$theme_name]['Template'] ) {
-                        foreach ( (array) $theme_names as $parent_theme_name ) {
-                                if ( ($wp_themes[$parent_theme_name]['Stylesheet'] == $wp_themes[$parent_theme_name]['Template']) &amp;&amp; ($wp_themes[$parent_theme_name]['Template'] == $wp_themes[$theme_name]['Template']) ) {
-                                        $wp_themes[$theme_name]['Parent Theme'] = $wp_themes[$parent_theme_name]['Name'];
-                                        break;
-                                }
-                        }
-                }
-        }
-
-        return $wp_themes;
-}
-
-/**
</del><span class="cx">  * Retrieve theme roots.
</span><span class="cx">  *
</span><span class="cx">  * @since 2.9.0
</span><span class="lines">@@ -480,23 +357,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Retrieve theme data.
- *
- * @since 1.5.0
- *
- * @param string $theme Theme name.
- * @return array|null Null, if theme name does not exist. Theme data, if exists.
- */
-function get_theme($theme) {
-        $themes = get_themes();
-
-        if ( is_array( $themes ) &amp;&amp; array_key_exists( $theme, $themes ) )
-                return $themes[$theme];
-
-        return null;
-}
-
-/**
</del><span class="cx">  * Retrieve current theme display name.
</span><span class="cx">  *
</span><span class="cx">  * If the 'current_theme' option has already been set, then it will be returned
</span><span class="lines">@@ -508,29 +368,10 @@
</span><span class="cx">  * @return string
</span><span class="cx">  */
</span><span class="cx"> function get_current_theme() {
</span><del>-        if ( $theme = get_option('current_theme') )
</del><ins>+        if ( $theme = get_option( 'current_theme' ) )
</ins><span class="cx">                 return $theme;
</span><span class="cx"> 
</span><del>-        $themes = get_themes();
-        $current_theme = 'Twenty Eleven';
-
-        if ( $themes ) {
-                $theme_names = array_keys( $themes );
-                $current_template = get_option( 'template' );
-                $current_stylesheet = get_option( 'stylesheet' );
-
-                foreach ( (array) $theme_names as $theme_name ) {
-                        if ( $themes[$theme_name]['Stylesheet'] == $current_stylesheet &amp;&amp;
-                                        $themes[$theme_name]['Template'] == $current_template ) {
-                                $current_theme = $themes[$theme_name]['Name'];
-                                break;
-                        }
-                }
-        }
-
-        update_option('current_theme', $current_theme);
-
-        return $current_theme;
</del><ins>+        return wp_get_theme()-&gt;get('Name');
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span></span></pre></div>
<a id="trunkwpincludesupdatephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/update.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/update.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-includes/update.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -235,32 +235,29 @@
</span><span class="cx">         if ( defined( 'WP_INSTALLING' ) )
</span><span class="cx">                 return false;
</span><span class="cx"> 
</span><del>-        if ( !function_exists( 'get_themes' ) )
-                require_once( ABSPATH . 'wp-includes/theme.php' );
-
-        $installed_themes = get_themes( );
</del><ins>+        $installed_themes = wp_get_themes();
</ins><span class="cx">         $last_update = get_site_transient( 'update_themes' );
</span><span class="cx">         if ( ! is_object($last_update) )
</span><span class="cx">                 $last_update = new stdClass;
</span><span class="cx"> 
</span><span class="cx">         $themes = array();
</span><span class="cx">         $checked = array();
</span><del>-        $exclude_fields = array('Template Files', 'Stylesheet Files', 'Status', 'Theme Root', 'Theme Root URI', 'Template Dir', 'Stylesheet Dir', 'Description', 'Tags', 'Screenshot');
</del><span class="cx"> 
</span><span class="cx">         // Put slug of current theme into request.
</span><span class="cx">         $themes['current_theme'] = get_option( 'stylesheet' );
</span><span class="cx"> 
</span><del>-        foreach ( (array) $installed_themes as $theme_title =&gt; $theme ) {
-                $themes[$theme['Stylesheet']] = array();
-                $checked[$theme['Stylesheet']] = $theme['Version'];
</del><ins>+        foreach ( $installed_themes as $theme ) {
+                $checked[ $theme-&gt;get_stylesheet() ] = $theme-&gt;get('Version');
</ins><span class="cx"> 
</span><del>-                $themes[$theme['Stylesheet']]['Name'] = $theme['Name'];
-                $themes[$theme['Stylesheet']]['Version'] = $theme['Version'];
-
-                foreach ( (array) $theme as $key =&gt; $value ) {
-                        if ( !in_array($key, $exclude_fields) )
-                                $themes[$theme['Stylesheet']][$key] = $value;
-                }
</del><ins>+                $themes[ $theme-&gt;get_stylesheet() ] = array(
+                        'Name'       =&gt; $theme-&gt;get('Name'),
+                        'Title'      =&gt; $theme-&gt;get('Name'),
+                        'Version'    =&gt; $theme-&gt;get('Version'),
+                        'Author'     =&gt; $theme-&gt;get('Author'),
+                        'Author URI' =&gt; $theme-&gt;get('AuthorURI'),
+                        'Template'   =&gt; $theme-&gt;get_template(),
+                        'Stylesheet' =&gt; $theme-&gt;get_stylesheet(),
+                );
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Check for update on a different schedule, depending on the page.
</span></span></pre></div>
<a id="trunkwpsettingsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-settings.php (20028 => 20029)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-settings.php        2012-02-28 21:21:16 UTC (rev 20028)
+++ trunk/wp-settings.php        2012-02-28 21:24:44 UTC (rev 20029)
</span><span class="lines">@@ -112,6 +112,7 @@
</span><span class="cx"> require( ABSPATH . WPINC . '/capabilities.php' );
</span><span class="cx"> require( ABSPATH . WPINC . '/query.php' );
</span><span class="cx"> require( ABSPATH . WPINC . '/theme.php' );
</span><ins>+require( ABSPATH . WPINC . '/class-wp-theme.php' );
</ins><span class="cx"> require( ABSPATH . WPINC . '/template.php' );
</span><span class="cx"> require( ABSPATH . WPINC . '/user.php' );
</span><span class="cx"> require( ABSPATH . WPINC . '/meta.php' );
</span></span></pre>
</div>
</div>

</body>
</html>