Title: WP_Posts_List_Table::handle_row_actions
Published: August 18, 2015
Last modified: February 24, 2026

---

# WP_Posts_List_Table::handle_row_actions( WP_Post $item, string $column_name, string $primary ): string

## In this article

 * [Parameters](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#wp--skip-link--target)

Generates and displays row action links.

## 󠀁[Parameters](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#parameters)󠁿

 `$item`[WP_Post](https://developer.wordpress.org/reference/classes/wp_post/)required

Post being acted upon.

`$column_name`stringrequired

Current column name.

`$primary`stringrequired

Primary column name.

## 󠀁[Return](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#return)󠁿

 string Row actions output for posts, or an empty string if the current column is
not the primary column.

## 󠀁[Source](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#source)󠁿

    ```php
    protected function handle_row_actions( $item, $column_name, $primary ) {
    	if ( $primary !== $column_name ) {
    		return '';
    	}

    	// Restores the more descriptive, specific name for use within this method.
    	$post = $item;

    	$post_type_object = get_post_type_object( $post->post_type );
    	$can_edit_post    = current_user_can( 'edit_post', $post->ID );
    	$actions          = array();
    	$title            = _draft_or_post_title();

    	if ( $can_edit_post && 'trash' !== $post->post_status ) {
    		$actions['edit'] = sprintf(
    			'<a href="%s" aria-label="%s">%s</a>',
    			get_edit_post_link( $post->ID ),
    			/* translators: %s: Post title. */
    			esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ),
    			__( 'Edit' )
    		);

    		/**
    		 * Filters whether Quick Edit should be enabled for the given post type.
    		 *
    		 * @since 6.4.0
    		 *
    		 * @param bool   $enable    Whether to enable the Quick Edit functionality. Default true.
    		 * @param string $post_type Post type name.
    		 */
    		$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );

    		if ( $quick_edit_enabled && 'wp_block' !== $post->post_type ) {
    			$actions['inline hide-if-no-js'] = sprintf(
    				'<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false">%s</button>',
    				/* translators: %s: Post title. */
    				esc_attr( sprintf( __( 'Quick edit &#8220;%s&#8221; inline' ), $title ) ),
    				__( 'Quick&nbsp;Edit' )
    			);
    		}
    	}

    	if ( current_user_can( 'delete_post', $post->ID ) ) {
    		if ( 'trash' === $post->post_status ) {
    			$actions['untrash'] = sprintf(
    				'<a href="%s" aria-label="%s">%s</a>',
    				wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ),
    				/* translators: %s: Post title. */
    				esc_attr( sprintf( __( 'Restore &#8220;%s&#8221; from the Trash' ), $title ) ),
    				__( 'Restore' )
    			);
    		} elseif ( EMPTY_TRASH_DAYS ) {
    			$actions['trash'] = sprintf(
    				'<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
    				get_delete_post_link( $post->ID ),
    				/* translators: %s: Post title. */
    				esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash' ), $title ) ),
    				_x( 'Trash', 'verb' )
    			);
    		}

    		if ( 'trash' === $post->post_status || ! EMPTY_TRASH_DAYS ) {
    			$actions['delete'] = sprintf(
    				'<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
    				get_delete_post_link( $post->ID, '', true ),
    				/* translators: %s: Post title. */
    				esc_attr( sprintf( __( 'Delete &#8220;%s&#8221; permanently' ), $title ) ),
    				__( 'Delete Permanently' )
    			);
    		}
    	}

    	if ( is_post_type_viewable( $post_type_object ) ) {
    		if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ), true ) ) {
    			if ( $can_edit_post ) {
    				$preview_link    = get_preview_post_link( $post );
    				$actions['view'] = sprintf(
    					'<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
    					esc_url( $preview_link ),
    					/* translators: %s: Post title. */
    					esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ),
    					__( 'Preview' )
    				);
    			}
    		} elseif ( 'trash' !== $post->post_status ) {
    			$actions['view'] = sprintf(
    				'<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
    				get_permalink( $post->ID ),
    				/* translators: %s: Post title. */
    				esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ),
    				__( 'View' )
    			);
    		}
    	}

    	if ( 'wp_block' === $post->post_type ) {
    		$actions['export'] = sprintf(
    			'<button type="button" class="wp-list-reusable-blocks__export button-link" data-id="%s" aria-label="%s">%s</button>',
    			$post->ID,
    			/* translators: %s: Post title. */
    			esc_attr( sprintf( __( 'Export &#8220;%s&#8221; as JSON' ), $title ) ),
    			__( 'Export as JSON' )
    		);
    	}

    	if ( is_post_type_hierarchical( $post->post_type ) ) {

    		/**
    		 * Filters the array of row action links on the Pages list table.
    		 *
    		 * The filter is evaluated only for hierarchical post types.
    		 *
    		 * @since 2.8.0
    		 *
    		 * @param string[] $actions An array of row action links. Defaults are
    		 *                          'Edit', 'Quick Edit', 'Restore', 'Trash',
    		 *                          'Delete Permanently', 'Preview', and 'View'.
    		 * @param WP_Post  $post    The post object.
    		 */
    		$actions = apply_filters( 'page_row_actions', $actions, $post );
    	} else {

    		/**
    		 * Filters the array of row action links on the Posts list table.
    		 *
    		 * The filter is evaluated only for non-hierarchical post types.
    		 *
    		 * @since 2.8.0
    		 *
    		 * @param string[] $actions An array of row action links. Defaults are
    		 *                          'Edit', 'Quick Edit', 'Restore', 'Trash',
    		 *                          'Delete Permanently', 'Preview', and 'View'.
    		 * @param WP_Post  $post    The post object.
    		 */
    		$actions = apply_filters( 'post_row_actions', $actions, $post );
    	}

    	return $this->row_actions( $actions );
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-admin/includes/class-wp-posts-list-table.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-admin/includes/class-wp-posts-list-table.php#L1472)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-admin/includes/class-wp-posts-list-table.php#L1472-L1610)

## 󠀁[Hooks](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#hooks)󠁿

 [apply_filters( ‘page_row_actions’, string[] $actions, WP_Post $post )](https://developer.wordpress.org/reference/hooks/page_row_actions/)

Filters the array of row action links on the Pages list table.

 [apply_filters( ‘post_row_actions’, string[] $actions, WP_Post $post )](https://developer.wordpress.org/reference/hooks/post_row_actions/)

Filters the array of row action links on the Posts list table.

 [apply_filters( ‘quick_edit_enabled_for_post_type’, bool $enable, string $post_type )](https://developer.wordpress.org/reference/hooks/quick_edit_enabled_for_post_type/)

Filters whether Quick Edit should be enabled for the given post type.

## 󠀁[Related](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#related)󠁿

| Uses | Description | 
| [get_preview_post_link()](https://developer.wordpress.org/reference/functions/get_preview_post_link/)`wp-includes/link-template.php` |

Retrieves the URL used for the post preview.

  | 
| [is_post_type_viewable()](https://developer.wordpress.org/reference/functions/is_post_type_viewable/)`wp-includes/post.php` |

Determines whether a post type is considered “viewable”.

  | 
| [_draft_or_post_title()](https://developer.wordpress.org/reference/functions/_draft_or_post_title/)`wp-admin/includes/template.php` |

Gets the post title.

  | 
| [get_edit_post_link()](https://developer.wordpress.org/reference/functions/get_edit_post_link/)`wp-includes/link-template.php` |

Retrieves the edit post link for post.

  | 
| [get_delete_post_link()](https://developer.wordpress.org/reference/functions/get_delete_post_link/)`wp-includes/link-template.php` |

Retrieves the delete posts link for post.

  | 
| [is_post_type_hierarchical()](https://developer.wordpress.org/reference/functions/is_post_type_hierarchical/)`wp-includes/post.php` |

Determines whether the post type is hierarchical.

  | 
| [current_user_can()](https://developer.wordpress.org/reference/functions/current_user_can/)`wp-includes/capabilities.php` |

Returns whether the current user has the specified capability.

  | 
| [__()](https://developer.wordpress.org/reference/functions/__/)`wp-includes/l10n.php` |

Retrieves the translation of $text.

  | 
| [_x()](https://developer.wordpress.org/reference/functions/_x/)`wp-includes/l10n.php` |

Retrieves translated string with gettext context.

  | 
| [esc_attr()](https://developer.wordpress.org/reference/functions/esc_attr/)`wp-includes/formatting.php` |

Escaping for HTML attributes.

  | 
| [esc_url()](https://developer.wordpress.org/reference/functions/esc_url/)`wp-includes/formatting.php` |

Checks and cleans a URL.

  | 
| [wp_nonce_url()](https://developer.wordpress.org/reference/functions/wp_nonce_url/)`wp-includes/functions.php` |

Retrieves URL with nonce added to URL query.

  | 
| [admin_url()](https://developer.wordpress.org/reference/functions/admin_url/)`wp-includes/link-template.php` |

Retrieves the URL to the admin area for the current site.

  | 
| [get_permalink()](https://developer.wordpress.org/reference/functions/get_permalink/)`wp-includes/link-template.php` |

Retrieves the full permalink for the current post or post ID.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  | 
| [get_post_type_object()](https://developer.wordpress.org/reference/functions/get_post_type_object/)`wp-includes/post.php` |

Retrieves a post type object by name.

  |

[Show 11 more](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#)

| Used by | Description | 
| [WP_Posts_List_Table::_column_title()](https://developer.wordpress.org/reference/classes/wp_posts_list_table/_column_title/)`wp-admin/includes/class-wp-posts-list-table.php` |  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/classes/wp_posts_list_table/handle_row_actions/?output_format=md#changelog)󠁿

| Version | Description | 
| [5.9.0](https://developer.wordpress.org/reference/since/5.9.0/) | Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. | 
| [4.3.0](https://developer.wordpress.org/reference/since/4.3.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Fclasses%2Fwp_posts_list_table%2Fhandle_row_actions%2F)
before being able to contribute a note or feedback.