Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/wp-admin/includes/class-wp-posts-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,23 +261,41 @@ protected function get_edit_link( $args, $link_text, $css_class = '' ) {
$class_html = '';
$aria_current = '';

if ( ! empty( $css_class ) ) {
$edit_filter_link_vars = compact( 'url', 'link_text', 'css_class' );

/**
* Filters the links created for filtering the posts list table.
*
* @since 6.9.0
*
* @param array $edit_filter_link_vars {
* The edit filter link variables.
*
* @type string $url The formatted link string.
* @type string $link_text The link text.
* @type string $css_class The class HTML.
* }
* @param array $args URL parameters for the link.
*/
$edit_filter_link_vars = apply_filters( 'edit_filter_links', $edit_filter_link_vars, $args );
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the right filter name? Shouldn't it be singular?

Suggested change
$edit_filter_link_vars = apply_filters( 'edit_filter_links', $edit_filter_link_vars, $args );
$edit_filter_link_vars = apply_filters( 'edit_filter_link', $edit_filter_link_vars, $args );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather, this filter still is difficult to understand.

Since it is specifically for filtering the link used in a column of the post list table, maybe:

  • post_list_column_edit_link

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it also seems strange that the link itself is not being filtered. It's the array that goes into constructing the link. That being the case, then it should be something like: post_list_column_edit_link_vars.

But that feels wrong too. Why not just let the HTML be constructed as it had been before, and then add a filter for the resulting HTML? This feels better to me:

diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php
index bc25dd0045..82781f82f2 100644
--- a/src/wp-admin/includes/class-wp-posts-list-table.php
+++ b/src/wp-admin/includes/class-wp-posts-list-table.php
@@ -272,13 +272,27 @@ class WP_Posts_List_Table extends WP_List_Table {
 			}
 		}
 
-		return sprintf(
+		$edit_link = sprintf(
 			'<a href="%s"%s%s>%s</a>',
 			esc_url( $url ),
 			$class_html,
 			$aria_current,
 			$link_text
 		);
+
+		/**
+		 * Filters an edit link which appears in a column of the post list table.
+		 *
+		 * This links to another post list table view to list posts by an author or posts in a category, for example.
+		 *
+		 * @since 9.6.0
+		 *
+		 * @param string   $edit_link Edit link.
+		 * @param string[] $args      Associative array of URL parameters for the link.
+		 * @param string   $link_text Link text.
+		 * @param string   $css_class Optional. Class attribute. Default empty string.
+		 */
+		return apply_filters( 'post_list_table_edit_link', $edit_link, $args, $link_text, $css_class );
 	}
 
 	/**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the HTML Tag Processor can be used to manipulate the edit link as desired.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will note that one problem I see over and over again with this kind of filtering is that we really don’t have a solution for proper escaping. by passing HTML through a filter we have mushed together actual HTML and escaped text nodes. this makes it hard to properly filter, because people would need to use the HTML Processor if they want to filter it after that. they should not use string functions.

I’ve been working on some ideas for improving this situation but they aren’t going to be ready for 6.9.0 and they aren’t going to fully address this.

at least when we are talking about the constituent parts we can agree that the values are “raw PHP strings.” once we mush things we lose the ability to track which parts are which.

this is a long-winded answer to a simple question, and it’s not in any way unique to this change, but it’s the reason I don’t feel like I have a simple response.


I’m reluctant to pass the HTML Processor or Tag Processor as the input to filters, but this is a kind of example where we could be exploring newer semantic filters.

maybe we could export the proposed attributes and children of the A element and let people much with them.


The original proposal seems simpler and raises fewer questions than this version of the patch.

add_filter('edit_link_url', 'wp_edit_link_filter');

function wp_edit_link_filter($url){
        return add_query_arg(array('taonomy'=>'slug'), $url);
}


if ( ! empty( $edit_filter_link_vars['css_class'] ) ) {
$class_html = sprintf(
' class="%s"',
esc_attr( $css_class )
esc_attr( $edit_filter_link_vars['css_class'] )
);

if ( 'current' === $css_class ) {
if ( 'current' === $edit_filter_link_vars['css_class'] ) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if other CSS classes had been added? This seems like an ideal place to use WP_HTML_Tag_Processor::parse_class_list() proposed in #10043 by @dmsnell. In that way, this code could instead be:

Suggested change
if ( 'current' === $edit_filter_link_vars['css_class'] ) {
if ( in_array( 'current', iterator_to_array( WP_HTML_Tag_Processor::parse_class_list( $edit_filter_link_vars['css_class'] ), true ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with all of the attribute activity going on here we could also benefit at large from using the HTML API.

$processor = new WP_HTML_Tag_Processor( '<a>LINK_TEXT</a>' );
$processor->next_token();
$processor->set_attribute( 'href', $edit_filter_link_vars['url'] );
$processor->set_attribute( 'class', $edit_filter_link_vars['css_class'] ?? null );
$processor->set_attribute( 'aria-current', 'page' );

$processor->next_token();
$processor->set_modifiable_text( $edit_filter_link_vars['link_text'] );

return $processor->get_updated_html();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmsnell what about #9950 (comment) ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well I don’t know. to be honest I didn’t fully understand the new filter, but I think the HTML API can play a nice role in constructing the HTML wherever it’s created, even if that’s before filtering.

$aria_current = ' aria-current="page"';
}
}

return sprintf(
'<a href="%s"%s%s>%s</a>',
esc_url( $url ),
esc_url( $edit_filter_link_vars['url'] ),
$class_html,
$aria_current,
$link_text
$edit_filter_link_vars['link_text']
);
}

Expand Down
Loading