Portal web de ayuntamiento
Full text
UNIVERSIDAD POLITÉCNICA DE VALENCIA Escuela técnica superior de informática aplicada Autor: Daniel Alcalá Alcocer Director: Félix Buendía García
A mi madre, que ostenta el máximo tiempo (varios años a decir verdad) persistiendo en su afán por que que concluyera este proyecto. A mi esposa, más persistente que la anterior si cabe, consiguiendo lo mismo en menor tiempo. A mi padre, por defenderme de las 2 primeras, aunque tuvo que recurrir a su gran elocuencia cuando comprobó que el proyecto se demoraba in extremis . A mi hermana, por resultar la más democrática y darme la calma, al saber hacerme ver a su manera, que por muchos años que pasaran, este día al fin llegaría. A la Universidad Politécnica de Valencia, y en especial a la Escuela Técnica Superior de Ingeniería Informática, por la trepidante juventud que allí pasé y los grandes recuerdos que me han dejado. 2
1. INTRODUCCIÓN............................................................................................................5 1.1. Propósito y objetivos...................................................................................................5 1.2. Motivaciones................................................................................................................6 1.3. Estructura.......................................................................................................................7 2. ESPECIFICACIÓN DE REQUISITOS.................................................................................9 2.1. Introducción.................................................................................................................9 2.1.1. Propósito................................................................................................................9 2.1.2. Ámbito.................................................................................................................10 2.1.3. Definiciones, acrónimos y abreviaturas.........................................................10 2.1.4. Referencias.........................................................................................................14 2.1.5. Visión global........................................................................................................15 2.2. Descripción general..................................................................................................15 2.2.1. Perspectiva del producto................................................................................15 2.2.2. Funciones del producto....................................................................................16 2.2.3. Características del usuario...............................................................................18 2.2.4. Restricciones generales....................................................................................20 2.2.5. Supuestos y dependencias..............................................................................20 2.3. Requisitos específicos...............................................................................................21 2.3.1. Requisitos de interfaces externos....................................................................21 2.3.2. Requisitos funcionales.......................................................................................23 2.3.3. Atributos...............................................................................................................49 3. ANÁLISIS......................................................................................................................51 3.1. Introducción...............................................................................................................51 3.2. Casos de uso..............................................................................................................52 3.3. Diagramas de clases................................................................................................59 3.4. Diagramas de secuencia........................................................................................62 3.4.1. Escenario 1: Autenticarse.................................................................................63 3.4.2. Escenario 2: Buscar trámites.............................................................................64 3.4.3. Escenario 3: Crear un nuevo usuario..............................................................65 3.4.4. Escenario 4: Eliminar un trámite.......................................................................65 3.4.5. Escenario 5: Recuperar contraseña olvidada..............................................68 4. DISEÑO.........................................................................................................................69 4.1. Introducción...............................................................................................................69 4.2. Nivel de interfaz.........................................................................................................71 3
4.3. Nivel de negocio.......................................................................................................73 4.4. Nivel de almacenamiento.......................................................................................76 4.4.1. Diagrama Entidad-Relación............................................................................76 4.4.2. Diseño lógico......................................................................................................79 5. IMPLEMENTACIÓN.......................................................................................................83 5.1. Introducción...............................................................................................................83 5.2. Tecnologías.................................................................................................................85 5.2.1. HTML.....................................................................................................................85 5.2.2. CSS........................................................................................................................86 5.2.3. PHP........................................................................................................................91 5.2.4. JavaScript............................................................................................................92 5.2.5. MySQL..................................................................................................................94 5.3. Herramientas..............................................................................................................95 5.3.1. Apache................................................................................................................95 5.3.2. Komodo Edit.......................................................................................................96 5.3.3. Adobe Photoshop.............................................................................................97 5.3.4. FileZilla..................................................................................................................99 5.4. Detalles de implementación.................................................................................101 5.4.1. Implementación del interfaz.........................................................................101 5.4.2. Implementación de la funcionalidad..........................................................115 5.4.3. Implementación de la gestión de datos....................................................165 6. EVALUACIÓN Y PRUEBAS..........................................................................................171 7. CONCLUSIONES........................................................................................................179 8. BIBLIOGRAFÍA............................................................................................................181 4
En los tiempos que corren, es posible afirmar sin temor a equivocación que en Internet, quien no está, no existe. Y es que cada vez son menos los reticentes a cuestionar tal pensamiento. Si bien constituye una afirmación que puede escucharse con gran rotundidad en un entorno empresarial o de negocio, hoy día resulta también factible aplicarla en una amplia variedad de contextos, como el que ahora nos ocupa, el de un Ayuntamiento. Sería especialmente de lamentar, no aprovechar todas las posibilidades que Internet brinda para aproximar Ayuntamiento y ciudadanos: mirar, participar, gestionar, resolver, expresar o compartir, son sólo algunas de las principales motivaciones que miles de usuarios encuentran a diario. En esta primera década del siglo XXI, la creación o renovación de un portal web para un ayuntamiento propicia un escenario privilegiado de comunicación, un transitado lugar de encuentro para ciudadanos, donde el ayuntamiento sale reforzado como principal protagonista, al servicio de los mismos. Lo contrario sería rechazar la evolución, significaría en resumidas cuentas, lo que esbozaba la frase que abría esta breve introducción: dejar de tener relevancia, caer en el olvido, dejar de existir. El presente documento pretende poner de manifiesto las diferentes etapas que comportan el desarrollo y creación de un portal web para un ayuntamiento, sirviendo el mismo como memoria de un Proyecto de Final de Carrera. 5
A groso modo, se pretenden cubrir los siguientes objetivos principales: –El portal deberá adaptarse a los hábitos de utilización de cada usuario, por lo que la programación deberá ser eminentemente dinámica, posibilidad que brinda la tecnología PHP. En este sentido, deben mostrarse de forma privilegiada aquellos elementos más utilizados por cada usuario, en detrimento de otros por los que el mismo muestre menor interés. –El portal web deberá resultar intuitivo y potente, ofreciendo al usuario la información que busca de forma coherente y en el menor tiempo posible. –Deberá brindar servicios diferenciados en virtud del rol del usuario. Distinguirá por tanto varios niveles de perfiles de usuario. –Tratará de forma permanente de “cautivar” al usuario no registrado (Anónimo), ofreciendo los elementos persuasivos necesarios para que el mismo tome la iniciativa de registrarse y pasar a formar parte de la comunidad de usuarios. En este sentido, se limitará al máximo el acceso a la diversas secciones del portal, si bien se le restringirá su participación (una frase que sintetiza bien la estrategia a serguir sería “podrá ver pero no tocar”, para eso tendría que registrarse) –El portal deberá presentar un carácter marcadamente interactivo. De este modo, deben aparecer apartados de esta índole, por ejemplo: foros de discusión o bien gestión de trámites. Entre los diversos factores que han podido influenciarme en la decisión de afrontar un proyecto de la envergadura del que nos ocupa, los englobaría en 2 bloques principales: aquellos orientados a colaborar en mi desarrollo personal por un lado, y los que propician una formación óptima para el desarrollo profesional por el otro. 6
De este modo, conseguiría cubrir una parte de mis inquietudes personales, esto es, hacer servir Internet para dar a conocer y compartir mi afición por la composición musical, alcanzando el nivel de dominio necesario sobre las tecnologías actuales en programación y diseño web. Tal dominio llegaría casi de forma natural, fruto del esfuerzo y rigurosidad que impone el desarrollo de un proyecto final de carrera como el que nos ocupa, es decir, la creación de un portal web de ayuntamiento, el cual supone un marco incomparable para poder involucrar una amplia variedad de recursos tecnológicos tanto de programación como de diseño web. Finalmente, lograría asimilar por otro lado, los conocimientos técnicos necesarios que me permitirían desarrollar una profesión cuya presencia en casi todos los sectores, durante esta primera década de siglo, ha ido “in crecendo” y que cada día que transcurre, continua consolidándose y convergiendo hacia una profesión de gran interés y demanda. El presente documento está constituido por una serie de capítulos, siguiendo un enfoque basado en el modelo de “cadena de valor”, esto es, una serie consecutiva de actividades o etapas que progresivamente van adicionando un valor al proyecto. De esta forma, la primera etapa, ya abordada, ha sido la propuesta del proyecto, donde se han definido las motivaciones y los objetivos. La siguiente etapa consiste en la Especificación de requisitos, que no es mas que una descripción de las necesidades del proyecto, atendiendo a las opiniones conseguidas por parte de los usuarios finales. Posteriormente aparecerá la etapa de Análisis y Diseño donde serán descritos nuevamente los requisitos anteriores pero desde una perspectiva más cercana al desarrollador de la aplicación web, estableciéndose aquí una primera toma de contacto con los modelos formales para su representación. 7
La etapa de Implementación recoge las diversas tecnologías recurridas con el objetivo de obtener una primera fase de productos o prototipos funcionales. Es posible reutilizar en este apartado, aquellas aplicaciones de terceros a las que se hayan recurrido. Posteriormente es posible encontrar la etapa de Evaluación. Es en esta etapa donde la aplicación web será sometida a una batería de pruebas para testear a fondo que la aplicación discurra según lo previsto, en cualquiera de sus vertientes posibles. Finalmente el documento concluye con la etapa de Conclusiones, donde se documenta el trabajo realizado durante todo el desarrollo del proyecto, los resultados alcanzados así como una breve argumentación de las experiencias contraídas. Por último, esta etapa contempla la inclusión de posibles ampliaciones realizables en un futuro. Es preciso asimismo documentar las principales fuentes de información en un apartado de Bibliografía. Deben referenciarse todas las fuentes o materiales consultados durante el desarrollo del proyecto, ya sean libros, apuntes o páginas Web. 8
La Especificación de requisitos debe recoger todas aquellas características a cumplir por nuestra aplicación para satisfacer las expectativas o exigencias del Ayuntamiento, en el caso que nos ocupa, así como de los usuarios finales. La descripción de los requisitos debe realizarse tratando de conservar una perspectiva cercana al usuario final, evitando términos o tecnicismos que habitualmente emplearía un desarrollador. Con este fin, se emplea habitualmente un documento que reúne de forma ordenada estos requisitos y que se conoce como Especificación de Requisitos Software (ERS), el cual puede tener diferentes formatos. En el proyecto que nos ocupa, se ha optado por organizar los requisitos capturados empleando una ERS en base al estándar IEEE 830-1998, el cual puede ser utilizado como referencia en la especificación de proyectos Web, dadas las analogías existentes con la metodología de proyectos software. Esta decisión está orientada en favor no sólo de estructurar los requisitos definidos previamente, sino también en pro de obtener una especificación consistente y no ambigua. Esta especificación de requisitos representa una parte vital dentro de la memoria, pues el desarrollo de apartados posteriores deberán cumplir y satisfacer las exigencias de cada uno de estos requerimientos de partida. 9
Las tecnologías principales empleadas en su implementación han sido: –Lenguaje PHP, en gran medida, dado el carácter eminentemente dinámico. –Lenguaje HTML, en menor medida. –Plantillas CSS para optimizar la legibilidad de la información mostrada, así como para propiciar un diseño actual, acorde a las últimas tendencias. –JavaScript de forma puntual, para moldear la forma en que mostraremos algunas páginas web que emergerán sobre otras (efecto pop-up) o bien, visualizar el tiempo, servicio ofrecido por 'www.tutiempo.net'. –MYSQL como sistema de gestión de base de datos. Será necesario por tanto un servidor donde alojar el website, que soporte las tecnologías citadas anteriormente, siendo recomendable asimismo una descripción de dominio natural y fácil de recordar por la mayoría de los potenciales usuarios. Las funciones ofrecidas por el portal en función de la tipología de usuario y que pueden ser distinguidas son las siguientes : •Acceso a la información referente al municipio y al ayuntamiento (parte más estática del website). •Operaciones sobre noticias: ◦Visualización de noticias. ◦Creación, edición y eliminación de noticias. •Operaciones sobre eventos de la agenda: ◦Visualización de eventos. ◦Creación, edición y eliminación de eventos. 16
•Operaciones sobre oposiciones: ◦Visualización y descarga de bases. ◦Creación, edición y eliminación de oposiciones. •Operaciones sobre trámites y gestiones (tramitaciones) : ◦Visualización de trámites y descarga de impresos. ◦Creación, edición y eliminación de trámites. ◦Filtros de búsqueda de trámites. ◦Visualización del estado de las gestiones (tramitaciones). ◦Gestión de tramitaciones (iniciación, modificación de su estado y eliminación). ◦Filtro de búsqueda de tramitaciones en base al usuario. •Operaciones sobre foros de discusión: ◦Visualización de los posts de un determinado topic. ◦Creación y eliminación de posts. ◦Creación y eliminación de topics. •Operaciones sobre usuarios: ◦Visualización de usuarios y toda la información asociada en su registro. ◦Registro y autenticación de usuarios. ◦Modificación de la información del registro, así como de sus preferencias. ◦Modificación del password y envío de uno nuevo en caso de olvido. ◦Creación, edición y eliminación de usuarios. ◦Cierre de sesión de usuario. •Gestión y seguimiento de los apartados más utilizados por cada usuario: ◦Seguimiento permanente del sistema de los hábitos de uso de cada usuario. ◦Ubicación dinámica de los diversos apartados del portal atendiendo a los hábitos de uso de cada usuario. •Gestión y envío automático de boletines: ◦Usuarios registrados podrán subscribirse al servicio de envío de boletines informativos. ◦El sistema enviará automáticamente por e-mail un boletín a todos los subscritos 17
cada vez que sean añadidos un total de 10 nuevos elementos (noticias y/o eventos). •Implementación de un motor de búsqueda interno: ◦Definición de uno y hasta dos términos simultáneos para la búsqueda. ◦Opción de búsqueda en todo el website o sólo en la página/sección actual. Atendiendo a la tipología de los usuarios que van a utilizar la aplicación, los mismos pueden ser clasificados como sigue : •Usuario Anónimo ◦Cualquier visitante esporádico o no, el cual no se haya autenticado. ◦La estrategia a seguir para este tipo de usuario será la de tratar permanentemente de persuadirlo para que termine registrándose en el portal. En este sentido, se le permitirá visualizar los diversos apartados del website, pero sin posibilidad de interactuar (podrá ver pero no participar). De forma más detallada : ▪Tendrá acceso total al apartado de Noticias y Agenda, pero no podrá recibir boletines informativos (newsletters) sobre las mismas. ▪En el apartado de Trámites, podrá visualizarlos y descargar impresos, pero no podrá iniciar tramitaciones. ▪En el apartado de Foros, podrá leer mensajes pero no podrá responder a los mismos, ni crear nuevos temas. ▪Tendrá acceso a toda la información de la parte más estática del portal (Ayuntamiento, Municipio, Servicios), además de a los apartados de El Tiempo y Callejero. •Usuario Registrado (USU) ◦Cualquier usuario que previamente haya completado el proceso de registro y se haya autenticado en el portal. 18
◦Es importante destacar que en el apartado de Trámites, dispondrá de las mismas opciones que un Usuario Anónimo. Esto es así porque para poder gestionar tramitaciones, es preciso introducir un DNI o CIF en el momento del registro, en cuyo caso, el apartado de “Trámites” pasaría a ser mostrado como “Oficina Virtual”. ◦Dispondrá de las mismas posibilidades de actuación que un Usuario Anónimo, además de las siguientes: ▪Los elementos de la página principal cambiarán su ubicación en función de las preferencias que tenga por los mismos. Para esto, el sistema “estudiará” desde el primer momento, todos sus “movimientos”. ▪Dispondrá de la opción de subscribirse al servicio de Newsletter. ▪En el apartado de Foros, podrá leer mensajes así como responderlos e iniciar nuevos temas de discusión. •Usuario Residencial (RES) ◦Cualquier usuario que previamente haya completado el proceso de registro introduciendo DNI en el momento del mismo, expresando así su deseo de disponer del servicio de Oficina Virtual, habiéndose autenticado asimismo en el portal. ◦Dispondrá de las mismas opciones que un Usuario Registrado, además de poder gestionar tramitaciones (Oficina Virtual). •Usuario Interino (INT) ◦Este tipo de usuario sólo puede ser creado por un Usuario Administrador. ◦El rol que cumple es la propia de un funcionario del ayuntamiento, es decir, dispondrá de un interface dedicado con el objetivo de gestionar los contenidos del portal, como sigue: ▪Visualizar, dar de alta y editar: noticias, eventos de la agenda, trámites y oposiciones. ▪Gestionar tramitaciones previamente iniciadas por un Usuario Residencial (podrá visualizarlas, añadir notificaciones y modificar su estado). ▪Visualizar el Website como si de un Usuario Anónimo se tratase, con el fin de verificar que los cambios introducidos son mostrados de la forma esperada. 19
•Usuario Administrado (ADM) ◦Este tipo de usuario sólo puede ser creado por otro Usuario Administrador. ◦Dispondrá de las mismas opciones que un Usuario Interino, además de las siguientes : ▪Visualizar, dar de alta y eliminar usuarios. ▪Eliminar noticias, eventos de la agenda, trámites y/o oposiciones. Como ya se ha comentado anteriormente, no existirá dependencia de un sistema mayor y bastará una computadora con un navegador web y una conexión Internet para tener acceso al portal. Obviamente serán adoptadas consideraciones orientadas a garantizar la seguridad e integridad de la información, como son la encriptación de las contraseñas de los usuarios, medidas contra ataques de inyección SQL o también la edición conveniente del archivo de configuración para PHP. Por otro lado, se hace altamente recomendable alojar el website en un servidor con HTTPS. El portal será visualizado de forma correcta a través de un navegador web compatible con el protocolo HTTP 1.0 o 1.1, JavaScript y con plantillas CSS, esto es, la amplia mayoría de los navegadores de actualidad. Como también se indicara anteriormente, el servidor donde esté alojado deberá cumplir unos requisitos mínimos como son: soporte para el lenguaje PHP y para administrar bases de datos MYSQL. 20
En este apartado serán descritos los requisitos, atendiendo al nivel de detalle preciso que permita abordar con éxito las siguientes etapas del proyecto, esto es: –descripción de las entradas (“inputs”) al sistema. –descripción del comportamiento o de las funciones adoptados por el sistema, en reacción a las entradas (“inputs”) o bien para cubrir las exigencias de una posible respuesta. –descripción de las respuestas (“outputs”) producidas por el sistema. Interfaces de usuario Atendiendo a la tipología de usuario, pueden diferenciarse 2 tipos de interface de usuario, como sigue : Usuarios no administradores (Anónimos, Registrados e Residenciales): Dispondrán de una página web principal, cuyo espacio se distribuye del siguiente modo: –Sendas barras de navegación situadas tanto en la parte superior como en el pie de página, incluyendo repetición de enlaces directos a algunas de los apartados principales: Trámites y Gestiones, Sugerencias, Agenda, Aviso Legal, etc. –También en la parte superior, barra de navegación principal con acceso a los apartados principales (parte más dinámica) del portal: Noticias, Agenda, Trámites, Foros. –Debajo de la barra de navegación principal anterior, se encuentra la caja de búsquedas, la cual ofrecerá la opción de buscar en todo el portal (única 21
opción disponible si nos encontramos en la página principal) o buscar sólo en el apartado actual (Noticias, Agenda, Trámites o Foros). –En la zona lateral izquierda, barra de navegación vertical con acceso a los apartados principales (parte más estática) sobre información del Ayuntamiento, Municipio y Servicios. –La zona central (tronco de la página principal), estará dedicado a mostrar un resumen de los últimos elementos incorporados a cada uno de los apartados principales: Noticias, Agenda o Foros. –La zona lateral derecha estará dedicada a mini-secciones de funciones de visualización rápida como son: calendario del mes con días marcados si existen eventos, callejero, el tiempo con 3 días de previsión. –La zona lateral derecha superior siempre estará dedicada al área de autenticación de usuarios, modificación del perfil de usuario y su contraseña, así como cierre de la sesión. –Todo el ancho de la zona inferior albergará una subsección “Secciones al detalle”, mostrando las últimas oposiciones publicadas dando opción a descargar sus bases, así como descarga también de los últimos impresos publicados o información sobre los últimos usuarios registrados (Comunidad). Usuarios administradores (Administradores e Interinos): Dispondrán de una página web principal, cuyo espacio quedará distribuido del siguiente modo: –En la zona más alta de cabecera, se dispondrá de sendos enlaces: uno poder visualizar el website como si de un Usuario Anónimo se tratase y otro para acceder a la página principal de administración. –En la zona superior, barra de navegación principal con acceso a los apartados principales de administración: Oficina Virtual, Noticias, Eventos, Oposiciones y Usuarios (ésta última no disponible para Interinos). –El área lateral izquierda superior estará reservada para las diversas opciones de gestión y que irán variando según el apartado principal seleccionado en la barra de navegación principal superior. –El área central principal (tronco de la página principal) estará dedicado a 22
mostrar las informaciones propias de cada gestión en curso. –Sendas barras de navegación tanto en la parte superior como a pie de página, con repetición de enlaces directos a algunas de los apartados principales: Trámites y Gestiones, Sugerencias, Agenda, Aviso Legal, etc. Interfaces de hardware Como ha sido mencionado anteriormente, los requisitos de hardware necesarios para el portal serán un servicio de alojamiento web con soporte para las tecnologías PHP y MYSQL, así como una computadora con conexión a Internet, capaz de ejecutar un navegador web, para los usuarios que accederán al portal. Interfaces de software El producto es desarrollado bajo el sistema operativo Windows XP SP3, sobre el cual se ha instalado y configurado un servidor Apache. Asimismo los lenguajes de programación utilizados son PHP y HTML, junto con plantillas CSS, y JavaScript en menor medida. El sistema de gestión de base de datos correrá a cargo del sistema archiconocido MySQL. Siguiendo una clasificación basada en la tipología de usuario, a continuación se muestra una descripción detallada de los distintos requisitos funcionales: Usuario Anónimo Conviene recordar que este tipo de usuario, es aquel que accede a nuestro portal de forma esporádica o no, el cual probablemente representa un potencial “cliente” para el portal del Ayuntamiento. La estrategia de “comportamiento” del portal en este caso, 23
debe focalizarse en tratar de captar la atención del mismo, hasta el grado de involucrarlo en el proceso del registro, pasando así a formar parte finalmente de la Comunidad de Usuarios. 24 2.3.2.1. Registrarse en el portal Introducción Entradas Cada uno de los campos del formulario de registro. Proceso Salidas El Usuario decide formar parte de la Comunidad de Usuarios registrados, probablemente atraído por alguno de los servicios exclusivos para los mismos (información mostrada de forma llamativa mediante iconos animados) El sistema muestra el formulario de alta de nuevo usuario. Si el usuario confirma su envío, el sistema verifica que hayan sido cumplimentados todos los campos marcados como obligatorios, así como la corrección del formato en algunos de ellos. Si las condiciones anteriores se cumplen, el nuevo usuario es insertado en la Base de Datos (BD), cerciorándose previamente el sistema de que no exista duplicidad en los campos Username y Email. Asimismo es añadida una tupla a la tabla 'preferencias_usuarios' inicializando las puntuaciones. Previamente se realiza un control anti-inyección SQL. Texto informando de que el proceso fue exitoso. Se ofrece un enlace redirigiendo al usuario a la página principal, donde el área de Usuarios exhibirá su nombre y el resto de opciones. 2.3.2.2. Autenticarse en el portal. Introducción Entradas Proceso Salidas Para identificarse en el portal e iniciar así un sesión, será suficiente con que el usuario ingrese su Username y Password en el área de Usuarios. Los datos Username y Password ingresados por el usuario. El sistema contrasta la información recibida contra la Base de Datos. En caso de encontrar una tupla que coincida, valida la operación, inicia una sesión y registra algunas variables de sesión con algunos datos de frecuente consulta sobre el usuario. Finalmente el usuario es redirigido a la página de la sección desde donde se inició la autenticación (si el Usuario tuviera la categoría de Administrador o Interino es redirigido a la página principal de admón). Mensaje de bienvenida, redirigiendo al usuario a la página correspondiente, en virtud del criterio expresado en el apartado anterior. En caso de fallo del proceso de autenticación, se sugiere al usuario volver a intentarlo.
25 2.3.2.3. Recuperar la contraseña en caso de olvido. Introducción Entradas Proceso Salidas El usuario pretende autenticarse sin éxito, debido a que no recuerda la contraseña. Bastará con que ingrese su Username y Password para recibir una nueva contraseña aleatoria por email, que posteriormente podrá modificar a conveniencia. Los datos Username e E-mail ingresados por el usuario. existan en una misma tupla, en cuyo caso, generará una contraseña aleatoria basada en un diccionario con miles de palabras, almacenado en un archivo. A continuación, la nueva contraseña es almacenada en la BD y enviada por email al Usuario para su conocimiento. Si los datos ingresados por el usuario no son encontrados en ninguna tupla, se informa al usuario y se le invita a volver a intentarlo. Se informa al usuario que revise su correo electrónico donde habrá recibido una nueva contraseña. Se invita al usuario a volver intentarlo con motivo de que algunos de los datos ingresados no es correcto. 2.3.2.4. Consultar eventos de un día del calendario. Introducción Entradas Proceso Salidas El usuario puede conocer todos los eventos programados para un día en concreto, simplemente haciendo click en un día del calendario, el cual deberá estar marcado de forma destacada como no vacío. Los días sin eventos no dispondrán de enlace alguno. Asimismo, el usuario puede cambiar de mes y año. El día seleccionado en el calendario, así como el año y mes seleccionados en los campos junto al calendario. Se recupera de la BD toda la información referente a eventos existentes en el día seleccionado. Ventada emergente mostrado el detalle de los eventos programados para el día seleccionado.
Usuario Registrado Conviene recordar que este usuario dispone de las posibilidades de un Usuario Anónimo, además de las descritas a continuación. 32 2.3.2.23. Cambiar contraseña. Introducción Entradas Proceso Salidas El usuario puede en cualquier momento cambiar su contraseña de autenticación por otra, en el área de Usuarios. Formulario cumplimentado por el usuario con la contraseña antigua, la nueva contraseña y la confirmación de la nueva contraseña. El sistema muestra el formulario de cambio de contraseña. Si el usuario confirma su envío, el sistema consulta a la BD para verificar que la contraseña antigua sea correcta. Comprueba asimismo que la nueva contraseña coincida con su confirmación. Finalmente, actualiza la nueva contraseña en la Base de Datos e informa al usuario que el proceso concluyó con éxito. Mensaje indicando que la contraseña fue cambiada con éxito o que por el contrario, existe algún error en los datos que introdujo. 2.3.2.24. Modificar perfil y preferencias de usuario. Introducción Entradas Proceso Salidas El usuario puede editar los datos de registro así como alterar sus preferencias para el servicio de Newsletter (en caso q estuviera subscrito). Formulario cumplimentado con los campos modificados a conveniencia del usuario. El sistema muestra el formulario de modificación al usuario. Si éste confirma su envío, el sistema verifica que los campos modificados presenten el formato adecuado. Asimismo comprueba que en caso de haber modificado el Username y/o Email, éstos no existiesen ya. A continuación, actualiza la tupla en la Base de Datos con los nuevos valores y registra nuevamente las variables de sesión de frecuente consulta sobre el usuario. Previamente se produce un control anti-inyección SQL. Se informa al usuario que la modificación concluyó con éxito o bien, que el proceso fue cancelado.
33 2.3.2.25. Cerrar sesión. Introducción Entradas Proceso Salidas El usuario puede cerrar la sesión activa en cualquier instante desde el área de Usuarios. Enlace “Cerrar Sesión” seleccionado por el usuario, el cual envía una variable logout empleando el método $_GET. Es destruido el identificador de sesión así como las variables de sesión. Se muestra la página principal con las opciones propias de un Usuario Anónimo. 2.3.2.26. Reubicar automáticamente las secciones de la pág. principal Introducción Entradas Proceso Salidas Cada vez que un usuario consigue autenticarse, se obtienen de la BD su histórico de preferencias de uso de cada sección principal del portal. Atendiendo a este histórico, cada vez que es motrada la página principal, ésta reubicará sus subsecciones, dando preferencia de visibilidad a aquellas con mayor puntuación. Los datos de autenticación enviados desde la página principal o bien el enlace 'Inicio' seleccionado por el usuario. El sistema obtiene de la BD las puntuaciones para el usuario autenticado, referentes al acumulado de ocasiones que el mismo ha visitado cada una de las secciones principales del portal. En función de estas puntuaciones, en la página principal serán mostrados unos apartados antes que otros. La página principal mostrará los elementos de cada sección, mostrando de forma preferente aquellos que el usuario visitó más veces, atendiendo al criterio expresado en el punto anterior. 2.3.2.27. Aumentar la puntuación de preferencia de una sección. Introducción Entradas Ninguna. Proceso Salidas Ninguna Cada usuario dispone de una puntuación para cada sección, en función de la cantidad de veces que las visita o utiliza. De esta forma, cuando un usuario visita un sección, es aumentado en 1 unidad su contador de puntuación asociado. El sistema obtiene de la BD la puntuación asociada a la sección que el usuario acaba de visitar, le adiciona 1 unidad y actualiza su valor en la BD.
34 2.3.2.28. Introducción Entradas Proceso Salidas Subscribirse al servicio de Newsletter. El usuario puede subscribir al servicio de envío de boletines. Dispone de 3 modalidades: recibir sólo noticias, sólo eventos o ambos. Para esto, el usuario debe pulsar sobre un icono animado situado en la página principal (sólo es mostrado cuando el usuario no se ha subscrito aún al servicio) el cual enlaza con un formulario que permite subscribirse seleccionando antes el tipo de Newsletter. Formulario con las opciones de subscripción seleccionadas por el usuario. El sistema muestra el formulario de subscripción. Si el usuario confirma su envío, verifica que se haya seleccionado al menos una de las opciones, en cuyo caso actualiza en la BD la tupla de la tabla 'preferencias_usuarios' con este valor. Se muestra un mensaje informando que la subscripción concluyó con éxito o bien que el proceso fue cancelado. 2.3.2.30. Introducción Entradas Formulario con el texto del mensaje introducido por el usuario. Proceso Salidas Crear un nuevo post (mensaje) en un tema del foro. El usuario puede crear un mensaje asociado a algún tema del foro, respondiendo al mensaje de otro usuario o bien simplemente aportando una opinión. El sistema comprueba que el texto del mensaje no esté vacío, en cuyo caso inserta una nueva tupla en la BD. Previamente se produce un control anti-inyección SQL. Se informa al usuario de que el mensaje fue creado correctamente, listándose a continuación todos los mensajes del tema asociado. Si el usuario envío el formulario el blanco, se le informa del error. 2.3.2.29. Abrir un nuevo topic (tema) en los foros. Introducción Entradas Proceso Salidas El usuario puede abrir un nuevo tema de discusión, adicionando además un primer mensaje o no. Formulario con el título del tema y (opcionalmente) texto del primer mensaje (post). El sistema muestra un formulario con el título del tema y texto del mensaje por cumplimentar. Si el usuario confía su envío, se comprueba que el título del tema no esté vacío, en cuyo caso analiza si existe además un primer mensaje. Seguidamente inserta en la BD el nuevo topic, así como el mensaje, si lo hubiera. Previamente se produce un control anti-inyección SQL. Se informa al usuario de que el tema fue creado correctamente, listándose a continuación todos los temas del foro. Si el usuario no introdujo algún título para el tema, se le informa de que esta circunstancia es imprescindible para continuar.
Usuario Residencial Conviene recordar que este usuario dispone de las posibilidades de un Usuario Registrado, además de la funcionalidad de Oficina Virtual. 35 2.3.2.32. Eliminar un tema del foro. Introducción Entradas Proceso Salidas El usuario puede eliminar un tema del foro, siempre y cuando sea propietario del mismo y no existan mensajes de otros usuarios en el mismo. El sistema no dará la opción de borrado si no se cumplen las condiciones anteriores. Enlace 'Eliminar tema' seleccionado por el usuario, el cual lleva asociado el identificador del tema a eliminar. Se elimina de la BD la tupla correspondiente al tema seleccionado. Si existen mensajes del propietario del tema, también son eliminados de la BD. Se informa al usuario de que el tema fue eliminado correctamente, listándose a continuación los temas del foro. 2.3.2.31. Eliminar un mensaje del foro. Introducción Entradas Proceso Salidas El usuario puede eliminar un mensaje del foro, siempre y cuando sea propietario del mismo. El sistema no dará la opción de borrado si no se cumple esta condición. Enlace 'Eliminar mensaje' seleccionado por el usuario, el cual lleva asociado el identificador del mensaje a eliminar. El sistema elimina de la DB la tupla asociada al identificador del mensaje. Se informa al usuario de que el mensaje fue eliminado correctamente, listándose a continuación todos los mensajes del tema asociado.
36 2.3.2.33. Visualizar tramitaciones o gestiones. Introducción Entradas Proceso Salidas El usuario puede visualizar todas las tramitaciones iniciadas previamente, así como su estado actual (Iniciado, Revisión, Aprobado o Denegado). El sistema dará la opción de eliminar aquéllas que aún no hayan sido revisadas así como de visualizar en detalle cada una de ellas. Enlace 'Gest. Tramitaciones' o 'Oficina Virtual' seleccionado por el usuario. Se obtienen de la BD todas las tramitaciones cuyo propietario sea el usuario autenticado. Se muestra un listado con todas las tramitaciones que haya iniciado el usuario autenticado, así como el estado de cada una de ellas (Iniciado, Revisión, Aprobado o Denegado), su fecha de iniciación, la opción de eliminar la tramitación si ésta se encuentra en estado de Iniciado así como también la posibilidad de ver todos los detalles de la misma. 2.3.2.34. Visualizar en detalle una tramitación o gestión. Introducción Entradas Proceso Salidas El usuario puede visualizar todos los detalles de una tramitación, esto es, el histórico de notificaciones usuario-funcionario, el estado de la misma, así como toda la información del trámite asociado. Enlace 'Ver estado' seleccionado por el usuario, el cual lleva asociado el identificador de la tramitación a visualizar. Se obtienen de la BD la información de la tramitación seleccionada por el usuario, así como la información del trámite a que corresponde la tramitación. Se muestra en una ventana emergente, todos los detalles de la tramitación seleccionada, es decir, el histórico de notificaciones usuario-funcionario, el estado de la misma y la información del trámite asociado.
37 2.3.2.35. Eliminar una tramitación o gestión. Introducción Entradas Proceso Salidas El usuario puede eliminar una tramitación que hubiera iniciado previamente, siempre y cuando no estuviera en revisión, es decir, su estado fuera de Iniciado, Aprobado o Denegado. Formulario de confirmación de borrado de tramitación, enviado por el usuario. El sistema muestra un formulario de confirmación de borrado. Si éste es confirmado, consulta a la BD el estado de la tramitación a eliminar para comprobar que no sea el de “Revision” (control del acceso concurrente ya que un Administrador podría haber cambiado su estado de Iniciado a Revision), en cuyo caso, elimina de la BD la tupla asociada a la tramitación. Se muestra un mensaje informando que la eliminación concluyó con éxito o bien que el proceso fue cancelado. 2.3.2.36. Editar una tramitación o gestión. Introducción Entradas Formulario con el texto de la notificación a adjuntar a la tramitación. Proceso Salidas El usuario puede añadir nuevas notificaciones a una tramitación, siempre y cuando no haya sido aprobada o denegada por un funcionario del Ayuntamiento. Estas notificaciones son el recurso disponible para comunicarnos con el funcionario durante el curso de la gestión de la tramitación. El sistema muestra en una ventana emergente el histórico actual de notificaciones así como un formulario para añadir una nueva notificación. A continuación actualiza la tramitación en BD, habiendo añadido previamente el nuevo texto de notificación. Previamente se produce un control anti-inyección SQL. Se informa al usuario de que la tramitación fue modificada con éxito o bien, que el proceso fue cancelado.
Usuario Interino Conviene recordar que este tipo de usuario es el responsable de manipular la información sobre los contenidos del portal. El único matiz que lo diferencia con el Usuario Administrador es que no dispone de opciones para eliminar ninguna información, así como de gestionar usuarios. 38 2.3.2.37. Iniciar una tramitación o gestión. Introducción Entradas Proceso Salidas Se informa al usuario de que la tramitación se inició correctamente. El usuario puede iniciar una nueva tramitación. Para ello, deberá realizar previamente una búsqueda de trámites empleando filtros. El resultado de la búsqueda mostrará un listado de trámites disponibles, dando el sistema las siguientes opciones sobre cada uno de ellos: - Visualizar todos sus detalles. - Iniciar su tramitación (siempre y cuando disponga de opción de tramitación electrónica). En primer lugar, formulario con los filtros de búsqueda seleccionados por el usuario. A continuación, formulario de confirmación de iniciación de tramitación, con el texto (opcional) de notificación a adjuntar. El sistema muestra formulario de búsqueda de tramitaciones. Posteriormente, inserta en la BD una nueva tramitación, así como el texto de notificación si lo hubiera. Previamente se produce un control anti-inyección SQL. 2.3.2.38. Visualizar tramitaciones pendientes de resolución. Introducción Entradas Proceso Salidas El usuario podrá visualizar todas las tramitaciones pendientes de resolución de un usuario determinado, mostrando diferentes opciones de actuación para cada una de ellas. Previamente habrá realizado una búsqueda filtrando por el nombre de usuario (Username). Formulario de búsqueda con el Username seleccionado por el usuario. El sistema obtiene de la BD las tramitaciones cuyo estado sea 'Iniciado' o 'Revision', del usuario seleccionado en el formulario de búsqueda Listado con las tramitaciones (nombre, estado y fecha de iniciación) pendientes de resolución del usuario seleccionado, ofreciendo sobre cada una de ellas, la siguiente opción: - Visualizar sus detalles. - Modificar su estado, añadiendo opcionalmente una notificación.
39 2.3.2.40. Visualizar trámites disponibles. Introducción Entradas Proceso Salidas El usuario puede obtener un listado de trámites disponibles, utilizando para ello un formulario de búsqueda. El listado resultado mostrará para cada trámite, opciones de edición o visualización en detalle. Formulario de búsqueda enviado por el usuario, junto con los filtros seleccionados por el mismo. El sistema muestra el formulario de búsqueda. Si el usuario confirma su envío, el sistema construye una consulta a la BD en función de los filtros seleccionados, obteniendo aquellos trámites que cumplen con los mismos. Listado con todos los trámites que reúnen las condiciones de búsqueda seleccionadas por el usuario, junto con algunas opciones de actuación según se explica en el apartado Introducción. 2.3.2.39. Modificar una tramitación. Introducción Entradas Proceso Salidas El usuario podrá cambiar el estado de la tramitación a alguno de los estados posible (Revision, Aprobado, Denegado), así como opcionalmente anexar una notificación. Asimismo este usuario podrá conservar el estado de Revisión y añadir opcionalmente una notificación requiriendo alguna información del usuario que originó la tramitación. Formulario con el nuevo valor del estado de la tramitación, así como el texto a notificar. El sistema obtiene de la BD el histórico de notificaciones existente sobre la tramitación seleccionada por el usuario y lo muestra en una ventana emergente, acompañándolo de un formulario donde el usuario puede añadir una nueva notificación así como indicar el nuevo estado para la tramitación. En caso de que éste anexara una nueva notificación, el sistema lo adiciona al histórico obtenido antes. A continuación, se actualiza en la BD la tupla correspondiente a la tramitación, con el nuevo valor de estado y del histórico de notificaciones. Se informa al usuario que la modificación concluyó con éxito o bien, que el proceso fue cancelado.
40 2.3.2.41. Visualizar en detalle un trámite. Introducción Entradas Identificador del trámite seleccionado por el usuario. Proceso Salidas El usuario puede visualizar todos los detalles de un trámite determinado, así como descargar el impreso asociado al mismo. El sistema busca el trámite en la BD y extrae toda la información necesaria de la tupla encontrada. Ventada emergente mostrando toda la información disponíble sobre el trámite, así como un enlace al impreso para su descarga, en caso de que exista un impreso asociado. 2.3.2.42. Crear un nuevo trámite. Introducción Entradas Formulario cumplimentado y enviado por el usuario. Proceso Salidas El usuario puede dar de alta nuevos trámites, cumplimentando cada uno de los campos del formulario. Asimismo, es posible anexar un impreso que permita ser descargado posteriormente. El sistema muestra el formulario de apertura de nuevo trámite. Si el usuario confirma su envío, el sistema comprobará que estén cumplimentados los campos obligatorios. Si además anexó algún impreso, comprobará que el mismo haya sido recibido correctamente. Si se cumplen las condiciones anteriores, el sistema insertará el trámite en la BD. Previamente se produce un control anti-inyección SQL. Se informa al usuario que el trámite fue introducido con éxito o bien, que el proceso fue cancelado. 2.3.2.43. Editar un trámite. Introducción Entradas Formulario de modificación enviado por el usuario. Proceso Salidas El usuario puede modificar un trámite existente, así como cambiar el impreso asociado al mismo. El sistema muestra el formulario de edición. Si el usuario confirma su envío, el sistema comprobará que estén cumplimentados los campos obligatorios. Si además anexó algún impreso, comprobará que el mismo haya sido recibido correctamente. Si se cumplen las condiciones anteriores, el sistema actualizará el trámite en la BD. Previamente se produce un control anti-inyección SQL. Se informa al usuario que la modificación concluyó con éxito o bien, que el proceso fue cancelado.
41 2.3.2.44. Visualizar noticias. Introducción Entradas Proceso Salidas El usuario puede obtener un listado de todas las noticias disponibles, utilizando para ello un formulario de búsqueda. El listado resultado mostrará para cada noticia, opciones de edición y visualización en detalle. Formulario de búsqueda enviado por el usuario, junto con los filtros seleccionados por el mismo. El sistema muestra el formulario de búsqueda. Si el usuario confirma su envío, el sistema construye una consulta a la BD en función de los filtros seleccionados, obteniendo aquellas noticias que cumplen con los mismos. Listado con todos las noticias que reúnen las condiciones de búsqueda seleccionadas por el usuario, junto con algunas opciones de actuación según se explica en el apartado Introducción. 2.3.2.45. Visualizar en detalle una noticia. Introducción Entradas Identificador de la noticia seleccionada por el usuario. Proceso Salidas El usuario puede visualizar todos los detalles de una noticia determinada. El sistema busca la noticia en la BD y extrae toda la información necesaria de la tupla encontrada. Ventada emergente mostrando toda la información disponible sobre la noticia, así como su foto en caso de que exista. 2.3.2.46. Crear una nueva noticia. Introducción Entradas Formulario cumplimentado y enviado por el usuario. Proceso Salidas El usuario puede dar de alta nuevas noticias,cumplimentando cada uno de los campos del formulario. Asimismo, es posible anexar una foto a la misma. El sistema muestra el formulario de apertura de nuevo noticia. Si el usuario confirma su envío, el sistema comprobará que estén cumplimentados los campos obligatorios. Si además anexó alguna foto, comprobará que la misma haya sido recibido correctamente. Si se cumplen las condiciones anteriores, el sistema insertará el trámite en la BD. Previamente se produce un control anti-inyección SQL. Se informa al usuario que la noticia fue introducida con éxito o bien, que el proceso fue cancelado.
48 2.3.2.64. Eliminar una oposición. Introducción El usuario puede eliminar oposiciones de la BD. Entradas Proceso Salidas Formulario de confirmación de borrado de oposición, enviado por el usuario. El sistema muestra un formulario de confirmación de borrado. Si éste es confirmado, se elimina de la BD la tupla asociada a la oposición. Se muestra un mensaje informando que la eliminación concluyó con éxito o bien que el proceso fue cancelado. 2.3.2.63. Eliminar un evento. Introducción El usuario puede eliminar eventos de la BD. Entradas Proceso Salidas Formulario de confirmación de borrado de evento, enviado por el usuario. El sistema muestra un formulario de confirmación de borrado. Si éste es confirmado, se elimina de la BD la tupla asociada al evento Se muestra un mensaje informando que la eliminación concluyó con éxito o bien que el proceso fue cancelado. 2.3.2.62. Eliminar una noticia. Introducción El usuario puede eliminar noticias de la BD. Entradas Proceso Salidas Formulario de confirmación de borrado de noticia, enviado por el usuario. El sistema muestra un formulario de confirmación de borrado. Si éste es confirmado, se elimina de la BD la tupla asociada a la noticia. Se muestra un mensaje informando que la eliminación concluyó con éxito o bien que el proceso fue cancelado. 2.3.2.65. Eliminar un mensaje del foro. Introducción Entradas Proceso Salidas El usuario puede eliminar cualquier mensaje del foro a conveniencia, con el fin de retirar comentarios ofensivos, o simplemente si se diera la circunstancia que el mensaje no guardase relación con el tema donde fue publicado. Enlace 'Eliminar mensaje' seleccionado por el usuario, el cual lleva asociado el identificador del mensaje a eliminar. Se elimina de la BD la tupla correspondiente al tema seleccionado. Si existen mensajes del propietario del tema, también son eliminados de la BD. Se informa al usuario de que el tema fue eliminado correctamente, listándose a continuación los temas del foro.
Seguridad La seguridad y consistencia de la información almacenada en la Base de Datos es un aspecto fundamental y de especial consideración dentro del proyecto. Por este motivo, se han adoptado diversas metodologías modernas en pro de evitar o, en el peor de los casos minimizar, las consecuencias que podría originar un percance en este apartado. A continuación se describen algunas de las buenas prácticas adoptadas : 1. Garantizaremos el acceso ordenado y confiable de la información a través de un sistema de autenticación de usuarios, donde cada usuario requerirá estar registrado en la base de datos con un nombre de usuario y una contraseña. Esta información estará almacenada en una tabla de la base de datos. 2. Las contraseñas serán almacenadas de forma encriptada en un sentido (no reversible) mediante la función de encriptación PASSWORD de MYSQL. 3. Las funciones propias de un tipo de usuario únicamente podrán ser ejecutadas por usuarios de su tipo. Esto se consigue consultando, previo a la ejecución de una función, la variable de sesión que hace referencia a la categoría (y por tanto a los privilegios) del usuario autenticado. Por ejemplo, un Usuario Registrado nunca podrá iniciar una tramitación (función sí disponible para un Usuario Residencial), puesto que previo a la ejecución de la función, se comprueba la categoría (variable de sesión) del usuario autenticado. 4. Activaremos la directiva magic_quotes_gpc del archivo de configuración PHP.INI, con el fin de evitar vulnerabilidades que podrían originarse a raíz de datos provenientes de los métocos GET y POST. Evitamos de este modo los escapes indeseados de información. 5. No se usarán variables de sesión por ser fácilmente modificables por el usuario. En su lugar, utilizaremos funciones y varialbes de sesión. Las funciones de sesión proporcionan un identificador único para el usuario. 6. Se eliminarán etiquetas HTML y PHP de las cadenas introducidas en formularios por el usuario, empleando la función strip_tags de PHP. 7. Para minimizar riesgos de ataques, nunca se enviará información de contenido o 49
de control importantes, a través de url (método GET). En su lugar, utilizaremos métodos POST. 8. La carga de librerías de funciones se hará de forma discriminada. De este forma, un usuario no administrador, no podrá “ver” funciones propias del mismo. 9. El archivo de conexión con la Base de Datos que almacena la contraseña y demás información que permite el enlace con la misma, estará almacenado fuera de la ruta del Website. Mantenimiento El mantenimiento de la información de contenido del portal (aquel que requiere de una actualización constante como por ejemplo el apartado de noticias o eventos, será responsabilidad de los usuarios con categoría de Administrativo o Interino, por tanto se tratará típicamente de personal del propio ayuntamiento. Los cambios en el rediseño de la estructura de la base de datos o del grafismo del portal, así como la actualización de la información de la parte más estática del portal (Ayuntamiento, Municipio, etc) y resolución de incidencias eventuales, serán solicitados por personal del Ayuntamiento al ingeniero del website. 50
Una vez han sido descritos los requisitos capturados, en el capítulo anterior, es preciso profundizar en alguna metodología que propicie la detección de aquellos apartados generales que guardan una relación directa con esos requisitos. Esta metodología debe tener la virtud de ser lo suficientemente abstracta como para conseguir mantener la independencia con los diversos recursos tecnológicos disponibles para su implementación, los cuales serán abordados en capítulos posteriores. En la actualidad, existe una metodología ya consolidada y denominada RUP (Rational Unified Process), que cubre ampliamente las expectativas expresadas en el párrafo anterior. Esta metodología se apoya en modelos UML (Unified Modeling Language) que ayudan a describir la función, la arquitectura o el diseño del software. UML es el lenguaje de modelado de sistemas software más utilizado actualmente, respaldado por el OMG (Object Management Group), que sirve eficazmente para describir procesos haciéndose valor para ello de elementos gráficos. Permite visualizar, especificar, construir y documentar un sistema. Ofrece por tanto de un estándar que podemos hacer servir óptimamente en nuestra aplicación web. UML dispone de diversos diagramas para identificar las diversas entidades del sistema a modelar. De entre todos ellos, nos basaremos en el Diagrama de Casos de Uso así como en el Diagrama de Clases para continuar con el desarrollo del proyecto que nos ocupa. 51
Un Diagrama de Casos de Uso muestra cómo debería reaccionar el sistema con el usuario, o bien con otro sistema, para conseguir un objetivo. Se trata por tanto de una representación de la secuencia de acciones entre un sistema y sus actores, respondiendo a un evento que inicia uno de los actores principales. El uso de este tipo de diagramas está ampliamente extendido debido a la notación relajada de la que hace uso, resultando por tanto muy cercano para el usuario final. En la Fig. 3.2.1 se muestran los diversos actores identificados cuyas peculiaridades ya fueron descritas en apartados anteriores. El diagrama pone de manifiesto la especialización de algunos de los usuarios. Expondremos a continuación los diferentes casos de uso para cada uno de los actores identificados. 52 Usuario Anónimo Usuario Registrado Usuario Residente Usuario Administrador Usuario Interino Fig. 3.2.1 - Actores principales del sistema
53 Fig. 3.2.2 – Casos de uso para el Usuario Anónimo Usuario Anónimo Registrarse Autenticarse Recuperar contraseña Consultar noticias Consultar eventos Consultar información sobre el Ayto. Consultar mapa Consultar el tiempo Contactar con Ayuntamiento Utilizar buscador Consultar trámites Consultar foros Consultar oposiciones Validar datos <<include>> Verificar username+psw <<include>> Validar Usuario [datos correctos] <<extend>> Mostrar Error [datos incorrectos] <<extend>> Verificar formulario <<include>> Listar trámites <<include>> Buscar trámites <<include>> Validar PSW+USERNAME Enviar contraseña Informar Error [Usuario+PSW correctos] <<extend>> [Usuario+PSW correctos] <<extend>> <<include>> Mostrar incidencia Enviar email al Ayto. [Form. correcto] <<extend>> [Form. con incidencias] <<extend>> Usuario Registrado Cambiar contraseña Modificar preferencias Cerrar sesión Subscribir a Newsletter Abrir temas en los foros Responder mensajes de foros Eliminar mensajes de foros Destruir variables sesión Verificar formulario <<include>> Informar de éxito Informar de error [datos correctos] <<extend>> [error datos] <<extend>> Comprobar formulario <<include>> Visualizar mensajes de foros <<include>> <<include>> Actualizar BD Informar Error [datos correctos] <<extend>> [error datos] <<extend>> <<include>> Eliminar temas de foros [existen sólo mensajes propios] <<extend>> Fig. 3.2.3 – Casos de uso para el Usuario Registrado (se obvia el caso de uso Autenticarse)
Los casos de uso del Diagrama para el Usuario Registrado (Fig. 3.2.3) deberían incluir al Caso de Uso “Autenticarse”. No obstante, se han obviado en pro de mejorar la legibilidad del mismo. En lo sucesivo para el resto de Diagramas que serán mostrados, se obviará representar este Caso de Uso con este fin, el de facilitar una interpretación ágil, salvo que su no inclusión sea contraproducente por propiciar resultados ambiguos. Puede apreciarse en el Diagrama de Casos de Uso para el Usuario Registrado (Fig. 3.2.3), cómo algunos escenarios involucran sistemáticamente a otros (aquellos identificados con la etiqueta <<include>> o inclusión). Por ejemplo, para responder o eliminar un mensaje de un tema del foro, inevitablemente será preciso visualizar previamente los mensajes del tema en cuestión. Del mismo modo, puede apreciarse en el mismo Diagrama, el uso de la etiqueta <<extend>> o extensión, para representar que diversos escenarios pueden desencadenarse en función de la condición que se cumpla (especificada entre corchetes []). Por ejemplo, el Caso de Uso “Modificar preferencias” involucraría actualizar la Base de Datos con la información enviada por usuario, siempre y cuando los datos del formulario estén correctos, o bien, implicaría informar al usuario de que existe un error en los datos introducidos, invitándole a volver a intentarlo. 54 Usuario Residencial Listar tramitaciones Visualizar tramitación en detalle Eliminar tramitación Editar tramitación Iniciar tramitación Listar trámites Verificar formulario Buscar trámites <<include>> <<include>> <<include>> <<include>> <<include>> <<include>> Fig. 3.2.4 – Casos de uso para el Usuario Residencial
55 Usuario Interino Gestionar tramitaciones Gestionar trámites Gestionar noticiasGestionar eventos Gestionar oposiciones Cerrar sesión Cambiar contraseña Modificar preferencias Fig. 3.2.5 – Visión general Casos de Uso para el Usuario Interino Fig. 3.2.6 – Visión en detalle del Caso de Uso “Gestionar tramitaciones” Usuario Interino Gestionar tramitaciones Listar tramitaciones Buscar tramitaciones Editar tramitación Visualizar tramitación <<include>> <<include>> <<include>>
En la fig. 3.2.7, se muestra con mayor nivel de detalle, el Caso de Uso “Gestionar noticias” correspondiente al Usuario Interino. Obviaremos representar los casos de uso “Gestionar eventos”, “Gestionar trámites” y “Gestionar oposiciones” por disponer de prácticamente idénticos Diagramas (siguen el mismo patrón). Cabe destacar para los Casos de Uso “Crear una noticia” y “Editar una noticia”, la importancia de verificar que el fichero que contiene la imagen de la noticia haya sido subido al servidor sin errores, previo a la inserción de la tupla correspondiente en la Base de Datos. Si ocurriese alguna incidencia durante su envío, se informaría al usuario y éste debería volver a intentarlo. A continuación se muestran en la fig. 3.2.8, los diferentes Casos de Uso para el Usuario Administrador, que lo diferencian del Usuario Interino, esto es, la posibilidad de eliminar información de la Base de Datos, así como la gestión de usuarios. 56 Usuario Interino Gestionar noticias Listar noticias Visualizar una noticia Crear una noticia Editar una noticia Buscar noticias <<include>> <<include>> <<include>> Verificar formulario <<include>> Subir imagen Mostrar error [datos correctos] <<extend>> [error datos] <<extend>> <<include>> Insertar noticia [imagen subida sin errores] <<extend>> [error al subir imagen] <<extend>> Fig. 3.2.7 – Visión en detalle del Caso de Uso “Gestionar noticias”
57 Usuario Administrador Eliminar noticia Eliminar trámite Eliminar evento Eliminar oposición Eliminar mensaje del foro Gestionar usuarios Fig. 3.2.8 – Visión general Casos de Uso para el Usuario Administrador Fig. 3.2.9 – Visión en detalle del Caso de Uso “Gestionar Usuarios” Usuario Administrador Gestionar Usuarios Listar usuarios Visualizar detalles usuario Crear usuario Eliminar usuario <<include>> <<include>> Verif. existe Username Verif. existe Email <<include>> [no existe Username] <<extend>> Verif. resto formulario [no existe email] <<extend>> Insertar usuario en BD Insertar preferencias en BD Mostrar Error [Username existe] <<extend>> [Email existe] <<extend>> [datos correctos] <<extend>> Eliminar preferencias de BD [es Usu. Reg. o Resid] <<extend>> [es Usu. Reg. o Resid] <<extend>>
3.4.2. Escenario 2: Buscar trámites. (Fig. 3.4.2.1) Cualquier usuario puede obtener un listado de trámites disponibles, que cumplan una serie de requisitos de búsqueda (formulario con filtros). 1. Se muestra al usuario un formulario con varios filtros. 2. El usuario lo cumplimenta y envía. 3. El sistema obtiene la información que coincide con los filtros y la prepara previo a mostrarla. 4. Finalmente, el sistema muestra en base a un formato determinado, la información anterior. Si ninguna información fuera encontrada, informa igualmente al usuario. 64 Fig. 3.4.2.1. – Diagrama de Secuencia: Buscar trámites
3.4.3. Escenario 3: Crear un nuevo usuario ( Fig. 3.4.3.1 ) El usuario Administrador es el único que puede dar de alta nuevos usuarios. 1. El usuario envia el formulario con los datos del nuevo socio. 2. El sistema comprueba que el Username y el Password no existiesen ya para un mismo socio. 3. Se verifican que el resto valores de campos del formulario estén en el formato correcto y hayan sido cumplimentados los obligatorios. 4. El usuario es insertado en la BD. 5. El usuario Administrador es informado del éxito. Si ocurriese cualquier error durante el escenario, también será informado del mismo. 3.4.4. Escenario 4: Eliminar un trámite. (Fig. 3.4.4.1) El usuario Administrador puede eliminar un trámite, para lo que previamente deberá listar los trámites disponibles aplicando una búsqueda por filtrado. Si existe algún impreso asociado, si fichero deberá ser eliminado igualmente. 1. Se muestra al usuario un formulario con varios filtros. Éste lo cumplimenta y envía. 2. El sistema obtiene la información que coincide con los filtros y la prepara previo a mostrarla. 3. El sistema muestra un listado con los trámites, dando sobre cada uno la opción de eliminarlo, entre otras. 4. El usuario selecciona la opción de eliminar y el sistema solicita el borrado de la BD. 5. Asimismo, si comprueba si existe algún impreso asociado, en cuyo caso el sistema solicita también el borrado del mismo. 6. Finalmente el sistema informa al usuario del resultado de la operación. 65
66 Fig. 3.4.3.1. – Diagrama de Secuencia: Crear un nuevo usuario
67 Fig. 3.4.4.1. – Diagrama de Secuencia: Eliminar un trámite
3.4.5. Escenario 5: Recuperar contraseña olvidada. (Fig. 3.4.5.1) Un usuario puede solicitar una nueva contraseña en caso de olvido de la misma. Para ello, deberá enviar un formulario indicando su Username y su Email. En sistema comprueba que la información es correcta, previo consulta a la BD. Si la información enviada es fidedigna, el sistema generará una nueva contraseña e informará al usuario de la misma, enviándole un email, informando al mismo de que debe revisar su email. 1. El usuario envía vía formulario, su Username y su Password. 2. El portal contrasta la información con la BD y en caso de éxito, genera un nuevo password. 3. Se envía la contraseña por email al usuario y se le informa de que debe revisar el correo para conocer el nuevo password. 68 Fig. 3.4.5.1. – Diagrama de Secuencia: Recuperar contraseña en caso de olvido
En este capítulo, la aplicación será descrita con un nivel de detalle todavía más elevado si cabe que el conseguido en el capítulo de Análisis. Para conseguir el objetivo anterior, nos haremos servir de una arquitectura Web basada en el modelo de tres niveles. Algunas de las virtudes de utilizar un modelo de 3 niveles o capas, es que permite continuar con el desarrollo en cualquiera de los niveles, siendo necesario revisar únicamente uno de ellos, en caso de precisar de alguna modificación. Otra virtual es que permite distribuir el trabajo por equipos, de forma que cada equipo consigue focalizar sus esfuerzos en el nivel que tenga asociado; en este caso, bastaría con conocer la API que existe entre el resto de niveles (se consigue así abstraer a los equipos, enfatizándose el “qué hace” más que el “cómo lo hace”). A continuación describiremos en detalle cada uno de los niveles. Asimismo bastará con observar la Fig. 4.1.1. para asimilar rápidamente lo que se pretende al emplear este tipo de arquitectura, en un entorno Web como el que nos ocupa: •Nivel de Interfaz o Presentación: formado por aquellos elementos que permiten al usuario interaccionar con el sistema (formularios, informes, confirmación de eventos, …). También utilizada por el sistema para informar al usuario (mensajes de error, información demandada, etc). 69
Asimismo, se refiere también al diseño y al formato en que es mostrada la información. Debe tener la virtud de resultar intuitiva y amigable para el usuario, esto es, comprender su funcionamiento en el menor tiempo posible, en pocas palabras: “ponerle las cosas fáciles” al usuario. El nivel de interfaz es el que se comunica con el nivel de negocio. •Nivel de Negocio o Lógico: formado por las funciones que implementan el comportamiento de las diferentes clases, ya especificado en el apartado de análisis. Es el apartado encargado por tanto de pilotar las operaciones, de aplicar la lógico de control, de procesar y gestionar la información. 70 Fig. 4.1.1. – Ejemplo de arquitectura web en base al modelo de 3 niveles
Este nivel representa el enlace que comunica las otros 2 niveles. •Nivel de Almacenamiento o Persistencia: integra la Base de Datos y el Sistema de Gestión de la Base de Datos (MySQL y phpMyAdmin respectivamente, en el caso que nos ocupa). No sólo es el encargado de almacenar la información, sino también el responsable de la seguridad e integridad de la misma. A continuación se detalla cómo han sido abordados cada uno de los niveles para el caso en estudio. En cualquier interfaz de usuario que se precie, debe prevalecer el carácter intuitivo y amigable del mismo, esto es, que cualquier usuario que se aventure a utilizarlo, sin importar la experiencia del mismo, consiga identificar los elementos principales en el menor tiempo posible. También el término amigable expresa la necesidad de “gustar” al usuario y esto se consigue con diferentes estrategias: tipos de letras legibles y adecuadas a cada contexto, así como la combinación de grafismos y simbologías empleada, colores suaves y poco estridentes, uniformidad en los diseños, etc. En el caso que nos ocupa, para representar cada una de las páginas que conforman el portal, se emplearán 2 formatos o estructura de página diferentes: –La Figura 4.2.1 muestra la estrategia utilizada para la página principal (Inicio), con cabida para albergar una mayor cantidad de elementos y secciones. Es posible detectar un disposición del área central en base a 3 columnas donde la columna central será dedicada a exhibir los contenidos principales, mientras que las columnas laterales, de menor extensión, albergarán elementos como menús de navegación, subsecciones u otros servicios menores. –Por otro lado, la Figura 4.2.2 representa el formato que será empleado para el resto de páginas, tanto para usuarios Funcionarios como No Funcionarios. Es 71
fácil comprobar que su aspecto, aunque similar al formato anterior, presenta una concentración menor de elementos dispares. De esta forma, la disposición del área central es ahora en base a 2 columnas y se ha eliminado el área inferior dedicado a las Secciones al Detalle. Obviamente, las opciones de usuario disponibles en las distintas barras de navegación o menús, cambiarán automáticamente en función del tipo de usuario autenticado. 72 Fig. 4.2.1. – Formato de página empleado para la Página Principal (Inicio)
El nivel de negocio está representado por el conjunto de componentes software que implementa de forma completa el comportamiento de las clases del dominio. 73 Fig. 4.2.2. – Formato de página empleado para el resto de páginas.
TRAMITES (id: entero_largo, titulo: varchar(100), tipo: varchar(50), online: varchar(2), desc: varchar(255), importe: entero, documentacion: varchar(255), lugar_present: varchar(50), organo_gestor: varchar(50), observaciones: varchar(255), impresos: varchar(50)) CP: {id} VNN: {tipo, online, importe} CAj: {id} → TRAMITES_USUARIOS CALENDARIO_EVENTOS (id: entero_largo, titulo_evento: varchar(100), desc_evento: text, inicio_evento: date) CP: {id} VNN: {titulo_evento, inicio_evento} CONTROL_NEWSLETTER (tipo_newsletter: varchar(18), pendientes_global: entero(2), pendientes_individual: entero(2)) CP: {tipo_newsletter} VNN: {pendientes_global, pendientes_individual} FORO_POSTS (post_id: entero_largo, topic_id: entero_largo, post_texto: text, post_fecha: date, post_prop: varchar(100)) CP: {post_id} VNN: {topic_id, post_texto, post_prop} CAj: {topic_id} → FORO_TOPICS FORO_TOPICS (topic_id: entero_largo, topic_titulo: varchar(100), topic_fecha: date, topic_prop: varchar(20), topic_ultimo: date) CP: {topic_id} VNN: {topic_titulo, topic_prop, topic_fecha} NOTICIAS (id: entero_largo, titular:varchar(200), texto: text, imagen: varchar(50), fecha: date) CP: {id} VNN: {titular, fecha} 80
OPOSICIONES (id: entero_largo, nombre: varchar(50), plazas: entero(3), fecha_publicacion: date, bases: varchar(100)) CP: {id} VNN: {nombre, plazas, fecha_publicacion} PREFERENCIAS_USUARIOS (username: varchar(40), newsletter: varchar(8), noticias: entero(4), eventos: entero(4), callejero: entero(4), tiempo: entero(4), foros: entero(4), ) CP: {username} VNN: {newsletter, noticias, eventos, callejero, tiempo, foros} CAj: {username} → USUARIOS SECCION_ESTATICA (seccion: varchar(4), contenido: text, imagen: varchar(30), fecha_actualizacion: date, apartado: varchar(15)) CP: {seccion} VNN: {contenido, apartado} 81
82
En el capítulo anterior, la aplicación objeto de este estudio fue estructurada en diversos niveles y fueron descritos todos ellos de la forma más abstracta posible, evitando entrar en detalles sobre tecnologías o recursos de implementación. En el capítulo que nos ocupa, serán revisadas las tecnologías Web recurridas para implementar la aplicación, progresando de forma ordenada a través de la estructura de niveles que fue especificada. En síntesis, aquellos recursos o tecnologías webs a los que se ha recurrido son: –Entorno de desarrollo web WampServer versión 2.0. Se trata de un paquete que incluye, instala y configura casi de manera automática: Apache, PHP, MySQL y PHPMyAdmin. –Lenguaje PHP para todo el apartado de programación y lógica de control, debido al carácter dinámico e interactivo perseguido, y habitualmente será entremezclado o combinado con el lenguaje de marcado HTML. La versión utilizada en el momento de editar este documento es la 5.3.0. –Plantillas CSS con el objetivo de ofrecer una interfaz atractiva y un diseño del website moderno, acorde a las últimas tendencias. Por otro lado, esta decisión mejorará notablemente el tiempo requerido para futuras modificaciones en el diseño. Para la maquetación del website se ha recurrido a uno de los Frameworks CSS más populares: 960 Grid System. 83
–Adobe Photoshop CS2 para para el diseño de algunas partes de las páginas como las diversas cajas que las componen, efectos de degradados y sombras en gran multitud de elementos, composición de imágenes empleadas en la cabecera o pie de página, efectos dinámicos para los barras de navegación, diseño de tipos de letra complejas así como iconos animados repartidos a lo largo de la página. –Javascript para gobernar el comportamiento de algunas ventanas del portal, reaccionando a la acción del usuario (típicamente un evento de ratón). También se ha utilizado para integrar el código necesario para mostrar el tiempo, servicio ofrecido por 'www.tutiempo.net'. –MySQL como Base de Datos, siendo ésta de las más extendidas y eficientes en la actualidad. Aunque se ha diseñado una interfaz al uso en el mismo portal para usuarios administradores de contenidos, en ocasiones puntuales podría precisarse gestionar la Base de Datos con una herramienta externa. En este caso, se ha optado por la utilidad PHPMyAdmin, también muy extendida y con un alto grado de amigabilidad para con el usuario. La versión empleada en el momento de edición de este documento es la 5.1.36. –Servidor Web Apache, concretamente la versión 2.2.11 en el momento de edición del presente documento. Se trata sin duda de uno de los servidores más populares debido a su robustez y calidad de servicios. Es compatible sobre multitud de plataformas y se integra a la perfección con el lenguaje PHP. –Otras utilidades menores como editores de código (Komodo Edit 5) o diferentes navegadores Web (Mozilla Firefox, Opera, Google Chrome, etc) para validar las diferentes páginas. 84
A continuación serán descritas con mayor nivel de profundidad, algunas de las tecnologías citadas anteriormente. HTML, siglas de HyperText Markup Language (Lenguaje de Marcado de Hipertexto), es le lenguaje que predomina en el desarrollo de páginas web. Gracias a él, es posible no sólo describir el contenido de texto de una página web sino también su forma o estructura, permitiendo incrustar imágenes y otros objetos en la misma. La historia del estándar se remonta a principio de 1990, cuando Tim Berners-Lee define el HTML como un subconjunto de un conocido lenguaje de etiquetas denominado SGML y además crea algo más valioso aún, el World Wide Web. Este lenguaje se escribe a base de etiquetas delimitadas por corchetes angulares ( < , > ). Cuando se utiliza una etiqueta, habitualmente debe utilizarse otra de cierre, la cual antepondrá el símbolo de barra ( / ). Sirva un ejemplo: <p>Esto está escrito con una fuente normal mientras que <strong>ésto está escrito con una fuente más gruesa o negrita</strong></p> 85 Fig. 5.2.1.1. – Etiquetas empleadas por el lengujae PHP.
El párrafo anterior será mostrado como : Esto está escrito con una fuente normal mientras que ésto está escrito con una fuente más gruesa o negrita El lenguaje HTML puede ser escrito y editado con cualquier editor de textos sencillo, aunque habitualmente se emplean editores potentes que permiten visualizar el resultado de lo que se está haciendo así como identificar errores de programación. Una página web HTML debe contener una estructura mínima de etiquetas como sigue: <html> <head> <title>Aquí iría el título de la página</title> </head> <body> Aquí debe ir el contenido de la página </body> </html> El diseño en HTML debe respetar unos criterios de accesibilidad web, siguiendo unas pautas o normativas. Se encuentra disponible y desarrollado por el W3C a través de las Pautas de Accesibilidad al Contenido Web 1.0 WCAG (actualizadas recientemente con la especificación 2.0. El lenguaje HTML está algo limitado si queremos emplearlo para definir la forma de un documento, ya que no fue concebido precisamente para este fin. Aún así, durante mucho tiempo los diseñadores han debido recurrir a “trucos” para salvar esta dificultad, causando a menudo problemas en las páginas a la hora de su visualización en distintas plataformas. 86
CSS u hojas de estilo en cascada (Cascading Style Sheets), es un lenguaje usado para definir la presentación de un documento estructurado escrito en HTML. Lo que se pretende con esta tecnología es separar la estructura de una página web de su presentación, esto es, el contenido en sí a mostrar de la forma con que se desea que aparezca. CSS puede incorporarse en el mismo documento HTML o bien adjuntarse como un documento por separado (obviamente el documento HTML deberá entonces referenciarle). Enumeraremos algunas de las ventajas de CSS: •Podemos definir la forma de presentación de un website entero, de sólo una página o una porción de la misma. Se agilizan por tanto enormemente, las tareas de modificación: por ejemplo, bastaría con editar una hoja de estilo CSS para que tuviera una repercusión inmediata en todas las páginas del website. •El documento HTML es más fácil de entender, pues conseguimos con CSS separar la forma del contenido (el código que hace referencia a la forma, ya no estará entremezclado con el código restante). •Una misma página Web puede ser mostrada de forma correcta en diversos dispositivos de salida: un móvil, una impresora, una PDA. Para ello bastará con sustituir la hoja de estilo empleada. •Aumento considerable de la accesibilidad, ya que un navegador web permite a un usuario especificar su propia hoja de estilo local. Idóneo por tanto para usuarios con deficiencias visuales (hojas que aumentan el tamaño de letra o la combinación de colores). Otro de los recursos ampliamente buscados por diseñadores web y que están basados en CSS son los denominado Framewoks CSS. Éstos no son mas que declaraciones de estilos escritas en CSS que preparan y agilizan la maquetación de una página web, principalmente porque resetean y normalizan los estilos, con el fin de homogeneizar los 87
resultados (conseguimos que nuestras páginas sean mostradas del mismo modo en cualquier navegador web). Para nuestro caso en estudio, se ha empleado el Framework 960 Grid System, el cual ha despertado el interés de muchos diseñadores web, partiéndose de un diseño inicial en el editor Photoshop. Framework 960 Grid System 960 Grid System define una serie de clases que formatean nuestra página web como si de una rejilla se tratara, es decir, habilita para uso del diseñador, una plantilla o rejilla con un ancho de 960 píxeles y dividida en un número fijo de columnas (12 columnas en nuestro caso) del mismo tamaño. Una de las ventajas principales de esta división en columnas de nuestro espacio de trabajo es que permite anclar o fijar, a conveniencia del diseñador, los distintos elementos que comportarán la página web, encajando éstos de forma precisa sobre la retícula, además de conseguir un alineamiento uniforme entre los elementos. Se trata por tanto de un recurso orientado principalmente al posicionamiento. 960 Grid System permite agrupar fácilmente estas columnas para conseguir columnas mayores y así estructurar la página web en base a 2, 3 o más columnas o áreas principales, de igual o diferente tamaño cada una de ellas. De este modo, es posible formatear fácilmente una página web con un diseño por ejemplo a 3 columnas. A continuación se muestra una breve explicación de cómo sería abordado este ejemplo: –Primera columna: compuesto por 2 columnas según el Framework. Este área lo reservaremos para ubicar por ejemplo un menú vertical. –Segunda columna: compuesto por 7 columnas según el Framework. Este área lo reservaremos al cuerpo principal de la página. –Tercera columna: compuesto por 3 columnas según el Framework. Esta última columna principal o área lo reservaremos para ubicar algunas cajas pequeñas 88
mostrando información de distintas secciones. En total, según el ejemplo anterior habríamos ocupado las 12 columnas de la rejilla a nuestra conveniencia. En el caso de nuestro portal objeto de estudio, la página principal (Inicio) ha sido diseñada en base a una estructura de 3 columnas o áreas principales, mientras que el resto de páginas respetan una estructura de 2 columnas principales. Modelo de Caja CSS pone a disposición del diseñador otro recurso muy extendido que es el Modelo de Caja. Este modelo permite estructurar los diferentes contenidos de la página como si de cajas rectangulares de tratara. Cada caja puede pertenecer a un servicio (por ejemplo, el buscador), una sección (por ejemplo el apartado de noticias) o a su vez una parte de una sección (por ejemplo la fotografía de la noticia). Las cajas a su vez están compuestas por partes o capas, presentando en conjunto una estructura tridimensional. De esta forma, toda caja tiene una parte que es el borde, 89 Fig. 5.2.2.1. - Ejemplo de página web diseñada a partir de la rejilla que habilita el Framework CSS 960 Grid System (versión 12 columnas).
Komodo Edit es un entorno integrado de desarrollo (IDE) multiplataforma y multilenguaje para la elaboración de aplicaciones web dinámicas. Incluye entre otras, funciones muy demandadas en este tipo de aplicaciones como: autocompletado, comprobación de sintaxis y resaltado del lenguaje. Komodo Edit ha sido preparado para los lenguajes dinámicos PHP, Ruby, Perl, Python y TCL; también permite trabajar con XML, HTML, Javascript y CSS. La aplicación hace uso de los denominados 'calltips', menús desplegables que permite seleccionar los atributos de las diferentes etiquetas durante la edición del código. Para el proyecto que nos ocupa, Komodo Edit ha resultado ser de gran utilidad, aumentando de forma constante la legibilidad del código, gracias a sus funciones de autotabulación, coloreado y ayuda en la sintaxis. Por otro lado, se integra a la perfección con programas de FTP, por lo que podíamos subir a un proveedor de alojamiento web el archivo que estaba siendo editado y verificar los resultados de forma instantánea. 96
Posiblemente Photoshop sea una de esas herramientas que no requieren presentación alguna. Su historia se remonta a finales de los 80, cuando su creador, el recién licenciado Thomas Knoll, comenzó a trabajar en su doctorado sobre “el procesado de imágenes digitales”. Fue entonces cuando Thomas adquirió un ordenador Mac (por aquel entonces, ni tan siquiera mostraban imágenes en escala de grises) y escribió un programa llamado Display que permitiese mostrar imágenes en escala de grises empleando tramas de 1 bit (blanco y negro). Éste fue el comienzo de Photoshop; Thomas iría ampliando sus las funcionalidades de Display al mismo tiempo que iría dispersándose de su tesis doctoral. En la actualidad, Photoshop es el resultado de muchos años de investigación, reinventándose una y otra vez. Su versión más actualizada es CS5 y algunas de sus funciones más recientes especialmente interesantes en un entorno web son: –Creación de logotipos, botones web e ilustraciones 3D desde cualquier capa de texto, selección, trazado o máscara de capa y, a continuación, es posible torcer, rotar, extrujar, biselar e inflar los diseños. 97 Fig. 5.3.2.1. - Captura de la aplicación Komodo Edit
–Selección extremadamente fácil de elementos intrincados de la imagen, como el pelo, para perfeccionarlos, componerlos o colocarlos en una composición. –Deformación o estiramiento de gráficos, texto o elementos de la imagen con precisión con el fin de crear apariencias únicas para los diseños web. –Servicio online que añaden comentarios a las imágenes desde el navegador web de un usuario y estos aparecerán inmediatamente en su pantalla. –Creación de bjetos y diseños 3D con una sencilla creación de sombras, luces basadas en la imagen y materiales como cristal y cromo. –Multitud de efectos novedosos, entre ellos, efectos pictóricos realistas y naturales con el pincel mezclador, que ofrece la posibilidad de fusionar colores en lienzos. 98 Fig. 5.3.3.1. - Captura de la aplicación Adobe Photoshop
En nuestro caso de estudio, fue utilizado Photoshop con los siguientes objetivos principales: –diseño de cabeceras y pies de página, realizando fotomontajes y fusión de varias fotografías, añadiendo textos y aplicando diversos efectos. –diseño de las diferentes cajas que muestran la información de una sección o subsección en particular, así como la caja de búsquedas. –diseño de algunos tipos de letra complejos que no era posible obtener mediante HTML+CSS. –diseño de iconos animados (GIF). –optimización de la calidad en relación al espacio en bytes ocupado por cada uno de los elementos gráficos incluidos en una página web (optimización tiempos de carga sin merma visual aparente), en función del formato gráfico más adecuado a cada contexto. –diseño de los efectos dinámicos utilizados en las barras de navegación (elemento activo, elemento no seleccionado, etc). FileZilla es un cliente FTP, gratuito, libre (GNU) y de código abierto. Se trata por tanto de una aplicación que permite transferir archivos, conectándose para ello a un servidor FTP. La vista de archivo y carpeta, situada debajo del registro de mensajes, proporciona una interfaz gráfica amigable. Los usuarios pueden navegar por las carpetas, ver y alterar sus contenidos tanto en la máquina local como en la remota, utilizando una interfaz de tipo árbol de exploración. Los usuarios pueden arrastrar y soltar archivos entre los ordenadores local y remoto. 99
Empleamos este cliente FTP en nuestro caso de estudio, fundamentalmente con el objetivo de ir subiendo a un servidor que ofreciese alojamiento web, las diferentes partes del portal conforme éstas eran programadas, pudiendo verificar de esta forma si todas ellas cumplían y se comportaban según lo esperado. Por otro lado, FileZilla se integró a la perfección con la aplicación de edición de código Komodo Edit, lo que aún facilitó más esta labor. 100 Fig. 5.3.4.1. - Captura de la aplicación FileZilla
Atendiendo a la estructura de 3 niveles que fue definida en un capítulo anterior y una vez revisados de forma general aquellos recursos y tecnologías web a los que se ha recurrido, se describirá de forma concisa cómo han sido implementadas estas tecnologías para el caso que nos ocupa. La elaboración del interfaz puede iniciarse mediante aspectos básicos de presentación como ahora un “blueprint” (Rosenfeld, 2002) o retícula (véase Figura 5.4.1.1) que pone de manifiesto las diferentes áreas en que puede dividirse la página principal del portal. 101 Fig. 5.4.1.1. – Esquema de contenidos del la aplicación Portal Web de Ayuntamiento.
La retícula ilustra las principales secciones del portal y sus contenidos, basándose en una estructura jerárquica aunque no se ha utilizado una notación concreta para representar sus componentes. Tomando la retícula anterior como punto de partida, se representa el diseño de la página Web mediante un formato de documento HTML (véase Figura 5.4.1.2.) basado en elementos de tipo “capa” (<div>). El diseño original se efectuó en el editor gráfico Photoshop, siendo trasladado posteriormente a lenguaje HTML junto con CSS. Se describen a continuación algunas de las partes relevantes en que se divide el diseño, junto con la estrategia buscada, incluyendo la página en sí de forma global: Página principal (Inicio) La página principal muestra un compendio sintetizado de las secciones principales que pueden encontrarse a lo largo del portal. Presenta un aspecto visual dinámico, conteniendo diversos iconos animados que invitan a participar en alguna de las secciones, para lo que previamente habrá que autenticarse en el portal. El dinamismo se consigue también integrando una pequeña área dedicada a una galería fotográfica en la misma cabecera donde es exhibido el título del portal. Se ha buscado una combinación de colores uniforme, basándose principalmente en variaciones y degradados del color azul, prevaleciendo tonalidades suaves. El diseño de las diferentes cajas que muestran la información propia de cada sección, responden a un patrón de diseño similar, pudiéndose detectar sutiles variaciones. El escudo del ayuntamiento dispondrá de una ubicación fija ubicada en la columna izquierda. Menú Superior En la parte superior izquierda, sobre la cabecera, se muestra se muestra un menú con enlaces a apartados del portal de relevancia secundaria: Inicio, Mapa Web y Contacto o Sugerencias. Cuando el usuario autenticado sea Funcionario, este menú le permitirá además visualizar el portal como si de un usuario No Funcionario se tratase. 102
103 Fig. 5.4.1.2. – Ejemplo de diseño de la página principal de la aplicación Portal Web de Ayuntamiento.
Fecha En la parte superior derecha es mostrada la fecha actualizada, junto con el nombre del día de la semana. Cabecera (Fig. 5.4.1.3) Muestra una panorámica de uno de los monumentos más emblemáticos de Paterna, la Torre, junto con una dibujo caricaturizando al motivo de la fiesta más popular del pueblo, la Cordá. Finalmente, existe una parte dinámica con fotografías del pueblo que van siendo mostradas sucesivamente. Cuerpo o área de contenidos Área principal dedicada a mostrar de forma sintetizada una porción de las diversas secciones principales del portal, esto es, noticias, eventos y foros. En el caso de cualquier otra página distinta de la principal, este área se dedicará exclusivamente a mostrar la información propia de esa sección. Subsecciones (Secciones al detalle) (Fig. 5.4.1.4) Área disponible únicamente en la página principal, en la parte inferior justo precediendo al pié de página. Su cometido es mostrar un resumen de los últimos elementos introducidos en el portal referente a impresos, oposiciones o usuarios registrados en la Comunidad. 104 Fig. 5.4.1.3 – Cabecera del portal
En la Figura 5.4.1.5. se muestra una relación de elementos <div> empleados en el diseño de la página principal, comenzando con la capa principal que “anida” al resto de capas. Conviene destacar que el tamaño de éstas, está especificado como “automático”, representando de este modo el hecho de que están anidadas o incluidas en la capa principal. 105 Fig. 5.4.1.4 – Secciones al detalle de la página principal
asocia un enlace a la página web que contiene dicha sección (el valor “apuntado” por la clave). Para resolver el apartado dinámico (se resalta la sección actual con un efecto tipo “pestaña”), se recurre a variables enviadas mediante el método GET. De este modo, cuando se imprime cada opción del menú asociándosele un enlace a la página web de la sección a que corresponde, se añade además a la parte final del enlace, una variable de nombre 'pag' cuyo valor será precisamente la clave del elemento en cuestión (esto es, el título de la opción del menú). De esta forma, antes de imprimir cada opción del menú se revisa el valor de 'pag' enviado a través del método GET y se le asigna la clase CSS 'current_page_item' sólo en el de coincidir con la sección actual. Esta clase CSS contiene precisamente la descripción de cómo debe mostrarse un elemento activo del menú, esto es, el efecto de resaltado referido antes. #top-nav a:hover { text-decoration: underline; font-size: 150%; } #top-nav ul { padding: 0; } #top-nav li { padding-left: 10px; } #navi { height: 60px; } #navi, #navi ul { list-style: none; line-height: 1; z-index: 100; padding: 0; } #navi a { display: block; line-height: 25px; z-index: 100; padding: 0 10px; color:#000; font-size: 14px; font-weight: 700; } #navi li { float: left; line-height: 30px; margin: 0; } #navi li a { color:#fff; text-decoration: none; padding: 0 0 0 16px; text-shadow: 0 1px #18344b; font-size: 140%; } #navi li a span { display: inline-block; height:30px; padding: 5px 15px 5px 5px; } #navi li a: hover, #navi li.active a, #navi li.current_page_item a { background: url(../images/top-nav-left.png) no-repeat left; color: #fdd967; cursor: pointer; text-decoration: none; } #navi li.active a span, #navi li.current_page_item a span, #navi li a: hover span { background: url(../images/top-nav-largo.png) no-repeat right; text-shadow: 0 2px #222; } 112 Fig. 5.4.1.12 – Implementación CSS para la barra de navegación principal
Algunos aspectos a destacar del código CSS mostrado en la Figura 5.4.1.12 son: –la definición de la imagen de fondo a utilizar para el resaltado de la opción del menú. Es preciso dividir la imagen en 2 partes (izquierda y derecha). De esta forma, la misma puede crecer para adaptarse a la longitud de cualquier palabra. –la disposición en horizontal de la lista que contiene los elementos de la barra de navegación. –la definición del efecto de sombra para los títulos de las diferentes opciones del menú. Menú Información Ayuntamiento, Municipio y Servicios (INFO. AYTO) (Fig. 5.4.1.13) Sobre la columna izquierda se dedica un área a la parte más estática del portal, esto es, enlaces a la información sobre el Ayuntamiento, el Municipio y los Servicios. Se utiliza para ello un menú vertical dinámico implementado siguiendo la misma estrategia que fue mostrada para el menú horizontal principal. Menú opciones usuarios Fig. 5.4.1.14) En aquellos apartados que requieren interacción con el Usuario (tramitaciones, participar en foros, etc), serán mostrados enlaces a las diversas opciones posibles de actuación. Estas opciones cambiarán en función de la sección en que se encuentre el usuario así como de los privilegios de que disponga el mismo. Se comprueba con este fin el valor de la variable de sesión 'categoria'. Menú pie de página (Fig. 5.4.1.15) El pie de página contiene una repetición de enlaces a los apartados o servicios de mayor popularidad además de una imagen panorámica de fondo que exhibe una de las zonas más turísticas del pueblo: la Torre de Paterna. 113
114 Fig. 5.4.1.13 – Menu Info. Ayto (parte estática) Fig. 5.4.1.15 – Enlaces a pie de página Fig. 5.4.1.14 – Menú de opciones de usuario
Buscador (Fig. 5.4.1.16) El buscador ha sido integrado en una caja como muestra la imagen. El mismo dispondrá de 2 versiones: una simple que será mostrada para la página principal y otra más avanzada, que será mostrada en el resto de páginas. La versión avanzada permitirá al usuario limitar la búsqueda a la sección actual o bien iniciarla en todo el portal. Usuarios (Fig. 5.4.1.17) Caja que permite autenticarse, así como también mostrar la información referente al usuario autenticado y otras opciones (modificar su perfil, cerrar la sesión). Se trata de un elemento destacado que siempre dispondrá de una ubicación fija, habitualmente preferente en la columna derecha (página principal) o bien izquierda (resto de páginas). En este apartado, se expondrán algunas secciones de código que implementan las funciones o procesos que forman parte del nivel de Negocio. Por cuestiones obvias de extensión, únicamente se plasman aquéllas cuya relevancia sea destacada. 115 Fig. 5.4.1.17 – Caja dedicada al apartado Usuarios Fig. 5.4.1.6 – Caja del buscador en su versión avanzada.
Visualización de la página principal. Reubicación dinámica de las cajas. La página principal contendrá 5 cajas dedicadas a diversas secciones, cuya ubicación no será fija sino dinámica. La posición que ocupen dentro de la página principal estará relacionada con la frecuencia con que el usuario ha visitado antes cada una de esas secciones (ubicación más arriba para cajas con mayor puntuación). El área principal de contenidos contendrá 3 de esas cajas dinámicas, concretamente las dedicadas Noticias, Eventos y Foros, mientras que la columna lateral derecha contendrá las 2 cajas restantes, en este caso, las dedicadas a las secciones El Tiempo y Callejero. Estas cajas aparecerán por orden de preferencia (arriba las de las secciones más visitadas por el usuario). Cada vez que un usuario visita una sección de las 5 citadas anteriormente, es aumentado el contador asociado a la sección en cuestión. Los contadores se encuentran almacenados en la Base de Datos, en la tabla 'preferencias_usuarios'. El código de la función que aumenta el contador de una sección, se muestra a continuación, así como el código de la función que limita el valor máximo que puede alcanzar un contador (para evitar que los contadores alcance valores innecesariamente elevados): function resetear_preferencias() { //divide entre 10 el contador de cada sección $obtener_prefer_sql = "SELECT noticias, eventos, foros, tiempo, callejero FROM preferencias_usuarios WHERE username = '".$_SESSION["username"]."'"; $mysqli = doDB(); $obtener_prefer_res = mysqli_query($mysqli, $obtener_prefer_sql) or die(mysqli_error($mysqli)); $prefer_info = mysqli_fetch_array($obtener_prefer_res); foreach( $prefer_info as $variable => $valor ) { $prefer_info[$variable] = ceil($prefer_info[$variable] / 10); // ceil calcula la div entera, redondeando por arriba } $actualizar_prefer_sql = "UPDATE preferencias_usuarios SET noticias = $prefer_info[0], eventos = $prefer_info[1], foros = $prefer_info[2], tiempo = $prefer_info[3], callejero = $prefer_info[4] WHERE username = 116
'".$_SESSION["username"]."'"; $actualizar_prefer_res = mysqli_query($mysqli, $actualizar_prefer_sql) or die(mysqli_error($mysqli)); mysqli_free_result($obtener_prefer_res); mysqli_free_result($actualizar_prefer_res); mysqli_close($mysqli); } // end of function resetear_preferencias() function aumentar_preferencias($seccion) { $obtener_preferencias_sql = "SELECT $seccion FROM preferencias_usuarios WHERE username = '".$_SESSION["username"]."'"; $mysqli = doDB(); $obtener_preferencias_res = mysqli_query($mysqli, $obtener_preferencias_sql) or die(mysqli_error($mysqli)); $preferencias_info = mysqli_fetch_array($obtener_preferencias_res); if ($preferencias_info[0] == 9999) { // limitamos el valor máximo de un contador a 10.000. Cuando alguno alcance este valor, se dividen todos entre 10. $nuevo_ranking = 1000; resetear_preferencias(); } else $nuevo_ranking = $preferencias_info[0] + 1; $actualizar_preferencias_sql = "UPDATE preferencias_usuarios SET $seccion = $nuevo_ranking WHERE username = '".$_SESSION["username"]."'"; $actualizar_preferencias_res = mysqli_query($mysqli, $actualizar_preferencias_sql) or die(mysqli_error($mysqli)); mysqli_free_result($obtener_preferencias_res); mysqli_free_result($actualizar_preferencias_res); mysqli_close($mysqli); } // end of function aumentar_preferencias() Se muestra a continuación el código de la función encargada de obtener los contadores asociados a las cajas del área principal de contenidos (se ha obviado representar el código que realiza la misma función sobre las cajas del área lateral 117
derecho, por ser análogo). La función devuelve un vector ordenado de mayor a menor preferencia de la sección en cuestión. function obtener_prefs_cajagran() { //obtiene un vector con las cajas grandes de la zona central del website, ordenadas de mayor a menor preferencias según el usuario consulte más unas cajas u otras. Las primeras del vector serán las más visitadas por el usuario. $obtener_prefsgran_sql = "SELECT noticias, eventos, foros FROM preferencias_usuarios WHERE username = '".$_SESSION["username"]."'"; $mysqli = doDB(); $obtener_prefsgran_res = mysqli_query($mysqli, $obtener_prefsgran_sql) or die(mysqli_error($mysqli)); $info_prefsgran = mysqli_fetch_assoc($obtener_prefsgran_res); arsort($info_prefsgran); return $info_prefsgran; mysqli_free_result($obtener_prefsgran_res); mysqli_close(); } // end of fuction obtener_prefs_cajagran() Una vez obtenido el vector, desde la página principal se recorre cada uno de sus elementos y para cada uno de ellos, se invoca a la función que imprime por pantalla la caja con sus contenidos de la sección indicada por el elemento en cuestión. function imprimir_prefs_cajasgran($seccion) { $salida_php = " <div class=\"cajagrande\"> <div class=\"cajagrande_arriba\">"; switch($seccion) { case 'noticias': $obtener_noticias_sql = "SELECT id, titular, texto, imagen, fecha FROM noticias ORDER BY fecha DESC LIMIT 0, 3"; // obtenemos las 3 noticias más recientes para mostrarlas en la página principal del website 118
$mysqli = doDB(); $obtener_noticias_res = mysqli_query($mysqli, $obtener_noticias_sql) or die(mysqli_error($mysqli)); $salida_php .= " <h3>Últimas Noticias</h3> </div> <div class=\"cajagrande_centro\">"; $noticia_info = mysqli_fetch_array($obtener_noticias_res); $noticia_imagen = "noticias/".$noticia_info['imagen']; $noticia_titular = $noticia_info['titular']; $fecha_temp = explode(" ", $noticia_info['fecha']); $fecha_temp = explode("-", $fecha_temp[0]); $noticia_fecha = $fecha_temp[2].".".$fecha_temp[1].".".$fecha_temp[0]; $noticia_texto = $noticia_info['texto']; $salida_php .= " <p><strong>$noticia_titular</strong><br> <span style=\"font-size:90%;font-style:italic;\">$noticia_fecha</span> <img src=\"$noticia_imagen\" width=\"200\" height=\"205\" alt=\"Foto_noticia\" class=\"imagen_noticia\" /> <div class=\"texto_noticia\"> $noticia_texto </div></p>"; while ($noticia_info = mysqli_fetch_array($obtener_noticias_res)) { $noticia_titular = $noticia_info['titular']; $noticia_id = $noticia_info['id']; $fecha_temp = explode(" ", $noticia_info['fecha']); $fecha_temp = explode("-", $fecha_temp[0]); $noticia_fecha = $fecha_temp[2].".".$fecha_temp[1].".". $fecha_temp[0]; $salida_php .= " <hr><p> --> <strong><a href=\"javascript:eventWindow ('detalles_noticia.php?id=$noticia_id')\">".$noticia_fecha." - ". $noticia_titular."</strong></a></p>"; } mysqli_free_result($obtener_noticias_res); $salida_php .= " <hr><p> > > > > > > <span style=\"font-size:120%;\"><strong><a href=\"noticias_public.php?pag=NOTICIAS\"> VER TODAS LAS NOTICIAS 119
</strong></span></a> < < < < < < < </p>"; break; case 'eventos': $obtener_eventos_sql = "SELECT id, titulo_evento, inicio_evento FROM calendario_eventos ORDER BY inicio_evento DESC LIMIT 0, 5"; $mysqli = doDB(); $obtener_eventos_res = mysqli_query($mysqli, $obtener_eventos_sql) or die(mysqli_error($mysqli)); $salida_php .=" <h3>Últimos Eventos</h3> </div> <div class=\"cajagrande_centro\"> <p>"; while ($evento_info = mysqli_fetch_array($obtener_eventos_res)) { $evento_id = $evento_info['id']; $evento_titular = $evento_info['titulo_evento']; $fecha_temp = explode(" ", $evento_info['inicio_evento']); $fecha_temp = explode("-", $fecha_temp[0]); $evento_inicio = $fecha_temp[2].".".$fecha_temp[1].".". $fecha_temp[0]; $salida_php .= " <p><strong> <a href=\"javascript:eventWindow('detalles_evento.php?id= $evento_id')\">$evento_inicio: <span style=\"font-size:120%;\"> $evento_titular</a></strong></p><hr>"; } $salida_php .= " <p> > > > > > > <span style=\"font-size:120%;\"><strong> <a href=\"agenda_public.php?pag=AGENDA\"> VER TODOS LOS EVENTOS </strong></span></a> < < < < < < < </p></p>"; mysqli_free_result($obtener_eventos_res); break; 120
case 'foros': $obtener_posts_sql = "SELECT post_texto, post_fecha, post_prop FROM foro_posts ORDER BY post_fecha LIMIT 0, 3"; $mysqli = doDB(); $obtener_posts_res = mysqli_query($mysqli, $obtener_posts_sql) or die(mysqli_error($mysqli)); $salida_php .= " <h3>Mensajes Foros</h3> </div> <div class=\"cajagrande_centro\"> <p>"; while ($post_info = mysqli_fetch_array($obtener_posts_res)) { $post_texto = $post_info['post_texto']; $fecha_temp = explode(" ", $post_info['post_fecha']); $fecha_temp = explode("-", $fecha_temp[0]); $post_fecha = $fecha_temp[2].".".$fecha_temp[1].".".$fecha_temp[0]; $post_prop = $post_info['post_prop']; $salida_php .= " <p><strong><span style=\"color:#951316; font-size:90%;\"> $post_texto</span></strong><br> <span style=\"font-style:italic;font-size:80%;\"> <br>Posteado por: $post_prop con fecha: $post_fecha</p><hr>"; } $salida_php .= " <p> > > > > > > <span style=\"font-size:120%;\"><strong> <a href=\"foros_user.php?list_topics?pag=FOROS\"> IR a los FOROS </strong></span></a> < < < < < < < </p></p>"; mysqli_free_result($obtener_posts_res); break; }; $salida_php .= " </div> <!-- end of cajacentro --> <div class=\"cajagrande_abajo\"></div> </div> <!-- end of cajagrande -->"; echo $salida_php; mysqli_close(); } //end of function imprimir_prefs_cajasgran($seccion) 121
$mysqli = doDB(); $obtener_eventos_res = mysqli_query ($mysqli, $obtener_eventos_sql) or die(mysqli_error($mysqli)); } $obtener_subscriptores_sql = "SELECT email FROM usuarios, preferencias_usuarios WHERE usuarios.username = preferencias_usuarios.username AND newsletter='total'"; $salida_newsletter = "<h1>Newsletter Noticias y Eventos</h1>"; if ($ptes_global_noticias > 0) while ($noticia_info = mysqli_fetch_array($obtener_noticias_res)) { $titular = $noticia_info["titular"]; $texto = $noticia_info["texto"]; $imagen = "/pfc/noticias/".$noticia_info["imagen"]; $fecha = $noticia_info["fecha"]; $salida_newsletter .= " <h3>Noticia: $titular<br> <strong style=\"font-size:60%\">$fecha</strong></h3> <img src=\"$imagen\" width=\"256\" alt=\"Foto_noticia\"> <p>$texto</p><hr>"; } if ($ptes_global_eventos > 0) while ($evento_info = mysqli_fetch_array($obtener_eventos_res)) { $titulo_evento = $evento_info["titulo_evento"]; $desc_evento = $evento_info["desc_evento"]; $inicio_evento = $evento_info["inicio_evento"]; $salida_newsletter .= " <h3>Evento: $titulo_evento<br> <strong style=\"font-size:60%\">$inicio_evento</strong></h3> <p>$desc_evento</p><hr>"; } while ($susbcriptor_info = mysqli_fetch_array($obtener_subscriptores_res)) { $headers .= $susbcriptor_info['email'].","; } } $headers .="\r\n"; mail($para, $asunto, $salida_newsletter, $headers); 128
mysqli_free_result($obtener_noticias_res); mysqli_free_result($obtener_eventos_res); mysqli_free_result($obtener_subscriptores_res); mysqli_close($mysqli); } //FIN function enviar_newsletter() Autenticación de usuarios y cierre de sesión. Un usuario anónimo puede autenticarse empleando un sencillo formulario de dos campos (Username y Password) desde cualquier página del portal. En todas ellas, estará disponible el área de Usuarios. La primera comprobación que el sistema efectúa al recibir el formulario, es verificar que exista una variable de tipo oculta (hidden). En caso de existir, contrasta si existe en la Base de Datos, alguna coincidencia con los datos enviados por el usuario. Una vez hallada coincidencia, se inicializan diversas variables de sesión con los datos de consulta más frecuentes sobre el usuario (a destacar aquélla que indica que existe algún usuario autenticado o bien, aquélla que informa sobre los privilegios del mismo ). Una vez ha sido validado el usuario, si éste es del tipo funcionario, se le reenvía a la página de administración de contenidos. Para el resto de usuario, serán remitidos a la página desde la cual efectuaron la autenticación, mostrando además las opciones a que tenga derecho según su categoría (por ejemplo, para un usuario de tipo Residencial, se habilitará la opción del menú principal 'Oficina Virtual'). En caso de que no se hallara coincidencia en la Base de Datos, se remite al usuario a la página principal, informándole además de los motivos. Por otro lado, el sistema también se encarga de desconectar o cerrar la sesión de un usuario previamente autenticado, si así lo hubiera solicitado. En este caso, el sistema recibirá una variable de nombre 'logout' mediante el método GET, desasignando a 129
continuación todas las variables de sesión existentes, así como también eliminando el fichero que almacena el identificados de sesión. Por último, el usuario es remitido a la página principal. /*comprobamos que el usuario ha intentado autenticarse de forma no malintencionada (en cuyo caso, se recibirá la variable login de tipo hidden)*/ if (isset($_POST["login"])) { eliminar_tags(); $user = $_POST['username']; $psw = $_POST['password']; //se comprueba que exista coincidencia en la BD $buscar_user_sql = "SELECT username, categoria, nombre, apellido1, email FROM usuarios WHERE username='".$user."' and password=PASSWORD('".$psw."')"; doDB(); $buscar_user_res = mysqli_query($mysqli, $buscar_user_sql) or die(mysqli_error($mysqli)); if ( mysqli_num_rows($buscar_user_res) > 0 ) { /*inicializamos una variable de sesión, que indicará al sistema que existe un usuario autenticado*/ $_SESSION["autenticado"] = "1"; //se almacenan los datos de frecuente consulta en variables de sesión while ($user_info = mysqli_fetch_array($buscar_user_res)) { $_SESSION["username"] = $user_info['username']; $_SESSION["categoria"] = $user_info['categoria']; $_SESSION["nombre_comp"] = $user_info['nombre']." ". $user_info['apellido1']; $_SESSION["email"] = $user_info['email']; mysqli_free_result($buscar_user_res); mysqli_close($mysqli); } //se remite al usuario a la página convenida, atendiendo a sus privilegios if ( $_SESSION["categoria"] == "ADM" || $_SESSION["categoria"] == "INT" ) { header("Location: index_admin.php"); } else switch($_POST["login"]) { 130
case "noticias": header("Location: noticias_public.php?pag= NOTICIAS"); break; case "agenda": header("Location: agenda_public.php?pag= EVENTOS"); break; case "tramites": if ($_SESSION["categoria"] == "RES") header("Location: tramites_user.php?pag= OFIC. VIRTUAL"); else header("Location: tramites_public.php?pag= TRAMITES"); break; case "foros": header("Location: foros_user.php?pag= FOROS"); break; default: header("Location: saludo.php?pag=INICIO"); break; }; } else { //el usuario no ha sido encontrado en la base de datos $_SESSION["autenticado"] = "0"; header("Location: index.php?pag=INICIO"); } session_write_close(); /*termina la sesión, forzando el almacenamiento de los datos de sesión. Útil para accesos concurrentes.*/ } if (isset($_GET["logout"])) { //un usuario ha solicitado desconectarse session_unset(); // desasigna las variables de sesión session_destroy(); //termina sesión y borra su archivo header("Location: index.php?logout&pag=INICIO"); } 131
Gestión de tramitaciones (Oficina Virtual). Los usuarios de tipo Residencial pueden iniciar y gestionar tramitaciones de aquellos trámites que estén disponibles para gestión online. El modus operandi es sencillo: el usuario inicia una tramitación, adjuntando si lo desea una notificación u observación, tras lo cual, un usuario funcionario recogerá esa tramitación, aceptándola o rechazándola (dándose por concluida) o bien requiriendo alguna información del usuario residencial (en cuyo caso, adjuntará una notificación). Por tanto, una tramitación dispondrá de un historial de notificaciones, en algunos casos, como medio de “conversación” entre usuario residencial y funcionario. Se muestra a continuación un extracto de código, el cual muestra la primera fase del proceso, donde se exhibe al usuario residencial un formulario informando de la tramitación que está a punto de iniciar, solicitando su confirmación. En caso de que el usuario confirme, el sistema insertará la nueva tramitación en la Base de Datos, adjuntando asimismo la notificación, en caso la hubiere. if ( $_SESSION["categoria"] == "RES" ) { if ( !isset($_POST["confirmar"]) && !isset($_POST["cancelar"]) ) { $id = $_GET["id"]; $nombre = $_GET["nombre"]; $importe = $_GET["importe"]; $salida_php = " <h2>Trámite ID: $id <br>$nombre</h2><p><strong>Importe: $importe €</strong> <p><form action=\"".$_SERVER["PHP_SELF"]."\" method=\"POST\"> <strong>A continuación indique las observaciones que desee adjuntar como anexo a la tramitación:</strong><br><br> <textarea cols=\"53\" rows=\"8\" name=\"notificaciones\"></textarea> <input type=\"hidden\" name=\"id\" value=$id><br><br> <input type=\"submit\" name=\"confirmar\" value=\"Confirmar\"> <input type=\"submit\" name=\"cancelar\" value=\"Cancelar\"></form>"; } else { if (isset($_POST["confirmar"])) { eliminar_tags(); 132
$notif = "<span style=\"color:#024b8b; font-weight:bold;\">". $_POST["notificaciones"]."</span>"; $id = $_POST["id"]; $fecha = getdate(); $fecha = $fecha[mday]."-".$fecha[mon]."-".$fecha[year]; $notificaciones = "<ul><li>Usuario \"".$_SESSION["username"]."\" con Fecha ".$fecha.", informa que:<ul><li>\"".$notif."\"</li></ul></li></ul>"; $insertar_tramitacion_sql = "INSERT INTO tramites_usuarios (id_tram, username, fecha, estado, hist_notificaciones) VALUES ('$id', '".$_SESSION["username"]."', now(), 'Iniciado', '$notificaciones')"; doDB(); $insertar_tramitacion_res = mysqli_query($mysqli, $insertar_tramitacion_sql) or die(mysqli_error($mysqli)); $salida_php .= " <h2>Tramitación enviada correctamente. En breve, será revisada y actualizado su estado</h2> <p><a href=# onClick=\"window.close()\">Cerrar</a></p>"; } if (isset($_POST["cancelar"])) $salida_php .= " <h2>Tramitación cancelada</h2> <p><a href=# onClick=\"window.close()\">Cerrar</a></p>"; } mysqli_free_result($insertar_tramitacion_sql); mysqli_close($mysqli); } else echo "<h2>Debes identificarte para poder acceder a Oficina Vitual</h2>"; Se describe a continuación el código relevante que forma parte de la segunda fase de una tramitación. El sistema recurre a esta implementación, tanto en el caso de un usuario funcionario que haya solicitado modificar el estado de la tramitación iniciada en la primera fase o bien, en el caso de un usuario residencial que haya solicitado incorporar alguna notificación a la misma. 133
if ( $_SESSION["categoria"] == "ADM" || $_SESSION["categoria"] == "INT" || $_SESSION["categoria"] == "RES" ) { if (isset($_GET["id"])) $id = $_GET["id"]; if (isset($_POST["id"])) $id = $_POST["id"]; //se obtiene el historial de notificaciones asociado a la tramitación $obtener_notificaciones_sql = "SELECT hist_notificaciones FROM tramites_usuarios WHERE id = '$id'"; doDB(); $obtener_notificaciones_res = mysqli_query($mysqli, $obtener_notificaciones_sql) or die(mysqli_error($mysqli)); if (mysqli_num_rows($obtener_notificaciones_res) > 0) { $notif_info = mysqli_fetch_array($obtener_notificaciones_res); $hist_notificaciones = $notif_info["hist_notificaciones"]; } else $hist_notificaciones = "No existen notificaciones"; //si el usuario aún no ha enviado el formulario, se le muestra if ( !isset($_POST["confirmar"]) && !isset($_POST["cancelar"]) ) { $id = $_GET["id"]; $username = $_GET["us"]; $estado = $_GET["es"]; $salida_php = " <h2>Usuario: $username<br>Estado actual: $estado</h2> <form action=\"".$_SERVER["PHP_SELF"]."\" method=\"POST\"> <h3>Histórico notificaciones:</h3> <div id=\"notific_modif_tramitacion\"> $hist_notificaciones </div><br><br>"; if ($_SESSION["categoria"] != "RES") //para usuarios funcionarios $salida_php .= " <h3>Indique un nuevo estado para la<br>tramitación:</h3> <input type=\"radio\" name=\"nuevo_estado\" value=\"Revision\" checked> Revisión <input type=\"radio\" name=\"nuevo_estado\" value=\"Aprobado\"> Aprobado 134
<input type=\"radio\" name=\"nuevo_estado\" value=\"Denegado\"> Denegado"; $salida_php .= " <br><br><strong>Información a notificar :</strong><br> <textarea cols=53 rows=8 name=\"nueva_notificacion\"></textarea> <input type=\"hidden\" name=\"id\" value=$id><br><br> <input type=\"submit\" name=\"confirmar\" value=\"Confirmar\"> <input type=\"submit\" name=\"cancelar\" value=\"Cancelar\">"; } else { //el usuario ha enviado el formulario if (isset($_POST["confirmar"])) { eliminar_tags(); /*las notificaciones de un usuario funcionario tendrán un texto de diferente color que las de un usuario residencial*/ $nueva_notif = "<span style=\"color:#"; if ($_SESSION["categoria"] != "RES") $nueva_notif .="024b8b"; else $nueva_notif .="46754f"; $nueva_notif .= "; font-weight:bold;\">".$_POST["nueva_notificacion"]."</span>"; $id = $_POST["id"]; $fecha = getdate(); $fecha = $fecha[mday]."-".$fecha[mon]."-".$fecha[year]; if ($_SESSION["categoria"] != "RES") $hist_notificaciones .= "<ul><li>Funcionario \"".$_SESSION["username"]."\" con Fecha ".$fecha.", notifica que:<ul><li>\"".$nueva_notif. "\"</li></ul></li></ul>"; else $hist_notificaciones .= "<ul><li>Usuario \"".$_SESSION["username"]."\" con Fecha ". $fecha.", notifica que:<ul><li>\"".$nueva_notif. "\"</li></ul></li></ul>"; $actualizar_tramitacion_sql = "UPDATE tramites_usuarios SET hist_notificaciones = '$hist_notificaciones'"; if ($_SESSION["categoria"] != "RES") $actualizar_tramitacion_sql .= ", estado = '".$_POST["nuevo_estado"]."'"; $actualizar_tramitacion_sql .= " WHERE id = '$id'"; 135
doDB(); $actualizar_tramitacion_res = mysqli_query($mysqli, $actualizar_tramitacion_sql) or die(mysqli_error($mysqli)); $salida_php .= " <h2>Tramitación modificada</h2> <p><a href=# onClick=\"window.close()\">Cerrar</a></p>"; } if (isset($_POST["cancelar"])) $salida_php .= " <h2>Modificación cancelada</h2> <p><a href=# onClick=\"window.close()\">Cerrar</a></p>"; } } else $salida_php = "<h2>No dispones de permisos para acceder a este recurso.</h2>"; mysqli_free_result($actualizar_tramitacion_res); mysqli_free_result($obtener_notificaciones_res); mysqli_close($mysqli); Como se observa en la implementación anterior, las notificaciones van siendo incrementadas y posteriormente actualizadas, haciéndose valor para ello de un único campo de una tupla (tabla 'tramites_usuario') en la Base de Datos. Se recurre a una tipología de letra de diferente color, entre otros, con el fin de aumentar la legibilidad del histórico de conversaciones (notificaciones) entre usuario residencial y funcionario. Cabe destacar que el código con las acciones a adoptar por el sistema, tanto para el caso de un usuario funcionario como residencial, se encuentra entremezclado, decidiéndose sobre la marcha qué “camino” seguir, en base a sencilla instrucciones condicionales. De este modo, el formulario mostrado tanto al usuario residencial como al funcionario es análogo, con la diferencia de que el primero únicamente tendrá una opción disponible, la de adjuntar una notificación, mientras que el usuario funcionario podrá además alterar el estado de la tramitación. Cualquier modificación efectuada tanto por uno como por otro, podrá ser inmediatamente visualizada tras confirmar la misma. 136
Contraseña olvidada. Recuperación. Aquellos usuarios que no recuerden la contraseña para autenticación, podrán en cualquier instante solicitar una nueva. Bastará para ello ingresar el Username y Email. El modus operandi implementado es el siguiente : El sistema verifica que existe una coincidencia en la Base de Datos para los datos ingresados por el usuario en el formulario. Si no existe la incidencia, se informa al usuario de los motivos (el Email introducido no se corresponde con la contraseña, o bien el Username no existe, etc) y se le invita a volver a intentarlo. Si después de la verificación anterior, se encuentra una coincidencia, se genera una nueva contraseña a partir de una palabra seccionada al azar de un diccionario (almacenado en un fichero) con miles de palabras en inglés. Además, para aumentar la seguridad de la contraseña, se le adicionará al final de la misma, un número aleatorio de 3 dígitos. Finalmente, la contraseña es enviada al usuario por correo y actualizada en la Base de Datos, previo a su encriptado. if (isset($_POST["form_resetpsw_enviado"])) { //si el usuario ha enviado el formulario try { if (empty($_POST["username"])) throw new Exception('Debe introducir un username.'); if (empty($_POST["email"])) throw new Exception('Debe introducir un email.'); } catch (Exception $e) { echo "<p><span style=\"font-size:150%; color:#a5271a;\";>ERROR: ". $e->getMessage()."</span><p>"; } if (empty($e)) { /*si no hay errores, se verifica que el usuario exista, aprovechando además para obtener su email, que será reutilizado más tarde*/ $obtener_email_sql = "SELECT email FROM usuarios WHERE username = '".$_POST["username"]."'"; doDB(); $obtener_email_res = mysqli_query($mysqli, $obtener_email_sql) or 137
while ($evento_info = mysqli_fetch_array($obtener_eventos_res)) { $evento_id = $evento_info['id']; $evento_titulo = $evento_info['titulo_evento']; $fecha_temp = explode(" ", $evento_info['inicio_evento']); $fecha_temp = explode("-", $fecha_temp[0]); $inicio_evento = $fecha_temp[2].".".$fecha_temp[1].".".$fecha_temp[0]; $salida_eventos .= "<tr><td align=\"center\"><strong> <a href=\"javascript:eventWindow('detalles_evento.php? id=$evento_id');\">".$evento_titulo."</a></strong></td> <td align=\"center\" width=\"20%\">".$inicio_evento." </td></tr>"; } $salida_eventos .= "</table><br><br><br>"; echo $salida_eventos; mysqli_free_result($obtener_eventos_res); mysqli_close($mysqli); } else echo "<h2>AGENDA: No existen coincidencias</h2><hr>"; break; case 'foros_user.php': if ($nro_palabras == 1) { //consulta a la BD usando LIKE $obtener_posts_sql = "SELECT * FROM foro_posts INNER JOIN foro_topics ON foro_topics.topic_id = foro_posts.topic_id WHERE foro_posts.post_texto LIKE '%$cadena%' OR foro_topics.topic_titulo LIKE '%$cadena%' LIMIT 50"; } elseif ($nro_palabras > 1 ) //consulta a la BD usando FULLTEXT $obtener_posts_sql = "SELECT * , MATCH (foro_posts.post_texto) AGAINST ('$cadena') AS puntuacion FROM foro_posts INNER JOIN foro_topics ON foro_topics.topic_id = foro_posts.topic_id WHERE MATCH (foro_posts.post_texto) AGAINST ('$cadena' IN BOOLEAN MODE) OR MATCH (foro_topics.topic_titulo) AGAINST ('$cadena' IN BOOLEAN MODE) ORDER BY puntuacion DESC LIMIT 50"; $obtener_posts_res = mysqli_query($mysqli, $obtener_posts_sql) or die(mysqli_error($mysqli)); 144
if (mysqli_num_rows($obtener_posts_res) > 0) { $salida_foros = " <h4 align=\"center\">FOROS</h4> <table cellpadding=\"3\" cellspacing=\"1\" border=\"1\"> <tr style=\"background-color: #CCCCCC\"> <th>Texto Mensaje</th> <th>TEMA</th> </tr>"; while ($post_info = mysqli_fetch_array($obtener_posts_res)) { $topic_id = $post_info['topic_id']; $post_id = $post_info['post_id']; $post_texto = $post_info['post_texto']; $post_prop = $post_info['post_prop']; $post_fecha = $post_info['post_fecha']; $obtener_tema_sql = " SELECT topic_titulo FROM foro_topics WHERE topic_id = '$topic_id'"; $obtener_tema_res = mysqli_query($mysqli, $obtener_tema_sql) or die(mysqli_error($mysqli)); $topic_info = mysqli_fetch_array($obtener_tema_res); $titulo = $topic_info["topic_titulo"]; $salida_foros .= " <tr><td><strong>".$post_texto."</strong><br/> <span style=\"font-style:italic\";><br>Creado con fecha: ". $post_fecha."<br>por <strong>".$post_prop."</strong></td></span> <td align=center width=\"30%\"><a href=\"foros_user.php?pag= FOROS&mostrar_topic=".$topic_id."\"><strong>".$titulo."</strong> </a></td></tr>"; } $salida_foros .= "</table><br><br><br>"; echo $salida_foros; mysqli_free_result($obtener_posts_res); mysqli_free_result($obtener_tema_res); mysqli_close($mysqli); } else echo "<h2>FOROS: No existen coincidencias</h2><hr>"; 145
break; case 'oposiciones.php': if ($nro_palabras == 1) { //consulta a la BD usando LIKE $obtener_oposiciones_sql = " SELECT id, nombre, plazas FROM oposiciones WHERE nombre LIKE '%$cadena%' ORDER BY fecha_publicacion DESC LIMIT 0, 5"; } elseif ($nro_palabras > 1 ) //consulta a la BD usando FULLTEXT $obtener_oposiciones_sql = " SELECT id, nombre, plazas , MATCH (nombre) AGAINST ('$cadena') AS puntuacion FROM oposiciones WHERE MATCH (nombre) AGAINST ('$cadena' IN BOOLEAN MODE) ORDER BY puntuacion DESC LIMIT 5"; $obtener_oposiciones_res = mysqli_query($mysqli, $obtener_oposiciones_sql) or die(mysqli_error($mysqli)); if (mysqli_num_rows($obtener_oposiciones_res) > 0) { $salida_oposiciones = " <h4 align=\"center\">OPOSICIONES</h4> <table cellpadding=\"3\" cellspacing=\"1\" border=\"1\"> <tr style=\"background-color: #CCCCCC\"> <th>Nombre Oposición</th> <th>Plazas</th> </tr>"; while ($oposicion_info = mysqli_fetch_array($obtener_oposiciones_res)) { $oposicion_id = $oposicion_info['id']; $oposicion_nombre = $oposicion_info['nombre']; $oposicion_plazas = $oposicion_info['plazas']; $salida_oposiciones .= "<tr><td align=\"center\"><strong> <a href=\"javascript:eventWindow('detalles_oposicion.php? id=$oposicion_id');\">".$oposicion_nombre."</a></strong></td> <td align=\"center\" width=\"20%\">".$oposicion_plazas. "</td></tr>"; } $salida_oposiciones .= "</table><br><br><br>"; echo $salida_oposiciones; mysqli_free_result($obtener_oposiciones_res); mysqli_close($mysqli); 146
} else echo "<h2>OPOSICIONES: No existen coincidencias</h2><hr>"; break; case 'tramites_user.php': case 'tramites_public.php': if ($nro_palabras == 1) { //consulta a la BD usando LIKE $obtener_tramites_sql = " SELECT id, titulo, online FROM tramites WHERE titulo LIKE '%$cadena%' OR tramites.desc LIKE '%$cadena%' OR documentacion LIKE '%$cadena%' OR observaciones LIKE '%$cadena%' ORDER BY tipo DESC LIMIT 0, 5"; } elseif ($nro_palabras > 1 ) //consulta a la BD usando FULLTEXT $obtener_tramites_sql = " SELECT id, titulo, online , MATCH (titulo, documentacion, lugar_present, organo_gestor, observaciones, impresos, tramites.desc) AGAINST ('$cadena') AS puntuacion FROM tramites WHERE MATCH (titulo, documentacion, lugar_present, organo_gestor, observaciones, impresos, tramites.desc) AGAINST ('$cadena' IN BOOLEAN MODE) ORDER BY puntuacion DESC LIMIT 5"; $obtener_tramites_res = mysqli_query($mysqli, $obtener_tramites_sql) or die(mysqli_error($mysqli)); if (mysqli_num_rows($obtener_tramites_res) > 0) { $salida_tramites = " <h4 align=\"center\">TRÁMITES</h4> <table cellpadding=\"3\" cellspacing=\"1\" border=\"1\"> <tr style=\"background-color: #CCCCCC\"> <th>Nombre Trámite</th> <th>Tramitación Online</th></tr>"; while ($tramite_info = mysqli_fetch_array($obtener_tramites_res)) { $tramite_id = $tramite_info['id']; $tramite_titulo = $tramite_info['titulo']; $tramite_online = $tramite_info['online']; $salida_tramites .= "<tr><td align=\"center\"><strong> <a href=\"javascript:eventWindow ('detalles_tramiteytramitacion.php?id_tramite=$tramite_id ');\">". $tramite_titulo."</a></strong></td> 147
<td align=\"center\" width=\"20%\">"; if (!empty($tramite_online)) $salida_tramites .= "SI</td></tr>"; else $salida_tramites .= "NO</td></tr>"; } $salida_tramites .= "</table><br><br><br>"; echo $salida_tramites; mysqli_free_result($obtener_tramites_res); mysqli_close($mysqli); } else echo "<h2>TRÁMITES: No existen coincidencias</h2><hr>"; break; case 'estatica': if ($nro_palabras == 1) { //consulta a la BD usando LIKE $obtener_estatica_sql = " SELECT apartado, seccion, contenido FROM seccion_estatica WHERE contenido LIKE '%$cadena%' ORDER BY apartado DESC LIMIT 0, 5"; } elseif ($nro_palabras > 1 ) //consulta a la BD usando FULLTEXT $obtener_estatica_sql = " SELECT apartado, seccion, contenido , MATCH (contenido) AGAINST ('$cadena') AS puntuacion FROM seccion_estatica WHERE MATCH (contenido) AGAINST ('$cadena' IN BOOLEAN MODE) ORDER BY puntuacion DESC LIMIT 5"; $obtener_estatica_res = mysqli_query($mysqli, $obtener_estatica_sql) or die(mysqli_error($mysqli)); if (mysqli_num_rows($obtener_estatica_res) > 0) { $salida_estatica = " <h4 align=\"center\">INFO AYUNTAMIENTO</h4> <table cellpadding=\"3\" cellspacing=\"1\" border=\"1\"> <tr style=\"background-color: #CCCCCC\"> <th>Apartado</th> <th>Sección</th> <th>Contenido</th></tr>"; 148
while ($estatica_info = mysqli_fetch_array($obtener_estatica_res)) { $estatica_apartado = $estatica_info['apartado']; $secciones = array("alca" => "El Alcalde", "orga" => "Órgs. de gobierno", "conc" => "Concejalias Barrio", "tfno" => "Tfnos. de interés", "fies" => "Fiestas", "guia" => "Guia de Paterna", "tran" => "Transportes", "sani" => "Sanidad", "cons" => "Consumo", "medi" => "Medio ambiente", "serv" => "Servicios sociales", "urba" => "Urbanismo"); $estatica_seccion = $estatica_info['seccion']; $nombre_seccion = $secciones[$estatica_seccion]; $estatica_contenido = substr($estatica_info['contenido'], 0, 300)." ...... "; $salida_estatica .= " <tr><td width=\"15%\"><strong>".$estatica_apartado."</strong> </td><td width=\"25%\"><strong>".$nombre_seccion."</strong> </td><td width=\"60%\"> <div id=\"busq_infoayto\">$estatica_contenido</div><br> <a href=\"index_lateral.php?sec1=$estatica_apartado&sec2= $estatica_seccion\">VER MÁS</a></td></tr>"; } $salida_estatica .= "</table><br><br><br>"; echo $salida_estatica; mysqli_free_result($obtener_estatica_res); mysqli_close($mysqli); } else echo "<h2>INFO AYUTANMIENTO: No existen coincidencias</h2><hr>"; break; }; } //end of function busqueda() 149
Finalmente, será preciso el siguiente código, en la página que muestra los resultados de la búsqueda, para pilotar la búsqueda en todas las tablas (búsqueda global) o en uno sola (búsqueda parcial) como sigue : if ( empty($_POST["busqueda_enviada"]) ) echo "El campo de búsqueda está vacío"; else { if ($_POST["tabla"] == "todas") { busqueda($_POST["busqueda_enviada"], "noticias_public.php"); busqueda($_POST["busqueda_enviada"], "agenda_public.php"); busqueda($_POST["busqueda_enviada"], "foros_user.php"); busqueda($_POST["busqueda_enviada"], "oposiciones.php"); busqueda($_POST["busqueda_enviada"], "tramites_user.php"); busqueda($_POST["busqueda_enviada"], "tramites_public.php"); busqueda($_POST["busqueda_enviada"], "estatica"); } else busqueda($_POST["busqueda_enviada"], $_POST["tabla"]); } Foros de discusión. Un usuario anónimo puede consultar cualquier mensaje del foro, aunque para poder participar abriendo nuevos temas y respondiendo a otros mensajes, precisa de autenticarse. Lo primero con lo que se encuentra un usuario al acceder a la página de foros, es una relación con todos los temas disponibles. Bastará con hacer click en cualquiera de ellos para acceder a los mensajes del mismo. A continuación se expone la implementación de la función que muestra la relación de temas de discusión disponibles. A destacar la sección donde el sistema exhibe la opción de eliminar un tema, sólo si no contiene mensajes de cualquier otro usuario (esto es, si no existe participación aparte de la de su creador). En otro orden de cosas, el sistema debe contabilizar la cantidad de mensajes contenidos en cada tema. 150
function listar_topics() { $obtener_topics_sql = " SELECT topic_id, topic_titulo, DATE_FORMAT(topic_fecha, '%b %e %Y at %r') AS ft_topic_fecha, topic_prop, DATE_FORMAT(topic_ultimo, '%b %e %Y at %r') AS ft_topic_ultimo FROM foro_topics ORDER BY topic_fecha DESC"; $mysqli = doDB(); $obtener_topics_res = mysqli_query($mysqli, $obtener_topics_sql) or die(mysqli_error($mysqli)); if (mysqli_num_rows($obtener_topics_res) < 1) $salida_php = "<p><em>No existen temas de debate</em></p>"; else $salida_php .= "<strong> <span style=\"font-size:150%\";> Seleccione un tema de debate:</span></strong><br><br>"; $salida_php .= " <table cellpadding=\"3\" cellspacing=\"1\" border=\"1\"> <tr style=\"background-color: #CCCCCC\"> <th>TITULOS DE LOS TEMAS</th> <th>MENSAJES</th> <th>ÚLTIMO MENSAJE</th> </tr>"; while ($topic_info = mysqli_fetch_array($obtener_topics_res)) { $topic_id = $topic_info['topic_id']; $topic_titulo = $topic_info['topic_titulo']; $topic_fecha = $topic_info['ft_topic_fecha']; $topic_prop = $topic_info['topic_prop']; $topic_ultimo = $topic_info['ft_topic_ultimo']; //se contabiliza la cantidad de mensajes para cada tema del foro $obtener_posts_sql = " SELECT post_prop FROM foro_posts WHERE topic_id = '".$topic_id."'"; $obtener_posts_res = mysqli_query($mysqli, $obtener_posts_sql) or die(mysqli_error($mysqli)); $cant_posts = mysqli_num_rows($obtener_posts_res); 151
/*si el usuario autenticado es quien abrió el topic y no existe participación alguna de cualquier otro usuario, se exhibe la opción de eliminarlo*/ $participantes = "solo_creador"; while ( ($post_info = mysqli_fetch_array($obtener_posts_res)) && ($participantes == "solo_creador") ) { if ($post_info["post_prop"] != $_SESSION["username"]) $participantes = "otros"; } $salida_php .= " <tr><td width=55%> <a href=\"foros_user.php?pag=FOROS&mostrar_topic=".$topic_id."\"> <strong>".$topic_titulo."</strong></a> <br>Creado con fecha: ".$topic_fecha."<br>Por: ".$topic_prop."<br>"; if ( $topic_prop == $_SESSION["username"] && $participantes == "solo_creador" ) $salida_php .= " <strong><a style=\"font-style:normal; color:#a0281f;\" href=\"foros_ user.php?pag=FOROS&del_topic_id=$topic_id&cant_posts= $cant_posts\"> > > Eliminar Tema < < </a></strong>"; $salida_php .= " </td> <td align=center>".$cant_posts."</td> <td align=center>".$topic_ultimo."</td> </tr>"; } $salida_php .= "</table>"; echo $salida_php; mysqli_free_result($obtener_topics_sql); mysqli_free_result($obtener_posts_res); mysqli_close($mysqli); } //FIN function listar_topics() 152
Un usuario autenticado puede abrir un nuevo tema de discusión en el foro, incluyendo opcionalmente un primer mensaje para el mismo. Para ello, deberá cumplimentar un sencillo formulario de 2 campos, el título del tema y el texto (opcional) del primer mensaje. El sistema recibe el formulario y verifica que al menos, se haya indicado algún título para el tema, en cuyo caso, inserta una nueva tupla en la tabla 'foro_topics' de la Base de Datos. Asimismo, comprueba si existe un primer mensaje y si lo hubiera, lo inserta en la tabla 'foro_posts' relacionándolo con el tema insertado anteriormente. La implementación de este apartado se expone a continuación: function insertar_topic() { if ($_SESSION["autenticado"] == "1") { try { if (empty($_POST["topic_titulo"])) throw new Exception('El título no puede estar en blanco.'); } catch (Exception $e) { echo "<span style=\"font-size:150%\";>ERROR: "; echo $e->getMessage()."</span>"; } if (empty($e)) { eliminar_tags(); $insertar_topic_sql = "INSERT INTO foro_topics (topic_titulo, topic_ fecha, topic_prop, topic_ultimo) VALUES ('".$_POST["topic_titulo"]. "',now(), '".$_SESSION["username"]."',now())"; $mysqli = doDB(); $insertar_topic_res = mysqli_query($mysqli, $insertar_topic_sql) or die(mysqli_error($mysqli)); if (!empty($_POST["post_texto"])) { $topic_id = mysqli_insert_id($mysqli); //retorna el id de la //última consulta de aquella columna que tenga el atributo //AUTO_INCREMENT, en este caso, ese campo es topic_id $insertar_post_sql = "INSERT INTO foro_posts (topic_id, post_ texto, post_fecha, post_prop) VALUES ('$topic_id', '". $_POST["post_texto"]."', now(), '".$_SESSION["username"]."')"; 153