6 maggio 2017

Area riservata di WebSite X5 13: avatar utente

Questo articolo nasce da una richiesta emersa nella community di WebSite X5 ed elaborata dall'utente Giorgio C. che ci ha coinvolto: mostrare un'immagine associata all'utente registrato, un avatar quindi, che un utente possa cambiare a piacere.
Partendo dal codice di Giorgio, con cui l'utente può visualizzare il proprio avatar nell'header del sito una volta loggato, noi abbiamo fatto una variazione sul tema, creando una pagina profilo e facendo in modo che l'immagine associata ad ogni utente sia visibile a tutti nel momento in cui l'utente inserisce un commento nel guestbook e/o in un articolo del blog.

Qui la nostra demo:

demo avatar utente area riservata
DEMO

Non entriamo nel merito di come creare un'area riservata, poiché la guida del programma è già esaustiva. Sottolineiamo però che, per il corretto funzionamento del codice, occorre che nel progetto venga impostata in Gestione Dati, una Cartella su Server con accesso in scrittura verificando che abbia i permessi necessari. Accertarsi inoltre di aver scritto correttamente l'Indirizzo URL del Sito al passo 1 (Attenzione: NON scrivere il nome della pagina index nel percorso).

Vediamo ora come procedere:

La pagina profilo


La pagina profilo è una pagina protetta in cui vengono richiamati i dati dell'utente loggato: l'output è dinamico cioè dipende da chi la visualizza. In essa è presente anche il form con cui l'utente può cambiare il proprio avatar. Può essere impostata come Pagina d'ingresso per tutti gli utenti, o anche raggiungibile con un link.
Inseriamo in essa un Oggetto Codice HTML con il seguente codice:

<!-- Code by Giorgio C. & MAeSI - quellidelcucuzzolo.blogspot.it
     Please do not remove credit  -->
<div id="ms-datiUtente">
<!-- dati utente -->
<?php
$qfolder  = $imSettings['general']['public_folder'];
$n        = time();
$pa       = Configuration::getPrivateArea();
$dati     = $pa->whoIsLogged();
$username = $dati['username'];
$datiUser = $pa->getUserByUsername($username); // SOLO EDIZIONE PROFESSIONAL 
$avatar   = glob($qfolder . "/avatar-" . $username . ".*");
$tsfoto = 0;
if (empty($avatar))
    $foto = $qfolder . "/default.png";
else {
    foreach ($avatar as $value) {
        if (filemtime($value) > $tsfoto) {
            $tsfoto = filemtime($value);
            $foto   = $value;
        }
    }
}
echo '<div id="datiUser">', 
'<img src="' . $foto . '?' . $n . '" alt="avatar" />', 
'<span>Username:</span> ' . $username . '<br />', 
'<span>Nome completo:</span> ' . $dati['realname'] . '<br />', 
'<span>E-mail:</span> ' . $datiUser['email'] . '<br />', // SOLO EDIZIONE PROFESSIONAL 
    '</div>';
?>
</div>
<div style="clear:both"></div>

<!-- form per cambio avatar -->
<form id="cambioAvatar" enctype="multipart/form-data" method="POST" action="uploadavatar.php">
<div><label for="avatar">Cambia l'immagine del profilo:</label></div>
<input type="file" name="image" id="avatar" />
<input type="submit" value="invia" />
</form>

<!-- messaggio di conferma/errore upload -->
<div id="messaggio">
<?php
if (!empty($_SESSION['message'])) {
    echo $_SESSION['message'];
    unset($_SESSION['message']);
}
?>
</div>

Chi utilizza la Evolution deve rimuovere le due righe di codice con il commento //SOLO EDIZIONE PROFESSIONAL: si tratta del dato e-mail che è presente unicamente se viene utilizzata la registrazione automatica, prevista solo nell'edizione Professional. Si sottolinea inoltre che questo codice può essere utilizzato solo in pagine protette, dove il richiamo del file x5engine.php, necessario per il corretto funzionamento del codice, è già incluso.

Il codice richiede la presenza, nella Cartella su Server con accesso in scrittura indicata in Gestione Dati, di una immagine di default che verrà utilizzata finché l'utente non la cambierà. Noi abbiamo usato questa immagine: default.png. Nel caso si utilizzi un'immagine con diverso nome e/o estensione occorrerà apportare le opportune modifiche al codice.

Ovviamente il risultato sarà visibile solo online. Se vogliamo tenere pulita la pagina dell'anteprima, evitando di visualizzare parti di codice, è possibile inserire questo script in Proprietà Pagina, Esperto, Codice personalizzato, Prima della chiusura del tag HEAD:

