I would like to be able to set the allowed_values of the optionwidgets_buttons with multiple values by code. But I'm not having much luck; I'm only able to set the first value.

I'm using hook_form_alter.

$form only shows allowed_values in one place: $form['#field_info']['field_hb_stations']['allowed_values']

Is there another API I can use in conjunction with hook_form_alter in order to pull in the option_widgets to set the values?

Here is my code:


/**
* Implementation of hook_form_alter().
*/
function station_reg_form_alter(&$form, $form_state, $form_id) {
      
     // Alter the node edit form.

    if (isset($form['#node']) && isset($form['type']['#value']) && $form_id == 'station_reg_node_form')         
        
        $output .= dsm('station_reg_form_alter');
        $output .= dsm($form);
        $output .= dsm($form_state);        
                        
        
        //pull in data from database
        $station_id = "nid";
        $station_name = "field_station_name_value";
     
        $query = 'SELECT n. ' . $station_name . ' FROM {content_type_station} n  ORDER BY ' . $station_name;
        $query_result = db_query($query);
         
        $record_count = 0;
        while ($row = db_fetch_array($query_result))
        {
    
            $val = $row[$station_name];
            $stations .=  $record_count . '|' . $val . '\r\n';  \\ saw \r\n in cck/tests/content.crudtest

            $record_count++;
        }
        
        $form['#field_info']['field_hb_stations']['allowed_values'] = $stations;
        $output .= dsm($stations);
    }
    
}


