Múltiples fondos personalizados en WordPress, ¿es posible?
¿Es posible crear múltiples páginas de administración de "fondo personalizado"? Un sitio en el que estoy trabajando ahora necesita 2 fondos diferentes en 2 áreas distintas, me encantaría darle a mi cliente la misma experiencia para ambos fondos en términos de color/imagen/selección-repetición, etc. ¿Alguna idea?

Hola @Amit:
La respuesta es "Sí, es posible." La pregunta de seguimiento es "¿Realmente lo quieres?"
Pensé que sería divertido ver si podía construir un plugin para hacer lo que estás pidiendo, así que decidí ver si era posible. Por supuesto, pude hacer que funcionara, pero me temo que el código del plugin que escribí necesita estar tan estrechamente acoplado con el código existente en WordPress que podría romperse fácilmente con una actualización del núcleo.
Este código maneja todo el lado de la consola de administración creando un nuevo elemento de menú en la sección Apariencia llamado "Fondo Especial". Lo que no hace es proporcionar ninguna forma de usar realmente el fondo; esa es la fase dos del plugin y requerirá enganchar muchas de las funciones en /wp-includes/themes.php
y, sinceramente, no sé si tendré la oportunidad de escribir ese código.
La razón por la que me detuve sin hacerlo es que no conocía los requisitos de dónde debería aparecer el fondo especial y dónde aparecería el regular. ¿Supongo que tal vez para páginas seleccionadas y/o rutas de URL?
Sin embargo, aquí está el código para el plugin (que también puedes descargar desde gist):
<?php
/*
Plugin Name: Fondo Especial
Plugin URI: http://wordpress.stackexchange.com/questions/972/
Description: Ejemplo para mostrar cómo agregar un fondo especial utilizando la página de administración de fondos existente en el núcleo.
Version: 0.1
Author: Mike Schinkel
Author URI: http://mikeschinkel.com/custom-wordpress-plugins/
*/
add_filter('admin_menu','add_special_background_menu_item');
function add_special_background_menu_item() {
add_theme_page(__('Fondo Especial'), __('Fondo Especial'),'edit_theme_options','special-background','special_background_admin_page');
}
add_filter('admin_init','add_js_for_special_background');
function add_js_for_special_background() {
global $custom_background;
if (is_special_background_page()) {
wp_enqueue_script('custom-background');
wp_enqueue_style('farbtastic');
}
$hook = 'load-appearance_page_special-background';
add_action($hook, array(&$custom_background, 'admin_load'));
add_action($hook, array(&$custom_background, 'take_action'), 49);
add_action($hook, array(&$custom_background, 'handle_upload'), 49);
}
add_filter('theme_mod_background_image', 'theme_mod_special_background_image');
add_filter('theme_mod_background_image_thumb','theme_mod_special_background_image_thumb');
add_filter('theme_mod_background_repeat', 'theme_mod_special_background_repeat');
add_filter('theme_mod_background_position_x', 'theme_mod_special_background_position_x');
add_filter('theme_mod_background_attachment', 'theme_mod_special_background_attachment');
add_filter('theme_mod_background_color', 'theme_mod_special_background_color');
function theme_mod_special_background_image($defaults) {
return theme_mod_special_background_image_attrs('image',$defaults);
}
function theme_mod_special_background_image_thumb($defaults) {
return theme_mod_special_background_image_attrs('image_thumb',$defaults);
}
function theme_mod_special_background_repeat($defaults) {
return theme_mod_special_background_image_attrs('repeat',$defaults);
}
function theme_mod_special_background_position_x($defaults) {
return theme_mod_special_background_image_attrs('position_x',$defaults);
}
function theme_mod_special_background_attachment($defaults) {
return theme_mod_special_background_image_attrs('attachment',$defaults);
}
function theme_mod_special_background_color($defaults) {
return theme_mod_special_background_image_attrs('color',$defaults);
}
function theme_mod_special_background_image_attrs($attr,$defaults) {
if (is_special_background_page()) {
$mods = get_option( 'mods_' . get_current_theme() );
$defaults = (!empty($mods["special_background_{$attr}"]) ? $mods["special_background_{$attr}"] : '');
}
return $defaults;
}
add_filter('pre_update_option_mods_' . get_current_theme(),'pre_update_option_special_background_image',10,2);
function pre_update_option_special_background_image($newvalue, $oldvalue) {
static $times_called = 0;
if (!empty($_POST) && is_special_background_page()) {
if ((isset($_POST['action']) && $_POST['action']=='save') || isset($_POST['reset-background']) || isset($_POST['remove-background'])) {
switch ($times_called) {
case 0:
$newvalue = special_background_image_value_swap('image',$newvalue,$oldvalue);
break;
case 1:
$newvalue = special_background_image_value_swap('image_thumb',$newvalue,$oldvalue);
break;
}
} else {
if ($times_called==0 && isset($_POST['background-repeat'])) {
$newvalue = special_background_image_value_swap('repeat',$newvalue,$oldvalue);
}
if ($times_called==1 && isset($_POST['background-position-x'])) {
$newvalue = special_background_image_value_swap('position_x',$newvalue,$oldvalue);
}
if ($times_called==2 && isset($_POST['background-attachment'])) {
$newvalue = special_background_image_value_swap('attachment',$newvalue,$oldvalue);
}
if ($times_called==3 && isset($_POST['background-color'])) {
$newvalue = special_background_image_value_swap('color',$newvalue,$oldvalue);
}
}
$times_called++;
}
return $newvalue;
}
function special_background_image_value_swap($swap_what,$newvalue,$oldvalue) {
$newvalue["special_background_{$swap_what}"] = $newvalue["background_{$swap_what}"];
$newvalue["background_{$swap_what}"] = $oldvalue["background_{$swap_what}"];
return $newvalue;
}
function special_background_admin_page() {
global $custom_background;
if (is_special_background_page()) {
global $parent_file,$submenu_file,$title;
$parent_file = 'themes.php';
$submenu_file = 'themes.php?page=special-background';
$title = 'Fondo Especial';
require_once(ABSPATH . 'wp-admin/admin-header.php');
ob_start();
$custom_background->admin_page();
$html = ob_get_clean();
$html = preg_replace('#<h2>([^<]+)</h2>#','<h2>Fondo Especial</h2>',$html);
echo $html;
include(ABSPATH . 'wp-admin/admin-footer.php');
exit;
}
}
function is_special_background_page() {
global $pagenow;
return ($pagenow=='themes.php' &&
isset($_GET['page']) && $_GET['page']== 'special-background');
}
Sinceramente, es demasiado código para explicar de manera proactiva, pero estaré encantado de responder preguntas específicas.

