PortLAB
PortLAB es la plataforma con la que, en el CNR-IFAC (Instituto de Física Aplicada «Nello Carrara»), se desarrollan y se gestionan portales científicos: un único motor, escrito en PHP con base de datos PostgreSQL, del que nacen sitios distintos — multilingües, adaptativos y ricos en contenidos interactivos — compartiendo estructura, estilo y herramientas.
Qué es
PortLAB es un framework ligero para la construcción de portales. Cada página se define mediante una pequeña configuración declarativa (en formato JSON) que establece su estructura, sus idiomas, sus bibliotecas y sus niveles de acceso, mientras que los contenidos viven en ficheros separados por idioma. Esto permite añadir páginas y sitios enteros con rapidez, manteniendo la coherencia gráfica y funcional y sin necesidad de tocar el motor.
Arquitectura por proyectos y personalización
PortLAB se organiza en torno a un sitio principal que hace de base compartida para todos los proyectos secundarios alojados en la plataforma. Cada proyecto dispone de sus propios contenidos y de sus propias personalizaciones locales, pero hereda automáticamente del sitio principal tanto el código común como las bibliotecas de terceros, compartidas una sola vez y mantenidas de forma centralizada: sin duplicación y con actualizaciones inmediatas para todos. Al mismo tiempo, cada proyecto puede personalizar cualquier elemento en cualquier punto, sustituyendo de forma selectiva e independiente la versión compartida por una versión local propia. El resultado es una arquitectura por capas — elementos locales, comunes y bibliotecas compartidas, libremente combinables — que permite poner en marcha nuevos portales con rapidez manteniendo para cada uno una identidad y un aspecto a medida.
Además del código común y de las bibliotecas, también los servicios y las herramientas que ofrece PortLAB (gestión y visualización de la base de datos, diagrama del esquema, gestión de usuarios, consulta de los registros y demás) pueden heredarse en los proyectos secundarios mediante enlaces simbólicos al proyecto principal: cada nuevo portal dispone así de todo el instrumental sin duplicación, pudiendo en cualquier caso sustituir o ampliar localmente cualquiera de sus partes.
Interfaz gráfica (GUI)
La interfaz se compone de elementos estándar basados en Bootstrap — cabeceras, barras de navegación, menús, migas de pan, pies de página y ventanas modales: piezas independientes y reutilizables que se combinan hasta obtener la estructura de página deseada, con coherencia visual y plena adaptabilidad.
Plantillas
La plantilla es el modelo de página: establece qué elementos de interfaz utilizar y cómo maquetarlos, incluido el tipo de menú (horizontal arriba o lateral) y el estilo general. Cada plantilla es una combinación predefinida y reutilizable de componentes, invocada por una página con una simple referencia; al cambiar de plantilla cambian el aspecto y la disposición de toda la página sin tocar sus contenidos.
Descriptor de página
Cada página se declara mediante un pequeño fichero JSON, y la declaración no es un trámite: sin ese fichero la página no existe para la plataforma y su dirección responde «no encontrada». Es el primer eslabón del control de acceso. El descriptor indica qué plantilla usar, quién puede abrir la página, qué cargar y en qué orden, y cómo se presenta la página en el menú.
{
"template": 1,
"profiles": [1],
"flags": { "menu_order": 3 },
"libs": {
"css": ["/css/common/table.css", "/css/local/diagram.css"],
"js": ["/js/libs/jquery-4.0.0.min.js"],
"js_end": ["/js/local/diagram_ui.js"]
}
}
- template — el modelo de página descrito más arriba.
- profiles — los perfiles autorizados. La lista vacía significa página pública, no página inaccesible: es la única apertura, y hay que escribirla a propósito.
- libs — hojas de estilo y scripts en el orden exacto en que deben cargarse, con js antes del cuerpo de la página y js_end después.
- flags.hide_in_menu — la página sigue siendo accesible por dirección pero no aparece en el menú.
- flags.menu_order — el lugar de la página entre los ficheros de su carpeta: número creciente y, a igualdad o en ausencia de número, orden por nombre. El nombre deshace siempre el empate, de modo que un número equivocado desplaza una entrada y no reordena la sección. Sirve para mantener el orden fuera de los nombres de los ficheros, que son también direcciones.
Todo lo demás no es configuración sino ficheros reconocidos por el nombre: el cuerpo de la página, uno por idioma; un diccionario para las cadenas de la interfaz Javascript; y, si hace falta, un fichero de lógica en el servidor. Añadir una página significa por tanto crear ficheros, no modificar un registro central — y es la razón por la que el menú, las migas de pan y el motor de búsqueda la encuentran solos.
Usuarios, accesos y navegación
Gestión de usuarios multiperfil
A cada usuario se le pueden asociar varios perfiles de autorización. Un recurso es accesible cuando al menos uno de los perfiles del usuario coincide con uno de los perfiles exigidos por el recurso; las páginas sin perfiles siguen siendo públicas. El mismo criterio gobierna de manera uniforme el acceso a páginas y secciones, las entradas de menú, los ficheros descargables e incluso la visibilidad de porciones concretas de una página: así, una misma página puede mostrar contenidos distintos a usuarios con perfiles distintos.
Área reservada
Las páginas públicas están netamente separadas del código de la aplicación y de los contenidos reservados, custodiados en un área situada fuera de la raíz web y, por tanto, inalcanzable directamente desde el navegador. Los documentos reservados nunca se exponen como URL estáticas: se entregan exclusivamente mediante procedimientos del servidor que, antes del envío, comprueban la identidad y los perfiles del usuario.
Seguridad y cifrado
Las defensas son transversales: sesiones protegidas con testigo anti-CSRF, regeneración del identificador de sesión y cookies con atributos de seguridad (HttpOnly, Secure, SameSite); contraseñas custodiadas solo como hash; parámetros de las consultas validados y acotados. Los contenidos reservados y los enlaces «de capacidad» están protegidos con cifrado estándar (AES-256 con autenticación HMAC) y claves mantenidas fuera del código fuente. El control de acceso es fail-closed: una página es accesible solo si está configurada explícitamente, y también los puntos de cálculo en el servidor están sujetos a los perfiles del usuario. Las peticiones a recursos inexistentes se reconducen a páginas de error estándar que devuelven al inicio.
Generación dinámica de los menús de navegación
El menú no se escribe a mano: se construye automáticamente explorando el árbol de carpetas y páginas. Cada página nueva aparece sola, organizada en varios niveles según el anidamiento; las entradas se filtran según el perfil del usuario y una marca de exclusión específica, y los títulos se toman de la página en el idioma elegido. El orden pone primero los ficheros y después las subcarpetas; entre los ficheros vale el número declarado en el descriptor de la página y, a igualdad — o en su ausencia —, el nombre. Una sección se reordena así cambiando un número, sin renombrar ficheros ni mover direcciones.
Contenidos, búsqueda y privacidad
Soporte multilingüe
Los idiomas disponibles se declaran página por página. El cuerpo de cada página reside en un fichero separado para cada idioma, mientras que las cadenas de la interfaz se gestionan mediante un sistema de traducción por diccionarios que funciona de manera idéntica en PHP y en Javascript: la misma función y los mismos diccionarios están disponibles tanto en el servidor como en el navegador. Así es posible traducir al vuelo cualquier cadena, procedente de cualquier sección de la página — incluidas las producidas por programas en Python o C++ ejecutados a través de la pasarela (gw2py) y devueltas a la página.
Se dispone además de una extensión para las cadenas paramétricas: el texto
traducido contiene marcadores numerados (p. ej. {0}, {1})
sustituidos en tiempo de ejecución por los valores reales. Es un detalle esencial,
porque en idiomas distintos el parámetro puede ocupar una posición distinta
dentro de la frase: el marcador se coloca donde hace falta en cada traducción, de modo
que el texto sigue siendo natural (por ejemplo «{0} elementi trovati» en
italiano pasa a ser «found {0} items» en inglés, con el valor en lugares
distintos). Toda la cadena de tratamiento está en UTF-8, por lo que admite cualquier
alfabeto; actualmente los portales están en italiano, inglés y español, con un
selector de idioma con bandera y sigla.
Búsqueda textual interna
Al teclear al menos tres caracteres, el sistema examina las páginas del sitio en el idioma seleccionado en ese momento y muestra los resultados en una ventana dedicada. De cada página se presenta un extracto con título, palabras clave, descripción y texto en el que aparece el término buscado, resaltado en su contexto, con enlace directo a la página. La búsqueda trata correctamente los alfabetos y los caracteres internacionales (UTF-8) y puede dirigirse, página por página, solo a los párrafos relevantes.
Gestión del RGPD
PortLAB incluye una gestión del RGPD lista para usar: una política de privacidad y cookies específica y un aviso de consentimiento reutilizable por todos los sitios. La plataforma está preparada para el uso de solo cookies técnicas, sin perfilado ni terceros; el aviso es puramente informativo, no bloquea la navegación y recuerda que se ha leído durante un periodo preestablecido.
Herramientas para la base de datos (PostgreSQL)
Gestión de las tablas
Una única interfaz reutilizable permite crear, modificar, eliminar y consultar las filas de las tablas de la base de datos, con herramientas de filtrado multicriterio, ordenación personalizable, paginación e importación/exportación de los criterios en formato JSON.
Visualización y exploración de los datos
Un visualizador completo de la base de datos reúne cuatro herramientas: un navegador que explora bases de datos, esquemas, tablas, vistas, vistas materializadas y funciones mediante un árbol interactivo y filtros en cascada (mostrando estructura, tipos, claves, tamaños y definiciones); un ejecutor de consultas SQL con editor avanzado, ejecución directa y exportación de los resultados en CSV; una biblioteca de consultas guardadas invocables con un clic; y una búsqueda por palabras clave en todos los campos, con filtros por esquema, tabla, campo y tipo de dato.
Diagrama gráfico del esquema
Un visualizador gráfico genera un diagrama interactivo del esquema: cada tabla o vista es un nodo con la lista de los campos y la clave primaria resaltada. Los nodos se arrastran libremente por el plano de trabajo y los enlaces entre los campos relacionados se trazan como líneas; disposición, colores y enlaces se guardan y se restauran en cada acceso.
Administración y diagnóstico
Consulta de los registros del servidor
Una consola de administración permite consultar los registros de Apache — accesos y errores — filtrando las líneas por inclusión o exclusión de una cadena, con la posibilidad de ocultar los mensajes informativos o de vaciar el registro; una sección específica muestra la configuración PHP del servidor. El acceso está reservado a los administradores.
Mensajes de error normalizados
Cada punto crítico del código — consultas SQL, operaciones PHP, llamadas a la pasarela Python, scripts en el cliente — está marcado con un código/índice: cuando algo va mal aparece un mensaje uniforme que indica ese código, lo que permite remontarse al punto exacto en que se ha producido el problema. Los mensajes están diferenciados por perfil: el usuario ve un aviso esencial con el código, mientras que al administrador se le muestran además los detalles técnicos (tipo, fichero, línea, texto de la consulta) útiles para la depuración. El mecanismo es uniforme para las páginas y para las llamadas AJAX.
Tecnologías
El núcleo del funcionamiento en el servidor es una pasarela que permite a las páginas invocar, de manera uniforme, programas y procesos escritos en lenguajes distintos — hasta ahora Python y C++ — devolviendo sus resultados (por lo general en formato JSON) directamente en la página. La pasarela se usa de forma generalizada junto con la interfaz AJAX de jQuery: esto ha normalizado de hecho las llamadas en todo el portal, con un único esquema petición/respuesta para cualquier operación dinámica.
- Motor en PHP sobre Apache/Linux, base de datos PostgreSQL; front-end sobre Bootstrap 5 y jQuery.
- Páginas configuradas de forma declarativa (JSON): plantilla, metadatos, bibliotecas y perfiles de acceso, sin modificar el motor.
- Componentes reutilizables y cálculo en el servidor mediante una pasarela Python: las páginas pueden lanzar simulaciones y procesos y mostrar sus resultados.
- Contenidos científicos interactivos: gráficos (ECharts), fórmulas en LaTeX (KaTeX), visualizaciones 3D (three.js), código con resaltado de sintaxis.
- Asistente para poner en marcha nuevos portales; diseño adaptativo para escritorio y móvil.
Proyectos realizados con PortLAB
- WebNIR — portal del CNR-IFAC sobre las radiaciones no ionizantes: campos electromagnéticos (CEM), radiaciones ópticas artificiales (ROA) y dispositivos médicos implantables activos, con herramientas para la evaluación de la exposición y del apantallamiento.
- UISH — Urban Intelligence Science Hub — proyecto del CNR para el gemelo digital de la ciudad: la actividad del CNR-IFAC sobre la calidad del aire en Catania y la validación del modelo AirPortal.
- Purple — portal dedicado a los métodos analíticos y al archivo de las actividades y las mediciones ambientales.
- Consola de administración — la interfaz de gestión de la propia plataforma, que alberga también una sección didáctica con ejemplos interactivos (la suite Quantum Monte Carlo para la ecuación de Schrödinger y el teorema de Pitágoras).
Keywords: PortLAB, CMS, framework PHP, portales científicos, multilingüe, PostgreSQL, CNR-IFAC