comment_parent ) || (int) $comment->comment_parent === (int) $comment->comment_ID ) { return array(); } $ancestors = array(); $id = (int) $comment->comment_parent; $ancestors[] = $id; while ( $id > 0 ) { $ancestor = \get_comment( $id ); if ( ! $ancestor ) { break; } $parent_id = (int) $ancestor->comment_parent; // Loop detection: If the ancestor has been seen before, break. if ( empty( $parent_id ) || ( $parent_id === (int) $comment->comment_ID ) || \in_array( $parent_id, $ancestors, true ) ) { break; } $id = $parent_id; $ancestors[] = $id; } return $ancestors; } /** * Registers a ActivityPub comment type. * * @param string $comment_type Key for comment type. * @param array $args Optional. Array of arguments for registering a comment type. Default empty array. * * @return array The registered Activitypub comment type. */ function register_comment_type( $comment_type, $args = array() ) { global $activitypub_comment_types; if ( ! \is_array( $activitypub_comment_types ) ) { $activitypub_comment_types = array(); } // Sanitize comment type name. $comment_type = \sanitize_key( $comment_type ); // Every key the plugin reads, so a type registered with only some of them does not break the others. $args = \wp_parse_args( $args, array( 'label' => $comment_type, 'singular' => $comment_type, 'description' => '', 'icon' => '', 'class' => '', 'type' => $comment_type, 'collection' => $comment_type, 'activity_types' => array(), 'excerpt' => '', 'count_single' => '%d', 'count_plural' => '%d', ) ); $activitypub_comment_types[ $comment_type ] = $args; /** * Fires after a ActivityPub comment type is registered. * * @param string $comment_type Comment type. * @param array $args Arguments used to register the comment type. */ \do_action( 'activitypub_registered_comment_type', $comment_type, $args ); return $args; } /** * Get the reply intent URI as a JavaScript URI. * * @return string The reply intent URI. */ function get_reply_intent_js() { return \sprintf( 'javascript:(()=>{window.open(\'%s\'+encodeURIComponent(window.location.href));})();', get_reply_intent_url() ); } /** * Get the reply intent URI. * * @return string The reply intent URI. */ function get_reply_intent_url() { /** * Filters the reply intent parameters. * * @param array $params The reply intent parameters. */ $params = \apply_filters( 'activitypub_reply_intent_params', array() ); $params += array( 'in_reply_to' => '' ); $query = \http_build_query( $params ); $path = 'post-new.php?' . $query; $url = \admin_url( $path ); /** * Filters the reply intent URL. * * @param string $url The reply intent URL. */ $url = \apply_filters( 'activitypub_reply_intent_url', $url ); return \esc_url_raw( $url ); } /** * Get a reaction author's display name as readable plain text. * * Shared by the reactions REST route and the block's server render so both produce the * same value for the same comment: they feed the same Interactivity template, and * `view.js` swaps the rendered items for the fetched ones wholesale. * * This reads the raw column rather than `get_comment_author()`, so it does not pick up * the emoji rendering that the comment list applies. That is deliberate for a * plain-text field. * * `wp_insert_comment()` callers bypass core's `pre_comment_author_name` chain, so the * column is not guaranteed tag-free, which is why this cleans rather than just reads. * * @since 9.3.0 * * @param \WP_Comment $comment The comment. * * @return string The author name as plain text. May contain `&` as a character, * so it is safe for a text sink only, never for HTML. */ function get_reaction_author_name( $comment ) { // Core stores this column entity-escaped, so decode for the text sinks; stripping after the // decode is what keeps an encoded tag from coming back to life. return \wp_strip_all_tags( \html_entity_decode( $comment->comment_author, ENT_QUOTES, 'UTF-8' ) ); }