Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/comments/model/_comment.funcs.php
<?php
/**
 * This file implements Comment handling functions.
  *
 * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}.
 * See also {@link https://github.com/b2evolution/b2evolution}.
 *
 * @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}.
 * Parts of this file are copyright (c)2004-2005 by Daniel HAHLER - {@link http://thequod.de/contact}.
 *
 * @package evocore
 *
 * @todo implement CommentCache based on LinkCache
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );

load_class( 'comments/model/_comment.class.php', 'Comment' );

/**
 * Generic comments/trackbacks/pingbacks/webmentions counting
 *
 * @todo check this in a multiblog page...
 * @todo This should support visibility: at least in the default front office (_feedback.php), there should only the number of visible comments/trackbacks get used ({@link Item::feedback_link()}).
 *
 * @param integer
 * @param string what to count
 * @param mixed string or array to count comments with this/these status(es)
 * @param boolean set true to count expired comments, leave on false otherwise
 */
function generic_ctp_number( $post_id, $mode = 'comments', $status = 'published', $count_expired = false, $filter_by_perm = true )
{
    global
$DB, $debug, $postdata, $cache_ctp_number, $preview, $servertimenow, $blog;

    if(
$preview )
    {
// we are in preview mode, no comments yet!
       
return 0;
    }

   
$show_statuses = ( is_admin_page() || ( ! $filter_by_perm ) ) ? get_visibility_statuses( 'keys', array( 'trash', 'redirected' ) ) : get_inskin_statuses( $blog, 'comment' );
   
$filter_index = $filter_by_perm ? 0 : 1;
    if( !isset(
$cache_ctp_number) || !isset($cache_ctp_number[$filter_index][$post_id]) )
    {
// we need a query to count comments
       
$count_SQL = new SQL();
       
$count_SQL->SELECT( 'comment_item_ID, comment_type, comment_status, COUNT(*) AS type_count' );
       
$count_SQL->FROM( 'T_comments' );
       
$count_SQL->GROUP_BY( 'comment_item_ID, comment_type, comment_status' );
        if( !empty(
$blog ) )
        {
           
$count_SQL->WHERE( statuses_where_clause( $show_statuses, 'comment_', $blog, 'blog_comment!', $filter_by_perm ) );
        }

        if( !
$count_expired )
        {
           
$count_SQL->FROM_add( 'LEFT JOIN T_items__item_settings as expiry_setting ON comment_item_ID = iset_item_ID AND iset_name = "comment_expiry_delay"' );
           
$count_SQL->WHERE_and( 'expiry_setting.iset_value IS NULL OR expiry_setting.iset_value = "" OR TIMESTAMPDIFF(SECOND, comment_date, '.$DB->quote( date2mysql( $servertimenow ) ).') < expiry_setting.iset_value' );
        }
    }

   
// init statuses count array
   
$statuses_array = array( 'published' => 0, 'community' => 0, 'protected' => 0, 'private' => 0, 'review' => 0, 'draft' => 0, 'deprecated' => 0, 'trash' => 0, 'total' => 0 );

   
/*
     * Make sure cache is loaded for current display list:
     */
   
if( !isset($cache_ctp_number) || !isset($cache_ctp_number[$filter_index]) )
    {
        global
$postIDlist, $postIDarray;

       
// if( $debug ) echo "LOADING generic_ctp_number CACHE for posts: $postIDlist<br />";

       
if( ! empty( $postIDlist ) )    // This can happen when displaying a featured post of something that's not in the MainList
       
{
            foreach(
$postIDarray as $tmp_post_id)
            {    
// Initializes each post to nocount!
               
$cache_ctp_number[$filter_index][$tmp_post_id] = array(
                       
'comments'   => $statuses_array,
                       
'trackbacks' => $statuses_array,
                       
'pingbacks'  => $statuses_array,
                       
'feedbacks'  => $statuses_array,
                       
'metas'      => $statuses_array,
                       
'webmentions'=> $statuses_array,
                    );
            }

           
$countall_SQL = $count_SQL;
           
$countall_SQL->WHERE_and( 'comment_item_ID IN ('.$postIDlist.')' );

            foreach(
$DB->get_results( $countall_SQL->get() ) as $row )
            {
               
// detail by status, tyep and post:
               
$cache_ctp_number[$filter_index][$row->comment_item_ID][$row->comment_type.'s'][$row->comment_status] = $row->type_count;

               
// Total for type on post:
               
$cache_ctp_number[$filter_index][$row->comment_item_ID][$row->comment_type.'s']['total'] += $row->type_count;

                if(
$row->comment_type != 'meta' )
                {
// Exclude internal comments from feedbacks
                    // Total for status on post:
                   
$cache_ctp_number[$filter_index][$row->comment_item_ID]['feedbacks'][$row->comment_status] += $row->type_count;

                   
// Total for post:
                   
$cache_ctp_number[$filter_index][$row->comment_item_ID]['feedbacks']['total'] += $row->type_count;
                }
            }
        }
    }
   
/*    else
    {
        echo "cache set";
    }*/


   
if( !isset($cache_ctp_number[$filter_index][$post_id]) )
    {
// this should be extremely rare...
        // echo "CACHE not set for $post_id";

        // Initializes post to nocount!
       
$cache_ctp_number[$filter_index][intval($post_id)] = array(
               
'comments'   => $statuses_array,
               
'trackbacks' => $statuses_array,
               
'pingbacks'  => $statuses_array,
               
'feedbacks'  => $statuses_array,
               
'metas'      => $statuses_array,
               
'webmentions'=> $statuses_array,
            );

       
$count_SQL->WHERE_and( 'comment_item_ID = '.intval($post_id) );

        foreach(
$DB->get_results( $count_SQL->get() ) as $row )
        {
           
// detail by status, type and post:
           
$cache_ctp_number[$filter_index][$row->comment_item_ID][$row->comment_type.'s'][$row->comment_status] = $row->type_count;

           
// Total for type on post:
           
$cache_ctp_number[$filter_index][$row->comment_item_ID][$row->comment_type.'s']['total'] += $row->type_count;

            if(
$row->comment_type != 'meta' )
            {
// Exclude internal comments from feedbacks
                // Total for status on post:
               
$cache_ctp_number[$filter_index][$row->comment_item_ID]['feedbacks'][$row->comment_status] += $row->type_count;

               
// Total for post:
               
$cache_ctp_number[$filter_index][$row->comment_item_ID]['feedbacks']['total'] += $row->type_count;
            }
        }
    }

    if( !
in_array( $mode, array( 'comments', 'trackbacks', 'pingbacks', 'metas', 'webmentions' ) ) )
    {
       
$mode = 'feedbacks';
    }

    if(
is_array( $status ) )
    {
// $status is an array and probably contains more then one visibility status
       
$result = 0;
        foreach(
$status as $one_status )
        {
            if( isset(
$cache_ctp_number[$filter_index][$post_id][$mode][$one_status] ) )
            {
               
$result = $result + $cache_ctp_number[$filter_index][$post_id][$mode][$one_status];
            }
        }
    }
    elseif( isset(
$cache_ctp_number[$filter_index][$post_id][$mode][$status] ) )
    {
// $status is a string with one visibility status
       
$result = $cache_ctp_number[$filter_index][$post_id][$mode][$status];
    }
    else
    {
// $status is not recognized return total feedback number
       
$result = $cache_ctp_number[$filter_index][$post_id][$mode]['total'];
    }

   
// pre_dump( $cache_ctp_number[$filter_index][$post_id] );

   
return $result;
}


