¿Cómo pasar variable a la devolución de llamada add_settings_section ()?

16

Estoy intentando automatizar, en la medida de lo posible, la función API de configuración requiere cada configuración en un complemento. Bucle a través de la matriz de opciones, y la salida add_settings_section()y add_settings_field()es bastante simple:

add_settings_section():

$oenology_hooks_tabs = oenology_hooks_get_settings_page_tabs();
foreach ( $oenology_hooks_tabs as $tab ) {
    $tabname = $tab['name'];
    $tabtitle = $tab['title'];
    $tabsections = $tab['sections'];
    foreach ( $tabsections as $section ) {
        $sectionname = $section['name'];
        $sectiontitle = $section['title'];
        $sectiondescription = $section['description'];
        // Add settings section
        add_settings_section(
            'oenology_hooks_' . $sectionname . '_section',
            $sectiontitle,
            'oenology_hooks_' . $sectionname . '_text',
            'oenology_hooks_' . $tabname . '_tab'
        );
    }
}

Y `add_settings_field ():

global $oenology_hooks;
$oenology_hooks = oenology_hooks_get_hooks();

foreach ( $oenology_hooks as $hook ) {
    $hookname = $hook['name'];
    $hooktitle = $hook['title'];
    $hooktab = $hook['tab'];
    $hooksection = $hook['section'];
    add_settings_field(
        'oenology_hooks_' . $hookname,
        $hooktitle,
        'oenology_hooks_setting_callback',
        'oenology_hooks_' . $hooktab . '_tab',
        'oenology_hooks_' . $hooksection . '_section',
        $hook
    );
}

Con add_settings_field(), puedo escribir fácilmente una devolución de llamada genérica, pasando la $hookvariable a la devolución de llamada, como el quinto parámetro en la llamada a la función:

function oenology_hooks_setting_callback( $hook ) {
    $oenology_hooks_options = get_option( 'plugin_oenology_hooks_settings' ); 
    $hookname = $hook['name'];
    $hooktitle = $hook['title'];
    $hookdescription = $hook['description'];
    $hooktype = $hook['type'];
    $hooktab = $hook['tab'];
    $hooksection = $hook['section'];
    $inputvalue = $hookname . '_hide';
    $inputname = 'plugin_oenology_hooks_settings[' . $inputvalue . ']';
    $textareaname = 'plugin_oenology_hooks_settings[' . $hookname . ']';
    $textareavalue = $oenology_hooks_options[$hookname];
    if ( 'Filter' == $hooktype ) {
        ?>
        <input type="checkbox" name="<?php echo $inputname; ?>" value="<?php echo $inputvalue;?>" <?php checked( true == $oenology_hooks_options[$inputvalue]  ); ?> />
        <span>Hide <?php echo $hooktitle; ?> content?</span><br />
        <?php
    }
    ?>
    <span class="description"><?php echo $hooktype; ?> Hook: <?php echo $hookdescription; ?></span><br />
    <textarea name="<?php echo $textareaname; ?>" cols="80" rows="3" ><?php 
        echo esc_textarea( $textareavalue ); 
    ?></textarea>
    <?php 
}

Sin embargo, parece que add_settings_section()no tiene un $argsparámetro análogo ; por lo tanto, no puedo usar el mismo método para pasar la $sectionvariable a la devolución de llamada.

Por lo tanto, mi pregunta: ¿hay alguna forma de pasar una variable a la add_settings_section()devolución de llamada, o alguna otra forma de crear una devolución de llamada análoga a lo que estoy haciendo add_settings_field()?

EDITAR:

@Bainternet lo clavó! Aquí está mi código de trabajo:

/**
 * Callback for add_settings_section()
 * 
 * Generic callback to output the section text
 * for each Plugin settings section. 
 * 
 * @param   array   $section_passed Array passed from add_settings_section()
 */
function oenology_hooks_sections_callback( $section_passed ) {
    global $oenology_hooks_tabs;
    $oenology_hooks_tabs = oenology_hooks_get_settings_page_tabs();
    foreach ( $oenology_hooks_tabs as $tab ) {
        $tabname = $tab['name'];
        $tabsections = $tab['sections'];
        foreach ( $tabsections as $section ) {
            $sectionname = $section['name'];
            $sectiondescription = $section['description'];
            $section_callback_id = 'oenology_hooks_' . $sectionname . '_section';
            if ( $section_callback_id == $section_passed['id'] ) {
                ?>
                <p><?php echo $sectiondescription; ?></p>
                <?php
            }
        }
    }
}
Chip Bennett
fuente
1
Solo una nota al margen: ¿Por qué no extract( $args, EXTR_SKIP );al principio oenology_hooks_setting_callback(), para que no tenga que guardar cada parte de la matriz en una nueva $var? Estos estarán disponibles con $'name_inside_the_array, por ej. '$ title , $ tab`, etc.
kaiser
... porque en realidad no soy tan inteligente con PHP? :) Lo intentaré; ¡Gracias!
Chip Bennett
Tal vez desee echar un vistazo a este Gist , que muestra algunos ejemplos de "tal vez la mejor práctica" sobre cómo agregar filtros y ganchos, analizar argumentos y tratar con la entrada de cadena de consulta. Es un poco viejo y probablemente lo reelaboraré cuando tenga tiempo, pero vale la pena echarle un vistazo. :)
kaiser
En realidad, esto es solo un complemento que agrega la interfaz de usuario para los ganchos que he agregado a Oenology. Me siento bastante cómodo con la forma en que he agregado los ganchos al tema. Ahora, solo estoy tratando de proporcionar una forma conveniente de exponerlos a los usuarios finales.
Chip Bennett
No te he entendido mal. Solo quería mostrarte esto en caso de que pueda ayudarte (cuando sea). Veo este código como algo irónico - sólo echar un vistazo la cantidad de esfuerzo que es conseguir que cada uno y todo para todo el mundo en el wordpress manera ...
Kaiser

