I had a problem where I need to filter blog posts by created date, but the date field in Views would only show a range e.g. -10 years to 0 years.
The problem with this is that would show years where their were no blog posts e.g. lets say there were no posts in 2007, you'd still have it as an option.
The solution to filter out unneeded years is as follows:
- In the exposed filter form there will be a field for date e.g.
$form['date_value']
. It should have a processing callback, in my case it was$form['date_value']['value']['#process'][0] = 'date_select_element_process'
. - Make an alter hook on the callback e.g.
mymodule_date_select_process_alter(&$element, $form_state, $context)
- Query your nodes with
EntityFieldQuery()
to figure out which years are in use by your existing nodes - Filter your list of dates accordingly e.g.
unset($element['year']['options'][2007]);
Here's an example implementation
/**
* Implements hook_date_select_process_alter().
*/
function mymodule_date_select_process_alter(&$element, $form_state, $context) {
if (!empty($context['form']['#id'])) {
// Check to ensure we're modifying the correct exposed form
if ($context['form']['#id'] == "views-exposed-form-blog-page-1") {
// Query the blog nodes to see which dates we have
$field_id = 'field_date';
$query = new EntityFieldQuery();
$results = $query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'blog')
->fieldCondition($field_id, 'value', 'NULL', '!=')
->fieldOrderBy($field_id, 'value', 'ASC')
->execute();
// Attach the field values to the nodes
$nodes = $results['node'];
field_attach_load('node', $nodes, FIELD_LOAD_CURRENT, array('field_id' => $field_id));
// Build the options array based on the query results
$options = array('' => "-Year");
foreach ($nodes as $node) {
$value = $node->{"$field_id"}['und'][0]['value'];
$date = DateTime::createFromFormat("Y-m-d H:i:s", $value);
$year = $date->format("Y");
$options[$year] = $year;
}
// Add the filtered options back to the element
$element['year']['#options'] = $options;
}
}
}