J'ai créé une taxonomie appelée "sujets" qui comporte 4 termes de premier niveau:
et chacun de ces termes aura des termes enfants. Je veux pouvoir verrouiller les termes du plus haut niveau, mais pas le terme enfant.
Fondamentalement, les éditeurs devraient pouvoir créer autant de termes qu'ils le souhaitent pour chacun de ces termes de premier niveau. Mais ces termes de premier niveau ne peuvent être ni supprimés ni modifiés.
Est-ce possible?
Ce n’est pas une réponse complète et toute faite, mais ce qui suit devrait vous aider à démarrer.
La première chose à noter est que la suppression et la modification sont des fonctionnalités différentes. Par conséquent, différentes fonctions et fonctions lui sont associées. Nous parlons de wp_delete_term()
- source et wp_update_term()
- source - en ce qui concerne les fonctions.
Jetons donc un coup d'œil à wp_delete_term()
, vous devez au moins considérer deux points d'ancrage: edit_term_taxonomies et delete_term_taxonomy . Ils sont tous deux pertinents en raison de l'action en masse et du traitement des taxonomies hiérarchiques.
Ci-dessous quelques exemples de code comment aborder cela. J'ai essayé d'expliquer les éléments les plus importants du code. Le reste, vous devez lire sur vous-même.
Commençons par les edit_term_taxonomies hook:
add_action(
'edit_term_taxonomies',
'wpse160191_top_level_lock_down_edit_term_taxonomies',
10,
1
);
function wpse160191_top_level_lock_down_edit_term_taxonomies(
$edit_tt_ids
) {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if(
// these are the conditions we are checking against
// is this a tag edit page
$base == 'edit-tags'
// we want this only for a specific taxonomy
&& $taxonomy == 'category'
// not super and/or admin
&& ! current_user_can( 'manage_options' )
// a least an editor
&& current_user_can( 'manage_categories' )
) {
// these are the terms up for deletion
$terms_queue_for_deletion = $_POST['delete_tags'];
$term_parents_ids = array();
// we need information if or not one of the terms is a top level one
foreach ( $terms_queue_for_deletion as $term_id ) {
$term_obj = get_term_by( 'id', $term_id, 'category' );
$term_parent = $term_obj->parent;
$term_parents_ids[] = $term_parent;
}
if( empty( $edit_tt_ids ) ) {
return;
}
if( ! empty( $edit_tt_ids ) ) {
if ( in_array( 0, $term_parents_ids ) ) {
$msg = new WP_Error(
'parent_terms_are_forever',
__('Sorry, you are not allowed to delete top level terms.')
);
wp_die( $msg );
} else {
return;
}
}
}
}
Deuxième le delete_term_taxonomy hook:
add_action(
'delete_term_taxonomy',
'wpse160191_top_level_lock_down_delete_term_taxonomy',
10,
1
);
function wpse160191_top_level_lock_down_delete_term_taxonomy(
$tt_id
) {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if (
// these are the conditions we are checking against
// is this a tag edit page
$base == 'edit-tags'
// we want this only for a specific taxonomy
&& $taxonomy == 'category'
// not super and/or admin
&& ! current_user_can( 'manage_options' )
// a least an editor
&& current_user_can( 'manage_categories' )
) {
$term_obj = get_term_by( 'term_taxonomy_id', $tt_id, 'category' );
$parent_id = $term_obj->parent;
if (
// this applies only to top level terms
$parent_id == 0
) {
$msg = new WP_Error(
'parent_terms_are_forever',
__('s:Sorry, you are not allowed to delete top level terms.')
);
wp_die( $msg );
}
}
}
Comme mentionné ci-dessus, cela devient un peu plus compliqué, principalement à cause des actions AJAX. Si vous envisagez de le faire avec la vérification bien connue et simple:
if ( defined('DOING_AJAX') && DOING_AJAX ) {
// code
}
Je peux vous dire maintenant que je suis à peu près certain que cela ne suffira pas. Principalement parce que vous ne pourrez pas faire toutes les vérifications dont vous avez besoin. Si vous vous contentez de désactiver ou, pour être exact, de supprimer le lien vers l'action AJAX, vous pouvez le faire un peu comme ceci:
add_action(
'admin_head' ,
'wpse160191_remove_ajax_delete_link'
);
function wpse160191_remove_ajax_delete_link() {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if(
// lets just remove the link on that one page and not everywhere
$base == 'edit-tags'
&& $taxonomy == 'category'
) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
var element = 'span.delete';
$(element).each(function(){
$(element).css('opacity', '0');
$(element).css('pointer-events', 'none');
$(element).remove();
});
});
</script>
<?php
}
}
Bien sûr, vous ne devriez pas le faire en ligne, etc., mais vous pouvez vous optimiser. Bien sûr, cela n’est pas très satisfaisant, car nous venons de supprimer la fonctionnalité.
Une façon d’imaginer traiter l’action AJAX consiste à utiliser debug_backtrace()
. Cela offrirait un moyen de déterminer et de gérer correctement l'action AJAX. Il pourrait être implémenté dans le code indiqué ci-dessus. Bien entendu, debug_backtrace()
est coûteux en termes de performances et, à plus grande échelle, sûrement déconseillé.
Une autre solution consisterait à implémenter votre propre action AJAX en remplacement de wp_ajax_delete_tag()
, mais vous devez également étendre le WP_Terms_List_Table
ou utilisez des crochets pour y parvenir. Pas tout à fait sûr pour le moment, vous devez donc vérifier cela vous-même.
La procédure pour wp_update_term()
et interdire la mise à jour/la modification est analogue à celle présentée ci-dessus. Avec les mêmes considérations concernant la partie AJAX, notamment en raison de la possibilité d'édition rapide en ligne.
Au début, j'ai totalement mal interprété la question et je l'ai donnée comme réponse.
Le garder parce que cela pourrait être utile aux autres.
Ce que vous pouvez faire, c'est vous connecter au pre_insert_term
pour effectuer les vérifications nécessaires.
Code:
add_action( 'pre_insert_term', 'wpse160191_restrict_top_level_term_creation', 10, 2 );
function wpse160191_restrict_top_level_term_creation( $term, $taxonomy ) {
if(
// these are the conditions we are checking against
// we want this only for a specific taxonomy
$taxonomy == 'topics'
// a value of 0 or -1 does indicate the top level
&& $_POST[ 'parent' ] <= '0'
// not super and/or admin
&& ! current_user_can( 'manage_options' )
// a least an editor
&& current_user_can( 'manage_categories' )
) {
// the user is an editor and not allowed to add parent terms
// so return a friendly message so the user at least knows
return new WP_Error(
'parent_terms_not_allowed_for_editors',
__('Sorry, you are not allowed to add parent terms.')
);
} else {
// a super and/or admin, s|he is allowed to do what s|he wants
return $term;
}
}
Le pre_insert_term
hook fait partie de la fonction wp_insert_term()
.
Quelques notes:
parent
du $args
EST 0
, si aucun parent n'est sélectionné. Mais nous n’avons pas accès à ceux de l’action, le formulaire renvoie la valeur -1
pour $_POST[ 'parent' ]
si "Aucun" est sélectionné. Donc <= '0'
devrait fonctionner dans tous les cas.current_user_can()
, car il s'agit simplement de faux - bien que vous le voyiez souvent, il est toujours mauvais. Au lieu de cela les capacités sont utilisées pour déterminer le type d'utilisateur avec lequel nous traitons.