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