CMSMS a small CookBook

CMS Made Simple è un Sistema di Gestione dei Contenuti flessibile e potente. La piattaforma si basa su PHP/MySQL ed implementa SMARTY (un template engine PHP versatile e di semplice comprensione). Questa guida è un piccolo cookbook utile a chi ha un’esperienza minima di CMSMS e vuole un riferimento veloce per risolvere problemi comuni o è in cerca di un UDT (User Defined Tags o Tag Definiti dallUtente) specifico.

Indice

How to

In questa sezione vengono fornite risposte in ordine sparso. I contenuti hanno in comune il fatto di essere sintetici e dal risvolto prettamente operativo.

D: Come stampare l'alias della pagina corrente?

R: Spesso è utile stampare l'alias della pagina corrente allo scopo di definire un id o una classe univoca così applicare stili specifici ad una pagina. Possiamo scrivere così nel body del template:


<body id="{$page_alias}">

D: Come stampare i figli della pagina corrente o di una pagina dato l’alias?

R: questa operazione potrebbe essere effettuata attraverso un menù ma spesso risulta più flessibile adottare il modulo CGSimpleSmarty che permette di recuperare potenzialmente tutti i contenuti appartenenti ad altre pagine usando la sintassi SMARTY. Possiamo scrivere così nella pagina:
Recupera i figli della pagina corrente
{$cgsimple->get_children($page_alias,'',variabile)}
{if count($variabile)}
{foreach from=$variabile item='varIndice'}
<a href="index.php?page={$varIndice.alias}">{$varIndice.title}</a>
{/foreach}
{/if}
Recupera i figli di una pagina dato l’alias
{content block=’aliasPagina’ oneline=’true’ assign=’aliasPagina’}
{$cgsimple->get_children($aliasPagina,'',variabile)}
{if count($variabile)}
{foreach from=$variabile item='varIndice'}
<a href="index.php?page={$varIndice.alias}">{$varIndice.title}</a>
{/foreach}
{/if}

D:Nel modulo NEWS come si stampa la data in italiano e nel formato corretto?

R: Se si desidera solamente impostare l’ordine corretto è sufficiente inserire dentro il template news {$entry->postdate|cms_date_format:"%B %Y"}.
Per scegliere il formato desiderato si può fare riferimento ai parametri di strftime.
Se si desidera avere giorno e/o mese estesi invece è necessario tradurli in italiano attraverso un UDT da inserire in cima al template.

  • Creare quindi un UDT, chiamarlo ad esempio setlocale e inserire setlocale(LC_TIME, 'italian');
  • dopodichè richiamare in cima ad ogni pagina (o in ogni caso prima di richiamare la data {setlocale}).

D: Estrarre il numero di figli di una pagina dato l'alias?

R: anche questo script utilizza il modulo CGSimpleSmarty che permette di recuperare contenuti appartenenti ad altre pagine usando la sintassi SMARTY.
Lo script recupera i figli dell a pagina data che vengono poi ciclati per far incrementare un contatore.

{content block='aliasPagina' oneline='true' assign='aliasPagina'}
{$cgsimple->get_children($aliasPagina,'','variabile')}
{counter start=0 assign='variabile_contatore'}
{foreach from=$variabile item='child_variabile'}
{counter}
{/foreach }
{$variabile_contatore}

D:Come posso stampare gli attributi della pagina corrente (extra1,extra2,extra3)?

R:Ogni pagina mette a disposizione tre attributi di pagina compilabili e richiamabili. Possono essere utili per diverse operazioni. Ad ogni modo per richiamarsi è sufficiente scrivere

{capture assign='extra1'}{$content_obj->GetPropertyValue('extra1')}{/capture}
{capture assign='extra2'}{$content_obj->GetPropertyValue('extra2')}{/capture}
{capture assign='extra3'}{$content_obj->GetPropertyValue('extra3')}{/capture}

Con questo script ho provveduto a richiamare i tre attributi di pagina e assegnarli ad altrettante variabili

D:Come mai le variabili SMARTY assegnate al di fuori del body non sono utilizzabili dentro di esso?