Consejo: list($var1, $var2) = array($var2, $var1); // intercambia los valores de $var1 y $var2

@MikeSchinkel: ¿Podrías añadir una pequeña descripción sobre tu concepto de intercambio/guardado? ¿Normalmente esos valores de modificación theme_mod_background_image son utilizados por el núcleo de WP para ofrecer el encabezado estándar? ¿Qué haces si no hay encabezado en el tema? Estoy pensando en crear algún objeto facade de opción/hook en mi fork... actualizado: http://codex.wordpress.org/Theme_Modification_API .

Hice un fork de ti. http://gist.github.com/554944

@hakre; gracias por el consejo sobre el swap. Aunque ya estoy familiarizado con ello. Debes entender que cuando escribí la función por primera vez era mucho más complicada y la refactoricé hasta lo que es ahora, así que originalmente no pensé que sería tan simple. Tampoco suelo envolver las cosas en una clase aquí en StackExchange porque hace que sea más difícil de entender para la gente cuando toda la infraestructura de la clase está en su lugar (sin embargo, no es óptimo; si uso una clase más gente se asustará; si no uso una clase les estoy enseñando una práctica menos buena).

@hakre - WordPress almacena el encabezado en una opción llamada mods_{$theme}
; mi tema se llamaba wp30 así que es mods_wp30
. Tiene una imagen de fondo, una miniatura y un color. Simplemente intercepto la actualización y añado mis elementos con nombres diferentes para el fondo especial, de ahí el swap, y luego hago lo contrario al obtener la opción. WordPress no da contexto en set_theme_mod()
lo que hizo esto mucho más difícil de lo que debería haber sido (solicité un filtro, ¿quizás podrías apoyarlo? http://core.trac.wordpress.org/ticket/14721)

@hakre - Tuve que usar el orden de guardado para averiguar qué se estaba guardando, lo cual es muy alarmante por lo frágil que es; ¡agregan una cosa a /wp-includes/custom-background.php
y todo se rompe! En cuanto a git, no lo conozco y no estoy listo para aprenderlo. Entiendo que bifurcar (forking) es algo bueno en git, pero yo siempre lo veo como algo negativo. ¿Quieres colaborar en esto para el repositorio en WordPress.org? Si es así, necesita manejar múltiples fondos, no solo uno.

@hakre - Acabo de mirar tu bifurcación. Es código "limpio" pero está tan abstracto que es difícil de seguir. Solía codificar de esa manera y solía (literalmente) predicar ese estilo de codificación en mis cursos de formación para programadores corporativos, gubernamentales y militares. Pero desde que trabajo con WordPress, he llegado a apreciar que el código menos abstracto puede ser en realidad un beneficio a veces porque es mucho más fácil de entender. Por lo que vale.

Oh, no tan abstracto. Solo me gusta que los hooks se enganchen en los mismos nombres. Y configurar las variantes al principio de la clase. Me encontré con un lío mientras refactorizaba tu base, así que aparecieron estas tres clases que pueden parecer un poco exageradas. La última está acoplada a la primera, la rutina se puede fusionar en la clase del plugin pero no lo he hecho todavía. La otra clase era algo con lo que me gustaba jugar para superar tu add_filter / montón de funciones globales -> una función global. Así que eso fue abstracto :D. :P ¡Gracias por el feedback!

@MikeSchinkel: También estoy empezando con git. No tengo problemas con hacer fork, creo que es como tener un nuevo repositorio. Por lo que he escuchado, eso funciona bien con git, así que hagamos algunos forks. Este gist es un pasteboard muy bueno. Puedes ver de dónde obtuviste las cosas, etc. Eso es genial. --- No sé si tiene sentido agregar más de una imagen de fondo en WP. ¿Tal vez? Pero creo que el problema es que no está diseñado de esa manera en el núcleo, debe haberse agregado algún número o clave para diferenciar entre cada uno de los fondos. Probablemente sea más simple volver a codificar ese formulario y ofrecer páginas de administración.

@MikeSchinkel: Prueba antes de comprar :D : http://progit.org/book/

@hakre: Lo abstracto es relativo. ¿Quieres ver algo abstracto? ¡Lee mi libro sobre programación! http://mikeschinkel.com/books/ Me gusta Gist, pero no planeo trabajar con Git, al menos no hasta que WordPress lo adopte (lo cual creo que es poco probable). Sí, tendría mucho sentido tener múltiples fondos; imagina una revista en línea con 5 secciones; un fondo para cada una más la página de inicio. Y siempre que sea posible, trato de trabajar con lo que WordPress tiene, pidiendo hooks donde los necesito, en lugar de desechar y comenzar de nuevo. Esa es simplemente mi filosofía para extender WordPress.

@Amit: Sin palabras, pero aún puedes escribir, ¿eh? :-) Me alegra haber podido ayudar. Estoy agotado con este, pasé mucho más tiempo del que esperaba cuando comencé a responder, pero si tu cliente necesita que esos fondos se muestren creados, ofrezco consultoría por horas... :)

