quickedit.module 6.94 KB
Newer Older
1 2 3 4 5 6
<?php

/**
 * @file
 * Provides in-place content editing functionality for fields.
 *
7 8
 * The Quick Edit module makes content editable in-place. Rather than having to
 * visit a separate page to edit content, it may be edited in-place.
9 10 11 12 13 14
 *
 * Technically, this module adds classes and data- attributes to fields and
 * entities, enabling them for in-place editing.
 */

use Drupal\Core\Entity\EntityInterface;
15
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
16
use Drupal\Core\Routing\RouteMatchInterface;
17 18 19 20

/**
 * Implements hook_help().
 */
21
function quickedit_help($route_name, RouteMatchInterface $route_match) {
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  switch ($route_name) {
    case 'help.page.quickedit':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Quick Edit module allows users with the <a href="!quickedit_permission">Access in-place editing</a> and <a href="!contextual_permission">Use contextual links</a> permissions to edit field content without visiting a separate page. For more information, see the <a href="!handbook_url">online documentation for the Quick Edit module</a>.', array('!handbook_url' => 'https://drupal.org/documentation/modules/edit', '!quickedit_permission' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-quickedit')), '!contextual_permission' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-contextual')))) . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Editing content in-place') . '</dt>';
      $output .= '<dd>';
      $output .= '<p>' . t('To edit content in place, you need to activate quick edit mode for a content item. Activate quick edit mode by choosing Quick edit from the contextual links for an area displaying the content (see the <a href="!contextual">Contextual Links module help</a> for more information about how to use contextual links).', array('!contextual' => \Drupal::url('help.page', array('name' => 'contextual')))) . '</p>';
      $output .= '<p>' . t('Once quick edit mode is activated, you will be able to edit the individual fields of your content. In the default theme, with a JavaScript-enabled browser and a mouse, the output of different fields in your content is outlined in blue, a pop-up gives the field name as you hover over the field output, and clicking on a field activates the editor. Closing the pop-up window ends quick edit mode.') . '</p>';
      $output .= '</dd>';
      $output .= '</dl>';
      return $output;
  }
}

38 39 40 41

/**
 * Implements hook_permission().
 */
42
function quickedit_permission() {
43 44 45 46 47 48 49 50
  return array(
    'access in-place editing' => array(
      'title' => t('Access in-place editing'),
    ),
  );
}

/**
51
 * Implements hook_page_build().
52
 *
53 54
 * Adds the quickedit library to the page for any user who has the 'access
 * in-place editing' permission.
55
 */
56
function quickedit_page_build(&$page) {
57
  if (!\Drupal::currentUser()->hasPermission('access in-place editing')) {
58 59 60
    return;
  }

61
  // In-place editing is only supported on the front-end.
62
  if (\Drupal::service('router.admin_context')->isAdminRoute()) {
63 64 65
    return;
  }

66
  $page['#attached']['library'][] = 'quickedit/quickedit';
67 68 69
}

/**
70 71 72
 * Implements hook_library_alter().
 *
 * Includes additional stylesheets defined by the admin theme to allow it to
73
 * customize the Quick Edit toolbar appearance.
74 75 76 77 78 79 80 81
 *
 * An admin theme can specify CSS files to make the front-end administration
 * experience of in-place editing match the administration experience in the
 * back-end.
 *
 * The CSS files can be specified via the "edit_stylesheets" property in the
 * .info.yml file:
 * @code
82 83
 * quickedit_stylesheets:
 *   - css/quickedit.css
84 85 86 87 88
 * @endcode
 *
 * The library needs to be dynamically enhanced, because an admin theme normally
 * does not participate in the front-end.
 *
89 90 91 92
 * @param array &$library
 *   The JavaScript/CSS library that is being altered.
 * @param string $name
 *   The name of the library.
93 94 95
 * @param string $theme
 *   (optional) Internal use only. A base theme name for which to retrieve the
 *   'edit_stylesheets' property.
96
 *
97 98
 * @todo Remove this in favor of the 'stylesheets-additional' property proposed
 *   in https://drupal.org/node/1209958
99
 */
100 101
function quickedit_library_alter(array &$library, $name, $theme = NULL) {
  if ($name == 'quickedit/quickedit') {
102 103 104 105 106 107 108 109
    // Retrieve the admin theme.
    if (!isset($theme)) {
      $theme = Drupal::config('system.theme')->get('admin');
    }
    if ($theme && $theme_path = drupal_get_path('theme', $theme)) {
      $info = system_get_info('theme', $theme);
      // Recurse to process base theme(s) first.
      if (isset($info['base theme'])) {
110
        quickedit_library_alter($library, $name, $info['base theme']);
111
      }
112 113
      if (isset($info['quickedit_stylesheets']) && is_array($info['quickedit_stylesheets'])) {
        foreach ($info['quickedit_stylesheets'] as $path) {
114 115
          $library['css'][$theme_path . '/' . $path] = array(
            'group' => CSS_AGGREGATE_THEME,
116
            'weight' => CSS_THEME,
117 118 119
          );
        }
      }
120 121 122 123
    }
  }
}

124 125 126
/**
 * Implements hook_field_formatter_info_alter().
 *
127 128 129 130 131
 * Quick Edit extends the @FieldFormatter annotation with the following keys:
 * - quickedit: currently only contains one subkey 'editor' which indicates
 *   which in-place editor should be used. Possible values are 'form',
 *   'plain_text', 'disabled' or another in-place editor other than the ones
 *   Quick Edit module provides.
132
 */
133
function quickedit_field_formatter_info_alter(&$info) {
134
  foreach ($info as $key => $settings) {
135
    // Set in-place editor to 'form' if none is supplied.
136 137
    if (empty($settings['quickedit'])) {
      $info[$key]['quickedit'] = array('editor' => 'form');
138 139 140 141
    }
  }
}

142
/**
143
 * Implements hook_preprocess_HOOK() for field templates.
144
 */
145
function quickedit_preprocess_field(&$variables) {
146
  $element = $variables['element'];
147
  /** @var $entity \Drupal\Core\Entity\EntityInterface */
148
  $entity = $element['#object'];
149

150 151 152
  // Quick Edit module only supports view modes, not dynamically defined
  // "display options" (which \Drupal\Core\Field\FieldItemListInterface::view()
  // always names the "_custom" view mode).
153
  // @see \Drupal\Core\Field\FieldItemListInterface::view()
154 155 156 157 158
  // @see https://drupal.org/node/2120335
  if ($element['#view_mode'] === '_custom') {
    return;
  }

159 160
  // Fields that are not part of the entity (i.e. dynamically injected "pseudo
  // fields") and computed fields are not editable.
161
  $definition = $entity->getFieldDefinition($element['#field_name']);
162
  if ($definition && !$definition->isComputed()) {
163
    $variables['attributes']['data-quickedit-field-id'] = $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode'];
164
  }
165 166
}

167
/**
168
 * Implements hook_entity_view_alter().
169
 */
170 171
function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  $build['#attributes']['data-quickedit-entity-id'] = $entity->getEntityTypeId() . '/' . $entity->id();
172
}
173