This is a duplicate of http://drupal.org/node/61073, however that was filed under Drupal 4.6.x.

Basically, I have a Profile date field (birthdate) that's optional, but when a user is on their My Account edit page, the date fields don't have any "null" option. Therefore, they are either forced to pick a date, or leave it as is (which I believe is pre-populated as the current date). Is there any way to include null options for the month, day, and year ("--" or blanks) if the setting is "optional" and set those as the default values?

Comments

pnlnl’s picture

and the only thing that i was able to do was to seperate the dates fields, not a solution but at least it works

deverman’s picture

I have the same problem with many of my required fields. I solved the solution doing something like this inside form_alter after checking the formid is "user_register" so that the user is forced to choose and cannot accept the default:

if(isset($form['Personal Information']['profile_sex']['#options']))
{
$option=array();
$option[""]="--";
$option=array_merge($option,$form['Personal Information']['profile_sex']['#options']);
$form['Personal Information']['profile_sex']['#options']=$option;
}

I'm not that sure how to proceed with the birthday field because it is NULL by default but the field shows up with the current date using a date selector pop up menu.

BTW, I am also using the Birthday's module.

tj2653’s picture

Thanks deverman. Perhaps it's possible to use similar code to that, and then default each box to "--" instead?

ekrispin’s picture

It seems that profile_validate_profile is not invoked in registration (only when editing the profile) so the validation is not enforced. See my issue at http://drupal.org/node/165390

graemec’s picture

I was experiencing the same issue, but I was able to fix it with the following steps... I'm still testing this & I'm not sure it's the best solution, but it seems to work. It works for required and non-required birthdate fields, but I have not tested it on other date fields.

Note: I'm currently using Drupal 5.2

My Solution
-----------
The profile.module uses the form.inc for handling the form. I modified the form.inc file as such:

1) Open form.inc
2) Locate the function expand_date($element)
3) On approximately Line 1194, fix the $options to include a blank option

...
foreach ($order as $type) {
switch ($type) {
case 'day':
$options = array('') + drupal_map_assoc(range(1, 31));
break;
case 'month':
$options = array('') + drupal_map_assoc(range(1, 12), 'map_month');
break;
case 'year':
$options = array('') + drupal_map_assoc(range(1900, 2050));
break;
}
...
}
...

4) Locate function date_validate($form), Approximately Line 1222

5) Modify the function to ignore the date field validation if the field is not required. For instance:

...
function date_validate($form) {
if(!$form['#required'] && empty($form['#value']['month']) && empty($form['#value']['day']) && empty($form['#value']['year'])) return;
if (!checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) {
form_error($form, t('The specified date is invalid.'));
}
}
...

graemec’s picture

Also, in the expand_date function, modify the default value... here, I just override the default value with blank defaults...I kept the original incase I need to rollback the change.

if (empty($element['#value'])) {
$element['#value'] = array('day' => format_date(time(), 'custom', 'j'),
'month' => format_date(time(), 'custom', 'n'),
'year' => format_date(time(), 'custom', 'Y'));
$element['#value'] = array('day' => '',
'month' => '',
'year' => '');
}

cozzi’s picture

I just implemented a profile field which I quickly noticed that the profile date field default value could not be set to empty.

