El Lenguaje Typoscript

Técnicamente, Typoscript es un lenguaje de configuración. No se puede programar con el, si no que puede configurar un sitio web TYPO3 de una forma exhaustiva. Con Typoscript se define la representación visual del sitio, incluida la navegación, contenido genérico, y como elementos de contenido individuales son desplegados en una página.

En TYPO3 el contenido y el diseño tienen una clara separación. Typoscript es el pegamento que los une, lee el contenido almacenado en la Base de datos, lo prepara y lo despliega en el Frontend.

Para representar una página, solo requerimos definir qué contenido desplegar y cómo visualizarlo.

  • El qué lo controla el Backend.
  • El cómo lo controla Typoscript.

Una característica destacable de TYPO3, pero algo insólita para un CMS, consiste en que permite introducir el contenido para la interfaz de usuario utilizando un lenguaje de configuración denominado TypoScript, algo que puede convertirse en una ardua tarea especialmente para los más inexpertos. 

https://www.ionos.es/digitalguide/hosting/cms/typo3-un-cms-de-grandes-prestaciones/ 

To top

Conceptos básicos

Plantillas

El código Typoscript utilizado para indicar como visualizar las páginas se encuentra en la plantilla principal. Esta plantilla se distingue por tener la bandera rootlevel marcada. 

Cuando se visualiza una página, TYPO3 busca por el árbol de páginas (de abajo hacia arriba) hasta encontrar la plantilla principal correspondiente a dicha página. También es posible, y normal; que hayan plantillas adicionales, que se irán combinando con la plantilla principal para obtener configuraciones mas específicas según se vaya profundizando en el árbol de páginas.

No deben confundirse estas plantillas Typoscript, con las plantillas HTML que sirven de base para el diseño del sitio web.

Si no se encuentra una plantilla principal, aunque existan otras plantillas en el árbol de páginas, TYPO3 desplegará el mensaje "No Typoscript template found".

Typoscript es, finalmente, un arreglo

Internamente, Typoscript es parseado y almacenado como un arreglo PHP. Por ejemplo el código 

page = PAGE
page.10 = TEXT
page.10.value = ¡Hola mundo!
page.10.stdWrap.wrap = <h2>|</h2>

sería convertido en 

$data['page'] = 'PAGE';
$data['page.']['10'] = 'TEXT';
$data['page.']['10.']['value'] = '¡Hola Mundo!';
$data['page.']['10.']['stdWrap.']['wrap'] = '<h2>|</h2>';

En la etapa de evaluación, se creará un objeto PAGE y se le pasará $data['page.'] como parámetro. El objeto PAGE buscará las propiedades que conoce. En este caso encontrará una entrada numérica ("10") que deberá ser evaluada. Un nuevo objeto de tipo TEXT es creado con el parámetro $data['page.']['10.']. El objeto TEXT conoce los parámetros value y stdWrap, así que asignará contenido de value de forma adecuada. Los parámetros de stdWrap serán pasados a la funcion "stdWrap", ahí la propiedad wrap es conocida y el texto "¡Hola Mundo!" será insertado en la posición de la barra vertical o pipe (|) y el resultado será retornado.

Es importante conocer esta relación para entender el comportamiento de Typoscript. Por ejemplo, si al anterior código se le agrega la siguiente línea:

page.10.miFuncion = ¡Buenas tardes!

La misma será convertida en 

$data['page.']['10.']['miFuncion'] = '¡Buenas tardes!';

Sin embargo, el objeto TEXT no conoce ninguna propiedad llamada "miFuncion", de tal manera que dicha entrada no tendrá ningún efecto.

¡IMPORTANTE! No se hace revisión de errores. Si se definen objetos o propiedades que no existen, no se desplegará ningún mensaje de error. En su lugar dichas líneas no hacen nada. Esto debe ser considerado a la hora de hacer diagnóstico de problemas.

To top

Sintaxis

La sintaxis de Typoscript es muy sencilla, a la izquierda se definen los objetos y propiedades y a la derecha los valores asignados. Tanto objetos como propiedades pueden contener otros objetos. Las propiedades son definidas utilizando la notación del punto "."

Por ejemplo

page = PAGE
page.10 = TEXT
page.10.value = ¡Hola Mundo!
page.10.stdWrap.wrap = <h2>|</h2>

Delimitadores

Normalmente cada línea Typoscript está delimitada por el cambio de línea, sin embargo hay situaciones en que se requiere trabajar con multiples líneas.