<script>
$(document).ready(function() {
  // funzionalità offline
  if (location.host == "127.0.0.1:8080")
    $("#ms-datiUtente").html("I dati saranno visibili solo quando il sito verrà esportato su Internet");
});
</script>

Nella scheda Esperto dell'Oggetto Codice HTML possiamo scrivere le regole CSS per definire l'aspetto grafico che preferiamo. Noi abbiamo utilizzato questo codice:

#datiUser,
#cambioAvatar {
  line-height: 26px;
  font-size: 16px;
  padding: 10px;
}
#datiUser span {
  width: 125px;
  font-weight: bold;
  display: inline-block;
}
#datiUser img {
  max-width: 256px;
  float: left;
  padding: 6px 10px 6px 0;
}
#cambioAvatar input {
  padding-bottom: 10px;
}
#messaggio {
  color: red;
}
#messaggio span {
  color: green;
}

Lo script per l'upload


L'upload del nuovo avatar è gestito dal file uploadavatar.php, che si occupa di validare l'estensione del file caricato, le sue dimensioni in byte, e di rinominare il file in modo che il suo nome contenga l'username dell'utente: nel momento in cui l'utente cambierà il suo avatar, la vecchia immagine verrà cancellata dal server e sostituita da quella nuova.
<?php
/* =================================================================
   PHP Code by Giorgio C. & MAeSI - quellidelcucuzzolo.blogspot.it
   Please do not remove credit    
   =================================================================  */
if (!isset($_SERVER['HTTP_REFERER'])){
exit;
}
//apertura e lettura dati di sessione
require_once("res/x5engine.php"); 
$qfolder = $imSettings['general']['public_folder']; 
$pa      = Configuration::getPrivateArea(); 
$dati    = $pa->whoIsLogged();
$username = $dati['username'];

//informazioni sull'immagine caricata
$max_size = 102400; //dimensioni massime in byte dell'immagine da caricare
$tmp      = $_FILES['image']['tmp_name'];
if(!function_exists('mime_content_type'))
$type     = $_FILES['image']['type'];
else 
$type     = mime_content_type($tmp);
$size     = $_FILES['image']['size'];  
  
//controllo delle estensioni accettate  
function check_ext($tipo){
 switch ($tipo) {
  case "image/png":
  return true;
  break;
  case "image/jpg":
  return true;
  break;
  case "image/jpeg":
  return true;
  break;
  case "image/gif":
  return true;
  break;
  default:
  return false;
  break;
 }
}

//estensione dell'immagine
function get_ext($tipo) {
 switch ($tipo) {
  case "image/png":
  return ".png";
  break;
  case "image/jpg":
  return ".jpg";
  break;
  case "image/jpeg":
  return ".jpg";
  break;
  case "image/gif":
  return ".gif";
  break;
  default:
  return false;
  break;
 }
}

//gestione degli errori
function get_error($tmp, $type, $size, $max_size){
    if (!is_uploaded_file($tmp)) {
  $_SESSION['message'] = 'File caricato in modo non corretto';
    }
    else if (!check_ext($type)) {
  $_SESSION['message'] = 'Estensione del file non ammessa';
    }
    else if($size > $max_size) {
        $_SESSION['message'] = 'Dimensione del file troppo grande';
    }
}


//caricamento nuova immagine
if (is_uploaded_file($tmp) && check_ext($type) && $size <= $max_size) {
    $ext     = get_ext($type);
    $newfoto = $qfolder . "/avatar-" . $username . $ext;
    if (move_uploaded_file($tmp, $newfoto)) {
        $_SESSION['message'] = '<span>Immagine caricata con succcesso</span>';
    } else {
        $_SESSION['message'] = 'Non è stato possibile caricare l\'immagine';

    }
} else {
    get_error($tmp, $type, $size, $max_size);
}

//ritorno alla pagina contenente il form per l'upload
header('Location: ' . $_SERVER['HTTP_REFERER']);
?>
Il codice è completamente commentato per rendere più agevole la sua comprensione. Sono personalizzabili le dimensioni massime e le estensioni accettate ed anche i messaggi di errore.
Per utilizzare questo codice occorre incollarlo in un file creato con Notepad++ o il Blocco Note, e salvarlo con nome uploadavatar e con estensione .php. I più pigri possono scaricare il file QUI.
Il file uploadavatar.php deve risiedere nella root del sito. Si può allegare al progetto attraverso la scheda Esperto dello stesso Oggetto Codice HTML inserito nella pagina profilo, avendo cura di lasciare vuoto il campo Percorso relativo sul Server, oppure trasferirlo sul server con un programma FTP.

