<!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>[10927] sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php: Theme Directory: Allow  default theme uploads by core committers.</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/10927">10927</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/10927","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>2021-04-27 03:08:01 +0000 (Tue, 27 Apr 2021)</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  default theme uploads by core committers.

This allows the twenty* themes to be updated by any current core committer, removing the need for an extra special person available during release windows.

Trac will reflect the user who uploads the theme, but the theme will remain owned by WordPress.org.

New default themes will still be limited to being uploaded by the WordPress.org user, this only controls updates.</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    2021-04-26 23:09:28 UTC (rev 10926)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php      2021-04-27 03:08:01 UTC (rev 10927)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -239,6 +239,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->author = wp_get_current_user();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // This check must be run before `get_theme_post()` to account for "twenty" themes.
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( $this->has_reserved_slug() ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        /* translators: 1: theme slug, 2: style.css */
</span><span class="cx" style="display: block; padding: 0 10px">                        return sprintf( __( 'Sorry, the theme name %1$s is reserved for use by WordPress Core. Please change the name of your theme in %2$s and upload it again.', 'wporg-themes' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -326,11 +327,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Is there already a theme with the name name by a different author?
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! empty( $this->theme_post ) && $this->theme_post->post_author != $this->author->ID ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        /* translators: 1: theme slug, 2: style.css */
-                       return sprintf( __( '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">+
+                       $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 ) {
+                               /* translators: 1: theme slug, 2: style.css */
+                               return sprintf( __( '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">@@ -673,12 +688,40 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'featured', 'popular', 'new', 'updated',
</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">-                // force the slug to be correct for the twenty-x themes
-               if ( in_array( $slug, $reserved_slugs ) && 'wordpressdotorg' == $this->author->user_login ) {
-                       $this->theme_slug = $slug;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // If it's not a reserved slug, they can have it.
+               if (
+                       ! in_array( $slug, $reserved_slugs, true ) &&
+                       ! in_array( $this->theme_slug, $reserved_slugs, true )
+               ) {
+                       return false;
</ins><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">-                return in_array( $slug, $reserved_slugs ) && 'wordpressdotorg' !== $this->author->user_login;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // force the slug to be correct for the twenty-x themes.
+               $this->theme_slug = $slug;
+
+               // WordPress.org user is always allowed to upload reserved slugs.
+               if ( 'wordpressdotorg' === $this->author->user_login ) {
+                       return false;
+               }
+
+               // Only committers uploading a default theme *update* are left to be checked for.
+               $theme_post = $this->get_theme_post();
+
+               // New default themes MUST be uploaded by `wordpressdotorg` and will fail this check.
+               if (
+                       // Updates only.
+                       $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', $theme_post->post_author )->user_login
+               ) {
+                       // Slug is reserved, but an update is being uploaded by a core committer.
+                       return false;
+               }
+
+               // Slug is reserved, user is not authorized.
+               return true;
</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">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1145,7 +1188,17 @@
</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">-                wp_mail( $this->author->user_email, $email_subject, $email_content, 'From: "WordPress Theme Directory" <themes@wordpress.org>' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $emails = [
+                       $this->author->user_email,
+               ];
+
+               // 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;
+               }
+
+               wp_mail( $emails, $email_subject, $email_content, 'From: "WordPress Theme Directory" <themes@wordpress.org>' );
</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">        /**
</span></span></pre>
</div>
</div>

</body>
</html>