public function renderPreview($display_id, $args = array()) {
// Save the current path so it can be restored before returning from this function.
$old_q = current_path();
// Determine where the query and performance statistics should be output.
$config = config('views.settings');
$show_query = $config
->get('ui.show.sql_query.enabled');
$show_info = $config
->get('ui.show.preview_information');
$show_location = $config
->get('ui.show.sql_query.where');
$show_stats = $config
->get('ui.show.performance_statistics');
if ($show_stats) {
$show_stats = $config
->get('ui.show.sql_query.where');
}
$combined = $show_query && $show_stats;
$rows = array(
'query' => array(),
'statistics' => array(),
);
$output = '';
$errors = $this->executable
->validate();
$this->executable
->destroy();
if (empty($errors)) {
$this->ajax = TRUE;
$this->executable->live_preview = TRUE;
$this->views_ui_context = TRUE;
// AJAX happens via $_POST but everything expects exposed data to
// be in GET. Copy stuff but remove ajax-framework specific keys.
// If we're clicking on links in a preview, though, we could actually
// still have some in $_GET, so we use $_REQUEST to ensure we get it all.
$exposed_input = drupal_container()
->get('request')->request
->all();
foreach (array(
'view_name',
'view_display_id',
'view_args',
'view_path',
'view_dom_id',
'pager_element',
'view_base_path',
'ajax_html_ids',
'ajax_page_state',
'form_id',
'form_build_id',
'form_token',
) as $key) {
if (isset($exposed_input[$key])) {
unset($exposed_input[$key]);
}
}
$this->executable
->setExposedInput($exposed_input);
if (!$this->executable
->setDisplay($display_id)) {
return t('Invalid display id @display', array(
'@display' => $display_id,
));
}
$this->executable
->setArguments($args);
// Store the current view URL for later use:
if ($this->executable->display_handler
->getOption('path')) {
$path = $this->executable
->getUrl();
}
// Make view links come back to preview.
$this->override_path = 'admin/structure/views/view/' . $this
->id() . '/preview/' . $display_id;
// Also override the current path so we get the pager.
$original_path = current_path();
$q = _current_path($this->override_path);
if ($args) {
$q .= '/' . implode('/', $args);
_current_path($q);
}
// Suppress contextual links of entities within the result set during a
// Preview.
// @todo We'll want to add contextual links specific to editing the View, so
// the suppression may need to be moved deeper into the Preview pipeline.
views_ui_contextual_links_suppress_push();
$show_additional_queries = $config
->get('ui.show.additional_queries');
timer_start('views_ui.preview');
if ($show_additional_queries) {
$this
->startQueryCapture();
}
// Execute/get the view preview.
$preview = $this->executable
->preview($display_id, $args);
$preview = drupal_render($preview);
if ($show_additional_queries) {
$this
->endQueryCapture();
}
$this->render_time = timer_stop('views_ui.preview');
views_ui_contextual_links_suppress_pop();
// Reset variables.
unset($this->override_path);
_current_path($original_path);
// Prepare the query information and statistics to show either above or
// below the view preview.
if ($show_info || $show_query || $show_stats) {
// Get information from the preview for display.
if (!empty($this->executable->build_info['query'])) {
if ($show_query) {
$query_string = $this->executable->build_info['query'];
// Only the sql default class has a method getArguments.
$quoted = array();
if ($this->executable->query instanceof Sql) {
$quoted = $query_string
->getArguments();
$connection = Database::getConnection();
foreach ($quoted as $key => $val) {
if (is_array($val)) {
$quoted[$key] = implode(', ', array_map(array(
$connection,
'quote',
), $val));
}
else {
$quoted[$key] = $connection
->quote($val);
}
}
}
$rows['query'][] = array(
'<strong>' . t('Query') . '</strong>',
'<pre>' . check_plain(strtr($query_string, $quoted)) . '</pre>',
);
if (!empty($this->additionalQueries)) {
$queries = '<strong>' . t('These queries were run during view rendering:') . '</strong>';
foreach ($this->additionalQueries as $query) {
if ($queries) {
$queries .= "\n";
}
$query_string = strtr($query['query'], $query['args']);
$queries .= t('[@time ms] @query', array(
'@time' => round($query['time'] * 100000, 1) / 100000.0,
'@query' => $query_string,
));
}
$rows['query'][] = array(
'<strong>' . t('Other queries') . '</strong>',
'<pre>' . $queries . '</pre>',
);
}
}
if ($show_info) {
$rows['query'][] = array(
'<strong>' . t('Title') . '</strong>',
filter_xss_admin($this->executable
->getTitle()),
);
if (isset($path)) {
$path = l($path, $path);
}
else {
$path = t('This display has no path.');
}
$rows['query'][] = array(
'<strong>' . t('Path') . '</strong>',
$path,
);
}
if ($show_stats) {
$rows['statistics'][] = array(
'<strong>' . t('Query build time') . '</strong>',
t('@time ms', array(
'@time' => intval($this->executable->build_time * 100000) / 100,
)),
);
$rows['statistics'][] = array(
'<strong>' . t('Query execute time') . '</strong>',
t('@time ms', array(
'@time' => intval($this->executable->execute_time * 100000) / 100,
)),
);
$rows['statistics'][] = array(
'<strong>' . t('View render time') . '</strong>',
t('@time ms', array(
'@time' => intval($this->executable->render_time * 100000) / 100,
)),
);
}
\Drupal::moduleHandler()
->alter('views_preview_info', $rows, $this);
}
else {
// No query was run. Display that information in place of either the
// query or the performance statistics, whichever comes first.
if ($combined || $show_location === 'above') {
$rows['query'] = array(
array(
'<strong>' . t('Query') . '</strong>',
t('No query was run'),
),
);
}
else {
$rows['statistics'] = array(
array(
'<strong>' . t('Query') . '</strong>',
t('No query was run'),
),
);
}
}
}
}
else {
foreach ($errors as $display_errors) {
foreach ($display_errors as $error) {
drupal_set_message($error, 'error');
}
}
$preview = t('Unable to preview due to validation errors.');
}
// Assemble the preview, the query info, and the query statistics in the
// requested order.
if ($show_location === 'above') {
if ($combined) {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => array_merge($rows['query'], $rows['statistics']),
)) . '</div>';
}
else {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => $rows['query'],
)) . '</div>';
}
}
elseif ($show_stats === 'above') {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => $rows['statistics'],
)) . '</div>';
}
$output .= $preview;
if ($show_location === 'below') {
if ($combined) {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => array_merge($rows['query'], $rows['statistics']),
)) . '</div>';
}
else {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => $rows['query'],
)) . '</div>';
}
}
elseif ($show_stats === 'below') {
$output .= '<div class="views-query-info">' . theme('table', array(
'rows' => $rows['statistics'],
)) . '</div>';
}
_current_path($old_q);
return $output;
}