Respuestas:

18

si observa la función do_settings_sections más específicamente la línea 1164 donde se ejecuta la función de devolución de llamada:

call_user_func($section['callback'], $section);

puede ver que la matriz $ section se pasa a la función de devolución de llamada, por lo que puede identificar la devolución de llamada mediante $section['id']

Espero que esto haga desde entonces.

Actualizar

Aquí hay un ejemplo, si su devolución de llamada add_settings_section para todas las secciones fue nombrada oenology_hooks_section_callback, puede identificarla así:

function oenology_hooks_section_callback($section_passed){
    if ($section_passed['id'] == 'whatever_section_id'){
        //do stuff
    }
    if ($section_passed['id'] == 'whatever_section_id_number2'){
        //do other stuff
    }
 }

y por hacer cosas quiero decir hacer lo que quieras hacer con esa devolución de llamada de la sección.

Bainternet
fuente
Hmm ... eso parece prometedor. ¿Cómo lo determino $section['id']?
Chip Bennett
@Chip Bennett idserá el primer argumento al que pasesadd_settings_section()
Rarst
@Chip Bennett Agregué un ejemplo para tratar de explicar mejor.
Bainternet
@Bainternet: ¡Impresionante! Tengo un script de opción y encontré el mismo problema que Chip Bennett. Ahora funciona como un encanto! Gracias.
Anh Tran
Bien, entonces finalmente hizo clic durante el fin de semana; déjame probar el código que tengo en mente y te informaré.
Chip Bennett
4

Sé que esta es una vieja pregunta, pero arrojaré mis dos centavos, en caso de que alguien más venga; una manera más simple de hacerlo sería escribir su propia modificación de la add_settings_section()función, que solo agregaría un parámetro de devolución de llamada al final de la misma.

Esto se vería así (o algo así)

function my_add_settings_section($id, $title, $callback, $page, $callbackargs) {

global $wp_settings_sections;

if ( !isset($wp_settings_sections) ) 
{
    $wp_settings_sections = array();
}

if ( !isset($wp_settings_sections[$page]) )
{
    $wp_settings_sections[$page] = array();
}

if ( !isset($wp_settings_sections[$page][$id]) )
{
    $wp_settings_sections[$page][$id] = array();
}

$wp_settings_sections[$page][$id] = array( 'id' => $id, 'title' => $title, 'callback' => $callback, 'callbackargs' => $callbackargs, 'page' => 'page' );
}

Ahora simplemente usaría esto en lugar de la función nativa de wordpress y accedería a sus argumentos de devolución de llamada a través de la 'callbackargs'clave de matriz de la manera habitual, como esta

function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   $section_passed['callbackargs']
}

Que podríamos usar para pasar a alguna otra función:

 function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   $args = $section_passed['callbackargs'];
   some_other_function( $args );
}

O los argumentos de devolución de llamada podrían ser una matriz que usamos:

function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   if ( $section_passed['callbackargs']['stuff'] !== 'things' ) 
   {
       echo 'stuff is not things!";
   }
}

Todo esto es posible porque todo lo que add_settings_section()hace es agregar un nuevo miembro de la matriz a la $wp_settings_sectionsvariable global, ese nuevo miembro de la matriz podría ser una matriz que contenga cualquier número de teclas con diferentes nombres, que podrían ser utilizados por cualquier función que supiera que estaban allí. Cuando do_settings_sectionsllama a la call_user_func_arrayque pasa un $sectionsparámetro de como se ha señalado Bainternet, esto significa que toda la matriz añadimos a $wp_settings_sectionsen my_add_settings_section()traspasó nuestra devolución de llamada, lo que significa que tenemos acceso a cada nuevo miembro de la matriz se añade al mismo, como el callbackargspermitir que nuestra función para tener una plena devolución de llamada de hecho.

Aunque estoy seguro de que esto podría ser obvio, pensé que solo lo explicaría en caso de que alguien que se confunde mire.

Cikica
fuente
0

También puede usar siempre un enfoque más general, sin buscar la implementación de la función en particular (es decir, sin verificar si add_settings_section pasa algo implícitamente). Este enfoque general utiliza el cierre de PHP.

Cómo usarlo: en cada lugar, donde pasa un nombre de función, en lugar de pasar una función anónima, con uso en él.

Ejemplo:

en lugar de

foreach ( $ar as $name => value ) {
    add_settings_section(
        $section,
        'something',
        'something-else',
        'callback_name'
    );
}

function callback_name() {
    do_something();
}

puedes usar:

foreach ( $ar as $name => value ) {
    add_settings_section(
        $section,
        'something',
        'something-else',
        function () use ( $name, $value ) {
            callback_name( $name, $value )
        }
    );
}

function callback_name( $name, $value ) {
    do_something( $name, $value );
}
Olga Farber
fuente