I commenti del guestbook e del blog


Avere un avatar che solo l'utente può vedere è, secondo noi, uno spreco di risorse. Abbiamo provato allora ad associare l'avatar ad un commento che l'utente loggato inserisce nel guestbook e/o nel blog del sito.

Per associare stabilmente l'avatar al commento sono necessarie due condizioni:
1. identificare l'utente loggato grazie all'username
2. memorizzare il percorso dell'immagine nei dati del commento.

Poiché il programma non permette l'inserimento di campi aggiuntivi nel form per l'invio dei commenti, abbiamo pensato di sacrificare il campo Sito Internet, utilizzandolo per memorizzare il percorso assoluto del file immagine. Ovviamente nasconderemo al visitatore questo campo con JavaScript, ma esso risulterà riempito in modo automatico in funzione di chi in quel momento visualizza la pagina: se il visitatore non è un utente loggato, il campo verrà riempito con il percorso corrispondente all'immagine di default.

Questo è il risultato ottenuto:
Nelle Proprietà della pagina che contiene l'Oggetto Guestbook e/o della pagina speciale Blog, scheda Esperto, Codice Personalizzato, Prima della chiusura del tag HEAD, inseriamo questo codice PHP/JS:

<!-- Code by Giorgio C. & MAeSI - quellidelcucuzzolo.blogspot.it
     Please do not remove credit   -->
<?php
$qfolder = $imSettings['general']['public_folder']; 
$qurl = pathCombine(array($imSettings['general']['url'], $qfolder));
$qblog = $_SERVER['PHP_SELF'];
if (strpos($qblog, '/blog/') !== false)
    $qpath = '../';
else
    $qpath = '';
$pa = Configuration::getPrivateArea();
$dati    = $pa->whoIsLogged();
$username = $dati['username'];
$realname = $dati['realname'];
$datiUser = $pa->getUserByUsername($username);  //SOLO EDIZIONE PROFESSIONAL 
$email = $datiUser['email'];      //SOLO EDIZIONE PROFESSIONAL
$avatar = glob($qpath.$qfolder."/avatar-" . $username . ".*"); 
$tsfoto = 0;
if (empty($avatar))
    $foto = $qurl . "/default.png";
else {
    foreach ($avatar as $value) {
        if (filemtime($value) > $tsfoto) {
            $tsfoto  = filemtime($value);
            $fotonew = $value;
        }
    }
    $foto = str_replace("../", "", $fotonew);
    $foto = str_replace($qfolder, $qurl, $foto);
}
?>
<script>
$(document).ready(function() {
    $("input[id$='topic-form-name']").val("<?php echo $realname ?>");
    $('input[id$="topic-form-email"]').val('<?php echo $email ?>'); //SOLO EDIZIONE PROFESSIONAL
    $('input[id$="topic-form-url"]').val('<?php echo $foto ?>').parent().hide();
  $(".topic-comments-user").each(function() {
    var $item = $(this).find("a");
    if ($item.length != 0) {
      var customCampo = $item.attr("href");
      var customNome = $item.contents();
      $item.replaceWith(customNome);
      $(this).prepend("<img class='campoCustomGb' src='" + customCampo + "' alt='avatar' />");
    }
  })
});
</script>

Il codice si occupa di identificare l'eventuale utente loggato, riempire automaticamente i campi del form con Nome completo e E-mail (solo per l'edizione Professional), inserire nel campo nascosto il percorso dell'immagine utilizzata dall'utente come avatar e, infine, visualizzare l'avatar nel relativo commento.


Anche in questo caso chi utilizza l'edizione Evolution deve rimuovere le tre righe di codice con il commento //SOLO EDIZIONE PROFESSIONAL. 

Di seguito al codice precedente, possiamo inserire le regole CSS che gestiscono la formattazione dell'avatar. Noi abbiamo utilizzato regole di stile minimali, ma qui ci si può sbizzarrire:
<style>
.topic-comment:after {
    content: '';
    display: block;
    clear: both;
}
.topic-comments-user img {
    float: left;
    margin-right: 12px;
    width: 64px;
}
</style>
La prima regola scritta è fondamentale poiché interrompe il flusso degli elementi, evitando sovrapposizioni nel caso in cui l'immagine sia più alta del relativo commento.
Se nel sito sono presenti sia il guestbook che il blog è preferibile inserire il codice CSS una volta sola nel progetto, in Impostazioni Avanzate, Statistiche, SEO e Codice, Esperto, Prima della chiusura del tag HEAD.