/**
 * Get a Comment by ID. Exits if the requested comment does not exist!
 *
 * @param integer
 * @param boolean
 * @return Comment
 */
function & Comment_get_by_ID( $comment_ID, $halt_on_error = true )
{
   
$CommentCache = & get_CommentCache();
    return
$CommentCache->get_by_ID( $comment_ID, $halt_on_error );
}


/*
 * last_comments_title(-)
 *
 * @movedTo _obsolete092.php
 */


/***** Comment tags *****/

/**
 * comments_number(-)
 *
 * @deprecated deprecated by {@link Item::feedback_link()}, used in _edit_showposts.php
 */
function comments_number( $zero='#', $one='#', $more='#', $post_ID = NULL )
{
    if(
$zero == '#' ) $zero = T_('Leave a comment');
    if(
$one == '#' ) $one = T_('1 comment');
    if(
$more == '#' ) $more = T_('%d comments');

    if( empty(
$post_ID ) )
    {
        global
$id;
       
$post_ID = $id;
    }

   
// attila> This function is called only from the backoffice ( _item_list_full.view.php ).
    // There we always have to show all comments.
   
$number = generic_ctp_number( $post_ID, 'comments', 'total' );
    if (
$number == 0)
    {
       
$blah = $zero;
    }
    elseif (
$number == 1)
    {
       
$blah = $one;
    }
    elseif (
$number  > 1)
    {
       
$n = $number;
       
$more = str_replace('%d', $n, $more);
       
$blah = $more;
    }
    echo
$blah;
}

/**
 * Get advanced perm for comment moderation on this blog
 *
 * @param int blog ID
 * @return array statuses - current user has permission to moderate comments with these statuses
 */
function get_allowed_statuses( $blog )
{
   
$statuses = array();

    if(
check_user_perm( 'blog_draft_comments', 'edit', false, $blog ) )
    {
       
$statuses[] = 'draft';
    }

    if(
check_user_perm( 'blog_published_comments', 'edit', false, $blog ) )
    {
       
$statuses[] = 'published';
    }

    if(
check_user_perm( 'blog_deprecated_comments', 'edit', false, $blog ) )
    {
       
$statuses[] = 'deprecated';
    }

    return
$statuses;
}


/**
 * Create comment form submit buttons
 *
 * Note: Publsih in only displayed when comment is in draft status
 *
 * @param $Form
 * @param $edited_Comment
 *
 */
function echo_comment_buttons( $Form, $edited_Comment )
{
    global
$Collection, $Blog, $AdminUI;

    if(
$edited_Comment->is_meta() )
    {
// Internal comments don't have a status, Display only one button to update
       
$Form->submit( array( 'actionArray[update]', T_('Save Changes!'), 'SaveButton' ) );
    }
    else
    {
// Normal comments have a status, Display the buttons to change it and update
       
if( $edited_Comment->status != 'trash' )
        {
           
// ---------- VISIBILITY ----------
           
echo T_('Visibility').get_manual_link( 'visibility-status' ).': ';
           
// Get those statuses which are not allowed for the current User to create comments in this blog
           
if( $edited_Comment->is_meta() )
            {    
// Don't restrict statuses for internal comments:
               
$restricted_statuses = array();
            }
            else
            {    
// Restrict statuses for normal comments:
               
$comment_Item = & $edited_Comment->get_Item();
               
// Comment status cannot be more than post status, restrict it:
               
$restrict_max_allowed_status = ( $comment_Item ? $comment_Item->status : '' );
               
$restricted_statuses = get_restricted_statuses( $Blog->ID, 'blog_comment!', 'edit', $edited_Comment->status, $restrict_max_allowed_status );
            }
           
$exclude_statuses = array_merge( $restricted_statuses, array( 'redirected', 'trash' ) );
           
// Get allowed visibility statuses
           
$status_options = get_visibility_statuses( '', $exclude_statuses );

            if( isset(
$AdminUI, $AdminUI->skin_name ) && $AdminUI->skin_name == 'bootstrap' )
            {
// Use dropdown for bootstrap skin
               
$status_icon_options = get_visibility_statuses( 'icons', $exclude_statuses );
               
$Form->hidden( 'comment_status', $edited_Comment->status );
                echo
'<div class="btn-group dropup comment_status_dropdown" data-toggle="tooltip" data-placement="left" data-container="body" title="'.get_status_tooltip_title( $edited_Comment->status ).'">';
                echo
'<button type="button" class="btn btn-status-'.$edited_Comment->status.' dropdown-toggle" data-toggle="dropdown" aria-expanded="false" id="comment_status_dropdown">'
                               
.'<span>'.$status_options[ $edited_Comment->status ].'</span>'
                           
.' <span class="caret"></span></button>';
                echo
'<ul class="dropdown-menu" role="menu" aria-labelledby="comment_status_dropdown">';
                foreach(
$status_options as $status_key => $status_title )
                {
                    echo
'<li rel="'.$status_key.'" role="presentation"><a href="#" role="menuitem" tabindex="-1">'.$status_icon_options[ $status_key ].' <span>'.$status_title.'</span></a></li>';
                }
                echo
'</ul>';
                echo
'</div>';
            }
            else
            {
// Use standard select element for other skins
               
echo '<select name="comment_status">';
                foreach(
$status_options as $status_key => $status_title )
                {
                    echo
'<option value="'.$status_key.'"'
                               
.( $edited_Comment->status == $status_key ? ' selected="selected"' : '' )
                                .
' class="btn-status-'.$status_key.'">'
                           
.$status_title
                       
.'</option>';
                }
                echo
'</select>';
            }
        }

        echo
'<span class="btn-group">';

       
// ---------- SAVE BUTTONS ----------
       
$Form->submit( array( 'actionArray[update_edit]', /* TRANS: This is the value of an input submit button */ T_('Save & edit'), 'SaveEditButton btn-status-'.$edited_Comment->status ) );
       
$Form->submit( array( 'actionArray[update]', T_('Save'), 'SaveButton btn-status-'.$edited_Comment->status ) );

        echo
'</span>';
    }
}


/**
 * Display buttons to update a comment
 *
 * @param object Form
 * @param object edited Comment
 * @param string Max allowed status
 * @param string Action: 'update' - for button titles like 'Save as Public!', 'comments_visibility' - for button titles like 'Set visibility to Public'
 */
