public function ViewUI::renderPreview

File

drupal/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php, line 516
Definition of Drupal\views_ui\ViewUI.

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.
  $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;
}