Propósito de esta sesión
En esta sesión veremos las principales características de Typoscript, su alcance y su interacción con TYPO3 y algunos ejemplos tanto genéricos a modo introductorio, como reales utilizados en esta nueva versión del Sitio Corporativo del BCIE.
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/
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.
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 = ¶meter=value
En este ejemplo, a la propiedad additionalParams se le asignará como parámetro el valor "¶meter=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]
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]
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
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 } }
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]