function echo_comment_status_buttons( $Form, $edited_Comment = NULL, $max_allowed_status = '', $action = 'update' )
{
    global
$Collection, $Blog;

    if(
$edited_Comment !== NULL )
    {    
// If the edited comment is defined, e-g on edit form:
       
if( $edited_Comment->is_meta() )
        {    
// Don't suggest to change a status of internal comment:
           
$Form->submit( array( 'actionArray['.$action.']', T_('Save Changes!'), 'SaveButton', '' ) );
            return;
        }

       
$comment_Item = & $edited_Comment->get_Item();
       
$comment_status = $edited_Comment->status;
    }
    else
    {    
// If comment is not defined, e-g on action for several comments from list:
       
$comment_Item = NULL;
       
$comment_status = $max_allowed_status;
    }

   
// Comment status cannot be more than post status, restrict it:
   
$restrict_max_allowed_status = ( $comment_Item ? $comment_Item->status : $max_allowed_status );

   
// Get those statuses which are not allowed for the current User to create posts in this blog
   
$exclude_statuses = array_merge( get_restricted_statuses( $Blog->ID, 'blog_comment!', 'edit', $comment_status, $restrict_max_allowed_status ), array( 'redirected', 'trash' ) );
   
// Get allowed visibility statuses:
   
if( $action == 'comments_visibility' )
    {
       
$status_options = get_visibility_statuses( '', $exclude_statuses );
        foreach(
$status_options as $status_key => $status_title )
        {
           
$status_options[ $status_key ] = sprintf( T_('Set visibility to %s'), $status_title );
        }
    }
    else
// 'update'
   
{
       
$status_options = get_visibility_statuses( 'button-titles', $exclude_statuses );
       
$status_options = array_map( 'T_', $status_options );
    }

    if( empty(
$status_options ) )
    {    
// If current User has no permission to edit to any status:
       
return;
    }

   
$status_icon_options = get_visibility_statuses( 'icons', $exclude_statuses );

    if( ! isset(
$status_options[ $comment_status ] ) )
    {    
// Check if the status is allowed for current User:
       
foreach( $status_options as $status_key => $status_title )
        {
           
$comment_status = $status_key;
            break;
        }
    }

   
$Form->hidden( 'comment_status', $comment_status );
    echo
'<div class="btn-group dropup comment_status_dropdown">';
    echo
'<button type="submit" class="btn btn-status-'.$comment_status.'" name="actionArray['.$action.']">'
               
.'<span>'.$status_options[ $comment_status ].'</span>'
           
.'</button>'
           
.'<button type="button" class="btn btn-status-'.$comment_status.' dropdown-toggle" data-toggle="dropdown" aria-expanded="false" id="comment_status_dropdown">'
               
.'<span class="caret"></span>'
           
.'</button>';
    echo
'<ul class="dropdown-menu" role="menu" aria-labelledby="comment_status_dropdown">';
    foreach(
$status_options as $status_key => $status_title )
    {
        echo
'<li rel="'.$status_key.'" role="presentation"><a href="#" role="menuitem" tabindex="-1">'.$status_icon_options[ $status_key ].' <span>'.$status_title.'</span></a></li>';
    }
    echo
'</ul>';
    echo
'</div>';
}


/**
 * Add a javascript ban action icon after the given url
 *
 * @param string url
 * @return string the url with ban icon
 */
function add_jsban( $url )
{
    global
$admin_url;

   
$ban_domain = get_ban_domain( $url );
   
$ban_url = $admin_url.'?ctrl=antispam&amp;action=ban&amp;keyword='.rawurlencode( $ban_domain ).'&amp;'.url_crumb('antispam');

    return
'<a id="ban_url" href="'.$ban_url.'" onclick="ban_url(\''.$ban_domain.'\'); return false;">'.get_icon( 'ban' ).'</a>';
}


/**
 * Add a javascript ban action icon after each url in the given content
 *
 * @param string Comment content
 * @return string the content with a ban icon after each url if the user has spamblacklist permission, the incoming content otherwise
 */
function add_ban_icons( $content )
{
    if( !
check_user_perm( 'spamblacklist', 'edit' ) )
    {
// Current user has no permission to edit the spam contents
       
return $content;
    }

    if(
stristr( $content, '<code' ) !== false || stristr( $content, '<pre' ) !== false )
    {
// Add icons only outside <code> and <pre>
       
return callback_on_non_matching_blocks( $content,
               
'~<(code|pre)[^>]+class="codeblock"[^>]*>.*?</\1>~is',
               
'add_ban_icons_callback' );
    }
    else
    {
        return
add_ban_icons_callback( $content );
    }
}


/**
 * Callback function to add a javascript ban action icon after each url in the given content
 *
 * @param string Comment content
 * @return string the content with a ban icon after each url if the user has spamblacklist permission, the incoming content otherwise
 */
function add_ban_icons_callback( $content )
{
   
$atags = get_atags( $content );
   
$imgtags = get_imgtags( $content );
   
$urls = get_urls( $content );
   
$result = '';
   
$from = 0; // current processing position
   
$length = 0; // current url or tag length
   
$i = 0; // url counter
   
$j = 0; // "a" tag counter
   
$k = 0; // "img" tag counter

    // Remove the duplicated <a> tags from array
   
$atags_fixed = array();
    foreach(
$atags as $atag )
    {
        if(
preg_match( '#href="([^"]+)"#', $atag, $matches ) && ! isset( $atags_fixed[ $matches[1] ] ) )
        {
           
$atags_fixed[ $matches[1] ] = $atag;
        }
    }
   
$atags = array();
    foreach(
$atags_fixed as $atag )
    {
       
$atags[] = $atag;
    }

   
$used_urls = array();
    while( isset(
$urls[$i] ) )
    {
// there is unprocessed url
       
$url = $urls[$i];
        if(
validate_url( $url, 'posting', false ) )
        {
// skip not valid urls
           
$i++;
            continue;
        }
        if(
in_array( $url, $used_urls ) )
        {
// skip already passed url
           
$i++;
            continue;
        }
       
$used_urls[] = $url;
        while( isset(
$imgtags[$k] ) && ( strpos( $content, $imgtags[$k] ) < $from ) )
        {
// skip already passed img tags
           
$k++;
        }

       
$pos = strpos( $content, $url, $from );
       
$length = utf8_strlen($url);
       
$i++;

       
// check img tags
       
if( isset( $imgtags[$k] ) && ( strpos( $imgtags[$k], $url ) !== false )
            && (
$pos > strpos( $content, $imgtags[$k], $from ) ) )
        {
// current url is inside the img tag, we need to skip this url.
           
$result .= substr( $content, $from, $pos + $length - $from );
           
$from = $pos + $length;
           
$k++;
            continue;
        }

       
// check a tags
       
if( isset($atags[$j]) )
        {
// there is unprocessed "a" tag
           
$tag = $atags[$j];
            if( ( (
$urlpos = strpos( $tag, $url ) ) !== false ) && ( $pos > strpos( $content, $tag, $from ) ) )
            {
// the url is inside the current tag, we have to add ban icon after the tag
               
$pos = strpos( $content, $tag, $from );
               
$length = strlen($tag);
                while( isset(
$urls[$i]) && ( ( $urlpos = strpos( $tag, $urls[$i], $urlpos + 1 ) ) !== false ) )
                {
// skip all other urls from this tag
                   
$i++;
                }
               
$j++;
            }
        }
       
// add processed part and ban icon to result and set current position
       
$result .= substr( $content, $from, $pos + $length - $from );
       
$from = $pos + $length;
       
$result .= add_jsban( $url );
    }

   
// add the end of the content to the result
   
$result .= substr( $content, $from, strlen($content) - $from );
    return
$result;
}


/**
 * Get opentrash link
 *
 * @param boolean check permission or not. Should be false only if it was already checked.
 * @param boolean show "Open recycle bin" link even if there is no comment with 'trash' status
 * @param array Additional params
 * @return Open recycle bin link if user has the corresponding 'blogs' - 'editall' permission, empty string otherwise
 */
