Newer
Older
Dries Buytaert
committed
* Provides discussion forums.
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language;
use Drupal\taxonomy\Entity\Term;
use Drupal\field\Field;
use Drupal\node\NodeInterface;
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_help().
Dries Buytaert
committed
*/
Gábor Hojtsy
committed
function forum_help($path, $arg) {
switch ($path) {
Dries Buytaert
committed
case 'admin/help#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. Forums are useful because they allow community members to discuss topics with one another while ensuring those conversations are archived for later reference. In a forum, users post topics and threads in nested hierarchies, allowing discussions to be categorized and grouped. The forum hierarchy consists of:') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('Optional containers (for example, <em>Support</em>), which can hold:') . '</li>';
$output .= '<ul><li>' . t('Forums (for example, <em>Installing Drupal</em>), which can hold:') . '</li>';
$output .= '<ul><li>' . t('Forum topics submitted by users (for example, <em>How to start a Drupal 6 Multisite</em>), which start discussions and are starting points for:') . '</li>';
$output .= '<ul><li>' . t('Threaded comments submitted by users (for example, <em>You have these options...</em>).') . '</li>';
$output .= '</ul>';
$output .= '</ul>';
$output .= '</ul>';
$output .= '</ul>';
$output .= '<p>' . t('For more information, see the online handbook entry for <a href="@forum">Forum module</a>.', array('@forum' => 'http://drupal.org/documentation/modules/forum')) . '</p>';
Angie Byron
committed
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Setting up 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.', array('@forums' => url('admin/structure/forum'))) . '</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 new content</a> page creates the first post of a new threaded discussion, or thread.', array('@create-topic' => url('node/add/forum'), '@content-add' => url('node/add'))) . '</dd>';
Dries Buytaert
committed
$output .= '<dt>' . t('Forum navigation') . '</dt>';
$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>.', array('@forums' => url('forum'))) . '</dd>';
Angie Byron
committed
$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>';
Angie Byron
committed
$output .= '</dl>';
Dries Buytaert
committed
return $output;
Dries Buytaert
committed
case 'admin/structure/forum':
Angie Byron
committed
$output = '<p>' . t('Forums contain forum topics. Use containers to group related forums.') . '</p>';
$more_help_link = array(
'#type' => 'link',
'#href' => 'admin/help/forum',
'#title' => t('More help'),
);
$container = array(
'#theme' => 'container',
'#children' => drupal_render($more_help_link),
'#attributes' => array(
'class' => array('more-help-link'),
),
);
Angie Byron
committed
$output .= drupal_render($container);
Angie Byron
committed
return $output;
Dries Buytaert
committed
case 'admin/structure/forum/add/container':
Angie Byron
committed
return '<p>' . t('Use containers to group related forums.') . '</p>';
Dries Buytaert
committed
case 'admin/structure/forum/add/forum':
Angie Byron
committed
return '<p>' . t('A forum holds related forum topics.') . '</p>';
Dries Buytaert
committed
case 'admin/structure/forum/settings':
Angie Byron
committed
return '<p>' . t('Adjust the display of your forum topics. Organize the forums on the <a href="@forum-structure">forum structure page</a>.', array('@forum-structure' => url('admin/structure/forum'))) . '</p>';
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_theme().
Dries Buytaert
committed
*/
function forum_theme() {
return array(
Dries Buytaert
committed
'forums' => array(
'template' => 'forums',
'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'term' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
Dries Buytaert
committed
),
'forum_list' => array(
'template' => 'forum-list',
'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
Dries Buytaert
committed
),
'forum_topic_list' => array(
'template' => 'forum-topic-list',
'variables' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
Dries Buytaert
committed
),
'forum_icon' => array(
'template' => 'forum-icon',
'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0, 'first_new' => FALSE),
Dries Buytaert
committed
),
Dries Buytaert
committed
'forum_submitted' => array(
'template' => 'forum-submitted',
'variables' => array('topic' => NULL),
),
Dries Buytaert
committed
'forum_form' => array(
'render element' => 'form',
Dries Buytaert
committed
),
Dries Buytaert
committed
);
}
Dries Buytaert
committed
* Implements hook_menu().
Dries Buytaert
committed
function forum_menu() {
$items['forum'] = array(
'title' => 'Forums',
'route_name' => 'forum.index',
Dries Buytaert
committed
);
$items['forum/%forum'] = array(
Angie Byron
committed
'title' => 'Forums',
'title callback' => 'entity_page_label',
'title arguments' => array(1),
'route_name' => 'forum.page',
Angie Byron
committed
);
Dries Buytaert
committed
$items['admin/structure/forum'] = array(
'title' => 'Forums',
Angie Byron
committed
'description' => 'Control forum hierarchy settings.',
'route_name' => 'forum.overview',
Dries Buytaert
committed
);
Angie Byron
committed
$items['admin/structure/forum/edit/container/%taxonomy_term'] = array(
'title' => 'Edit container',
'route_name' => 'forum.edit_container',
Dries Buytaert
committed
);
Angie Byron
committed
$items['admin/structure/forum/edit/forum/%taxonomy_term'] = array(
'title' => 'Edit forum',
'route_name' => 'forum.edit_forum',
Dries Buytaert
committed
);
Angie Byron
committed
$items['admin/structure/forum/delete/forum/%taxonomy_term'] = array(
'title' => 'Delete forum',
'route_name' => 'forum.delete',
Angie Byron
committed
);
Dries Buytaert
committed
return $items;
}
Dries Buytaert
committed
/**
* Implements hook_menu_local_tasks().
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_menu_local_tasks(&$data, $route_name) {
$user = \Drupal::currentUser();
Dries Buytaert
committed
Angie Byron
committed
// Add action link to 'node/add/forum' on 'forum' sub-pages.
Angie Byron
committed
if (in_array($route_name, array('forum.index', 'forum.page'))) {
$request = \Drupal::request();
$forum_term = $request->attributes->get('taxonomy_term');
$vid = \Drupal::config('forum.settings')->get('vocabulary');
$links = array();
// Loop through all bundles for forum taxonomy vocabulary field.
$field = Field::fieldInfo()->getField('node', 'taxonomy_forums');
Alex Pott
committed
foreach ($field->getBundles() as $type) {
if (\Drupal::entityManager()->getAccessController('node')->createAccess($type)) {
$links[$type] = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('Add new @node_type', array('@node_type' => entity_load('node_type', $type)->label())),
'href' => 'node/add/' . $type,
),
);
if ($forum_term && $forum_term->bundle() == $vid) {
// We are viewing a forum term (specific forum), append the tid to the
// url.
$links[$type]['#link']['localized_options']['query']['forum_id'] = $forum_term->id();
Dries Buytaert
committed
}
}
}
if (empty($links)) {
// Authenticated user does not have access to create new topics.
if ($user->isAuthenticated()) {
$links['disallowed'] = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('You are not allowed to post new content in the forum.'),
),
);
}
// Anonymous user does not have access to create new topics.
else {
$links['login'] = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('<a href="@login">Log in</a> to post new content in the forum.', array(
'@login' => url('user/login', array('query' => drupal_get_destination())),
)),
'localized_options' => array('html' => TRUE),
),
);
Dries Buytaert
committed
}
}
$data['actions'] += $links;
Dries Buytaert
committed
}
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Implements hook_entity_info().
*/
function forum_entity_info(&$info) {
// Register forum specific form controllers.
$info['taxonomy_term']['controllers']['form']['forum'] = 'Drupal\forum\Form\ForumFormController';
$info['taxonomy_term']['controllers']['form']['container'] = 'Drupal\forum\Form\ContainerFormController';
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_entity_bundle_info_alter().
Dries Buytaert
committed
*/
Dries Buytaert
committed
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')) {
Dries Buytaert
committed
if (isset($bundles['taxonomy_term'][$vid])) {
$bundles['taxonomy_term'][$vid]['uri_callback'] = 'forum_uri';
Dries Buytaert
committed
}
}
}
/**
Dries Buytaert
committed
* Entity URI callback used in forum_entity_bundle_info_alter().
Dries Buytaert
committed
*/
function forum_uri($forum) {
return array(
'path' => 'forum/' . $forum->id(),
Dries Buytaert
committed
);
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_node_validate().
*
Jennifer Hodgdon
committed
* Checks in particular that the node is assigned only a "leaf" term in the
* forum taxonomy.
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_validate(EntityInterface $node, $form, &$form_state) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
Dries Buytaert
committed
// vocabulary is selected, not a "container" term.
catch
committed
if (!$node->taxonomy_forums->isEmpty()) {
Dries Buytaert
committed
// Extract the node's proper topic ID.
catch
committed
foreach ($node->taxonomy_forums as $delta => $item) {
Angie Byron
committed
// If no term was selected (e.g. when no terms exist yet), remove the
// item.
catch
committed
if (empty($item->target_id)) {
unset($node->taxonomy_forums[$delta]);
Angie Byron
committed
continue;
}
catch
committed
$term = $item->entity;
Dries Buytaert
committed
if (!$term) {
Angie Byron
committed
form_set_error('taxonomy_forums', $form_state, t('Select a forum.'));
Dries Buytaert
committed
continue;
}
catch
committed
$used = \Drupal::entityQuery('taxonomy_term')
->condition('tid', $term->id())
->condition('vid', $term->bundle())
->range(0, 1)
->count()
->execute();
if ($used && !empty($term->forum_container->value)) {
Angie Byron
committed
form_set_error('taxonomy_forums', $form_state, t('The item %forum is a forum container, not a forum. Select one of the forums below instead.', array('%forum' => $term->label())));
Dries Buytaert
committed
}
}
Dries Buytaert
committed
}
}
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_node_presave().
Dries Buytaert
committed
*
Jennifer Hodgdon
committed
* Assigns the forum taxonomy when adding a topic from within a forum.
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_presave(EntityInterface $node) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
Dries Buytaert
committed
// Make sure all fields are set properly:
$node->icon = !empty($node->icon) ? $node->icon : '';
catch
committed
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 = db_query_range("SELECT f.tid FROM {forum} f INNER JOIN {node} n ON f.vid = n.vid WHERE n.nid = :nid ORDER BY f.vid DESC", 0, 1, array(':nid' => $node->id()))->fetchField();
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.
catch
committed
$node->taxonomy_forums[count($node->taxonomy_forums)] = array('target_id' => $old_tid);
}
Dries Buytaert
committed
}
}
}
}
Gábor Hojtsy
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_node_update().
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_update(EntityInterface $node) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
Angie Byron
committed
// If this is not a new revision and does exist, update the forum record,
// otherwise insert a new one.
if ($node->getRevisionId() == $node->original->getRevisionId() && db_query('SELECT tid FROM {forum} WHERE nid=:nid', array(':nid' => $node->id()))->fetchField()) {
Angie Byron
committed
if (!empty($node->forum_tid)) {
Dries Buytaert
committed
db_update('forum')
Angie Byron
committed
->fields(array('tid' => $node->forum_tid))
->condition('vid', $node->getRevisionId())
Dries Buytaert
committed
->execute();
Dries Buytaert
committed
}
// The node is removed from the forum.
else {
Dries Buytaert
committed
db_delete('forum')
->condition('nid', $node->id())
Dries Buytaert
committed
->execute();
Dries Buytaert
committed
}
}
else {
Angie Byron
committed
if (!empty($node->forum_tid)) {
Dries Buytaert
committed
db_insert('forum')
->fields(array(
Angie Byron
committed
'tid' => $node->forum_tid,
'vid' => $node->getRevisionId(),
'nid' => $node->id(),
Dries Buytaert
committed
))
->execute();
Gábor Hojtsy
committed
}
Dries Buytaert
committed
}
Angie Byron
committed
// If the node has a shadow forum topic, update the record for this
// revision.
Dries Buytaert
committed
if (!empty($node->shadow)) {
Angie Byron
committed
db_delete('forum')
->condition('nid', $node->id())
->condition('vid', $node->getRevisionId())
Angie Byron
committed
->execute();
db_insert('forum')
->fields(array(
'nid' => $node->id(),
'vid' => $node->getRevisionId(),
Angie Byron
committed
'tid' => $node->forum_tid,
))
->execute();
}
// If the node is published, update the forum index.
if ($node->isPublished()) {
db_delete('forum_index')->condition('nid', $node->id())->execute();
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($node->getTranslationLanguages() as $langcode => $language) {
$translation = $node->getTranslation($langcode);
foreach ($translation->taxonomy_forums as $item) {
$query->values(array(
'nid' => $node->id(),
'title' => $translation->label(),
'tid' => $item->target_id,
'sticky' => (int) $node->isSticky(),
'created' => $node->getCreatedTime(),
'comment_count' => 0,
'last_comment_timestamp' => $node->getCreatedTime(),
));
}
}
$query->execute();
// The logic for determining last_comment_count is fairly complex, so
// update the index too.
\Drupal::service('forum_manager')->updateIndex($node->id());
}
// When a forum node is unpublished, remove it from the forum_index table.
else {
db_delete('forum_index')->condition('nid', $node->id())->execute();
}
Dries Buytaert
committed
}
}
Gábor Hojtsy
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_node_insert().
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_insert(EntityInterface $node) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
Angie Byron
committed
if (!empty($node->forum_tid)) {
db_insert('forum')
Dries Buytaert
committed
->fields(array(
Angie Byron
committed
'tid' => $node->forum_tid,
'vid' => $node->getRevisionId(),
'nid' => $node->id(),
Dries Buytaert
committed
))
->execute();
Dries Buytaert
committed
}
// If the node is published, update the forum index.
if ($node->isPublished()) {
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($node->getTranslationLanguages() as $langcode => $language) {
$translation = $node->getTranslation($langcode);
$query->values(array(
'nid' => $node->id(),
'title' => $translation->label(),
'tid' => $translation->taxonomy_forums->target_id,
'sticky' => (int) $node->isSticky(),
'created' => $node->getCreatedTime(),
'comment_count' => 0,
'last_comment_timestamp' => $node->getCreatedTime(),
));
}
$query->execute();
}
Dries Buytaert
committed
}
}
Gábor Hojtsy
committed
Dries Buytaert
committed
/**
catch
committed
* Implements hook_node_predelete().
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_predelete(EntityInterface $node) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
Dries Buytaert
committed
db_delete('forum')
->condition('nid', $node->id())
Dries Buytaert
committed
->execute();
Angie Byron
committed
db_delete('forum_index')
->condition('nid', $node->id())
Angie Byron
committed
->execute();
Dries Buytaert
committed
}
Dries Buytaert
committed
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_node_load().
Dries Buytaert
committed
*/
Angie Byron
committed
function forum_node_load($nodes) {
$node_vids = array();
foreach ($nodes as $node) {
if (\Drupal::service('forum_manager')->checkNodeType($node)) {
$node_vids[] = $node->getRevisionId();
}
}
if (!empty($node_vids)) {
Angie Byron
committed
$query = db_select('forum', 'f');
$query
->fields('f', array('nid', 'tid'))
->condition('f.vid', $node_vids);
$result = $query->execute();
foreach ($result as $record) {
$nodes[$record->nid]->forum_tid = $record->tid;
}
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implements hook_permission().
Dries Buytaert
committed
*/
function forum_permission() {
$perms = array(
Angie Byron
committed
'administer forums' => array(
'title' => t('Administer forums'),
),
);
return $perms;
Angie Byron
committed
/**
Dries Buytaert
committed
* Implements hook_comment_publish().
Angie Byron
committed
*
Jennifer Hodgdon
committed
* This actually handles the insertion and update of published nodes since
* $comment->save() calls hook_comment_publish() for all published comments.
Angie Byron
committed
*/
function forum_comment_publish($comment) {
if ($comment->entity_type->value == 'node') {
\Drupal::service('forum_manager')->updateIndex($comment->entity_id->value);
}
Angie Byron
committed
}
/**
Dries Buytaert
committed
* Implements hook_comment_update().
Angie Byron
committed
*
Jennifer Hodgdon
committed
* The Comment module doesn't call hook_comment_unpublish() when saving
* individual comments, so we need to check for those here.
Angie Byron
committed
*/
function forum_comment_update($comment) {
// $comment->save() calls hook_comment_publish() for all published comments,
Jennifer Hodgdon
committed
// so we need to handle all other values here.
if (!$comment->status->value && $comment->entity_type->value == 'node') {
\Drupal::service('forum_manager')->updateIndex($comment->entity_id->value);
Angie Byron
committed
}
}
/**
Dries Buytaert
committed
* Implements hook_comment_unpublish().
Angie Byron
committed
*/
function forum_comment_unpublish($comment) {
if ($comment->entity_type->value == 'node') {
\Drupal::service('forum_manager')->updateIndex($comment->entity_id->value);
}
Angie Byron
committed
}
/**
Dries Buytaert
committed
* Implements hook_comment_delete().
Angie Byron
committed
*/
function forum_comment_delete($comment) {
if ($comment->entity_type->value == 'node') {
\Drupal::service('forum_manager')->updateIndex($comment->entity_id->value);
}
Angie Byron
committed
}
Gerhard Killesreiter
committed
/**
* Implements hook_form_BASE_FORM_ID_alter().
Gerhard Killesreiter
committed
*/
function forum_form_taxonomy_vocabulary_form_alter(&$form, &$form_state, $form_id) {
$vid = \Drupal::config('forum.settings')->get('vocabulary');
$vocabulary = $form_state['controller']->getEntity();
if ($vid == $vocabulary->id()) {
$form['help_forum_vocab'] = array(
'#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'] = TAXONOMY_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 taxonomy_term_form().
*/
function forum_form_taxonomy_term_form_alter(&$form, &$form_state, $form_id) {
$vid = \Drupal::config('forum.settings')->get('vocabulary');
if (isset($form['vid']['#value']) && $form['vid']['#value'] == $vid) {
Gábor Hojtsy
committed
// Hide multiple parents select from forum terms.
$form['relations']['parent']['#access'] = FALSE;
Gábor Hojtsy
committed
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter() for node_form().
*/
function forum_form_node_form_alter(&$form, &$form_state, $form_id) {
$node = $form_state['controller']->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'] = array(
'#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'] = array('#type' => 'value', '#value' => $node->forum_tid);
}
if (isset($form['taxonomy_forums'])) {
Angie Byron
committed
$widget =& $form['taxonomy_forums']['widget'];
Gábor Hojtsy
committed
// Make the vocabulary required for 'real' forum-nodes.
Angie Byron
committed
$widget['#required'] = TRUE;
$widget['#multiple'] = FALSE;
if (empty($widget['#default_value'])) {
Dries Buytaert
committed
// 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).
Alex Pott
committed
$requested_forum_id = \Drupal::request()->query->get('forum_id');
Angie Byron
committed
$widget['#default_value'] = is_numeric($requested_forum_id) ? $requested_forum_id : '';
Dries Buytaert
committed
}
Gábor Hojtsy
committed
}
Gerhard Killesreiter
committed
}
/**
Angie Byron
committed
* Implements hook_preprocess_HOOK() for block templates.
*/
function forum_preprocess_block(&$variables) {
if ($variables['configuration']['module'] == 'forum') {
Dries Buytaert
committed
$variables['attributes']['role'] = 'navigation';
}
}
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
/**
* Implements hook_theme_suggestions_HOOK().
*/
function forum_theme_suggestions_forums(array $variables) {
$suggestions = array();
$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
Jennifer Hodgdon
committed
* 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.
Jennifer Hodgdon
committed
* - 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.
Dries Buytaert
committed
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'] = array(
'#theme' => 'forum_list',
'#forums' => $variables['forums'],
'#parents' => $variables['parents'],
'#tid' => $variables['tid'],
);
}
else {
$variables['forums'] = array();
}
if ($variables['term'] && empty($variables['term']->forum_container->value)) {
$variables['topics'] = array(
'#theme' => 'forum_topic_list',
'#tid' => $variables['tid'],
'#topics' => $variables['topics'],
'#sortby' => $variables['sortby'],
'#forum_per_page' => $variables['forum_per_page'],
);
else {
$variables['topics'] = array();
}
$variables['forums'] = array();
$variables['topics'] = array();
* Prepares variables for forum list templates.
* Default template: forum-list.html.twig.
*
* @param array $variables
Jennifer Hodgdon
committed
* 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();
// Sanitize each forum so that the template can safely print the data.
foreach ($variables['forums'] as $id => $forum) {
$variables['forums'][$id]->description = filter_xss_admin($forum->description->value);
$variables['forums'][$id]->link = url("forum/" . $forum->id());
Angie Byron
committed
$variables['forums'][$id]->name = check_plain($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;
Angie Byron
committed
$variables['forums'][$id]->icon_class = 'default';
$variables['forums'][$id]->icon_title = t('No new posts');
Dries Buytaert
committed
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 = format_plural($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>', array('%title' => $variables['forums'][$id]->label()));
$variables['forums'][$id]->new_url = url('forum/' . $forum->id(), array('fragment' => 'new'));
Angie Byron
committed
$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 = array('#theme' => 'forum_submitted', '#topic' => $forum->last_post);
$variables['forums'][$id]->last_reply = drupal_render($forum_submitted);
$variables['pager'] = array(
'#theme' => 'pager',
);
// Give meaning to $tid for themers. $tid actually stands for term ID.
Gábor Hojtsy
committed
$variables['forum_id'] = $variables['tid'];
unset($variables['tid']);
* Prepares variables for forum topic list templates.
*
* Default template: forum-topic-list.html.twig.
*
* @param array $variables
Jennifer Hodgdon
committed
* An array containing the following elements:
* - tid: Taxonomy term ID of the current forum.
* - topics: An array of all the topics in the current forum.
* - forum_per_page: The maximum number of topics to display per page.
function template_preprocess_forum_topic_list(&$variables) {
$header = '';
if (!empty($forum_topic_list_header)) {
// Create the tablesorting header.
$ts = tablesort_init($forum_topic_list_header);
foreach ($forum_topic_list_header as $cell) {
$cell = tablesort_header($cell, $forum_topic_list_header, $ts);
$header .= _theme_table_cell($cell, TRUE);
}
}
$variables['header'] = $header;
if (!empty($variables['topics'])) {
foreach ($variables['topics'] as $id => $topic) {
$variables['topics'][$id]->icon = array(
'#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,
);
$variables['topics'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
$row++;
Dries Buytaert
committed
// 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.
Angie Byron
committed
if ($variables['tid'] != $topic->forum_tid) {
Dries Buytaert
committed
$variables['topics'][$id]->moved = TRUE;
$variables['topics'][$id]->title = check_plain($topic->getTitle());
Dries Buytaert
committed
$variables['topics'][$id]->message = l(t('This topic has been moved'), "forum/$topic->forum_tid");
}
else {
$variables['topics'][$id]->moved = FALSE;
catch
committed
$variables['topics'][$id]->title_link = l($topic->getTitle(), 'node/' . $topic->id());
Dries Buytaert
committed
$variables['topics'][$id]->message = '';
}
catch
committed
$forum_submitted = array('#theme' => 'forum_submitted', '#topic' => (object) array(
'uid' => $topic->getAuthorId(),
'name' => $topic->getAuthor()->getUsername(),
'created' => $topic->getCreatedTime(),
));
$variables['topics'][$id]->submitted = drupal_render($forum_submitted);
$forum_submitted = array(
'#theme' => 'forum_submitted',
'#topic' => isset($topic->last_reply) ? $topic->last_reply : NULL,
);
$variables['topics'][$id]->last_reply = drupal_render($forum_submitted);
$variables['topics'][$id]->new_text = '';
$variables['topics'][$id]->new_url = '';
if ($topic->new_replies) {
catch
committed
$variables['topics'][$id]->new_text = format_plural($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>', array('%title' => $variables['topics'][$id]->label()));
$variables['topics'][$id]->new_url = url('node/' . $topic->id(), array('query' => comment_new_page_count($topic->comment_count, $topic->new_replies, $topic, 'comment_node_forum'), 'fragment' => 'new'));
else {
Jennifer Hodgdon
committed
// Make this safe for the template.
$variables['topics'] = array();
}
Gábor Hojtsy
committed
// Give meaning to $tid for themers. $tid actually stands for term id.
$variables['topic_id'] = $variables['tid'];
unset($variables['tid']);
$variables['pager'] = array(
'#theme' => 'pager',
);
/**
* Prepares variables for forum icon templates.
*
* Default template: forum-icon.html.twig.
*
* @param array $variables
Jennifer Hodgdon
committed
* 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']) {
$icon_status_class = $variables['new_posts'] ? 'hot-new' : 'hot';
Dries Buytaert
committed
$variables['icon_title'] = $variables['new_posts'] ? t('Hot topic, new comments') : t('Hot topic');
$icon_status_class = $variables['new_posts'] ? 'new' : 'default';
Dries Buytaert
committed
$variables['icon_title'] = $variables['new_posts'] ? t('New comments') : t('Normal topic');
if ($variables['comment_mode'] == COMMENT_CLOSED || $variables['comment_mode'] == COMMENT_HIDDEN) {
$icon_status_class = 'closed';
Dries Buytaert
committed
$variables['icon_title'] = t('Closed topic');
}
if ($variables['sticky'] == 1) {
$icon_status_class = 'sticky';
Dries Buytaert
committed
$variables['icon_title'] = t('Sticky topic');
}
$variables['attributes']['class'][] = 'icon';
$variables['attributes']['class'][] = 'topic-status-' . $icon_status_class;
$variables['attributes']['title'] = $variables['icon_title'];
Dries Buytaert
committed
}
/**
* Prepares variables for forum submission information templates.
Jennifer Hodgdon
committed
*
* The submission information will be displayed in the forum list and topic
* list.
*
* Default template: forum-submitted.html.twig.
*
* @param array $variables
Jennifer Hodgdon
committed
* An array containing the following elements:
* - topic: The topic object.
*/
Dries Buytaert
committed
function template_preprocess_forum_submitted(&$variables) {
$variables['author'] = '';
if (isset($variables['topic']->uid)) {
$username = array('#theme' => 'username', '#account' => user_load($variables['topic']->uid));
$variables['author'] = drupal_render($username);
}
Angie Byron
committed
$variables['time'] = isset($variables['topic']->created) ? format_interval(REQUEST_TIME - $variables['topic']->created) : '';
Dries Buytaert
committed
/**
* Returns HTML for a forum form.
*
* By default this does not alter the appearance of a form at all, but is
* provided as a convenience for themers.
*
* @param $variables
* An associative array containing:
* - form: A render element representing the form.
*
* @ingroup themeable
*/
function theme_forum_form(array $variables) {
return drupal_render_children($variables['form']);
}
/**
* Implements hook_library_info().
*
* Forum specific libraries.
*/
function forum_library_info() {
$libraries['forum.index'] = array(
'title' => 'Forum index',
'version' => \Drupal::VERSION,
'css' => array(
drupal_get_path('module', 'forum') . '/css/forum.module.css' => array(),
),
);
return $libraries;
}