'users', 'provider' => 'internal', // won't show up in external list. 'join' => array( 'left' => array( 'table' => 'node', 'field' => 'uid' ), 'right' => array( 'field' => 'uid' ), ), 'filters' => array( 'distinct' => array( 'name' => t('Profile: Distinct'), 'operator' => array('=' => 'is'), 'list' => array('distinct' => 'distinct'), 'handler' => 'views_handler_filter_profile_distinct', 'value-type' => 'array', 'help' => t('This filter ensures that each user profile may only be listed once, even if it matches multiple criteria.'), ), ), ); // add all profile fields as possible display fields and filters $profile_fields = profile_views_get_fields(); foreach ($profile_fields as $field) { $tables["$field->name"] = views_new_table('profile_values', 'internal', 'users', 'uid', 'uid', array( 'fid' => $field->fid ) ); profile_views_add_field($tables["$field->name"], $field); profile_views_add_filter($tables["$field->name"], $field); } return $tables; } function profile_views_arguments() { } function profile_views_default_views() { } /** * Get all profile fields */ function profile_views_get_fields() { $fields = array(); $results = db_query("SELECT * FROM {profile_fields} ORDER BY category, weight"); while ($row = db_fetch_object($results)) { // don't include private fields if (user_access('administer users') || $row->visibility != PROFILE_PRIVATE) { // make this work for default and modified profile.module //$row->options = unserialize($row->options); if( !empty($row->options) ){ if( unserialize($row->options) == false ){ // unserialized fields default version $options = $row->options; unset($row->options); $row->options['selection'] = $options; } else { // serialized fields or modified version $row->options = unserialize($row->options); } } $fields[] = $row; } } return $fields; } /** * Add profile fields to view table */ function profile_views_add_field(&$table, $field) { $name = 'value'; $label = t('Profile: %field-name', array('%field-name' => $field->title)); switch ($field->type) { case 'vocabulary': $help = t('This will display all options of the profile field %field-name. ', array('%field-name' => $field ->title)); $others = array( 'sortable' => false, 'handler' => 'views_handler_field_profile_vocabulary', ); break; case 'selection': $help = t('This will display all options of the profile field %field-name. ', array('%field-name' => $field ->title)); $others = array( 'sortable' => false, 'handler' => 'views_handler_field_profile_selection', ); break; case 'date': $help = t('This filter allows nodes to be filtered by their creation date. Enter dates in the format: CCYY-MM-DD HH:MM:SS. Enter \'now\' to use the current time. You may enter a delta (in seconds) to the option that will be added to the time; this is most useful when combined with now. If you have the jscalendar module from jstools installed, you can use a popup date picker here.'); $others = array( 'sortable' => false, 'handler' => 'views_handler_field_profile_date', ); break; case 'checkbox': $help = t('Checkbox based profile field help'); $others = array( 'sortable' => false, 'handler' => 'views_handler_field_profile_checkbox', ); break; default: $help = t('Other types based profile field help'); $others = array( 'sortable' => false, 'handler' => 'views_handler_field_profile_default', ); } views_table_add_field($table, $name, $label, $help, $others); } /** * Add profile filters to view table */ function profile_views_add_filter(&$table, $field) { $name = 'value'; $label = t('Profile: %field-name', array('%field-name' => $field->title)); switch ($field->type) { case 'vocabulary': $help = t('Taxonomy based profile field help'); $others = array( 'list' => 'views_handler_filter_tid_by_voc', 'value-type' => 'array', 'option' => 'string', 'operator' => 'views_handler_operator_andor', 'handler' => 'views_handler_filter_profile_andor', 'vocabulary' => $field->options['vocabulary'], ); break; case 'selection': $help = t('Selection based profile field help'); $others = array( 'list' => 'views_handler_filter_profile_selection', 'operator' => 'views_handler_operator_andor', 'options' => $field->options['selection'], 'handler' => 'views_handler_filter_profile_andor', ); break; case 'date': $help = t('This filter allows nodes to be filtered by their creation date. Enter dates in the format: CCYY-MM-DD HH:MM:SS. Enter \'now\' to use the current time. You may enter a delta (in seconds) to the option that will be added to the time; this is most useful when combined with now. If you have the jscalendar module from jstools installed, you can use a popup date picker here.'); $others = array( 'operator' => 'views_handler_operator_gtlt', //'value' => views_handler_filter_date_value_form(), 'value' => views_handler_filter_profile_date_value_form(), 'handler' => 'views_handler_filter_profile_date', 'value-type' => 'array', 'fid' => $field->fid, ); break; case 'checkbox': $help = t('Checkbox based profile field help'); $others = array( 'operator' => array('=' => 'Equals'), 'list' => 'views_handler_operator_yesno', //'value-type' => 'array', //'list-type' => 'select', ); break; default: $help = t('Other types based profile field help'); $others = array( 'list-type' => 'list', 'operator' => 'views_handler_operator_like', 'handler' => 'views_handler_filter_like', ); } views_table_add_filter($table, $name, $label, $help, $others); } /* FIELD HANDLER METHODS */ /** * Display a profile field of type 'vocabulary' */ function views_handler_field_profile_vocabulary($fieldinfo, $fielddata, $value, $data) { return _profile_field_vocabulary_getlist( unserialize($value) , 'taxonomy/term/' ); } /** * Display a profile field of type 'selection' */ function views_handler_field_profile_selection($fieldinfo, $fielddata, $value, $data) { $value = ( unserialize($value) == false ) ? $value : unserialize($value); if ( !is_array($value)) { $value = array($value); } // handles cases where values were set before this new profile module was put in place return check_plain(implode(', ',$value)); } /** * Default display method for a profile field */ function views_handler_field_profile_default($fieldinfo, $fielddata, $value, $data) { $value = ( unserialize($value) == false ) ? $value : unserialize($value); return check_plain($value); } /** * Display a profile field of type 'checkbox', view as tick mark */ function views_handler_field_profile_checkbox($fieldinfo, $fielddata, $value, $data) { $value = ( unserialize($value) == false ) ? $value : unserialize($value); return (check_plain($value) == '0') ? '✗' : '✓'; } /** * Display a profile field of type 'date' */ function views_handler_field_profile_date($fieldinfo, $fielddata, $value, $data) { $format = substr(variable_get('date_format_short', 'm/d/Y - H:i'), 0, 5); // Note: Avoid PHP's date() because it does not handle dates before // 1970 on Windows. This would make the date field useless for e.g. // birthdays. $value = unserialize($value); $replace = array('d' => sprintf('%02d', $value['day']), 'j' => $value['day'], 'm' => sprintf('%02d', $value['month']), 'M' => map_month($value['month']), 'Y' => $value['year'], 'H:i' => null, 'g:ia' => null); return strtr($format, $replace); } /* FILTER LIST METHODS */ function views_handler_filter_profile_selection($op, $filter) { $options = array(); foreach ( explode("\r", check_plain($filter['options'])) as $option) { $options[trim($option)] = trim($option); } return $options; } /* FILTER HANDLER FUNCTIONS */ /** * Provide distince filter for user object. Note: this replaces the node * distinct field and hence donflicts with it. */ function views_handler_filter_profile_distinct($op, $filter, $filterinfo, &$query) { $field = 'users.uid'; $query->fields[0] = "DISTINCT($field)"; $query->count_field = "DISTINCT($field)"; } /** * Handle a profile date fild. * * The problem here is that profile date fields are stored as serialized data. * Doing any other operation that matching the date is difficult. * possibilities include: * 1.) hack profile.module to store date always with same number of digits, * then user mysql STR_TO_DATE() function. * 2.) Fetch the date here, unserialize, filter out users that match criteria */ function views_handler_filter_profile_date($op, $filter, $filterinfo, &$query) { // Approach 2: // - read out date, unserialize // - compare to input date // - filter out matching users: WHERE users.uid IN(match1, match2, match3) if( empty($filter['value']) ) return; // CAREFUL! this may result in negative timestamp... if( is_array($filter['value']) ){ // custom selection boxes for date entry were used $value = mktime(0, 0, 0, $filter['value']['month'], $filter['value']['day'], $filter['value']['year']); } else { // compatibility with old method of entering dates in a textfield $value = $filter['value'] == 'now' ? time() : strtotime($filter['value']); } $users = array(); $results = db_query("SELECT uid, value FROM {profile_values} WHERE fid = %d", $filterinfo['fid']); while ($profile = db_fetch_object($results)) { $date = unserialize($profile->value); // Epoch problem again... $time = mktime(0, 0, 0, $date['month'], $date['day'], $date['year']); switch($filter['operator']){ case '>': if($time > $value) $users[] = $profile->uid; break; case '>=': if($time >= $value) $users[] = $profile->uid; break; case '=': if($time == $value) $users[] = $profile->uid; break; case '!=': if($time != $value) $users[] = $profile->uid; break; case '<=': if($time <= $value) $users[] = $profile->uid; break; case '<': if($time < $value) $users[] = $profile->uid; break; } } if( empty($users) ) $users[] = 'NULL'; // TODO: make this owrk for date entry into textfield if( checkdate($filter['value']['month'], $filter['value']['day'], $filter['value']['year']) ){ $query->ensure_table('users'); $query->add_where('users.uid IN(' . implode(', ', $users) .')'); } } /** * Custom filter for andor operator for serialized profile fields. * Note: This sunstring matching method may not be the most elegant method, * yet working, and anyone is free to point out a better approach to me.. */ function views_handler_filter_profile_andor($op, $filter, $filterinfo, &$query) { if( empty($filter['value']) ) return; switch ($op) { case 'handler': $table = $filterinfo['table']; $column = $filterinfo['field']; if (empty($column)) { $fieldbits = explode('.', $filter['field']); $column = $fieldbits[1]; } $field = "$table.$column"; $query->ensure_table($table); $where = array(); $args = array(); $operator = ($filter['operator'] == 'NOR') ? 'NOT LIKE' : 'LIKE'; // for 'force single' convert to array if( !is_array($filter['value']) ) $filter['value'] = array($filter['value']); foreach($filter['value'] as $value){ //$where[] = "%s $operator '%%\"%s\"%%'"; // use this line with modified version of profile.module $where[] = "%s $operator '%s'"; // use this line with original version of profile.module $args[] = $field; $args[] = $value; } $operator = ($filter['operator'] == 'NOR') ? 'AND' : $filter['operator']; $where = implode(" $operator ", $where); $query->add_where("$where", $args); break; } } /** * Drupal builtin date type does not allow to not have a * value, hence build custom date field here */ function views_handler_filter_profile_date_value_form() { $form['#tree'] = true; $form['day'] = array( '#prefix' => '