How to pre-populate fields on a node creation form based on fields from Profile2 module?

There is a content type ("Job Listing") that a business account can use to list job openings, and a Profile2 profile for each business that contains the business's address, organization name and taxonomy terms such as industry type.

95% of the businesses that will list a job posting will use the same information; I could just use the profile information, but I need to account for the 5% that might want to change the job listing form. For example, the job might be in another state or country and that needs to be accounted for. I think the the best way to handle this situation is to have the same fields in both the profile and job listing form but allow the business change the information in the job listing form.

It would make sense to pre-populate the job listing form with business profile information as the default. How do I best do this? I was going to use Rules but I can't find a single option for a Rule before the original node creation form is created.

Should I just use hook_form_alter() to access the profile information on orginal node creation and use that information to set the default values?

Answers 3

  • I created a hook_form_FORM_ID_alter() function in a helper module that tests to see if the node has a NID and if so if it is not in the operation preview. Then I populate the default values of the form with the companies profile information so they can change it later.

    // We need to set the default of the Job Listing fields on a new Job Listing form */
    function helper_form_job_listing_node_form_alter(&$form, &$form_state) {
      // test if node for has been assigned a NID. If not then populate fields with default data */
      if (empty($form['nid']['#value']) && (!isset($form['#node']->op))){
        $profile = profile2_load_by_user ($form['uid']['#value'], 'business_profile'); 
        // We currently do not know what the profile language is */
        // Organization name
        if (isset($profile->field_job_organization['und'][0]['value'])){
          $form['field_job_organization']['und'][0]['value']['#default_value'] =  $profile->field_job_organization['und'][0]['value'];
        }
        // Set the default address
        if (isset($profile->field_resume_address['und'][0]['thoroughfare'])) {
          $form['field_resume_address']['und'][0]['#address']['thoroughfare'] = $profile->field_resume_address['und'][0]['thoroughfare'];
        }
        if (isset($profile->field_resume_address['und'][0]['locality'])) {
          $form['field_resume_address']['und'][0]['#address']['locality'] = $profile->field_resume_address['und'][0]['locality']; 
        }
        if (isset($profile->field_resume_address['und'][0]['administrative_area'])) {
          $form['field_resume_address']['und'][0]['#address']['administrative_area'] = $profile->field_resume_address['und'][0]['administrative_area'];                  
        }
        if (isset($profile->field_resume_address['und'][0]['country'])) { 
          $form['field_resume_address']['und'][0]['#address']['country'] = $profile->field_resume_address['und'][0]['country'];  
        }
        if (isset($profile->field_resume_address['und'][0]['premise'])) {
          $form['field_resume_address']['und'][0]['#address']['premise'] = $profile->field_resume_address['und'][0]['premise']; 
        }
        if (isset($profile->field_resume_address['und'][0]['postal_code'])) {
          $form['field_resume_address']['und'][0]['#address']['postal_code'] = $profile->field_resume_address['und'][0]['postal_code']; 
        }  
      }                                                              
    }
    

  • I had the same requirement and used the code above to get started. Unfortunately the code above does not take multiple country selections and therefore the dynamic field nature of country specific fields (provinces, states, etc.) into account. I cobbled together a new function to pre-populate the address field but with the ability to switch to the right country.

    I got that snippet of code on how to do this from mrfelton who wrote a patch for similar address population functionality for drupal commerce. Thanks for that inspiration.

    So here is my function that I used to pre-fill field address data. Please improve on this and give back to the community.


        //method to prepopulate the address field including switching to the right country context
    function field_prepopulate_field_widget_form_alter(&$element, &$form_state, $context) {
        // Forms where the pre-population is supposed to occur
        $validforms = array(
                "job_listing_node_form",
                "job_editing_node_form",
                "some_other_node_form"
        ); 
    
        // Check that I am on the right form
        if(in_array($form_state['build_info']['form_id'], $validforms)) {
            // Check that I am changing the right field
            if($context['field']['field_name'] == 'field_address') {
                global $user;
                $user_fields = user_load($user->uid);
                if (isset($user_fields->field_address) && !empty($user_fields->field_address)) {
                    // use field_get_items function to avoid the entire language nonsense (tongue-in-cheek) in the array
                    $address_data = field_get_items('user', $user_fields, 'field_address');
                    //This may look redundant but is important - fill the address fields out once so that the right country is set
                    foreach($address_data[0] as $key => $value) {
                        $context['items'][$context['delta']][$key] = $value;
                    }
                    // regenerate the widget so that the right country specific fields are rendered
                    $format = addressfield_field_widget_form($context['form'], $form_state, $context['field'], $context['instance'], $context['langcode'], $context['items'], $context['delta'], array());
    
                    // Switch out the form elements with our newly generated ones.
                    foreach ($element as $key => $value) {
                        if (isset($format[$key])) {
                            $element[$key] = $format[$key];
                        }
                    }
    
                    // Set the detault values.
                    $element['#address'] = $address_data[0];
                }
            }
        }
    }
    


  • I made a more generic (but not perfect) module based on the answer from endless summer. It assumes that the field names from your profile and the node are the same and will prepopulate all fields from a given profile:

    function helper_form_job_listing_node_form_alter(&$form, &$form_state) 
    {
        if (!empty($form['nid']['#value']) || isset($form['#node']->op))
        {
            return;
        }
        $profile = profile2_load_by_user ($form['uid']['#value'], 'business_profile'); 
        if (isset($profile)) {
            helper_prepopulate($profile, $form);
        }                                                              
    }
    
    function helper_prepopulate(&$source, &$destination) 
    {
        foreach($source as $fieldName => $sourceValue)
        {
            if(substr($fieldName, 0, strlen('field_')) !== 'field_' ||
                !isset($destination[$fieldName]['und'][0]) ||
                !isset($sourceValue['und'][0])) 
            { 
                continue; 
            }
            if(isset($destination[$fieldName]['und'][0]['#addressfield']) &&
                $destination[$fieldName]['und'][0]['#addressfield'])
            {
                foreach($sourceValue['und'][0] as $addressFieldName => $addressvalue)
                {
                    $destination[$fieldName]['und'][0]['#address'][$addressFieldName] = $addressvalue;
                }
            }
            else if(isset($destination[$fieldName]['und'][0]['#type']) &&
                $destination[$fieldName]['und'][0]['#type'] == 'date_combo')
            {
                $destination[$fieldName]['und'][0]['#default_value']['value'] = $sourceValue['und'][0]['value'];    
            }
            else
            {
                $destination[$fieldName]['und'][0]['value']['#default_value'] = $sourceValue['und'][0]['value'];
            }
        }
    }
    

Related Questions