function get_opentrash_link( $check_perm = true, $force_show = false, $params = array() )
{
    global
$admin_url, $DB, $blog;

   
$params = array_merge( array(
           
'before' => '<div id="recycle_bin" class="pull-right">',
           
'after'  => ' </div>',
           
'class'  => 'action_icon btn btn-default btn-sm',
        ),
$params );

   
$show_recycle_bin = ( !$check_perm || check_user_perm( 'blogs', 'editall' ) );
    if(
$show_recycle_bin && ( !$force_show ) )
    {
// get number of trash comments:
       
$SQL = new SQL( 'Get number of trash comments for open trash link' );
       
$SQL->SELECT( 'COUNT( comment_ID )' );
       
$SQL->FROM( 'T_comments' );
       
$SQL->FROM_add( 'INNER JOIN T_items__item ON comment_item_ID = post_ID' );
       
$SQL->FROM_add( 'INNER JOIN T_categories ON post_main_cat_ID = cat_ID' );
       
$SQL->WHERE( 'comment_status = "trash"' );
        if( isset(
$blog ) )
        {
           
$SQL->WHERE_and( 'cat_blog_ID = '.$DB->quote( $blog ) );
        }
       
$show_recycle_bin = ( $DB->get_var( $SQL ) > 0 );
    }

   
$result = $params['before'];
    if(
$show_recycle_bin )
    {
// show "Open recycle bin"
       
global $CommentList;
       
$comment_list_param_prefix = 'cmnt_fullview_';
        if( !empty(
$CommentList->param_prefix ) )
        {
           
$comment_list_param_prefix = $CommentList->param_prefix;
        }
       
$result .= action_icon( T_('Open recycle bin'), 'recycle_full',
                       
$admin_url.'?ctrl=comments&amp;blog='.$blog.'&amp;'.$comment_list_param_prefix.'show_statuses[]=trash', ' '.T_('Open recycle bin'), 5, 3, array( 'class' => $params['class'] ) );
    }
    return
$result.$params['after'];
}


/**
 * Display disabled comment form
 *
 * @param string Blog allow comments settings value
 * @param string Item url, where this comment form should be displayed
 * @param array Skin params
 */
function echo_disabled_comments( $allow_comments_value, $item_url, $params = array() )
{
    global
$Settings;

   
$params = array_merge( array(
           
'comments_disabled_text_member'     => T_( 'You must be a member of this blog to comment.' ),
           
'comments_disabled_text_registered' => T_( 'In order to leave a comment' ),
           
'comments_disabled_text_validated'  => T_( 'You must activate your account before you can leave a comment.' ),
           
'form_comment_text'                 => T_('Comment text'),
           
'form_class_comment'                => 'bComment',
        ),
$params );

    if( empty(
$params['form_params'] ) )
    {
       
$params['form_params'] = array();
    }

   
$params['form_params'] = array_merge( array(
           
'comments_disabled_before' => '<div class="comment_posting_disabled_msg"><p>',
           
'comments_disabled_after' => '</p></div>',
           
'formstart'      => '',
           
'formend'        => '',
           
'fieldset_begin' => '<fieldset>',
           
'fieldset_end'   => '</fieldset>',
           
'fieldstart'     => '',
           
'fieldend'       => '',
           
'labelstart'     => '<div class="evo_label"><label for="p">',
           
'labelend'       => '</label></div>',
           
'inputstart'     => '<div class="evo_input">',
           
'inputend'       => '</div>',
        ),
$params['form_params'] );

    switch(
$allow_comments_value )
    {
        case
'member':
           
$disabled_text = $params['comments_disabled_text_member'];
           
$form_disabled_text = $disabled_text;
            break;

        case
'registered':
           
$disabled_text = $params['comments_disabled_text_registered'];
           
$form_disabled_text = T_( 'You must be logged in to leave a comment.' );
            break;

        default:
           
// case any or never, in this case comment form is already displayed, or comments are not allowed at all.
           
return;
    }

   
$login_link = '';
   
$activateinfo_link = '';
   
$is_logged_in = is_logged_in();
    if( !
$is_logged_in )
    {
// user is not logged in
       
$login_link = '<a class="btn btn-primary btn-sm" href="'.get_login_url( 'cannot comment', $item_url ).'">'.T_( 'Log in now!' ).'</a>';
    }
    elseif(
check_user_status( 'can_be_validated' ) )
    {
// logged in but the account is not activated
       
$disabled_text = $params['comments_disabled_text_validated'];
       
$form_disabled_text = $disabled_text;
       
$activateinfo_link = '<a href="'.get_activate_info_url( $item_url, '&amp;' ).'">'.T_( 'More info &raquo;' ).'</a>';
    }
   
// else -> user is logged in and account was activated

   
if( ( !$is_logged_in ) && ( $Settings->get( 'newusers_canregister' ) == 'yes' ) && ( $Settings->get( 'registration_is_public' ) ) )
    {
       
$register_link = '<a class="btn btn-primary btn-sm" href="'.get_user_register_url( $item_url, 'reg to post comment' ).'">'.T_( 'Register now!' ).'</a>';
    }

   
// disabled comment form
   
echo '<form class="'.$params['form_class_comment'].'" action="">';

    echo
$params['form_params']['formstart'];

    echo
$params['form_params']['fieldset_begin'];

    echo
$params['form_params']['comments_disabled_before'];
    if(
$is_logged_in )
    {
        echo
$disabled_text.' '.$activateinfo_link;
    }
    else
    {
// not logged in, add login and register links
       
echo $disabled_text.' '.$login_link.( ! empty( $register_link ) ? ' '.T_('or').' '.$register_link : '' );
    }
    echo
$params['form_params']['comments_disabled_after'];

    echo
$params['form_params']['fieldset_end'];

    echo
$params['form_params']['fieldset_begin'];
    echo
$params['form_params']['fieldstart'];
    echo
$params['form_params']['labelstart'].$params['form_comment_text'].':'.$params['form_params']['labelend'];
    echo
$params['form_params']['inputstart'];
    echo
'<textarea id="p" class="bComment form_textarea_input" rows="5" name="p" cols="40" disabled="disabled">'.$form_disabled_text.'</textarea>';
    echo
$params['form_params']['inputend'];
    echo
$params['form_params']['fieldend'];
    echo
$params['form_params']['fieldset_end'];

    echo
$params['form_params']['formend'];

   
// margin at the bottom of the form
   
echo '<div style="margin-top:10px"></div>';
    echo
'</form>';
}


/**
 * Save Comment object into the current Session
 *
 * @param object Comment
 * @param string Kind of session var: 'unsaved' or 'preview'
 * @param string Comment type: Meta or Normal
 */
function save_comment_to_session( $Comment, $kind = 'unsaved', $type = '' )
{
    global
$Session;

    if(
$type != 'meta' )
    {    
// Use default type if it is not allowed:
       
$type = '';
    }

   
$Session->set( 'core.'.$kind.'_Comment'.$type, $Comment );
}


/**
 * Get Comment object from the current Session
 *
 * @param string Kind of session var: 'unsaved' or 'preview'
 * @param string Comment type: Meta or Normal
 * @return Comment|NULL Comment object if Session core.unsaved_Comment param is set, NULL otherwise
 */