R:Nelle versioni di CMSMS precedenti alla 1.4 il template veniva elaborato nella sua interezza per cui una variabile dichiarata al di fuori di body poteva essere utilizzata anche al suo interno, nelle ultime release ci sono due processi separati. Se si preferisce il metodo precedente è sufficiente andare in config.php (riga 27) e settare il parametro "process_whole_template" a true

$config['process_whole_template'] = true;

D:Come posso aumentare la qualità delle miniature generate dal modulo gallery?

R:Il modulo gallery è un'ottima estensione ma, ad oggi, non permette di scegliere la qualità con cui vengono generate le miniature. Per aggirare il problema è possibile intervenire in questo modo: nel file Gallery.module.php che si trova in modules/Gallery, cercare la funzione imagejpeg(...); riga 928 nella release 1.4.4 e modificare l’ultimo parametro ad esempio mettendo imagejpeg($newimage, $thumbname, 80);

D:Come posso cambiare le dimensioni delle miniature generate dal modulo core manage image (gestione immagini)?

R: Dalla release 1.8 in poi è sufficiente andare in Ammistrazione Sito > Impostazioni Globali al tab Impostazioni Generali in fondo;

D:Come posso creare un semplice slide di immagini con il modulo gallery e jQuery?

R:Il modulo gallery propone diversi template già pronti, tuttavia spesso è più produttivo partire realizzandone uno ex-novo che risponda alle proprie esigenze.

Questo template è molto semplice e consiste in un semplicissimo slide di immagini realizzato con l'ausiglio di jQuery e il plugin Cycle

Procediamo:

  • Scaricate jQuery e Cycle
  • Andate in contenuto > gallery poi sul tab "templates" e createne uno nuovo
  • Alla voce "template source" inserite il seguente codice:

    <div id="slideWrapper">
    <div class="innerSlide">
    {foreach from=$images item=image}
    {if !$image->isdir}
    <img src="{$image->file|escape:'url'|replace:'%2F':'/'}" alt="{$image->titlename}" width="600" height="350" />
    {/if}
    {/foreach}
    </div>
    </div>
  • alla voce "Template CSS-stylesheet" inserite gli eventuali stili relativi alla gallery (la gallery per funzionare non necessita di stili aggiuntivi):
  • alla voce "Template Javascript" inserite il seguente codice (omettete il framework se già utilizzato nel template)
    <script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>
    <script type="text/javascript" src="js/jquery.cycle.all.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
    $("#slideRicette .innerSlide").cycle();
    });
    </script>
  • La suddetta gallery non farà altro che caricare le foto omettendo eventuali sotto-gallery

D:È possibile scrivere in PHP direttamente nei template?

R: Di regola no (è consigliabile scrivere un UDT e poi richiamarlo nel template). Tuttavia andando nel config.php è possibile attivare il parsing del php mettendo true il paramentro "use_smarty_php_tags"

$config['use_smarty_php_tags'] = true;

D:Come ottimizzare le pagine da un punto di vista SEO?

R:Le attività SEO sono complesse e richiedono tempo per essere pianificate correttamente, tuttavia è possibile effettuare alcune ottimizzazioni base utili per rendere maggiormente ricercabili i contenuti di ciascuna pagina.
Con questo piccolo script da inserire in ogni template è possibile personalizzare title, titolo e altri parametri in ogni pagina

