Múltiples fondos personalizados en WordPress, ¿es posible?

27 ago 2010, 20:39:09
Vistas: 1.07K
Votos: 3

¿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?

0
Todas las respuestas a la pregunta 2
14

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.

28 ago 2010 08:10:05
Comentarios

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

hakre hakre
28 ago 2010 09:18:20

Ese es un plugin que definitivamente envolvería en una clase.

hakre hakre
28 ago 2010 09:20:06

@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 .

hakre hakre
28 ago 2010 12:06:22

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

hakre hakre
28 ago 2010 16:11:34

@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).

MikeSchinkel MikeSchinkel
28 ago 2010 17:27:49

@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)

MikeSchinkel MikeSchinkel
28 ago 2010 17:58:57

@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.

MikeSchinkel MikeSchinkel
28 ago 2010 18:01:19

@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.

MikeSchinkel MikeSchinkel
28 ago 2010 18:25:26

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!

hakre hakre
28 ago 2010 19:01:20

@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.

hakre hakre
28 ago 2010 19:05:03

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

hakre hakre
28 ago 2010 19:25:49

@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.

MikeSchinkel MikeSchinkel
28 ago 2010 20:07:15

¡Guau! ¡Funciona increíble! Estoy sin palabras.

Amit Amit
29 ago 2010 23:18:34

@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... :)

MikeSchinkel MikeSchinkel
30 ago 2010 00:13:52
Mostrar los 9 comentarios restantes
5

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.

27 ago 2010 21:11:10
Comentarios

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.

Amit Amit
27 ago 2010 21:17:01

¿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).

hakre hakre
27 ago 2010 21:32:28

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

MikeSchinkel MikeSchinkel
28 ago 2010 08:10:49

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

hakre hakre
28 ago 2010 09:14:49

Cierto. ¡Pero no deberías desanimar a la gente; donde hay voluntad hay un camino!

MikeSchinkel MikeSchinkel
30 ago 2010 00:30:16