View source
<?php
class views_field_view_handler_field_view extends views_handler_field {
public $child_arguments = array();
public $child_view_results = array();
public $child_view = false;
function option_definition() {
$options = parent::option_definition();
$options['view'] = array(
'default' => '',
);
$options['display'] = array(
'default' => 'default',
);
$options['arguments'] = array(
'default' => '',
);
$options['query_aggregation'] = array(
'default' => FALSE,
);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$options = drupal_map_assoc(array_keys(views_get_all_views()));
unset($options[$this->view->name]);
$form['view'] = array(
'#type' => 'select',
'#title' => t('View'),
'#default_value' => $this->options['view'],
'#options' => $options,
);
if ($this->options['view']) {
$view = views_get_view($this->options['view']);
$options = array();
foreach ($view->display as $name => $display) {
$options[$name] = $display->display_title;
}
$form['display'] = array(
'#title' => t('Display'),
'#type' => 'select',
'#default_value' => $this->options['display'],
'#options' => $options,
);
$form['arguments'] = array(
'#title' => t('Arguments'),
'#description' => t('Use a comma-seperated list of each argument which should be forwarded to the view') . $form['alter']['help']['#prefix'],
'#type' => 'textfield',
'#default_value' => $this->options['arguments'],
);
$form['query_aggregation'] = array(
'#title' => t('Aggregate queries'),
'#description' => t('Views Field View usually runs a separate query for each instance of this field on each row and that can mean a lot of queries. This option attempts to aggregate these queries into one query per instance of this field (regardless of how many rows are displayed). <strong>Currently child views must be configured to "display all values" if no argument is present and query aggregation is enabled.</strong>. This may only work on simple views, please test thoroughly.') . $form['alter']['help']['#prefix'],
'#type' => 'checkbox',
'#default_value' => $this->options['query_aggregation'],
);
if (views_api_version() == '3.0') {
$views_data = views_fetch_data($view->base_table);
if ($views_data['table']['base']['query class'] == 'views_query') {
$form['query_aggregation']['#disabled'] = TRUE;
}
}
}
$form['alter']['#access'] = FALSE;
}
function query() {
$this
->add_additional_fields();
}
function pre_render($values) {
if ($this->options['view'] && $this->options['query_aggregation']) {
$child_view_name = $this->options['view'];
$child_view_display = $this->options['display'];
foreach (explode(',', $this->options['arguments']) as $token) {
$argument = substr($token, 1, -1);
if (isset($this->view->field[$argument]->field_alias)) {
$field_alias = $this->view->field[$argument]->field_alias;
foreach ($values as $value) {
if (isset($value->{$field_alias})) {
$this->child_arguments[$field_alias]['argument_name'] = $argument;
$this->child_arguments[$field_alias]['values'][] = $value->{$field_alias};
}
}
}
}
if (count($this->child_arguments)) {
$this->child_view = views_get_view($child_view_name);
$child_view = $this->child_view;
$child_view
->access($child_view_display);
foreach ($child_view->display['default']->display_options['arguments'] as $argument_name => $argument_value) {
if (isset($child_view->display[$child_view_display]->display_options['arguments'][$argument_name])) {
$configured_arguments[$argument_name] = $child_view->display[$child_view_display]->display_options['arguments'][$argument_name];
}
else {
$configured_arguments[$argument_name] = $child_view->display['default']->display_options['arguments'][$argument_name];
}
}
$argument_ids = array();
foreach ($this->child_arguments as $child_argument_name => $child_argument) {
$configured_argument = array_shift($configured_arguments);
$argument_ids[$child_argument_name] = $child_view
->add_item($child_view_display, 'field', $configured_argument['table'], $configured_argument['field'], array(
'exclude' => TRUE,
));
if (isset($child_view->pager['items_per_page'])) {
$child_view->pager['items_per_page'] = 0;
}
$child_view
->build();
$sql = ' IN (';
$i = 0;
foreach ($child_argument['values'] as $argument) {
if ($i > 0) {
$sql .= ', ';
}
$i++;
if (is_numeric($argument)) {
$sql .= '%n';
}
else {
$sql .= "'%s'";
}
}
$sql .= ')';
$child_view->query
->add_where(0, $configured_argument['table'] . '.' . $configured_argument['field'] . $sql, $child_argument['values']);
}
$child_view->build_info['query'] = $child_view->query
->query();
$child_view->build_info['count_query'] = $child_view->query
->query(TRUE);
$child_view->build_info['query_args'] = $child_view->query
->get_where_args();
$child_view
->execute();
foreach ($argument_ids as $child_argument_name => $argument_id) {
$this->child_arguments[$child_argument_name]['child_view_field_alias'] = $child_view->field[$argument_id]->field_alias;
}
$results = $child_view->result;
foreach ($values as $value) {
$this->child_view_results[$value->{$this->view->base_field}] = array();
$child_view_result_row =& $this->child_view_results[$value->{$this->view->base_field}];
foreach ($results as $result) {
$matching_item = TRUE;
foreach ($this->child_arguments as $child_argument_field_alias => $child_argument) {
if (isset($value->{$child_argument_field_alias}) && $value->{$child_argument_field_alias} != $result->{$child_argument['child_view_field_alias']}) {
$matching_item = FALSE;
}
}
if ($matching_item) {
$child_view_result_row[] = $result;
}
}
if (isset($this->child_view->pager['items_per_page'])) {
$item_limit = $this->child_view->pager['items_per_page'];
if ($item_limit != 0) {
$results = array_chunk($results, $item_limit);
$offset = isset($this->child_view->pager['offset']) ? $this->child_view->pager['offset'] : 0;
$results = $results[$offset];
}
}
unset($child_view_result_row);
}
$this->child_view->built = TRUE;
$this->child_view->executed = TRUE;
}
}
}
function render($values) {
static $running = array();
if (empty($running[$this->options['view']][$this->options['display']]) || variable_get('views_field_view_evil', FALSE)) {
if ($this->options['view'] && !$this->options['query_aggregation']) {
$running[$this->options['view']][$this->options['display']] = TRUE;
$args = array();
$args[] = $this->options['view'];
$args[] = $this->options['display'];
if (!empty($this->options['arguments'])) {
foreach (explode(',', $this->options['arguments']) as $argument) {
$alter = array(
'text' => $argument,
);
$tokens = $this
->get_render_tokens($alter);
$value = $this
->render_altered($alter, $tokens);
$args[] = $value;
}
}
$output = call_user_func_array('views_embed_view', $args);
$running[$this->options['view']][$this->options['display']] = FALSE;
}
else {
if ($this->child_view && $this->options['view'] && $this->options['query_aggregation']) {
$running[$this->options['view']][$this->options['display']] = TRUE;
$child_view = $this->child_view;
$results = $this->child_view_results[$values->{$this->view->base_field}];
$child_view->result = $results;
if (isset($child_view->style_plugin->rendered_fields)) {
unset($child_view->style_plugin->rendered_fields);
}
$output = $child_view
->render();
$running[$this->options['view']][$this->options['display']] = FALSE;
}
}
}
else {
$output = t('Recursion, stop!');
}
return $output;
}
}