/**
* Role-aware Quick Links dashboard widget.
*
* - Only shows links the current user can actually access
* - Filterable link list — extend without touching this file
* - Properly escaped output
* - WordPress-native styling
* - Translatable strings
* - Widget is collapsible/hideable by the user
*
* Extend via filter:
* add_filter( 'wpfolks_dashboard_quick_links', function( $links ) {
* $links[] = [
* 'label' => 'My Custom Page',
* 'url' => admin_url( 'admin.php?page=my-plugin' ),
* 'capability' => 'manage_options',
* 'new_tab' => false,
* ];
* return $links;
* });
*/
// 1. Register the widget
add_action( 'wp_dashboard_setup', 'wpfolks_register_quick_links_widget' );
function wpfolks_register_quick_links_widget(): void {
// Only show to users who can access the dashboard meaningfully
if ( ! current_user_can( 'edit_posts' ) ) return;
wp_add_dashboard_widget(
'wpfolks_quick_links', // Widget ID
__( 'Quick Links', 'textdomain' ), // Title
'wpfolks_render_quick_links_widget', // Callback
null, // Control callback (none)
null, // Callback args
'normal', // Context: normal | side | column3 | column4
'high' // Priority: high | core | default | low
);
}
// 2. Define the full link list
function wpfolks_get_quick_links(): array {
$links = [
[
'label' => __( 'New Post', 'textdomain' ),
'url' => admin_url( 'post-new.php' ),
'capability' => 'edit_posts',
'new_tab' => false,
],
[
'label' => __( 'New Page', 'textdomain' ),
'url' => admin_url( 'post-new.php?post_type=page' ),
'capability' => 'edit_pages',
'new_tab' => false,
],
[
'label' => __( 'Upload Media', 'textdomain' ),
'url' => admin_url( 'media-new.php' ),
'capability' => 'upload_files',
'new_tab' => false,
],
[
'label' => __( 'Manage Comments', 'textdomain' ),
'url' => admin_url( 'edit-comments.php' ),
'capability' => 'moderate_comments',
'new_tab' => false,
],
[
'label' => __( 'Manage Plugins', 'textdomain' ),
'url' => admin_url( 'plugins.php' ),
'capability' => 'activate_plugins',
'new_tab' => false,
],
[
'label' => __( 'Manage Users', 'textdomain' ),
'url' => admin_url( 'users.php' ),
'capability' => 'list_users',
'new_tab' => false,
],
[
'label' => __( 'General Settings', 'textdomain' ),
'url' => admin_url( 'options-general.php' ),
'capability' => 'manage_options',
'new_tab' => false,
],
[
'label' => __( 'Customizer', 'textdomain' ),
'url' => admin_url( 'customize.php' ),
'capability' => 'customize',
'new_tab' => false,
],
[
'label' => __( 'View Site', 'textdomain' ),
'url' => home_url( '/' ),
'capability' => 'read',
'new_tab' => true, // External-style — opens in new tab
],
];
/**
* Filter: wpfolks_dashboard_quick_links
*
* Add, remove, or reorder links without editing this file.
* Each link is an array with keys: label, url, capability, and new_tab.
*
* @param array $links
* @return array
*/
return apply_filters( 'wpfolks_dashboard_quick_links', $links );
}
// 3. Render the widget
function wpfolks_render_quick_links_widget(): void {
$links = wpfolks_get_quick_links();
// Filter to only links the current user can access
$visible = array_filter( $links, function( array $link ): bool {
$cap = $link['capability'] ?? 'read';
return current_user_can( $cap );
} );
if ( empty( $visible ) ) {
echo '<p>' . esc_html__( 'No quick links available for your role.', 'textdomain' ) . '</p>';
return;
}
// WordPress-native table styling — consistent with core dashboard widgets
echo '<table class="widefat striped" role="presentation"><tbody>';
foreach ( $visible as $link ) {
$label = isset( $link['label'] ) ? esc_html( $link['label'] ) : '';
$url = isset( $link['url'] ) ? esc_url( $link['url'] ) : '';
$new_tab = ! empty( $link['new_tab'] );
if ( ! $label || ! $url ) continue;
$target = $new_tab ? ' target="_blank" rel="noopener noreferrer"' : '';
printf(
'<tr><td><a href="%s"%s>%s%s</a></td></tr>',
$url,
$target,
$label,
$new_tab
? ' <span class="dashicons dashicons-external" style="font-size:14px;vertical-align:middle;" aria-label="' . esc_attr__( 'opens in new tab', 'textdomain' ) . '"></span>'
: ''
);
}
echo '</tbody></table>';
}