In generale i motivi per cui si possa avere la necessità di implementare un’area riservata in un sito web sono tanti, ma fondamentalmente tutto si riduce al fatto che alcuni contenuti devono essere visibili solo ad alcuni utenti.
Scaricare documenti riservati, informazioni personalizzate, schede tecniche per i propri clienti, qualunque sia il motivo per cui possa essere richiesta la presenza di un’area riservata cercando su Google mi venivano sempre proposte soluzioni che implicavano l’utilizzo di uno o più plugin esterni.
Per questo motivo, se avete un minimo di dimestichezza con il codice PHP e sapete come modificare il file functions.php del vostro tema grafico in questo articolo vi spiegherò come creare un’area riservata in un sito WordPress senza dover utilizzare alcun plugin!
Caso 1: l’area riservata nella sua forma più basica

La domanda sembrerà banale, ma in effetti forse non tutti hanno pensato alla soluzione più semplice ed immediata, e cioè quella di utilizzare la funzione nativa di WordPress che permette di proteggere i contenuti di un post tramite password. Anche se l’intento di questo articolo non è certo quello di “spiegare l’uso della ruota”, è bene ricordare che chi cerca soluzioni sui motori a volte è un vero novizio e per questo motivo vale la pena spendere due righe per accennare al fatto che WordPress prevede un campo “visibilità” che permette di nascondere i contenuti di quel post fino a che non si sia introdotta una password.
Il grosso vantaggio/svantaggio di questo metodo è che non esiste nessun controllo sull’utente che sblocca i contenuti perchè la password non è associata a credenziali personali e quindi questo metodo si rende disponibile anche agli utenti non registrati.
Non c’è limite alle pagine che si possono proteggere con password e ognuna può essere protetta da una password diversa.
Caso 2: creare un’area riservata strutturata, senza l’uso dei plugin
Scopo di questo progetto sarà quello di creare una pagina che possa fare da contenitore di tutti i post privati registrati nell’area riservata. Avremo perciò bisogno di realizzare un template da applicare alla pagina “area riservata” che contenga una form per il login e una query che vada a chiamare tutti i contenuti privati contenuti nel sito, rendendo visibili all’utente registrato solo quelli a lui assegnati.
Gli step per ottenere quello che ci serve sono quindi fondamentalmente i seguenti:
- creare un ruolo utente che possa ricevere i diritti di accesso all’area riservata, e uno di amministratore che possa assegnare di diritti
- creare un custom post type “area riservata” per l’inserimento di contenuti protetti
- per praticità, possibilità di rendere “privato” di default ogni nuovo post della tipologia “area riservata”
- creare un metabox da far apparire nei post di tipo “area riservata” che permetta l’associazione al rispettivo destinatario
- creare una login per il riconoscimento degli utenti registrati all’area riservata, che possa evitare di rimandare alla login di default dell’admin di WordPress in caso di dati di registrazione errati o mancanti.
- creare un template per la pagina del sito che dovrà visualizzare i contenuti protetti dell’area riservata
1. creare un ruolo utente che possa ricevere i diritti di accesso all’area riservata, e uno di amministratore che possa assegnare di diritti
Per ragioni di sicurezza ipotizziamo che gli utenti che devono avere accesso all’area riservata non debbano avere niente a che fare con la gestione dell’area di admin, nemmeno a livello basso, quindi creiamo un’ruolo apposito a cui non sia associato nessun diritto di editing e che ci servirà per raggruppare tutti gli utenti che dovranno vedere un contenuto a loro privatamente destinato sul lato front-end del sito.
Per ottenere questo, il codice da inserire nel file functions.php del tema dovrà essere il seguente:
function add_reserved_area_roles() {
add_role(
'area_riservata_utente', 'Area riservata: Utente',
array (
'read' => true,
'read_private_posts' => true,
'read_private_pages' => true,
)
);
add_role(
'area_riservata_gestore', 'Area riservata: Gestore',
array (
'read' => true,
'create_users' => true,
'delete_users' => true,
'edit_users' => true,
'list_users' => true,
'promote_users' => true,
'remove_users' => true,
'delete_others_pages' => true,
'delete_pages' => true,
'delete_private_pages' => true,
'delete_published_pages' => true,
'edit_others_pages' => true,
'edit_pages' => true,
'edit_private_pages' => true,
'edit_published_pages' => true,
'publish_pages' => true,
'read_private_pages' => true,
'delete_others_posts' => true,
'delete_posts' => true,
'delete_private_posts' => true,
'delete_published_posts' => true,
'edit_others_posts' => true,
'edit_posts' => true,
'edit_private_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'read_private_posts' => true,
'upload_files' => true,
)
);
}
add_action('admin_init', 'add_reserved_area_roles');
// CONFIGURO I PERMESSI DEI RUOLI CREATI
// controllo quali "admin" possono creare/modificare/cancellare un utente ...
function my_get_allowed_roles( $user ) {
$allowed = array();
if ( in_array( 'administrator', $user->roles ) ) { // administrator can edit all roles
$allowed = array_keys( $GLOBALS['wp_roles']->roles );
} elseif ( in_array( 'area_riservata_gestore', $user->roles ) ) {
$allowed[] = 'area_riservata_utente';
}
return $allowed;
}
// ... quali ruoli possono assegnare questi "admin" ...
function my_editable_roles( $roles ) {
if ( $user = wp_get_current_user() ) {
$allowed = my_get_allowed_roles( $user );
foreach ( $roles as $role => $caps ) {
if ( ! in_array( $role, $allowed ) )
unset( $roles[ $role ] );
}
}
return $roles;
}
add_filter( 'editable_roles', 'my_editable_roles' );
// ... e infine evito che gli "admin" possano creare/modificare/cancellare utenti oltre a quelli dei ruoli permessi.
function my_map_meta_cap( $caps, $cap, $user_ID, $args ) {
if ( ( $cap === 'edit_user' || $cap === 'delete_user' ) && $args ) {
$the_user = get_userdata( $user_ID ); // The user performing the task
$user = get_userdata( $args[0] ); // The user being edited/deleted
if ( $the_user && $user && $the_user->ID != $user->ID /* User can always edit self */ ) {
$allowed = my_get_allowed_roles( $the_user );
if ( array_diff( $user->roles, $allowed ) ) {
// Target user has roles outside of our limits
$caps[] = 'not_allowed';
}
}
}
return $caps;
}
add_filter( 'map_meta_cap', 'my_map_meta_cap', 10, 4 );
2. Creare un custom post type “area riservata” per l’inserimento di contenuti protetti
Qui non si richiede nessuna programmazione specifica salvo quella standard che WordPress ci fornisce per la creazione di un custom post type, e starà a voi decidere quali. Aggiungete quindi, sempre nel file functions.php del tema, anche questo pezzo di codice dopo quello che avete trovato al punto 1.
add_action('init', 'crea_contenuti');
function crea_contenuti() {
$args = array(
'labels' => $labels,
'public' => true,
'rewrite' => array( 'slug' => 'contenuti' ),
'has_archive' => true,
'hierarchical' => false,
'supports' => array(
'title',
'editor',
'thumbnail',
'comments'
),
'menu_icon' => 'dashicons-lock',
'show_in_rest' => TRUE,
);
register_post_type('area-riservata', $args);
}
3. Possibilità di rendere “privato” di default ogni nuovo post della tipologia “area riservata”
Basta questo questo pezzo di codice, sempre nel file functions.php del tema, aggiunto di seguito a quello già indicato al punto 2.
function force_type_private($post)
{
if ( $post['post_type'] == 'area-riservata' ) {
if ( $post['post_status'] == 'publish' ) {
$post['post_status'] = 'private';
}
}
return $post;
}
add_filter('wp_insert_post_data', 'force_type_private');
4. creare un metabox da far apparire nei post di tipo “area riservata” che permetta l’associazione al rispettivo destinatario
function users_meta_init(){
add_meta_box("users-meta", "Visibilità Utenti", "users", "area-riservata", "normal", "high");
}
add_action("admin_init", "users_meta_init");
// LISTA DEGLI UTENTI
function users() {
global $post;
$custom = get_post_custom($post->ID);
$users = isset($custom["users"][0]);
$user_args = array(
// cerco solo gli utenti di tipo sottoscrittore
'role' => 'area_riservata_utente',
'orderby' => 'display_name'
);
// creo la WP_User_Query object
$wp_user_query = new WP_User_Query($user_args);
// richiamo i risultati
$subscribers = $wp_user_query->get_results();
// controllo i risultati
if (!empty($subscribers)) {
// l'attributo di name è la chiave del customfield
echo "<select name='users'>";
echo '<option value="all">Tutti</option>';
// loop che mostra tutti i sottoscrittori
foreach ($subscribers as $subscriber){
// richiamo i dati dei sottoscrittori
$subscriber_info = get_userdata($subscriber->ID);
$subscriber_id = get_post_meta($post->ID, 'users', true);
if($subscriber_id == $subscriber_info->ID) {
$subscriber_selected = 'selected="selected"';
} else {
$subscriber_selected = '';
}
echo '<option value='.$subscriber_info->ID.' '.$subscriber_selected.'>'.$subscriber_info->display_name.'</option>';
}
echo "</select>";
} else {
echo 'No authors found';
}
}
// SALVO IMPOSTAZIONE LISTA
add_action('save_post', 'save_userlist');
function save_userlist() {
global $post;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $post->ID;
}
update_post_meta($post->ID, "users", $_POST["users"]);
}
La prima funzione è quella che crea il metabox del la selezione dell’utente da associare al contenuto dell’area riservata, mentre la seconda è quella che popola la select, dove abbiamo previsto, oltre ai nomi dei singoli utenti anche l’opzione “tutti” che ci permetterà di creare un contenuto protetto disponibile per tutti gli utenti previsti dall’area registrata.
5. Creare una login per il riconoscimento degli utenti registrati all’area riservata
Anche questa volta il codice deve essere inserito nel file functions.php del tema, dopo quello che avete inserito fino ad ora.
// se: dati invalidi
function custom_login_failed( $username ) {
$referrer = $_SERVER['HTTP_REFERER'];
if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
wp_redirect( '/area-riservata?dati_errati_o_mancanti', 301 );
// wp_redirect( home_url() );
exit;
}
}
add_action( 'wp_login_failed', 'custom_login_failed' );
// se: dati mancanti ( input vuoti )
function custom_authenticate( $user, $username, $password ) {
if ( is_wp_error( $user ) && isset( $_SERVER[ 'HTTP_REFERER' ] ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-admin' ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-login.php' ) ) {
$referrer = $_SERVER[ 'HTTP_REFERER' ];
foreach ( $user->errors as $key => $error ) {
if ( in_array( $key, array( 'empty_password', 'empty_username') ) ) {
unset( $user->errors[ $key ] );
$user->errors[ 'custom_'.$key ] = $error;
}
}
}
return $user;
}
add_filter('authenticate','custom_authenticate', 31, 3);
6. Creare un template per la pagina del sito che dovrà visualizzare i contenuti protetti dell’area riservata
Questa volta il codice deve essere inserito nel PHP del template della pagina che deve fare da “contenitore” dell’area riservata e deve essere inserito al post del loop standard che richiama i contenuti.
Al primo passaggio verifichiamo se chi sta visualizzando la pagina è un’utente loggato, e in quel caso presentiamo un piccolo messaggio di saluto, poi, di seguito, pubblichiamo il contenuto della pagina, se presente. Diversamente la pagina presenterà il form di login e i contenuti dell’area riservata non saranno visibili.
Ora viene il bello, perchè in caso di utente loggato il codice farà una query di tutti i custom post type di tipo “area riservata” e se l’utente è un’amministratore esso potrà vedere tutti i contenuti privati, mentre se l’utente non è amministratore esso potrà vedere esclusivamente i post a lui associati o quelli protetti ma visibili a qualsiasi registrato indistintamente.
<?php
//se l'utente è loggato mostra messaggio di benvenuto e post
if ( is_user_logged_in() ) {?>
<?php //info dell'utente loggato
global $current_user;
get_currentuserinfo();
$my_user = $current_user->user_login ;
$my_user_level = $current_user->user_level ;
$my_user_id = $current_user->ID;
echo 'Benvenuto, '. $my_user;
?>
<hr />
<?php // se c'è contenuto nella pagina lo pubblico
while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', 'page' ); ?>
<?php endwhile; // end of the loop. ?>
<?php //se l'utente è l'admin mostro tutti i contenuti, altrimenti mostro quelli dell'utente associato al post
if( $my_user_level == 10 ) {
//loop con tutti i contenuti
$wpquery = new WP_Query(array(
'post_type' => 'area-riservata',
));
} else {
//loop con i contenuti del relativo utente + quelli contrassegnati come all
$wpquery = new WP_Query(array(
'post_type' => 'area-riservata',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'users',
'value' => $my_user_id,
'compare' => '='
),
array(
'key' => 'users',
'value' => 'all',
'compare' => '='
)
)
)
);
}
?>
<?php if ( $wpquery -> have_posts() ) : while ( $wpquery -> have_posts() ) : $wpquery -> the_post(); ?>
<?php //richiamo le info dell'utente associato al post
$user_selected = get_post_meta($post->ID, 'users', TRUE);
$user_info = get_userdata($user_selected);
?>
<div class="post">
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_content('Leggi...');?>
<?php if($user_selected == 'all') { ?>
<small><i><?php echo 'Contenuto per Tutti'; ?></i></small>
<?php } else { ?>
<small><i><?php echo 'Contenuto per l\'utente: ' . $user_info->user_login . "\n"; ?></i></small>
<?php } ?>
</div>
<?php endwhile; else: ?>
<div class="post">
<h3>Spiacenti, non ci sono contenuti...</h3>
</div>
<?php endif; ?>
<a href="<?php echo wp_logout_url( home_url() ); ?>" title="Logout">Logout</a>
<?php } else { ?>
<h2>Login</h2>
<?php wp_login_form(); ?>
<?php } ?>
Conclusioni
Forse questo metodo non è proprio di semplice implementazione, o perlomeno non lo è sicuramente per chi è a completo digiuno di programmazione però, di blog che spiegano come realizzare un’area riservata utilizzando almeno 2 o 3 plugin ce ne sono già a bizzeffe per cui, per evitare di ripeterci, abbiamo pensato di fare cosa gradita perlomeno a chi, come noi, preferisce sporcarsi le mani con il codice piuttosto che utilizzare plugin di terze parti che potrebbero entrare in conflitto con il tema!