Ajax_comments и форма комментариев выше комментариев
Просматривая исходные коды данных модулей в надежде их все таки подружить, я заметил что в принципе метод предложенный neochief, а именно подменой темы на некотором этапе рендеринга, на свою не единственный (опять же гибкость Drupal в этом плане меня поражает).
Поэтому хочу предложить свой метод, основанный на хуке hook_menu_alter, ведь в принципе ни кто нам не запрещает полностью переопределить вывод ноды подменив стандартный коллбэк «node/%node».
Дальше я заранее извиняюсь, что позаимствовал часть кода из модуля «Форма комментариев поверх комментов» в плане hook_form_alter.
Итак определяем новый модуль (назвал я его acomment)
создаем папку sites/all/modules/accoment
в нем файл acomment.info
name = Comment form above comments
description = Adds option to place comment form above comments.
dependencies[] = comment
core = 6.x
далее, в той же папке создадим файл acomment.module
Основная идея данного модуля, подменить стандартный вывод через node_page_view своим, и в нем проверить как настроен вывод комментария у данного типа ноды, если это стандартный вывод COMMENT_FORM_SEPARATE_PAGE или COMMENT_FORM_BELOW то вызываем стандартный node_show, если же наш новый тип вывода COMMENT_FORM_ABOVE, то вызовем свой обработчик acomment_node_show.
В принципе ничего интересного в самом коде нет, все функции дублируют аналогичные функции из стандартных модулей node и comment, единственное отличие функции
acomment_comment_render от comment_render из модуля comment - это замена строки
$output .= comment_form_box(array('nid' => $nid), t('Post new comment'));
на
$output = comment_form_box(array('nid' => $nid), t('Post new comment')) . $output;
где мы собственно и переносим форму ввода комментария, сразу после ноды.
// $Id$
/**
* @file
* Adds option to place comment form above comments.
*/
define('COMMENT_FORM_ABOVE', 2);
/**
* Implementation of hook_form_alter().
*/
function acomment_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
$form['comment']['comment_form_location'] = array(
'#type' => 'radios',
'#title' => t('Location of comment submission form'),
'#default_value' => variable_get('comment_form_location_'. $form['#node_type']->type, COMMENT_FORM_SEPARATE_PAGE),
'#options' => array(
COMMENT_FORM_SEPARATE_PAGE => t('Display on separate page'),
COMMENT_FORM_BELOW => t('Display below post or comments'),
COMMENT_FORM_ABOVE => t('Display below post, but before comments'),
),
);
}
}
function acomment_menu_alter(&$items) {
$items['node/%node']['page callback'] = 'acomment_node_page_view';
}
function acomment_node_page_view($node, $cid = NULL) {
drupal_set_title(check_plain($node->title));
if (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_ABOVE) {
$output = acomment_node_show($node, $cid);
}
else {
$output = node_show($node, $cid);
}
return $output;
}
function acomment_node_show($node, $cid = NULL) {
$output = node_view($node, FALSE, TRUE);
if ($node->comment) {
$output .= acomment_comment_render($node, $cid);
}
node_tag_new($node->nid);
return $output;
}
function acomment_comment_render($node, $cid = 0) {
global $user;
$output = '';
if (user_access('access comments')) {
// Pre-process variables.
$nid = $node->nid;
if (empty($nid)) {
$nid = 0;
}
$mode = _comment_get_display_setting('mode', $node);
$order = _comment_get_display_setting('sort', $node);
$comments_per_page = _comment_get_display_setting('comments_per_page', $node);
if ($cid && is_numeric($cid)) {
// Single comment view.
$query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
$query_args = array($cid);
if (!user_access('administer comments')) {
$query .= ' AND c.status = %d';
$query_args[] = COMMENT_PUBLISHED;
}
$query = db_rewrite_sql($query, 'c', 'cid');
$result = db_query($query, $query_args);
if ($comment = db_fetch_object($result)) {
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
$links = module_invoke_all('link', 'comment', $comment, 1);
drupal_alter('link', $links, $node, $comment);
$output .= theme('comment_view', $comment, $node, $links);
}
}
else {
// Multiple comment view
$query_count = 'SELECT COUNT(*) FROM {comments} c WHERE c.nid = %d';
$query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
$query_args = array($nid);
if (!user_access('administer comments')) {
$query .= ' AND c.status = %d';
$query_count .= ' AND c.status = %d';
$query_args[] = COMMENT_PUBLISHED;
}
if ($order == COMMENT_ORDER_NEWEST_FIRST) {
if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
$query .= ' ORDER BY c.cid DESC';
}
else {
$query .= ' ORDER BY c.thread DESC';
}
}
elseif ($order == COMMENT_ORDER_OLDEST_FIRST) {
if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
$query .= ' ORDER BY c.cid';
}
else {
// See comment above. Analysis reveals that this doesn't cost too
// much. It scales much much better than having the whole comment
// structure.
$query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))';
}
}
$query = db_rewrite_sql($query, 'c', 'cid');
$query_count = db_rewrite_sql($query_count, 'c', 'cid');
// Start a form, for use with comment control.
$result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
$divs = 0;
$num_rows = FALSE;
$comments = '';
drupal_add_css(drupal_get_path('module', 'comment') .'/comment.css');
while ($comment = db_fetch_object($result)) {
$comment = drupal_unpack($comment);
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
$comment->depth = count(explode('.', $comment->thread)) - 1;
if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
if ($comment->depth > $divs) {
$divs++;
$comments .= '<div class="indented">';
}
else {
while ($comment->depth < $divs) {
$divs--;
$comments .= '</div>';
}
}
}
if ($mode == COMMENT_MODE_FLAT_COLLAPSED) {
$comments .= theme('comment_flat_collapsed', $comment, $node);
}
elseif ($mode == COMMENT_MODE_FLAT_EXPANDED) {
$comments .= theme('comment_flat_expanded', $comment, $node);
}
elseif ($mode == COMMENT_MODE_THREADED_COLLAPSED) {
$comments .= theme('comment_thread_collapsed', $comment, $node);
}
elseif ($mode == COMMENT_MODE_THREADED_EXPANDED) {
$comments .= theme('comment_thread_expanded', $comment, $node);
}
$num_rows = TRUE;
}
while ($divs-- > 0) {
$comments .= '</div>';
}
$comment_controls = variable_get('comment_controls_'. $node->type, COMMENT_CONTROLS_HIDDEN);
if ($num_rows && ($comment_controls == COMMENT_CONTROLS_ABOVE || $comment_controls == COMMENT_CONTROLS_ABOVE_BELOW)) {
$output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
}
$output .= $comments;
$output .= theme('pager', NULL, $comments_per_page, 0);
if ($num_rows && ($comment_controls == COMMENT_CONTROLS_BELOW || $comment_controls == COMMENT_CONTROLS_ABOVE_BELOW)) {
$output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
}
}
// If enabled, show new comment form if it's not already being displayed.
$reply = arg(0) == 'comment' && arg(1) == 'reply';
if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location_'. $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_ABOVE) && !$reply) {
$output = comment_form_box(array('nid' => $nid), t('Post new comment')) . $output;
}
if ($output) {
$output = theme('comment_wrapper', $output, $node);
}
}
return $output;
}
Ну и далее что бы оформить модуль подобающим образом (и прибраться за собой если модуль удаляют) создадим файл acomment.install
Ну здесь все просто, если модуль удаляют и у каких-либо типов нод вид вывода комментария равен COMMENT_FORM_ABOVE мы им назначаем вывод комментариев вида COMMENT_FORM_BELOW.
// $Id$
/**
* @file
* Install acomment module.
*/
/**
* Implementation of hook_install(). We need to execute our module after
* others to prevent some glitches caused by $node->comment = NULL set in
* hook_preprocess_node().
*/
function acomment_install() {
db_query("UPDATE {system} SET weight = 10 WHERE name = 'acomment'");
}
/**
* Implementation of hook_uninstall().
*/
function acomment_uninstall() {
$types = node_get_types('types');
foreach ($types as $key => $value) {
if (variable_get('comment_form_location_' . $key, COMMENT_FORM_SEPARATE_PAGE ) == COMMENT_FORM_ABOVE) {
variable_set('comment_form_location_' . $key, COMMENT_FORM_BELOW);
}
}
}
Ну вроде все, только хочется добавить, что данный модуль отлично (по крайней мере у меня) «дружит» с ajax_comments (еще раз респект и уважуха
neochief).
Ну и как это примерно выглядит, можно посмотреть например в ветке форума моего нового проекта Loros Studio
Ну и прикреплю архивчик с данным модулем, потесируйте если будет интерес выложу на drupal.org.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- 1058 просмотров
А на самом деле у neochief модули "дружат", только странным образом
Если отметить галочкой поле Показывать на отдельной странице, то показывается ниже сообщения, но выше комментариев
)) У вас же, всё правильно. У neochief в случае, если отметить опцию "Показывать ниже сообщения, но выше комментариев", то он - да, показывает, но форма всегда раскрыта.