Chris@0: ' . t('About') . ''; Chris@0: $output .= '

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

'; Chris@18: $output .= '

' . t('The Forum module adds and uses a content type called Forum topic. For background information on content types, see the Node module help page.', [':node_help' => Url::fromRoute('help.page', ['name' => 'node'])->toString()]) . '

'; Chris@0: $output .= '

' . t('A forum is represented by a hierarchical structure, consisting of:'); Chris@0: $output .= '

'; Chris@0: $output .= '

'; Chris@0: $output .= '

' . t('For more information, see the online documentation for the Forum module.', [':forum' => 'https://www.drupal.org/documentation/modules/forum']) . '

'; Chris@0: $output .= '

' . t('Uses') . '

'; Chris@0: $output .= '
'; Chris@0: $output .= '
' . t('Setting up the forum structure') . '
'; Chris@18: $output .= '
' . t('Visit the Forums page to set up containers and forums to hold your discussion topics.', [':forums' => Url::fromRoute('forum.overview')->toString()]) . '
'; Chris@0: $output .= '
' . t('Starting a discussion') . '
'; Chris@18: $output .= '
' . t('The Forum topic link on the Add content 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()]) . '
'; Chris@0: $output .= '
' . t('Navigating in the forum') . '
'; Chris@18: $output .= '
' . t('Enabling the Forum module provides a default Forums menu item in the Tools menu that links to the Forums page.', [':forums' => Url::fromRoute('forum.index')->toString()]) . '
'; Chris@0: $output .= '
' . t('Moving forum topics') . '
'; Chris@0: $output .= '
' . 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 Leave shadow copy option creates a link in the original forum pointing to the new location.') . '
'; Chris@0: $output .= '
' . t('Locking and disabling comments') . '
'; Chris@0: $output .= '
' . t('Selecting Closed under Comment settings while editing a forum topic will lock (prevent new comments on) the thread. Selecting Hidden under Comment settings while editing a forum topic will hide all existing comments on the thread, and prevent new ones.') . '
'; Chris@0: $output .= '
'; Chris@0: return $output; Chris@0: Chris@0: case 'forum.overview': Chris@0: $output = '

' . t('Forums contain forum topics. Use containers to group related forums.') . '

'; Chris@0: $more_help_link = [ Chris@0: '#type' => 'link', Chris@0: '#url' => Url::fromRoute('help.page', ['name' => 'forum']), Chris@0: '#title' => t('More help'), Chris@0: '#attributes' => [ Chris@0: 'class' => ['icon-help'], Chris@0: ], Chris@0: ]; Chris@0: $container = [ Chris@0: '#theme' => 'container', Chris@0: '#children' => $more_help_link, Chris@0: '#attributes' => [ Chris@0: 'class' => ['more-link'], Chris@0: ], Chris@0: ]; Chris@0: $output .= \Drupal::service('renderer')->renderPlain($container); Chris@0: return $output; Chris@0: Chris@0: case 'forum.add_container': Chris@0: return '

' . t('Use containers to group related forums.') . '

'; Chris@0: Chris@0: case 'forum.add_forum': Chris@0: return '

' . t('A forum holds related forum topics.') . '

'; Chris@0: Chris@0: case 'forum.settings': Chris@18: return '

' . t('Adjust the display of your forum topics. Organize the forums on the forum structure page.', [':forum-structure' => Url::fromRoute('forum.overview')->toString()]) . '

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