function get_comment_from_session( $kind = 'unsaved', $type = '' )
{
    global
$Session, $b2evo_session_comments;

    if(
$type != 'meta' )
    {    
// Use default type if it is not allowed:
       
$type = '';
    }

   
$session_var_name = 'core.'.$kind.'_Comment'.$type;

    if( ! isset(
$b2evo_session_comments[ $session_var_name ] ) )
    {    
// Set Comment to cache array:
       
if( ! is_array( $b2evo_session_comments ) )
        {    
// Initialize array for caching:
           
$b2evo_session_comments = array();
        }

        if( (
$Comment = $Session->get( $session_var_name ) ) && $Comment instanceof Comment )
        {    
// If Comment is detected for current Session:

            // Delete Comment to clear Session data:
           
$Session->delete( $session_var_name );
        }
        else
        {    
// Comment is not detected, Return NULL:
           
$Comment = NULL;
        }

       
// Cache Comment in global var:
       
$b2evo_session_comments[ $session_var_name ] = $Comment;
    }

    return
$b2evo_session_comments[ $session_var_name ];
}


/**
 * Dispay the replies of a comment on front-office
 *
 * @param integer Comment ID
 * @param array Template params
 * @param integer Level
 */
function display_comment_replies( $comment_ID, $params = array(), $level = 1 )
{
    global
$CommentReplies;

   
$params = array_merge( array(
           
'comment_template'    => '_item_comment.inc.php',
           
'preview_block_start' => '',
           
'preview_start'       => '<div class="bComment" id="comment_preview">',
           
'preview_end'         => '</div>',
           
'preview_block_end'   => '',
           
'comment_start'       => '<div class="bComment">',
           
'comment_end'         => '</div>',
           
'comment_error_start' => '<div class="bComment" id="comment_error">',
           
'comment_error_end'   => '</div>',
           
'link_to'             => 'userurl>userpage', // 'userpage' or 'userurl' or 'userurl>userpage' or 'userpage>userurl'
           
'author_link_text'    => 'name', // avatar_name | avatar_login | only_avatar | name | login | nickname | firstname | lastname | fullname | preferredname
       
), $params );

    if( isset(
$CommentReplies[ $comment_ID ] ) )
    {
// This comment has the replies
       
foreach( $CommentReplies[ $comment_ID ] as $Comment )
        {
// Loop through the replies:
           
if( empty( $Comment->ID ) )
            {
// Get html tag of the comment block of preview
               
$comment_start = $Comment->email_is_detected ? $params['comment_error_start'] : $params['preview_start'];
            }
            else
            {
// Get html tag of the comment block of existing comment
               
$comment_start = $params['comment_start'];
            }

           
// Set margin left for each sub level comment
           
$attrs = ' style="margin-left:'.( 20 * $level ).'px"';
            if(
strpos( $comment_start, 'class="' ) === false )
            {
// Add a class attribute for the replied comment
               
$attrs .= ' class="replied_comment"';
            }
            else
            {
// Add a class name for the replied comment
               
$comment_start = str_replace( 'class="', 'class="replied_comment ', $comment_start );
            }
           
$comment_start = str_replace( '>', $attrs.'>', $comment_start );

            if( ! empty(
$Comment->ID ) )
            {
// Comment from DB
               
skin_include( $params['comment_template'], array_merge( $params, array(
                       
'Comment'          => & $Comment,
                       
'comment_start'    => $comment_start
                   
) ) );
            }
            else
            {
// PREVIEW comment
               
skin_include( $params['comment_template'], array_merge( $params, array(
                       
'Comment'              => & $Comment,
                       
'comment_block_start'  => $Comment->email_is_detected ? '' : $params['preview_block_start'],
                       
'comment_start'        => $comment_start,
                       
'comment_end'          => $Comment->email_is_detected ? $params['comment_error_end'] : $params['preview_end'],
                       
'comment_block_end'    => $Comment->email_is_detected ? '' : $params['preview_block_end'],
                       
'author_link_text'     => $params['author_link_text'],
                    ) ) );
            }

           
// Display the rest replies recursively
           
display_comment_replies( $Comment->ID, $params, $level + 1 );
        }
    }
}


/**
 * Dispay the replies of a comment on back-office
 *
 * @param integer Comment ID
 * @param array Params
 * @param integer Level
 */
function echo_comment_replies( $comment_ID, $params, $level = 1 )
{
    global
$CommentReplies;

    if( ! isset(
$CommentReplies[ $comment_ID ] ) )
    {    
// This comment has no replies, Exit here:
       
return false;
    }

   
$params = array_merge( array(
           
'redirect_to'        => NULL,
           
'save_context'       => false,
           
'display_meta_title' => false,
        ),
$params );

    foreach(
$CommentReplies[ $comment_ID ] as $Comment )
    {    
// Loop through the replies:

        // Display a comment:
       
echo_comment( $Comment, $params['redirect_to'], $params['save_context'], $Comment->get_inlist_order(), $params['display_meta_title'], $level );

       
// Display the rest replies recursively:
       
echo_comment_replies( $Comment->ID, $params, $level + 1 );
    }
}


/**
 * JS Behaviour: Output JavaScript code to reply the comments
 *
 * @param object Item
 */
function echo_comment_reply_js( $Item )
{
    global
$Collection, $Blog;

    if( ! isset(
$Blog ) || ! $Blog->get_setting( 'threaded_comments' ) )
    {    
// If threaded comments are not enabled for current Collection:
       
return false;
    }

   
$js_config = array(
           
'item_ID' => $Item->ID,
           
'reply_button_msg' => TS_('Reply to this comment'),
           
'link_back_url' => url_add_param( $Item->get_permanent_url(), 'reply_ID=\' + comment_ID + \'&amp;redir=no', '&amp;', false ),
           
'link_back_specific_comment_msg' => TS_('You are currently replying to a specific comment'),
           
'link_back_current_comment_msg' => TS_('You are currently replying to this comment'),
        );

   
expose_var_to_js( 'evo_init_comment_reply_config', $js_config );
}


/**
 * JS Behaviour: Output JavaScript code to moderate the comments
 * Vote on the comment
 * Change a status of the comment
 */
function echo_comment_moderate_js()
{
    if( !
is_logged_in( false ) )
    {
        return
false;
    }

    global
$Collection, $Blog;

    if( empty(
$Blog ) )
    {
        return
false;
    }

   
load_funcs( 'comments/model/_comment_js.funcs.php' );
}


/**
 * Check to display a form to mass delete the comments
 *
 * @param object Comment List
 * @return boolean TRUE - if a form is available
 */
function check_comment_mass_delete( $CommentList )
{
    if( !
check_user_perm( 'blogs', 'all' ) )
    {    
// Check permission
       
return false;
    }

    if(
$CommentList->get_total_rows() == 0 )
    {    
// No comments for current list
       
return false;
    }

   
// Form is available to mass delete the comments
   
return true;
}


/**
 * Check if autocomplete username is enabled
 *
 * @param object Comment object
 * @return boolean TRUE - if autocomplete username is enabled
 */
function check_autocomplete_usernames( $Comment )
{
    global
$Settings, $Collection, $Blog;

    if(
$Comment->is_meta() )
    {    
// Always enable autocomplete username for internal comments
       
return true;
    }
    elseif(
is_admin_page() && ! empty( $Blog ) )
    {    
// Check setting in the Back office or when Blog is not defined
       
return $Blog->get_setting( 'autocomplete_usernames' );
    }
    else
    {    
// Check setting in the Front office for current blog & skin
       
$SkinCache = & get_SkinCache();
       
$skin = & $SkinCache->get_by_ID( $Blog->get( 'skin_ID' ) );
        return
$skin->get_setting( 'autocomplete_usernames' );
    }

    return
false;
}


/**
 * Dispay a form to mass delete the comments
 *
 * @param object Comment List
 */
