protected function views_handler_filter_selective::get_oids in Views Selective Filters 7
Get list of options for current view, only at runtime.
1 call to views_handler_filter_selective::get_oids()
- views_handler_filter_selective::get_value_options in ./
views_handler_filter_selective.inc - Child classes should be used to override this function and set the 'value options', unless 'options callback' is defined as a valid function or static public method to generate these values.
File
- ./
views_handler_filter_selective.inc, line 265 - Views Filter Selective Handler Overrides.
Class
- views_handler_filter_selective
- Views filter handler for selective values.
Code
protected function get_oids() {
// Parameters that we will be using during the process.
$base_field = $this->definition['field_base'];
$ui_name = $this->options['ui_name'];
$signature = $this
->getSignature();
// Prevent same filters from being recalculated.
if (empty(self::$results[$signature])) {
// We don't want a badly configured selective filter
// to return thousands of possible values.
$max_items = (int) $this->options['selective_items_limit'];
// Clone the view (so it works while editting) and get all results.
$view_copy = $this->view
->clone_view();
if (!$view_copy) {
return NULL;
}
// Store a flag so that we can know from other places
// that this view is being used to obtain selective data.
$view_copy->selective_oids = TRUE;
// Store information about what filter is this view being used for.
$view_copy->selective_handler_signature = $signature;
// If this filter is configured to *not* continue to filter the options
// list as new exposed values are applied, make sure to explicitly set any
// exposed input values to null and remove contextual filters (args).
if (isset($this->options['selective_options_ignore_exposed_data']) && $this->options['selective_options_ignore_exposed_data'] === 1) {
if (!empty($this->view->exposed_input) && is_array($this->view->exposed_input)) {
$new_exposed_input = array();
foreach ($this->view->exposed_input as $key => $val) {
$new_exposed_input[$key] = NULL;
}
$view_copy
->set_exposed_input($new_exposed_input);
}
}
else {
$view_copy
->set_exposed_input($this->view->exposed_input);
}
// Transfer contextual information to cloned view.
$view_copy
->set_arguments($this->view->args);
// Mess up with the field used for distinct have thousands of elements.
// Limit result set to 100: anything above is not user friendly at all.
$view_copy
->set_items_per_page($max_items);
// Remove paging, and page number from context.
if (isset($_GET['items_per_page'])) {
$items_per_page = $_GET['items_per_page'];
unset($_GET['items_per_page']);
}
if (isset($_GET['page'])) {
$exposed_page = $_GET['page'];
unset($_GET['page']);
}
// Manipulate display + default: don't know if fields are overriden.
$display = $view_copy->display[$this->view->current_display];
$display_default = $view_copy->display['default'];
// Initialize the current display handler.
$display->handler = views_get_plugin('display', $view_copy->display[$this->view->current_display]->display_plugin);
$display_default->handler =& $display->handler;
// Remove any exposed form configuration. This showed up with BEF module!
unset($display->display_options['exposed_form']);
unset($display_default->display_options['exposed_form']);
// Also disable attachments.
$display->handler->definition['accept attachments'] = FALSE;
$display_default->handler->definition['accept attachments'] = FALSE;
// If we are using fields from default or current display.
if (isset($display->display_options['fields'])) {
$display_options_fields =& $display->display_options['fields'];
}
else {
$display_options_fields =& $display_default->display_options['fields'];
}
// Original implementation based field matching on ui_name matches
// so we need to preserve backwards compatibility.
$field_to_keep = $this->options['selective_display_field'];
if (empty($field_to_keep)) {
foreach ($display_options_fields as $key => $value) {
if (isset($value['ui_name']) && $value['ui_name'] == $ui_name) {
$field_to_keep = $key;
break;
}
}
}
// Remove all fields but the one used to display and aggregate.
foreach ($display_options_fields as $key => $value) {
if ($key != $field_to_keep) {
unset($display_options_fields[$key]);
}
else {
// If there is a group column on the field, remove it so
// Field Collections will work.
// https://www.drupal.org/node/2333065
unset($display_options_fields[$key]['group_column']);
}
}
// Check to see if the user remembered to add the field.
if (empty($display_options_fields)) {
drupal_set_message(t('Selective query filter must have corresponding field added to view with Administrative Name set to "@name" and Base Type "@type"', array(
'@name' => $ui_name,
'@type' => $base_field,
)), 'error');
return array();
}
// Get ID of field that will be used for rendering.
$display_field = reset($display_options_fields);
// Get field Id.
$display_field_id = $display_field['id'];
// Check that relationships are coherent between Field and Filter.
$no_display_field_relationship = empty($display_field['relationship']) || $display_field['relationship'] === 'none';
$no_filter_relationship = empty($this->options['relationship']) || $this->options['relationship'] === 'none';
$equal = $no_display_field_relationship === TRUE && $no_filter_relationship === TRUE || $display_field['relationship'] === $this->options['relationship'];
if (!$equal) {
drupal_set_message(t('Selective filter "@name": relationship of field and filter must match.', array(
'@name' => $ui_name,
'@type' => $base_field,
)), 'error');
return array();
}
// If main field is excluded from presentation, bring it back.
// Set group type for handler to populate database relationships in query.
$display_field['exclude'] = 0;
$display_field['group_type'] = 'group';
// Remove all sorting: sorts must be added to aggregate fields.
unset($display->display_options['sorts']);
unset($display_default->display_options['sorts']);
// Turn this into an aggregate query.
$display->display_options['group_by'] = 1;
$display->handler->options['group_by'] = 1;
$display_default->display_options['group_by'] = 1;
$display_default->handler->options['group_by'] = 1;
// Aggregate is incompatible with distinct and pure distinct.
// At least it does not make sense as it is implemented now.
unset($display_default->display_options['query']['options']['distinct']);
unset($display_default->display_options['query']['options']['pure_distinct']);
unset($display->display_options['query']['options']['distinct']);
unset($display->display_options['query']['options']['pure_distinct']);
// Make sure we are not using a pager to prevent unnecessary count(*)
// queries.
$display->display_options['pager'] = unserialize('a:2:{s:4:"type";s:4:"none";s:7:"options";a:1:{s:6:"offset";s:1:"0";}}');
$display_default->display_options['pager'] = unserialize('a:2:{s:4:"type";s:4:"none";s:7:"options";a:1:{s:6:"offset";s:1:"0";}}');
// Some style plugins can affect the built query, make sure
// we use a reliable field based style plugin.
$display->display_options['style_plugin'] = 'default';
$display->display_options['style_options'] = unserialize('a:4:{s:9:"row_class";s:0:"";s:17:"default_row_class";i:1;s:17:"row_class_special";i:1;s:11:"uses_fields";i:0;}');
$display->display_options['row_plugin'] = 'fields';
$display->display_options['row_options'] = unserialize('s:6:"fields";');
// Run View.
$view_copy
->execute($this->view->current_display);
// Restore context parameters for real View.
if (isset($items_per_page)) {
$_GET['items_per_page'] = $items_per_page;
}
if (isset($exposed_page)) {
$_GET['page'] = $exposed_page;
}
// Get Handler after execution.
$display_field_handler = $view_copy->field[$display_field_id];
// We show human-readable values when case.
if (method_exists($display_field_handler, 'get_value_options')) {
$display_field_handler
->get_value_options();
}
// Create array of objects for selector.
$oids = array();
$field_alias_original = isset($display_field_handler->aliases[$display_field_handler->real_field]) ? $display_field_handler->aliases[$display_field_handler->real_field] : $display_field_handler->table_alias . '_' . $display_field_handler->real_field;
// views_plugin_query_default::add_field() truncates aliases to 60
// characters.
$field_alias = substr($field_alias_original, 0, 60);
foreach ($view_copy->result as $index => $row) {
// $key = $display_field_handler->get_value($row) should be more robust
// but values are sometimes nested arrays, and we need scalar values
// for the filters.
$key = $display_field_handler
->get_value($row);
if (!is_scalar($key)) {
$key = $row->{$field_alias};
}
$value = strip_tags($view_copy
->render_field($display_field_id, $index));
$oids[$key] = empty($value) ? t('Empty (@key)', array(
'@key' => empty($key) ? json_encode($key) : $key,
)) : $value;
}
// Sort values.
$sort_option = $this->options['selective_display_sort'];
switch ($sort_option) {
case 'ASC':
asort($oids);
break;
case 'DESC':
arsort($oids);
break;
case 'KASC':
ksort($oids);
break;
case 'KDESC':
krsort($oids);
break;
case 'ORIG':
$oids = self::filterOriginalOptions($this
->getOriginalOptions(), array_keys($oids));
break;
case 'NONE':
break;
default:
asort($oids);
}
drupal_alter('views_filters_selective_sort', $oids, $this);
// If limit exceeded this field is not good for being "selective".
if (!empty($max_items) && count($oids) == $max_items) {
drupal_set_message(t('Selective filter "@field" has limited the amount of total results. Please, review you query configuration.', array(
'@field' => $ui_name,
)), 'warning');
}
self::$results[$signature] = $oids;
$view_copy
->destroy();
}
return self::$results[$signature];
}