Below is an export of the custom content type with the CCK field in question. I have set allowed_values to dummy values ('0|Station 1
1|Station 2
2|Station 3', ) that i would like to replace by code with real values drawn from the database.

$content['type']  = array (
  'name' => 'Station Registration Form',
  'type' => 'station_reg',
  'description' => 'Register volunteer for an event\'s station.',
  'title_label' => 'Title',
  'body_label' => '',
  'min_word_count' => '0',
  'help' => '',
  'node_options' => 
  array (
    'status' => true,
    'promote' => false,
    'sticky' => false,
    'revision' => false,
  ),
  'old_type' => 'station_reg',
  'orig_type' => '',
  'module' => 'node',
  'custom' => '1',
  'modified' => '1',
  'locked' => '0',
  'comment' => '0',
  'comment_default_mode' => '4',
  'comment_default_order' => '1',
  'comment_default_per_page' => '50',
  'comment_controls' => '3',
  'comment_anonymous' => 0,
  'comment_subject_field' => '1',
  'comment_preview' => '1',
  'comment_form_location' => '0',
  'ant' => '1',
  'ant_pattern' => '[type-name] [author-uid]',
  'ant_php' => 0,
);
$content['fields']  = array (
  0 => 
  array (
    'label' => 'Registrant',
    'field_name' => 'field_hb_registrant',
    'type' => 'text',
    'widget_type' => 'text_textfield',
    'change' => 'Change basic information',
    'weight' => '-1',
    'rows' => 5,
    'size' => '60',
    'description' => 'Person registering either self or another person',
    'default_value' => 
    array (
      0 => 
      array (
        'value' => '',
        '_error_element' => 'default_value_widget][field_hb_registrant][0][value',
      ),
    ),
    'default_value_php' => '',
    'default_value_widget' => NULL,
    'group' => false,
    'required' => 0,
    'multiple' => '0',
    'text_processing' => '0',
    'max_length' => '',
    'allowed_values' => '',
    'allowed_values_php' => '',
    'op' => 'Save field settings',
    'module' => 'text',
    'widget_module' => 'text',
    'columns' => 
    array (
      'value' => 
      array (
        'type' => 'text',
        'size' => 'big',
        'not null' => false,
        'sortable' => true,
        'views' => true,
      ),
    ),
    'display_settings' => 
    array (
      'label' => 
      array (
        'format' => 'above',
        'exclude' => 0,
      ),
      'teaser' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      'full' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      4 => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
    ),
  ),
  1 => 
  array (
    'label' => 'Assignee',
    'field_name' => 'field_hb_assignee',
    'type' => 'userreference',
    'widget_type' => 'userreference_autocomplete',
    'change' => 'Change basic information',
    'weight' => '1',
    'autocomplete_match' => 'contains',
    'size' => '60',
    'reverse_link' => 1,
    'description' => 'Assign a PTA member to one or more of the stations below.',
    'default_value' => 
    array (
      0 => 
      array (
        'uid' => NULL,
        '_error_element' => 'default_value_widget][field_hb_assignee][0][uid][uid',
      ),
    ),
    'default_value_php' => '',
    'default_value_widget' => 
    array (
      'field_hb_assignee' => 
      array (
        0 => 
        array (
          'uid' => 
          array (
            'uid' => '',
            '_error_element' => 'default_value_widget][field_hb_assignee][0][uid][uid',
          ),
          '_error_element' => 'default_value_widget][field_hb_assignee][0][uid][uid',
        ),
      ),
    ),
    'group' => false,
    'required' => 0,
    'multiple' => '0',
    'referenceable_roles' => 
    array (
      2 => 0,
    ),
    'referenceable_status' => '',
    'op' => 'Save field settings',
    'module' => 'userreference',
    'widget_module' => 'userreference',
    'columns' => 
    array (
      'uid' => 
      array (
        'type' => 'int',
        'unsigned' => true,
        'not null' => false,
        'index' => true,
      ),
    ),
    'display_settings' => 
    array (
      'label' => 
      array (
        'format' => 'above',
        'exclude' => 0,
      ),
      'teaser' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      'full' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      4 => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
    ),
  ),
  2 => 
  array (
    'label' => 'Stations',
    'field_name' => 'field_hb_stations',
    'type' => 'text',
    'widget_type' => 'optionwidgets_buttons',
    'change' => 'Change basic information',
    'weight' => '2',
    'description' => '',
    'default_value' => 
    array (
      0 => 
      array (
        'value' => NULL,
      ),
    ),
    'default_value_php' => '',
    'default_value_widget' => 
    array (
      'field_hb_stations' => 
      array (
        'value' => 
        array (
          '' => 1,
          0 => false,
          1 => false,
          2 => false,
        ),
      ),
    ),
    'group' => false,
    'required' => 1,
    'multiple' => '1',
    'text_processing' => '0',
    'max_length' => '',
    'allowed_values' => '0|Station 1
1|Station 2
2|Station 3',
    'allowed_values_php' => '',
    'op' => 'Save field settings',
    'module' => 'text',
    'widget_module' => 'optionwidgets',
    'columns' => 
    array (
      'value' => 
      array (
        'type' => 'text',
        'size' => 'big',
        'not null' => false,
        'sortable' => true,
        'views' => true,
      ),
    ),
    'display_settings' => 
    array (
      'label' => 
      array (
        'format' => 'above',
        'exclude' => 0,
      ),
      'teaser' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      'full' => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
      4 => 
      array (
        'format' => 'default',
        'exclude' => 0,
      ),
    ),
  ),
);
$content['extra']  = array (
  'title' => '-5',
  'revision_information' => '-3',
  'comment_settings' => '-2',
  'menu' => '-4',
);

Please assist.
Thanks,
Tom

Comments

markus_petrux’s picture

Status: Active » Fixed

Much easier than hook_form_alter(): Use PHP code in field settings to generate the allowed values list. That snippet should return an array of labels keyed by value.

Something like the following:

$values = array();
$result = db_query('SELECT nid, field_station_name_value AS name FROM {content_type_station} ORDER BY field_station_name_value');
while ($row = db_fetch_object($result)) {
  $values[$row->nid] = $row->name;
}
return $values;

You may also want to add an index by field_station_name_value to that table.

tomsherlock’s picture

Markus, thank you very much for quick and detailed reply. Thank you for taking the precious time to review and digest my post.

Your suggested snippet worked like a charm. Of course when i tried to apply it last night, i forgot to remove the php mark-up. And so, naturally, i didn't work until i removed the php mark-up.

I'm not sure had to add the index to the table. I realize that is beyond the scope of this forum, so i'll just browse mysql sources to glean that information.

I would still like to know how to populated the allowed_values field in code. Following one of your snippets on disabling a widget, i was able to successfully disable optionwidgets_onoff in an afterbuild function. I imagine that i would do something similar with optionwidgets_buttons and allowed_values.

However, this knowledge is no longer urgent as your suggested snippet will allow me to move on with my project.

Now, your references to nid made me realize that i won't have write any code at all to obtain my list of checkboxes; i can simply use nodereference.

Thanks,
Tom

markus_petrux’s picture

Re: "I would still like to know how to populated the allowed_values field in code."

This is a lot more complex because at the time hook_form_alter() is processed, the options have not been expanded yet, and at the time an after_build callback is invoked, all the checkboxes are expanded in the form as individual form elements. You would have to use var_dump() or similar to figure out the format, and then try to change that in the form. Too tricky, I think. On the other hand, generating the allowed values list using a PHP snippet in the field settings is so much simpler, to code, and then to maintain.

Re: "I'm not sure had to add the index to the table."

If you use something like "ORDER BY field_station_name_value" in your query, then you may want to add an index by that column. You can do it using the UI of something like phpMyAdmin.

tomsherlock’s picture

I've decided to abandon the nodereference approach and resume the approach discussed in this thread. I've taken your sample code, markus_petrux, to produce a more complex derivative (see code below). I am presenting only those options that are still available.
Each station has a limited number of spots. Once all those spots are filled the station is removed from the list.

This causes a problem in edit mode. I am presented with only those station that still have available spots. The spot that a volunteer had selected is not presented on the page when in edit mode, because the simple code wont present stations that are full.

I wonder if any of this can be separated and put it in a module, using hook_form_alter, hook_after_build. Or use a costumized node-nodename.tpl.php, page-node-add-nodename.tpl.php or page-node-edit.tpl.php, etc. but it is not clear to me what I can pull out.

I am using a node-nodename.tpl.php to present the saved node and am now struggling with page-node-edit.tpl.php. With the following code in the optionwidgets_buttons allowed_values field while in edit mode of an existing node, the previous selected settings are not presented.

 $stations = array();
 $availability = '';
    
    $query = 'SELECT nid, field_station_name_value AS name FROM {content_type_station} ORDER BY field_station_name_value';

    $result = db_query($query);

    while ($row = db_fetch_object($result)) {

        $station = node_load($row->nid);
        $max_station_slots = $station->field_station_vol_count[0]['value'];
        
        $query_2 = 'SELECT COUNT(field_hb_stations_value) FROM {content_field_hb_stations} WHERE field_hb_stations_value = \'%d\'';
        
        $station_member_count = db_result(db_query($query_2, $row->nid));
        $station_name = $station->field_station_name[0]['value'];
          
         if($station_member_count < $max_station_slots){
           
           $slots_free =  $max_station_slots - $station_member_count;
           $max_spots = ' (' . $max_station_slots . ' spots in total) ';

           if($slots_free > 1){
             $availability = $max_spots . ' <div class="status">' . $slots_free . ' spots still available for ' . $station_name . ' </div>';
           }
           else{
             $availability = $max_spots . ' <div class="status">' . $slots_free . ' spot still available for ' . $station_name . ' </div>';
           } 
           $stations[$row->nid] = $station_name . $availability ;
          }
          else{
            drupal_set_message('The station ' . $station_name . ' is not available.');
          }
    }

return $stations;

Your input is much appreciated.

tomsherlock’s picture

When i'm in edit mode, i need to be able to populated the array $stations returned by allowed values with stations already selected as well as stations still available but not yet selected.

I'm thinking i would need to check if in edit mode, if is a particular node type and if node id exists. Then get selected values for the field. Populate array with stations selected as well as stations available. If there is an overlap i would eliminated from the second group according to node id.

Again, this seems like a lot of logic to place in the allowed values php field. I'm wondering if i could do all this in hook_form_alter, hook_after_build or a preprocessor and then allow the allowed values php field to pull in an array from the relevant node.

Thoughts?

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.