Droits d'accès : menu Outils visible pour les éditeurs + édition des séances héritée du séminaire

This commit is contained in:
2026-06-13 06:40:48 +02:00
parent 9280c3b9ce
commit e6ab5124dd

View File

@@ -8,8 +8,47 @@
* - redirections login/dashboard des non-admins. * - redirections login/dashboard des non-admins.
*/ */
/**
* Séances qu'un utilisateur peut éditer par héritage : toutes les séances
* listées (meta Pods `seances`) dans un séminaire dont il est l'auteur OU où
* il figure en membres/autre_membres. Mémoïsé par utilisateur — user_has_cap
* est appelé de très nombreuses fois par chargement de page admin.
*/
function thalim_user_editable_seance_ids( int $user_id ): array {
static $cache = [];
if ( isset( $cache[ $user_id ] ) ) {
return $cache[ $user_id ];
}
global $wpdb;
// Séminaires éditables : auteur OU membre listé.
$seminaire_ids = array_map( 'intval', (array) $wpdb->get_col( $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_author = %d
UNION
SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key IN ('membres', 'autre_membres') AND meta_value = %s",
$user_id,
(string) $user_id
) ) );
if ( empty( $seminaire_ids ) ) {
return $cache[ $user_id ] = [];
}
// Séances listées par ces séminaires.
$in = implode( ',', $seminaire_ids );
$seance_ids = array_map( 'intval', (array) $wpdb->get_col(
"SELECT meta_value FROM {$wpdb->postmeta}
WHERE meta_key = 'seances' AND post_id IN ($in)"
) );
return $cache[ $user_id ] = array_values( array_unique( $seance_ids ) );
}
// Restrict Contributors to see only their own posts in admin, // Restrict Contributors to see only their own posts in admin,
// but also include posts where they appear in membres/autre_membres. // but also include posts where they appear in membres/autre_membres,
// plus les séances des séminaires qu'ils peuvent éditer.
function restrict_contributor_posts( $query ) { function restrict_contributor_posts( $query ) {
if ( ! is_admin() || ! $query->is_main_query() || current_user_can( 'edit_others_posts' ) ) { if ( ! is_admin() || ! $query->is_main_query() || current_user_can( 'edit_others_posts' ) ) {
return; return;
@@ -26,8 +65,11 @@ function restrict_contributor_posts( $query ) {
) )
) ); ) );
if ( empty( $membre_ids ) ) { // Séances héritées des séminaires que l'utilisateur peut éditer.
// Fast path: no membre posts, use simple author filter. $seance_ids = thalim_user_editable_seance_ids( $user_ID );
if ( empty( $membre_ids ) && empty( $seance_ids ) ) {
// Fast path: no membre/séance posts, use simple author filter.
$query->set( 'author', $user_ID ); $query->set( 'author', $user_ID );
return; return;
} }
@@ -40,7 +82,7 @@ function restrict_contributor_posts( $query ) {
) )
) ); ) );
$all_ids = array_unique( array_merge( $authored_ids, $membre_ids ) ); $all_ids = array_unique( array_merge( $authored_ids, $membre_ids, $seance_ids ) );
// post__in with [0] returns nothing when the combined set is empty. // post__in with [0] returns nothing when the combined set is empty.
$query->set( 'post__in', empty( $all_ids ) ? [ 0 ] : $all_ids ); $query->set( 'post__in', empty( $all_ids ) ? [ 0 ] : $all_ids );
@@ -104,7 +146,15 @@ function thalim_membres_can_edit_post( $allcaps, $caps, $args, $user ) {
) )
); );
if ( in_array( $user_id, $membre_ids, true ) ) { $can_edit = in_array( $user_id, $membre_ids, true );
// Séance de séminaire : hérite des droits d'édition du séminaire parent
// (auteur ou membre du séminaire qui la liste dans `seances`).
if ( ! $can_edit ) {
$can_edit = in_array( $post_id, thalim_user_editable_seance_ids( $user_id ), true );
}
if ( $can_edit ) {
// Grant every primitive cap mapped for this check // Grant every primitive cap mapped for this check
// (e.g. edit_others_posts, edit_published_posts). // (e.g. edit_others_posts, edit_published_posts).
foreach ( $caps as $c ) { foreach ( $caps as $c ) {
@@ -147,6 +197,12 @@ add_filter( 'wp_count_posts', function ( $counts, $type, $perm ) {
global $wpdb; global $wpdb;
$user_id = get_current_user_id(); $user_id = get_current_user_id();
// Séances héritées des séminaires éditables (liste d'IDs entiers, sûre à interpoler).
$seance_ids = thalim_user_editable_seance_ids( $user_id );
$seance_union = $seance_ids
? ' UNION SELECT ' . implode( ' AS ID UNION SELECT ', $seance_ids ) . ' AS ID'
: '';
$results = $wpdb->get_results( $results = $wpdb->get_results(
$wpdb->prepare( $wpdb->prepare(
"SELECT post_status, COUNT(*) AS num_posts "SELECT post_status, COUNT(*) AS num_posts
@@ -158,6 +214,7 @@ add_filter( 'wp_count_posts', function ( $counts, $type, $perm ) {
UNION UNION
SELECT post_id FROM {$wpdb->postmeta} SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key IN ('membres', 'autre_membres') AND meta_value = %s WHERE meta_key IN ('membres', 'autre_membres') AND meta_value = %s
$seance_union
) )
GROUP BY post_status", GROUP BY post_status",
$type, $type,
@@ -206,12 +263,16 @@ add_filter( 'wp_nav_menu_objects', function( $items, $args ) {
} ) ); } ) );
}, 10, 2 ); }, 10, 2 );
// Non-admins: hide dashboard and tools menu, redirect to posts list // Non-admins: hide dashboard, redirect to posts list.
// Outils reste visible pour les éditeurs (cap edit_others_posts) : les pages
// HAL Import / Newsletter y sont gatées sur cette même cap.
add_action( 'admin_menu', function() { add_action( 'admin_menu', function() {
if ( ! current_user_can( 'manage_options' ) ) { if ( ! current_user_can( 'manage_options' ) ) {
remove_menu_page( 'tools.php' );
remove_menu_page( 'index.php' ); remove_menu_page( 'index.php' );
} }
if ( ! current_user_can( 'edit_others_posts' ) ) {
remove_menu_page( 'tools.php' );
}
} ); } );
// Redirect non-admins away from dashboard to their posts list // Redirect non-admins away from dashboard to their posts list