431 lines
16 KiB
Plaintext
431 lines
16 KiB
Plaintext
<?php
|
|
|
|
/**
|
|
* @file
|
|
* Provide structure for the administrative interface to Views.
|
|
*/
|
|
|
|
use Drupal\views\ViewExecutable;
|
|
use Drupal\views\ViewStorageInterface;
|
|
use Drupal\views_ui\ViewUI;
|
|
use Drupal\views\Analyzer;
|
|
use Drupal\Core\Ajax\AjaxResponse;
|
|
use Drupal\Core\Ajax\ReplaceCommand;
|
|
|
|
/**
|
|
* Implements hook_help().
|
|
*/
|
|
function views_ui_help($path, $arg) {
|
|
|
|
switch ($path) {
|
|
case 'admin/help#views_ui':
|
|
$output = '';
|
|
$output .= '<h3>' . t('About') . '</h3>';
|
|
$output .= '<p>' . t('The Views UI module provides an interface for managing views for the <a href="@views">Views module</a>. For more information, see the <a href="@handbook">online documentation for the Views UI module</a>.', array('@views' => \Drupal::url('help.page', array('name' => 'views')), '@handbook' => 'https://drupal.org/documentation/modules/views_ui')) . '</p>';
|
|
$output .= '<h3>' . t('Uses') . '</h3>';
|
|
$output .= '<dl>';
|
|
$output .= '<dt>' . t('Creating and managing views.') . '</dt>';
|
|
$output .= '<dd>' . t('Views can be created from the <a href="@list">Views list page</a> by using the "Add new view" action. Existing views can be managed from the <a href="@list">Views list page</a> by locating the view in the "Enabled" or "Disabled" list and selecting the desired operation action, for example "Edit".', array('@list' => \Drupal::url('views_ui.list', array('name' => 'views_ui')))) . '</dd>';
|
|
$output .= '<dt>' . t('Enabling and disabling views.') . '<dt>';
|
|
$output .= '<dd>' . t('Views can be enabled or disabled from the <a href="@list">Views list page</a>. To enable a view, find the view within the "Disabled" list and select the "Enable" operation. To disable a view find the view within the "Enabled" list and select the "Disable" operation.', array('@list' => \Drupal::url('views_ui.list', array('name' => 'views_ui')))) . '</dd>';
|
|
$output .= '<dt>' . t('Exporting and importing views.') . '</dt>';
|
|
$output .= '<dd>' . t('Views can be exported and imported as configuration files by using the <a href="@config">Configuration Manager module</a>.', array('@config' => \Drupal::url('help.page', array('name' => 'config')))) . '</dd>';
|
|
$output .= '<dt>' . t('Theming views.') . '</dt>';
|
|
$output .= '<dd>' . t('The template files used by views can be overridden from a custom theme. When editing a view, you can see the templates that are used and alternatives for overriding them by clicking on the "Templates" link, found in the Advanced > Other section under "Output".') . '</dd>';
|
|
$output .= '</dl>';
|
|
return $output;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_menu().
|
|
*/
|
|
function views_ui_menu() {
|
|
$items = array();
|
|
|
|
// Top-level Views module pages (not tied to a particular View).
|
|
$items['admin/structure/views'] = array(
|
|
'title' => 'Views',
|
|
'description' => 'Manage customized lists of content.',
|
|
'route_name' => 'views_ui.list',
|
|
);
|
|
|
|
// A page in the Reports section to show usage of plugins in all views.
|
|
$items['admin/reports/views-plugins'] = array(
|
|
'title' => 'Views plugins',
|
|
'description' => 'Overview of plugins used in all views.',
|
|
'route_name' => 'views_ui.reports_plugins',
|
|
);
|
|
|
|
return $items;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_entity_info().
|
|
*/
|
|
function views_ui_entity_info(&$entity_info) {
|
|
/** @var $entity_info \Drupal\Core\Entity\EntityTypeInterface[] */
|
|
$entity_info['view']
|
|
->setForm('edit', 'Drupal\views_ui\ViewEditFormController')
|
|
->setForm('add', 'Drupal\views_ui\ViewAddFormController')
|
|
->setForm('preview', 'Drupal\views_ui\ViewPreviewFormController')
|
|
->setForm('clone', 'Drupal\views_ui\ViewCloneFormController')
|
|
->setForm('delete', 'Drupal\views_ui\ViewDeleteFormController')
|
|
->setForm('break_lock', 'Drupal\views_ui\Form\BreakLockForm')
|
|
->setList('Drupal\views_ui\ViewListController')
|
|
->setLinkTemplate('edit-form', 'views_ui.edit');
|
|
}
|
|
|
|
/**
|
|
* Implements hook_theme().
|
|
*/
|
|
function views_ui_theme() {
|
|
return array(
|
|
// edit a view
|
|
'views_ui_display_tab_setting' => array(
|
|
'variables' => array('description' => '', 'link' => '', 'settings_links' => array(), 'overridden' => FALSE, 'defaulted' => FALSE, 'description_separator' => TRUE, 'class' => array()),
|
|
'template' => 'views-ui-display-tab-setting',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
'views_ui_display_tab_bucket' => array(
|
|
'render element' => 'element',
|
|
'template' => 'views-ui-display-tab-bucket',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
'views_ui_rearrange_filter_form' => array(
|
|
'render element' => 'form',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
'views_ui_expose_filter_form' => array(
|
|
'render element' => 'form',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
|
|
// list views
|
|
'views_ui_view_info' => array(
|
|
'variables' => array('view' => NULL, 'displays' => NULL),
|
|
'file' => 'views_ui.theme.inc',
|
|
'template' => 'views-ui-view-info',
|
|
),
|
|
|
|
// Group of filters.
|
|
'views_ui_build_group_filter_form' => array(
|
|
'render element' => 'form',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
|
|
// On behalf of a plugin
|
|
'views_ui_style_plugin_table' => array(
|
|
'render element' => 'form',
|
|
'file' => 'views_ui.theme.inc',
|
|
'template' => 'views-ui-style-plugin-table',
|
|
),
|
|
|
|
// When previewing a view.
|
|
'views_ui_view_preview_section' => array(
|
|
'variables' => array('view' => NULL, 'section' => NULL, 'content' => NULL, 'links' => ''),
|
|
'file' => 'views_ui.theme.inc',
|
|
'template' => 'views-ui-view-preview-section',
|
|
),
|
|
|
|
// Generic container wrapper, to use instead of theme_container when an id
|
|
// is not desired.
|
|
'views_ui_container' => array(
|
|
'variables' => array('children' => NULL, 'attributes' => array()),
|
|
'template' => 'views-ui-container',
|
|
'file' => 'views_ui.theme.inc',
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implements hook_permission().
|
|
*/
|
|
function views_ui_permission() {
|
|
return array(
|
|
'administer views' => array(
|
|
'title' => t('Administer views'),
|
|
'description' => t('Access the views administration pages.'),
|
|
'restrict access' => TRUE,
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Implements hook_library_info().
|
|
*/
|
|
function views_ui_library_info() {
|
|
$libraries = array();
|
|
|
|
$path = drupal_get_path('module', 'views_ui') . '/js/';
|
|
|
|
$libraries['views_ui.admin'] = array(
|
|
'title' => 'Views UI ADMIN',
|
|
'version' => \Drupal::VERSION,
|
|
'js' => array(
|
|
$path . 'ajax.js' => array('group' => JS_DEFAULT),
|
|
$path . 'dialog.views.js' => array('group' => JS_DEFAULT),
|
|
$path . 'views-admin.js' => array('group' => JS_DEFAULT),
|
|
),
|
|
'dependencies' => array(
|
|
array('system', 'jquery'),
|
|
array('system', 'drupal'),
|
|
array('system', 'drupalSettings'),
|
|
array('system', 'jquery.once'),
|
|
array('system', 'jquery.form'),
|
|
array('system', 'drupal.ajax'),
|
|
array('views', 'views.ajax'),
|
|
),
|
|
);
|
|
|
|
$libraries['views_ui.listing'] = array(
|
|
'title' => 'Views UI listing',
|
|
'version' => Drupal::VERSION,
|
|
'js' => array(
|
|
$path . 'views_ui.listing.js' => array('group' => JS_DEFAULT),
|
|
),
|
|
);
|
|
|
|
return $libraries;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_preprocess_HOOK() for views templates.
|
|
*/
|
|
function views_ui_preprocess_views_view(&$variables) {
|
|
$view = $variables['view'];
|
|
if (!empty($view->live_preview) && \Drupal::moduleHandler()->moduleExists('contextual')) {
|
|
$view->setShowAdminLinks(FALSE);
|
|
foreach (array('title', 'header', 'exposed', 'rows', 'pager', 'more', 'footer', 'empty', 'attachment_after', 'attachment_before') as $section) {
|
|
if (!empty($variables[$section])) {
|
|
$variables[$section] = array(
|
|
'#theme' => 'views_ui_view_preview_section',
|
|
'#view' => $view,
|
|
'#section' => $section,
|
|
'#content' => $variables[$section],
|
|
'#theme_wrappers' => array('views_ui_container'),
|
|
'#attributes' => array('class' => 'contextual-region'),
|
|
);
|
|
$variables[$section] = $variables[$section];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns contextual links for each handler of a certain section.
|
|
*
|
|
* @TODO
|
|
* Bring in relationships
|
|
* Refactor this function to use much stuff of views_ui_edit_form_get_bucket.
|
|
*
|
|
* @param $title
|
|
* Add a bolded title of this section.
|
|
*/
|
|
function views_ui_view_preview_section_handler_links(ViewExecutable $view, $type, $title = FALSE) {
|
|
$display = $view->display_handler->display;
|
|
$handlers = $view->display_handler->getHandlers($type);
|
|
$links = array();
|
|
|
|
$types = ViewExecutable::viewsHandlerTypes();
|
|
if ($title) {
|
|
$links[$type . '-title'] = array(
|
|
'title' => $types[$type]['title'],
|
|
);
|
|
}
|
|
|
|
foreach ($handlers as $id => $handler) {
|
|
$field_name = $handler->adminLabel(TRUE);
|
|
$links[$type . '-edit-' . $id] = array(
|
|
'title' => t('Edit @section', array('@section' => $field_name)),
|
|
'href' => "admin/structure/views/nojs/config-item/{$view->storage->id()}/{$display['id']}/$type/$id",
|
|
'attributes' => array('class' => array('views-ajax-link')),
|
|
);
|
|
}
|
|
$links[$type . '-add'] = array(
|
|
'title' => t('Add new'),
|
|
'href' => "admin/structure/views/nojs/add-item/{$view->storage->id()}/{$display['id']}/$type",
|
|
'attributes' => array('class' => array('views-ajax-link')),
|
|
);
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Returns a link to editing a certain display setting.
|
|
*/
|
|
function views_ui_view_preview_section_display_category_links(ViewExecutable $view, $type, $title) {
|
|
$display = $view->display_handler->display;
|
|
$links = array(
|
|
$type . '-edit' => array(
|
|
'title' => t('Edit @section', array('@section' => $title)),
|
|
'href' => "admin/structure/views/nojs/display/{$view->storage->id()}/{$display['id']}/$type",
|
|
'attributes' => array('class' => array('views-ajax-link')),
|
|
),
|
|
);
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Returns all contextual links for the main content part of the view.
|
|
*/
|
|
function views_ui_view_preview_section_rows_links(ViewExecutable $view) {
|
|
$links = array();
|
|
$links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'filter', TRUE));
|
|
$links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'field', TRUE));
|
|
$links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'sort', TRUE));
|
|
$links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'argument', TRUE));
|
|
$links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'relationship', TRUE));
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_views_plugins_display_alter().
|
|
*/
|
|
function views_ui_views_plugins_display_alter(&$plugins) {
|
|
// Attach contextual links to each display plugin. The links will point to
|
|
// paths underneath "admin/structure/views/view/{$view->id()}" (i.e., paths
|
|
// for editing and performing other contextual actions on the view).
|
|
foreach ($plugins as &$display) {
|
|
$display['contextual links']['views_ui_edit'] = array(
|
|
'route_name' => 'views_ui.edit',
|
|
'route_parameters_names' => array('view' => 'id'),
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_contextual_links_view_alter().
|
|
*/
|
|
function views_ui_contextual_links_view_alter(&$element, $items) {
|
|
// Remove contextual links from being rendered, when so desired, such as
|
|
// within a View preview.
|
|
if (views_ui_contextual_links_suppress()) {
|
|
$element['#links'] = array();
|
|
}
|
|
// Append the display ID to the Views UI edit links, so that clicking on the
|
|
// contextual link takes you directly to the correct display tab on the edit
|
|
// screen.
|
|
elseif (!empty($element['#links']['views-uiedit'])) {
|
|
$display_id = $items['views_ui.edit']['metadata']['display_id'];
|
|
$element['#links']['views-uiedit']['route_parameters']['display_id'] = $display_id;
|
|
$element['#links']['views-uiedit']['route_name'] = 'views_ui.edit_display';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets a static variable for controlling whether contextual links are rendered.
|
|
*
|
|
* @see views_ui_contextual_links_view_alter()
|
|
*/
|
|
function views_ui_contextual_links_suppress($set = NULL) {
|
|
$suppress = &drupal_static(__FUNCTION__);
|
|
if (isset($set)) {
|
|
$suppress = $set;
|
|
}
|
|
return $suppress;
|
|
}
|
|
|
|
/**
|
|
* Increments the views_ui_contextual_links_suppress() static variable.
|
|
*
|
|
* When this function is added to the #pre_render of an element, and
|
|
* 'views_ui_contextual_links_suppress_pop' is added to the #post_render of the
|
|
* same element, then all contextual links within the element and its
|
|
* descendants are suppressed from being rendered. This is used, for example,
|
|
* during a View preview, when it is not desired for nodes in the Views result
|
|
* to have contextual links.
|
|
*
|
|
* @see views_ui_contextual_links_suppress_pop()
|
|
*/
|
|
function views_ui_contextual_links_suppress_push() {
|
|
views_ui_contextual_links_suppress(((int) views_ui_contextual_links_suppress())+1);
|
|
}
|
|
|
|
/**
|
|
* Decrements the views_ui_contextual_links_suppress() static variable.
|
|
*
|
|
* @see views_ui_contextual_links_suppress_push()
|
|
*/
|
|
function views_ui_contextual_links_suppress_pop() {
|
|
views_ui_contextual_links_suppress(((int) views_ui_contextual_links_suppress())-1);
|
|
}
|
|
|
|
/**
|
|
* This is part of a patch to address a jQueryUI bug. The bug is responsible
|
|
* for the inability to scroll a page when a modal dialog is active. If the content
|
|
* of the dialog extends beyond the bottom of the viewport, the user is only able
|
|
* to scroll with a mousewheel or up/down keyboard keys.
|
|
*
|
|
* @see http://bugs.jqueryui.com/ticket/4671
|
|
* @see https://bugs.webkit.org/show_bug.cgi?id=19033
|
|
* @see /js/jquery.ui.dialog.patch.js
|
|
* @see /js/jquery.ui.dialog.min.js
|
|
*
|
|
* The javascript patch overwrites the $.ui.dialog.overlay.events object to remove
|
|
* the mousedown, mouseup and click events from the list of events that are bound
|
|
* in $.ui.dialog.overlay.create.
|
|
*/
|
|
|
|
function views_ui_library_alter(&$libraries, $module) {
|
|
if ($module == 'system' && isset($libraries['jquery.ui.dialog'])) {
|
|
if (version_compare($libraries['jquery.ui.dialog']['version'], '1.7.2', '>=')) {
|
|
$libraries['jquery.ui.dialog']['js'][drupal_get_path('module', 'views') . '/js/jquery.ui.dialog.patch.js'] = array();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_views_analyze().
|
|
*
|
|
* This is the basic views analysis that checks for very minimal problems.
|
|
* There are other analysis tools in core specific sections, such as
|
|
* node.views.inc as well.
|
|
*/
|
|
function views_ui_views_analyze(ViewExecutable $view) {
|
|
$ret = array();
|
|
// Check for something other than the default display:
|
|
if (count($view->displayHandlers) < 2) {
|
|
$ret[] = Analyzer::formatMessage(t('This view has only a default display and therefore will not be placed anywhere on your site; perhaps you want to add a page or a block display.'), 'warning');
|
|
}
|
|
// You can give a page display the same path as an alias existing in the
|
|
// system, so the alias will not work anymore. Report this to the user,
|
|
// because he probably wanted something else.
|
|
foreach ($view->displayHandlers as $display) {
|
|
if (empty($display)) {
|
|
continue;
|
|
}
|
|
if ($display->hasPath() && $path = $display->getOption('path')) {
|
|
$normal_path = \Drupal::service('path.alias_manager.cached')->getSystemPath($path);
|
|
if ($path != $normal_path) {
|
|
$ret[] = Analyzer::formatMessage(t('You have configured display %display with a path which is an path alias as well. This might lead to unwanted effects so better use an internal path.', array('%display' => $display->display['display_title'])), 'warning');
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Truncate strings to a set length and provide a ... if they truncated.
|
|
*
|
|
* This is often used in the UI to ensure long strings fit.
|
|
*/
|
|
function views_ui_truncate($string, $length) {
|
|
if (drupal_strlen($string) > $length) {
|
|
$string = drupal_substr($string, 0, $length);
|
|
$string .= '...';
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Magic load function. Wrapper to load a view.
|
|
*/
|
|
function views_ui_load($name) {
|
|
return views_get_view($name);
|
|
}
|