<!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>[12186] sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php: Theme Directory: Allow core committers to upload default themes, both updates and new default themes.</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 { white-space: pre-line; 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 { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { 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" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/12186">12186</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/12186","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-11-02 03:16:40 +0000 (Wed, 02 Nov 2022)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Theme Directory: Allow core committers to upload default themes, both updates and new default themes.

This also allows for default themes (any theme owned by WordPress.org) to bypass Theme Check failures, which happens due to the unexpected slugs.

Previously <a href="http://meta.trac.wordpress.org/changeset/10927">[10927]</a>, <a href="http://meta.trac.wordpress.org/changeset/11479">[11479]</a>, and others.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsthemedirectoryclasswporgthemesuploadphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsthemedirectoryclasswporgthemesuploadphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php    2022-11-02 02:06:55 UTC (rev 12185)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php      2022-11-02 03:16:40 UTC (rev 12186)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -444,6 +444,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Default Theme handling.
+               if (
+                       // Reserved slugs include twenty* and other terms
+                       $this->has_reserved_slug() &&
+                       // ...so limit to twenty* only
+                       str_starts_with( $this->theme_slug, 'twenty' ) &&
+                       // The current user is a Core Committer. [ 'user_login' => 'Trac Title', ... ]
+                       ! empty( $GLOBALS['committers'][ $this->author->user_login ] ) &&
+                       (
+                               // New theme submission
+                               ! $this->theme_post
+                               ||
+                               // OR an Update and the theme is owned by WordPress.org.
+                               'wordpressdotorg' === get_user_by( 'id', $this->theme_post->post_author )->user_login
+                       )
+               ) {
+                       // Set the author to WordPress.org
+                       $this->author = get_user_by( 'login', 'wordpressdotorg' );
+
+                       // WordPress.org is allowed to bypass Theme Check, see further down.
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Make sure it doesn't use a slug deemed not to be used by the public.
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $this->has_reserved_slug() ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $style_errors->add(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -558,29 +580,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        ! empty( $this->author ) &&
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->theme_post->post_author != $this->author->ID
</span><span class="cx" style="display: block; padding: 0 10px">                ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                       $is_allowed_to_upload_for_theme = false;
-                       if (
-                               // The theme is owned by WordPress.org.
-                               'wordpressdotorg' === get_user_by( 'id', $this->theme_post->post_author )->user_nicename &&
-                               // The current user is a Core Committer. [ 'user_login' => 'Trac Title', ... ]
-                               ! empty( $GLOBALS['committers'][ $this->author->user_login ] )
-                       ) {
-                               // Allow core committers to update default themes (as authored by @wordpressdotorg)
-                               $is_allowed_to_upload_for_theme = true;
-                       }
-
-                       if ( ! $is_allowed_to_upload_for_theme ) {
-                               $style_errors->add(
-                                       'cannot_upload_theme',
-                                       sprintf(
-                                               /* translators: 1: theme slug, 2: style.css */
-                                               __( 'There is already a theme called %1$s by a different author. Please change the name of your theme in %2$s and upload it again.', 'wporg-themes' ),
-                                               '<code>' . $this->theme_slug . '</code>',
-                                               '<code>style.css</code>'
-                                       ) . $are_you_in_the_right_place
-                               );
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $style_errors->add(
+                               'cannot_upload_theme',
+                               sprintf(
+                                       /* translators: 1: theme slug, 2: style.css */
+                                       __( 'There is already a theme called %1$s by a different author. Please change the name of your theme in %2$s and upload it again.', 'wporg-themes' ),
+                                       '<code>' . $this->theme_slug . '</code>',
+                                       '<code>style.css</code>'
+                               ) . $are_you_in_the_right_place
+                       );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Check if the ThemeURI is already in use by another theme by another author.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -651,9 +659,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return $style_errors;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Don't block special themes based on Theme Check.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Don't block special themes or default themes based on Theme Check.
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( has_category( 'special-case-theme', $this->theme_post ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $args['block_on_themecheck'] = false;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                } elseif ( 'wordpressdotorg' === get_user_by( 'id', $this->theme_post->post_author )->user_login ) {
+                       $args['block_on_themecheck'] = false;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Pass it through Theme Check and see how great this theme really is.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -989,20 +999,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Only committers uploading a default theme *update* are left to be checked for.
-               // New default themes MUST be uploaded by `wordpressdotorg` and will fail this check.
-               if (
-                       // Updates only.
-                       $this->theme_post &&
-                       // The current user is a Core Committer. [ 'user_login' => 'Trac Title', ... ]
-                       ! empty( $GLOBALS['committers'][ $this->author->user_login ] ) &&
-                       // The theme is owned by WordPress.org.
-                       'wordpressdotorg' === get_user_by( 'id', $this->theme_post->post_author )->user_login
-               ) {
-                       // Slug is reserved, but an update is being uploaded by a core committer.
-                       return false;
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 // Slug is reserved, user is not authorized.
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1198,6 +1194,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->trac = new Trac( 'themetracbot', THEME_TRACBOT_PASSWORD, 'https://themes.trac.wordpress.org/login/xmlrpc' );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                /*
+                * Trac reporter is always the authenticated user, unless it's not-auth'd in which case it's the Theme Author.
+                *
+                * This allows for Committers to upload Default themes under 'WordPress.org' but it still be to noted on Trac who uploaded it.
+                * This also allows for SVN imports where the current user is not set.
+                */
+               $trac_ticket_reporter = wp_get_current_user()->user_login ?? $this->author->user_login;
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // If there's a previous version and the most current version's status is `new`, we update.
</span><span class="cx" style="display: block; padding: 0 10px">                if (
</span><span class="cx" style="display: block; padding: 0 10px">                        ! empty( $this->theme_post->max_version ) &&
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1214,7 +1218,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $ticket_id = $this->trac->ticket_create( $this->trac_ticket->summary, $this->trac_ticket->description, array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'type'      => 'theme',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'keywords'  => implode( ' ', $this->trac_ticket->keywords ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        'reporter'  => $this->author->user_login,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 'reporter'  => $trac_ticket_reporter,
</ins><span class="cx" style="display: block; padding: 0 10px">                                         'cc'        => $this->author->user_email,
</span><span class="cx" style="display: block; padding: 0 10px">                                        'priority'  => $this->trac_ticket->priority,
</span><span class="cx" style="display: block; padding: 0 10px">                                        'owner'     => '',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1226,7 +1230,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $ticket_id = $this->trac->ticket_create( $this->trac_ticket->summary, $this->trac_ticket->description, array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'type'      => 'theme',
</span><span class="cx" style="display: block; padding: 0 10px">                                'keywords'  => implode( ' ', $this->trac_ticket->keywords ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                'reporter'  => $this->author->user_login,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         'reporter'  => $trac_ticket_reporter,
</ins><span class="cx" style="display: block; padding: 0 10px">                                 'cc'        => $this->author->user_email,
</span><span class="cx" style="display: block; padding: 0 10px">                                'priority'  => $this->trac_ticket->priority,
</span><span class="cx" style="display: block; padding: 0 10px">                                'owner'     => '',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1533,19 +1537,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $emails = [
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Email the Theme Author(s). The uploader & theme author may differ in special cases (default themes).
+               $emails = array_filter( array_unique( [
+                       // The theme author
</ins><span class="cx" style="display: block; padding: 0 10px">                         $this->author->user_email,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // The theme Author (usually the same)
+                       get_user_by( 'id', $this->theme_post->post_author )->user_email ?? false,
+                       // The current user (also, usually the same)
+                       wp_get_current_user()->user_email
+               ] ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // If the uploader and the author are different, email them both.
-               // This only happens under special circumstances.
-               if (
-                       ! empty( $this->theme_post ) &&
-                       $this->theme_post->post_author != $this->author->ID
-               ) {
-                       $emails[] = get_user_by( 'id', $this->theme_post->post_author )->user_email;
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 wp_mail( $emails, $email_subject, $email_content, 'From: "WordPress Theme Directory" <themes@wordpress.org>' );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>