__( 'Single Feature Request', 'feature-request-system' ), 'description' => __( 'Shows one feature request: its vote button, status, description and comments.', 'feature-request-system' ), 'content' => (string) file_get_contents( $file ), // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- A local file of this plugin. ] ); } } /** * Adds the details above the description of the request being viewed, unless its * template already has them, and the official response below. * * @param string $content Formatted post content. */ public static function add_to_content( string $content ): string { if ( self::$adding || ! self::is_request_page() ) { return $content; } self::$adding = true; $details = self::template_has_details() ? '' : render_block( [ 'blockName' => self::BLOCK, 'attrs' => [], 'innerBlocks' => [], 'innerHTML' => '', 'innerContent' => [], ] ); $response = self::official_response( (int) get_the_ID() ); self::$adding = false; return $details . $content . $response; } /** * Renders the details of a request. Called by the block's render.php. * * @param int $request_id Request ID. * @param string $wrapper_attributes Attributes from get_block_wrapper_attributes(). */ public static function render_details( int $request_id, string $wrapper_attributes ): string { $post = get_post( $request_id ); if ( ! $post || RequestPostType::NAME !== $post->post_type || post_password_required( $post ) ) { return ''; } $board = RequestTerms::term_of( $post->ID, BoardTaxonomy::NAME ); $page_url = CurrentPage::url(); $item = RequestItem::prepare( $post, BoardSettings::voting( $board ? $board->term_id : 0 ), RequestNotice::from_request() ); // Only logged-in users can follow, and their pages are not cached, so the page can say whether they do. $can_follow = is_user_logged_in() && Subscriptions::enabled() && 'publish' === $post->post_status; if ( $can_follow ) { $item['context']['following'] = Subscriptions::is_following( $post->ID, get_current_user_id() ); $item['context']['followBusy'] = false; } VoteStore::provide(); return Template::render( 'request', [ 'namespace' => VoteStore::NAME, 'wrapper_attributes' => $wrapper_attributes, 'context' => VoteStore::context( [ $item ] ), 'item' => $item, 'board_name' => $board ? $board->name : '', 'board_url' => $board ? BoardSettings::page_url( $board->term_id ) : '', 'vote' => VoteForm::template_args( $page_url ), 'follow' => $can_follow ? FollowForm::template_args( $page_url ) : null, 'login_url' => wp_login_url( $page_url ), ] ); } /** * Whether the content being filtered is the description on a request's own page. */ private static function is_request_page(): bool { return is_singular( RequestPostType::NAME ) && in_the_loop() && is_main_query() && get_the_ID() === get_queried_object_id() && ! is_feed() && ! doing_filter( 'get_the_excerpt' ) && ! post_password_required(); } /** * Whether the block template in use already holds the Feature Request Details block. */ private static function template_has_details(): bool { global $_wp_current_template_content; return is_string( $_wp_current_template_content ) && has_block( self::BLOCK, $_wp_current_template_content ); } /** * Renders the request's newest official response, or '' when it has none. * * @param int $request_id Request ID. */ private static function official_response( int $request_id ): string { $comment = OfficialResponse::latest( $request_id ); if ( ! $comment ) { return ''; } return Template::render( 'official-response', [ 'id' => 'mwtfrs-official-response-' . $request_id, 'text' => CommentThread::text_without_label( $comment ), 'author' => get_comment_author( $comment ), 'date' => get_comment_date( '', $comment ), 'datetime' => get_comment_date( 'c', $comment ), 'url' => get_comment_link( $comment ), ] ); } }