public ViewUI::renderPreview($display_id, $args = array())
File
- core/modules/views_ui/src/ViewUI.php, line 515
Class
- ViewUI
- Stores UI related temporary settings.
Namespace
Drupal\views_ui
Code
public function renderPreview($display_id, $args = array()) {
// Save the current path so it can be restored before returning from this function.
$request_stack = \Drupal::requestStack();
$current_request = $request_stack->getCurrentRequest();
$executable = $this->getExecutable();
// Determine where the query and performance statistics should be output.
$config = \Drupal::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());
$errors = $executable->validate();
$executable->destroy();
if (empty($errors)) {
$this->ajax = TRUE;
$executable->live_preview = TRUE;
// AJAX happens via HTTP 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
// have some input in the query parameters, so we merge request() and
// query() to ensure we get it all.
$exposed_input = array_merge(\Drupal::request()->request->all(), \Drupal::request()->query->all());
foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER, 'ajax_page_state', 'form_id', 'form_build_id', 'form_token') as $key) {
if (isset($exposed_input[$key])) {
unset($exposed_input[$key]);
}
}
$executable->setExposedInput($exposed_input);
if (!$executable->setDisplay($display_id)) {
return [
'#markup' => t('Invalid display id @display', array('@display' => $display_id)),
];
}
$executable->setArguments($args);
// Store the current view URL for later use:
if ($executable->hasUrl() && $executable->display_handler->getOption('path')) {
$path = $executable->getUrl();
}
// Make view links come back to preview.
// Also override the current path so we get the pager, and make sure the
// Request object gets all of the proper values from $_SERVER.
$request = Request::createFromGlobals();
$request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'entity.view.preview_form');
$request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, \Drupal::service('router.route_provider')->getRouteByName('entity.view.preview_form'));
$request->attributes->set('view', $this->storage);
$request->attributes->set('display_id', $display_id);
$raw_parameters = new ParameterBag();
$raw_parameters->set('view', $this->id());
$raw_parameters->set('display_id', $display_id);
$request->attributes->set('_raw_variables', $raw_parameters);
foreach ($args as $key => $arg) {
$request->attributes->set('arg_' . $key, $arg);
}
$request_stack->push($request);
// 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('entity.view.preview_form');
if ($show_additional_queries) {
$this->startQueryCapture();
}
// Execute/get the view preview.
$preview = $executable->preview($display_id, $args);
if ($show_additional_queries) {
$this->endQueryCapture();
}
$this->render_time = Timer::stop('entity.view.preview_form') ['time'];
views_ui_contextual_links_suppress_pop();
// Prepare the query information and statistics to show either above or
// below the view preview.
// Initialise the empty rows arrays so we can safely merge them later.
$rows['query'] = [];
$rows['statistics'] = [];
if ($show_info || $show_query || $show_stats) {
// Get information from the preview for display.
if (!empty($executable->build_info['query'])) {
if ($show_query) {
$query_string = $executable->build_info['query'];
// Only the sql default class has a method getArguments.
$quoted = array();
if ($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(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'Query' %}</strong>",
),
),
array(
'data' => array(
'#type' => 'inline_template',
'#template' => '<pre>{{ query }}</pre>',
'#context' => array('query' => strtr($query_string, $quoted)),
),
),
);
if (!empty($this->additionalQueries)) {
$queries[] = array(
'#prefix' => '<strong>',
'#markup' => t('These queries were run during view rendering:'),
'#suffix' => '</strong>',
);
foreach ($this->additionalQueries as $query) {
$query_string = strtr($query['query'], $query['args']);
$queries[] = array(
'#prefix' => "\n",
'#markup' => t('[@time ms] @query', array('@time' => round($query['time'] * 100000, 1) / 100000.0, '@query' => $query_string)),
);
}
$rows['query'][] = array(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'Other queries' %}</strong>",
),
),
array(
'data' => array(
'#prefix' => '<pre>',
'queries' => $queries,
'#suffix' => '</pre>',
),
),
);
}
}
if ($show_info) {
$rows['query'][] = array(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'Title' %}</strong>",
),
),
Xss::filterAdmin($executable->getTitle()),
);
if (isset($path)) {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
$path = \Drupal::l($path->toString(), $path);
}
else {
$path = t('This display has no path.');
}
$rows['query'][] = array(
array(
'data' => array(
'#prefix' => '<strong>',
'#markup' => t('Path'),
'#suffix' => '</strong>',
),
),
array(
'data' => array(
'#markup' => $path,
),
)
);
}
if ($show_stats) {
$rows['statistics'][] = array(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'Query build time' %}</strong>",
),
),
t('@time ms', array('@time' => intval($executable->build_time * 100000) / 100)),
);
$rows['statistics'][] = array(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'Query execute time' %}</strong>",
),
),
t('@time ms', array('@time' => intval($executable->execute_time * 100000) / 100)),
);
$rows['statistics'][] = array(
array(
'data' => array(
'#type' => 'inline_template',
'#template' => "<strong>{% trans 'View render time' %}</strong>",
),
),
t('@time ms', array('@time' => intval($this->render_time * 100) / 100)),
);
}
\Drupal::moduleHandler()->alter('views_preview_info', $rows, $executable);
}
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(
'data' => array(
'#prefix' => '<strong>',
'#markup' => t('Query'),
'#suffix' => '</strong>',
),
),
array(
'data' => array(
'#markup' => t('No query was run'),
),
),
);
}
else {
$rows['statistics'][] = array(
array(
'data' => array(
'#prefix' => '<strong>',
'#markup' => t('Query'),
'#suffix' => '</strong>',
),
),
array(
'data' => array(
'#markup' => t('No query was run'),
),
),
);
}
}
}
}
else {
foreach ($errors as $display_errors) {
foreach ($display_errors as $error) {
drupal_set_message($error, 'error');
}
}
$preview = ['#markup' => t('Unable to preview due to validation errors.')];
}
// Assemble the preview, the query info, and the query statistics in the
// requested order.
$table = array(
'#type' => 'table',
'#prefix' => '<div class="views-query-info">',
'#suffix' => '</div>',
'#rows' => array_merge($rows['query'], $rows['statistics']),
);
if ($show_location == 'above') {
$output = [
'table' => $table,
'preview' => $preview,
];
}
else {
$output = [
'preview' => $preview,
'table' => $table,
];
}
// Ensure that we just remove an additional request we pushed earlier.
// This could happen if $errors was not empty.
if ($request_stack->getCurrentRequest() != $current_request) {
$request_stack->pop();
}
return $output;
}
Please login to continue.