{* Dichiaro i blocchi *}
{content block='titolo_sostitutivo' label='SEO - questo titolo sostituisce quello originale' oneline='true' assign='titolo_sostitutivo'}
{content block='logo_sostitutivo' label='SEO - questo testo viene inserito nel logo' oneline='true' assign='logo_sostitutivo'}
{content block='metadesc' label='SEO - descrizione pagina' oneline='true' assign='metadesc'}
{content block='metakey' label='SEO - keywords pagina' oneline='true' assign='metakey'}
{global_content name='globalKeywords' assign='globalKeywords'}
{global_content name='globalDescription' assign='globalDescription'}
{* Sostituisco il title se il blocco e' stato compilato *}
{if $titolo_sostitutivo != '' && $titolo_sostitutivo != -1}
<title>{$titolo_sostitutivo}</title>
{else}
<title>{title} | {sitename}</title>
{/if}
....
{if $metakey != '' && $metakey != -1}
<meta name="keywords" content="{$metakey}" />
{else}
<meta name="keywords" content="{$globalKeywords|strip_tags}" /> {/if}
{if $metadesc != '' && $metadesc != -1}
<meta name="description" content="{$metadesc|truncate:140}">
{else}
<meta name="description" content="{$globalDescription|strip_tags|truncate:140}">
{/if}
....
{* Sostituisco il testo del logo se il blocco e' stato compilato *}
{if $logo_sostitutivo != '' && $logo_sostitutivo != -1}
<h1 id="logo">{$logo_sostitutivo}</h1>
{else}
<h1 id="logo">{sitename}</h1>
{/if}

Vi ricordo che per utilizzare quest script è necessario settare nel config.php

$config['process_whole_template'] = true;

Ricordarsi di creare i due contenuti globali globalKeywords e globalDescription

NOTA: le description vengono automaticamente ripulite da eventuali tag (se arrivano dal global content) e troncate ai 140 caratteri.

D:Quando creo un link ad un'ancora della pagina viene caricata la homepage, come posso aggirare il problema?

R: Per gestire le ancore è sufficiente non stampare il meta tag "base", per disattivarlo settare il parametro showbase a false per lo smarty metadata

{metadata showbase="false"}

UDT

In questa sezione vengono riportati alcuni UDT (User Defined Tags) utili per facilitare alcune operazioni.

Truncate Better

Questo UDT permette di gestire in modo più efficiente campi di testo da troncare. Rispetto alla funzione base di SMARTY questo UDT preserva i tag html dei testi troncati limitandosi a chiuderli correttamente prima di troncare il testo

Risorsa originale
/*
* http://www.smarty.net/forums/viewtopic.php?t=533
* Purpose: Cut a string preserving any tag nesting and matching.
* Author: Original Javascript Code: Benjamin Lupu <lupufr@aol.com>
* Translation to PHP & Smarty: Edward Dale <scompt@scompt.com>
* Modification to add a string: Sebastian Kuhlmann <sebastiankuhlmann@web.de>
* Modification to utilize as a CMSMS UDT and to add user defined closing text
* before closing tag if tag matches specified element:
* Avi J Liebowitz avij.com
* Install: Place in CMSMS UDT with name of 'truncate_better'
* Example CMSMS Usage:
* {truncate_better text=$entry->content truncate='300' add=' . . . '  link=$entry->moreurl link_text="Read More!"} */

// only execute if text is longer than desired length
if (strlen($params['text']) > $params['truncate']) {
if( !empty( $params['text'] ) && $params['truncate']>0 ) {
$isText = true;
$ret = "";
$i = 0;

$currentChar = "";
$lastSpacePosition = -1;
$lastChar = "";

$tagsArray = array();
$currentTag = "";
$tagLevel = 0;

$noTagLength = strlen( strip_tags( $params['text'] ) );

// Parser loop
for( $j=0; $j<strlen( $params['text'] ); $j++ ) {

$currentChar = substr( $params['text'], $j, 1 );
$ret .= $currentChar;

// Lesser than event
if( $currentChar == "<") $isText = false;

// Character handler
if( $isText ) {

// Memorize last space position
if( $currentChar == " " ) { $lastSpacePosition = $j; }
else { $lastChar = $currentChar; }

$i++;
} else {
$currentTag .= $currentChar;
}

// Greater than event
if( $currentChar == ">" ) {
$isText = true;

// Opening tag handler
if( ( strpos( $currentTag, "<" ) !== FALSE ) &&
( strpos( $currentTag, "/>" ) === FALSE ) &&
( strpos( $currentTag, "</") === FALSE ) ) {

// Tag has attribute(s)
if( strpos( $currentTag, " " ) !== FALSE ) {
$currentTag = substr( $currentTag, 1, strpos( $currentTag, " " ) - 1 );
} else {
// Tag doesn't have attribute(s)
$currentTag = substr( $currentTag, 1, -1 );
}

array_push( $tagsArray, $currentTag );

} else if( strpos( $currentTag, "</" ) !== FALSE ) {
array_pop( $tagsArray );
}

$currentTag = "";
}

if( $i >= $params['truncate']) {
break;
}
}

// Cut HTML string at last space position
if( $params['truncate'] < $noTagLength ) {
if( $lastSpacePosition != -1 ) {
$ret = substr( $params['text'], 0, $lastSpacePosition );
} else {
$ret = substr( $params['text'], $j );
}
}

// Close broken XHTML elements
while( sizeof( $tagsArray ) != 0 ) {
if ( sizeof( $tagsArray ) > 1 ) {
$aTag = array_pop( $tagsArray );
$ret .= "</" . $aTag . ">\n";
}
// You may add more tags here to put the link and added text before the closing tag
elseif ($aTag = 'p' || 'div') {
$aTag = array_pop( $tagsArray );
$ret .= $params['add'] . "<a href=\"". $params['link'] . "\" alt=\"". $params['link_text'] . "\">" . $params['link_text'] . "</a></" . $aTag . ">\n";
}
else {
$aTag = array_pop( $tagsArray );
$ret .= "</" . $aTag . ">" . $params['add'] . "<a href=\"". $params['link'] . "\" alt=\"". $params['link_text'] . "\">" . $params['link_text'] . "</a>\n";
}
}

} else {
$ret = "";
}

return( $ret );
echo ( $ret );
}
else {
return ( $params['text'] );
echo ( $params['text'] );
}

Redirect su pagina specifica per smartphone

Questo UDT effettua un redirect a pagina specifica (dato opportuno alias) se l'user agent è uno smartphone. In questo caso sepcifico è stata usata una classe commerciale di cui vi riporto il link

Classe MobileDetect //includo l'oggetto globale
$gCms = cmsms(); //global $gCms;
$smarty = &$gCms->GetSmarty();

include("MobileDetect.php");
$MobileDetect = new MobileDetect();

if($MobileDetect->IsIphone() || $MobileDetect->IsAndroid()){
//parso uno smarty per effettuare il redirect in un l'UDT
$smarty_data = "{redirect_page page='home-mobile'}";
$smarty->_compile_source('temporary template', $smarty_data, $_compiled );
@ob_start();
$smarty->_eval('?>' . $_compiled);
$_contents = @ob_get_contents();
@ob_end_clean();
echo $_contents;
}

L'UDT deve essere richiamato subito dopo {process_pagedata}

Moduli consigliati

In questa sezione viene riportata una selezione di moduli e plugin ritenuti dal sottoscritto particolarmente utili

Template Externalizer

Questo modulo, una volta attivato, genera nella cartella temp/externalizer file testuali relativi a tutti i template, i fogli di stile e i moduli del core che usano template (menu e news). Con l’ultima release vengono generati file per tutti i principali moduli che fanno uso di template come ad esempio Gallery.

TIPS: il modulo permette di impostare un tempo di attività superato il quale il modulo viene disattivato. Per disattivare la funzione portare questo valore a 0. Quando è attivo il modulo evitare di modificare i template da backend altrimenti si rischia di perdere le modifiche prodotte successivamente sui file esportati.

Gallery

Un modulo per la creazione di gallerie immagini estremamente flessibile. Le sue principali caratteristiche:

  • Caricamento multiplo delle foto
  • Creazione automatica delle miniature a partire dalle foto caricate
  • Possibilità di gestire gallerie collegate e gerarchiche, per navigrare fra le gallerie è sufficiente impostare la funzione a livello di gallerie e poi utilizzare nel layout della gallery:
    {if !$hideparentlink && !empty($parentlink)}
    <div class="parentlink">{$parentlink}</div>{/if}
    {if $pages > 1}
    <div class="pagelinks">{$pagelinks}</div>
    {/if}
  • Paginazione delle foto, per utilizzare questa funzione è sufficiente impostare un numero massimo di foto per pagina ed utilizzare nel layout della gallery:
    {if $pages > 1}
    <div class="prevpage">{$prevpage}</div>
    <div class="nextpage">{$nextpage}</div>
    {/if}
  • Ogni galleria è associabile ad un modello
  • Ogni galleria ha un titolo, una descrizione e la possibilità di attivare campi custom
  • Ogni immagine ha un titolo, una descrizione e la possibilità di attivare campi custom

Il modulo può essere utilizzato in molti modi, elenchiamone alcuni:

  • creazione di un unica galleria generale collegata a gallerie secondarie

CGSimpleSmarty

Modulo fondamentale per la gestione razionale dei contenuti delle pagine. Attraverso alcuni oggetti smarty e ai loro metodi è possibile accedere in modo semplice ma molto versatile ai contenuti di altre pagine.

Alcuni semplici esempi:

  • Slider immagini intelligente: ogni sezione del vostro sito ha un immagine in testata. Questa immagine è inserita come conten_image. La homepage potrà visualizzare uno slider di immagini prese dalle testate di tutte le sezioni ciclando tutte le sezioni e recuperando i path relativi alle immagini che in questo modo potranno essere stampate in home
  • Riepilogo contenuti di sezione: il vostro sito è suddiviso in un certo numero di sezioni che contengono un certo numero di pagine relative a prodotti o servizi. Con CGSimpleSmarty è possibile creare un box riepilogativo che visualizzi il titolo della pagine, un abstract del suo contenuto, una miniatura e un link alla pagina specifica

CGContentUtils

Questo modulo è un coltellino svizzero vero e proprio: raggruppa al suo interno molte funzioni essenziali.
Nello specifico:

  • Impostazione/esportazione contenuto: è possibile importare ed esportare il contenuto di gruppo di pagine. Nel caso dell'esportazione verrà generato un file XML; nel caso dell'importazione verrà richiesto il file XML precedentemente generato. Questa funzionalit& aggira quella che da sempre è stata una delle principali pecche di questo CMS: la mancanza di funzionalità Batch al pari di altri CMS (come an esempio Joomla).
  • Impostazione/esportazione codice: come per il contenuto è possibile importare ed esportare i template relativi a diversi moduli (ad es. per le news, i form ecc.). Nel caso dell'esportazione verrà generato un file XML; nel caso dell'importazione verrà richiesto il file XML precedentemente generato. Questa funzionalit& può risultare utile per facilitare il riutilizzo di elementi realizzati in progetti precedenti.
  • Blocchi personalizzati: da sola questa funzionalità vale l'installazione del modulo! In buona sostanza è possibile creare blocchi personalizzati al pari di quelli disponibili per il modulo news. Una volta creati e configurati è possibile inserire il codice smarty generato all'interno del template per rendere disponibile il blocco nel template. Fra i blocchi disponibili abbiamo il file selector, per la selezione di file data una cartella (con la possibilità di includere/escludere estensioni specifiche e abilitare la ricorsività delle sotto cartelle), il page selector, per la selezione di una pagina specifica (viene restituito l'id di pagina che può diventare, per esempio, l'input per un selflink) e tutti i classici blocchi disponibili nel modulo news (radio button, input, textarea ecc.)

Content Dump Plug-in

Questo plugin è stato per lungo tempo fra i miei preferiti (sul wiki trovate la guida al suo utilizzo) per la sua semplicità e flessibilità. In sintesi fa le stesse cose del modulo CGSimpleSmarty anche se in modo differente. A volte può essere utile utilizzarlo assieme a CGSimpleSmarty per aggirare i limiti di entrambi.

Ad esempio se vogliamo ciclare tutto il sito tranne alcune pagine possiamo semplicemente scrivere

{content_dump exclude="13,23,53,12,32"}

Oppure se vogliamo "ripulire" il contenuto dei blocchi delle pagine che stiamo ciclando possiamo scrivere

{content_dump html="neutral"}

Oppure se vogliamo visualizzare le ultime 10 pagine inserite

{content_dump limit_count=10 first_sort="created" first_sort_order="down"}
<ul>
{foreach from=$dump item=dump}
<li>{cms_selflink page=`$dump->content->alias` text=`$dump->content->title`}</li>
{/foreach}
</ul>

CGSmartImage

Modulo estremamente duttile per la manipolazione di immagini.
Questa estensione fornisce un modo semplice per elaborare e visualizzare le immagini. Permette di aggiungere watermark alle immagini, creare miniature della dimensione e della qualità desiderata ed altre elaborazioni più avanzate. Il modulo ha anche un sistema di cache per ridurre le risorse impiegate.

Riporto qui di seguito le principali elaborazioni:

  • Blur
  • Brightness
  • Colorize
  • Contrast
  • Crop
  • Crop To Fit
  • Edge Detection
  • Emboss
  • Grayscale
  • Mean Removal
  • Negate
  • Pixelate
  • Resize
  • Rotate
  • Selictive Blur
  • Smooth
  • Watermark

TIPS 1: come ti creo una mini-gallery con miniature automatiche e light-box

{assign var='files' value="uploads/images/nomeCartella/*.jpg'|glob}
{if count($files)}
{foreach from=$files item='file'}
<a rel='gallery' class="fancybox" href="{CGSmartImage src=$file notag=1 noembed=1 filter_resize='h,550'}">
{CGSmartImage src=$file filter_croptofit='59,90'}
</a> {/foreach}
{/if}
{/if}

Vengono ciclate tutte le foto (in formato jpg) di una cartella data. Di ogni foto vengono create le rispettive miniature, mentre le immagini più grandi vengono "normalizzate" ad un altezza di 550px

TIPS 2: come ti creo le miniature per la vista sommario delle news

{assign var='file' value=$entry->file_location|cat:"/"|cat:$entry->immagine}
{if $entry->summary}
<a title="Continua a leggere - {$entry->title}" href="{$entry->moreurl}"> {CGSmartImage src=$file filter_croptofit='165,125' alt=$titolo quality="80"} </a>
{else}
{CGSmartImage class='noLink' src=$file filter_croptofit='165,125' alt=$titolo quality="80"}
{/if}

Assegno alla variabile file il path della foto della news corrente (questo snippet va inserito nel ciclo foreach del vostro template news - sommario).
Se la news ha un sommario (e quindi anche una vista dettaglio) creiamo una miniatura dell'immagine caricata assieme alla news di 165x125px croppando l'immagine se ha proprozioni differenti. In assenza di un sommario verrà generata solamente la miniatura (e verrà applicata la classe noLink al tag img generato).

Form Builder

Il modulo Form Builder consente di creare form di complessità variabile (da semplici form di contatto a quelli a paginazione ecc.), con la funzionalità di archiviazione su database. Se usato assieme a Form Browser , è possibile utilizzarlo per creare semplici applicazioni per la gestione di DB.

I form creati utilizzando il Form Builder possono essere inseriti in modelli e/o pagine. I form possono contenere molte tipologie di campi input; è supportata la convalida lato server dei dati (e la predisposizione della convalida lato client). I risultati delle compilazioni possono essere trattati in vari modi: archiviazione su db, su file testuale, invio a una o più caselle di posta (anche dinamiche).

È possibile creare diverse tipologie di form poi esportabili via XML e importabili in altri progetti

Frontend Users

Questo modulo permette la gestione e l'amministrazione degli utenti front-end (utenti che non hanno accesso al backend). Consente la creazione di gruppi di utenti e utenti; contiene inoltre funzionalità di login e logout (attraverso appositi form richiamabili nel template di pagina).
Può essere utilizzato in combinazione con il modulo CustomContent per visualizzare contenuti diversi a utenti diversi.
Può essere utilizzato in combinazione con il modulo SelfReg per visualizzare contenuti diversi a utenti diversi

Multilanguage CMS

questo modulo permette di gestire con efficacia più lingue con CMSMS e, per quanto mi riguarda, costituisce ad oggi la migliore soluzione in questo senso. Il modulo permette di tradurre praticamente tutti glie elementi di pagina. A questo indirizzo trovate le istruzioni per installare ed utilizzare il modulo.

CGGoogleMaps

Questo modulo permette l'inserimento di macche che utilizzano le API di Google in modo semplice e veloce. A parte l'inserimento semplice permette di sfruttare alcune funzionalità extra come la visualizzazione di più punti di interesse sulla mappa, la personalizzazione dei tooltip e l'ottimizzazione per la visualizzazione delle mappe su dispositivi mobili.

Il modulo mette a disposizione una serie di icone predefinite da utilizzare come segnaposto oltre alla possibilità di caricarne di nuove.

Bibliografia

Come si installa un modulo?

Un modulo può essere installato in più modi in base alle necessità

Come si installa un plugin o TAG?

Un plugin si installa semplicemente caricando via FTP o via SSH il file (generalmente è composto da un singolo file o comunque pochi file) nella cartella plugin.
Non esiste una procedura di installazione vera e propria. Una volta caricato il file il TAG sarà disponibile alla voce estensioni > TAG