' . t('About') . ''; $output .= '

' . t('The Quick Edit module allows users with the Access in-place editing and Use contextual links permissions to edit field content without visiting a separate page. For more information, see the online documentation for the Quick Edit module.', [':handbook_url' => 'https://www.drupal.org/documentation/modules/edit', ':quickedit_permission' => \Drupal::url('user.admin_permissions', [], ['fragment' => 'module-quickedit']), ':contextual_permission' => \Drupal::url('user.admin_permissions', [], ['fragment' => 'module-contextual'])]) . '

'; $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Editing content in-place') . '
'; $output .= '
'; $output .= '

' . 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 Contextual Links module help for more information about how to use contextual links).', [':contextual' => \Drupal::url('help.page', ['name' => 'contextual'])]) . '

'; $output .= '

' . 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.') . '

'; $output .= '
'; $output .= '
'; return $output; } } /** * Implements hook_page_attachments(). * * Adds the quickedit library to the page for any user who has the 'access * in-place editing' permission. */ function quickedit_page_attachments(array &$page) { if (!\Drupal::currentUser()->hasPermission('access in-place editing')) { return; } // In-place editing is only supported on the front-end. if (\Drupal::service('router.admin_context')->isAdminRoute()) { return; } $page['#attached']['library'][] = 'quickedit/quickedit'; } /** * Implements hook_library_info_alter(). * * Includes additional stylesheets defined by the admin theme to allow it to * customize the Quick Edit toolbar appearance. * * 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 * quickedit_stylesheets: * - css/quickedit.css * @endcode */ function quickedit_library_info_alter(&$libraries, $extension) { if ($extension === 'quickedit' && isset($libraries['quickedit'])) { $theme = Drupal::config('system.theme')->get('admin'); // First let the base theme modify the library, then the actual theme. $alter_library = function (&$library, $theme) use (&$alter_library) { if (isset($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'])) { $alter_library($library, $info['base theme']); } if (isset($info['quickedit_stylesheets'])) { foreach ($info['quickedit_stylesheets'] as $path) { $library['css']['theme']['/' . $theme_path . '/' . $path] = []; } } } }; $alter_library($libraries['quickedit'], $theme); } } /** * Implements hook_field_formatter_info_alter(). * * 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. */ function quickedit_field_formatter_info_alter(&$info) { foreach ($info as $key => $settings) { // Set in-place editor to 'form' if none is supplied. if (empty($settings['quickedit'])) { $info[$key]['quickedit'] = ['editor' => 'form']; } } } /** * Implements hook_preprocess_HOOK() for the page title template. */ function quickedit_preprocess_page_title(&$variables) { $variables['#cache']['contexts'][] = 'user.permissions'; if (\Drupal::currentUser()->hasPermission('access in-place editing')) { $variables['title_attributes']['class'][] = 'js-quickedit-page-title'; } } /** * Implements hook_preprocess_HOOK() for field templates. */ function quickedit_preprocess_field(&$variables) { $variables['#cache']['contexts'][] = 'user.permissions'; $element = $variables['element']; /** @var $entity \Drupal\Core\Entity\EntityInterface */ $entity = $element['#object']; if (!\Drupal::currentUser()->hasPermission('access in-place editing') || !_quickedit_entity_is_latest_revision($entity)) { return; } // Quick Edit module only supports view modes, not dynamically defined // "display options" (which \Drupal\Core\Field\FieldItemListInterface::view() // always names the "_custom" view mode). // @see \Drupal\Core\Field\FieldItemListInterface::view() // @see https://www.drupal.org/node/2120335 if ($element['#view_mode'] === '_custom') { return; } // Fields that are computed fields are not editable. $definition = $entity->getFieldDefinition($element['#field_name']); if (!$definition->isComputed()) { $variables['attributes']['data-quickedit-field-id'] = $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode']; } } /** * Implements hook_entity_view_alter(). */ function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) { $build['#cache']['contexts'][] = 'user.permissions'; if (!\Drupal::currentUser()->hasPermission('access in-place editing') || !_quickedit_entity_is_latest_revision($entity)) { return; } $build['#attributes']['data-quickedit-entity-id'] = $entity->getEntityTypeId() . '/' . $entity->id(); } /** * Check if a loaded entity is the latest revision. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to check. * * @return bool * TRUE if the loaded entity is the latest revision, FALSE otherwise. * * @todo Remove this method once better support for pending revisions is added * to core https://www.drupal.org/node/2784201. * * @internal */ function _quickedit_entity_is_latest_revision(ContentEntityInterface $entity) { $entity_type_manager = \Drupal::entityTypeManager(); $entity_definition = $entity_type_manager->getDefinition($entity->getEntityTypeId()); if (!$entity_definition->isRevisionable()) { return TRUE; } $revision_ids = $entity_type_manager ->getStorage($entity->getEntityTypeId()) ->getQuery() ->allRevisions() ->condition($entity_definition->getKey('id'), $entity->id()) ->sort($entity_definition->getKey('revision'), 'DESC') ->range(0, 1) ->execute(); return $entity->getLoadedRevisionId() == array_keys($revision_ids)[0]; }