logoApuntes agrupados: Sobre este diario


Sobre este diario (diario): Se encontraron 30 apuntes:

  1. Este diario: Historial de navegación
  2. Este diario: Las etiquetas
  3. Este diario: La edición
  4. Este diario: Extras
  5. Este diario: Los comentarios
  6. Este diario: Sindicación
  7. Este diario: Las categorías
  8. Este diario: Las imágenes
  9. Este diario: Los contadores
  10. Este diario: Diseño modular
  11. Este diario: Los enlaces
  12. Este diario: Los apuntes
  13. Este diario: Sindicación dinámica
  14. Este diario: Un comodín
  15. Este diario: Mejoras en los comentarios
  16. Este diario: Mapa del sitio vs. sitemap
  17. Este diario: BBCodes en comentarios
  18. Este diario: Comentarios y seguridad
  19. Este diario: Valorar contenido
  20. Este diario: Más comentarios
  21. Este diario: resumen del año 2011
  22. Este diario: Sindición extra
  23. Este diario: filtrando historial de navegación
  24. Este diario: Gestión de imágenes
  25. Este diario: Top 10
  26. Este diario: sitemap.xml
  27. Este diario: sitemap.xsl
  28. Este diario: Agrupando apuntes
  29. Este diario: resumen del año 2013
  30. Este diario: Listado de Archivos


Titulo: Este diario: Historial de navegación


emoticón de Caricatos Publicado el día 02 de enero de 2011
id=3

El historial de navegación sirve para tener un atajo de los sitios visitados en la sesión de navegación de cada usuario. Al igual que en la sección de últimos temas y etiquetas, los enlaces no se repiten, y el enlace activo no es "caliente" y queda al principio de la lista.

En el historial pueden encontrarse tanto los apuntes visitados, como los distintos listados ya sea de últimos apuntes como los más vistos, o etiquetas, o categorías.

Para obtener la lista hemos creado una variable de sesión con un array que se va actualizando con la variable "QUERY_STRING" de la variable $_SERVER del lenguaje php.

Resolviendo problemas

Evidentemente hemos tenido que resolver distintos percances en cada pequeño módulo de esta página; este apartado no ha sido ninguna excepción. En esta sección, podíamos encontrarnos con enlaces repetidos, por ejemplo si abrimos un apunte por su título, el enlace tiene la forma:

<a href="?titulo=El+diario+de+Caricatos:+Historial+de+navegaci%F3n">
	El diario de Caricatos: Historial de navegación
</a>

Pero el mismo apunte se puede abrir con la url:

<a href="?id=17">
	El diario de Caricatos: Historial de navegación
</a>

Para resolver este problema, hemos eliminado todo rastro del enlace del historial usando el métod array_diff de php.

$_SESSION["historico"] = array_diff(
	$_SESSION["historico"],
	array("?id=$id", "?titulo=".$titulo)
);
array_unshift($_SESSION["historico"], "?titulo=$titulo");

Nótese el uso de array_unshift() para añadir a la lista (array) cada nuevo elemento a la lista de enlaces. También es posible distinguir una forma de evitar enlaces duplicados; en este caso un apunte puede referenciarse por el id y también por el título.

Otros posibles duplicados

Los enlaces con caracteres especiales y espacios en blanco tienen una codificación distinta, pero esa codificación no es única. El lenguaje que se usa en el servidor (php), cambia los espacios en blanco por el signo de sumar (&#43;), pero ese mismo espacio, los navegadores lo cambian por el mismo carácter "escapado" (%20). Pues para evitar este tipo de duplicados, aplicamos el método urldecode de php al enlace.






Titulo: Este diario: Las etiquetas


emoticón de Caricatos Publicado el día 02 de enero de 2011
id=4

Las etiquetas en este diario ocupan un lugar destacado, porque no solo pretendemos que sea una herramienta de ayuda a los buscadores, sino que le dedicaremos una descripción y una serie de enlaces, porque pensamos que debe tener un sentido útil, y no solamente sea un recurso para mejorar el posicionamiento en los buscadores.

Se genera con el siguiente código:

CREATE TABLE etiquetas (
	"nombre" varchar(50),
	"descripcion" text,
	"ids" text
);

No creo necesario explicar la razón de cada campo, aunque tal vez pueda no estar muy claro lo de "ids": Se trata de los identificadores de los apuntes que llevan esa eiqueta (campo "nombre"), separados por comas.

Nube de etiquetas

Para implementar la nube de etiquetas de esta página, primeramente hemos obtenido el mayor valor de entre todas las etiquetas (las que aparecen en más apuntes), y simplemente hemos hecho una división entre el número de apuntes de cada etiqueta y ese valor máximo obtenido, consiguiendo un número en el rango [0..1]; luego le sumamos uno (1) para obtener el valor que le aplicamos al estilo "font-size" de esa etiqueta, usando "em" como medida (cuestión de estilos).

Nótese que aparte de distinguir las etiquetas con su tamaño, también hay distintos colores y énfasis; simplemente hemos destacado las etiquetas del apunte que se está viendo.


La organización (orden) de visualización es aleatorio, simplemente leyendo la tabla con la cláusula "order by rand()".

Etiquetas en el editor

En la tabla de los apuntes no se hace ninguna referencia sobre las etiquetas, pero en el editor hemos añadido un espacio para poner una lista de ellas. El secreto está en hacer una consulta a la tabla de etiquetas, sabiendo el id del apunte:

$sql = "select nombre from $etiquetas where concat(',', ids, ',') like '%,$id,%'";

Ya teniendo esa lista en el editor, a la hora de realizar actualizaciones, procesamos la lista original, junto a la misma lista con posibles modificaciones. Luego es cuestión de modificar los elementos que se hayan modificado quitando o poniendo etiquetas.






Titulo: Este diario: La edición


emoticón de Caricatos Publicado el día 02 de enero de 2011
id=5

Actualmente el editor de este sistema permite aparte de crear nuevos apuntes -guardándolos como borradores, o publicándolos-; editar los apuntes guardados (borradores o apuntes publicados); el truco para diferenciar un borrador de una publicación está en el mismo botón que se muestra/oculta dinámicamente al iniciarse o modificar la adición. Puede ser un botón "actualizar" si el apunte ya está publicado (campo activo con valor "1"); o "borrador" si aún no se ha publicado o es nuevo, y un último caso sería "publicar", donde se modificaría el campo activo. El título de cada apunte sólo se puede modificar previo chequeo de disponibilidad con Ajax (no pueden duplicarse).

También podemos modificar el resto de elementos editables: etiquetas, extras, imágenes, etc., donde podemos editar el campo "descripción", y en los tres primeros casos se asignan los apuntes relacionados. Cuando intentamos editar el nombre de etiquetas, categoría o extras, se crea automáticamente un ítem en la tabla con el nuevo nombre, o si ya existiese, se cargaría en el editor. Estos elementos pueden borrarse.

imagen Las imágenes deben tener en cualquier página un lugar destacado, y este diario no será una excepción. Para subir cada imagen, tenemos un formulario solo activo cuando se ha registrado correctamente para evitar tráfico absurdo de la página por parte de los visitantes con "dedos flojos".

Usamos un sistema para previsulizar las imágenes "a subir", que se describe en este artículo: Revisar las imágenes antes de subirlas, pero en lugar de guardar la imágen en una variable de sesión, tal como explico en el artículo, se guardan en un archivo temporal usando la instrucción php move_uploaded_file, mejorando la gestión de imágenes del sistema.

No es posible borrar las imágenes, pero podemos cambiarla por otra, aunque seguramente no sea necesario. Cada una tiene un identificador "id", y para mostrarla basta usar el fichero "diario.imagen.php", que cuando no tiene ese identificador como parámetro se muestra la imagen que vemos a la izquierda, que para resaltar su fondo transparente le hemos puesto color de fondo, una imagen "grilla", y un borde azul.

imagen Podemos generar las imágenes con un tamaño menor usando el parámetro "max". La miniatura de la derecha tiene id pero no es válido, así que se gestiona como si no lo tuviese: "id=no&max=80". La tabla donde guardamos las imágenes tiene otros campos para rellenar de los que destacamos el título que se debería usar como atributos alt y title en cuanto las insertemos.

Lo último que destacaremos en este apunte es la inserción de una botonera del tipo de añadir BBCodes, aunque realmente se insertan etiquetas (tags) html. Para la edición nos hemos basado en esta página: Editor de texto, y en el futuro tenemos previsto crear una botonera personalizada.






Titulo: Este diario: Extras


emoticón de Caricatos Publicado el día 07 de enero de 2011
id=6

Llamaremos extras a los elementos de los apuntes que no son ni el texto ni las imágenes relacionadas o incrustadas. Como ejemplo de "extras" vemos en este apunte un adorno en su esquina superior derecha que explicamos a continuación:


Sabemos que todos los apuntes se presentan en un contenedor de esta página con un identificador (id="apunte"), con unos estilos definidos en la hoja de estilos genérica. Pues entonces solo tenemos que crear un elemento en la tabla "extras" con la pertinente modificación:

#apunte {
	background: white url(../postales/General/General002.gif) no-repeat right top;
}

Para diferenciar los distintos extras, le asignamos un numbre con una característica propia, ya que debe tener un nombre y a la vez indicar que tipo de extra es; en principio script o estilo. En este caso concreto el nombre es "estilo:diario". El último paso siempre será indicar a que apunte se aplicará el extra definido.

También javascript

Para poder aplicar los script en esta página (algo muy importante para el autor de la misma), debemos aplicarlos de forma no-intrusiva, así que estamos obligados a declararlos integramente en estos extras.

flor Para poner un simple ejemplo, ya que no es la intención de este apunte desarrollar estos scripts, vamos a insertar una imagen y le añadiremos un efecto rollover. La idea global es que los efectos y la dinámica de cada apunte solo se note en el enlace del mismo, y no en las distintas listas en donde pueda aparecer (categorías, etiquetas, etc.)

También tenemos que evitar problemas de redefiniciones de scripts, así que debemos añadir siempre una opción para guardar (o resguardar) las inicializaciones.

if (window.onload != "")
	resguardamos_extras = window.onload;
window.onload = function() {
	rollovear(
		document.getElementById("rollover"),
		"diario.imagen.php?id=11&max=120"
	);
	if (resguardamos_extras != undefined)
		resguardamos_extras();
}

Nótese que antes de asignar el efecto, hemos resguardado (resguardamos_extras), los eventos que pudiesen existir declarados en la inicialización de la página (hablamos del apunte).

Y más dinamismo: includes.

Al igual que los lenguajes de programación web podemos insertar en los apuntes pequeños trozos de código que dependerá de las condiciones que tenga el sistema completo, entre otras cosas porque podemos consultar nuestra base de datos. Un ejemplo es el siguiente listado con los 10 apuntes más vistos.


[incluir]vistos()[/incluir]

Los extras seguramente seguirán evolucionando, así que nos encontraremos en próximos apuntes...






Titulo: Este diario: Los comentarios


emoticón de Caricatos Publicado el día 30 de enero de 2011
id=9

Como todo blog, tenemos un espacio para dejar comentarios en los apuntes. Ya teníamos experiencia al respecto, y la hemos reflejado en este pequeño tutorial: Ponga comentarios en su web, pero modificaremos un poco el sistema descrito para poder responder a los comentarios; o sea tanto se puede comentar el apunte como algún comentario del apunte. Para ello hemos creado un sistema de indexación compuesto, o sea, para el apunte con id="1", la referencia (campo referido en la tabla), será 1; además cada comentario tiene su propio índice único de identificación (id), así que ese "id" será la parte nueva de indexación. Resumiendo, si el nuevo comentario del apunte con id="1", tiene un id="10", el campo "referido" se llenará con el valor "1.10".

Una tabla para los comentarios

Ya hemos adelantado alguna característica de la tabla, su propio identificador, el apunte referido (si fuese el caso, el comentario referido), la fecha, el nombre del autor y el propio comentario.

CREATE TABLE $comentarios (
	nombre varchar(50) NOT NULL,
	comentario text NOT NULL,
	referido varchar(100) NOT NULL,
	fecha timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	id int(11) NOT NULL AUTO_INCREMENT,
	PRIMARY KEY (id)
)

