Index: sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-hooks.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-hooks.php	(revision 9773)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-hooks.php	(date 1587682791514)
@@ -488,6 +488,13 @@
 			) {
 				$robots = true;
 			}
+
+			// If topic is marked as NSFW.
+			$is_nsfw = get_post_meta( bbp_get_topic_id(), '_topic_is_nsfw', true );
+
+			if ( $is_nsfw ) {
+				$robots = true;
+			}
 		}
 
 		if ( $robots ) {
Index: sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-nsfw-handler.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-nsfw-handler.php	(date 1587684112492)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-nsfw-handler.php	(date 1587684112492)
@@ -0,0 +1,199 @@
+<?php
+
+namespace WordPressdotorg\Forums;
+
+class NSFW_Handler {
+
+	public function __construct() {
+		add_action( 'init', array( $this, 'register_taxonomy' ) );
+
+		add_action( 'bbp_new_topic_post_extras', array( $this, 'manually_assign_nsfw_flag' ), 10 );
+		add_action( 'bbp_edit_topic_post_extras', array( $this, 'manually_assign_nsfw_flag' ), 10 );
+
+		add_action( 'bbp_new_topic_post_extras', array( $this, 'maybe_flag_nsfw_automatically' ), 11 );
+		add_action( 'bbp_edit_topic_post_extras', array( $this, 'maybe_flag_nsfw_automatically' ), 11 );
+
+		add_action( 'nsfw_terms_add_form_fields', array( $this, 'add_term_meta' ) );
+
+		add_action( 'bbp_theme_before_topic_form_subscriptions', array( $this, 'mark_topic_nsfw_form_field' ) );
+
+		add_filter( 'bbp_get_topic_title', array( $this, 'prepend_topic_title' ), 10, 2 );
+
+		add_action( 'admin_head', array( $this, 'taxonomy_styles' ) );
+	}
+
+	/**
+	 * Provide additional term meta fields.
+	 */
+	public function add_term_meta() {
+	    // Output a helping text indicating what to use the description field for.
+	    echo '<p>' . __( 'Please provide a reason for adding this term in the description field', 'wporg-forums' ) . '</p>';
+    }
+
+	/**
+	 * Output some CSS to keep the NSFW term interface as simple as possible.
+	 */
+    public function taxonomy_styles() {
+	    if ( ! isset( $_GET['taxonomy'] ) || 'nsfw_terms' !== $_GET['taxonomy'] ) {
+	        return;
+        }
+
+	    ?>
+
+        <style type="text/css">
+            body.taxonomy-nsfw_terms .term-slug-wrap {
+                display: none;
+            }
+            body.taxonomy-nsfw_terms .column-posts,
+            body.taxonomy-nsfw_terms .column-slug {
+                display: none;
+            }
+        </style>
+
+        <?php
+    }
+
+	public function register_taxonomy() {
+		register_taxonomy(
+			'nsfw_terms',
+			'forum',
+			array(
+				'labels' => array(
+					'name' => __( 'NSFW Terms', 'wporg-forums' ),
+				),
+				'description'   => __( 'Declare terms for mature content that the forums will automatically mark not safe for work (NSFW)', 'wporg-forums' ),
+				'public'        => false,
+				'show_ui'       => true,
+				'show_in_menu'  => true,
+				'show_in_rest'  => false,
+				'show_tagcloud' => false,
+				'show_in_quick_edit' => false,
+				'capabilities' => array(
+					'keep_gate',
+				),
+			)
+		);
+	}
+
+	/**
+     * Helper to check if a topic is in a forum that should get the added features of this file.
+     *
+	 * @param $topic_id
+	 *
+	 * @return bool
+	 */
+	private function topic_in_affected_forum( $topic_id ) {
+	    return ( Plugin::REVIEWS_FORUM_ID != bbp_get_topic_forum_id( $topic_id ) && ( ! bbp_is_single_view() || 'reviews' !== bbp_get_view_id() ) );
+    }
+
+	/**
+	 * Output an additional form field when creating or editing a topic to mark it as containing mature content.
+	 */
+	public function mark_topic_nsfw_form_field() {
+		$topic_id = bbp_get_topic_id();
+
+		if ( $this->topic_in_affected_forum( $topic_id ) ) {
+			$checked = false;
+
+			if ( bbp_is_topic_edit() ) {
+				$checked = get_post_meta( $topic_id, '_topic_is_nsfw', true );
+			}
+
+			?>
+
+			<p>
+				<label for="topic-is-nsfw">
+					<input type="checkbox" name="topic_is_nsfw" id="topic-is-nsfw" <?php checked( true, $checked ); ?>>
+					<?php esc_html_e( 'This topic relates to mature content and may be considered Not Safe For Work (NSFW)', 'wporg-forums' ); ?>
+				</label>
+			</p>
+
+			<?php
+		}
+	}
+
+	/**
+     * Capture manually assigned mature content from form submissions.
+     *
+	 * @param $topic_id
+	 */
+	public function manually_assign_nsfw_flag( $topic_id ) {
+	    if ( ! $this->topic_in_affected_forum( $topic_id ) ) {
+	        return;
+        }
+
+		if ( isset( $_POST['topic_is_nsfw'] ) ) {
+			update_post_meta( $topic_id, '_topic_is_nsfw', true );
+		} else {
+			update_post_meta( $topic_id, '_topic_is_nsfw', false );
+		}
+	}
+
+	/**
+     * Automatically test if a topic might contain mature content when being published.
+     *
+	 * @param $topic_id
+	 */
+	public function maybe_flag_nsfw_automatically( $topic_id ) {
+		// If the topic was manually flagged, save some processing by not seeing if it needs automatic flagging.
+		if ( isset( $_POST['topic_is_nsfw'] ) ) {
+			return;
+		}
+
+		/* Skip checking for moderators, this is so that the flagging happens even on edits
+		 * by users, but allows mods to force-remove the tag if needed.
+		 */
+		if ( current_user_can( 'moderate' ) ) {
+		    return;
+        }
+
+		$topic_title = bbp_get_topic_title( $topic_id );
+		$topic_url   = ( isset( $_POST['site_url'] ) && ! empty( $_POST['site_url'] ) ? $_POST['site_url'] : null );
+
+		$terms = get_terms(
+			array(
+                'taxonomy'   => 'nsfw_terms',
+                'hide_empty' => false,
+			)
+		);
+
+		foreach ( $terms as $term ) {
+		    // If the term is found in the title or URL field, mark it as NSFW and stop processing.
+			if ( stristr( $topic_title, $term->name ) || ( null !== $topic_url && stristr( $topic_url, $term->name ) ) ) {
+				update_post_meta( $topic_id, '_topic_is_nsfw', true );
+			    return;
+            }
+		}
+	}
+
+	/**
+     * Add a NSFW tag to any title marked as such.
+     *
+	 * @param $title
+	 * @param $topic_id
+	 *
+	 * @return string
+	 */
+	public function prepend_topic_title( $title, $topic_id ) {
+		$is_nsfw = get_post_meta( $topic_id, '_topic_is_nsfw', true );
+
+		if ( ! $is_nsfw ) {
+			return $title;
+		}
+
+		$prefix = sprintf(
+            '<abbr title="%s">%s</abbr>',
+            // translators: Explanation of what the abbreviation NSFW means.
+            esc_attr( __( 'Not Safe For Work / Mature content', 'wporg-forums' ) ),
+			// translators: Prepended titles for topics with mature content.
+            __( '[NSFW]', 'wporg-forums' )
+        );
+
+		return sprintf(
+			'%s %s',
+			$prefix,
+			$title
+		);
+	}
+
+}
Index: sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-plugin.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-plugin.php	(revision 9773)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-plugin.php	(date 1587676367860)
@@ -42,6 +42,7 @@
 		$this->moderators   = new Moderators;
 		$this->hooks        = new Hooks;
 		$this->report_topic = new Report_Topic;
+		$this->nsfw_handler = new NSFW_Handler;
 
 		// These modifications are specific to https://wordpress.org/support/
 		$blog_id = get_current_blog_id();
Index: sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/support-forums.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/support-forums.php	(revision 9773)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/support-forums.php	(date 1587676336556)
@@ -25,6 +25,7 @@
 include( dirname( __FILE__ ) . '/inc/class-moderators.php' );
 include( dirname( __FILE__ ) . '/inc/class-hooks.php' );
 include( dirname( __FILE__ ) . '/inc/class-report-topic.php' );
+include( dirname( __FILE__ ) . '/inc/class-nsfw-handler.php' );
 
 // Compat-only includes.
 include( dirname( __FILE__ ) . '/inc/class-dropin.php' );
