Refactoring : sécurité (XSS), découpage en modules inc/* et js/admin/*, IDs résolus par slug, perf (caches, cron Gravatar, assets auto-hébergés), tests
This commit is contained in:
165
inc/admin-tweaks.php
Normal file
165
inc/admin-tweaks.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* Customisations de l'admin WP : synchro display_name, champs Pods sur
|
||||
* user-new.php, colonnes et filtres des taxonomies, filtre catégorie exact,
|
||||
* admin bar, rewrite rule /autres, mode visuel forcé.
|
||||
*/
|
||||
|
||||
// Auto-sync display_name from first_name + last_name on every profile save
|
||||
add_action( 'profile_update', 'thalim_sync_display_name' );
|
||||
add_action( 'user_register', 'thalim_sync_display_name' );
|
||||
add_action( 'pods_api_post_save_pod_item_user', function( $pieces ) {
|
||||
$user_id = isset( $pieces['id'] ) ? intval( $pieces['id'] ) : 0;
|
||||
if ( $user_id ) thalim_sync_display_name( $user_id );
|
||||
} );
|
||||
|
||||
function thalim_sync_display_name( int $user_id ): void {
|
||||
$first = get_user_meta( $user_id, 'first_name', true );
|
||||
$last = get_user_meta( $user_id, 'last_name', true );
|
||||
// sanitize_text_field: le nom est réaffiché un peu partout (cards, data-*),
|
||||
// on neutralise ici tout balisage saisi dans prénom/nom.
|
||||
$name = sanitize_text_field( trim( "$first $last" ) );
|
||||
if ( ! $name ) return;
|
||||
// Bypass the filter to avoid infinite loop
|
||||
remove_action( 'profile_update', 'thalim_sync_display_name' );
|
||||
wp_update_user( [ 'ID' => $user_id, 'display_name' => $name ] );
|
||||
add_action( 'profile_update', 'thalim_sync_display_name' );
|
||||
}
|
||||
|
||||
// Show Pods user meta fields on the Add New User page (user-new.php).
|
||||
// Fires the same hook Pods listens to on profile.php / user-edit.php.
|
||||
add_action('user_new_form', function($operation) {
|
||||
if ($operation === 'add-existing-user') return;
|
||||
$user = new WP_User(0);
|
||||
do_action('show_user_profile', $user);
|
||||
});
|
||||
|
||||
// Save Pods user meta fields when a new user is registered.
|
||||
// Re-fires Pods' personal_options_update callback with the new user ID
|
||||
// while $_POST still contains the submitted form data.
|
||||
add_action('user_register', function($user_id) {
|
||||
do_action('personal_options_update', $user_id);
|
||||
}, 20);
|
||||
|
||||
// Remove the Pods autocomplete 30-item cap for the "étiquettes" (post_tag) pick field
|
||||
// so all tags are available in the dropdown, not just the first 30 alphabetically.
|
||||
add_filter( 'pods_form_ui_field_pick_autocomplete_limit', function( $limit, $name ) {
|
||||
if ( 'etiquettes' === $name ) {
|
||||
return -1;
|
||||
}
|
||||
return $limit;
|
||||
}, 10, 2 );
|
||||
|
||||
// Admin "Programmes de recherche" taxonomy list:
|
||||
// - Filter by "Type de programme" (select injected via JS into the search form).
|
||||
// - Add a "Type de programme" column to the list table.
|
||||
|
||||
// Server-side filtering: read the GET param and add a meta_query on pre_get_terms.
|
||||
add_action( 'pre_get_terms', function( $query ) {
|
||||
if ( ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
if ( ! in_array( 'programme_de_recherche', (array) $query->query_vars['taxonomy'], true ) ) {
|
||||
return;
|
||||
}
|
||||
$type = isset( $_GET['type_de_programme'] ) ? sanitize_text_field( $_GET['type_de_programme'] ) : '';
|
||||
if ( '' === $type ) {
|
||||
return;
|
||||
}
|
||||
$query->query_vars['meta_query'] = [
|
||||
[
|
||||
'key' => 'type_de_programme',
|
||||
'value' => $type,
|
||||
'compare' => '=',
|
||||
],
|
||||
];
|
||||
} );
|
||||
|
||||
// Column: add "Type de programme" to the list table, replacing "Description".
|
||||
add_filter( 'manage_edit-programme_de_recherche_columns', function( $columns ) {
|
||||
unset( $columns['description'] );
|
||||
$columns['type_de_programme'] = __( 'Type de programme', 'thalim' );
|
||||
return $columns;
|
||||
} );
|
||||
|
||||
add_filter( 'manage_programme_de_recherche_custom_column', function( $output, $column_name, $term_id ) {
|
||||
if ( 'type_de_programme' !== $column_name ) {
|
||||
return $output;
|
||||
}
|
||||
return esc_html( get_term_meta( (int) $term_id, 'type_de_programme', true ) ?: '—' );
|
||||
}, 10, 3 );
|
||||
|
||||
// Admin tag list: replace the "Description" column with the custom boolean field
|
||||
// "ne_pas_afficher_dans_le_nuage" (Ne pas afficher dans le nuage de mots-clé).
|
||||
|
||||
add_filter( 'manage_edit-post_tag_columns', function( $columns ) {
|
||||
unset( $columns['description'] );
|
||||
$columns['nuage_exclus'] = __( 'Exclure du nuage', 'thalim' );
|
||||
return $columns;
|
||||
} );
|
||||
|
||||
add_filter( 'manage_post_tag_custom_column', function( $output, $column_name, $term_id ) {
|
||||
if ( 'nuage_exclus' !== $column_name ) {
|
||||
return $output;
|
||||
}
|
||||
$val = get_term_meta( (int) $term_id, 'ne_pas_afficher_dans_le_nuage', true );
|
||||
return $val ? '✓' : '—';
|
||||
}, 10, 3 );
|
||||
|
||||
// In admin post list, filter by exact category only (exclude subcategories)
|
||||
function thalim_exact_category_filter( $query ) {
|
||||
if ( is_admin() && $query->is_main_query() ) {
|
||||
$cat = $query->get( 'cat' );
|
||||
if ( $cat ) {
|
||||
$query->set( 'cat', '' );
|
||||
$query->set( 'tax_query', [
|
||||
[
|
||||
'taxonomy' => 'category',
|
||||
'field' => 'term_id',
|
||||
'terms' => [ (int) $cat ],
|
||||
'include_children' => false,
|
||||
],
|
||||
] );
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'pre_get_posts', 'thalim_exact_category_filter' );
|
||||
|
||||
// Rewrite rule for /category/{slug}/autres → posts directly in parent category
|
||||
add_action('init', function() {
|
||||
add_rewrite_rule(
|
||||
'category/([^/]+)/autres/?$',
|
||||
'index.php?category_name=$matches[1]&thalim_direct_posts=1',
|
||||
'top'
|
||||
);
|
||||
});
|
||||
add_filter('query_vars', function($vars) {
|
||||
$vars[] = 'thalim_direct_posts';
|
||||
return $vars;
|
||||
});
|
||||
|
||||
// Admin bar customizations (front + back)
|
||||
add_action('admin_bar_menu', function($wp_admin_bar) {
|
||||
$wp_admin_bar->remove_node('wp-logo');
|
||||
$wp_admin_bar->remove_node('customize');
|
||||
foreach ($wp_admin_bar->get_nodes() as $node) {
|
||||
if (empty($node->title) || stripos($node->title, 'article') === false) continue;
|
||||
$node->title = preg_replace_callback('/article/i', function($m) {
|
||||
$w = $m[0];
|
||||
if ($w === strtoupper($w)) return 'ANNONCE';
|
||||
if ($w[0] === strtoupper($w[0])) return 'Annonce';
|
||||
return 'annonce';
|
||||
}, $node->title);
|
||||
$wp_admin_bar->add_node((array) $node);
|
||||
}
|
||||
}, 999);
|
||||
|
||||
add_action('wp_before_admin_bar_render', function() {
|
||||
global $wp_admin_bar;
|
||||
$wp_admin_bar->remove_node('wpforms-menu');
|
||||
});
|
||||
|
||||
// Force visual (TinyMCE) editor for all users — our admin CSS hides the
|
||||
// Visual/Code tabs, so if a user has "Disable the visual editor" checked
|
||||
// in their profile they get stuck in code mode with no way to switch back.
|
||||
add_filter( 'user_can_richedit', '__return_true' );
|
||||
Reference in New Issue
Block a user