I was amazed to see that you documented a fix just a few days prior (my profiles would have been quite messy had I not noticed this (and it would have taken me forever to write the patch :-)

I wonder how people lived with this for so long?

It is possible to have this built directly into core (I realize D5 is probably frozen, but how about 6? Who do we ask about such things?

queenielow’s picture

Finally i see this fix.. Yay!

Sadly, just need to hack the core module.. Same as You cozzi, i hope they do fix this in new drupal version.. I think drupal 6 they had fix it, but not so sure.

This is really a headache, i've been trying to use different solutions to get this done without hacking the core, but looks like , i have to now.

brad.bulger’s picture

where i just ran into it.

either the date defaults to today's date - not real appropriate for an unrequired birthday field...
or you choose between a PHP error and a validation error

editing includes/form.inc is troublesome because that will let an empty date go *everywhere*, and i don't doubt that there are modules that are counting on the current behavior

T-34@drupal.ru’s picture

Thanks graemec.

One more thing should be fixed - if to save blank options, in a profile date 00.00.0 is displayed. It is desirable that in that case date in a profile was not shown

quotesbro’s picture

profile.module:

function profile_view_field($user, $field) {

...

         $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);

=>

function profile_view_field($user, $field) {

...

        if($value['day']) {
         $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);} else return 0;
Alaska’s picture

Is there a suggested fix to add a 'phone' field? Noticed that the validation checks for the user/register page are being done in the user.module.

mmilano’s picture

In the case that the field is required, but no values are selected, checkdate() throws a nasty error. I added checks for each value before checkdate() was run to avoid this.

if (!$form['#value']['month'] || !$form['#value']['day'] || !$form['#value']['year'] || !checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) {
form_error($form, t('The specified date is invalid.'));
}

sagar ramgade’s picture

Can we use any hooks to achieve the default options for the profile date field ?

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

matason’s picture

Here's a non hack approach that may help some people, it's for Drupal 6, it assumes your category is "Personal" and your date field is "profile_dob" but these can be changed in the code to suit.

<?php

/**
 * Implementation of hook_form_alter().
 */
function custom_form_alter($form, &$form_state, $form_id) {
  if ($form_id == 'user_register' || $form_id == 'user_profile_form') {
    $form['Personal']['profile_dob']['#after_build'] = array('custom_date_after_build');
  }
}

/**
 * After build callback for date element.
 */
function custom_date_after_build($element) {
  $element['day']['#options'][0] = t('--');
  $element['month']['#options'][0] = t('--');
  $element['year']['#options'][0] = t('----');

  ksort($element['day']['#options']);
  ksort($element['month']['#options']);
  ksort($element['year']['#options']);

  if (empty($element['#default_value'])) {
    $element['day']['#value'] = 0;
    $element['month']['#value'] = 0;
    $element['year']['#value'] = 0;
  }

  $element['#element_validate'] = array('custom_date_validate');

  return $element;
}

/**
 * Custom validation for date element.
 */
function custom_date_validate($form) {
  if ($form['#value']['day'] == 0 && $form['#value']['month'] == 0 && $form['#value']['year'] == 0) {
    return;
  }

  if (!checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) {
    form_error($form, t('The specified date is invalid.'));
  }
}

/**
 * Implementation of hook_user().
 */
function custom_user($op, &$edit, &$user, $category = NULL) {
  if ($op == 'view') {
    if ($user->profile_dob['day'] == 0 && $user->profile_dob['month'] == 0 && $user->profile_dob['year'] == 0) {
      $user->content['Personal']['profile_dob']['#value'] = t('None given');
    }
  }
}
hoporr’s picture

Matason: this is a very clean solution.

As an option to setting the value to 'None given' in hook_user, it is also possible to simply unset the entry. That way, the field will never be shown at all.
unset ($account->content['Basic Info']['profile_birthdate']);

I also noticed that if your profile has "categories" (the form has MENU_LOCAL_TASKS or tabs) like "Basic Info," "Contact Info", then the #after_build callback gets called every time you open any edit-page for that form, even for those tabs that do not have the birthday fields. At least in my case, this had an unwanted side effect. For some reason, the string '000' was written below the page title, which apparently was caused by the assignment of the default values (three zeros) for any local-task that does not have this date fields.

The way to get around this is easy; you simply have to check if the current form also displays the right category or MENU_LOCAL_TASK in the hook_form_alter. There may be several ways to do this. I simply check if the passed in form has an array entry set with the name of the category/local-task that contains the birthday, like this:
if ( $form_id == 'user_profile_form' && isset ( $form['Basic Info'])) {...