forum.module in Drupal 9
Same filename and directory in other branches
Provides discussion forums.
File
core/modules/forum/forum.moduleView source
<?php
/**
* @file
* Provides discussion forums.
*/
use Drupal\comment\CommentInterface;
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\taxonomy\VocabularyInterface;
use Drupal\user\Entity\User;
/**
* Implements hook_help().
*/
function forum_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.forum':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$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>';
$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>';
$output .= '<p>' . t('A forum is represented by a hierarchical structure, consisting of:');
$output .= '<ul>';
$output .= '<li>' . t('<em>Forums</em> (for example, <em>Recipes for cooking vegetables</em>)') . '</li>';
$output .= '<li>' . t('<em>Forum topics</em> submitted by users (for example, <em>How to cook potatoes</em>), which start discussions.') . '</li>';
$output .= '<li>' . t('Threaded <em>comments</em> submitted by users (for example, <em>You wash the potatoes first and then...</em>).') . '</li>';
$output .= '<li>' . t('Optional <em>containers</em>, used to group similar forums. Forums can be placed inside containers, and vice versa.') . '</li>';
$output .= '</ul>';
$output .= '</p>';
$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>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Setting up the forum structure') . '</dt>';
$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>';
$output .= '<dt>' . t('Starting a discussion') . '</dt>';
$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>';
$output .= '<dt>' . t('Navigating in the forum') . '</dt>';
$output .= '<dd>' . t('Enabling the Forum module provides a default <em>Forums</em> menu link in the Tools menu that links to the <a href=":forums">Forums page</a>.', [
':forums' => Url::fromRoute('forum.index')
->toString(),
]) . '</dd>';
$output .= '<dt>' . t('Moving forum topics') . '</dt>';
$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>';
$output .= '<dt>' . t('Locking and disabling comments') . '</dt>';
$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>';
$output .= '</dl>';
return $output;
case 'forum.overview':
$output = '<p>' . t('Forums contain forum topics. Use containers to group related forums.') . '</p>';
$more_help_link = [
'#type' => 'link',
'#url' => Url::fromRoute('help.page', [
'name' => 'forum',
]),
'#title' => t('More help'),
'#attributes' => [
'class' => [
'icon-help',
],
],
];
$container = [
'#theme' => 'container',
'#children' => $more_help_link,
'#attributes' => [
'class' => [
'more-link',
],
],
];
$output .= \Drupal::service('renderer')
->renderPlain($container);
return $output;
case 'forum.add_container':
return '<p>' . t('Use containers to group related forums.') . '</p>';
case 'forum.add_forum':
return '<p>' . t('A forum holds related forum topics.') . '</p>';
case 'forum.settings':
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>';
}
}
/**
* Implements hook_theme().
*/
function forum_theme() {
return [
'forums' => [
'variables' => [
'forums' => [],
'topics' => [],
'topics_pager' => [],
'parents' => NULL,
'term' => NULL,
'sortby' => NULL,
'forum_per_page' => NULL,
'header' => [],
],
],
'forum_list' => [
'variables' => [
'forums' => NULL,
'parents' => NULL,
'tid' => NULL,
],
],
'forum_icon' => [
'variables' => [
'new_posts' => NULL,
'num_posts' => 0,
'comment_mode' => 0,
'sticky' => 0,
'first_new' => FALSE,
],
],
'forum_submitted' => [
'variables' => [
'topic' => NULL,
],
],
];
}
/**
* Implements hook_entity_type_build().
*/
function forum_entity_type_build(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
// Register forum specific forms.
$entity_types['taxonomy_term']
->setFormClass('forum', 'Drupal\\forum\\Form\\ForumForm')
->setFormClass('container', 'Drupal\\forum\\Form\\ContainerForm')
->setLinkTemplate('forum-edit-container-form', '/admin/structure/forum/edit/container/{taxonomy_term}')
->setLinkTemplate('forum-delete-form', '/admin/structure/forum/delete/forum/{taxonomy_term}')
->setLinkTemplate('forum-edit-form', '/admin/structure/forum/edit/forum/{taxonomy_term}');
}
/**
* Implements hook_entity_bundle_info_alter().
*/
function forum_entity_bundle_info_alter(&$bundles) {
// Take over URI construction for taxonomy terms that are forums.
if ($vid = \Drupal::config('forum.settings')
->get('vocabulary')) {
if (isset($bundles['taxonomy_term'][$vid])) {
$bundles['taxonomy_term'][$vid]['uri_callback'] = 'forum_uri';
}
}
}
/**
* Entity URI callback used in forum_entity_bundle_info_alter().
*/
function forum_uri($forum) {
return Url::fromRoute('forum.page', [
'taxonomy_term' => $forum
->id(),
]);
}
/**
* Implements hook_entity_bundle_field_info_alter().
*/
function forum_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
if ($entity_type
->id() == 'node' && !empty($fields['taxonomy_forums'])) {
$fields['taxonomy_forums']
->addConstraint('ForumLeaf', []);
}
}
/**
* Implements hook_ENTITY_TYPE_presave() for node entities.
*
* Assigns the forum taxonomy when adding a topic from within a forum.
*/
function forum_node_presave(EntityInterface $node) {
if (\Drupal::service('forum_manager')
->checkNodeType($node)) {
// Make sure all fields are set properly:
$node->icon = !empty($node->icon) ? $node->icon : '';
if (!$node->taxonomy_forums
->isEmpty()) {
$node->forum_tid = $node->taxonomy_forums->target_id;
// Only do a shadow copy check if this is not a new node.
if (!$node
->isNew()) {
$old_tid = \Drupal::service('forum.index_storage')
->getOriginalTermId($node);
if ($old_tid && isset($node->forum_tid) && $node->forum_tid != $old_tid && !empty($node->shadow)) {
// A shadow copy needs to be created. Retain new term and add old term.
$node->taxonomy_forums[count($node->taxonomy_forums)] = [
'target_id' => $old_tid,
];
}
}
}
}
}
/**
* Implements hook_ENTITY_TYPE_update() for node entities.
*/
function forum_node_update(EntityInterface $node) {
if (\Drupal::service('forum_manager')
->checkNodeType($node)) {
// If this is not a new revision and does exist, update the forum record,
// otherwise insert a new one.
/** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
$forum_index_storage = \Drupal::service('forum.index_storage');
if ($node
->getRevisionId() == $node->original
->getRevisionId() && $forum_index_storage
->getOriginalTermId($node)) {
if (!empty($node->forum_tid)) {
$forum_index_storage
->update($node);
}
else {
$forum_index_storage
->delete($node);
}
}
else {
if (!empty($node->forum_tid)) {
$forum_index_storage
->create($node);
}
}
// If the node has a shadow forum topic, update the record for this
// revision.
if (!empty($node->shadow)) {
$forum_index_storage
->deleteRevision($node);
$forum_index_storage
->create($node);
}
// If the node is published, update the forum index.
if ($node
->isPublished()) {
$forum_index_storage
->deleteIndex($node);
$forum_index_storage
->createIndex($node);
}
else {
$forum_index_storage
->deleteIndex($node);
}
}
}
/**
* Implements hook_ENTITY_TYPE_insert() for node entities.
*/
function forum_node_insert(EntityInterface $node) {
if (\Drupal::service('forum_manager')
->checkNodeType($node)) {
/** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
$forum_index_storage = \Drupal::service('forum.index_storage');
if (!empty($node->forum_tid)) {
$forum_index_storage
->create($node);
}
// If the node is published, update the forum index.
if ($node
->isPublished()) {
$forum_index_storage
->createIndex($node);
}
}
}
/**
* Implements hook_ENTITY_TYPE_predelete() for node entities.
*/
function forum_node_predelete(EntityInterface $node) {
if (\Drupal::service('forum_manager')
->checkNodeType($node)) {
/** @var \Drupal\forum\ForumIndexStorageInterface $forum_index_storage */
$forum_index_storage = \Drupal::service('forum.index_storage');
$forum_index_storage
->delete($node);
$forum_index_storage
->deleteIndex($node);
}
}
/**
* Implements hook_ENTITY_TYPE_storage_load() for node entities.
*/
function forum_node_storage_load($nodes) {
$node_vids = [];
foreach ($nodes as $node) {
if (\Drupal::service('forum_manager')
->checkNodeType($node)) {
$node_vids[] = $node
->getRevisionId();
}
}
if (!empty($node_vids)) {
$result = \Drupal::service('forum.index_storage')
->read($node_vids);
foreach ($result as $record) {
$nodes[$record->nid]->forum_tid = $record->tid;
}
}
}
/**
* Implements hook_ENTITY_TYPE_update() for comment entities.
*/
function forum_comment_update(CommentInterface $comment) {
if ($comment
->getCommentedEntityTypeId() == 'node') {
\Drupal::service('forum.index_storage')
->updateIndex($comment
->getCommentedEntity());
}
}
/**
* Implements hook_ENTITY_TYPE_insert() for comment entities.
*/
function forum_comment_insert(CommentInterface $comment) {
if ($comment
->getCommentedEntityTypeId() == 'node') {
\Drupal::service('forum.index_storage')
->updateIndex($comment
->getCommentedEntity());
}
}
/**
* Implements hook_ENTITY_TYPE_delete() for comment entities.
*/
function forum_comment_delete(CommentInterface $comment) {
if ($comment
->getCommentedEntityTypeId() == 'node') {
\Drupal::service('forum.index_storage')
->updateIndex($comment
->getCommentedEntity());
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter() for \Drupal\taxonomy\VocabularyForm.
*/
function forum_form_taxonomy_vocabulary_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$vid = \Drupal::config('forum.settings')
->get('vocabulary');
$vocabulary = $form_state
->getFormObject()
->getEntity();
if ($vid == $vocabulary
->id()) {
$form['help_forum_vocab'] = [
'#markup' => t('This is the designated forum vocabulary. Some of the normal vocabulary options have been removed.'),
'#weight' => -1,
];
// Forum's vocabulary always has single hierarchy. Forums and containers
// have only one parent or no parent for root items. By default this value
// is 0.
$form['hierarchy']['#value'] = VocabularyInterface::HIERARCHY_SINGLE;
// Do not allow to delete forum's vocabulary.
$form['actions']['delete']['#access'] = FALSE;
// Do not allow to change a vid of forum's vocabulary.
$form['vid']['#disabled'] = TRUE;
}
}
/**
* Implements hook_form_FORM_ID_alter() for \Drupal\taxonomy\TermForm.
*/
function forum_form_taxonomy_term_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$vid = \Drupal::config('forum.settings')
->get('vocabulary');
if (isset($form['vid']['#value']) && $form['vid']['#value'] == $vid) {
// Hide multiple parents select from forum terms.
$form['relations']['parent']['#access'] = FALSE;
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm.
*/
function forum_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$node = $form_state
->getFormObject()
->getEntity();
if (isset($node->taxonomy_forums) && !$node
->isNew()) {
$forum_terms = $node->taxonomy_forums;
// If editing, give option to leave shadows.
$shadow = count($forum_terms) > 1;
$form['shadow'] = [
'#type' => 'checkbox',
'#title' => t('Leave shadow copy'),
'#default_value' => $shadow,
'#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'),
];
$form['forum_tid'] = [
'#type' => 'value',
'#value' => $node->forum_tid,
];
}
if (isset($form['taxonomy_forums'])) {
$widget =& $form['taxonomy_forums']['widget'];
$widget['#multiple'] = FALSE;
if (empty($widget['#default_value'])) {
// If there is no default forum already selected, try to get the forum
// ID from the URL (e.g., if we are on a page like node/add/forum/2, we
// expect "2" to be the ID of the forum that was requested).
$requested_forum_id = \Drupal::request()->query
->get('forum_id');
$widget['#default_value'] = is_numeric($requested_forum_id) ? $requested_forum_id : '';
}
}
}
/**
* Implements hook_preprocess_HOOK() for block templates.
*/
function forum_preprocess_block(&$variables) {
if ($variables['configuration']['provider'] == 'forum') {
$variables['attributes']['role'] = 'navigation';
}
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function forum_theme_suggestions_forums(array $variables) {
$suggestions = [];
$tid = $variables['term']
->id();
// Provide separate template suggestions based on what's being output. Topic
// ID is also accounted for. Check both variables to be safe then the inverse.
// Forums with topic IDs take precedence.
if ($variables['forums'] && !$variables['topics']) {
$suggestions[] = 'forums__containers';
$suggestions[] = 'forums__' . $tid;
$suggestions[] = 'forums__containers__' . $tid;
}
elseif (!$variables['forums'] && $variables['topics']) {
$suggestions[] = 'forums__topics';
$suggestions[] = 'forums__' . $tid;
$suggestions[] = 'forums__topics__' . $tid;
}
else {
$suggestions[] = 'forums__' . $tid;
}
return $suggestions;
}
/**
* Prepares variables for forums templates.
*
* Default template: forums.html.twig.
*
* @param array $variables
* An array containing the following elements:
* - forums: An array of all forum objects to display for the given taxonomy
* term ID. If tid = 0 then all the top-level forums are displayed.
* - topics: An array of all the topics in the current forum.
* - parents: An array of taxonomy term objects that are ancestors of the
* current term ID.
* - term: Taxonomy term of the current forum.
* - sortby: One of the following integers indicating the sort criteria:
* - 1: Date - newest first.
* - 2: Date - oldest first.
* - 3: Posts with the most comments first.
* - 4: Posts with the least comments first.
* - forum_per_page: The maximum number of topics to display per page.
*/
function template_preprocess_forums(&$variables) {
$variables['tid'] = $variables['term']
->id();
if ($variables['forums_defined'] = count($variables['forums']) || count($variables['parents'])) {
if (!empty($variables['forums'])) {
$variables['forums'] = [
'#theme' => 'forum_list',
'#forums' => $variables['forums'],
'#parents' => $variables['parents'],
'#tid' => $variables['tid'],
];
}
if ($variables['term'] && empty($variables['term']->forum_container->value) && !empty($variables['topics'])) {
$forum_topic_list_header = $variables['header'];
$table = [
'#theme' => 'table__forum_topic_list',
'#responsive' => FALSE,
'#attributes' => [
'id' => 'forum-topic-' . $variables['tid'],
],
'#header' => [],
'#rows' => [],
];
if (!empty($forum_topic_list_header)) {
$table['#header'] = $forum_topic_list_header;
}
/** @var \Drupal\node\NodeInterface $topic */
foreach ($variables['topics'] as $id => $topic) {
$variables['topics'][$id]->icon = [
'#theme' => 'forum_icon',
'#new_posts' => $topic->new,
'#num_posts' => $topic->comment_count,
'#comment_mode' => $topic->comment_mode,
'#sticky' => $topic
->isSticky(),
'#first_new' => $topic->first_new,
];
// We keep the actual tid in forum table, if it's different from the
// current tid then it means the topic appears in two forums, one of
// them is a shadow copy.
if ($variables['tid'] != $topic->forum_tid) {
$variables['topics'][$id]->moved = TRUE;
$variables['topics'][$id]->title = $topic
->getTitle();
$variables['topics'][$id]->message = Link::fromTextAndUrl(t('This topic has been moved'), Url::fromRoute('forum.page', [
'taxonomy_term' => $topic->forum_tid,
]))
->toString();
}
else {
$variables['topics'][$id]->moved = FALSE;
$variables['topics'][$id]->title_link = Link::fromTextAndUrl($topic
->getTitle(), $topic
->toUrl())
->toString();
$variables['topics'][$id]->message = '';
}
$forum_submitted = [
'#theme' => 'forum_submitted',
'#topic' => (object) [
'uid' => $topic
->getOwnerId(),
'name' => $topic
->getOwner()
->getDisplayName(),
'created' => $topic
->getCreatedTime(),
],
];
$variables['topics'][$id]->submitted = \Drupal::service('renderer')
->render($forum_submitted);
$forum_submitted = [
'#theme' => 'forum_submitted',
'#topic' => isset($topic->last_reply) ? $topic->last_reply : NULL,
];
$variables['topics'][$id]->last_reply = \Drupal::service('renderer')
->render($forum_submitted);
$variables['topics'][$id]->new_text = '';
$variables['topics'][$id]->new_url = '';
if ($topic->new_replies) {
$page_number = \Drupal::entityTypeManager()
->getStorage('comment')
->getNewCommentPageNumber($topic->comment_count, $topic->new_replies, $topic, 'comment_forum');
$query = $page_number ? [
'page' => $page_number,
] : NULL;
$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(),
]);
$variables['topics'][$id]->new_url = Url::fromRoute('entity.node.canonical', [
'node' => $topic
->id(),
], [
'query' => $query,
'fragment' => 'new',
])
->toString();
}
// Build table rows from topics.
$row = [];
$row[] = [
'data' => [
$topic->icon,
[
'#markup' => '<div class="forum__title"><div>' . $topic->title_link . '</div><div>' . $topic->submitted . '</div></div>',
],
],
'class' => [
'forum__topic',
],
];
if ($topic->moved) {
$row[] = [
'data' => $topic->message,
'colspan' => '2',
];
}
else {
$new_replies = '';
if ($topic->new_replies) {
$new_replies = '<br /><a href="' . $topic->new_url . '">' . $topic->new_text . '</a>';
}
$row[] = [
'data' => [
[
'#prefix' => $topic->comment_count,
'#markup' => $new_replies,
],
],
'class' => [
'forum__replies',
],
];
$row[] = [
'data' => $topic->last_reply,
'class' => [
'forum__last-reply',
],
];
}
$table['#rows'][] = $row;
}
$variables['topics_original'] = $variables['topics'];
$variables['topics'] = $table;
$variables['topics_pager'] = [
'#type' => 'pager',
];
}
}
}
/**
* Prepares variables for forum list templates.
*
* Default template: forum-list.html.twig.
*
* @param array $variables
* An array containing the following elements:
* - forums: An array of all forum objects to display for the given taxonomy
* term ID. If tid = 0 then all the top-level forums are displayed.
* - parents: An array of taxonomy term objects that are ancestors of the
* current term ID.
* - tid: Taxonomy term ID of the current forum.
*/
function template_preprocess_forum_list(&$variables) {
$user = \Drupal::currentUser();
$row = 0;
// Sanitize each forum so that the template can safely print the data.
foreach ($variables['forums'] as $id => $forum) {
$variables['forums'][$id]->description = [
'#markup' => $forum->description->value,
];
$variables['forums'][$id]->link = forum_uri($forum);
$variables['forums'][$id]->name = $forum
->label();
$variables['forums'][$id]->is_container = !empty($forum->forum_container->value);
$variables['forums'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
$row++;
$variables['forums'][$id]->new_text = '';
$variables['forums'][$id]->new_url = '';
$variables['forums'][$id]->new_topics = 0;
$variables['forums'][$id]->old_topics = $forum->num_topics;
$variables['forums'][$id]->icon_class = 'default';
$variables['forums'][$id]->icon_title = t('No new posts');
if ($user
->isAuthenticated()) {
$variables['forums'][$id]->new_topics = \Drupal::service('forum_manager')
->unreadTopics($forum
->id(), $user
->id());
if ($variables['forums'][$id]->new_topics) {
$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(),
]);
$variables['forums'][$id]->new_url = Url::fromRoute('forum.page', [
'taxonomy_term' => $forum
->id(),
], [
'fragment' => 'new',
])
->toString();
$variables['forums'][$id]->icon_class = 'new';
$variables['forums'][$id]->icon_title = t('New posts');
}
$variables['forums'][$id]->old_topics = $forum->num_topics - $variables['forums'][$id]->new_topics;
}
$forum_submitted = [
'#theme' => 'forum_submitted',
'#topic' => $forum->last_post,
];
$variables['forums'][$id]->last_reply = \Drupal::service('renderer')
->render($forum_submitted);
}
$variables['pager'] = [
'#type' => 'pager',
];
// Give meaning to $tid for themers. $tid actually stands for term ID.
$variables['forum_id'] = $variables['tid'];
unset($variables['tid']);
}
/**
* Prepares variables for forum icon templates.
*
* Default template: forum-icon.html.twig.
*
* @param array $variables
* An array containing the following elements:
* - new_posts: Indicates whether or not the topic contains new posts.
* - num_posts: The total number of posts in all topics.
* - comment_mode: An integer indicating whether comments are open, closed,
* or hidden.
* - sticky: Indicates whether the topic is sticky.
* - first_new: Indicates whether this is the first topic with new posts.
*/
function template_preprocess_forum_icon(&$variables) {
$variables['hot_threshold'] = \Drupal::config('forum.settings')
->get('topics.hot_threshold');
if ($variables['num_posts'] > $variables['hot_threshold']) {
$variables['icon_status'] = $variables['new_posts'] ? 'hot-new' : 'hot';
$variables['icon_title'] = $variables['new_posts'] ? t('Hot topic, new comments') : t('Hot topic');
}
else {
$variables['icon_status'] = $variables['new_posts'] ? 'new' : 'default';
$variables['icon_title'] = $variables['new_posts'] ? t('New comments') : t('Normal topic');
}
if ($variables['comment_mode'] == CommentItemInterface::CLOSED || $variables['comment_mode'] == CommentItemInterface::HIDDEN) {
$variables['icon_status'] = 'closed';
$variables['icon_title'] = t('Closed topic');
}
if ($variables['sticky'] == 1) {
$variables['icon_status'] = 'sticky';
$variables['icon_title'] = t('Sticky topic');
}
$variables['attributes']['title'] = $variables['icon_title'];
}
/**
* Prepares variables for forum submission information templates.
*
* The submission information will be displayed in the forum list and topic
* list.
*
* Default template: forum-submitted.html.twig.
*
* @param array $variables
* An array containing the following elements:
* - topic: The topic object.
*/
function template_preprocess_forum_submitted(&$variables) {
$variables['author'] = '';
if (isset($variables['topic']->uid)) {
$username = [
'#theme' => 'username',
'#account' => User::load($variables['topic']->uid),
];
$variables['author'] = \Drupal::service('renderer')
->render($username);
}
$variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')
->formatTimeDiffSince($variables['topic']->created) : '';
}