También hemos puesto el correo del "comentarista" con el propósito de obligar a validar el mensaje en futuras modificaciones del sistema, tal como se explica en el enlace anterior. En la tabla real hay algunos campos más que no vienen al caso como email, url...

Con esta tabla, para poder leer los comentarios de un apunte, la instrucción de búsqueda es de esta forma:

$sql = "select * from $tabla_comentarios where referido='$id' or referido like '$id.%' order by id";

El único inconveniente que tenemos ahora es el orden de recogida de los comentarios, que resolveremos tal como explicamos a continuación.

Anidamiento y recursión

Para poder mostrar cada comentario en el sitio que le corresponde. hemos recogido los elementos en dos arrays (arreglos), uno para los comentarios del propio apunte, y otro array compuesto, indexado por el id del comentario que refiere. Las sentencias las mostramos a continuación.

$res = mysql_query($sql);
while($dato = mysql_fetch_array($res))	{
	$_ids = $dato["referido"];
	if ($_ids === $id)	{
		array_push($ms_apunte, $dato);
	}
	else	{
		list($fantasma, $iid) = explode(".", $_ids);
		if (!isset($ms_comentario[$iid]))
			$ms_comentario[$iid] = array();
		array_push($ms_comentario[$iid], $dato);
	}
}

Lo que nos queda es desapilar cada comentario del array $ms_apunte, y comprobar la existencia de comentarios relacionados con su id del array $ms_comentario de forma recurrente. En este caso no pondremos el código porque se extiende mucho al existir instrucciones para la visualización de la página.

Cuestión de seguridad (dedos flojos)

Todos sabemos con qué facilidad podemos pinchar en los botones de una página web, por eso hemos añadido unos pocos elementos de seguridad. En principio no hemos contado con proteción en el navegador (javascript) para que sea más eficiente.

En el servidor hacemos un chequeo del código de seguridad para evitar esos mensajes automatizados tan molestos, y también controlamos que se escriba algo en el espacio dedicado al comentario. En principio no importa lo que se ponga, aunque luego deberá ser moderado.

También se realiza una validación básica con javascript (o sea en el navegador), aunque todos sabemos que no es del todo eficiente, ya que simplemente puede desactivarse.






Titulo: Este diario: Sindicación


emoticón de Caricatos Publicado el día 12 de febrero de 2011
id=12

logo rss Podemos recibir en nuestro lector rss (ya sea programa o servicio online), información de las novedades de este diario. Para ello actualizaremos nuestro fichero rss cada vez que publiquemos un nuevo apunte. La implementación la hemos realizados en base a la especificeción RSS 2.0, y aunque la información oficial está en inglés, es relativamente fácil buscar los campos obligatorios y los opcionales.

En un principio usaremos los campos obligatorios de la raíz del rss: title (título), link (enlace) y description (descripción), que obtenemos directamente del fichero de configuración de la página; y viendo que tanto el número de campos item (elemento) como los subcampos que lleve, al ser todos opcionales, los decidiremos nosotros.

Al principio pondremos todos los apuntes, pero cuando crezca ese número considerablemente -por ejemplo, que pase de cincuenta (50)-, limitaremos ese valor. Y sobre los campos por cada item, en principio seleccionamos el título, el enlace, enlace único (permanent link), la fecha de publicación y la descripción o resumen.

Obteniendo datos

Ya hemos comentado que la raíz o cabecera del documento lo obtenemos de nuestro fichero de configuración, pero los items los obtendremos de la tabla de apuntes con la siguiente secuencia de código, donde puede verse que ya tenemos contemplada la limitación del número de ítems:

$limite = ($_GET["n"] == "") ? "": " limit 0, {$_GET[n]}";
$sql = "select * from $tabla_apuntes order by fecha desc$limite";
$res = mysql_query($sql);
if ($res)	{
	while ($datos = mysql_fetch_array($res))
		array_push($items, $datos);
}

Con esa secuencia obtenemos los registros en su totalidad, aunque tan solo nos interesan los campos que hemos detallado antes. Si fuese necesario, cambiaríamos la instrucción de búsqueda. Para generar luego cada item las instrucciones son:

foreach($items as $datos => $item)	{
	$titulo = $item["titulo"];
	echo "<item>";
	echo "<id>{$item["id"]}</id>";
	echo "<titulo><![CDATA[$titulo]]></titulo>";
	echo "<link><![CDATA[$diario?titulo=".urlencode($titulo)."]]></link>";
	echo "<guid><![CDATA[$diario?id={$item["id"]}]]></guid>";
	echo "<fecha>".Date(r, strtotime($item["fecha"]))."</fecha>";
	preg_match("/(.*?)/is", $item["apunte"], $des);
	echo "<descripcion><![CDATA[$des[1]]]></descripcion>";
	echo "</item>";
}

La especificación del fichero rss no contempla algunos de los campos que aquí vemos, y eso se debe porque estas líneas no son exactamente las que generarán el fichero, sino las que buscará el editor de este diario antes de generar el fichero rss definitivo. Comentaremos a continuación brevemente algunas de las líneas de código.

Breve resumen del código

Lo primero que destacamos es el envoltorio en estructuras CDATA de los campos que no sabemos con certeza que puedan provocar que nuestro fichero xml sea "mal formado".

Tanto los campos link como guid son enlaces, aunque solo el último es permanente, por eso hemos usado dos enlaces distintos para referenciar la misma página, pero en nuestra base de datos, solo contemplamos que el id sea único. Sobre la referencia a partir del título, nótese que usamos la función urlencode del lenguaje php.

La fecha de publicación está generada por el gestor de la base de datos (mysql), cuyo formato no es el que la especificación rss requiere, así que le damos formato con el lenguaje php.

Para la descripción, hemos usado unos códigos especiales BBCODES ([[/]rss]) insertados en cada apunte para seleccionar el trozo de apunte que aparecerá en nuestro fichero rss.






Titulo: Este diario: Las categorías


emoticón de Caricatos Publicado el día 13 de febrero de 2011
id=13

categorías Hemos estructurado este diario de manera que se puedan encontrar los apuntes desde distintos criterios. Destacamos entre ellos "Las Categorías" (Temas) porque nos sirve para agrupar apuntes por un concepto concreto. No debe confundirse con niveles.

Al igual que las etiquetas, las imágenes y los contadores, las categorías son tratadas desde su propia tabla. También existe un campo en la tabla reservada para los ids; y para obtener las páginas con esa categoría, hemos usado la técnica que hemos descrito en el apunte Este diario: Las etiquetas.

Se deben distinguir de las etiquetas por diversas razones, ya que puede tratarse de solo una palabra o de una frase; también se trata de una descripción más significativa o detallada, y aunque pueden ser importantes como ayuda para los buscadores, no son insertadoas entre las palabras clave de la página, cosa que sí se hace con las etiquetas.

Categorías básicas

Para temáticas "web" las primeras categorías han sido Así se hizo justamente para agrupar temas que describen como se ha hecho esta misma página; Vicisitudes de un webmaster, también para mostrar tanto el desarrollo de las páginas, como explicaciones sobre las herramientas que hemos usado, etc.

También habrá apuntes de opiniones y críticas, tanto en temas relacionados con Internet y el mundo informático, como en dibujo, pintura y diseño, debido a que también soy caricaturista; y no descartamos escribir de cosas tan variadas como turismo, hostelería, sociedad, arte...

La implementación

Hay una similitud muy notoria entre el tratamiento que se hace con este elemento y con las etiquetas. Puede distinguirse que siempre se leen todas las etiquetas y todas las categorías, ya sea listando cosas (apuntes relacionados con estos elementos o especiales como "Los más vistos"), así que adelantamos que el tratamiento es exactamente igual, y tan solo se distinguen en la forma de ser presentados.

El número de apuntes que tiene cada categoría se sabe por su campo ids en la tabla, y se puede ver junto al nombre de la misma. En el caso de las etiquetas se usa ese número para aumentar el tamaño de las letras en su espacio específico.






Titulo: Este diario: Las imágenes


emoticón de Caricatos Publicado el día 25 de febrero de 2011
id=16

¡Voy volando! Las imágenes en este diario pueden insertarse desde otra página web, usando en tal caso su ruta completa, o desde la propia galería que pude verse en el editor. La manera de insertarlas en los apuntes es tan sencilla como entrar en la tabla "imágenes", seleccionarla desde la galería de miniaturas, y copiarla al portapapeles.

A las imágenes de la galería, se las inserta desde la url "diario.imagen.php" (interrogante), y el tamaño puede modificarse con la variable "max", y la selección se realiza por su identificador "id". Para la imagen que vemos en este apunte, la dirección se construye así:

<img
	src="diario.imagen.php?id=2&max=160"
	title="¡Voy volando!"
	alt="¡Voy volando!"
	style="margin: 1em; float: left; border: 3px outset blue"
	id="imagen_mia"
	longdesc="diario.ficha.php?id=2"
>

Hemos modificado el tamaño y estilos, a la vez que añadido un identificador por si en el futuro necesitásemos una forma de referenciarla. Nótese que insertando la imagen desde el portapapeles automáticamente se asignan valores a los atributos "html" alt y title, importantes para el componente de accesibilidad de esta página. También se añade el atributo longdesc con destino de una ficha donde también se muestra su descripción. Para la imágen de este apunte este es el enlace de su ficha (también puede pulsar en la propia imagen).

odalisca Por defecto hemos usado el valor 300 para la variable max, pero si la imagen en cuestión (siempre hablando de las que se encuentran en la librería) tuviese menor tamaño, se mostrará la imagen sin redimensionar.

odalisca odalisca Para las animaciones, si se redimensionan con la variable max, esa animación se pierde (siempre que se trate de una reducción); por esa razón las opciones serán perder la animación y reducir su peso redimensionándola con la variable max, o reducir la imagen con estilos para mantener la animación; para realizar esta segunda opción, tan solo se debe modificar uno de los estilos (altura: height o anchura: width). De todas formas, las imágenes animadas no suelen tener grandes dimensiones, por lo que tal vez no consideremos mucho esta característica.






Titulo: Este diario: Los contadores


emoticón de Caricatos Publicado el día 03 de marzo de 2011
id=17

Para implementar los contadores de esta página, hemos creado una tabla con un par de campos: página y cuenta. El campo página indicará si es la principal (index) o en otros casos se tratará de un campo compuesto por el tipo de contenido, por ejemplo "apunte", o "etiqueta", seguido de un identificador como un campo "id" en el caso de los apuntes, y en otros dependerá del índice de la tabla afectada.

Evitaremos el incremento de los contadores cuando las páginas han sido visitadas recientemente utilizando variables de sesión, guardando en una lista las visitadas en cada sesión (sin incrementar la cuenta particular según el caso).

Un poco de historia y de estilo

Hay muchas formas de plantear la gestión de un contador, la más sencilla es actualizarlo siempre que se carga la página como en este tema: contador en todas las paginas; y esa cuenta pude llevarse desde un simple fichero (como ya hemos indicado, no es nuestro caso), que se lee para saber la cuenta actual, se incrementa, se reserva en una variable para mostrarlo, y se actualiza con el nuevo valor en el mismo fichero. Evidentemente para este sencillo proceso, necesitamos un lenguaje de programación en nuestro servidor, y como ya hemos avisado en otros apuntes, usamos el lenguaje php.

cuenta Podemos ver el contador de este apunte en formato gráfico en la imagen adjunta, y nos puede dar una idea de las tantísimas posibles variantes; en este caso la cuenta se pasa como parámetro a un fichero (n.php), y viendo el código de ese fichero podemos pensar en cambiar fuentes, colores, tamaños... o distorsionarlas como en algunos "captchas" de muchos sitios de la web... incluso con algo de imaginación podríamos hacerlo animado.

<?php
if (isset($_GET["n"]))
	$n = $_GET["n"];
else
	$n = "0";
$vale = ereg("[0-9]", $n);
if (!$vale) $n = "0";
$digitos = ereg_replace("[^0-9]", "", $n);
$largo = strlen($digitos);
$imagen = Array($largo);
for ($i = 0; $i < $largo; $i ++)	{
	$digitos[$i] = substr($digitos, $i, 1); 
}

header("Content-Type: image/png");
$ancho = 0;
for ($i = 0; $i < $largo; $i ++)	{
	$im = "verde".$digitos[$i].".png";
	$imagen[$i] = imagecreatefrompng($im);
	$ancho += imagesx($imagen[$i]);
}
$alto = imagesy($imagen[0]);
$_imagen = imagecreate($ancho, $alto);
$ImgWhite = imagecolorallocate($_imagen, 255, 255, 255);
imagefill($_imagen, 0, 0, $ImgWhite);
imagecolortransparent($_imagen, $ImgWhite);
$ancho = 0;
for ($i = 0; $i < $largo; $i ++)	{
	if (file_exists($d = "verde".$digitos[$i].".png"))	{
		imagecopy(
			$_imagen,
			$imagen[$i],
			$ancho, 0, 0, 0,
			imagesx($imagen[$i]),
			$alto
		);
		$ancho += imagesx($imagen[$i]);
	}
}
@imagepng($_imagen);
for ($i = 0; $i < $largo; $i ++)	{
	if (file_exists($d = "verde".$digitos[$i].".png"))	{
		imagedestroy($imagen[$i]);
	}
}
imagedestroy($_imagen);
?>

No descartamos cambiar en este diario el contador que usamos por uno gráfico, pero en principio estamos evitando usar implementaciones innecesarias para mejorar la fuidez en la carga de la página.






Titulo: Este diario: Diseño modular


emoticón de Caricatos Publicado el día 06 de marzo de 2011
id=18

Siguiendo con los pasos que hemos dado para el desarrollo de este diario, vamos a comentar como se ha planteado su diseño.

En la cabecera de la página tan solo se incrusta dinámicamente datos muy básicos como el título y las palabras clave para las búsquedas; a la vez que dependiendo de que se tratase de un apunte, se añade un script de validación para los comentarios, y si llevara información "extra", también se añade (scripts y estilos adicionales). El cuerpo de la página principal se acomoda con una instrucción include, usando un simple fichero txt con las etiquetas html definidas y con elementos de inserción de variables php.

La cabecera del cuerpo de la página solo tiene el título que definimos en el fichero de configuración, y el logotipo (mi propio emoticón) que además lleva información de la página para datos estadísticos futuros. En el momento de escribir este apunte no tenía ninguna floritura más, aunque tenemos previsto mejorar el diseño. El pie de página está por desarrollar, aunque se reserva para las cosas típicas de esta zona (créditos, derechos de autor, etc.)

Divide y vencerás

pintor Durante mis estudios informáticos en España, ésta ha sido una de las frases que más he tenido que escuchar en las asignaturas de programación. Creo que este diario es un auténtico ejemplo de uso de la misma; les comento ¿por qué?:

Las distintas secciones laterales están programadas en ficheros individuales, y en consecuencia, cuando debo modificar algo en alguna de esas secciones, simplemente tengo que editar un ficherito con unas pocas líneas (tal vez 20 o 30).

Para poner un ejemplo comentaremos la zona de etiquetas, que como puede verse, está implementada con el aspecto de una nube de palabras, sobre el color, es fácil reconocer que cambian a rojo las etiquetas asociadas al apunte activo; y sobre el tamaño, será mayor mientras mayor número de apuntes tengan asociada la etiqueta. El tamaño se obtiene con relativa facilidad:

function tam_fuente($mis_ids, $max, $escala, $base)	{
	return $base + ($mis_ids / $max * $escala);
}
//...
$fuente = "font-size: ".tam_fuente(count($_etiquetas), $max_ids, 1.4, .7)."em";

Nótese que a medida que necesitemos diferenciar más el tamaño, mayor valor deberemos asociar a la variable $escala, y el tamaño mínimo proporcional se encuentra en la variable $base. También de la misma forma podemos saber el número de apuntes asociados a cada categoría, pero en esta ocasión, ese dato lo incorporamos directamente en el mismo listado.

Más módulos de quita y pon

Tenemos previsto añadir más módulos con la intención de hacer el diario más atractivo. Nos interesa también mejorar la usabilidad del sitio, por eso podríamos realizar algunos cambios en el futuro. Algunas de las opciones que nos hemos planteado es integrar antiguos elementos del dominio como La máquina de Turing, el viejo Generador de Fórmulas Matemáticas y Lenguaje HTML o el también viejo editor de Postales digitales; aunque posiblemente actualizaremos esas viejas versiones. También implementaremos las interesantes citas: Ponga una cita en su página, pero a la vez que se asocie a un módulo de "Eventos y efemérides".

yo A medida que se ande el camino, iremos informándolo. ¡Que lo disfruten!







Titulo: Este diario: Los enlaces


emoticón de Caricatos Publicado el día 20 de marzo de 2011
id=20

Siempre nos gusta referenciar esos sitios especiales y que visitamos con frecuencia, o tal vez simplemente son de nuestros amigos. En la lista de enlaces que proponemos hay para casi todos los gustos.

Hemos decidido reservar la zona izquierda del diario para los enlaces no relacionados con la página tales como las recomendaciones, páginas de clientes o de amigos, etc. Y a la derecha, pretendemos poner una completa referencia del sitio, con enlaces para obtener listados por etiquetas o categorías, últimos apuntes publicados, mapa del sitio, rss, etc.

¡Y a la izquierda de su pantalla...!

Las distintas listas de enlaces referencian algunas páginas propias de uso persona, que tienen que ver con dos de mis principales actividades: artística y tecnológica. Evidentemente todas están relacionadas, mi primera página ha sido para promocionar mis caricaturas, pero he tenido que informarme sobre su construcción y en base a ello crear mis propios recursos que en un pricipio he plasmado en este dominio; este contenido está volcado como artículos en el otro dominio referenciado. Ahora que hemos cambiado el formato a esta página, reservaremos caricatos.net para artículos y recursos.

Aunque he tenido la suerte de tener clientes poco exigentes, han sido de una importancia relevante en la evolución de mis conocimientos para la creación de páginas web. Si les interesa alguna de las temáticas que tiene estas páginas, recomiendo su visita.

Son también de obligada mención mis amigos webmasters, con los que he aprendido todo lo que ahora sé. Posiblemente debamos hacer mención de ellos en muchos apuntes, de igual manera que mencionaremos a los artistas (algunos de ellos también webmaster, igual que algunos webmasters también son artistas).

Por último, "Mis recomendaciones", es como un cajón de sastre donde podemos encontrar enlaces a página de cualquier índole.

¡Y en este rincón...! (la derecha)

El otro lado lo hemos dedicado a los enlaces del diario y del dominio; y alguna información adicional, en ocasiones enmascarada como el tamaño y color en las letras de las etiquetas, indicando la relación con el apunte y sobre todos los apuntes. Algo parecido pasa con las categorías, donde hemos puesto entre paréntesis el número de apuntes asociados.

Los apuntes están paginados en grupos de cinco en cada listado: los últimos, los más leídos, los asociados a etiquetas o categorías, pero hemos puesto los diez últimos también en esta zona; aunque en el mapa del sitio se pueden encontrar todos.

Tenemos también información del número de visitantes por página y el enlace para sindaicar el sitio. Y para los viejos visitantes intentaremos incluir las viejas páginas que siguen existiendo desde hace ya varios años. Un buen ejemplo es la "Máquina de Turing" creada en el año 2002 como puede verse en el resumen siguiente:

[incluir]turing()[/incluir]

Para poder hacer un seguimiento de las visitas a esta página, aún manteniendo la versión original (.html), hemos clonado la misma en versión php. En ambos casos mostramos la fecha de su última modificación mediante la función php filemtime.

Después de ver el resultado en el servidor, evidentemente la fecha de creación no se corresponde con la fecha que hemos comentado, así que para confirmar lo dicho, muestro la página original: versión original, y la referencia hecha de la misma en los Foros del Web.

Terminando...

Nos queda decir que la zona del centro se completa con los enlaces propios de cada apunte, y unos pocos controles para la navegación del sitio.






Titulo: Este diario: Los apuntes


emoticón de Caricatos Publicado el día 10 de mayo de 2011
id=25

Al igual que los blogs, este diario muestra los últimos cinco (5) apuntes publicados cuando se muestra en el "modo listado". Cuando el número de elementos de ese listado es mayor de cinco, se muestran unos enlaces de paginación. Evidentemente el último de los listado puede tener un número menor de apuntes.

La otra forma de presentación de esta página, sería el "modo apunte", donde solo se muestra el apunte seleccionado (por su titulo o su identificador "id"). En este modo también se encuentra activo el formulario para realizar comentarios (desactivado en los listados); y la navegación cambia con otros enlaces:

<< primer apunte   < apunte anterior   apunte siguiente >   último apunte >>  

Otra característica del modo es que pueden tener activados distintos elementos que no se apreciarían en los listados, como la simpática brujita del rincón superior derecho de este apunte.

La Publicación

Ya hemos mostrado el editor de esta página, y en la sección de apuntes podemos ver entre sus controles los botones "borrador" y "publicar" para guardar los apuntes que no se harán visibles hasta que se pulse el segundo botón. Esto es práctico porque podemos reflexionar antes de que nuestra redacción se haga pública. Para terminar, solo nos quedará asociar las categorías y etiquetas que correspondan.






Titulo: Este diario: Sindicación dinámica


emoticón de Caricatos Publicado el día 05 de junio de 2011
id=29

rss Ya hemos comentado como se implementó el sistema de sindicación rss de este diario, pero por un motivo que detallaré a continuación he decidido ampliar la sindicación y hacerlo por categoría o etiqueta. Ahora cuando seleccionamos una categoría o etiqueta aparte de la descripción y el listado de apuntes, podemos encontrar junto a su nombre, el típico dibujo que permite la sindicación.

Si solo nos interesan los apuntes de una u otra categoría o etiqueta, y descartar el resto, podemos sindicarnos solo a ella.

El motivo: titulares en SuCaricatura.com

Al entrar a la página SuCaricatura.com puede verse a la izquierda un recuadro con la leyenda "Apuntes de mi diario", donde se puede encontrar el título y el resúmen RSS de loa apuntes asociados a la etiqueta Caricaturas, refrescándose con cierta frecuencia. También podría considerarse alguna categoría como "Artes y Oficio" o tal vez "Globalización", y no descartamos realizar cambios de acuerdo a las necesidades.

Comprobando la facilidad de su implementación, esperamos adaptar este sistema a la otra página referenciada en "Mis Enlaces".

La implementación

En el sistema actual, tan solo leemos de una tabla de nuestro sistema de base de datos, con la condición que el apunte este publicado (también podrían "no estar publicados": los borradores) ordenados inversamente según la fecha de publicación, y luego volcados esos datos al fichero "diario.rss.xml", pero para no crear un fichero rss.xml para cada elemento hemos creado uno que se genere dinámicamente en cada ocasión con extensión php: diario.rss.php, donde pasamos el nombre de la categoría o etiqueta en la línea de dirección (url); o sea que para la sindicación de la etiqueta Caricaturas (el origen de este proyecto), la url será "diario.rss.php?etiqueta=Caricaturas". Nótese que sin usar parámetros, el listado generado es el mismo que en la página xml.

Ahora la consulta será en dos tiempos:

if (isset($_GET["etiqueta"]))	{
	$sql = "select descripcion, ids from $tabla_etiquetas where nombre='".$_GET["etiqueta"]."'";
	$res = mysql_query($sql);
	if ($res)	{
		if (mysql_num_rows($res) > 0)	{
			$ids = mysql_result($res, 0, 1);
			preg_match('/(.*?)/is', mysql_result($res, 0, 0), $des);
			$descripcion = $des[1];
			$where = " and id in ($ids)";
		}
		else $where = "";
	}
	else $where = "";
}

Podemos apreciar que obtenemos de la descripción el resumen -rss-, y creamos una variable $where que usaremos en la búsqueda de apuntes:

$sql = "select titulo, id, fecha, apunte from $tabla_apuntes where activo>0$where order by fecha desc";

Tan solo nos queda presentar los datos, que en principio debe llevar su correspondiente cabecera xml, tal como hemos comentado en el apunte "sindicación".






Titulo: Este diario: Un comodín


emoticón de Caricatos Publicado el día 17 de junio de 2011
id=32

paleta Web En los últimos apuntes hemos necesitado de un elemento extra para recibir datos de un formulario (en Colores y Probador web) ampliando la funcionalidad del diario; ahora la pregunta obligada es: ¿Y qué tiene que ver la paleta de colores que sale junto a este texto?... Justamente esa imagen la genera el comodín que estamos referenciando.

No solo sirve para recibir y mostrar datos de texto, sino al ser un fichero del lenguaje php, pueden mostrarse imágenes y otros tipos de ficheros (veremos si en el futuro aprovechamos más esa característica).

ocio También las imágenes se pueden recoger de otros dominios y dimensionarlas a gusto como la que está minimizada junto a este párrafo; mostrándola ampliada a continuación (con javascript activado se puede distinguir los cambios de tamaño en el mismo recuadro; en caso contrario deberá aparecer un botón para mostrarla en una ventana nueva).


Imagen de fondo


El extra "escalar" tiene el siguiente código:

$url = $_GET["url"];
$soy_fichero = is_file($url);
list ($ancho, $alto, $tipo) = @getimagesize($url);
if ($ancho)	{
	if (isset($_GET["max"]))	{
		$img = imagecreatefromstring(file_get_contents($url));
		$ratio = ($ancho > $alto) ? $max / $ancho: $max / $alto; 
		$anchito = $ancho * $ratio;
		$altito = $alto * $ratio;
		$mini = imagecreate($anchito, $altito);
		$fondo = imagecolorallocate($mini, 0, 0, 0);
		imagecolortransparent($mini, $fondo);
		imagefill($mini, 0, 0, $fondo);

		imagecopyresampled($mini, $img, 0, 0, 0, 0, $anchito, $altito, $ancho, $alto);
		header("Content-Type: image/png");
		imagepng($mini);
		imagedestroy($mini);
	}
	else	{
		$img = imagecreatefromstring(file_get_contents($url));
		header("Content-Type: image/png");
		imagepng($img);
		imagedestroy($img);
	}
}
else	{
	$img = imagecreatefromstring(file_get_contents("dibujos/miemoticon.gif"));
	header("Content-Type: image/gif");
	imagegif($img);
	imagedestroy($img);
}
unset($css);
unset($body);

Ya habíamos indicado en otro apunte como ver el código del comodín (con el extra "mostrarme").






Titulo: Este diario: Mejoras en los comentarios


emoticón de Caricatos Publicado el día 17 de julio de 2011
id=33

Sabíamos que tarde o temprano nos visitarían los spamers (léase "mamarrachos") introduciendo basura en nuestro sistema de comentarios, así que nos hemos visto obligados a retocarlo. Queríamos algo rápido de implementar para evitar en adelante que cuelen más basura así que pensamos en algo provisional, pero fácil de modificar.

Cavilaciones

Consideramos el sistema de comentarios que sirvió de referencia para este diario ("Ponga comentarios en su web"), pero pensamos que obligar a introducir una dirección de correo electrónico para la validación podría evitarse, así que decidimos que en un principio la activación la haga el webmaster del sitio; y así funciona actualmente (posiblemente la implementación será mixta).

Para facilitar las tareas de administración, hemos añadido en el listado de comentarios una marca indicando si existen comentarios sin activar, y de paso también añadimos el número de comentarios de cada apunte. Revisando el código de nuestro editor donde listamos los comentarios tenemos estas nuevas líneas:

_nuevos_ = items[i].getElementsByTagName("id")[0].getAttribute("nuevos");
_activos_ = items[i].getElementsByTagName("id")[0].getAttribute("activos");
_coletilla_ = (_nuevos_ == "0") ? "": "*";
_coletilla_ += (_activos_ == "0") ? "": " (" + _activos_ + ")";

La variable que hemos llamado "_coletilla_" es la encargada de mostrar los datos antes comentados, aunque sólo sea accesible durante la administración del diario.

También tuvimos que modificar en la página principal el proceso de envío de los comentarios ya que después de una inserción se redirigía al nuevo mensaje insertado pero al dejar de automatizarse el proceso, la redirección se hace hacia un recuadro que informa del estado del comentario:


Se notificará al webmaster sobre el nuevo comentario.
En breve se activará...

Y hemos mantenido los antiguos mensajes de error cuando no era correcto el código de seguridad o no se insertase un comentario (puede notarse con javascript desactivado).

Resultados

Aunque hemos recibido más basura, al no publicarse en ningún sitio esperamos que dejen de enviarla; de todos modos estamos trabajando en ampliar o mejorar la seguridad del sistema.






Titulo: Este diario: Mapa del sitio vs. sitemap


emoticón de Caricatos Publicado el día 30 de julio de 2011
id=34

A la derecha de la página junto al enlace de sindicación, podemos encontrar el "Mapa del sitio" donde estamos intentando que se localicen todas las páginas del diario y también del dominio.

Aunque Mapa del sitio sería la traducción de sitemap, en este caso usaremos "sitemap" como mapa orientado a buscadores, y "mapa del sitio" será una referencia para la navegación de nuestros visitantes; presente también a pie de página.

Todo al alcance de un click

Si pulsamos en nuestro Mapa encontraremos diferentes listas que, a pesar de que muchas de ellas están presentes durante la navegación normal, están mostradas en su totalidad (cosa que no sucede justamente con los apuntes). Además podemos encontrar todas nuestras imágenes.

El caso concreto de las imágenes, tiene una característica especial ya que cada una tiene asignada una ficha con su nombre, descripción y catalogación. Otro caso para destacar es el apartado "Otras páginas del dominio" ya que es una recopilación de antiguas páginas que en muchos casos son ficheros html con la consecuente carencia de dinamismo.

Las vicisitudes

Antes de escribir este apunte, usabamos un documento que leía las tablas afectadas y mostraba los resultados de las búsquedas completas de cada tabla cada vez que entrábamos a la página, pero nos ha parecido un gasto de recursos innecesarios y por ello generamos el resultado solo una vez y lo volcamos a un fichero con extensión "html" que solo se modificará con la inserción de nuevos apuntes (o imágenes, o categorías, o etiquetas).

Teniendo el sistema de generación del sitemap para los buscadores, tan solo hemos añadido un elemento indicando de qué listado se trata, simplemente indicando de qué tabla se obtienen los datos, con la única excepción del caso "archivos", cuyos datos también se obtienen de la tabla "apuntes".

Archivos y apuntes

Acabamos de comentar que estos dos listados provienen de una sola tabla, y a continuación indicaremos cómo resolvimos el asunto; y a la vez cómo conseguimos el mensaje "contextual" (lo que se asigna al atributo title del lenguaje html).

La tabla es leída ordenada por fechas (orden inverso), rescatando el título tanto para indicarlo en el listado como para generar el enlace usando urlencode; y el mensaje contextual se corresponde con el texto descriptivo usado para la sindicación. Para evitar incluir etiquetas html en el texto descriptivo las hemos filtrado.

Para el caso del listado de "archivos", hemos convertido la fecha de publicación de los apuntes en el texto que servirá de enlace: "mes año", y por mensaje contextual listamos los apuntes, que durante la lectura habíamos encadenado separando los mismos con una barra vertical. Los códigos de filtrado se ven a continuación:

	$codigos = array(
		"/\<(.*?)\>(.*?)\<\/(.*?)\>/is",
		"/|/is"
	);

	$reemplazos = array(
		"$2",
		"\
"
	);

	$title = preg_replace($codigos, $reemplazos, $descripcion);

También hemos considerado la eliminación de barras adicionales añadidas por el lenguaje usando stripslashes.






Titulo: Este diario: BBCodes en comentarios


emoticón de Caricatos Publicado el día 11 de septiembre de 2011
id=39

insertar foto Los comentarios a los apuntes eran demasiado básicos así que hemos decidido enriquecerlos algo con unas pocas variantes: negritas, cursivas y subrayados con respecto al texto, a la vez que permitimos la inserción de imágenes y enlaces.

También hemos modificado los párrafos para que se lean con el típico formato de párrafos del idioma (sangrando la primera línea y sin separación ente párrafos), distinguiendolos del odioso formato típico anglosajón, que lamentablemente está siendo adoptado por no programar las pocas líneas necesarias para el caso.

insertar foto Sobre las imágenes, debemos especificar su ubicación en Internet, y no importa que se encuentren en otro dominio; claro está que nos reservamos el derecho de mostrarlas para evitar mal intencionados (al igual que podemos borrar el comentario directamente, evitando entre otras cosas el spam).

Hemos comentado que se trata de pocas líneas de código, y en concreto son las siguientes:

$bbcodigos = array(
	"/[n](.*?)[/n]/",
	"/[c](.*?)[/c]/",
	"/[s](.*?)[/s]/",
	"/[url=(.*?)](.*?)[/url]/",
	"/[img](.*?)[/img]/",
	"/\r/",
	"/\n\n+/",
	"/\n/"
);	
$bbreemplazos = array(
	"<b>$1</b>",
	"<i>$1</i>",
	"<u>$1</u>",
	"<a href="$1">$2</a>",
	"<img src="$1" alt="imagen insertada" />",
	"",
	"</p><br/><p>",
	"</p><p>"
);

// y se aplica...
$mensaje = preg_replace($bbcodigos, $bbreemplazos, $mensaje);

Los últimos dos códigos son los referentes a los párrafos "a la española", donde en vez de insertar un salto de línea, se cierra el párrafo abierto y se inicia uno nuevo. Los estilos usados en los párrafos son:

p	{
	text-indent: 3em;
	margin: 0 1em;
}

Creo que no es necesario comentar el sistema de enriquecimiento de texto, ya que es el mismo en todos los sitios que se implementan.

¿Y los emoticones?

Por ahora solo hemos añadido un emoticón básico ";-)", pero al tratarse de imágenes, solo basta con insertar la dirección del que se desee añadir, con el botón de inserción de imágenes.






Titulo: Este diario: Comentarios y seguridad


emoticón de Caricatos Publicado el día 18 de septiembre de 2011
id=40

¿virus? No creía que pudieran usar una página mía para enviar mensajes "basura" de forma masiva, y aunque también se puede considerar un halago el hecho de que nos considerasen (aunque para tan despreciable motivo), nos obliga a revisar nuestro sistema de seguridad.

Mientras escribimos estos primeros párrafos nos han intentado colar varios mensajes que con un sencillo cambio en el sistema de seguridad hemos evitado satisfactoriamente.

Captcha

Las imágenes "captcha" son tal vez las primeras medidas de seguridad que se hayan creado, y en teoría se trata de una buena medida, ya que el texto que aparece se encuentra en una imagen, y para saberlo con técnicas automatizadas debemos usar algoritmos OCR, nada fáciles de implementar.

Para generar nuestro captcha, generamos en nuestro mismo fichero php una variable de sesión con el código de seguridad, y a partir de esos caracteres creamos nuestra imagen (en nuestro caso concreto un número de seis cifras). La validación solo puede hacerse en el servidor durante el envío de datos, sumando a los datos normales el código de seguridad; y su chequeo es una simple línea de código:

$captcha_bueno = ($_POST["captcha"] == $_SESSION["captcha"]);

Un añadido de seguridad es que si intentamos copiar la imagen para su tratamiento con terceros programas, será una copia distinta a la de la página, y en consecuencia se obtendrán datos erroneos.

Alternativas

Los ataque que hemos tenido por el momento han sido en inglés, así que nuestra primera alternativa será que escriban algo en español (no sólo números como hasta ahora).

Al leer la nota importante de nuestro formulario de comentarios descubrimos (en español) que el recuadro para el código de seguridad, debemos llenarlo con una palabra que hemos resaltado cambiando su color. Tal vez no sea un método bueno, pero hasta que los "mamarrachos spammers", si siguen interesados en llevar a cabo sus intenciones por medio de esta página, lean y traduzcan el texto y programen algo que les sirva, posiblemente ya habramos madurado otras formas de mejorar nuestra seguridad.

El sistema consiste en convertir la frase en un array de palabras, y seleccionar aleatoriamente una a la que le aplicaremos el efecto estético deseado (colorear), y guardaremos en una variable de sesión que nos servirá en el chequeo del código de seguridad:

$frase = explode(" ", "Estamos modificando el sistema...");
do	{
	$posi_palabra = rand(0, count($frase));
	$pasa_palabra = $frase[$posi_palabra];
}	while (strlen($pasa_palabra) < 3);
$_SESSION["palabra_seguridad"] = $pasa_palabra;
$frase[$posi_palabra] = "<span style="color: red" >$pasa_palabra</span>";
$frasesita = implode(" ", $frase);

Solo queda modificar el chequeo en el servidor:

$buena_seguridad = ($_POST["captcha"] == $_SESSION["palabra_seguridad"]);





Titulo: Este diario: Valorar contenido


emoticón de Caricatos Publicado el día 09 de octubre de 2011
id=44

Sol Se puede notar en esta página una pequeña modificación junto a la zona de comentarios; se trata de otra zona pero en este caso reservada a evaluar los contenidos.

El sistema de valoración se asemeja al de los artículos y utilidades de otra página del autor: Caricatos.net, y se explica su implementación en "Ponga comentarios en su web", con muy pocas diferencias.

Un voto por máquina

Para evitar comportamientos tiránicos a la hora de emitir la valoración, solo se admite un valor por máquina (discriminando la dirección IP de la misma), para este objetivo, hemos creado una tabla para las valoraciones con la siguiente estructura:

CREATE TABLE 'diario_valores' (
	'pagina' varchar(200),
	'valor' int(11),
	'ip' varchar(15),
	'id' int(11) AUTO_INCREMENT,
	KEY 'id' ('id')
);

De este modo consultando la existencia de un valor para la página e IP correspondiente, se efectúa una transacción de insersión o modificación del valor.

Valoración media

Una de las diferencias con el sistema original es el cálculo de la media de todas las valoraciones dadas, y el resultado se muestra directamente presentando la imagen (consultando la tabla de valores previamente).

$sql = "select sum(valor) as total, count(valor) as cuantos from $tabla_valores where pagina='$pagina'";
// Recibimos los valores en la variable $datos...
	$total = $datos["total"];
	$cuenta = $datos["cuantos"];
// Hacemos el cálculo, previos chequeos para evitar errores como una división por cero...
	$porcentuar = (int) ($total / $cuenta * 10);
// Y creamos la variable que usará el sistema (véase el código original en la página antes citada...
	$fondos = "eeeeee-$porcentuar-ffcc00";

Las imágenes son generadas en blanco (Diez estrellas blancas.) cuando no existe ninguna valoración o no existe la página indicada.






Titulo: Este diario: Más comentarios


emoticón de Caricatos Publicado el día 17 de octubre de 2011
id=46

Hemos diseñado nuestro sistema de comentarios solo para los apuntes, y ahora lo hemos retocado para que también puedan comentarse los demás elementos. Pero antes de nada era necesario realizar unos cambios para la identificación de la página, y a la vez para obtener las respuestas. Los elementos ya no podían referenciarse solo por el identificador "id", ya que también las imágenes tenían el mismo identificador, así que debíamos añadirle un prefijo.

Preliminares

Debido a que ya teníamos implementado el sistema de identificación también en el sistema de valoración por estrellas, nos decidimos a adaptarlo a ese sistema, añadiendo al id de los apuntes la cadena de texto "apunte."; y en el caso de las imágenes: "imagen.". Hemos creado un comodín con el siguiente código.

$sql = "select referido, id from $tabla_comentarios";
$conexion = mysql_connect($diario_host, $diario_usuario, $diario_pw);
if ($conexion)	{
	if (mysql_select_db($diario_basededatos, $conexion))	{
		$res = mysql_query($sql);
		if ($res)	{
			$datos = array();
			while	($dato = mysql_fetch_array($res))	{
				$id = $dato["id"];
				$ref = str_replace(".", "|", $dato["referido"]);
				$sql = "update $tabla_comentarios set referido="apunte.$ref" where id="$id"";
				array_push($datos, $sql);
			}
			for ($i = 0, $total = count($datos); $i < $total; $i++)
				@mysql_query($datos[$i]);
		}
		else
			echo "imposible leer tabla...".mysql_error();
	}
	else	{
		echo "no se seleccionó nada...";
	}
}
else	{
	echo "imposible la conexión...";
}

Con ese código (que debe ejecutarse una sola vez), cambiamos los puntos (".") de las referencias por el carácter "|", que habíamos usado para el anidamiento de los comentarios (cuidando de arreglarlo también en las presentaciones de los mismos), y le añadimos el prefijo antes mencionado ("apunte.") para dejarmo listo en el momento de hacer las modificaciones.

Para el retorno a la página origen del comentario usamos una variable del sistema ($_SERVER["HTTP_REFERER"]), eliminando si lo hubiese enlaces internos, y aañadiendo un enlace interno hacia el mensaje informativo del éxito de la transacción.

$volver = preg_replace('/#(.*?)$/', "", $_SERVER["HTTP_REFERER"])."$coletilla"#comentarios;
header("Location: $volver");

Tan solo nos queda incluir el módulo de comentarios de la página sin el condicionamiento de que se trate de un apunte, y en la página (ficha) para las imágenes, y a la vez añadir las funcionalidades javascript de edición y validación.

En breve también lo incluiremos en las otras páginas del dominio.






Titulo: Este diario: resumen del año 2011


emoticón de Caricatos Publicado el día 05 de enero de 2012
id=64

Este año que acaba de terminar hemos publicado algo más de una cincuentena de apuntes de diversa índole, pero también hemos modificado algunos aspectos de la misma, tanto estéticos como de funcionalidad.

Con respecto a los contenidos, intentamos que fuesen originales y en lo posible de utilidad, aunque también quisimos ser algo críticos (véase la categoría Mamarrachadas).

Intentamos que todos los apuntes sean fáciles de encontrar desde nuestro Mapa del web, pero también creamos propias herramientas con nuestros comodines. Uno de ellos (el último hasta el momento) nos proporciona el listado anual de nuestros apuntes. Así podemos mostrar el listado de apuntes del año pasado: 2011.

Extras: pocos pero importantes.

Algunos de los extras que hemos implementado son bastante útiles, tanto es así que en este año que comienza reservaremos un rinconcito de la página principal para ellos. Por lo pronto desde hace algunos días hemos añadido el listado de los extras. A continuación listamos algunos:

Listado de extras

Con este comodín, podemos ver todos los extras y los apuntes donde se utilizan. Es el primero incluido en la página principal.

Código de los extras

Desde el listado (item anterior) podemos enlazar para ver su código. Aquí mostramos el suyo propio.

Código del comodín (diario.jocker.php)

Página mágica que permite ejecutar código php guardado en una tabla de la base de datos.

Búsqueda de texto (Novedad) en los apuntes y demás páginas del diario (categorías, etiquetas, extras, imágenes...)

Aunque es un extra de este año nuevo (2012), evidentemente es a consecuencia del incremento de contenidos del sitio.

Resultado de la búsqueda complementando al item anterior.

A continuación podemos ver un resultado: buscar=caricaturas (en la tabla apuntes).

Una característica del comodín asociado a los extras es que el nombre se pasa en la línea de comandos, pero también puede tratarse de valores pasados por formularios con método "post" (http).

Comentarios, seguridad... y otras yerbas.

En un principio solo se podían comentar los apuntes y aunque sea lo más importante, hemos ampliado las posibilidades en el sistema de comentarios pudiéndolo hacer también en las descripciones de categorías, etiquetas e imágenes; y tenemos pensado aún ampliar esa caracteríatica a las viejas páginas del dominio. Éstas últimas también se han añadido durante el 2011.

Con respecto a la seguridad, nos han atacado con spam en numerosas ocasiones, viéndonos obligados a borrar cientos de comentarios; por tal motivo hemos hecho unos retoques en el sistema, y no descartamos seguir en ello.

Otras temáticas que hemos tratado en bastantes ocasiones son las imágenes y postales, donde hemos retocado un viejo editor de postales para poderlas guardar y editar; así como hemos hablado en muchas ocasiones de manipulación de imágenes.

También hemos comentado algunas cosas del mundo de las caricaturas y los caricaturistas.






Titulo: Este diario: Sindición extra


emoticón de Caricatos Publicado el día 12 de enero de 2012
id=66

Cuando hemos tratado el "resumen del año 2011" mostramos unos nuevos extras que implementamos recientemente, y ahora que empiezan a ser considerables, nos ha parecido buena idea mejorar el rincón dedicado a los extras que tenemos en la página.

Entre esas nuevas implementaciones acabamos de realizar una que permite sindicar automáticamente los propios extras y que en la nueva sección aparece con el clásico dibujo de sindicación de contenidos: sindicar extras .

Preliminares

Para que el enlace al archivo "rss" fuera legible hemos creado también un fichero "xsl" para que se vean los extras como una lista:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="www.w3.org/1999/xlink">
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="rss/channel/title" /></title>
<style type="text/css">
<![CDATA[
*	{
	margin: 0;
}
h1	{
	text-align: center;
	background-color: #eeeeee;
	padding: 1em;
}
dl	{
	margin: 1em;
	padding: 1em;
	border: 3px ridge blue;
}
dd	{
	text-indent: 2em;
}
#pie	{
	background-color: #eeeeee;
	padding: 10px 0;
	clear: both;
}
h6	{
	text-align: center;
	margin: 0;
}
]]>
</style>
</head>
<body>
<h1>
<xsl:value-of select="rss/channel/title" />
</h1>
<dl>
<xsl:for-each select="rss/channel/item" >
<dt>
<a href="{link}"><xsl:value-of select="title" /></a>
</dt>
<dd><xsl:value-of select="description" /></dd>
</xsl:for-each>
</dl>
<div id="pie">
	<h6>
		<span style="font-weight: bolder">Copyright © 2002-2012 <a href="index.php">www.pepemolina.com</a></span>
		<br/>
		<a href="diario.rss.xml" >RSS
			<img src="diario.imagen.php?id=22&max=10" alt="rss" title="rss" longdesc="diario.ficha.php?id=22" />
		</a>
		| Ver
		<a href="diario.sitemap.html" >
			Mapa del sitio
		</a>
	</h6>
</div><!-- id="pie" -->
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Y para descripciones hemos usado el típico BBCode que en nuestro caso son del tipo &#91;rss&#93;Descripción&#91;/rss&#93;. El código puede verse con este otro comodín: Código del extra "extras_xml". Nótese como la "descripción" se añade en un comentario del código.

// descripción para la sindicación:
/*
	&#91;rss&#93;Con este comodín podemos obtener el listado de extras del diario en formato rss (xml).&#91;/rss&#93;
*/

Algunos extras destacados

Aparte de los que se han añadido en el nuevo sector reservado a los extras, destacamos los relacionados con manipulación de imágenes:

Paleta Web Marco ovalado esquinas redondeadas círculo azulado banderita flameante

En el recuadro hemos utilizado los siguientes comodines:






Titulo: Este diario: filtrando historial de navegación


emoticón de Caricatos Publicado el día 18 de febrero de 2012
id=72

A medida que vamos visitando las distintas páginas del diario (empiezan a ser muchas), notamos como se va incrementando el historial de navegación que tenemos a pie de página.

Ya habíamos comentado la gestión de esa lista en el apunte: "Este diario: Historial de navegación", y vimos que se trata simplemente de una variable de sesión de tipo array (arreglo) cuyo índice se incrementa con cada nueva visita; también llevando el control de las posibles duplicidades.

Hemos aprovechado nuestro nuevo sistema de complementos para utilizar uno para eliminar los que no nos interesa tener en la lista del historial; podiéndose usar desde un enlace al complemento, o desde el propio listado que se ve a pie de página, donde hemos puesto unos controles de selección y un botón para tal fin programado con Ajax.

Turno de códigos

La verdad es que hay poco código para mostrar, pero hay va el listado:

function navegando($item)	{
	list ($_t, $_p, $_n) = split("=", substr($item, 1));
	list ($__t, $__p) = split("&", $_p);
	$coletilla = ($_n == "") ? "": " [$_n]";
	if ($__t == "vistos")
		$__t = "Los más vistos";
	else
		$__t = urldecode($__t);
	$coletilla = (in_array($_t, array("mostrar", "titulo"))) ? "": "($_t)";
	$coletilla.= ($_n == "") ? "": " [$_n]";
	return "$__t $coletilla";
}

if (isset($_SESSION["historico"])) {
	$listado = array();
	for($i = 0, $total = count($_SESSION["historico"]); $i < $total; $i++)	{
		$h = $_SESSION["historico"][$i];
		if ($h != "")	{
			$item = "<label> <input type='checkbox' name='h[]' value='$h' checked='checked'/> ";
			$item .= navegando($h)."</label>";
			array_push($listado, $item);
		}
	}
	$lista = implode("<br/>\n", $listado);
	$form = <<< formulario

<form action='?plugin=modificar_historial' method='post' >
$lista

<br/>
<br/>
<button type="submit">Actualizar historial</button>
</form>

formulario;

}

Sobre el código podemos ver que simplemente se trata de un formulario con el listado de páginas visitadas acompañadas de un botón de envío del mismo (hemos obviado los elementos estéticos del mismo), pero si bien es sorprendente la sencillez del código, más sorprendidos estaremos viendo el código receptor del formulario:

if (isset($_POST['h']))
	$_SESSION["historico"] = $_POST['h'];
else
	$_SESSION["historico"] = array();

Me encanta cuando mostramos código sencillo y útil (al menos para quien piense implementar un sistema de páginas visitadas como en nuestro diario).

El toque "Ajax"

Desde el complemento faltaría en el código un simple redireccionamiento al listado de complementos u otro sitio que se nos ocurra oportuno, pero con ajax debemos mantenernos en la misma página así que debemos hacer una última discriminación. Creo que mostrando el resto del código tendría que ser suficiente:

if (isset($_POST["ajax"]))	{
	unset($body);
	unset($css);
	echo "Ok";
}
else
	header("Location: ?plugin=listado_plugins");

¡Sí!, en la página principal con el envío enviamos también el parámetro "ajax", y no importa con que valor. Por semántica hemos puesto "ajax=si", aunque con un valor "no", evidentemente también nos serviría.






Titulo: Este diario: Gestión de imágenes


emoticón de Caricatos Publicado el día 25 de febrero de 2012
id=73

Nos gustaría ver en las búsquedas de imágenes de los más importantes buscadores las que estamos insertando en nuestros apuntes, y por ello nos hemos decidido a realizar unas pocas modificaciones en nuestro sistema cuyo funcionamiento hemos explicado en el apunte Este diario: Las imágenes. Esas modificaciones las detallaremos a continuación.

Toda página web "bien hecha", tiene elementos descriptivos o informativos acerca de su contenido, entre ellos existe uno obligatorio: el título; que evidentemente siempre hemos contemplado tanto en la etiqueta title (título), obligatoria en la sección de cabecera de la página (head), como para usarlo de cabecera de primer nivel de la página (etiqueta h1).

Palabras clave (keywords)

Las palabras claves son una lista de palabras que teóricamente deberían ser una ayuda para los buscadores aunque hay publicaciones que niegan tal característica (en casos concretos); de todos modos por coherencia hemos considerado incluírlas en nuestras fichas para las imágenes.

Vincent Van-Gogh Vamos a empezar viendo los resultados con la caricatura de Vincent Van Gogh que mostramos junto a estas líneas, subida hace unos pocos días.

En primer lugar tenemos que saber como añadir esos elementos en nuestro sistema, donde tenemos una tabla para nuestras imágenes, pero entre sus campos no tenemos ninguno para las palabras clave o keywords. Basándonos en el apunte Sencilla gestión de una base de datos: estructuras, y aprovechándonos de nuestro recientemente estrenado sistema de complementos explicado en otro de los últimos apuntes: Metamorfosis con dos ficheros y una tabla, hemos añadido a nuestra tabla de imágenes un nuevo campo del tipo text llamado keywords. Simplemente hemos tenido que usar una instrucción sql "alter table".

También hemos creado otro complemento para editar ese nuevo campo que inicialmente estará vacío, pero antes crearemos uno similar al que está en el apunte Sintaxis más entendible para listar las imágenes (no solo las caricaturas como se puede ver en el apunte citado), pero se diferenciará básicamente por estar enfocado a la gestión de esas palabras clave: Listado de imágenes...

Para mejorar aún más la gestión, añadimos también en el listado el resto de campos importantes como descripción y categoría, presentando también el texto que se añadiría en otro elemento que describiremos a continuación.

Descripción (meta description)

Otro elemento importante para los buscadores es un elemento que especifica la descripción de la página y que en nuestro caso creemos oportuno que sea el mismo texto que usamos en la sindicación (rss).

Resumiendo, en esta imagen concreta tenemos como descripción el texto:

Vincent Van Gogh, Pintor holandés del siglo XIX considerado un genio de la pintura.

Y estas palabras clave:

impresionismo, pintura, caricatura de Van Gogh

También se referencian todas las imágenes tanto en el mapa del sitio (sitemap) que se envía a algunos buscadores, como en el listado de imágenes que hemos añadido como extra. A medida que vaya progresando el proceso de búsqueda, seguiré informando.






Titulo: Este diario: Top 10


emoticón de Caricatos Publicado el día 19 de junio de 2012
id=88

Como habíamos adelantado, hemos reemplazado la sección "Últimos apuntes" por otra que llamamos "Top 10" (los 10 apuntes más leídos). Los motivos y parte de los códigos ya la habíamos explicado en el apunte "Top 10 con Ajax (paginación)", y esa lista resultante está paginada tal como ocurre en el apunte mencionado.

Paso a paso

Para eliminar la vieja sección simplemente la hemos ocultado, y hemos puesto un enlace que la vuelve a mostrarla si fuese necesario. Pudiendo ocultarse nuevamente con un nuevo click.

var mostrar_últimos = true;
function mostrando_ultimos(e)	{
	tag("ultimos").style.display = (mostrar_últimos) ? "block":"none";
	mostrar_últimos = !mostrar_últimos;
	cancelar_evento(e);
}

Luego añadimos la nueva sección mostrando la primera de las páginas y resaltando el número uno (1) en el listado de páginas, y asignamos estilos iguales al resto de los sectores. Ese número resaltado, en principio enlaza con la misma página que anteriormente había para mostrar los apuntes "más leídos", ya que siempre hay que considerar a los visitantes que no tengan javascript activado.

Ya resuelto el aspecto visual nos toca trabajar en el aspecto funcional, que comentaremos a continuación.

Paginando

Ya adelantamos el código en el otro apunte antes mencionado y que podemos ver en este enlace, así que tan solo debíamos reutilizarlo con algunas modificaciones. El volcado de los resultados en ambos casos se realizan en listas (obvio), pero las listas que usamos en nuestras distintas secciones son las desordenadas (ul: unordered lists), y en el apunte habíamos usado las listas de definiciones (dl: definition lists) que hemos considerado semánticamente mejor pudiendo discriminar entre términos y definiciones.

La petición Ajax es exactamente igual (se puede comprobar forzando el enlace, tal vez en una nueva ventana o pestaña), enlazando a la misma página con los mismos parámetros, pero mostrando los resultados con otro formato. Por ejemplo, la descripción o definición se asigna al atributo title de cada enlace.

Asignando los eventos y enlaces

Para terminar solo nos queda definir las funciones que usaremos en nuestra nueva sección que son las peticiones Ajax y le reasignación de enlaces. Los enlaces son hacia los listados en formato rss (para poderlos considerar con el menú contextual), y serán cancelados con las peticiones Ajax.

Quiero destacar que esas peticiones no son redundantes, ya que por cada petición se crea una lista nueva, ocultando la anterior para tan solo modificar los estilos de visualización si necesitamos volverlas a mostrar. Sabiendo que será la primera página la única visible y existente, inicializamos una variable con ese dato:

ultimo_tope = "1";
var lista_tope = {};
lista_tope[ultimo_tope] = {"visible": true};

Para luego considerar esa existencia a la hora de paginar.

	if (lista_tope[pag] == undefined)	{
		// creamos la variable de referencia y realizamos la petición Ajax
		lista_tope[pag] = {"visible": true};
		//...
	}
	else	{
		if (ultimo_tope == pag)	alert("Se encuentra en la paginación " + pag)
		else	{
			tag("topes_" + ultimo_tope).style.display = "none";
			ultimo_tope = pag;
			tag("topes_" + ultimo_tope).style.display = "block";
		}

	}





Titulo: Este diario: sitemap.xml


emoticón de Caricatos Publicado el día 17 de octubre de 2012
id=98

Hemos tenido un pequeño problema con la generación de nuestro "sitemap.xml" debido a que ha crecido bastante el contenido de esta página, por lo que hemos decidido revisarlo minuciosamente.

En concreto, tan solo obteníamos unas pocas más de cien entradas, así que lo estamos re-implementando.

Los enlaces

Estamos interesados en que nuestras enlaces se generen correctamente así que hemos revisado que no exista ningún error en su localización.

Hemos descubierto algunos enlaces, sobre todo de imágenes que estaban mal referenciadas, así que decidimos hacer una búsqueda generalizada de enlaces, sobre todo descubrir los enlaces internos y eliminar la ruta absoluta de los mismos. Para ello hemos acudido a nuestro buscador interno (sección "Extras"), seleccionamos todas las tablas y en el campo de búsqueda insertando el nombre de nuestro dominio, obteniendo el listado de páginas que en su contenido se encuentra: pulse para ver ese resultado.

Revisando las páginas obtenidas en nuestra búsqueda, descubrimos que son casos con recortes de imágenes, y nuestro sistema necesita esa ruta completa para su funcionamiento, así que decidimos realizar las búsquedas algo más complejas, añadiendo al principio de la cadena a buscar los atributos donde va el nombre del dominio (href=", src="); chequeando también las mismas cadenas pero con comillas simples.

Las imágenes

La referencia de imágenes en el sitemap puede hacerse simplemente con su URL (ubicación), o adjuntando más información como un título o una descripción: Sitemaps de imágenes.

Revisando nuestro Listado de imágenes se nos ha ocurrido que podríamos aportar un título (nombre -> image:title) y una descripción (Resúmen -> image:caption). Para obtener esos datos desde la tabla de imágenes implementamos este código:

// Declaramos el array images para guardar información de nuestra tabla.
$images = array();

$sql = "select id, titulo, descripcion from $tabla_imagenes";
$res = @mysql_query($sql);
while ($dato = mysql_fetch_array($res))    {
	$id = $dato["id"];
	$titulo = $dato["titulo"];
	preg_match('/\[rss\](.*?)\[\/rss\]/is', $dato["descripcion"], $des);
	$info = preg_replace(array('/\<(.*?)\>/','/\"/'), '', $des[1]);
	$images[$id] = array("titulo" => $titulo, "info" => $info);
}

Ahora debemos buscar en los contenidos de las páginas que referenciamos en nuestro sitemap las imágenes y en el caso de que sean de nuestra tabla de imágenes, rescatar esa información adicional que hemos reseñado. Al tratarse de un mismo código para todos los textos, hemos implementado una función:

function sacaImagenes($texto)	{
	global $images, $diario_ruta;
	preg_match_all('/\<img src=\"(.*?)\"/is', $texto, $_imagen);
	$imgs = array();
	for ($i = 0, $total=count($_imagen[1]); $i < $total; $i++)
	if (substr($_imagen[1][$i], 0, 7) != "http://")	{
		$_src = $_imagen[1][$i];
		$_ids = substr($_src, 0, 17);
		$_id = false;
		if ($_ids == "diario.imagen.php")	{
			preg_match("/id=(\d*)/is", $_src, $__id);
			if (array_key_exists($__id[1], $images))	$_id = $__id[1];
		};
		if ($_id != false)	{
			$_titulo = $images[$_id]["titulo"];
			$_info = $images[$_id]["info"];
			array_push($imgs, array("loc" => "$diario_ruta/$_src", "title" => $_titulo, "caption" => $_info));
		}
		else	{
			array_push($imgs, array("loc" => "$diario_ruta/$_src"));
		}
	}
	return $imgs;
}

Con esa función obtenemos un array con los datos de las imágenes encontradas y que pertenecen al dominio por tener una ruta relativa.

Ahora nos queda mostrar las imágenes:

//$item es el objeto con los datos de una entrada del sitemap
//$item["images"] es el array de imágenes asociado al "$item"
while (count($item["images"]) > 0)	{
	$imagenes = array_pop($item["images"]);
	$lista .= "\n\t<image:image>";
	foreach($imagenes as $itemImage => $itemsito)
		$lista .= "\n\t\t<image:$itemImage><![CDATA[".$itemsito."]]></image:$itemImage>";
	$lista .= "\n\t</image:image>";
}

La experiencia de adaptar nuestro sitemap para referenciar nuestras imágenes nos ha servido para plantearnos futuros retos que en breve iremos comentando.

Prioridades

A pesar de que el valor "priority" de las entradas del sitemap no es relevante, pensamos que si podemos ofrecer mayor información de nuestro sitio será mejor valorado por los buscadores, así que nos atrevimos a implementar un sistema que genere un valor coherente para ese atributo.

Teniendo como base que los valores admitidos están entre el cero (0) y el uno (1), creemos oportuno darle valor "1.0" a la página principal. Las demás páginas tendrán como mínimo el valor "0.5", y dependerá de las visitas que hay registradas; por último dependiendo del tipo de página le daremos una prioridad mayor o menor. Con el código que mostramos a continuación apreciaremos esa discriminación:

$datosPrioridades = array(
	"apunte" => array("tope" => 4, "min" => false, "max" => false),
	"archivos" => array("tope" => 2, "min" => false, "max" => false),
	"imagen" => array("tope" => 4, "min" => false, "max" => false),
	"categoria" => array("tope" => 3, "min" => false, "max" => false),
	"etiqueta" => array("tope" => 3, "min" => false, "max" => false),
	"extra" => array("tope" => 3, "min" => false, "max" => false),
	"pagina" => array("tope" => 4.5, "min" => false, "max" => false)
);

Los tipos de páginas que tenemos en el sitemap son como puede apreciarse: apuntes, archivos, imágenes, categorías, etiquetas, extras y páginas. El valor que etiquetamos como tope es el máximo que sumaremos al "0.5" mínimo que ya hemos comentado, y ese tope coincidirá con el número máximo de visitas correspondientes a cada tipo (dividido por diez)... ¡Sí, sí!, todo un galimatías, por eso nos fiaremos que se entienda con el código:

function prioridad($tipo, $cual)	{
	global $datosPrioridades, $contadores;
	$yo = $contadores["$tipo.$cual"];
	$tope = $datosPrioridades[$tipo]["tope"];
	$min = $datosPrioridades[$tipo]["min"];
	$max = $datosPrioridades[$tipo]["max"];
	return number_format(0.5 + ($tope * (($yo * $min) / ($max * $min)) / 10), 2);
}

Este código nos devuelve un número entre "0.5" y un valor máximo igual al tope dividido 10... o sea entre 0.5 y 0.9 en los apuntes; entre 0.5 y 0.95 en el tipo "página", etc.

Nos falta explicar de donde sale esa variable "$yo" de nuestro código, que evidentemente es un valor numérico obtenido desde un array, en concreto el número de veces que fue visitada la página:

$contadores = array();
$sql = "select pagina, cuenta from $tabla_contadores order by pagina";
$res = @mysql_query($sql);
while ($dato = mysql_fetch_array($res))	{
	$pag = $dato["pagina"];
	$cuenta = $dato["cuenta"];
	$contadores[$pag] = $cuenta;
	list($tipo) = explode(".", $pag);
	if (!$datosPrioridades[$tipo]["min"])	{
		$datosPrioridades[$tipo]["min"] = $cuenta;
	}
	elseif ($cuenta < $datosPrioridades[$tipo]["min"])	{
		$datosPrioridades[$tipo]["min"] = $cuenta;
	}
	if (!$datosPrioridades[$tipo]["max"])	{
		$datosPrioridades[$tipo]["max"] = $cuenta;
	}
	elseif ($cuenta > $datosPrioridades[$tipo]["max"])	{
		$datosPrioridades[$tipo]["max"] = $cuenta;
	}
}

El código también nos muestra como obtenemos el valor máximo y mínimo de cada tipo de página.

Generando nuestro sitemap.xml

Empezaremos con la cabecera XML:

// La cabecera header se ha usado durante las pruebas...
//header("Content-type: text/xml");
$cabeza =<<< cabecera
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="sitemap.xsl" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
	xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">

cabecera;
$ahora = date("Y-m-d"); 

$lista = "";
$listados = array();

$listados["index"] = array("link" => $diario, "fecha" => $ahora, "images" => array(array("loc" => "$diario_ruta/caricatos.ico", "title" => "icono de $diario_titulo", "caption" => "Icono de mi caricatura")), "pri" => "1.0");

Vemos que a la vez que generamos la cabecera, también abrimos la etiqueta "urlset", dejando el contenido en la variable "$cabeza". También tenemos la variable "$ahora" con la fecha actual en formato válido para sitemaps. Un array llamado "$listados" con un elemento "index" que será la primera url del sitemap, y que representará la raíz del mismo. Antes de detenernos en el sentido de la variable "$lista" veremos el tratamiento de un tipo de página: "los apuntes".

$sql = "select id, titulo, apunte, fecha from $tabla_apuntes where activo > 0 order by fecha desc"; 
$res = @mysql_query($sql); 

while ($dato = mysql_fetch_array($res))    {
	$id = $dato["id"];
	$titulo = $dato["titulo"];
	$link = $diario."?titulo=".urlencode($titulo);
	$fecha = substr($dato["fecha"], 0, 10);
	$imgs = sacaImagenes($dato["apunte"]);
	$listados["apunte.$id"] = array("link" => $link, "fecha" => $fecha, "images" => $imgs, "pri" => prioridad("apunte", $id));
	list($aaaa, $mm) = explode("-", $fecha);
	$cadena_archivos = $mes[$mm]." $aaaa";
	if (!isset($archivos[$cadena_archivos]))	$archivos[$cadena_archivos] = array();
}

Omitiremos explicar las tres últimas líneas del código ya que solo sirven para obtener los datos de las secciones "archivos", pero puede notarse que se van generando elementos del array "$listados" con los datos que usaremos en cada etiqueta "url" de nuestro sitemap.

El siguiente código es concretamente el que genera todas las "url"s:

foreach ($listados as $dato => $item)	{
	$lista .= "<url>\n\t";
	$lista .= "<loc>".$item["link"]."</loc>";
	if (isset($item["fecha"]))
		$lista .= "\n\t<lastmod>".$item["fecha"]."</lastmod>";
	$lista .= "\n\t<changefreq>never</changefreq>";
	$lista .= "\n\t<priority>".$item["pri"]."</priority>";
	while (count($item["images"]) > 0)	{
		$imagenes = array_pop($item["images"]);
		$lista .= "\n\t<image:image>";
		foreach($imagenes as $itemImagen => $imagen)
			$lista .= "\n\t\t<image:$itemImagen>$imagen</image:$itemImagen>";
		$lista .= "\n\t</image:image>";
	}
	$lista .= "\n</url>\n";
}

Para terminar cerramos esa etiqueta "urlset" y volcamos el sitemap:

$sitemap = "$cabeza\n$lista\n</urlset>\n";
file_put_contents("sitemap.xml", $sitemap);

Nos falta...

La prueba de fuego

Es hora de generar el sitemap y probarlo en las herramientas para webmaster de google...

He de reconocer que el primer intento fue un fracaso por los parámetros que llevaban algunas imágenes, no obstante se ha solucionado sencillamente ya que solo debía cambiar los elementos "&" por su entidad "&amp;". Con el siguiente código:

$_src = preg_replace('/(\&amp;|\&)/', '&amp;', $_imagen[1][$i]);
//$_src = str_replace("&amp;amp;", "&amp;", str_replace("&", "&amp;", $_imagen[1][$i]));

Tenemos más para contar, pero lo dejaremos para más adelante...






Titulo: Este diario: sitemap.xsl


emoticón de Caricatos Publicado el día 26 de octubre de 2012
id=99

Hemos visto como generamos nuestro sitemap.xml, ahora toca hablar de como lo mostramos: sitemap.xsl.

Ya habíamos mostrado códigos "xsl", que puede considerarse como una mezcla de html y xml; como todo código html puede tener estilos y scripts, y como todo xml debe estar bien formado.

HTML: Elección de etiquetas

Para elegir las etiquetas que servirán para mostrar nuestro sitemap.xml, buscaremos las que nos parezcan más apropiadas semánticamente. Tenemos unos párrafos informativos encerrados en una capa donde al cargarse la página nos informa sobre los enlaces existentes:

<div id="info">
<p>
	Para ver las imágenes basta en pulsar en su respectivo enlace.
</p>
<p id="info_enlaces_totales" class="oculto">
	Número de enlaces encontrados: <i id="n_enlaces"></i>:
	(páginas: <i id="info_paginas"></i>,
	imágenes: <i id="info_imagenes"></i>).
</p>
</div>

Nótese que que el segundo párrafo tiene el atributo: class="oculto", que sencillamente no se muestra.

Pero lo que importa es lo que viene: el listado de enlaces del sitemap. Usamos una definición de lista (dl: definition lists), y consideramos como términos (dt: definition term) la etiqueta loc de cada elemento; el resto de los campos los consideraremos descripciones (dd: definition description).

Con las imágenes hemos anidado otra lista pero sin distinciones (ul: unordered list, li: list item). De algunas imágenes tenemos también un título y una descripción (image:title, image:caption), pero su presentación la describiremos más adelante.

Estilos

Tenemos que diferenciar entre los iniciales y los modificados con javascript. Si vemos la página sin javascript tendrá una apariencia un poco distinta; y es que mediante este lenguaje hemos modificado algo la presentación. Por lo pronto, hemos declarado algunos elementos con la clase "oculto" y que sencillamente no se muestran.

Poco más podemos decir de los estilos, así que seguiremos adelante con la programación.

Programación XML

No nos asustemos con la programación XML, ya que es muy básica, simplemente recorrer tados los nodos "sitemap:url", insertándolos en enlaces con class="enlace", dentro de elementos "dt":

<xsl:for-each select="sitemap:urlset/sitemap:url">
	<xsl:variable name="indice">
		<xsl:value-of select="position()" />
	</xsl:variable>

<dt id="dt_{$indice}">

	<xsl:variable name="itemURL">
		<xsl:value-of select="sitemap:loc"/>
	</xsl:variable>
	<a class="enlace" href="{$itemURL}" id="id_{$indice}">
		<xsl:value-of select="sitemap:loc"/>
	</a>

</dt>
<dd class="oculto" id="info_{$indice}"></dd>

<!-- ... -->

</xsl:for-each>

Donde puede apreciarse la creación de la variable "indice", que nos servirá para referencias "javascript". Luego un condicional muestra la etiqueta lastmod si existe:

<xsl:if test="sitemap:lastmod">
<dd>
lastmod: <xsl:value-of select='sitemap:lastmod' />
</dd>
</xsl:if>

Y por último el tratamiento de las imágenes:

<xsl:choose>
<xsl:when test="image:image">
<dd><b>Imágenes:</b><br/>
<ul>
<xsl:for-each select="image:image">
	<li>
		<xsl:variable name="itemSRC">
			<xsl:value-of select="image:loc"/>
		</xsl:variable>
		<xsl:variable name="itemtitle">
			<xsl:value-of select="image:title"/>
		</xsl:variable>
		<xsl:variable name="itemdesc">
			<xsl:value-of select="image:caption"/>
		</xsl:variable>
		<p>
			<a class="imagen" href="{$itemSRC}" title="{$itemtitle}"><i class="oculto"><xsl:value-of select="image:caption"/></i><span><xsl:value-of select="image:loc"/></span></a>
		</p>
	</li>
</xsl:for-each>
</ul>
</dd>
</xsl:when>
<xsl:otherwise>
<dd>*** <i>No hay imágenes</i> ***</dd><br/>
</xsl:otherwise>
</xsl:choose>

Esta presentación cambia al cargarse la página.

Programación javascript

Lo primero que encontramos en el código javascript es un sistema para filtrar entidades del tipo "&amp;":

var entidades = [
	{entidad	: /&amp;/g,
	ente		: "&"},
	{entidad	: /&aacute;/g,
	ente		: "á"},
	{entidad	: /&eacute;/g,
	ente		: "é"},
	{entidad	: /&iacute;/g,
	ente		: "í"},
	{entidad	: /&oacute;/g,
	ente		: "ó"},
	{entidad	: /&uacute;/g,
	ente		: "ú"},
	{entidad	: /&ntilde;/g,
	ente		: "ñ"},
	{entidad	: /&iexcl;/g,
	ente		: "¡"},
	{entidad	: /&iquest;/g,
	ente		: "¿"}
];
	
function filtrar(texto)	{
	for (e in entidades)
		texto = texto.replace(entidades[e].entidad, entidades[e].ente);
	return texto;
}

Luego, al cargarse la página, recorremos todos los enlaces para discriminar los enlaces en sí, de las imágenes; que a la vez incrementan sendos contadores ("_paginas" e "_imagenes") que nos servirán para mostrar datos estadísticos básicos:

window.onload = function()	{
	enlaces = document.getElementsByTagName("a");
	for (i = 0, total = enlaces.length; i < total; i++)	{
		if (enlaces[i].className == "imagen")	tratar_imagen(enlaces[i]);
		if (enlaces[i].className == "enlace")	tratar_enlace(enlaces[i]);
	}
	document.getElementById("n_enlaces").innerHTML = _paginas + _imagenes;
	document.getElementById("info_paginas").innerHTML = _paginas;
	document.getElementById("info_imagenes").innerHTML = _imagenes;
	document.getElementById("info_enlaces_totales").style.display = "block";
}

Los enlaces de imágenes se caracterizan por constar de dos elementos, uno contiene el enlace y el otro su descripción si existiese. En éste último caso se muestra, ocultando la url del enlace. A la vez anteponemos su título.

function tratar_imagen(_a)	{
	_imagenes++;
	if (_a.firstChild.innerHTML != "")	{
		_tex = filtrar(_a.firstChild.innerHTML);
		_a.firstChild.innerHTML = _tex;
		_b = document.createElement("strong");
		_b.appendChild(document.createTextNode(filtrar(_a.title)));
		_a.title = filtrar(_a.title);
		_a.parentNode.insertBefore(_b, _a);
		_a.parentNode.insertBefore(document.createTextNode(": "), _a);
		_a.firstChild.style.display = "inline";
		_a.firstChild.nextSibling.style.display = "none";
	}
}

Sobre el resto de los enlaces, la presentación se modifica dependiendo de los parámetros de los mismos de una manera similar a las imágenes; pero añadimos un botón (y su formulario) para un futuro uso destinado a buscar más información con Ajax.

function tratar_enlace(_a)	{
	_paginas++;
	sumar = document.createElement("form");
	sumando = document.createElement("button");
	sumando.title = _a.href;
	sumando.appendChild(document.createTextNode(" más información... "));
	sumando.onclick = function() {
		yo = this;
		mi_id = urls[yo.title].id;
		tipo = urls[yo.title].tipo;
		valor = urls[yo.title].valor;
		alert("tipo de item (" + mi_id + "): " + tipo + "\nvalor: " + valor + "\nurl: " + this.title + "\n\npor desarrollar...");
		return false;
	};
	sumando.style.marginLeft = "1cm";
	sumar.appendChild(sumando);
	sumar.style.display = "inline";
	tipo = document.createElement("input");
	tipo.setAttribute("type", "hidden");
	tipo.setAttribute("name", "tipo");
	sumar.appendChild(tipo);
	valor = document.createElement("input");
	valor.setAttribute("type", "hidden");
	valor.setAttribute("name", "valor");
	sumar.appendChild(valor);
	pares = _a.href.split("?");

	/*
		Aquí procesamos los parámetros y asignamos los valores (value)
		a los campos tipo y valor del formulario...
	*/

	_a.parentNode.appendChild(sumar);
	urls[_a.href] = {tipo: tipo.value, valor: valor.value, id: _a.id.substr(3), info: ""};
}

En este trozo de código, la alerta que aparece en el botón del formulario la reemplazaremos por la llamada Ajax que mencionamos anteriormente. Seguramente nos ocuparemos de ello en un futuro apunte.

Notas finales

Como consecuencia de la elaboración de nuestro sitemap y su hoja xsl asociada, hemos notado que podemos mejorar algunos aspectos de nuestro sistema. Entre otras cosas, podemos dar un título y su descripción a todas nuestras imágenes, añadiendo esos datos en su tabla correspondiente.

También hemos encontrado algunos valores incorrectos de las direcciones de las imágenes que hemos "maquillado" durante la generación del mapa y pronto arreglaremos.






Titulo: Este diario: Agrupando apuntes


emoticón de Caricatos Publicado el día 27 de noviembre de 2012
id=105

Tenemos muchos apuntes que en realidad son parte de un tema común, así que hemos decidido crear un sistema para agruparlos. Este nuevo "extra" que hemos incorporado en su correspondiente sección y que también está accesible pulsando la imagen que acompaña este párrafo, muestra algunos de esos temas comunes.

Se navega fácilmente con un menú que accede a los grupos; y en éstos tenemos enlaces a los apuntes, y al acabar cada apunte hay un par de botones "svg" que enlazan al tope de la página y al menú de grupos.

Los grupos

Podemos ver en el código fuente de la página (extra) para agrupar apuntes, que para conseguir agruparlos tenemos un array asociativo que vincula un título con una porción de instrucción sql que se corresponde a la cláusula "where" de ésta. A día de hoy tenemos esto (lo iremos ampliando):

$grupos = array	(
	"diario" => array("titulo" => "Sobre este diario", "sql" => "titulo like 'Este diario:%'"),
	"gerona_2011" => array("titulo" => "Minicon Gerona 2011", "sql" => "titulo like '%Gerona%'"),
	"yo_soy_ese" => array("titulo" => "Así me han visto", "sql" => "titulo like 'Así me ha visto:%'"),
	"ajax" => array("titulo" => "Programación Ajax", "sql" => "titulo like '%ajax%' or titulo like '%Mitología%'"),
	"tutor_comentarios" => array("titulo" => "Sistema de comentarios paso a paso", "sql" => "titulo like 'Sistema de comentarios paso a paso:%'"),
	"xml" => array("titulo" => "Ficheros xml", "sql" => "titulo like '%xml%'"),
	"svg" => array("titulo" => "Imágenes svg", "sql" => "titulo like '%svg%'"),
	"sudokus" => array("titulo" => "Sudokus", "sql" => "titulo like '%sudoku%'")
);

Para terminar vamos a recordar que en la sección "Extras" del diario hemos añadido un enlace con la leyenda grupos de apuntes.






Titulo: Este diario: resumen del año 2013


emoticón de Caricatos Publicado el día 07 de enero de 2014
id=129

A lo largo del año 2013 hemos tratado de ampliar nuestros conocimientos sobre las imágenes en formato SVG, y también hemos tratado el juego sudoku, hasta el punto de crear el Sudo-Captcha: Sudoku y Captcha.

Aunque pueda parecer poco contenido, se han tratado de manera bastante minuciosa.

Sobre los Sudokus, hemos empezado creándolos desde una cadena de 81 números que se insertan sobre una especie de tablero/damero de 81 casillas (9 x 9), pero para resolverlos debíamos editar esa lista de números bastante "jeroglíficos"; así que luego hemos tratado la interactividad de esa imagen SVG.

Mientras tanto hemos recopilado una serie de sudokus y los hemos sabido resolver de manera autómata. Con esos pocos sudokus que hemos guardado, conseguimos un buen número de variantes para no aburrirnos de repetir siempre los mismos; y para que sean más vistosos desarrollamos los "de colores".

Con respecto a las imágenes en formato SVG, justamente hemos empezado el año creando sudokus en ese formato; aunque sobre todo hemos tratado los polígonos tanto con las estrellas como con los mapas. Pero también hemos embebido otras imágenes, animándolas, y nos iniciamos con los caminos "path", creando recorridos circulares para alinear texto en ese tipo de curvas.

Por último hemos convertido los polígonos en recorridos "path", y tratamos vagamente los fondos en gradientes.

Completamos este resumen indicando como usar nuestro recurso para hacer postales digitales para insertar imágenes o textos en cualquier página web, y un par de apuntes los hemos dedicado a nuestra serie de apuntes sobre los sistemas de comentarios.

Resumen del 2012

Se nos ha olvidado hacer un resumen del pasado años, así que ahi va.

Desarrollamos algunos trucos gráficos, empezando por generar marcos ovalados en las imágenes, que más tarde hemos personalizado configurando el color y el grosor del borde: Destacamos en otros apuntes algunas zonas, recortándolas y ampliándolas.

Este año, a mediados, empezamos a hurgar en el formato SVG, creando entre otras cosas el mapa de España similar al que ya habíamos mostrado el año anterior. Siguiendo con polígonos (que son cada una de las provincias), hemos dedicado algunos apuntes a crear estrellas, y también las hemos animado; animando también otras imágenes "mapas de bits". También animamos un reloj analógico que se inicia con la hora del sistema, terminando este tema de las imágenes svg interactuando con ellas.

Tratamos paso a paso un sistema de comentarios (aún en desarrollo), pero también le hemos dado un toque "social" al diario con apuntes sobre caricaturas, citas, sintaxis, etc., aunque más han pesado las temáticas de programación (xml, Ajax...)

Para el 2014

Este año que acaba de empezar, tenemos algunas cosas pendientes para desarrollar como generar los sudokus desde cero; crear diseños en svg (más desarrollados), y adentrarnos algo más en la seguridad de las páginas web (constantemente quieren "colarnos" mensajes de "spam", y vulnerar el sistema). Veremos como tratamos estos asuntos...






Titulo: Este diario: Listado de Archivos


emoticón de Caricatos Publicado el día 14 de mayo de 2014
id=135

Entre los recuadros que encontramos a los lados del diario, a la derecha y hacia el final de la página encontramos este listado. Se trata del listado de apuntes organizados por la fecha de publicación. Hasta el momento el listado estaba agrupados por meses, pero empezaba a ser un listado muy extenso, así que lo hemos comprimido.

Ahora hemos agrupado los apuntes por año, que al pulsar despliega los meses que cuentan con apuntes, que a la vez se despliega con los títulos de cada apunte. Tanto el listado de años como el de los meses tienen entre paréntesis el número de apuntes asociados. Estos listados se obtienen de una consulta sql a nuestra base de datos de apuntes:

$sql = "select fecha from $tabla_apuntes where activo > 0 order by fecha desc";

Nótese que tan solo nos interesa la fecha de nuestros apuntes, que procesamos con el siguiente código:

$archivos = array();
while ($dato = mysql_fetch_array($respuesta))	{
	list($año, $mes) = explode("-", $dato["fecha"]);
	if (isset($archivos[$año]))	{
		$archivos[$año]["cuenta"]++;
		if (isset($archivos[$año]["meses"][$mes]))	{
			$archivos[$año]["meses"][$mes]["cuenta"]++;
		}
		else	{
			$archivos[$año]["meses"][$mes]["cuenta"] = 1;
		}
	}
	else	{
		$archivos[$año]["cuenta"] = 1;
		$archivos[$año]["meses"] = array();
		$archivos[$año]["meses"][$mes]["cuenta"] = 1;
	}
}

Con este código tenemos los años con sus contadores, y por cada año los correspondientes meses y sus contadores.

Compresión y accesibilidad

En los primeros párrafos hemos indicado que el listado estaba comprimido, pero de manera visual, ya que realmente lo que hemos hecho es expandir el mismo... ahora comentaremos el galimatías.

No solo tenemos los meses, sino hemos añadido los años, aunque estos elementos sirven para desplegar los meses correspondientes. Aún siendo más elementos vemos solo los años, y al pulsar sobre ellos es cuando se despliegan los meses.

La mencionada "accesibilidad" podemos distinguirla porque los elementos desplegables son a la vez enlaces que funcionan como tal en navegadores con javascript desactivado. Estos enlaces se dirigen a los anuarios que aparecen en otra sección de la página (Extras), pero se cancela para desplegar el listado de meses; y al mismo sistema de archivos que siempre ha existido agrupados por el mes y el año de su publicación, pero también se cancela y despliega mostrando los títulos correspondientes.



Zona de comentarios

Esto grupo aún no tiene comentarios.

Evaluación

Valoración de esta página: (grupo.diario) valor

Valoración evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar

Respuesta: Zona de mensajes (proceso de evaluación)

Copyright © 2002-2024 www.pepemolina.com
RSS rss | Ver Mapa del sitio