1794f66f902f30f06ac6a1938f1a4cba85303c5f
[yaffs-website] / web / core / modules / quickedit / quickedit.module
1 <?php
2
3 /**
4  * @file
5  * Provides in-place content editing functionality for fields.
6  *
7  * The Quick Edit module makes content editable in-place. Rather than having to
8  * visit a separate page to edit content, it may be edited in-place.
9  *
10  * Technically, this module adds classes and data- attributes to fields and
11  * entities, enabling them for in-place editing.
12  */
13
14 use Drupal\Core\Entity\ContentEntityInterface;
15 use Drupal\Core\Entity\EntityInterface;
16 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
17 use Drupal\Core\Routing\RouteMatchInterface;
18
19 /**
20  * Implements hook_help().
21  */
22 function quickedit_help($route_name, RouteMatchInterface $route_match) {
23   switch ($route_name) {
24     case 'help.page.quickedit':
25       $output = '<h3>' . t('About') . '</h3>';
26       $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>.', [':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'])]) . '</p>';
27       $output .= '<h3>' . t('Uses') . '</h3>';
28       $output .= '<dl>';
29       $output .= '<dt>' . t('Editing content in-place') . '</dt>';
30       $output .= '<dd>';
31       $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).', [':contextual' => \Drupal::url('help.page', ['name' => 'contextual'])]) . '</p>';
32       $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>';
33       $output .= '</dd>';
34       $output .= '</dl>';
35       return $output;
36   }
37 }
38
39 /**
40  * Implements hook_page_attachments().
41  *
42  * Adds the quickedit library to the page for any user who has the 'access
43  * in-place editing' permission.
44  */
45 function quickedit_page_attachments(array &$page) {
46   if (!\Drupal::currentUser()->hasPermission('access in-place editing')) {
47     return;
48   }
49
50   // In-place editing is only supported on the front-end.
51   if (\Drupal::service('router.admin_context')->isAdminRoute()) {
52     return;
53   }
54
55   $page['#attached']['library'][] = 'quickedit/quickedit';
56 }
57
58 /**
59  * Implements hook_library_info_alter().
60  *
61  * Includes additional stylesheets defined by the admin theme to allow it to
62  * customize the Quick Edit toolbar appearance.
63  *
64  * An admin theme can specify CSS files to make the front-end administration
65  * experience of in-place editing match the administration experience in the
66  * back-end.
67  *
68  * The CSS files can be specified via the "edit_stylesheets" property in the
69  * .info.yml file:
70  * @code
71  * quickedit_stylesheets:
72  *   - css/quickedit.css
73  * @endcode
74  */
75 function quickedit_library_info_alter(&$libraries, $extension) {
76   if ($extension === 'quickedit' && isset($libraries['quickedit'])) {
77     $theme = Drupal::config('system.theme')->get('admin');
78
79     // First let the base theme modify the library, then the actual theme.
80     $alter_library = function (&$library, $theme) use (&$alter_library) {
81       if (isset($theme) && $theme_path = drupal_get_path('theme', $theme)) {
82         $info = system_get_info('theme', $theme);
83         // Recurse to process base theme(s) first.
84         if (isset($info['base theme'])) {
85           $alter_library($library, $info['base theme']);
86         }
87         if (isset($info['quickedit_stylesheets'])) {
88           foreach ($info['quickedit_stylesheets'] as $path) {
89             $library['css']['theme']['/' . $theme_path . '/' . $path] = [];
90           }
91         }
92       }
93     };
94
95     $alter_library($libraries['quickedit'], $theme);
96   }
97 }
98
99 /**
100  * Implements hook_field_formatter_info_alter().
101  *
102  * Quick Edit extends the @FieldFormatter annotation with the following keys:
103  * - quickedit: currently only contains one subkey 'editor' which indicates
104  *   which in-place editor should be used. Possible values are 'form',
105  *   'plain_text', 'disabled' or another in-place editor other than the ones
106  *   Quick Edit module provides.
107  */
108 function quickedit_field_formatter_info_alter(&$info) {
109   foreach ($info as $key => $settings) {
110     // Set in-place editor to 'form' if none is supplied.
111     if (empty($settings['quickedit'])) {
112       $info[$key]['quickedit'] = ['editor' => 'form'];
113     }
114   }
115 }
116
117 /**
118  * Implements hook_preprocess_HOOK() for the page title template.
119  */
120 function quickedit_preprocess_page_title(&$variables) {
121   $variables['#cache']['contexts'][] = 'user.permissions';
122   if (\Drupal::currentUser()->hasPermission('access in-place editing')) {
123     $variables['title_attributes']['class'][] = 'js-quickedit-page-title';
124   }
125 }
126
127 /**
128  * Implements hook_preprocess_HOOK() for field templates.
129  */
130 function quickedit_preprocess_field(&$variables) {
131   $variables['#cache']['contexts'][] = 'user.permissions';
132   $element = $variables['element'];
133   /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
134   $entity = $element['#object'];
135
136   if (!\Drupal::currentUser()->hasPermission('access in-place editing') || !$entity->isLatestRevision()) {
137     return;
138   }
139
140   // Quick Edit module only supports view modes, not dynamically defined
141   // "display options" (which \Drupal\Core\Field\FieldItemListInterface::view()
142   // always names the "_custom" view mode).
143   // @see \Drupal\Core\Field\FieldItemListInterface::view()
144   // @see https://www.drupal.org/node/2120335
145   if ($element['#view_mode'] === '_custom') {
146     return;
147   }
148
149   // Fields that are computed fields are not editable.
150   $definition = $entity->getFieldDefinition($element['#field_name']);
151   if (!$definition->isComputed()) {
152     $variables['attributes']['data-quickedit-field-id'] = $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode'];
153   }
154 }
155
156 /**
157  * Implements hook_entity_view_alter().
158  */
159 function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
160   /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
161   $build['#cache']['contexts'][] = 'user.permissions';
162   if (!\Drupal::currentUser()->hasPermission('access in-place editing') || !$entity->isLatestRevision()) {
163     return;
164   }
165
166   $build['#attributes']['data-quickedit-entity-id'] = $entity->getEntityTypeId() . '/' . $entity->id();
167 }
168
169 /**
170  * Check if a loaded entity is the latest revision.
171  *
172  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
173  *   The entity to check.
174  *
175  * @return bool
176  *   TRUE if the loaded entity is the latest revision, FALSE otherwise.
177  *
178  * @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use
179  *   \Drupal\Core\Entity\RevisionableInterface::isLatestRevision() instead.
180  *   As internal API, _quickedit_entity_is_latest_revision() may also be removed
181  *   in a minor release.
182  *
183  * @internal
184  */
185 function _quickedit_entity_is_latest_revision(ContentEntityInterface $entity) {
186   @trigger_error('_quickedit_entity_is_latest_revision() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Entity\RevisionableInterface::isLatestRevision() instead. As internal API, _quickedit_entity_is_latest_revision() may also be removed in a minor release.', E_USER_DEPRECATED);
187   return $entity->isLatestRevision();
188 }