function widget($args, $instance)
 {
     // prepare $instance values for complex fields
     if (!empty($this->complex_field_names)) {
         $instance = self::unwrap_complex_field_values($instance, $this->complex_field_names);
     }
     // prepare $instance values for association fields
     foreach ($instance as &$field_value) {
         $field_value = resume_parse_relationship_field($field_value);
     }
     // output
     if ($this->print_wrappers) {
         echo $args['before_widget'];
     }
     $this->front_end($args, $instance);
     if ($this->print_wrappers) {
         echo $args['after_widget'];
     }
 }
 function resume_get_complex_fields($type, $name, $id = null)
 {
     $datastore = Resume_DataStore_Base::factory($type);
     if ($id) {
         $datastore->set_id($id);
     }
     $group_rows = $datastore->load_values($name);
     $input_groups = array();
     foreach ($group_rows as $row) {
         if (!preg_match('~^' . preg_quote($name, '~') . '(?P<group>\\w*)-_?(?P<key>.*?)_(?P<index>\\d+)_?(?P<sub>\\w+)?(-(?P<trailing>.*))?$~', $row['field_key'], $field_name)) {
             continue;
         }
         $row['field_value'] = maybe_unserialize($row['field_value']);
         // backward compatibility for Relationship field
         $row['field_value'] = resume_parse_relationship_field($row['field_value']);
         $input_groups[$field_name['index']]['_type'] = $field_name['group'];
         if (!empty($field_name['trailing'])) {
             $input_groups = resume_expand_nested_field($input_groups, $row, $field_name);
         } else {
             if (!empty($field_name['sub'])) {
                 $input_groups[$field_name['index']][$field_name['key']][$field_name['sub']] = $row['field_value'];
             } else {
                 $input_groups[$field_name['index']][$field_name['key']] = $row['field_value'];
             }
         }
     }
     // create groups list with loaded fields
     rbf_ksort_recursive($input_groups);
     return $input_groups;
 }