function display_comment_mass_delete( $CommentList )
{

   
$action = param_action();

    if(
$action != 'mass_delete' )
    {    
// Display this form only for action "mass_delete"
       
return;
    }

    if( !
check_comment_mass_delete( $CommentList ) )
    {    
// Form is not available
       
return;
    }

    require
dirname(__FILE__).'/../views/_comment_mass.form.php';
}


/**
 * Delete the comments
 *
 * @param string Type of deleting:
 *               'recycle' - to move into recycle bin
 *               'delete' - to delete permanently
 * @param string sql query to get deletable comment ids
 */
function comment_mass_delete_process( $mass_type, $deletable_comments_query )
{
    if(
$mass_type != 'recycle' && $mass_type != 'delete' )
    {
// Incorrect action
       
return;
    }

    global
$DB, $cache_comments_has_replies, $cache_items_user_data, $cache_postcats;

   
/**
     * Disable log queries because it increases the memory and stops the process with error "Allowed memory size of X bytes exhausted..."
     */
   
$DB->log_queries = false;

   
$Form = new Form();

   
$Form->begin_form( 'fform' );

   
$Form->begin_fieldset( T_('Mass deleting log') );

    echo
T_('The comments are deleting...');
   
evo_flush();

   
$CommentCache = & get_CommentCache();
   
$ItemCache = & get_ItemCache();
   
$ChapterCache = & get_ChapterCache();

   
// Get the comments by 1000 to avoid an exhausting of memory
   
$deletable_comment_ids = $DB->get_col( $deletable_comments_query.' LIMIT 1000' );
    while( !empty(
$deletable_comment_ids ) )
    {
       
// Get the first slice of the deletable comment ids list
       
$ids = array_splice( $deletable_comment_ids, 0, 100 );
       
// Make sure the CommentCache is empty
       
$CommentCache->clear();
       
// Load deletable comment ids
       
$CommentCache->load_list( $ids );

        while( (
$iterator_Comment = & $CommentCache->get_next() ) != NULL )
        {
// Delete all comments from CommentCache
           
$iterator_Comment->dbdelete( ($mass_type == 'delete') );
        }

       
// Display progress dot
       
echo ' .';
       
evo_flush();

        if( empty(
$deletable_comment_ids ) )
        {
           
// Clear all caches to save memory
           
$ItemCache->clear();
           
$ChapterCache->clear();
           
$cache_comments_has_replies = array();
           
$cache_items_user_data = array();
           
$cache_postcats = array();

           
// Get new portion of deletable comments
           
$deletable_comment_ids = $DB->get_col( $deletable_comments_query.' LIMIT 1000' );
        }
    }

    echo
' OK';

   
$Form->end_form();

   
// Clear a comment cache
   
$CommentCache->clear();
}


/**
 * Move all child comments to new post by parent comment ID
 *
 * @param integer/array Parent comment IDs
 * @param integer Item ID
 * @param boolean TRUE to convert a comment to root/top comment of the post
 */
function move_child_comments_to_item( $comment_IDs, $item_ID, $convert_to_root = true )
{
    global
$DB;

   
$child_comments_SQL = new SQL();
   
$child_comments_SQL->SELECT( 'comment_ID' );
   
$child_comments_SQL->FROM( 'T_comments' );
   
$child_comments_SQL->WHERE( 'comment_in_reply_to_cmt_ID IN ( '.$DB->quote( $comment_IDs ).' )' );
   
$child_comments_IDs = $DB->get_col( $child_comments_SQL->get() );

    if( empty(
$child_comments_IDs ) )
    {
// No child comments, Exit here
       
return;
    }

   
// Move the child comments recursively
   
move_child_comments_to_item( $child_comments_IDs, $item_ID, false );

   
// Update item ID to new
   
if( $convert_to_root )
    {
// Make these comments as root comments (remove their parent depending)
       
$update_sql = ', comment_in_reply_to_cmt_ID = NULL';
    }
   
$DB->query( 'UPDATE T_comments
        SET comment_item_ID = '
.$DB->quote( $item_ID ).$update_sql.'
        WHERE comment_in_reply_to_cmt_ID IN ( '
.$DB->quote( $comment_IDs ).' )' );
}


/**
 * Display comments results table
 *
 * @param array Params
 */
function comments_results_block( $params = array() )
{
   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'edited_User'          => NULL,
           
'results_param_prefix' => 'actv_comment_',
           
'results_title'        => T_('Comments posted by the user'),
           
'results_no_text'      => T_('User has not posted any comment yet'),
           
'action'               => '',
        ),
$params );

    if( !
is_logged_in() )
    {    
// Only logged in users can access to this function
       
return;
    }

    if( !
check_user_perm( 'users', 'moderate' ) )
    {    
// Check minimum permission:
       
return;
    }

   
$edited_User = $params['edited_User'];
    if( !
$edited_User )
    {    
// No defined User, probably the function is calling from AJAX request
       
$user_ID = param( 'user_ID', 'integer', 0 );
        if( empty(
$user_ID ) )
        {    
// Bad request, Exit here
           
return;
        }
       
$UserCache = & get_UserCache();
        if( (
$edited_User = & $UserCache->get_by_ID( $user_ID, false ) ) === false )
        {    
// Bad request, Exit here
           
return;
        }
    }

    global
$DB, $AdminUI;

   
param( 'user_tab', 'string', '', true );
   
param( 'user_ID', 'integer', 0, true );


   
$SQL = new SQL();
   
$SQL->SELECT( '*' );
   
$SQL->FROM( 'T_comments' );
   
$SQL->WHERE( 'comment_author_user_ID = '.$DB->quote( $edited_User->ID ) );

   
// Create result set:
   
$comments_Results = new Results( $SQL->get(), $params['results_param_prefix'], 'D' );
   
$comments_Results->Cache = & get_CommentCache();
   
$comments_Results->title = $params['results_title'];
   
$comments_Results->no_results_text = $params['results_no_text'];

    if(
$params['action'] != 'view' && $comments_Results->get_total_rows() > 0 && $edited_User->has_comment_to_delete() )
    {    
// Display action icon to delete all records if at least one record exists & current user can delete at least one comment posted by user
       
$comments_Results->global_icon( sprintf( T_('Delete all comments posted by %s'), $edited_User->login ), 'recycle', '?ctrl=user&amp;user_tab=activity&amp;action=delete_all_comments&amp;user_ID='.$edited_User->ID.'&amp;'.url_crumb('user'), ' '.T_('Delete all'), 3, 4 );
    }

   
// Initialize Results object
   
comments_results( $comments_Results, array(
           
'field_prefix' => 'comment_',
           
'display_kind' => false,
           
'display_additional_columns' => true,
           
'plugin_table_name' => 'activity',
           
'display_spam' => false,
        ) );

    if(
is_ajax_content() )
    {    
// init results param by template name
       
if( !isset( $params[ 'skin_type' ] ) || ! isset( $params[ 'skin_name' ] ) )
        {
           
debug_die( 'Invalid ajax results request!' );
        }
       
$comments_Results->init_params_by_skin( $params[ 'skin_type' ], $params[ 'skin_name' ] );
    }

   
$results_params = $AdminUI->get_template( 'Results' );
   
$display_params = array(
       
'before' => str_replace( '>', ' style="margin-top:25px" id="comments_result">', $results_params['before'] ),
    );
   