Si fa presente che il percorso dell'avatar viene memorizzato, per ogni commento, nel database o in un file di testo quindi, se un utente cambia l'immagine del profilo scegliendo una nuova immagine con uguale estensione, tutti i commenti (vecchi e nuovi) visualizzeranno la nuova immagine poiché la nuova immagine sovrascrive sul server quella vecchia; se però un utente dovesse caricare un'immagine con estensione diversa da quella precedentemente utilizzata, solo i nuovi commenti inseriti avranno memorizzato l'estensione della nuova immagine, quindi i vecchi commenti visualizzeranno l'avatar vecchio, i nuovi commenti quello nuovo.


Un grande ringraziamento a Giorgio per tutto il lavoro che ha svolto e ha condiviso e all'autore di questo articolo ispiratore.


Aggiornamento del 10/05/2017

Aggiornato il codice per mantenere sul server avatar dello stesso utente con diversa estensione.

19 commenti:

  1. Come sempre, semplicemente grandissimi! Complimenti.
    Una cosa non ho capito, qualora volessi far comparire l'immagine ad esempio nell'header delle pagine una volta loggato, che codice devo inserire?

    Nicola

    RispondiElimina
    Risposte
    1. Ciao Nicola,
      grazie a te per il commento.
      In questo post sull'HelpCenter Giorgio ha postato il codice (ultimo aggiornamento) da utilizzare per visualizzare l'avatar e un messaggio di benvenuto nell'header del sito.
      Ovviamente tutte le pagine del sito devono avere estensione .php

      Elimina
    2. Buongiorno, lo script deve essere inserito dentro un oggetto html nell'intestazione, giusto? Con quale altezza?

      Elimina
    3. Ciao,
      sì, lo script postato da Giorgio su X5 Help Center va inserito ovviamente in un oggetto HTML nell'header del sito. Per l'altezza ti devi regolare in base al font utilizzato e all'altezza massima impostata per l'avatar.

      Elimina
    4. Spettacolare, rendete professionale questo programma :)

      Elimina
  2. Grazie come sempre..ma nel post indicato non ho trovato alcun codice tantomeno nei post di Giorgio, ..mi sono perso qualcosa? se si abbiate pazienza. :)

    RispondiElimina
    Risposte
    1. E' un file .rar allegato nel post che ti abbiamo linkato: forse non ti sei loggato su X5 Help Center.

      Elimina
  3. Complimenti per il magnifico articolo perchè questa funzionalità rende Website molto professionale :)

    RispondiElimina
  4. Bravi, come sempre. Complimenti anche a Giorgio.

    RispondiElimina
  5. Penso di aver eseguito alla lettera le istruzioni ma l'esecuzione si blocca su :
    $pa = Configuration::getPrivateArea();
    e dice che la "Class Configuration" non e' stata trovata.
    A cosa si riferisce quest'istruzione?
    Grazie a chi vorra' rispondermi.

    RispondiElimina
    Risposte
    1. Ciao Crispino,
      un paio di domande:
      - stai forse provando con la versione 12?
      - stai forse provando il codice in una pagina non protetta?
      Il codice è stato scritto per la versione 13 e la pagina "profilo" deve essere protetta (come è scritto nell'articolo).

      Elimina
  6. Ecco, ne avevo il dubbio ma vedevo raccomandazioni solo per la versione pro, non ho visto in nessun posto v.13
    Ok, mi aggiorno. grazie ancora.

    RispondiElimina
  7. Anzi... ora vedo chiaro in prima riga del blog "x5 13", chiedo scusa

    RispondiElimina
  8. Ciao ragazzi, per la v14 non funziona la parte di upload della propria immagine avatar: Mi sembra che il problema in queste righe di codice, forse la variabile "username" che ormai non esiste:

    require_once("res/x5engine.php");

    $qfolder = $imSettings['general']['public_folder'];

    $pa = Configuration::getPrivateArea();

    $dati = $pa->whoIsLogged();

    $username = $dati['username'];

    ma ho provato ad inserie "email", "firstname","uname",...

    RispondiElimina
    Risposte
    1. Ciao,
      come ti abbiamo già scritto, NON abbiamo la 14 per poter verificare eventuali variazioni del motore PHP di WebSite X5.

      Come ti abbiamo già scritto, posta il link alla tua prova per tentare di capire il tuo problema.

      Elimina
    2. Ciao MAesi,
      ecco il sito online: http://sitiwebapp.16mb.com

      Elimina
    3. Ciao,
      abbiamo letto la marea di post che hai scritto su X5 Help Center.
      Con un progetto già pronto che ti ha postato Skeggia non hai avuto i problemi da te riscontrati, quindi i problemi erano nella tua implementazione.

      Elimina