Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * Provides discussion forums.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 use Drupal\comment\CommentInterface;
|
Chris@0
|
9 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
Chris@0
|
10 use Drupal\Core\Entity\EntityInterface;
|
Chris@0
|
11 use Drupal\Core\Entity\EntityTypeInterface;
|
Chris@0
|
12 use Drupal\Core\Url;
|
Chris@0
|
13 use Drupal\Core\Form\FormStateInterface;
|
Chris@0
|
14 use Drupal\Core\Routing\RouteMatchInterface;
|
Chris@0
|
15 use Drupal\taxonomy\VocabularyInterface;
|
Chris@0
|
16 use Drupal\user\Entity\User;
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * Implements hook_help().
|
Chris@0
|
20 */
|
Chris@0
|
21 function forum_help($route_name, RouteMatchInterface $route_match) {
|
Chris@0
|
22 switch ($route_name) {
|
Chris@0
|
23 case 'help.page.forum':
|
Chris@0
|
24 $output = '';
|
Chris@0
|
25 $output .= '<h3>' . t('About') . '</h3>';
|
Chris@0
|
26 $output .= '<p>' . t('The Forum module lets you create threaded discussion forums with functionality similar to other message board systems. In a forum, users post topics and threads in nested hierarchies, allowing discussions to be categorized and grouped.') . '</p>';
|
Chris@18
|
27 $output .= '<p>' . t('The Forum module adds and uses a content type called <em>Forum topic</em>. For background information on content types, see the <a href=":node_help">Node module help page</a>.', [':node_help' => Url::fromRoute('help.page', ['name' => 'node'])->toString()]) . '</p>';
|
Chris@0
|
28 $output .= '<p>' . t('A forum is represented by a hierarchical structure, consisting of:');
|
Chris@0
|
29 $output .= '<ul>';
|
Chris@0
|
30 $output .= '<li>' . t('<em>Forums</em> (for example, <em>Recipes for cooking vegetables</em>)') . '</li>';
|
Chris@0
|
31 $output .= '<li>' . t('<em>Forum topics</em> submitted by users (for example, <em>How to cook potatoes</em>), which start discussions.') . '</li>';
|
Chris@0
|
32 $output .= '<li>' . t('Threaded <em>comments</em> submitted by users (for example, <em>You wash the potatoes first and then...</em>).') . '</li>';
|
Chris@0
|
33 $output .= '<li>' . t('Optional <em>containers</em>, used to group similar forums. Forums can be placed inside containers, and vice versa.') . '</li>';
|
Chris@0
|
34 $output .= '</ul>';
|
Chris@0
|
35 $output .= '</p>';
|
Chris@0
|
36 $output .= '<p>' . t('For more information, see the <a href=":forum">online documentation for the Forum module</a>.', [':forum' => 'https://www.drupal.org/documentation/modules/forum']) . '</p>';
|
Chris@0
|
37 $output .= '<h3>' . t('Uses') . '</h3>';
|
Chris@0
|
38 $output .= '<dl>';
|
Chris@0
|
39 $output .= '<dt>' . t('Setting up the forum structure') . '</dt>';
|
Chris@18
|
40 $output .= '<dd>' . t('Visit the <a href=":forums">Forums page</a> to set up containers and forums to hold your discussion topics.', [':forums' => Url::fromRoute('forum.overview')->toString()]) . '</dd>';
|
Chris@0
|
41 $output .= '<dt>' . t('Starting a discussion') . '</dt>';
|
Chris@18
|
42 $output .= '<dd>' . t('The <a href=":create-topic">Forum topic</a> link on the <a href=":content-add">Add content</a> page creates the first post of a new threaded discussion, or thread.', [':create-topic' => Url::fromRoute('node.add', ['node_type' => 'forum'])->toString(), ':content-add' => Url::fromRoute('node.add_page')->toString()]) . '</dd>';
|
Chris@0
|
43 $output .= '<dt>' . t('Navigating in the forum') . '</dt>';
|
Chris@18
|
44 $output .= '<dd>' . t('Enabling the Forum module provides a default <em>Forums</em> menu item in the Tools menu that links to the <a href=":forums">Forums page</a>.', [':forums' => Url::fromRoute('forum.index')->toString()]) . '</dd>';
|
Chris@0
|
45 $output .= '<dt>' . t('Moving forum topics') . '</dt>';
|
Chris@0
|
46 $output .= '<dd>' . t('A forum topic (and all of its comments) may be moved between forums by selecting a different forum while editing a forum topic. When moving a forum topic between forums, the <em>Leave shadow copy</em> option creates a link in the original forum pointing to the new location.') . '</dd>';
|
Chris@0
|
47 $output .= '<dt>' . t('Locking and disabling comments') . '</dt>';
|
Chris@0
|
48 $output .= '<dd>' . t('Selecting <em>Closed</em> under <em>Comment settings</em> while editing a forum topic will lock (prevent new comments on) the thread. Selecting <em>Hidden</em> under <em>Comment settings</em> while editing a forum topic will hide all existing comments on the thread, and prevent new ones.') . '</dd>';
|
Chris@0
|
49 $output .= '</dl>';
|
Chris@0
|
50 return $output;
|
Chris@0
|
51
|
Chris@0
|
52 case 'forum.overview':
|
Chris@0
|
53 $output = '<p>' . t('Forums contain forum topics. Use containers to group related forums.') . '</p>';
|
Chris@0
|
54 $more_help_link = [
|
Chris@0
|
55 '#type' => 'link',
|
Chris@0
|
56 '#url' => Url::fromRoute('help.page', ['name' => 'forum']),
|
Chris@0
|
57 '#title' => t('More help'),
|
Chris@0
|
58 '#attributes' => [
|
Chris@0
|
59 'class' => ['icon-help'],
|
Chris@0
|
60 ],
|
Chris@0
|
61 ];
|
Chris@0
|
62 $container = [
|
Chris@0
|
63 '#theme' => 'container',
|
Chris@0
|
64 '#children' => $more_help_link,
|
Chris@0
|
65 '#attributes' => [
|
Chris@0
|
66 'class' => ['more-link'],
|
Chris@0
|
67 ],
|
Chris@0
|
68 ];
|
Chris@0
|
69 $output .= \Drupal::service('renderer')->renderPlain($container);
|
Chris@0
|
70 return $output;
|
Chris@0
|
71
|
Chris@0
|
72 case 'forum.add_container':
|
Chris@0
|
73 return '<p>' . t('Use containers to group related forums.') . '</p>';
|
Chris@0
|
74
|
Chris@0
|
75 case 'forum.add_forum':
|
Chris@0
|
76 return '<p>' . t('A forum holds related forum topics.') . '</p>';
|
Chris@0
|
77
|
Chris@0
|
78 case 'forum.settings':
|
Chris@18
|
79 return '<p>' . t('Adjust the display of your forum topics. Organize the forums on the <a href=":forum-structure">forum structure page</a>.', [':forum-structure' => Url::fromRoute('forum.overview')->toString()]) . '</p>';
|
Chris@0
|
80 }
|
Chris@0
|
81 }
|
Chris@0
|
82
|
Chris@0
|
83 /**
|
Chris@0
|
84 * Implements hook_theme().
|
Chris@0
|
85 */
|
Chris@0
|
86 function forum_theme() {
|
Chris@0
|
87 return [
|
Chris@0
|
88 'forums' => [
|
Chris@0
|
89 'variables' => ['forums' => [], 'topics' => [], 'topics_pager' => [], 'parents' => NULL, 'term' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL, 'header' => []],
|
Chris@0
|
90 ],
|
Chris@0
|
91 'forum_list' => [
|
Chris@0
|
92 'variables' => ['forums' => NULL, 'parents' => NULL, 'tid' => NULL],
|
Chris@0
|
93 ],
|
Chris@0
|
94 'forum_icon' => [
|
Chris@0
|
95 'variables' => ['new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0, 'first_new' => FALSE],
|
Chris@0
|
96 ],
|
Chris@0
|
97 'forum_submitted' => [
|
Chris@0
|
98 'variables' => ['topic' => NULL],
|
Chris@0
|
99 ],
|
Chris@0
|
100 ];
|
Chris@0
|
101 }
|
Chris@0
|
102
|
Chris@0
|
103 /**
|
Chris@0
|
104 * Implements hook_entity_type_build().
|
Chris@0
|
105 */
|
Chris@0
|
106 function forum_entity_type_build(array &$entity_types) {
|
Chris@0
|
107 /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
Chris@0
|
108 // Register forum specific forms.
|
Chris@0
|
109 $entity_types['taxonomy_term']
|
Chris@0
|
110 ->setFormClass('forum', 'Drupal\forum\Form\ForumForm')
|
Chris@0
|
111 ->setFormClass('container', 'Drupal\forum\Form\ContainerForm')
|
Chris@0
|
112 ->setLinkTemplate('forum-edit-container-form', '/admin/structure/forum/edit/container/{taxonomy_term}')
|
Chris@0
|
113 ->setLinkTemplate('forum-delete-form', '/admin/structure/forum/delete/forum/{taxonomy_term}')
|
Chris@0
|
114 ->setLinkTemplate('forum-edit-form', '/admin/structure/forum/edit/forum/{taxonomy_term}');
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 /**
|
Chris@0
|
118 * Implements hook_entity_bundle_info_alter().
|
Chris@0
|
119 */
|
Chris@0
|
120 function forum_entity_bundle_info_alter(&$bundles) {
|
Chris@0
|
121 // Take over URI construction for taxonomy terms that are forums.
|
Chris@0
|
122 if ($vid = \Drupal::config('forum.settings')->get('vocabulary')) {
|
Chris@0
|
123 if (isset($bundles['taxonomy_term'][$vid])) {
|
Chris@0
|
124 $bundles['taxonomy_term'][$vid]['uri_callback'] = 'forum_uri';
|
Chris@0
|
125 }
|
Chris@0
|
126 }
|
Chris@0
|
127 }
|
Chris@0
|
128
|
Chris@0
|
129 /**
|
Chris@0
|
130 * Entity URI callback used in forum_entity_bundle_info_alter().
|
Chris@0
|
131 */
|
Chris@0
|
132 function forum_uri($forum) {
|
Chris@0
|
133 return Url::fromRoute('forum.page', ['taxonomy_term' => $forum->id()]);
|
Chris@0
|
134 }
|
Chris@0
|
135
|
Chris@0
|
136 /**
|
Chris@0
|
137 * Implements hook_entity_bundle_field_info_alter().
|
Chris@0
|
138 */
|
Chris@0
|
139 function forum_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
|
Chris@0
|
140 if ($entity_type->id() == 'node' && !empty($fields['taxonomy_forums'])) {
|
Chris@0
|
141 $fields['taxonomy_forums']->addConstraint('ForumLeaf', []);
|
Chris@0
|
142 }
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 /**
|
Chris@0
|
146 * Implements hook_ENTITY_TYPE_presave() for node entities.
|
Chris@0
|
147 *
|
Chris@0
|
148 * Assigns the forum taxonomy when adding a topic from within a forum.
|
Chris@0
|
149 */
|
Chris@0
|
150 function forum_node_presave(EntityInterface $node) {
|
Chris@0
|
151 if (\Drupal::service('forum_manager')->checkNodeType($node)) {
|
Chris@0
|
152 // Make sure all fields are set properly:
|
Chris@0
|
153 $node->icon = !empty($node->icon) ? $node->icon : '';
|
Chris@0
|
154 if (!$node->taxonomy_forums->isEmpty()) {
|
Chris@0
|
155 $node->forum_tid = $node->taxonomy_forums->target_id;
|
Chris@0
|
156 // Only do a shadow copy check if this is not a new node.
|
Chris@0
|
157 if (!$node->isNew()) {
|
Chris@0
|
158 $old_tid = \Drupal::service('forum.index_storage')->getOriginalTermId($node);
|
Chris@0
|
159 if ($old_tid && isset($node->forum_tid) && ($node->forum_tid != $old_tid) && !empty($node->shadow)) {
|
Chris@0
|
160 // A shadow copy needs to be created. Retain new term and add old term.
|
Chris@0
|
161 $node->taxonomy_forums[count($node->taxonomy_forums)] = ['target_id' => $old_tid];
|
Chris@0
|
162 }
|
Chris@0
|
163 }
|
Chris@0
|
164 }
|
Chris@0
|
165 }
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 /**
|
Chris@0
|
169 * Implements hook_ENTITY_TYPE_update() for node entities.
|
Chris@0
|
170 */
|
Chris@0
|
171 function forum_node_update(EntityInterface $node) {
|
Chris@0
|
172 if (\Drupal::service('forum_manager')->checkNodeType($node)) {
|
Chris@0
|
173 // If this is not a new revision and does exist, update the forum record,
|
Chris@0
|
174 // otherwise insert a new one.
|
Chris@0
|
175 /** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
|
Chris@0
|
176 $forum_index_storage = \Drupal::service('forum.index_storage');
|
Chris@0
|
177 if ($node->getRevisionId() == $node->original->getRevisionId() && $forum_index_storage->getOriginalTermId($node)) {
|
Chris@0
|
178 if (!empty($node->forum_tid)) {
|
Chris@0
|
179 $forum_index_storage->update($node);
|
Chris@0
|
180 }
|
Chris@0
|
181 // The node is removed from the forum.
|
Chris@0
|
182 else {
|
Chris@0
|
183 $forum_index_storage->delete($node);
|
Chris@0
|
184 }
|
Chris@0
|
185 }
|
Chris@0
|
186 else {
|
Chris@0
|
187 if (!empty($node->forum_tid)) {
|
Chris@0
|
188 $forum_index_storage->create($node);
|
Chris@0
|
189 }
|
Chris@0
|
190 }
|
Chris@0
|
191 // If the node has a shadow forum topic, update the record for this
|
Chris@0
|
192 // revision.
|
Chris@0
|
193 if (!empty($node->shadow)) {
|
Chris@0
|
194 $forum_index_storage->deleteRevision($node);
|
Chris@0
|
195 $forum_index_storage->create($node);
|
Chris@0
|
196 }
|
Chris@0
|
197
|
Chris@0
|
198 // If the node is published, update the forum index.
|
Chris@0
|
199 if ($node->isPublished()) {
|
Chris@0
|
200 $forum_index_storage->deleteIndex($node);
|
Chris@0
|
201 $forum_index_storage->createIndex($node);
|
Chris@0
|
202 }
|
Chris@0
|
203 // When a forum node is unpublished, remove it from the forum_index table.
|
Chris@0
|
204 else {
|
Chris@0
|
205 $forum_index_storage->deleteIndex($node);
|
Chris@0
|
206 }
|
Chris@0
|
207 }
|
Chris@0
|
208 }
|
Chris@0
|
209
|
Chris@0
|
210 /**
|
Chris@0
|
211 * Implements hook_ENTITY_TYPE_insert() for node entities.
|
Chris@0
|
212 */
|
Chris@0
|
213 function forum_node_insert(EntityInterface $node) {
|
Chris@0
|
214 if (\Drupal::service('forum_manager')->checkNodeType($node)) {
|
Chris@0
|
215 /** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
|
Chris@0
|
216 $forum_index_storage = \Drupal::service('forum.index_storage');
|
Chris@0
|
217 if (!empty($node->forum_tid)) {
|
Chris@0
|
218 $forum_index_storage->create($node);
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 // If the node is published, update the forum index.
|
Chris@0
|
222 if ($node->isPublished()) {
|
Chris@0
|
223 $forum_index_storage->createIndex($node);
|
Chris@0
|
224 }
|
Chris@0
|
225 }
|
Chris@0
|
226 }
|
Chris@0
|
227
|
Chris@0
|
228 /**
|
Chris@0
|
229 * Implements hook_ENTITY_TYPE_predelete() for node entities.
|
Chris@0
|
230 */
|
Chris@0
|
231 function forum_node_predelete(EntityInterface $node) {
|
Chris@0
|
232 if (\Drupal::service('forum_manager')->checkNodeType($node)) {
|
Chris@0
|
233 /** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
|
Chris@0
|
234 $forum_index_storage = \Drupal::service('forum.index_storage');
|
Chris@0
|
235 $forum_index_storage->delete($node);
|
Chris@0
|
236 $forum_index_storage->deleteIndex($node);
|
Chris@0
|
237 }
|
Chris@0
|
238 }
|
Chris@0
|
239
|
Chris@0
|
240 /**
|
Chris@0
|
241 * Implements hook_ENTITY_TYPE_storage_load() for node entities.
|
Chris@0
|
242 */
|
Chris@0
|
243 function forum_node_storage_load($nodes) {
|
Chris@0
|
244 $node_vids = [];
|
Chris@0
|
245 foreach ($nodes as $node) {
|
Chris@0
|
246 if (\Drupal::service('forum_manager')->checkNodeType($node)) {
|
Chris@0
|
247 $node_vids[] = $node->getRevisionId();
|
Chris@0
|
248 }
|
Chris@0
|
249 }
|
Chris@0
|
250 if (!empty($node_vids)) {
|
Chris@0
|
251 $result = \Drupal::service('forum.index_storage')->read($node_vids);
|
Chris@0
|
252 foreach ($result as $record) {
|
Chris@0
|
253 $nodes[$record->nid]->forum_tid = $record->tid;
|
Chris@0
|
254 }
|
Chris@0
|
255 }
|
Chris@0
|
256 }
|
Chris@0
|
257
|
Chris@0
|
258 /**
|
Chris@0
|
259 * Implements hook_ENTITY_TYPE_update() for comment entities.
|
Chris@0
|
260 */
|
Chris@0
|
261 function forum_comment_update(CommentInterface $comment) {
|
Chris@0
|
262 if ($comment->getCommentedEntityTypeId() == 'node') {
|
Chris@0
|
263 \Drupal::service('forum.index_storage')->updateIndex($comment->getCommentedEntity());
|
Chris@0
|
264 }
|
Chris@0
|
265 }
|
Chris@0
|
266
|
Chris@0
|
267 /**
|
Chris@0
|
268 * Implements hook_ENTITY_TYPE_insert() for comment entities.
|
Chris@0
|
269 */
|
Chris@0
|
270 function forum_comment_insert(CommentInterface $comment) {
|
Chris@0
|
271 if ($comment->getCommentedEntityTypeId() == 'node') {
|
Chris@0
|
272 \Drupal::service('forum.index_storage')->updateIndex($comment->getCommentedEntity());
|
Chris@0
|
273 }
|
Chris@0
|
274 }
|
Chris@0
|
275
|
Chris@0
|
276 /**
|
Chris@0
|
277 * Implements hook_ENTITY_TYPE_delete() for comment entities.
|
Chris@0
|
278 */
|
Chris@0
|
279 function forum_comment_delete(CommentInterface $comment) {
|
Chris@0
|
280 if ($comment->getCommentedEntityTypeId() == 'node') {
|
Chris@0
|
281 \Drupal::service('forum.index_storage')->updateIndex($comment->getCommentedEntity());
|
Chris@0
|
282 }
|
Chris@0
|
283 }
|
Chris@0
|
284
|
Chris@0
|
285 /**
|
Chris@0
|
286 * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\taxonomy\VocabularyForm.
|
Chris@0
|
287 */
|
Chris@0
|
288 function forum_form_taxonomy_vocabulary_form_alter(&$form, FormStateInterface $form_state, $form_id) {
|
Chris@0
|
289 $vid = \Drupal::config('forum.settings')->get('vocabulary');
|
Chris@0
|
290 $vocabulary = $form_state->getFormObject()->getEntity();
|
Chris@0
|
291 if ($vid == $vocabulary->id()) {
|
Chris@0
|
292 $form['help_forum_vocab'] = [
|
Chris@0
|
293 '#markup' => t('This is the designated forum vocabulary. Some of the normal vocabulary options have been removed.'),
|
Chris@0
|
294 '#weight' => -1,
|
Chris@0
|
295 ];
|
Chris@0
|
296 // Forum's vocabulary always has single hierarchy. Forums and containers
|
Chris@0
|
297 // have only one parent or no parent for root items. By default this value
|
Chris@0
|
298 // is 0.
|
Chris@0
|
299 $form['hierarchy']['#value'] = VocabularyInterface::HIERARCHY_SINGLE;
|
Chris@0
|
300 // Do not allow to delete forum's vocabulary.
|
Chris@0
|
301 $form['actions']['delete']['#access'] = FALSE;
|
Chris@0
|
302 // Do not allow to change a vid of forum's vocabulary.
|
Chris@0
|
303 $form['vid']['#disabled'] = TRUE;
|
Chris@0
|
304 }
|
Chris@0
|
305 }
|
Chris@0
|
306
|
Chris@0
|
307 /**
|
Chris@0
|
308 * Implements hook_form_FORM_ID_alter() for \Drupal\taxonomy\TermForm.
|
Chris@0
|
309 */
|
Chris@0
|
310 function forum_form_taxonomy_term_form_alter(&$form, FormStateInterface $form_state, $form_id) {
|
Chris@0
|
311 $vid = \Drupal::config('forum.settings')->get('vocabulary');
|
Chris@0
|
312 if (isset($form['vid']['#value']) && $form['vid']['#value'] == $vid) {
|
Chris@0
|
313 // Hide multiple parents select from forum terms.
|
Chris@0
|
314 $form['relations']['parent']['#access'] = FALSE;
|
Chris@0
|
315 }
|
Chris@0
|
316 }
|
Chris@0
|
317
|
Chris@0
|
318 /**
|
Chris@0
|
319 * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm.
|
Chris@0
|
320 */
|
Chris@0
|
321 function forum_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
|
Chris@0
|
322 $node = $form_state->getFormObject()->getEntity();
|
Chris@0
|
323 if (isset($node->taxonomy_forums) && !$node->isNew()) {
|
Chris@0
|
324 $forum_terms = $node->taxonomy_forums;
|
Chris@0
|
325 // If editing, give option to leave shadows.
|
Chris@0
|
326 $shadow = (count($forum_terms) > 1);
|
Chris@0
|
327 $form['shadow'] = [
|
Chris@0
|
328 '#type' => 'checkbox',
|
Chris@0
|
329 '#title' => t('Leave shadow copy'),
|
Chris@0
|
330 '#default_value' => $shadow,
|
Chris@0
|
331 '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'),
|
Chris@0
|
332 ];
|
Chris@0
|
333 $form['forum_tid'] = ['#type' => 'value', '#value' => $node->forum_tid];
|
Chris@0
|
334 }
|
Chris@0
|
335
|
Chris@0
|
336 if (isset($form['taxonomy_forums'])) {
|
Chris@0
|
337 $widget =& $form['taxonomy_forums']['widget'];
|
Chris@0
|
338 // Make the vocabulary required for 'real' forum-nodes.
|
Chris@0
|
339 $widget['#required'] = TRUE;
|
Chris@0
|
340 $widget['#multiple'] = FALSE;
|
Chris@0
|
341 if (empty($widget['#default_value'])) {
|
Chris@0
|
342 // If there is no default forum already selected, try to get the forum
|
Chris@0
|
343 // ID from the URL (e.g., if we are on a page like node/add/forum/2, we
|
Chris@0
|
344 // expect "2" to be the ID of the forum that was requested).
|
Chris@0
|
345 $requested_forum_id = \Drupal::request()->query->get('forum_id');
|
Chris@0
|
346 $widget['#default_value'] = is_numeric($requested_forum_id) ? $requested_forum_id : '';
|
Chris@0
|
347 }
|
Chris@0
|
348 }
|
Chris@0
|
349 }
|
Chris@0
|
350
|
Chris@0
|
351 /**
|
Chris@0
|
352 * Implements hook_preprocess_HOOK() for block templates.
|
Chris@0
|
353 */
|
Chris@0
|
354 function forum_preprocess_block(&$variables) {
|
Chris@0
|
355 if ($variables['configuration']['provider'] == 'forum') {
|
Chris@0
|
356 $variables['attributes']['role'] = 'navigation';
|
Chris@0
|
357 }
|
Chris@0
|
358 }
|
Chris@0
|
359
|
Chris@0
|
360 /**
|
Chris@0
|
361 * Implements hook_theme_suggestions_HOOK().
|
Chris@0
|
362 */
|
Chris@0
|
363 function forum_theme_suggestions_forums(array $variables) {
|
Chris@0
|
364 $suggestions = [];
|
Chris@0
|
365 $tid = $variables['term']->id();
|
Chris@0
|
366
|
Chris@0
|
367 // Provide separate template suggestions based on what's being output. Topic
|
Chris@0
|
368 // ID is also accounted for. Check both variables to be safe then the inverse.
|
Chris@0
|
369 // Forums with topic IDs take precedence.
|
Chris@0
|
370 if ($variables['forums'] && !$variables['topics']) {
|
Chris@0
|
371 $suggestions[] = 'forums__containers';
|
Chris@0
|
372 $suggestions[] = 'forums__' . $tid;
|
Chris@0
|
373 $suggestions[] = 'forums__containers__' . $tid;
|
Chris@0
|
374 }
|
Chris@0
|
375 elseif (!$variables['forums'] && $variables['topics']) {
|
Chris@0
|
376 $suggestions[] = 'forums__topics';
|
Chris@0
|
377 $suggestions[] = 'forums__' . $tid;
|
Chris@0
|
378 $suggestions[] = 'forums__topics__' . $tid;
|
Chris@0
|
379 }
|
Chris@0
|
380 else {
|
Chris@0
|
381 $suggestions[] = 'forums__' . $tid;
|
Chris@0
|
382 }
|
Chris@0
|
383
|
Chris@0
|
384 return $suggestions;
|
Chris@0
|
385 }
|
Chris@0
|
386
|
Chris@0
|
387 /**
|
Chris@0
|
388 * Prepares variables for forums templates.
|
Chris@0
|
389 *
|
Chris@0
|
390 * Default template: forums.html.twig.
|
Chris@0
|
391 *
|
Chris@0
|
392 * @param array $variables
|
Chris@0
|
393 * An array containing the following elements:
|
Chris@0
|
394 * - forums: An array of all forum objects to display for the given taxonomy
|
Chris@0
|
395 * term ID. If tid = 0 then all the top-level forums are displayed.
|
Chris@0
|
396 * - topics: An array of all the topics in the current forum.
|
Chris@0
|
397 * - parents: An array of taxonomy term objects that are ancestors of the
|
Chris@0
|
398 * current term ID.
|
Chris@0
|
399 * - term: Taxonomy term of the current forum.
|
Chris@0
|
400 * - sortby: One of the following integers indicating the sort criteria:
|
Chris@0
|
401 * - 1: Date - newest first.
|
Chris@0
|
402 * - 2: Date - oldest first.
|
Chris@0
|
403 * - 3: Posts with the most comments first.
|
Chris@0
|
404 * - 4: Posts with the least comments first.
|
Chris@0
|
405 * - forum_per_page: The maximum number of topics to display per page.
|
Chris@0
|
406 */
|
Chris@0
|
407 function template_preprocess_forums(&$variables) {
|
Chris@0
|
408 $variables['tid'] = $variables['term']->id();
|
Chris@0
|
409 if ($variables['forums_defined'] = count($variables['forums']) || count($variables['parents'])) {
|
Chris@0
|
410 if (!empty($variables['forums'])) {
|
Chris@0
|
411 $variables['forums'] = [
|
Chris@0
|
412 '#theme' => 'forum_list',
|
Chris@0
|
413 '#forums' => $variables['forums'],
|
Chris@0
|
414 '#parents' => $variables['parents'],
|
Chris@0
|
415 '#tid' => $variables['tid'],
|
Chris@0
|
416 ];
|
Chris@0
|
417 }
|
Chris@0
|
418
|
Chris@0
|
419 if ($variables['term'] && empty($variables['term']->forum_container->value) && !empty($variables['topics'])) {
|
Chris@0
|
420 $forum_topic_list_header = $variables['header'];
|
Chris@0
|
421
|
Chris@0
|
422 $table = [
|
Chris@0
|
423 '#theme' => 'table__forum_topic_list',
|
Chris@0
|
424 '#responsive' => FALSE,
|
Chris@0
|
425 '#attributes' => ['id' => 'forum-topic-' . $variables['tid']],
|
Chris@0
|
426 '#header' => [],
|
Chris@0
|
427 '#rows' => [],
|
Chris@0
|
428 ];
|
Chris@0
|
429
|
Chris@0
|
430 if (!empty($forum_topic_list_header)) {
|
Chris@0
|
431 $table['#header'] = $forum_topic_list_header;
|
Chris@0
|
432 }
|
Chris@0
|
433
|
Chris@0
|
434 /** @var \Drupal\node\NodeInterface $topic */
|
Chris@0
|
435 foreach ($variables['topics'] as $id => $topic) {
|
Chris@0
|
436 $variables['topics'][$id]->icon = [
|
Chris@0
|
437 '#theme' => 'forum_icon',
|
Chris@0
|
438 '#new_posts' => $topic->new,
|
Chris@0
|
439 '#num_posts' => $topic->comment_count,
|
Chris@0
|
440 '#comment_mode' => $topic->comment_mode,
|
Chris@0
|
441 '#sticky' => $topic->isSticky(),
|
Chris@0
|
442 '#first_new' => $topic->first_new,
|
Chris@0
|
443 ];
|
Chris@0
|
444
|
Chris@0
|
445 // We keep the actual tid in forum table, if it's different from the
|
Chris@0
|
446 // current tid then it means the topic appears in two forums, one of
|
Chris@0
|
447 // them is a shadow copy.
|
Chris@0
|
448 if ($variables['tid'] != $topic->forum_tid) {
|
Chris@0
|
449 $variables['topics'][$id]->moved = TRUE;
|
Chris@0
|
450 $variables['topics'][$id]->title = $topic->getTitle();
|
Chris@0
|
451 $variables['topics'][$id]->message = \Drupal::l(t('This topic has been moved'), new Url('forum.page', ['taxonomy_term' => $topic->forum_tid]));
|
Chris@0
|
452 }
|
Chris@0
|
453 else {
|
Chris@0
|
454 $variables['topics'][$id]->moved = FALSE;
|
Chris@18
|
455 $variables['topics'][$id]->title_link = \Drupal::l($topic->getTitle(), $topic->toUrl());
|
Chris@0
|
456 $variables['topics'][$id]->message = '';
|
Chris@0
|
457 }
|
Chris@0
|
458 $forum_submitted = [
|
Chris@0
|
459 '#theme' => 'forum_submitted',
|
Chris@0
|
460 '#topic' => (object) [
|
Chris@0
|
461 'uid' => $topic->getOwnerId(),
|
Chris@0
|
462 'name' => $topic->getOwner()->getDisplayName(),
|
Chris@0
|
463 'created' => $topic->getCreatedTime(),
|
Chris@0
|
464 ],
|
Chris@0
|
465 ];
|
Chris@0
|
466 $variables['topics'][$id]->submitted = \Drupal::service('renderer')->render($forum_submitted);
|
Chris@0
|
467 $forum_submitted = [
|
Chris@0
|
468 '#theme' => 'forum_submitted',
|
Chris@0
|
469 '#topic' => isset($topic->last_reply) ? $topic->last_reply : NULL,
|
Chris@0
|
470 ];
|
Chris@0
|
471 $variables['topics'][$id]->last_reply = \Drupal::service('renderer')->render($forum_submitted);
|
Chris@0
|
472
|
Chris@0
|
473 $variables['topics'][$id]->new_text = '';
|
Chris@0
|
474 $variables['topics'][$id]->new_url = '';
|
Chris@0
|
475
|
Chris@0
|
476 if ($topic->new_replies) {
|
Chris@0
|
477 $page_number = \Drupal::entityManager()->getStorage('comment')
|
Chris@0
|
478 ->getNewCommentPageNumber($topic->comment_count, $topic->new_replies, $topic, 'comment_forum');
|
Chris@0
|
479 $query = $page_number ? ['page' => $page_number] : NULL;
|
Chris@0
|
480 $variables['topics'][$id]->new_text = \Drupal::translation()->formatPlural($topic->new_replies, '1 new post<span class="visually-hidden"> in topic %title</span>', '@count new posts<span class="visually-hidden"> in topic %title</span>', ['%title' => $variables['topics'][$id]->label()]);
|
Chris@18
|
481 $variables['topics'][$id]->new_url = Url::fromRoute('entity.node.canonical', ['node' => $topic->id()], ['query' => $query, 'fragment' => 'new'])->toString();
|
Chris@0
|
482 }
|
Chris@0
|
483
|
Chris@0
|
484 // Build table rows from topics.
|
Chris@0
|
485 $row = [];
|
Chris@0
|
486 $row[] = [
|
Chris@0
|
487 'data' => [
|
Chris@0
|
488 $topic->icon,
|
Chris@0
|
489 [
|
Chris@0
|
490 '#markup' => '<div class="forum__title"><div>' . $topic->title_link . '</div><div>' . $topic->submitted . '</div></div>',
|
Chris@0
|
491 ],
|
Chris@0
|
492 ],
|
Chris@0
|
493 'class' => ['forum__topic'],
|
Chris@0
|
494 ];
|
Chris@0
|
495
|
Chris@0
|
496 if ($topic->moved) {
|
Chris@0
|
497 $row[] = [
|
Chris@0
|
498 'data' => $topic->message,
|
Chris@0
|
499 'colspan' => '2',
|
Chris@0
|
500 ];
|
Chris@0
|
501 }
|
Chris@0
|
502 else {
|
Chris@0
|
503 $new_replies = '';
|
Chris@0
|
504 if ($topic->new_replies) {
|
Chris@0
|
505 $new_replies = '<br /><a href="' . $topic->new_url . '">' . $topic->new_text . '</a>';
|
Chris@0
|
506 }
|
Chris@0
|
507
|
Chris@0
|
508 $row[] = [
|
Chris@0
|
509 'data' => [
|
Chris@0
|
510 [
|
Chris@0
|
511 '#prefix' => $topic->comment_count,
|
Chris@0
|
512 '#markup' => $new_replies,
|
Chris@0
|
513 ],
|
Chris@0
|
514 ],
|
Chris@0
|
515 'class' => ['forum__replies'],
|
Chris@0
|
516 ];
|
Chris@0
|
517 $row[] = [
|
Chris@0
|
518 'data' => $topic->last_reply,
|
Chris@0
|
519 'class' => ['forum__last-reply'],
|
Chris@0
|
520 ];
|
Chris@0
|
521 }
|
Chris@0
|
522 $table['#rows'][] = $row;
|
Chris@0
|
523 }
|
Chris@0
|
524
|
Chris@17
|
525 $variables['topics_original'] = $variables['topics'];
|
Chris@0
|
526 $variables['topics'] = $table;
|
Chris@0
|
527 $variables['topics_pager'] = [
|
Chris@0
|
528 '#type' => 'pager',
|
Chris@0
|
529 ];
|
Chris@0
|
530 }
|
Chris@0
|
531 }
|
Chris@0
|
532 }
|
Chris@0
|
533
|
Chris@0
|
534 /**
|
Chris@0
|
535 * Prepares variables for forum list templates.
|
Chris@0
|
536 *
|
Chris@0
|
537 * Default template: forum-list.html.twig.
|
Chris@0
|
538 *
|
Chris@0
|
539 * @param array $variables
|
Chris@0
|
540 * An array containing the following elements:
|
Chris@0
|
541 * - forums: An array of all forum objects to display for the given taxonomy
|
Chris@0
|
542 * term ID. If tid = 0 then all the top-level forums are displayed.
|
Chris@0
|
543 * - parents: An array of taxonomy term objects that are ancestors of the
|
Chris@0
|
544 * current term ID.
|
Chris@0
|
545 * - tid: Taxonomy term ID of the current forum.
|
Chris@0
|
546 */
|
Chris@0
|
547 function template_preprocess_forum_list(&$variables) {
|
Chris@0
|
548 $user = \Drupal::currentUser();
|
Chris@0
|
549 $row = 0;
|
Chris@0
|
550 // Sanitize each forum so that the template can safely print the data.
|
Chris@0
|
551 foreach ($variables['forums'] as $id => $forum) {
|
Chris@0
|
552 $variables['forums'][$id]->description = ['#markup' => $forum->description->value];
|
Chris@0
|
553 $variables['forums'][$id]->link = forum_uri($forum);
|
Chris@0
|
554 $variables['forums'][$id]->name = $forum->label();
|
Chris@0
|
555 $variables['forums'][$id]->is_container = !empty($forum->forum_container->value);
|
Chris@0
|
556 $variables['forums'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
|
Chris@0
|
557 $row++;
|
Chris@0
|
558
|
Chris@0
|
559 $variables['forums'][$id]->new_text = '';
|
Chris@0
|
560 $variables['forums'][$id]->new_url = '';
|
Chris@0
|
561 $variables['forums'][$id]->new_topics = 0;
|
Chris@0
|
562 $variables['forums'][$id]->old_topics = $forum->num_topics;
|
Chris@0
|
563 $variables['forums'][$id]->icon_class = 'default';
|
Chris@0
|
564 $variables['forums'][$id]->icon_title = t('No new posts');
|
Chris@0
|
565 if ($user->isAuthenticated()) {
|
Chris@0
|
566 $variables['forums'][$id]->new_topics = \Drupal::service('forum_manager')->unreadTopics($forum->id(), $user->id());
|
Chris@0
|
567 if ($variables['forums'][$id]->new_topics) {
|
Chris@0
|
568 $variables['forums'][$id]->new_text = \Drupal::translation()->formatPlural($variables['forums'][$id]->new_topics, '1 new post<span class="visually-hidden"> in forum %title</span>', '@count new posts<span class="visually-hidden"> in forum %title</span>', ['%title' => $variables['forums'][$id]->label()]);
|
Chris@18
|
569 $variables['forums'][$id]->new_url = Url::fromRoute('forum.page', ['taxonomy_term' => $forum->id()], ['fragment' => 'new'])->toString();
|
Chris@0
|
570 $variables['forums'][$id]->icon_class = 'new';
|
Chris@0
|
571 $variables['forums'][$id]->icon_title = t('New posts');
|
Chris@0
|
572 }
|
Chris@0
|
573 $variables['forums'][$id]->old_topics = $forum->num_topics - $variables['forums'][$id]->new_topics;
|
Chris@0
|
574 }
|
Chris@0
|
575 $forum_submitted = ['#theme' => 'forum_submitted', '#topic' => $forum->last_post];
|
Chris@0
|
576 $variables['forums'][$id]->last_reply = \Drupal::service('renderer')->render($forum_submitted);
|
Chris@0
|
577 }
|
Chris@0
|
578
|
Chris@0
|
579 $variables['pager'] = [
|
Chris@0
|
580 '#type' => 'pager',
|
Chris@0
|
581 ];
|
Chris@0
|
582
|
Chris@0
|
583 // Give meaning to $tid for themers. $tid actually stands for term ID.
|
Chris@0
|
584 $variables['forum_id'] = $variables['tid'];
|
Chris@0
|
585 unset($variables['tid']);
|
Chris@0
|
586 }
|
Chris@0
|
587
|
Chris@0
|
588 /**
|
Chris@0
|
589 * Prepares variables for forum icon templates.
|
Chris@0
|
590 *
|
Chris@0
|
591 * Default template: forum-icon.html.twig.
|
Chris@0
|
592 *
|
Chris@0
|
593 * @param array $variables
|
Chris@0
|
594 * An array containing the following elements:
|
Chris@0
|
595 * - new_posts: Indicates whether or not the topic contains new posts.
|
Chris@0
|
596 * - num_posts: The total number of posts in all topics.
|
Chris@0
|
597 * - comment_mode: An integer indicating whether comments are open, closed,
|
Chris@0
|
598 * or hidden.
|
Chris@0
|
599 * - sticky: Indicates whether the topic is sticky.
|
Chris@0
|
600 * - first_new: Indicates whether this is the first topic with new posts.
|
Chris@0
|
601 */
|
Chris@0
|
602 function template_preprocess_forum_icon(&$variables) {
|
Chris@0
|
603 $variables['hot_threshold'] = \Drupal::config('forum.settings')->get('topics.hot_threshold');
|
Chris@0
|
604
|
Chris@0
|
605 if ($variables['num_posts'] > $variables['hot_threshold']) {
|
Chris@0
|
606 $variables['icon_status'] = $variables['new_posts'] ? 'hot-new' : 'hot';
|
Chris@0
|
607 $variables['icon_title'] = $variables['new_posts'] ? t('Hot topic, new comments') : t('Hot topic');
|
Chris@0
|
608 }
|
Chris@0
|
609 else {
|
Chris@0
|
610 $variables['icon_status'] = $variables['new_posts'] ? 'new' : 'default';
|
Chris@0
|
611 $variables['icon_title'] = $variables['new_posts'] ? t('New comments') : t('Normal topic');
|
Chris@0
|
612 }
|
Chris@0
|
613
|
Chris@0
|
614 if ($variables['comment_mode'] == CommentItemInterface::CLOSED || $variables['comment_mode'] == CommentItemInterface::HIDDEN) {
|
Chris@0
|
615 $variables['icon_status'] = 'closed';
|
Chris@0
|
616 $variables['icon_title'] = t('Closed topic');
|
Chris@0
|
617 }
|
Chris@0
|
618
|
Chris@0
|
619 if ($variables['sticky'] == 1) {
|
Chris@0
|
620 $variables['icon_status'] = 'sticky';
|
Chris@0
|
621 $variables['icon_title'] = t('Sticky topic');
|
Chris@0
|
622 }
|
Chris@0
|
623
|
Chris@0
|
624 $variables['attributes']['title'] = $variables['icon_title'];
|
Chris@0
|
625 }
|
Chris@0
|
626
|
Chris@0
|
627 /**
|
Chris@0
|
628 * Prepares variables for forum submission information templates.
|
Chris@0
|
629 *
|
Chris@0
|
630 * The submission information will be displayed in the forum list and topic
|
Chris@0
|
631 * list.
|
Chris@0
|
632 *
|
Chris@0
|
633 * Default template: forum-submitted.html.twig.
|
Chris@0
|
634 *
|
Chris@0
|
635 * @param array $variables
|
Chris@0
|
636 * An array containing the following elements:
|
Chris@0
|
637 * - topic: The topic object.
|
Chris@0
|
638 */
|
Chris@0
|
639 function template_preprocess_forum_submitted(&$variables) {
|
Chris@0
|
640 $variables['author'] = '';
|
Chris@0
|
641 if (isset($variables['topic']->uid)) {
|
Chris@0
|
642 $username = ['#theme' => 'username', '#account' => User::load($variables['topic']->uid)];
|
Chris@0
|
643 $variables['author'] = \Drupal::service('renderer')->render($username);
|
Chris@0
|
644 }
|
Chris@0
|
645 $variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')->formatTimeDiffSince($variables['topic']->created) : '';
|
Chris@0
|
646 }
|