$comments_Results->display( $display_params );

    if( !
is_ajax_content() )
    {    
// Create this hidden div to get a function name for AJAX request
       
echo '<div id="'.$params['results_param_prefix'].'ajax_callback" style="display:none">'.__FUNCTION__.'</div>';
    }
}


/**
 * Initialize Results object for comments list
 *
 * @param object Results
 * @param array Params
 */
function comments_results( & $comments_Results, $params = array() )
{
   
// Make sure we are not missing any param:
   
$params = array_merge( array(
           
'field_prefix' => '',
           
'display_date' => true,
           
'display_permalink' => true,
           
'display_item' => false,
           
'display_status' => false,
           
'display_kind' => true,
           
'display_author' => true,
           
'display_url' => true,
           
'display_email' => true,
           
'display_ip' => true,
           
'display_additional_columns' => false,
           
'plugin_table_name' => '',
           
'display_spam' => true,
           
'display_visibility' => true,
           
'display_actions' => true,
           
'col_post' => T_('Post'),
        ),
$params );

    if(
$params['display_date'] )
    {    
// Display Date column
       
$td = '<span class="date">@date()@</span>';
        if(
$params['display_permalink'] )
        {
           
$td = '@get_permanent_link( get_icon(\'permalink\') )@ '.$td;
        }
       
$comments_Results->cols[] = array(
               
'th' => T_('Date'),
               
'order' => $params['field_prefix'].'date',
               
'default_dir' => 'D',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => $td,
            );
    }

    if(
$params['display_item'] )
    {    
// Display Date column
       
$td = '%{Obj}->get_permanent_item_link()%';
        if(
$params['display_status'] )
        {
// Dislpay status banner
           
$td = '%{Obj}->get_status( "styled" )%'.$td;
        }
       
$comments_Results->cols[] = array(
               
'th' => $params['col_post'],
               
'order' => $params['field_prefix'].'item_ID',
               
'td' => $td,
            );
    }

    if(
$params['display_kind'] )
    {    
// Display Kind column
       
$comments_Results->cols[] = array(
               
'th' => T_('Kind'),
               
'order' => $params['field_prefix'].'type',
               
'th_class' => 'nowrap',
               
'td' => '%get_type( {Obj} )%',
            );
    }

    if(
$params['display_author'] )
    {    
// Display Author column
       
$comments_Results->cols[] = array(
               
'th' => T_('Author'),
               
'order' => $params['field_prefix'].'author',
               
'th_class' => 'nowrap',
               
'td' => '%get_author( {Obj} )%',
            );
    }

    if(
$params['display_url'] )
    {    
// Display Url column
       
$comments_Results->cols[] = array(
               
'th' => T_('URL'),
               
'order' => $params['field_prefix'].'author_url',
               
'th_class' => 'nowrap',
               
'td' => '%get_url( {Obj} )%',
            );
    }

    if(
$params['display_email'] )
    {    
// Display Email column
       
$comments_Results->cols[] = array(
               
'th' => T_('Email'),
               
'order' => $params['field_prefix'].'author_email',
               
'th_class' => 'nowrap',
               
'td_class' => 'nowrap',
               
'td' => '%get_author_email( {Obj} )%',
            );
    }

    if(
$params['display_ip'] )
    {    
// Display IP column
       
$comments_Results->cols[] = array(
               
'th' => T_('IP'),
               
'order' => $params['field_prefix'].'author_IP',
               
'th_class' => 'nowrap',
               
'td_class' => 'nowrap',
               
'td' => '%get_author_ip( {Obj}, "'.$comments_Results->param_prefix.'" )%',
            );
    }


    if(
$params['display_additional_columns'] )
    {    
// Display additional columns from the Plugins
       
global $Plugins;
       
$Plugins->trigger_event( 'GetAdditionalColumnsTable', array(
           
'table'   => $params['plugin_table_name'],
           
'column'  => $params['field_prefix'].'author_IP',
           
'Results' => $comments_Results ) );
    }

    if(
$params['display_spam'] )
    {    
// Display Spam karma column
       
$comments_Results->cols[] = array(
               
'th' => T_('Spam karma'),
               
'order' => $params['field_prefix'].'spam_karma',
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%get_spam_karma( {Obj} )%'
           
);
    }

    if(
$params['display_visibility'] )
    {    
// Display Visibility column
       
$comments_Results->cols[] = array(
               
'th' => T_('Visibility'),
               
'order' => $params['field_prefix'].'status',
               
'th_class' => 'nowrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%{Obj}->get_status( "styled" )%',
            );
    }

    if(
$params['display_actions'] )
    {    
// Display Actions column
       
$comments_Results->cols[] = array(
               
'th' => T_('Actions'),
               
'th_class' => 'shrinkwrap',
               
'td_class' => 'shrinkwrap',
               
'td' => '%comment_edit_actions( {Obj} )%'
           
);
    }
}


/**
 * JS Behaviour: Output JavaScript code to change Item of the Comment
 */
function echo_comment_change_item_js()
{
    global
$Blog, $admin_url, $evo_comment_change_item_js_initialized;

    if( ! empty(
$evo_comment_change_item_js_initialized ) )
    {    
// Don't initialize this JS code twice on same page:
       
return;
    }

   
// Set flag to know this is initialized:
   
$evo_comment_change_item_js_initialized = true;

   
// Initialize JavaScript to build and open window:
   
echo_modalwindow_js();

   
// Initialize JavaScript for item selector window:
   
echo_item_selector_js();
?>
<script>
function evo_comment_change_item_load_window( item_ID )
{
    return evo_item_selector_load_window( item_ID,
        [ '<?php echo TS_('Link to Another Post'); ?>', '<?php echo T_('Link to Another Post'); ?>' ],
        false,
        [ { 'text': '<?php echo TS_('Link comment to this post'); ?>', 'id': 'evo_comment_change_item_btn', 'class': 'btn btn-primary' } ],
        <?php echo empty( $Blog ) ? 0 : $Blog->ID; // Default collection ?>,
        'collections', { list_in_frontoffice: 'all', per_page: -1 }
    );
}

// Submit form to link the Comment to another Item:
jQuery( document ).on( 'click', '#evo_comment_change_item_btn', function()
{
    var post = jQuery( '#evo_item_selector_dest_post_ID' ).data( 'post' )

    // Update info field link:
    var item_link = jQuery('.comment_item_title')[0];
    item_link.innerHTML = post.title;
    item_link.href = '<?php echo $admin_url; ?>?ctrl=items&blog=' + jQuery( '#evo_item_selector_colls_list' ).find( ':selected' ).data( 'coll-id' ) + '&p=' + jQuery( '#evo_item_selector_dest_post_ID').val();

    // Update moveto_post field:
    jQuery( 'input[name="moveto_post"]' ).val( jQuery('#evo_item_selector_dest_post_ID').val() );

    // Close main modal window:
    closeModalWindow();
} );
</script>
<?php
}


/**
 * Handles anonymous comment cookies
 *
 * @param boolean True to set cookie, false otherwise
 * @param string Value of anonymous comment author
 * @param string Value of anonymous comment author's email
 * @param string Value of anonymous comment author's URL
 * @param boolean True if anonymous URLs are allowed
 */
