Taxonomy: Restrict term edit link generation in WP_Terms_List_Table::handle_row_actions().

This changeset restricts edit term link generation if the user lacks the `edit_term` cap in order to prevent PHP 8.1+ deprecations shown when a user lacks this 
capability and `get_edit_term_link()` returns null.

Props thelovekesh, jrf.
Fixes #59336.





git-svn-id: https://develop.svn.wordpress.org/trunk@56631 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jb Audras
2023-09-20 08:08:42 +00:00
parent 669d11f063
commit 1113b2df5a
2 changed files with 95 additions and 7 deletions
@@ -474,18 +474,18 @@ class WP_Terms_List_Table extends WP_List_Table {
$taxonomy = $this->screen->taxonomy;
$uri = wp_doing_ajax() ? wp_get_referer() : $_SERVER['REQUEST_URI'];
$edit_link = add_query_arg(
'wp_http_referer',
urlencode( wp_unslash( $uri ) ),
get_edit_term_link( $tag, $taxonomy, $this->screen->post_type )
);
$actions = array();
if ( current_user_can( 'edit_term', $tag->term_id ) ) {
$actions['edit'] = sprintf(
'<a href="%s" aria-label="%s">%s</a>',
esc_url( $edit_link ),
esc_url(
add_query_arg(
'wp_http_referer',
urlencode( wp_unslash( $uri ) ),
get_edit_term_link( $tag, $taxonomy, $this->screen->post_type )
)
),
/* translators: %s: Taxonomy term name. */
esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $tag->name ) ),
__( 'Edit' )
@@ -0,0 +1,88 @@
<?php
/**
* @group admin
*
* @covers WP_Terms_List_Table
*/
class Tests_Admin_WpTermsListTable extends WP_UnitTestCase {
/**
* List table.
*
* @var WP_Terms_List_Table $terms_list_table
*/
private $terms_list_table;
private static $admin_id;
private static $author_id;
private static $term_object;
const CATEGORY_TAXONOMY = 'category';
public static function set_up_before_class() {
parent::set_up_before_class();
self::$admin_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
self::$author_id = self::factory()->user->create( array( 'role' => 'author' ) );
self::$term_object = self::factory()->term->create_and_get( array( 'taxonomy' => self::CATEGORY_TAXONOMY ) );
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-terms-list-table.php';
}
public function set_up() {
parent::set_up();
$this->terms_list_table = new WP_Terms_List_Table();
}
/**
* Call an inaccessible (private or protected) method.
*
* @param object|string $object Object instance or class string to call the method of.
* @param string $method_name Name of the method to call.
* @param array $args Optional. Array of arguments to pass to the method.
* @return mixed Return value of the method call.
* @throws ReflectionException If the object could not be reflected upon.
*/
private function call_inaccessible_method( $object, $method_name, $args = array() ) {
$method = ( new ReflectionClass( $object ) )->getMethod( $method_name );
$method->setAccessible( true );
return $method->invokeArgs( $object, $args );
}
/**
* @covers WP_Terms_List_Table::handle_row_actions()
*
* @ticket 59336
*/
public function test_handle_row_actions_as_author() {
wp_set_current_user( self::$author_id );
$actions = $this->call_inaccessible_method( $this->terms_list_table, 'handle_row_actions', array( self::$term_object, 'title', 'title' ) );
$this->assertStringContainsString( '<div class="row-actions">', $actions, 'Row actions should be displayed.' );
$this->assertStringContainsString( 'View', $actions, 'View action should be displayed to the author.' );
$this->assertStringNotContainsString( 'Edit', $actions, 'Edit action should not be displayed to the author.' );
$this->assertStringNotContainsString( 'Delete', $actions, 'Delete action should not be displayed to the author.' );
}
/**
* @covers WP_Terms_List_Table::handle_row_actions()
*
* @ticket 59336
*/
public function test_handle_row_actions_as_admin() {
wp_set_current_user( self::$admin_id );
$actions = $this->call_inaccessible_method( $this->terms_list_table, 'handle_row_actions', array( self::$term_object, 'title', 'title' ) );
$this->assertStringContainsString( '<div class="row-actions">', $actions, 'Row actions should be displayed.' );
$this->assertStringContainsString( 'View', $actions, 'View action should be displayed to the admin.' );
$this->assertStringContainsString( 'Edit', $actions, 'Edit action should be displayed to the admin.' );
$this->assertStringContainsString( 'Delete', $actions, 'Delete action should be displayed to the admin.' );
$this->assertStringContainsString( admin_url( 'term.php' ), $actions, 'Edit term link should be displayed to the admin.' );
}
}