Agrupar "{...}"

Para facilitar la legibilidad del Typoscript y reducir errores, se pueden agrupar objetos y/o propiedades con las llaves. Es necesario que la llave de apertura "{" esté en la misma línea de la ruta común. El código de ejemplo anterior se puede escribir así:

page{
    10 = TEXT
    10{
        value = ¡Hola Mundo! 
        stdWrap.wrap = <h2>|</h2>
    }
}

Texto multi-línea "(...)"

Se utiliza para asignar un valor con varias líneas de texto. Por ejemplo:

page{
    10 = TEXT
    10{
        value = ( ¡Hola Mundo! 
        Este es un texto
        multi-linea.
        )
        stdWrap.wrap = <p>|</p>
    }
}

 

Operadores

 

Asignación "="

Como se ha visto en los ejemplos anteriores, el operador de asignación separa los objetos y propiedades de los valores, será tomado en cuenta como operador, la primera ocurrencia (de izquierda a derecha) en la línea del símbolo "=", por ejemplo

page.10.stdWrap.typolink.additionalParams = &parameter=value

En este ejemplo, a la propiedad additionalParams se le asignará como parámetro el valor "&parameter=value"

Copiado "<"

Este operador permite copiar una porción de Typoscript de un objeto o propiedad a otro, por ejemplo

prueba = TEXT
prueba.value = Acerca del BCIE
...
page.10 < prueba

en page.10 se copió el objeto prueba, y en vez de "¡Hola Mundo!", se desplegará "Acerca del BCIE"

esto es particularmente útil cuando ya se tiene un conjunto de Typoscript base de una solución para la cual luego solo se ocupará cambiar algunos detalles, por ejemplo, este código tomado del nuevo Sitio Corporativo del BCIE

lib.feuserGroups1 = CONTENT
lib.feuserGroups1 {
    table = fe_groups
    select {
        pidInList = 506
    }
    renderObj = COA
    renderObj {
       10=TEXT
       10.field = title
       10.wrap = <div class="form-check form-check-inline"><input class="form-check-input usergroup-value" type="checkbox" id="inlineCheckbox{field:uid}" value="{field:uid}"><label class="form-check-label" for="inlineCheckbox{field:uid}">|</label></div>
       10.insertData=1
    }  
}

lib.feuserGroups2 < lib.feuserGroups1
lib.feuserGroups2.select.pidInList = 508

lib.feuserGroups3 < lib.feuserGroups1
lib.feuserGroups3.select.pidInList = 507

lib.feuserGroups4 < lib.feuserGroups1
lib.feuserGroups4.select.pidInList = 509

Borrado o Truncado ">"

Cuando por el contrario al caso anterior, se quiere iniciar desde 0 y no "arrastrar" algun Typoscript no deseado o desconocido, se utiliza el operador de descarte.

El código del inicio de esta página produce un resultado similar a

¡Hola Mundo!

si mas adelante en el código se agrega la siguiente línea

page.10.value = Acerca del BCIE

la configuración de stdWrap se mantiene y el texto generado seguirá modificado por la etiqueta h2, produciendo algo como 

Acerca del BCIE

Si se quiere quitar la modificación de la etiqueta h2 hay 2 opciones

page.10.stdWrap.wrap >

que da como resultado

Acerca del BCIE

o bien 

page.10 >

en cuyo caso habría que reescribir el objeto

page.10 = TEXT
page.10.value = Acerca del BCIE
page.10.stdWrap.wrap = <b>|</b>

y este daría como resultado

Acerca del BCIE

Comentarios "#"

Para agregar comentarios en medio del Typoscript, se utiliza el símbolo numeral o almohadilla "#"

page = PAGE
page.10 = TEXT
page.10.value = ¡Hola Mundo!
#Modificado el 15/02/2020 por GALILEO, antes page.10.stdWrap.wrap = <h1>|</h1>
page.10.stdWrap.wrap = <h2>|</h2>

Condicionales 

Se puede ejecutar un Typoscript solo bajo ciertos parámetros, como el identificador de la página (o si la págin pertenece a una rama del árbol de páginas), el idioma o la presencia de un plugin en particular. La condición se debe poner entre corchetes.

[siteLanguage("languageId") == "1"]
    lib.feuserGroups1.renderObj.10.field= description
[end]

 

To top

Configuración del CMS

Se puede administrar parte de la configuración del CMS con Typoscript, por ejemplo:

