Lo hice y lo entendí

El blog de Vicente Navarro
11 mar

Guardar las imágenes subidas al servidor fuera del árbol de directorios de WordPress

Desde que uso el excelente WordPress, hay algo que nunca me ha gustado: El no poder guardar las imágenes subidas al servidor desde el editor de entradas fuera del árbol de directorios de WordPress cuando la Dirección de WordPress es distinta de la Dirección del blog. Por ejemplo, tenemos el blog en http://www.ejemplo.com, el WordPress en http://www.ejemplo.com/wp y queremos tener las imágenes subidas en http://www.ejemplo.com/img.

Es en Opciones → Miscelánea donde podemos elegir en qué directorio debajo de la estructura de WordPress queremos tener las imágenes subidas, pero si tenemos el WordPress en, por ejemplo, <DocumentRoot>/wordpress, nunca podríamos tener las imágenes en <DocumentRoot>/img.

Buscando si había alguna forma estándar de cambiar esto, encontré a mucha gente que preguntaba lo mismo, pero pocas respuestas. Finalmente llegé a una entrada en el foro de soporte de WordPress que me daba pistas, pero para mi versión actual, la 2.1.2, la solución propuesta no se podía aplicar directamente.

WP Upload Options

Dándole algunas vueltas he encontrado la solución final editando el <WordPressRoot>/wp-include/functions.php y sustituyendo en la función wp_upload_dir() las líneas:

$path = str_replace(ABSPATH, '', trim(get_option('upload_path')));
$dir = ABSPATH . $path;
$url = trailingslashit($siteurl) . $path;

por

$abspath_vic = $_SERVER['DOCUMENT_ROOT'];
$path = str_replace($abspath_vic, '', trim(get_option('upload_path')));
$dir = $abspath_vic . $path;
$url = trailingslashit(get_option('home')) . $path;

Como no es infrecuente tener que actualizar el WordPress, he preparado un parche (con “diff -Naur original new“)para poder aplicar este cambio a versiones futuras siempre que este trozo del fichero functions.php no cambie. Por si a alguien más le resulta útil, lo he subido a la página. Para aplicarlo, sólo tienes que ir a <WordPressRoot>/wp-include/ y ejecutar:

patch -p0 < /path_al_parche/wp_212_uploads_outside.patch

Una vez aplicado el parche, la carpeta elegida en Opciones → Miscelánea será relativa a <DocumentRoot>, no a <WordPressRoot>.

Bueno, y una vez llegados a este punto, ya podremos guardar todas las nuevas imágenes que subamos desde ese momento en el nuevo directorio fuera de la jerarquía de WordPress. Pero, ¿qué pasa con las que ya teníamos?

En mi caso, unos cuantos sed sobre el fichero de salida del mysqldump me ha arreglado definitivamente el problema:

mysqldump -p --extended-insert --no-create-db --add-drop-table --databases wordpress > wp.bak
sed 's_valencia.homelinux.org/wp/wp-content/uploads_valencia.homelinux.org/img_g' < wp.bak > wp.bak2
sed 's_/var/htdocs/wp/wp-content/uploads/_/var/htdocs/img/_g' < wp.bak2 > wp.bak3
mysql -p < wp.bak3

Actualización 31/3/07 14:15: Lo anterior funcionaba perfectamente cuando el hostname del servidor era exactamente igual que la URL del blog, por ejemplo cuando antes la dirección de este blog era http://valencia.homelinux.org. Ahora que ha pasado a ser http://www.vicente-navarro.com/blog/ me he dado cuenta de que hay problemas por el /blog/, ya que el path donde se han de guardar las imágenes se forma del DOCUMENT_ROOT y del upload_path, ninguno de los cuales incluiría ese /blog/.

He cambiado las líneas que generan los paths así:

$docroot = $_SERVER['DOCUMENT_ROOT'];
$serverurl = trailingslashit("http://" . $_SERVER['SERVER_NAME']);
$abspath_vic = $docroot . str_replace($serverurl,'',trailingslashit(get_option('home')));
$path = trim(get_option('upload_path'));
$dir = $abspath_vic . $path;
$url = trailingslashit(get_option('home')) . $path;

y ahora, en una configuración como la de este blog, en el que he puesto img en el cuadro de configuración de WordPress donde especificamos el directorio donde guardar las imágenes, las variables tomarían estos valores:

$docroot /var/htdocs/
$serverurl http://www.vicente-navarro.com/
$abspath_vic /var/htdocs/blog/
$path img
$dir /var/htdocs/blog/img
$url http://www.vicente-navarro.com/blog/img

Con este cambio, la carpeta elegida en Opciones → Miscelánea será relativa al path donde está el blog.

Creo que puede haber muchas casuísticas que ocasionen que estos cambios no funcionen, por ejemplo si configuráramos el Apache para que /blog fuera un Alias de un directorio que estuviera en otro sitio. Supongo que es por todas estas casuísticas que los programadores de WordPress decidirían que las imágenes tuvieran que estar siempre bajo la jerarquía de su árbol de directorios, pero bueno, en configuraciones sencillas como esta, funciona.

He creado un nuevo parche wp_212_uploads_outside_v2.patch con estos cambios.

Actualización 5/4/07: Parece que el parche funciona perfectamente para WordPress 2.1.3

Actualización 25/5/07: Parece que el parche funciona perfectamente para WordPress 2.2

Actualización 24/7/07: Parece que el parche funciona perfectamente para WordPress 2.2.1

Actualización 5/9/07: Parece que el parche funciona perfectamente para WordPress 2.2.2

Actualización 10/9/07: Parece que el parche funciona perfectamente para WordPress 2.2.3

Actualización 29/10/07: Parece que el parche funciona perfectamente para WordPress 2.3.1

Actualización 30/12/07: Parece que el parche funciona perfectamente para WordPress 2.3.2

Actualización 4/2/08: Parece que el parche funciona perfectamente para WordPress 2.3.3

Entradas relacionadas

Tema LHYLE09, creado por Vicente Navarro