Commit 960537ae authored by webchick's avatar webchick
Browse files

Issue #1904854 by tim.plunkett: Convert Views UI to routes.

parent 2f7db422
......@@ -67,6 +67,11 @@ function field_ui_menu() {
'type' => MENU_NORMAL_ITEM,
'file' => 'field_ui.admin.inc',
);
$items['admin/reports/fields/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
// Create tabs for all possible bundles.
foreach (entity_get_info() as $entity_type => $entity_info) {
......
......@@ -41,7 +41,7 @@ function testDefaultViews() {
// Enable the front page view, and make sure it is now visible on the main
// listing page.
$this->drupalGet('admin/structure/views/templates');
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Enable'), '/frontpage/');
$this->assertUrl('admin/structure/views');
$this->assertLinkByHref($edit_href);
......@@ -64,7 +64,7 @@ function testDefaultViews() {
// Save another view in the UI.
$this->drupalPost('admin/structure/views/nojs/display/archive/page_1/title', array(), t('Apply'));
$this->drupalPost('admin/structure/views/view/archive/page_1', array(), t('Save'));
$this->drupalPost('admin/structure/views/view/archive/edit/page_1', array(), t('Save'));
// Check there is an enable link. i.e. The view has not been enabled after
// editing.
......@@ -107,7 +107,7 @@ function testDefaultViews() {
// $this->assertNoLinkByHref($edit_href);
// The easiest way to verify it appears on the disabled views listing page
// is to try to click the "enable" link from there again.
$this->drupalGet('admin/structure/views/templates');
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Enable'), '/frontpage/');
$this->assertUrl('admin/structure/views');
$this->assertLinkByHref($edit_href);
......
......@@ -36,14 +36,13 @@ public function testDetails() {
$view_name = 'test_view';
$view = views_get_view($view_name);
$path = "admin/structure/views/nojs/edit-details/$view_name";
$edit = array(
'human_name' => $this->randomName(),
'tag' => $this->randomName(),
'description' => $this->randomName(30),
);
$this->drupalPost($path, $edit, t('Apply'));
$this->drupalPost("admin/structure/views/nojs/edit-details/$view_name/default", $edit, t('Apply'));
$this->drupalPost(NULL, array(), t('Save'));
$view = views_get_view($view_name);
......
......@@ -14,6 +14,13 @@
*/
class TagTest extends ViewUnitTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('views', 'views_ui');
public static function getInfo() {
return array(
'name' => 'Tag',
......@@ -38,12 +45,16 @@ public function testViewsUiAutocompleteTag() {
}
// Make sure just ten results are returns.
$result = views_ui_autocomplete_tag('autocomplete_tag_test');
$controller = $this->container->get('views_ui.controller');
$request = $this->container->get('request');
$request->query->set('q', 'autocomplete_tag_test');
$result = $controller->autocompleteTag($request);
$matches = (array) json_decode($result->getContent());
$this->assertEqual(count($matches), 10, 'Make sure the maximum amount of tag results is 10.');
// Make sure that matching by a certain prefix works.
$result = views_ui_autocomplete_tag('autocomplete_tag_test_even');
$request->query->set('q', 'autocomplete_tag_test_even');
$result = $controller->autocompleteTag($request);
$matches = (array) json_decode($result->getContent());
$this->assertEqual(count($matches), 8, 'Make sure that only a subset is returned.');
foreach ($matches as $tag) {
......@@ -51,7 +62,8 @@ public function testViewsUiAutocompleteTag() {
}
// Make sure an invalid result doesn't return anything.
$result = views_ui_autocomplete_tag($this->randomName());
$request->query->set('q', $this->randomName());
$result = $controller->autocompleteTag($request);
$matches = (array) json_decode($result->getContent());
$this->assertEqual(count($matches), 0, "Make sure an invalid tag doesn't return anything.");
}
......
......@@ -13,31 +13,13 @@
use Drupal\views\Ajax\DismissFormCommand;
use Drupal\Core\Ajax\AjaxResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Drupal\views_ui\ViewUI;
use Drupal\views_ui\ViewFormControllerBase;
use Drupal\views\Analyzer;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\wizard\WizardException;
/**
* Returns the results of the live preview.
*/
function views_ui_preview(ViewUI $view, $display_id) {
// Pass along any other arguments.
$args = func_get_args();
unset($args[0], $args[1]);
return $view->renderPreview($display_id, $args);
}
/**
* Page callback to add a new view.
*/
function views_ui_add_page() {
drupal_set_title(t('Add new view'));
$view = entity_create('view', array());
return entity_get_form($view, 'add');
}
/**
* Converts a form element in the add view wizard to be AJAX-enabled.
*
......@@ -321,22 +303,6 @@ function views_ui_edit_page(ViewUI $view, $display_id = NULL) {
return $build;
}
/**
* Page callback for rendering the preview form and the preview of the view.
*
* @param \Drupal\views_ui\ViewUI $view
* The view UI object to preview.
* @param string $display_id
* The display ID to preview.
*
* @return array
* The form array of the full preview form.
*/
function views_ui_build_preview(ViewUI $view, $display_id) {
$view->displayID = $display_id;
return entity_get_form($view, 'preview');
}
/**
* Move form elements into details for presentation purposes.
*
......@@ -569,7 +535,7 @@ function views_ui_ajax_form($js, $key, ViewUI $view, $display_id = '') {
$form = views_ui_ajax_forms($key);
if (empty($form)) {
return MENU_NOT_FOUND;
throw new NotFoundHttpException();
}
module_load_include('inc', 'views', 'includes/ajax');
......@@ -730,7 +696,11 @@ function views_ui_edit_details_form_submit($form, &$form_state) {
$view->set($key, $value);
}
}
$form_state['#page_title'] = views_ui_edit_page_title($view);
$bases = drupal_container()->get('views.views_data')->fetchBaseTables();
$form_state['#page_title'] = $view->getHumanName();
if (isset($bases[$view->get('base_table')])) {
$form_state['#page_title'] .= ' (' . $bases[$view->get('base_table')]['title'] . ')';
}
views_ui_cache_set($view);
}
......@@ -2076,29 +2046,6 @@ function views_ui_edit_display_form_change_theme($form, &$form_state) {
$form_state['rebuild'] = TRUE;
}
/**
* Page callback for views tag autocomplete
*/
function views_ui_autocomplete_tag($string = NULL) {
$matches = array();
if (!isset($string)) {
$string = drupal_container()->get('request')->query->get('q');
}
// get matches from default views:
$views = views_get_all_views();
foreach ($views as $view) {
$tag = $view->get('tag');
if ($tag && strpos($tag, $string) === 0) {
$matches[$tag] = $tag;
if (count($matches) >= 10) {
break;
}
}
}
return new JsonResponse($matches);
}
function _views_sort_types($a, $b) {
$a_group = drupal_strtolower($a['group']);
$b_group = drupal_strtolower($b['group']);
......@@ -2256,85 +2203,3 @@ function views_ui_form_button_was_clicked($element, &$form_state) {
}
return $element;
}
/**
* List all instances of fields on any views.
*
* Therefore it builds up a table of each field which is used in any view.
*
* @see field_ui_fields_list()
*/
function views_ui_field_list() {
$views = views_get_all_views();
$data = drupal_container()->get('views.views_data');
// Fetch all fieldapi fields which are used in views
// Therefore search in all views, displays and handler-types.
$fields = array();
$handler_types = ViewExecutable::viewsHandlerTypes();
foreach ($views as $view) {
$executable = $view->get('executable');
$executable->initDisplay();
foreach ($executable->displayHandlers as $display_id => $display) {
if ($executable->setDisplay($display_id)) {
foreach ($handler_types as $type => $info) {
foreach ($executable->getItems($type, $display_id) as $item) {
$table_data = $data->get($item['table']);
if (isset($table_data[$item['field']]) && isset($table_data[$item['field']][$type])
&& $field_data = $table_data[$item['field']][$type]) {
// The final check that we have a fieldapi field now.
if (isset($field_data['field_name'])) {
$fields[$field_data['field_name']][$view->id()] = $view->id();
}
}
}
}
}
}
}
$header = array(t('Field name'), t('Used in'));
$rows = array();
foreach ($fields as $field_name => $views) {
$rows[$field_name]['data'][0] = check_plain($field_name);
foreach ($views as $view) {
$rows[$field_name]['data'][1][] = l($view, "admin/structure/views/view/$view");
}
$rows[$field_name]['data'][1] = implode(', ', $rows[$field_name]['data'][1]);
}
// Sort rows by field name.
ksort($rows);
$output = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No fields have been used in views yet.'),
);
return $output;
}
/**
* Lists all plugins and what enabled Views use them.
*/
function views_ui_plugin_list() {
$rows = views_plugin_list();
foreach ($rows as &$row) {
// Link each view name to the view itself.
foreach ($row['views'] as $row_name => $view) {
$row['views'][$row_name] = l($view, "admin/structure/views/view/$view");
}
$row['views'] = implode(', ', $row['views']);
}
// Sort rows by field name.
ksort($rows);
return array(
'#theme' => 'table',
'#header' => array(t('Type'), t('Name'), t('Provided by'), t('Used in')),
'#rows' => $rows,
'#empty' => t('There are no enabled views.'),
);
}
<?php
/**
* @file
* Contains \Drupal\views_ui\Routing\ViewsUIController.
*/
namespace Drupal\views_ui\Routing;
use Drupal\views\ViewExecutable;
use Drupal\views\ViewStorageInterface;
use Drupal\views_ui\ViewUI;
use Drupal\views\ViewsDataCache;
use Drupal\user\TempStoreFactory;
use Drupal\Core\Entity\EntityManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
/**
* Returns responses for Views UI routes.
*/
class ViewsUIController {
/**
* Stores the Entity manager.
*
* @var \Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* Stores the Views data cache object.
*
* @var \Drupal\views\ViewsDataCache
*/
protected $viewsData;
/**
* Stores the user tempstore.
*
* @var \Drupal\user\TempStore
*/
protected $tempStore;
/**
* Constructs a new \Drupal\views_ui\Routing\ViewsUIController object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The Entity manager.
* @param \Drupal\views\ViewsDataCache views_data
* The Views data cache object.
* @param \Drupal\user\TempStoreFactory $temp_store_factory
* The factory for the temp store object.
*/
public function __construct(EntityManager $entity_manager, ViewsDataCache $views_data, TempStoreFactory $temp_store_factory) {
$this->entityManager = $entity_manager;
$this->viewsData = $views_data;
$this->tempStore = $temp_store_factory->get('views');
}
/**
* Lists all of the views.
*
* @return array
* The Views listing page.
*/
public function listing() {
return $this->entityManager->getListController('view')->render();
}
/**
* Returns the form to add a new view.
*
* @return array
* The Views add form.
*/
public function add() {
drupal_set_title(t('Add new view'));
$entity = $this->entityManager->getStorageController('view')->create(array());
return entity_get_form($entity, 'add');
}
/**
* Form builder for the admin display defaults page.
*
* @return array
* The Views basic settings form.
*/
public function settingsBasic() {
// @todo Remove the need for this.
module_load_include('inc', 'views_ui', 'admin');
return drupal_get_form('views_ui_admin_settings_basic');
}
/**
* Form builder for the advanced admin settings page.
*
* @return array
* The Views advanced settings form.
*/
public function settingsAdvanced() {
// @todo Remove the need for this.
module_load_include('inc', 'views_ui', 'admin');
return drupal_get_form('views_ui_admin_settings_advanced');
}
/**
* Lists all instances of fields on any views.
*
* @return array
* The Views fields report page.
*/
public function reportFields() {
$views = $this->entityManager->getStorageController('view')->load();
// Fetch all fieldapi fields which are used in views
// Therefore search in all views, displays and handler-types.
$fields = array();
$handler_types = ViewExecutable::viewsHandlerTypes();
foreach ($views as $view) {
$executable = $view->get('executable');
$executable->initDisplay();
foreach ($executable->displayHandlers as $display_id => $display) {
if ($executable->setDisplay($display_id)) {
foreach ($handler_types as $type => $info) {
foreach ($executable->getItems($type, $display_id) as $item) {
$table_data = $this->viewsData->get($item['table']);
if (isset($table_data[$item['field']]) && isset($table_data[$item['field']][$type])
&& $field_data = $table_data[$item['field']][$type]) {
// The final check that we have a fieldapi field now.
if (isset($field_data['field_name'])) {
$fields[$field_data['field_name']][$view->id()] = $view->id();
}
}
}
}
}
}
}
$header = array(t('Field name'), t('Used in'));
$rows = array();
foreach ($fields as $field_name => $views) {
$rows[$field_name]['data'][0] = check_plain($field_name);
foreach ($views as $view) {
$rows[$field_name]['data'][1][] = l($view, "admin/structure/views/view/$view");
}
$rows[$field_name]['data'][1] = implode(', ', $rows[$field_name]['data'][1]);
}
// Sort rows by field name.
ksort($rows);
$output = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No fields have been used in views yet.'),
);
return $output;
}
/**
* Lists all plugins and what enabled Views use them.
*
* @return array
* The Views plugins report page.
*/
public function reportPlugins() {
$rows = views_plugin_list();
foreach ($rows as &$row) {
// Link each view name to the view itself.
foreach ($row['views'] as $row_name => $view) {
$row['views'][$row_name] = l($view, "admin/structure/views/view/$view");
}
$row['views'] = implode(', ', $row['views']);
}
// Sort rows by field name.
ksort($rows);
return array(
'#theme' => 'table',
'#header' => array(t('Type'), t('Name'), t('Provided by'), t('Used in')),
'#rows' => $rows,
'#empty' => t('There are no enabled views.'),
);
}
/**
* Calls a method on a view and reloads the listing page.
*
* @param \Drupal\views\ViewStorageInterface $view
* The view being acted upon.
* @param string $op
* The operation to perform, e.g., 'enable' or 'disable'.
*
* @return \Drupal\Core\Ajax\AjaxResponse|\Symfony\Component\HttpFoundation\RedirectResponse
* Either returns a rebuilt listing page as an AJAX response, or redirects
* back to the listing page.
*/
public function ajaxOperation(ViewStorageInterface $view, $op, Request $request) {
// Perform the operation.
$view->$op()->save();
// If the request is via AJAX, return the rendered list as JSON.
if ($request->request->get('js')) {
$list = $this->entityManager->getListController('view')->render();
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand('#views-entity-list', drupal_render($list)));
return $response;
}
// Otherwise, redirect back to the page.
// @todo Remove url() wrapper once http://drupal.org/node/1668866 is in.
return new RedirectResponse(url('admin/structure/views', array('absolute' => TRUE)));
}
/**
* Returns the form to clone a view.
*
* @param \Drupal\views\ViewStorageInterface $view
* The view being cloned.
*
* @return array
* The Views clone form.
*/
public function cloneForm(ViewStorageInterface $view) {
drupal_set_title(t('Clone of @human_name', array('@human_name' => $view->getHumanName())));
return entity_get_form($view, 'clone');
}
/**
* Returns the form to delete a view.
*
* @param \Drupal\views\ViewStorageInterface $view
* The view being deleted.
*
* @return array
* The Views delete form.
*/
public function deleteForm(ViewStorageInterface $view) {
return drupal_get_form('views_ui_confirm_delete', $view);
}
/**
* Menu callback for Views tag autocompletion.
*
* Like other autocomplete functions, this function inspects the 'q' query
* parameter for the string to use to search for suggestions.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* A JSON response containing the autocomplete suggestions for Views tags.
*/
public function autocompleteTag(Request $request) {
$matches = array();
$string = $request->query->get('q');
// Get matches from default views.
$views = $this->entityManager->getStorageController('view')->load();
foreach ($views as $view) {
$tag = $view->get('tag');
if ($tag && strpos($tag, $string) === 0) {
$matches[$tag] = $tag;
if (count($matches) >= 10) {
break;
}
}
}
return new JsonResponse($matches);
}
/**
* Returns the form to edit a view.
*
* @param \Drupal\views\ViewStorageInterface $view
* The view being deleted.
* @param string|null $display_id
* (optional) The display ID being edited. Defaults to NULL, which will load
* the first available display.
*
* @return array
* An array containing the Views edit and preview forms.
*/
public function edit(ViewStorageInterface $view, $display_id = NULL) {
$view_ui = $this->getViewUI($view);
$name = $view_ui->getHumanName();
$data = $this->viewsData->get($view_ui->get('base_table'));
if (isset($data['table']['base']['title'])) {
$name .= ' (' . $data['table']['base']['title'] . ')';
}
drupal_set_title($name);
$view_ui->displayID = $display_id;
$build['edit'] = entity_get_form($view_ui, 'edit');
$build['preview'] = entity_get_form($view_ui, 'preview');
return $build;