Index: profile_csv.info =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/profile_csv/profile_csv.info,v retrieving revision 1.3.2.2 diff -u -p -r1.3.2.2 profile_csv.info --- profile_csv.info 11 May 2010 23:32:37 -0000 1.3.2.2 +++ profile_csv.info 8 Sep 2010 14:06:58 -0000 @@ -1,5 +1,3 @@ name = Profile CSV -description = Allows exporting profile data in Comma Separated Values (CSV) format. -dependencies[] = profile +description = "Allows exporting profile data in Comma Separated Values (CSV) format, works with either the core Profile module or nodes via Content_Profile." core = 6.x - Index: profile_csv.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/profile_csv/profile_csv.module,v retrieving revision 1.10.2.6 diff -u -p -r1.10.2.6 profile_csv.module --- profile_csv.module 12 Aug 2010 15:59:16 -0000 1.10.2.6 +++ profile_csv.module 8 Sep 2010 14:06:58 -0000 @@ -84,9 +84,9 @@ function profile_csv_admin_settings() { '#collapsed' => TRUE, ); $options = array( - 1 => t('Active'), - 0 => t('Blocked'), - 2 => t('Both'), + 1 => t('Active'), + 0 => t('Blocked'), + 2 => t('Both'), ); $form[$set][PROFILE_CSV_STATUS] = array( '#type' => 'select', @@ -115,35 +115,175 @@ function profile_csv_admin_settings() { '#default_value' => variable_get(PROFILE_CSV_PARAM .'fields', array()), ); + // Drupal core's profile module. $set = 'profile'; - $form[$set] = array( - '#type' => 'fieldset', - '#title' => t('Categories'), - '#description' => t('Select one or more profile fields from categories below.'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); + if (!module_exists($set)) { + $form[$set] = array( + '#type' => 'fieldset', + '#title' => t('Profile Fields'), + '#description' => t('No profile fields are available as the core Profile module is disabled. Once it is enabled and fields are added they will be listed here.', array('%link' => url('admin/build/modules'))), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ); + } + else { + $form[$set] = array( + '#type' => 'fieldset', + '#title' => t('Profile Fields'), + '#description' => t('Select one or more profile fields from categories below. These are provided by the core Durpal Profiles module.'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); - $result = db_query("SELECT pf.fid, pf.name, pf.title, pf.category - FROM {profile_fields} pf - ORDER BY pf.category, pf.weight, pf.title"); - while ($row = db_fetch_object($result)) { - $fld = PROFILE_CSV_PARAM .'profile_'. $row->fid; - if (!isset($form[$set][$row->category])) { - $form[$set][$row->category] = array( - '#type' => 'fieldset', - '#title' => check_plain(t($row->category)), - '#collapsible' => TRUE, + $result = db_query("SELECT pf.fid, pf.name, pf.title, pf.category + FROM {profile_fields} pf + ORDER BY pf.category, pf.weight, pf.title"); + $profile_fields = FALSE; + while ($row = db_fetch_object($result)) { + $profile_fields = TRUE; + $fld = PROFILE_CSV_PARAM .'profile_'. $row->fid; + if (!isset($form[$set][$row->category])) { + $form[$set][$row->category] = array( + '#type' => 'fieldset', + '#title' => check_plain(t($row->category)), + '#collapsible' => TRUE, + ); + } + + $form[$set][$row->category][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain(t($row->title)), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), ); } + if (!$profile_fields) { + $form[$set]['#description'] .= '
' . t('Note: No fields have been configured, once fields are added they will appear below.', array('%link' => url('admin/user/profile'))); + } + } - $form[$set][$row->category][$fld] = array( - '#type' => 'checkbox', - '#title' => check_plain(t($row->title)), - '#return_value' => 1, - '#default_value' => variable_get($fld, 0), + $set = 'content_profile'; + if (!module_exists($set)) { + $form[$set] = array( + '#type' => 'fieldset', + '#title' => t('Content_Profile Fields'), + '#description' => t('No fields are available as the Content Profile contrib module is not installed.', array('%link' => url('http://drupal.org/project/content_profile'))), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ); + } + else { + $form[$set] = array( + '#type' => 'fieldset', + '#title' => t('Content_Profile Fields'), + '#description' => t('Select one or more profile fields from categories below. These are provided by the Content Profile contrib module.', array('%link' => url('http://drupal.org/project/content_profile'))), + '#collapsible' => TRUE, + '#collapsed' => TRUE, ); + + // Get a list of all content types. + foreach (_profile_csv_get_content_profile_types() as $type_name => $type) { + // Start a new fieldset to contain everything. + $fieldset = PROFILE_CSV_PARAM . 'content_profile_' . $type_name; + $form[$set][$fieldset] = array( + '#type' => 'fieldset', + '#title' => check_plain($type_details['name']), + '#collapsible' => TRUE, + ); + + // Optional title. + if ($type->has_title) { + $fld = PROFILE_CSV_PARAM . $type_name . '_title'; + $form[$set][$fieldset][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain(t($type->title_label . ' (node title)')), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), + ); + } + + // Optional body field. + if ($type->has_body) { + $fld = PROFILE_CSV_PARAM . $type_name . '_body'; + $form[$set][$fieldset][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain(t($type->body_label . ' (node body)')), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), + ); + } + + // Vocabularies. + if (module_exists('taxonomy')) { + $vocabs = taxonomy_get_vocabularies($type_name); + if (!empty($vocabs)) { + $form[$set][$fieldset]['vocabs'] = array( + '#type' => 'fieldset', + '#title' => check_plain(t('Vocabularies')), + '#collapsible' => TRUE, + ); + foreach ($vocabs as $vocab_name => $vocab) { + $fld = PROFILE_CSV_PARAM . $type_name . '_vocab_' . $vocab_name; + $form[$set][$fieldset]['vocabs'][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain($vocab->name), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), + ); + } + } + } + + // CCK. + if (module_exists('content')) { + $type_details = content_types($type_name); + + $form_groups = array(); + if (function_exists('fieldgroup_groups') && $groups = fieldgroup_groups($type_name)) { + // Loop over each of the fieldgroups that are used for this type. + foreach ($groups as $group_name => $group) { + $form_groups[$group_name] = array( + '#type' => 'fieldset', + '#title' => check_plain($group['label']), + '#collapsible' => TRUE, + ); + // Loop over each field that is stored in this group. + foreach ($group['fields'] as $field_name => $field) { + $fld = PROFILE_CSV_PARAM . $type_name . '_' . $field_name; + $form_groups[$group_name][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain($field['label'] . ' (' . $field['widget_type'] . ')'), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), + ); + // Remove this field from the main stack so it isn't processed again. + unset($type_details['fields'][$field_name]); + } + } + } + + // Loop over each field. + foreach ($type_details['fields'] as $field_name => $field) { + $fld = PROFILE_CSV_PARAM . $type_name . '_' . $field_name; + $form[$set][$fieldset][$fld] = array( + '#type' => 'checkbox', + '#title' => check_plain($field['widget']['label'] . ' (' . $field['widget']['type'] . ')'), + '#return_value' => 1, + '#default_value' => variable_get($fld, FALSE), + ); + } + + // Add any fieldgroups after the individual fields. + if (!empty($form_groups)) { + $form[$set][$fieldset] += $form_groups; + } + } + } } + + //TODO: add a hook to allow modules to tap into the output. + //TODO: location module support. + return system_settings_form($form); } @@ -195,6 +335,9 @@ function profile_csv_page() { exit(); } +/** + * List of fields from the core Profile module. + */ function _profile_csv_get_profile_fields() { static $fields; @@ -212,17 +355,138 @@ function _profile_csv_get_profile_fields return $fields; } +/** + * List of content types that are used for profiles. + */ +function _profile_csv_get_content_profile_types() { + static $types; + + if (!isset($types)) { + $types = array(); + foreach (node_get_types() as $type_name => $type) { + // See if this content type is used for content_profile. + if (variable_get('content_profile_use_' . $type_name, FALSE)) { + $types[$type_name] = $type; + } + } + } + + return $types; +} + +/** + * List of fields from the Content_Profile module & CCK. + */ +function _profile_csv_get_content_profile_fields() { + static $fields; + + if (!isset($fields)) { + $fields = array(); + foreach (_profile_csv_get_content_profile_types() as $type_name => $type) { + // Title. + if ($type->has_title) { + $fld = PROFILE_CSV_PARAM . $type_name . '_title'; + if (variable_set($fld, FALSE)) { + $fields[] = array('name' => 'title', 'title' => $type->title_label, 'type' => $type->type, 'visibility' => 1, 'node_type' => $type_name); + } + } + // Body. + if ($type->has_body) { + $fld = PROFILE_CSV_PARAM . $type_name . '_body'; + if (variable_set($fld, FALSE)) { + $fields[] = array('name' => 'body', 'title' => $type->body_label, 'type' => 'body', 'visibility' => 1, 'node_type' => $type_name); + } + } + + // Vocabularies. + if (module_exists('taxonomy')) { + $vocabs = taxonomy_get_vocabularies($type_name); + if (!empty($vocabs)) { + foreach ($vocabs as $vocab_name => $vocab) { + $fld = PROFILE_CSV_PARAM . $type_name . '_vocab_' . $vocab_name; + if (variable_set($fld, FALSE)) { + $fields[] = array('name' => 'vocab_' . $vocab_name, 'title' => $vocab->name, 'type' => 'vocab', 'visibility' => 1, 'node_type' => $type_name); + } + } + } + } + + // CCK. + if (module_exists('content')) { + $type_details = content_types($type_name); + $form_groups = array(); + + if (function_exists('fieldgroup_groups') && $groups = fieldgroup_groups($type_name)) { + // Loop over each of the fieldgroups that are used for this type. + foreach ($groups as $group_name => $group) { + // Loop over each field that is stored in this group. + foreach ($group['fields'] as $field_name => $field) { + $fld = PROFILE_CSV_PARAM . $type_name . '_' . $field_name; + if (variable_get($fld, FALSE)) { + $form_groups[] = array('name' => $field_name, 'title' => $field['label'], 'type' => $field['widget_type'], 'visibility' => 1, 'node_type' => $type_name); + } + // Remove this field from the main stack so it isn't processed again. + unset($type_details['fields'][$field_name]); + } + } + } + + // Loop over each field. + foreach ($type_details['fields'] as $field_name => $field) { + $fld = PROFILE_CSV_PARAM . $type_name . '_' . $field_name; + if (variable_get($fld, FALSE)) { + $fields[] = array('name' => $fld, 'title' => $field['widget']['label'], 'type' => $field['widget']['type'], 'visibility' => 1, 'node_type' => $type_name); + } + } + + // Add any fieldgroups after the individual fields. + if (!empty($form_groups)) { + $fields += $form_groups; + } + } + } + + // Allow other modules to alter the output. + // hook_profile_csv_fields(&$fields); + $hook = 'profile_csv_fields'; + foreach (module_implements($hook) as $module) { + $f = $module . '_' . $hook; + $f($fields, $field, $node); + } + } + + return $fields; +} + function _profile_csv_format_user($uid = 0) { - $user_data = _profile_csv_get_user($uid); - $profile_data = _profile_csv_get_profile($uid, $user_data['data']); - unset($user_data['data']); - $info = array_merge($user_data, $profile_data); - //all of the valid fields in ['data'] should have been picked out in _profile_csv_get_profile, so unset it + $new_info = array(); + + // Get the basic user fields. + $info = _profile_csv_get_user($uid); + + // The profile module is enabled. + if (module_exists('profile')) { + $profile_data = _profile_csv_get_profile($uid, $info['data']); + // All of the valid fields in ['data'] should have been picked out in + // _profile_csv_get_profile, so unset it. + unset($info['data']); + $info += $profile_data; + } + + // The profile module is enabled. + if (module_exists('content_profile')) { + $profile_data = _profile_csv_get_content_profile($uid); + // All of the valid fields in ['data'] should have been picked out in + // _profile_csv_get_profile, so unset it. + unset($info['data']); + $info += $profile_data; + } + // Compile the fields. foreach ($info as $value) { $new_info[] = '"'. str_replace('"', '""', $value) .'"'; } - if (isset($new_info)) { + if (!empty($new_info)) { $line = implode(",", $new_info); } $data .= trim($line) ."\n"; @@ -233,7 +497,8 @@ function _profile_csv_format_user($uid = function _profile_csv_get_user($uid) { $user = array(); $fields = _profile_csv_users_selected_fields(); - //Verify that the columns haven't been deleted since the last save or the query will fail + // Verify that the columns haven't been deleted since the last save or the + // query will fail. $schema = drupal_get_schema('users'); foreach ($fields as $field_name => $value) { if (!$schema['fields'][$field_name]) { @@ -253,8 +518,8 @@ function _profile_csv_get_user($uid) { function _profile_csv_get_profile($uid=0, $user_data=NULL) { $profile_fields = _profile_csv_get_profile_fields(); $profile_result = array(); - foreach ($profile_fields as $profile_field) { - if ($profile_field ['visibility'] == 4) { + foreach ($profile_fields as $profile_field) { + if ($profile_field['visibility'] == 4) { // Try to get it from the $user_data $value = $user_data[$profile_field['name']]; } @@ -277,14 +542,179 @@ function _profile_csv_get_profile($uid=0 return $profile_result; } +/** + * Obtain data from the content profile. + */ +function _profile_csv_get_content_profile($uid=0) { + $profile_fields = _profile_csv_get_content_profile_fields(); + $profile_result = array(); + // Loop over each supported profile content type. + foreach (_profile_csv_get_content_profile_types() as $type_name => $type) { + $results = db_query("SELECT nid FROM {node} WHERE uid=%d AND type='%s'", $uid, $type_name); + + // Loop over each profile node for this user. + while ($n = db_fetch_array($results)) { + // Load the full node. Note: node caching would help here. + $node = node_load($n['nid']); + + // Loop over each field. + foreach ($profile_fields as $field) { + // If this field is in this node type, process it. + if ($field['node_type'] == $type_name) { + // Allow some fields to be based on others. + if (isset($field['base'])) { + $value = $node->{$field['base']}; + } + else { + $value = $node->{$field['name']}; + } + + // See if any hooks want to modify the output. + // hook_profile_csv_export(&$value, $field, $node); + $from_hook = FALSE; + $hook = 'profile_csv_export'; + foreach (module_implements($hook) as $module) { + $f = $module . '_' . $hook; + $return = $f($value, $field, $node); + // Take the first response that returns. + if ($return) { + $from_hook = TRUE; + break; + } + } + + // If nothing returned from the hook, handle it here. + if (!$from_hook) { + switch ($field['type']) { + // Core fields. + case 'title': + case 'body': + // Keep the fields as-is. + break; + + // Standard CCK text fields. + case 'text_textarea': + case 'text_textfield': + $values = array(); + foreach ($value as $x => $data) { + $values[] = $data['value']; + } + $value = $values; + unset($values); + break; + + // Standard CCK optionwidget fields. + case 'optionwidgets_buttons': + case 'optionwidgets_select': + $values = array(); + foreach ($value as $x => $data) { + $values[] = $data['value']; + } + $value = implode(', ', $values); + unset($values); + break; + + // Date module. + case 'date_select': + // Empty date strings. + $dates = array(); + foreach ($value as $date) { + // Skip empty dates. + if ($date['value'] != '0000-00-00T00:00:00') { + $dates[] = date_format_date($date['value']); + } + } + $value = $dates; + unset($dates); + break; + + // Link module. + case 'link': + $links = array(); + foreach ($value as $link) { + if (!empty($link['title'])) { + $links[] = $link['title'] . ': ' . $link['url']; + } + else { + $links[] = $link['url']; + } + } + $value = implode("\n", $links); + break; + + // Location module. + case 'location': + $locations = array(); + foreach ($value as $l) { + $locations[] = strip_tags(theme('location', $l)); + } + $value = $locations; + unset($locations); + break; + + // Content_Taxonomy module. + case 'content_taxonomy_autocomplete': + $terms = array(); + foreach ($value as $t) { + $term = taxonomy_get_term($t['value']); + $terms[] = check_plain($term->name); + } + // These can be joined into one line. + $value = implode(', ', $terms); + unset($terms); + break; + + // Computed module. + case 'computed': + $output = array(); + foreach ($value as $val) { + $output[] = check_plain($val); + } + $value = $output; + unset($output); + break; + + // Anything else. + default: + watchdog('profile_csv', "Unknown field {$field['type']}."); + $output = array(); + foreach ($value as $val) { + $output[] = strip_tags(content_format($field['type'], $val)); + } + $value = $output; + unset($output); + } + } + if (is_array($value)) { + $value = implode("\n", $value); + } + $profile_result[] = trim($value); + } + } + } + } + return $profile_result; +} + function _profile_csv_header() { $row = array(); $fields = _profile_csv_users_selected_fields(); foreach ($fields as $field_name => $value) { $row[] = '"'. _profile_csv_users_map_column_name($field_name) .'"'; } - foreach (_profile_csv_get_profile_fields() as $field) { - $row[] = '"'. $field['title'] .'"'; + + // The profile module is enabled. + if (module_exists('profile')) { + foreach (_profile_csv_get_profile_fields() as $field) { + $row[] = '"'. $field['title'] .'"'; + } + } + + // The content_profile module is enabled. + if (module_exists('content_profile')) { + foreach (_profile_csv_get_content_profile_fields() as $field) { + $row[] = '"'. $field['title'] .'"'; + } } return implode(",", $row) ."\n";