function handle_comment_cookies( $set_cookies, $author, $email = '', $url = '', $allow_anon_url = false )
{
    global
$cookie_name, $cookie_email, $cookie_url, $cookie_expires, $cookie_expired;

    if( !
is_logged_in() )
    {
        if(
$set_cookies )
        {    
// Set cookies:
           
if ($email == '')
               
$email = ' '; // this to make sure a cookie is set for 'no email'
           
if ($url == '')
               
$url = ' '; // this to make sure a cookie is set for 'no url'

            // fplanque: made cookies available for whole site
           
evo_setcookie( $cookie_name, $author, $cookie_expires, '', '', false, true );
           
evo_setcookie( $cookie_email, $email, $cookie_expires, '', '', false, true );
            if(
$allow_anon_url )
            {
               
evo_setcookie( $cookie_url, $url, $cookie_expires, '', '', false, true );
            }
        }
        else
        {    
// Erase cookies:
           
if( !empty( $_COOKIE[$cookie_name] ) )
            {
               
evo_setcookie( $cookie_name, '', $cookie_expired, '', '', false, true );
            }
            if( !empty(
$_COOKIE[$cookie_email] ) )
            {
               
evo_setcookie( $cookie_email, '', $cookie_expired, '', '', false, true );
            }
            if( !empty(
$_COOKIE[$cookie_url] ) )
            {
               
evo_setcookie( $cookie_url, '', $cookie_expired, '', '', false, true );
            }
        }
    }

   
// Send the predefined cookies:
   
evo_sendcookies();
}


/**
 * Helper functions to display Comments results.
 * New ( not display helper ) functions must be created above comments_results function
 */

/**
 * Get comment type.
 *
 * @param object Comment
 * @return string Comment type OR '---' if user has no permission to moderate this comment
 */
function get_type( $Comment )
{
    if(
$Comment->can_be_displayed() || check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
        return
$Comment->get( 'type' );
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment author
 *
 * @param object Comment
 * @return string Comment author OR '---' if user has no permission to moderate this comment
 */
function get_author( $Comment )
{
    if(
$Comment->can_be_displayed() || check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
       
$author_User = $Comment->get_author_User();
        if(
$author_User != NULL )
        {    
// author is a registered user
           
return $author_User->get_identity_link();
        }
       
// author is not a registered user
       
return $Comment->get_author( array( 'link_to' => 'userpage' )  );
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment author url
 *
 * @param object Comment
 * @return string Comment url OR '---' if user has no permission to moderate this comment
 */
function get_url( $Comment )
{
    if(
check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
        return
$Comment->author_url_with_actions( NULL, false );
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment author email
 *
 * @param object Comment
 * @return string Comment author email OR '---' if user has no permission to moderate this comment
 */
function get_author_email( $Comment )
{
    if(
check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
        return
$Comment->get_author_email();
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment author IP
 *
 * @param object Comment
 * @return string Comment author IP OR '---' if user has no permission to moderate this comment
 */
function get_author_ip( $Comment, $param_prefix = '' )
{
    if(
check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
        if( empty(
$Comment->author_IP ) )
        {
            return
'';
        }
        else
        {
           
$antispam_icon = get_icon( 'lightning', 'imgtag', array( 'title' => T_( 'Go to edit this IP address in antispam control panel' ) ) );
           
$antispam_link = ' '.implode( ', ', get_linked_ip_list( array( $Comment->author_IP ), NULL, $antispam_icon ) );

           
$filter_IP_url = regenerate_url( 'filter', $param_prefix.'author_IP='.$Comment->get( 'author_IP' ) );
           
$country = $Comment->get_ip_country( ' ' );

            return
'<a href="'.$filter_IP_url.'">'.$Comment->get( 'author_IP' ).'</a>'.$antispam_link.$country;
        }
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment spam karma
 *
 * @param object Comment
 * @return string Comment spam karma OR '---' if user has no permission to moderate this comment
 */
function get_spam_karma( $Comment )
{
    if(
check_user_perm( 'comment!CURSTATUS', 'moderate', false, $Comment ) )
    {
        return
$Comment->get( 'spam_karma' );
    }
    else
    {
        return
'<span class="dimmed">---</span>';
    }
}


/**
 * Get comment status
 *
 * @param object Comment
 * @return string Comment status OR '---' if user has no permission to edit this comment
 */
function get_colored_status( $Comment )
{
    return
'<span class="tdComment'.$Comment->get( 'status' ).'">'.$Comment->get( 't_status' ).'</span>';
}


/**
 * Get template for the styled status of comment or item
 *
 * @param string Status value
 * @param string Status title
 * @param string Status class
 * @return string Styled template for status
 */
// DEPRECATED: instead use something like: $Item->format_status( array(    'template' => '<div class="evo_status__banner evo_status__$status$">$status_title$</div>' ) );
function get_styled_status( $status_value, $status_title, $status_class = '' )
{
    return
'<div class="floatright">'
       
.'<span class="note status_'.$status_value.'">'
       
.'<span'.( empty( $status_class ) ? '' : ' class="'.$status_class.'"' ).'>'.format_to_output( $status_title ).'</span>'
       
.'</span>'
       
.'</div>';
}


/**
 * Get the edit actions for comment
 *
 * @param object Comment
 * @return string The edit actions
 */
function comment_edit_actions( $Comment )
{
    global
$admin_url;

   
$r = '';
    if( !
is_logged_in() )
    {
        return
$r;
    }

   
$user_has_edit_perm = check_user_perm( 'comment!CURSTATUS', 'edit', false, $Comment );
   
$user_has_delete_perm = check_user_perm( 'comment!CURSTATUS', 'delete', false, $Comment );

    if(
$user_has_edit_perm || $user_has_delete_perm )
    {
// Display edit and delete button if current user has the rights:
       
$redirect_to = rawurlencode( regenerate_url( 'comment_ID,action', 'filter=restore', '', '&' ) );

        if(
$user_has_edit_perm )
        {
// Display edit button only if current user can edit comment with current status
           
$Comment->get_Item();
           
$item_Blog = & $Comment->Item->get_Blog();
            if(
$item_Blog->get_setting( 'in_skin_editing' ) && !is_admin_page() )
            {
               
$edit_url = url_add_param( $item_Blog->gen_blogurl(), 'disp=edit_comment&amp;c='.$Comment->ID );
            }
            else
            {
               
$edit_url = $admin_url.'?ctrl=comments&amp;comment_ID='.$Comment->ID.'&amp;action=edit&amp;redirect_to='.$redirect_to;
            }
           
$r .= action_icon( TS_('Edit this comment').'...', 'properties', $edit_url );
        }

        if(
$user_has_delete_perm )
        {
// Display delete/recycle button because current user has permission to delete/recycle this comment
           
$params = array();
            if(
$Comment->status == 'trash' )
            {
// Comment is already in the recycle bin, display delete action and add js confirm
               
$title = T_('Delete this comment').'!';
               
$params['onclick'] = "return confirm('".TS_('You are about to delete this comment!\\nThis cannot be undone!')."')";
            }
            else
            {
// Comment will be moved into the recycle bin
               
$title = T_('Recycle this comment!');
            }

           
$r .=  action_icon( $title, 'recycle',
               
$admin_url.'?ctrl=comments&amp;comment_ID='.$Comment->ID.'&amp;action=delete&amp;'.url_crumb('comment')
                .
'&amp;redirect_to='.$redirect_to, NULL, NULL, NULL, $params );
        }
    }

    return
$r;
}

/**
 * End of helper functions block to display Comments results.
 * New ( not display helper ) functions must be created above comments_results function
 */

?>