# Localization:
config {
        linkVars = L(int)
        sys_language_uid = 0
        sys_language_overlay = 1
        sys_language_mode = content_fallback;1,0
        language = es
        locale_all = es_ES.UTF-8
        htmlTag_setParams = lang="es" dir="ltr" class="no-js"
}
[siteLanguage("languageId") == "1"]
        config {
        sys_language_uid = 1
        language = en
        locale_all = en_US.UTF-8
        htmlTag_setParams = lang="en" dir="ltr" class="no-js"      
        }
[end]

To top

Userfunc

Algunas veces es necesario hacer algún procesamiento de datos que excede el alcance de Typoscript, o se hace muy complicado de crear con este y darle mantenimiento, por lo que se recurre a llamadas a funciones en PHP

#Build a JSON
JSON = PAGE
JSON {
 # ...
  10 = USER
  10 {
    userFunc = Galileocr\BciePackage\ViewHelpers\ExportJson->fetchData
    userFunc {
        selectedTable=tx_news_domain_model_news
        selectedFields=uid,title,teaser, categories
        selectedPid=342
    }
  }  
}

y en el PHP

public function fetchData ($content = '', $conf = array()) {

        global $TSFE;
        $local_cObj = $TSFE->cObj; // cObject
        $conf = $conf['userFunc.']; // ts config

        $selectedTable = $conf['selectedTable'];
        $selectedPid = $conf['selectedPid'];
        $selectedFields = $conf['selectedFields'];
        //... procesamiento PHP

To top

Configuración de extensiones

Se puede manipular una parte de la configuración de las extensiones.

plugin.tx_solr.settings.xlfPath = LLL:EXT:bcie_package/Resources/Extensions/Solr/Resources/Private/Language/locallang.xlf

Otros ejemplos

plugin.tx_indexedsearch.settings.displayAdvancedSearchLink = 0
plugin.tx_indexedsearch.settings.displayRules = 0
plugin.tx_indexedsearch.settings.displayLevel1Sections = 0
plugin.tx_news {
    settings {
        listPid = 344
        detailPid = 345
        list.media.image.maxHeight = 500.c
        list.media.image.maxWidth = 500
        list.mediaRelated.image.maxWidth = 300.c    
        list.mediaRelated.image.maxHeight = 150
        detail.media.image.height = 500
        detail.media.image.width = 500
        detail.showSocialShareButtons = 1
        detail.media.image.maxWidth = 800.c
        detail.media.image.maxHeight = 600    
        detail.showPrevNext = 0
        detail.showMetaTags = 1
    }
}

To top

Ejemplos actuales

Creación de tipos de registro para Adquisiciones

#News custom resources stored in BCIE_package
config.tx_extbase.persistence.classes {
    GeorgRinger\News\Domain\Model\News {
        subclasses {
            3 = Galileocr\BciePackage\Domain\Model\Agreement
            4 = Galileocr\BciePackage\Domain\Model\Notice
            5 = Galileocr\BciePackage\Domain\Model\Plan
        }
    }

    Galileocr\BciePackage\Domain\Model\Agreement {
        mapping {
            recordType = 3
            tableName = tx_news_domain_model_news
        }
    }

    Galileocr\BciePackage\Domain\Model\Notice {
        mapping {
            recordType = 4
            tableName = tx_news_domain_model_news
        }
    }
    Galileocr\BciePackage\Domain\Model\Plan {
            mapping {
                recordType = 5
                tableName = tx_news_domain_model_news
            }
    }
}

Elementos de contenido "repetidos"

###Repeated element: searchbox
lib.searchBoxRepeated= CONTENT
lib.searchBoxRepeated {
  table = tt_content
  select {
    pidInList = 202
    where = uid= 588
  }
}
###Repeated element: newsletter subscription
lib.subscribeNewsletter = CONTENT
lib.subscribeNewsletter {
  table = tt_content
  select {
    pidInList = 450
    where = uid= 438
  }
}

Obtener los países para el formulario de suscripción 

lib.countryOrigin = CONTENT
lib.countryOrigin {
    table = fe_groups
    select {
        pidInList = 508,511
        where = fe_groups.uid != 10 
    }
    renderObj = COA
    renderObj {
       10=TEXT
       10.field = title
       10.wrap = <option value="{field:title}">|</option>
       10.insertData=1
    }  
}
[siteLanguage("languageId") == "1"]
    lib.countryOrigin.renderObj.10.field= description
[end]

To top