Conversation
There was a problem hiding this comment.
Pull request overview
Adds a “Hidden Tags” capability to Newspack so editors can mark post_tag terms as hidden and have them suppressed across multiple public-facing surfaces and integrations, while remaining available for internal organization in wp-admin.
Changes:
- Introduces
Newspack\Hidden_Tagsto manage hidden-tag term meta, admin UI (Add/Edit/Quick Edit + list table column), and labeling. - Filters frontend/integration outputs to suppress hidden tags (term links, tag cloud, archives/feeds, CSS classes, ad targeting, Yoast schema/sitemaps).
- Loads the new tags module from the main plugin include list.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
includes/tags/class-hidden-tags.php |
Implements Hidden Tags behavior, admin UI, and frontend/integration filtering. |
includes/class-newspack.php |
Registers the new Hidden Tags module for loading. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
If this surfaces for review. Please hold off. I'm going to work through all of the Copilot suggestions and catches. Thank you! |
Fixed two issues: one where programmatic saves could accidentally clear hidden status, and one where the tag filter was running in wp-admin, plus improvements around internationalization, accessibility, and query performance.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…e tag cloud on frontend only
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Build the removal list from only this post's private tags. | ||
| $names_to_remove = []; | ||
| foreach ( $all_tags as $tag ) { | ||
| if ( in_array( $tag->term_id, $private_ids, true ) ) { | ||
| $names_to_remove[] = $tag->name; | ||
| } | ||
| } | ||
|
|
||
| if ( empty( $names_to_remove ) ) { | ||
| return $data; | ||
| } | ||
|
|
||
| // array_diff removes private tag names; array_values re-indexes the result into a sequential array. |
There was a problem hiding this comment.
filter_yoast_schema_article() builds $names_to_remove from private tag IDs, but then removes from $data['keywords'] by name via array_diff(). If a post has both a public and private tag with the same name (WP allows duplicate tag names with different slugs), this will still remove the keyword even though a public tag exists, contradicting the comment about avoiding collisions. Consider only removing a name if all tags on the post with that name are private (e.g., build a map of name => has_public) or switch to a Yoast data structure that uses term IDs/slugs if available.
| // Build the removal list from only this post's private tags. | |
| $names_to_remove = []; | |
| foreach ( $all_tags as $tag ) { | |
| if ( in_array( $tag->term_id, $private_ids, true ) ) { | |
| $names_to_remove[] = $tag->name; | |
| } | |
| } | |
| if ( empty( $names_to_remove ) ) { | |
| return $data; | |
| } | |
| // array_diff removes private tag names; array_values re-indexes the result into a sequential array. | |
| // Build the removal list from only this post's private tags, but only | |
| // remove a name if *all* tags on this post with that name are private. | |
| // This avoids removing a keyword when a public tag shares a name with a private tag. | |
| $tag_name_visibility = []; | |
| foreach ( $all_tags as $tag ) { | |
| $name = $tag->name; | |
| if ( ! isset( $tag_name_visibility[ $name ] ) ) { | |
| $tag_name_visibility[ $name ] = [ | |
| 'has_private' => false, | |
| 'has_public' => false, | |
| ]; | |
| } | |
| if ( in_array( $tag->term_id, $private_ids, true ) ) { | |
| $tag_name_visibility[ $name ]['has_private'] = true; | |
| } else { | |
| $tag_name_visibility[ $name ]['has_public'] = true; | |
| } | |
| } | |
| $names_to_remove = []; | |
| foreach ( $tag_name_visibility as $name => $flags ) { | |
| if ( $flags['has_private'] && ! $flags['has_public'] ) { | |
| $names_to_remove[] = $name; | |
| } | |
| } | |
| if ( empty( $names_to_remove ) ) { | |
| return $data; | |
| } | |
| // array_diff removes private-only tag names; array_values re-indexes the result into a sequential array. |
| $label = self::get_private_label(); | ||
| if ( | ||
| isset( $response->data['name'] ) && | ||
| is_string( $response->data['name'] ) && | ||
| self::is_term_private( $term ) && | ||
| substr( $response->data['name'], -strlen( $label ) ) !== $label | ||
| ) { | ||
| $response->data['name'] .= $label; | ||
| } |
There was a problem hiding this comment.
In append_private_label_to_rest(), the private check uses self::is_term_private( $term ), which calls get_term_meta() per term. rest_prepare_post_tag can run for large tag collections in Gutenberg, so this becomes an N+1 meta lookup. Consider using the cached ID list (self::get_private_tag_ids()) like append_private_label_to_name() does, and checking in_array( $term->term_id, $private_ids, true ) to avoid per-term meta calls.
All Submissions:
Changes proposed in this Pull Request:
Productizes the private tag concept from Texas Tribune's private plugin into core newspack-plugin.
Carried over from Texas Tribune:
(private)label in the admin tag editor and Gutenberg sidebarNew in this implementation:
post_class/body_classHTML attributesRelates to
NPPD-780How to test the changes in this Pull Request:
Admin UI:
Bauhaus(or a name of your choice).Bauhaus (private)in the Tags list.Bauhaus.Bauhaus. Confirm the "Private tag" checkbox appears pre-checked.Frontend:
Bauhaustag.Bauhaus (private)in the Tags panel.bauhausdoes not appear in body/article class attributes, the JSON-LD block, or common_targeting./tag/bauhaus/— confirm 404./?feed=rss2&tag=bauhaus— confirm 404./post_tag-sitemap.xml— confirm no entry for/tag/bauhaus/.Other information: