====== Embeber OpacMarc en DokuWiki ====== Es atractiva la posibilidad de "embeber" ("encajar", "incrustar") el OPAC como parte del sitio web de la biblioteca, en lugar de presentarlo como una página o sitio que debe ser visitado en forma separada. La idea puede encontrarse, por ejemplo, en [[http://www.slideshare.net/halwete/IGeLU2007opac|esta presentación de Daniel Forsman (2007)]], de la [[http://www.bibl.hj.se/eng/|Biblioteca de Jönköping University]] (Suecia). La manera de implementar esto dependerá de las características de la herramienta usada para administrar el sitio; en el caso particular del INMABB nos interesaba poder hacerlo con DokuWiki. Con ese fin, hubo que realizar varias modificaciones en OpacMarc, y crear un plugin para DokuWiki. A continuación se describen los pasos efectuados y los problemas encontrados. Es importante resaltar que los cambios hechos en OpacMarc posiblemente sean suficientes para permitir que también sea embebido en //otras// aplicaciones. ===== Cambios en OpacMarc ===== Para hacer el opac "embeddable", tuvimos que hacerle [[http://code.google.com/p/opacmarc/source/detail?r=67|algunas modificaciones]]. ==== Generación parcial de la página ==== Definimos un nuevo parámetro **output** en ''opac.xis''. Un cliente puede especificar --mediante **output=embed**-- que sólo desea recibir el contenido propiamente, es decir, que ''opac.xis'' debe omitir generar el comienzo (hasta el header inclusive) y el final de la página (posiblemente un footer, y el string "") ==== Generación de enlaces a scripts (''href'' en links, ''action'' en forms) ==== Definimos un parámetro **script_url** en ''opac.xis''. Mediante este parámetro, un cliente puede sobrescribir el valor del parámetro de configuración SCRIPT_URL. El valor es utilizado como "prefijo" en todas las URLs que apuntan al OPAC, tanto links como formularios. Por ejemplo, para DokuWiki tendríamos **script_url=/doku.php/catalogo** (si se configura DokuWiki con //userewrite=2//), o **script_url=/doku.php?id=catalogo** (con el default //userewrite=0//). Para poder hacer uso de este parámetro, tuvimos que efectuar este reemplazo en varios archivos: * ''getenv('SCRIPT_NAME')'' => ''v6001^u'' (o ''v6001^u[1]'' dentro de un grupo repetible) Para tener en cuenta el caso en que ''script_url'' ya incluye un //query string// (e.g. ''script_url=/doku.php?id=catalogo''), hicimos este otro reemplazo en múltiples archivos: * ''?IsisScript='' => ''&IsisScript='' Pero esto aún deja sin resolver el caso de los formularios. Para evitar el problema, podríamos limitarnos a admitir como ''script_url'' solamente valores //sin// query string, para evitar la complicación de los parámetros adicionales en los formularios; de ahí la conveniencia de utilizar en DokuWiki un valor de //userewrite// diferente de 0. FIXME Sería mejor si pudiéramos quitar estos dos parámetros de todas las URLs: &IsisScript=xis/opac.xis&db=demo pues pueden ser insertados por el plugin, como sucede con la portada del OPAC. Pero no es una necesidad. ==== Generación de enlaces a archivos estáticos (''src'' en , ''href'' en ) ==== Creamos un nuevo parámetro para OpacMarc, **path_htdocs**, con el que un cliente puede sobrescribir el parámetro de configuración PATH_HTDOCS. ==== Adecuación de CSS ==== El //primer problema// a resolver es: cómo hacer que las reglas de estilo del opac se mantengan acotadas y no "contaminen" el resto de la página que aloja al opac. La solución es simple: * a nivel de HTML, hacemos que un **
** envuelva el contenido propio del opac * a nivel de CSS, modificamos las hojas de estilo del opac, anteponiendo **div.opacmarc** a todos los selectores. Por ahora, sólo hice esas modificaciones en una copia de los archivos .css para ser usada por DokuWiki; creo que el cambio finalmente habría que hacerlo en las .css originales de OpacMarc. FIXME Ver qué partes del css del opac son para header/footer (i.e. fuera de ese div) y por lo tanto no deberían llevar ese prefijo en los selectores. El //segundo problema// es: cómo evitar que las reglas de estilo de la página //host// (DokuWiki) causen "interferencias" sobre la porción de la página correspondiente al opac. Aquí a su vez se presentan dos posibles situaciones: * Que una regla de estilo del //host// compita con una regla de estilo del opac y le gane. Para evitar esto, nos gustaría poder tener un **important!** para las reglas del opac. * Que una regla de estilo del //host// se aplique a un elemento del opac, sin que haya una regla de estilo del opac para competir. Para evitar esto, ¿podríamos "blindar" nuestro
para suprimir el efecto de reglas externas al opac? El //tercer problema//: cómo ajustar los paths de las imágenes usadas por las hojas de estilo, p.ej. background-image: url(../img/0180_bullet.gif); //Cuarto problema:// ¿cómo obtiene el cliente las hojas de estilo e imágenes asociadas? Hay hojas de estilo default, locales, por base, para IE, ... Las hojas de estilo de los templates son cargadas después de las de los plugins ([[doku>devel:css]]). ==== JavaScript ==== ==== Title de la página ==== Así como agregamos elementos //link// y //script// al de la página del catálogo, también nos gustaría poder alterar el , para que muestre un título generado por el OPAC. ¿Cómo hacemos? FIXME ==== HTML vs XHTML ==== DokuWiki usa XHTML 1.0 Transitional. Para que la inclusión de contenido del OPAC no altere la validez del código XHTML, vamos a tener que hacer algunos ajustes, de manera que OpacMarc produzca XHTML válido. * ''<br>'' => ''<br/>'' * ''<hr>'' => ''<hr/>'' * ''<img ...>'' => ''<img .../>'' * ''<input ...>'' => ''<input .../>'' * ''selected'' => ''selected="selected"'' * ''checked'' => ''checked="checked"'' * ''&'' => ''&'' Hice varios ajustes, pero habrá que revisar más exhaustivamente (sé que dejé algunas cosas colgadas). Arreglos pendientes, según validador de W3C: FIXME * thead, tfoot en Etiquetado ===== Plugin para DokuWiki ===== Implementamos la funcionalidad "encajar OpacMarc en una página del wiki" mediante un plugin llamado //opacmarc//. El plugin define esta sintaxis: {{OPAC>nombre_de_la_base}} (Para usar algo como ''%%{{OPAC>demo}}%%'' (análogo a la sintaxis de //blog// o //rss//), tenemos que elegir adecuadamente el valor retornado por la función getSort, para poder "ganarle" a la sintaxis usada para insertar media. Ver [[doku>devel:syntax_plugins#sort_number]] y [[doku>devel:parser:getsort_list]].) Los archivos creados son: * ''syntax.php'' * ''action.php'' * ''conf/metadata.php'' * ''conf/default.php'' * ''lang/en/settings.php'' * ''lang/es/settings.php'' El archivo ''action.php'' (action plugin) se ocupa de insertar elementos ''script'' y ''link'' en el head de la página, para solicitar CSS y JavaScript directamente al servidor del OPAC. Esto lo hace solamente para la página del catálogo. Así, el plugin no necesita mantener una copia del CSS ni del JS del OPAC. Un inconveniente a resolver: ¿cómo hacer que esta modificación sólo suceda en la página del catálogo? No queremos tener que reconocer la página mediante su //id//; se supone que es la presencia de la sintaxis ''%%{{OPAC...}}%%'' lo que caracteriza a la página como "catálogo". FIXME Ver si se puede registrar el event handler desde syntax.php ([[doku>devel:events#registering_to_receive_an_event]]). Probé y no dio resultado. Consultar en la lista. ===== Problemas ===== ==== Múltiples ejecuciones ==== El primer síntoma fue que por cada "búsqueda por autor", que normalmente genera un único archivo temporal, al usar DokuWiki se generaban **siete** archivos iguales. Usando estas líneas en ''opac.xis'': <code xml> <file action="append" type="output">/tmp/opacmarc-dokuwiki.log</file> <display><pft>'ejecutando opac.xis'/</pft></display> <file action="close" type="output">/tmp/opacmarc-dokuwiki.log</file> </code> quedó claro que el problema está en que ''opac.xis'' **se está ejecutando siete veces**, incluso al visitar la página de inicio del catálogo. Usando estas líneas en ''syntax.php'': <code php> $fp = fopen('/tmp/opacmarc-dokuwiki-syntax', 'a'); fwrite($fp, "syntax-render\n"); fclose($fp); </code> nos enteramos de que es la función **render** en ''syntax.php'' la que se está ejecutando siete veces. (El resto del código en ese archivo aparentemente sólo se ejecuta una vez.) Haciendo un test similar con el plugin **now**, encontramos que: * al hacer el preview, render se ejecuta una vez * al guardar la página, render se ejecuta tres veces En pruebas posteriores, el número siete baja a dos, pero en cualquier caso la pregunta es: ¿por qué render() se ejecuta más de una vez? Consulta enviada al foro. Instalé Xdebug para PHP (''sudo apt-get install php5-xdebug'') para tratar de ver mejor lo que está pasando. Ver [[http://www.splitbrain.org/blog/2008-02/21-understanding_php_code_better_with_xdebug|Understanding PHP code better with Xdebug]] Usando Xdebug veo que en ''renderer.php'', class ''Doku_Renderer'', la función ''plugin'' es llamada 7 veces; quien llama es ''call_user_func_array'' en ''parserutils.php''. Consulta enviada a la lista de desarrolladores. Probar con una instalación completamente limpia del wiki (template default, etc.). Para ver si influye la presencia de links hacia la misma página: Creé una página "instituto/test", con el contenido "[OPAC>demo]". Al ver la página no aparecen links a ella misma. La función render se sigue ejecutando 7 veces. FIXME ver efecto de los breadcrumbs. OJO! Ver la [[doku>config:useheading]]. También ver valor de $mode en cada ejecución de render. Al desactivar [[doku>config:useheading]] se producen **tres** llamadas a render: una con $mode=xhtml y dos con $mode=metadata. Antes eran una con $mode=xhtml y seis con $mode=metadata. Si bien la función render se sigue ejecutando muchas veces (lo que parecería ser un comportamiento normal del wiki), resolví lo de las múltiples llamadas al OPAC mediante un sencillo cache: almaceno la respuesta del OPAC en una variable la primera vez que se ejecuta render, y en las siguientes veces no vuelve a ejecutar ese bloque de código. Mejor solución: moví el bloque de código al interior del if: <code php> if($mode == 'xhtml') { ... } </code> ya que es allí donde lo necesitamos; las llamadas extra a render tienen $mode='metadata'. Explicar por qué no podemos realizar la llamada al OPAC dentro de la función handle (cuyo resultado sí es guardado en cache), y en cambio debemos hacerla desde render (que no se cachea). Ver discusión en la lista: **plugin render() called multiple times for metadata** (mayo 2009). ==== PHP Warning ==== Warning: preg_replace_callback() [function.preg-replace-callback]: Compilation failed: invalid UTF-8 string at offset 20 in /home/fernando/www/html/dokuwiki/inc/html.php on line 271 Cómo se produce: entrar por índice de autores a Raúl Alfonsín, ver el registro, clic en el punto de acceso para Raúl Alfonsín. Se repite si desde ahí hago clic en "Catálogo", y desaparece cuando insisto. Esto está relacionado con el **resaltado de términos**, al hacer una búsqueda con términos acentuados. Ver abajo. ==== Resaltado de términos ==== El wiki aplica un resaltado en algunas páginas, mediante un **<span class="search_hit">**. Esto se debe a una interferencia del parámetro **query** usado para el OPAC. Detalles: En doku.php se define $HIGH: <code php> $HIGH = $_REQUEST['s']; if(empty($HIGH)) $HIGH = getGoogleQuery(); </code> que a su vez puede depender de getGoogleQuery, definida en inc/common.php: <code php> /** * extracts the query from a search engine referrer * * @author Andreas Gohr <andi@splitbrain.org> * @author Todd Augsburger <todd@rollerorgans.com> */ function getGoogleQuery(){ $url = parse_url($_SERVER['HTTP_REFERER']); if(!$url) return ''; $query = array(); parse_str($url['query'],$query); if(isset($query['q'])) $q = $query['q']; // google, live/msn, aol, ask, altavista, alltheweb, gigablast elseif(isset($query['p'])) $q = $query['p']; // yahoo elseif(isset($query['query'])) $q = $query['query']; // lycos, netscape, clusty, hotbot elseif(preg_match("#a9\.com#i",$url['host'])) // a9 $q = urldecode(ltrim($url['path'],'/')); if(!$q) return ''; $q = preg_split('/[\s\'"\\\\`()\]\[?:!\.{};,#+*<>\\/]+/',$q,-1,PREG_SPLIT_NO_EMPTY); return $q; } </code> En inc/html.php se utiliza $HIGH para aplicar el resaltado: <code php> /** * show a wiki page * * @author Andreas Gohr <andi@splitbrain.org> */ function html_show($txt=''){ global $ID; global $REV; global $HIGH; global $INFO; ... ... if ($REV) print p_locale_xhtml('showrev'); $html = p_wiki_xhtml($ID,$REV,true); $html = html_secedit($html,$secedit); if($INFO['prependTOC']) $html = tpl_toc(true).$html; $html = html_hilight($html,$HIGH); echo $html; ... } </code> <code php> /** * Highlights searchqueries in HTML code * * @author Andreas Gohr <andi@splitbrain.org> * @author Harry Fuecks <hfuecks@gmail.com> */ function html_hilight($html,$phrases){ $regex = join('|',array_map('preg_quote_cb',array_filter((array) $phrases))); if ($regex ==== '') return $html; $html = preg_replace_callback("/((<[^>]*)|$regex)/ui",'html_hilight_callback',$html); return $html; } /** * Callback used by html_hilight() * * @author Harry Fuecks <hfuecks@gmail.com> */ function html_hilight_callback($m) { $hlight = unslash($m[0]); if ( !isset($m[2])) { $hlight = '<span class="search_hit">'.$hlight.'</span>'; } return $hlight; } </code> El resaltado está **atrasado**; es decir, se resaltan términos correspondientes a la búsqueda previa. Cuestiones a resolver: * ¿Queremos que DokuWiki aplique el resaltado en páginas del OPAC? Posiblemente no lo aplique de manera satisfactoria (desfasaje, problemas con acentos), así que en una primera etapa será mejor prescindir de esa funcion. * ¿Cómo la desactivamos? Una posibilidad (no muy limpia) es mediante CSS (''.search_hit {background-color: inherit; color: inherit;}''), pero esto no resuelve el problema de las expresiones con acentos, donde se produce un error de PHP. Entonces, como solución de emergencia, comenté en inc/common.php las dos líneas de getGoogleQuery donde se hace referencia a un parámetro "query". Claro que esto no es bueno, porque estamos alterando código core de DokuWiki. FIXME ==== Charset/encoding de términos de búsqueda ==== No funcionan las búsquedas cuando se ingresan términos con acentos. Resuelto aplicando utf8_decode a ciertos parámetros, en base a la presencia de $_REQUEST['form']. Es importante tener en cuenta que el decode es necesario para términos procedentes de un form (i.e. ingresados por un usuario), pero no para aquellos procedentes de un link (i.e. generados por el OPAC). Esto llevó a crear un parámetro oculto ''form'' en los formularios del OPAC. FIXME Queda algún problema pendiente. Buscar registros de "Unión Matemática Argentina", y desde uno de ellos clic en "Listado", da error. ==== Hojas de estilo para IE ==== ¿Cómo podemos usar comentarios condicionales para cargar las hojas de estilo que sólo debe ver IE? Mediante action.php: no parece que se puedan añadir comentarios. Mediante el template (archivo ''meta.html''): no parece buena idea introducir elementos propios del plugin dentro de un template, pero podría ser aceptable para nuestro caso. FIXME ==== Display de ficha AACR2 ==== Si entramos a un registro directamente desde el índice de autores y pasamos a la ficha, no la muestra; si en cambio pasamos antes por otro estilo y luego intentamos otra vez la ficha, sí se ve. La diferencia que pude detectar en las URLs: &curr=1&total=1&cn=&style=Ficha versus &curr=1&total=&cn=&style=Ficha Ahora aparece **RESUELTO** (no sé por qué). ==== Logs ==== Los logs que almacene OpacMarc carecerán de datos sobre el cliente (número de IP, browser), a menos que el plugin se ocupe de incluirlos en la petición. FIXME ==== Conflictos ==== * La presencia de otro contenido en la página del OPAC impide el uso del catálogo, cuando no está presente ''%%~~NOCACHE~~%%'' {{tag>opacmarc desarrollo dokuwiki}}