/** * {@inheritdoc} */ public function renderMoreLink() { if ($this->isMoreEnabled() && ($this->useMoreAlways() || !empty($this->view->pager) && $this->view->pager->hasMoreRecords())) { // If the user has supplied a custom "More" link path, replace any // argument tokens and use that for the URL. if ($this->getOption('link_display') == 'custom_url' && ($override_path = $this->getOption('link_url'))) { $tokens = $this->getArgumentsTokens(); $path = $this->viewsTokenReplace($override_path, $tokens); // @todo Views should expect and store a leading /. See: // https://www.drupal.org/node/2423913 $url = Url::fromUserInput('/' . $path); } else { $url = $this->view->getUrl(NULL, $this->display['id']); } // If a URL is available (either from the display or a custom path), // render the "More" link. if ($url) { $url_options = array(); if (!empty($this->view->exposed_raw_input)) { $url_options['query'] = $this->view->exposed_raw_input; } $url->setOptions($url_options); return array('#type' => 'more_link', '#url' => $url, '#title' => $this->useMoreText(), '#view' => $this->view); } } }
/** * @covers ::getUrl */ public function testGetUrlWithPlaceholdersAndWithoutArgsAndExceptionValue() { $this->displayHandler->expects($this->any())->method('getRoutedDisplay')->willReturn($this->displayHandler); $this->displayHandlers->expects($this->any())->method('get')->willReturn($this->displayHandler); $this->displayHandler->expects($this->any())->method('getUrlInfo')->willReturn(Url::fromRoute('views.test.page_1')); $this->displayHandler->expects($this->any())->method('getPath')->willReturn('test-path/%/%'); $route = new Route('/test-path/{arg_0}/{arg_1}'); $this->routeProvider->expects($this->any())->method('getRouteByName')->with('views.test.page_1')->willReturn($route); $argument_handler = $this->getMockBuilder('Drupal\\views\\Plugin\\views\\argument\\ArgumentPluginBase')->disableOriginalConstructor()->getMock(); $argument_handler->options['exception']['value'] = 'exception_0'; $this->executable->argument['key_1'] = $argument_handler; $argument_handler = $this->getMockBuilder('Drupal\\views\\Plugin\\views\\argument\\ArgumentPluginBase')->disableOriginalConstructor()->getMock(); $argument_handler->options['exception']['value'] = 'exception_1'; $this->executable->argument['key_2'] = $argument_handler; $this->assertEquals(Url::fromRoute('views.test.page_1', ['arg_0' => 'exception_0', 'arg_1' => 'exception_1']), $this->executable->getUrl()); }
/** * Render the 'more' link */ public function renderMoreLink() { if ($this->isMoreEnabled() && ($this->useMoreAlways() || !empty($this->view->pager) && $this->view->pager->hasMoreRecords())) { $path = $this->getPath(); if ($this->getOption('link_display') == 'custom_url' && ($override_path = $this->getOption('link_url'))) { $tokens = $this->getArgumentsTokens(); $path = strtr($override_path, $tokens); } if ($path) { if (empty($override_path)) { $path = $this->view->getUrl(NULL, $path); } $url_options = array(); if (!empty($this->view->exposed_raw_input)) { $url_options['query'] = $this->view->exposed_raw_input; } $theme = $this->view->buildThemeFunctions('views_more'); $path = check_url(url($path, $url_options)); return array('#theme' => $theme, '#more_url' => $path, '#link_text' => String::checkPlain($this->useMoreText()), '#view' => $this->view); } } }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, ViewExecutable $view = NULL, $output = []) { if (!($step = $form_state->get('step'))) { $step = 'views_form_views_form'; $form_state->set('step', $step); } $form_state->set(['step_controller', 'views_form_views_form'], 'Drupal\\views\\Form\\ViewsFormMainForm'); // Cache the built form to prevent it from being rebuilt prior to validation // and submission, which could lead to data being processed incorrectly, // because the views rows (and thus, the form elements as well) have changed // in the meantime. $form_state->setCached(); $form = array(); $query = $this->requestStack->getCurrentRequest()->query->all(); $query = UrlHelper::filterQueryParameters($query, array(), ''); $options = array('query' => $query); $form['#action'] = $view->hasUrl() ? $view->getUrl()->setOptions($options)->toString() : Url::fromRoute('<current>')->setOptions($options)->toString(); // Tell the preprocessor whether it should hide the header, footer, pager... $form['show_view_elements'] = array('#type' => 'value', '#value' => $step == 'views_form_views_form' ? TRUE : FALSE); $form_object = $this->getFormObject($form_state); $form += $form_object->buildForm($form, $form_state, $view, $output); return $form; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, ViewExecutable $view = NULL, $output = []) { if (!($step = $form_state->get('step'))) { $step = 'views_form_views_form'; $form_state->set('step', $step); } $form_state->set(['step_controller', 'views_form_views_form'], 'Drupal\\views\\Form\\ViewsFormMainForm'); // Add the base form ID. $form_state->addBuildInfo('base_form_id', $this->getBaseFormId()); $form = array(); $query = $this->requestStack->getCurrentRequest()->query->all(); $query = UrlHelper::filterQueryParameters($query, array(), ''); $options = array('query' => $query); $form['#action'] = $view->hasUrl() ? $view->getUrl()->setOptions($options)->toString() : Url::fromRoute('<current>')->setOptions($options)->toString(); // Tell the preprocessor whether it should hide the header, footer, pager, // etc. $form['show_view_elements'] = array('#type' => 'value', '#value' => $step == 'views_form_views_form' ? TRUE : FALSE); $form_object = $this->getFormObject($form_state); $form += $form_object->buildForm($form, $form_state, $view, $output); return $form; }
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 = \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()); $output = ''; $errors = $this->executable->validate(); $this->executable->destroy(); if (empty($errors)) { $this->ajax = TRUE; $this->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', '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('entity.view.preview_form'); 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('entity.view.preview_form'); 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(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 = '<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(array('data' => array('#type' => 'inline_template', '#template' => "<strong>{% trans 'Other queries' %}</strong>")), SafeMarkup::set('<pre>' . $queries . '</pre>')); } } if ($show_info) { $rows['query'][] = array(array('data' => array('#type' => 'inline_template', '#template' => "<strong>{% trans 'Title' %}</strong>")), Xss::filterAdmin($this->executable->getTitle())); if (isset($path)) { $path = _l($path, $path); } else { $path = t('This display has no path.'); } $rows['query'][] = array(SafeMarkup::set('<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->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(SafeMarkup::set('<strong>' . t('Query') . '</strong>'), t('No query was run'))); } else { $rows['statistics'] = array(array(SafeMarkup::set('<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. $table = array('#type' => 'table', '#prefix' => '<div class="views-query-info">', '#suffix' => '</div>'); if ($show_location === 'above' || $show_location === 'below') { if ($combined) { $table['#rows'] = array_merge($rows['query'], $rows['statistics']); } else { $table['#rows'] = $rows['query']; } } elseif ($show_stats === 'above' || $show_stats === 'below') { $table['#rows'] = $rows['statistics']; } if ($show_location === 'above' || $show_stats === 'above') { $output .= drupal_render($table) . $preview; } elseif ($show_location === 'below' || $show_stats === 'below') { $output .= $preview . drupal_render($table); } _current_path($old_q); return $output; }
/** * {@inheritdoc} */ public function attachTo(ViewExecutable $clone, $display_id, array &$build) { $displays = $this->getOption('displays'); if (empty($displays[$display_id])) { return; } // Defer to the feed style; it may put in meta information, and/or // attach a feed icon. $clone->setArguments($this->view->args); $clone->setDisplay($this->display['id']); $clone->buildTitle(); if ($plugin = $clone->display_handler->getPlugin('style')) { $plugin->attachTo($build, $display_id, $clone->getUrl(), $clone->getTitle()); foreach ($clone->feedIcons as $feed_icon) { $this->view->feedIcons[] = $feed_icon; } } // Clean up. $clone->destroy(); unset($clone); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, ViewExecutable $view = NULL, $output = NULL) { $form_state['step'] = isset($form_state['step']) ? $form_state['step'] : 'views_form_views_form'; $form_state['step_controller']['views_form_views_form'] = 'Drupal\\views\\Form\\ViewsFormMainForm'; // Cache the built form to prevent it from being rebuilt prior to validation // and submission, which could lead to data being processed incorrectly, // because the views rows (and thus, the form elements as well) have changed // in the meantime. $form_state['cache'] = TRUE; $form = array(); $query = $this->requestStack->getCurrentRequest()->query->all(); $query = UrlHelper::filterQueryParameters($query, array(), ''); $form['#action'] = $this->urlGenerator->generateFromPath($view->getUrl(), array('query' => $query)); // Tell the preprocessor whether it should hide the header, footer, pager... $form['show_view_elements'] = array('#type' => 'value', '#value' => $form_state['step'] == 'views_form_views_form' ? TRUE : FALSE); $form_object = $this->getFormObject($form_state); $form += $form_object->buildForm($form, $form_state, $view, $output); return $form; }