Técnicamente es posible (extender el código fuente de WordPress), pero no por defecto. Así que mi respuesta sería no. La función de fondo de tema incorporada está diseñada para un solo gráfico por defecto.
Pero si describes un poco más sobre las "2 áreas diferentes" de las que hablas, podría haber algo interesante que sugerir además de esto.
Edición: Destacado para MikeSchinkel. Los plugins extienden el código fuente de WordPress.

Bueno... Está el sitio principal (unas 20 secciones más o menos) y luego hay como un sub-sitio bajo una de esas secciones que cambia para este evento especial y necesita sus propios colores de estilo e imagen de fondo.
En teoría podría decirle al cliente que suba una imagen a la "página maestra" de cada sección y llamarla "de alguna manera" pero me gusta la funcionalidad de fondo personalizado y la posición semántica en el CMS.

¿estás usando una plantilla por sección? eso podría ser algo en lo que enganchar. O para sobrescribir con un subtema para un área determinada (eso escalaría a dos imágenes de fondo en total porque tendrías dos temas, tema padre y tema hijo).

¡Oh tú de poca fe! ¡Deberías saber que no hay que decir que algo no es posible con WordPress! ;-)

No lo hice. Quiero decir que es un montón de PHP que solo necesitas reorganizar un poco para hacer las cosas :)
