Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am attempting to automate, as much as possible, the Settings API function calls for each setting in a Plugin. Looping through the options array, and outputting add_settings_section() and add_settings_field() is simple enough:

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'
        );
    }
}

And `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
    );
}

With add_settings_field(), I can easily write a generic callback, by passing the $hook variable to the callback, as the fifth parameter in the function call:

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 
}

However, it appears that add_settings_section() does not have an analogous $args parameter; thus, I cannot use the same method to pass the $section variable to the callback.

Thus, my question: is there any way to pass a variable to the add_settings_section() callback, or some other way to create a callback analogous to what I'm doing for add_settings_field()?

EDIT:

@Bainternet nailed it! Here's my working code:

/**
 * 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
            }
        }
    }
}
share|improve this question
1  
Just a sidenote: Why don't you extract( $args, EXTR_SKIP ); at the beginning of oenology_hooks_setting_callback(), so you don't have to save every part of the array into a new $var? These will then be avaible with $'name_inside_the_array, for ex. '$title`, $tab, etc. –  kaiser Jun 3 '11 at 16:29
    
...because I'm not actually all that smart with PHP? :) I'll give that a try; thanks! –  Chip Bennett Jun 3 '11 at 17:45
    
Maybe you want to take a look at this Gist, which shows some "maybe best practice" example on how to add filters & hooks, parse arguments and deal with query string input. It's a little old and i will likely rework it when i got time, but imo it's worth a look. :) –  kaiser Jun 3 '11 at 18:01
    
This is actually just a Plugin that adds UI for hooks that I've added to Oenology. I'm pretty comfortable with how I've actually added the hooks to the Theme. Now, I'm just trying to provide a convenient way to expose them to end users. –  Chip Bennett Jun 3 '11 at 18:39
    
I haven't missunderstood you. I just wanted to show you this in case it might of some help (whenever) to you. I see this code as something ironic - just take a look how much effort it is to get each and everything for everybody in the wordpress way... –  kaiser Jun 3 '11 at 20:17

2 Answers 2

up vote 15 down vote accepted

if you look at the do_settings_sections function more specifically the line 1164 where the callback function is being executed :

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

you can see that the $section array is being passed to the callback function, so you can identify the callback by the $section['id']

hope this make since.

Update

here is an example, if your add_settings_section callback for all sections was named oenology_hooks_section_callback then you can identify it like this:

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
    }
 }

and by do stuff i mean do whatever you want to do with that section callback.

share|improve this answer
    
Hmm... that looks promising. How do I determine $section['id']? –  Chip Bennett Jun 3 '11 at 17:45
    
@Chip Bennett id will be first argument you pass to add_settings_section() –  Rarst Jun 3 '11 at 19:12
    
@Chip Bennett I added an example to try and explain better. –  Bainternet Jun 4 '11 at 0:55
    
@Bainternet: Awesome! I have an option script and met the same problem as Chip Bennett has. Now it works like a charm. Thanks. –  Rilwis Jun 4 '11 at 4:05
    
Okay, so it finally clicked over the weekend; let me try the code I have in mind, and I'll report back. –  Chip Bennett Jun 5 '11 at 22:31

I know this is an old question but I'll throw my two cents in, just in case someone else comes along; a simpler way to do so would be do write you own modification of the add_settings_section() function, which would only add a callback args parameter at the end of it.

This would look like this ( or something like it )

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' );
}

Now you would simply use this instead of the native wordpress function and access your callback args through the 'callbackargs' array key in a usual fashion, like this

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

Which we could use to pass to some other function :

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

Or the callback args could be an array themselves which we use :

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

This is all possible because all add_settings_section() does is add a new array member to the $wp_settings_sections global variable, that new array member could be an array itself containing any number of keys with different names, which could be used, by any function that knew they were there. When do_settings_sections calls the call_user_func_array it passes a $sections paramater as Bainternet noted, this means that the entire array we added to $wp_settings_sections in my_add_settings_section() is passed into our callback, meaning we have access to every new array member we add to it such as the callbackargs allowing our function to have a full fledged callback.

Even though im sure that this might be obvious i thought that I'd just explain it in case someone who gets confused looks in.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.