'',
        'comment_item_type'                => '',
        'comment_db'                       => '',
        'comment_col'                      => '',
        'comment_item_id'                  => '',
        'clink'                            => '',
        'comment_allow_subject'            => TRUE,
        'comment_allow_reply'              => TRUE,
        'comment_allow_post'               => TRUE,
        'comment_allow_ratings'            => FALSE,
        'comment_allow_vote'               => TRUE,
        'comment_once'                     => FALSE,
        'comment_echo'                     => FALSE,
        'comment_title'                    => '',
        'comment_form_title'               => '',
        'comment_count'                    => TRUE,
        'comment_ui_template'              => 'display_comments_ui',
        'comment_template'                 => 'display_comments_section',
        'comment_form_template'            => 'display_comments_form',
        'comment_bbcode'                   => TRUE,
        'comment_tinymce'                  => FALSE,
        'comment_tinymce_skin'             => 'lightgray',
        'comment_custom_script'            => FALSE,
        'comment_post_callback_function'   => '', // trigger custom functions during post comment event
        'comment_edit_callback_function'   => '',  // trigger custom functions during reply event
        'comment_delete_callback_function' => '' // trigger custom functions during delete event
    ];
    private $jquery_enabled = FALSE;
    private $locale = [];
    private $userdata = [];
    private $settings = [];
    private $postLink = "";
    private $c_arr = [
        'c_con'  => [],
        'c_info' => [
            'c_makepagenav' => FALSE,
            'admin_link'    => FALSE
        ]
    ];
    private $comment_params = [];
    private $comment_data = [];
    private $cpp = 0;
    private function __construct() {
        // Set Settings
        $this->settings = fusion_get_settings();
        $this->jquery_enabled = FALSE; //fusion_get_settings('comments_jquery') ? TRUE : FALSE;
        // Set Global Locale
        $this->locale = fusion_get_locale('',
            [
                LOCALE.LOCALESET."comments.php",
                LOCALE.LOCALESET."user_fields.php",
                LOCALE.LOCALESET."ratings.php"
            ]
        );
        // Set current userdata
        $this->userdata = fusion_get_userdata();
        // Post link?
        $this->postLink = FUSION_SELF.(FUSION_QUERY ? "?".FUSION_QUERY : "");
        $this->postLink = preg_replace("^(&|\?)c_action=(edit|delete)&comment_id=\d*^", "", $this->postLink);
        // Comments Per Page
        $this->cpp = fusion_get_settings('comments_per_page');
    }
    /**
     * Get an instance by key
     *
     * @param array  $params
     * @param string $key
     *
     * @return static
     */
    public static function getInstance(array $params = [], $key = 'Default') {
        if (dbcount('(settings_name)', DB_SETTINGS, "settings_name=:jq", [':jq' => 'comments_jquery'])) {
            dbquery("DELETE FROM ".DB_SETTINGS." WHERE settings_name=:jq", [':jq' => 'comments_jquery']);
        }
        if (!isset(self::$instances[$key])) {
            self::$instances[$key] = new static();
            self::$key = $key;
            $params['comment_key'] = $key;
            self::$params = $params + self::$params;
            self::setInstance($key);
        }
        return self::$instances[$key];
    }
    private static function setInstance($key) {
        $obj = self::getInstance([], $key);
        $obj->setParams(self::$params);
        $obj->setEmptyCommentData();
        $obj->checkPermissions();
        $obj->execute_CommentUpdate();
        $obj->get_Comments();
    }
    /**
     * Displays Comments
     */
    public function showComments() {
        $comments_listing = '';
        $comments_form = '';
        $html = '';
        if ($this->settings['comments_enabled'] == TRUE) {
            $settings = fusion_get_settings();
            $comments_ui_template = $this->getParams('comment_ui_template');
            $comments_template = $this->getParams('comment_template');
            $comments_form_template = $this->getParams('comment_form_template');
            $clink = $this->getParams('clink');
            /**
             * Forms
             */
            if ($this->getParams('comment_allow_post')) {
                if (is_callable($comments_form_template)) {
                    $edata = [
                        'comment_cat'     => 0,
                        'comment_subject' => '',
                        'comment_message' => '',
                    ];
                    if (iMEMBER && (isset($_GET['c_action']) && $_GET['c_action'] == "edit") && (isset($_GET['comment_id']) && isnum($_GET['comment_id']))) {
                        $edit_query = "
                        SELECT tcm.*
                        FROM ".DB_COMMENTS." tcm
                        WHERE comment_id=:comment_id AND comment_item_id=:comment_item_id AND comment_type=:comment_type AND comment_hidden=:comment_hidden";
                        $edit_param = [
                            ':comment_id'      => $_GET['comment_id'],
                            ':comment_item_id' => $this->getParams('comment_item_id'),
                            ':comment_type'    => $this->getParams('comment_item_type'),
                            ':comment_hidden'  => 0,
                        ];
                        $e_result = dbquery($edit_query, $edit_param);
                        if (dbrows($e_result)) {
                            $edata = dbarray($e_result);
                            if ((iADMIN && checkrights("C")) || (iMEMBER && $edata['comment_name'] == fusion_get_userdata('user_id') && isset($edata['user_name']))) {
                                $clink = $this->getParams('clink')."&c_action=edit&comment_id=".$edata['comment_id'];
                            }
                        }
                    }
                    $can_post = iMEMBER || fusion_get_settings('guestposts') ? TRUE : FALSE;
                    // Comments form
                    //$form_action = fusion_get_settings('site_path').str_replace('../', '', self::format_clink($clink));
                    $form_action = self::format_clink($clink);
                    $comments_form = openform('inputform', 'post', $form_action, [
                            'form_id'    => $this->getParams('comment_key').'-inputform',
                            'remote_url' => fusion_get_settings('comments_jquery') ? fusion_get_settings('site_path')."includes/classes/PHPFusion/Feedback/Comments.ajax.php" : ''
                        ]
                    );
                    $ratings_input = '';
                    $_CAPTCHA_INPUT = '';
                    if ($can_post) {
                        $comments_form .= form_hidden('comment_id', '', '', ['input_id' => $this->getParams('comment_key').'-comment_id']);
                        $comments_form .= form_hidden('comment_cat', '', $edata['comment_cat'], ['input_id' => $this->getParams('comment_key').'-comment_cat']);
                        //$comments_form .= form_hidden('comment_key', '', $this->getParams('comment_key'), ['input_id' => $this->getParams('comment_key').'-comment_key']);
                        //$comments_form .= form_hidden('comment_options', '', \defender::serialize($this->getParams()), array('input_id' => $this->getParams('comment_key').'-comment_options'));
                        //$comments_form .= form_hidden('comment_item_id', '', $this->getParams('comment_item_id'), array('input_id' => $this->getParams('comment_key').'-comment_item_id'));
                        //$comments_form .= form_hidden('comment_item_type', '', $this->getParams('comment_item_type'), array('input_id' => $this->getParams('comment_key').'-comment_item_type'));
                        /*
                         * Ratings Selector
                         */
                        if (fusion_get_settings('ratings_enabled') && $this->getParams('comment_allow_ratings') && $this->getParams('comment_allow_vote')) {
                            $ratings_input .= form_select('comment_rating', $this->locale['r106'], '',
                                [
                                    'input_id' => $this->getParams('comment_key').'-comment_rating',
                                    'options'  => [
                                        5 => $this->locale['r120'],
                                        4 => $this->locale['r121'],
                                        3 => $this->locale['r122'],
                                        2 => $this->locale['r123'],
                                        1 => $this->locale['r124']
                                    ]
                                ]
                            );
                        }
                    }
                    // Captcha for Guest
                    if (!iMEMBER && fusion_get_settings('guestposts') == TRUE && (!isset($_CAPTCHA_HIDE_INPUT) || (isset($_CAPTCHA_HIDE_INPUT) && !$_CAPTCHA_HIDE_INPUT))) {
                        $_CAPTCHA_HIDE_INPUT = FALSE;
                        $_CAPTCHA_INPUT .= '
';
                        $_CAPTCHA_INPUT .= '
';
                        include INCLUDES.'captchas/'.$settings['captcha'].'/captcha_display.php';
                        $_CAPTCHA_INPUT .= display_captcha([
                            'captcha_id' => 'captcha_'.$this->getParams('comment_key'),
                            'input_id'   => 'captcha_code_'.$this->getParams('comment_key'),
                            'image_id'   => 'captcha_image_'.$this->getParams('comment_key')
                        ]);
                        $_CAPTCHA_INPUT .= '
';
                        $_CAPTCHA_INPUT .= '
';
                        if (!$_CAPTCHA_HIDE_INPUT) {
                            $_CAPTCHA_INPUT .= form_text('captcha_code', $this->locale['global_151'], '', ['required' => TRUE, 'autocomplete_off' => TRUE, 'input_id' => 'captcha_code_'.$this->getParams('comment_key')]);
                        }
                        $_CAPTCHA_INPUT .= '
';
                        $_CAPTCHA_INPUT .= '
';
                            $bal = 5 - $i;
                            $ratings .= "
\n";
                            for ($x = 1; $x <= $i; $x++) {
                                $ratings .= "\n";
                            }
                            for ($b = 1; $b <= $bal; $b++) {
                                $ratings .= "\n";
                            }
                            $ratings .= "(".($c_info['ratings_count'][$i] ?: 0).")";
                            $ratings .= "
\n
\n";
                            $progress_num = $c_info['ratings_count'][$i] == 0 ? 0 : round((($c_info['ratings_count'][$i] / $c_info['ratings_count']['total']) * 100), 1);
                            $ratings .= progress_bar($progress_num, '', ['height' => '10px', 'hide_info' => TRUE, 'progress_class' => 'm-0']);
                            $ratings .= "
\n";
                            $ratings .= '
'.$this->locale['c101'].'
']);
                ob_start();
                display_comments_listing();
                $comments = strtr(ob_get_clean(), [
                        '{%comments_page%}'       => ($this->c_arr['c_info']['c_makepagenav'] ? "".$this->c_arr['c_info']['c_makepagenav']."
\n" : ''),
                        '{%comments_list%}'       => (!empty($this->c_arr['c_con']) ? $this->display_all_comments($this->c_arr['c_con'], 0, $this->getParams()) : $no_comments_text),
                        '{%comments_admin_link%}' => $this->c_arr['c_info']['admin_link'],
                    ]
                );
                ob_start();
                $comments_template($this->c_arr['c_con'], $this->c_arr['c_info'], $this->getParams());
                $comments_listing = strtr(ob_get_clean(), [
                        '{%comment_count%}'   => ($this->getParams('comment_count') ? $this->c_arr['c_info']['comments_count'] : ''),
                        '{%comment_ratings%}' => $ratings_html,
                        '{%comments%}'        => $comments,
                        '{%comments_form%}'   => $comments_form
                    ]
                );
            } else {
                trigger_error('function '.$comments_template.' not found or declared too late. Is defined in your theme?');
            }
            if (is_callable($comments_ui_template)) {
                ob_start();
                $comments_ui_template();
                $html .= strtr(ob_get_clean(), [
                    '{%comment_title%}'             => $this->getParams('comment_title'),
                    '{%comment_count%}'             => ($this->getParams('comment_count') ? $this->c_arr['c_info']['comments_count'] : ''),
                    '{%comment_container_id%}'      => $this->getParams('comment_key'),
                    '{%comment_form_container_id%}' => $this->getParams('comment_key').'-comments_form',
                    '{%comments_listing%}'          => $comments_listing,
                    '{%comments_form%}'             => $comments_form,
                ]);
            } else {
                trigger_error('function '.$comments_ui_template.' not found or declared too late. Is defined in your theme?');
            }
        }
        if ($this->getParams('comment_echo')) {
            echo $html;
            /*
             * Note: Required to output to prevent broken select2.
             * Original ajax script to be removed to prevent event bubbling
             */
            if ($this->jquery_enabled === TRUE) {
                if (!defined("COMMENTS_JQUERY_SCRIPT")) {
                    define("COMMENTS_JQUERY_SCRIPT", TRUE);
                    $jquery_tags = OutputHandler::$jqueryTags;
                    $comment_js = str_replace([""], [], $this->buildJavascript());
                    $jquery_tags = str_replace($comment_js, '', $jquery_tags);
                    echo "\n";
                }
            }
        }
        return $html;
    }
    /**
     * Comments Listing
     *
     * @param     $c_data
     * @param int $index
     * @param     $options
     *
     * @return string
     */
    private function display_all_comments($c_data, $index = 0, $options) {
        $comments_html = '';
        //print_p(debug_backtrace());
        foreach ($c_data[$index] as $comments_id => $data) {
            $data['comment_ratings'] = '';
            if (fusion_get_settings('ratings_enabled') && $this->getParams('comment_allow_ratings')) {
                $data['comment_ratings'] .= "\n";
                $remainder = 5 - (int)$data['ratings'];
                for ($i = 1; $i <= $data['ratings']; $i++) {
                    $data['comment_ratings'] .= "\n";
                }
                if ($remainder) {
                    for ($i = 1; $i <= $remainder; $i++) {
                        $data['comment_ratings'] .= "\n";
                    }
                }
                $data['comment_ratings'] .= "
\n";
            }
            $data_api = \defender::encode($options);
            $comments_html .= "\n";
            ob_start();
            display_comments_list($data);
            $comments_html .= strtr(ob_get_clean(), [
                    '{%comment_list_id%}'      => 'c'.$data['comment_id'],
                    '{%user_avatar%}'          => $data['user_avatar'],
                    '{%user_name%}'            => $data['comment_name'],
                    '{%comment_date%}'         => $data['comment_datestamp'],
                    '{%comment_ratings%}'      => $data['comment_ratings'],
                    '{%comment_subject%}'      => $data['comment_subject'],
                    '{%comment_message%}'      => $data['comment_message'],
                    '{%comment_reply_link%}'   => ($data['reply_link'] ? "" : ''),
                    '{%comment_edit_link%}'    => ($data['edit_link'] ? "" : ''),
                    '{%comment_delete_link%}'  => ($data['delete_link'] ? "" : ''),
                    '{%comment_reply_form%}'   => ($data['reply_form'] ?: ''),
                    '{%comment_sub_comments%}' => (isset($c_data[$data['comment_id']]) ? $this->display_all_comments($c_data, $data['comment_id'], $options) : '')
                ]
            );
            $comments_html .= "";
        }
        return $comments_html;
    }
    private function checkPermissions() {
        $my_id = fusion_get_userdata('user_id');
        if (dbcount("(rating_id)", DB_RATINGS, "
            rating_user='".$my_id."'
            AND rating_item_id='".$this->getParams('comment_item_id')."'
            AND rating_type='".$this->getParams('comment_item_type')."'
            "
        )
        ) {
            $this->replaceParam('comment_allow_vote', FALSE); // allow ratings
        }
        if (dbcount("(comment_id)", DB_COMMENTS, "
            comment_name='".$my_id."' AND comment_cat='0'
            AND comment_item_id='".$this->getParams('comment_item_id')."'
            AND comment_type='".$this->getParams('comment_item_type')."'
            "
            )
            && $this->getParams('comment_once')
        ) {
            $this->replaceParam('comment_allow_post', FALSE); // allow post
        }
    }
    /**
     * Get Comment Object Parameter
     *
     * @param null $key - null for all array
     *
     * @return null
     */
    public function getParams($key = NULL) {
        if ($key !== NULL) {
            return isset($this->comment_params[self::$key][$key]) ? $this->comment_params[self::$key][$key] : NULL;
        }
        return $this->comment_params[self::$key];
    }
    /**
     * Replace Comment Object Parameter
     *
     * @param $param
     * @param $value
     */
    public function replaceParam($param, $value) {
        if (isset($this->comment_params[self::$key][$param])) {
            $this->comment_params[self::$key][$param] = $value;
        }
    }
    /**
     * Set Comment Object Parameters
     *
     * @param array $params
     */
    private function setParams(array $params = []) {
        $this->comment_params[self::$key] = $params;
    }
    private function setEmptyCommentData() {
        $this->comment_data = [
            'comment_id'        => isset($_GET['comment_id']) && isnum($_GET['comment_id']) ? $_GET['comment_id'] : 0,
            'comment_name'      => '',
            'comment_subject'   => '',
            'comment_message'   => '',
            'comment_datestamp' => TIME,
            'comment_item_id'   => $this->getParams('comment_item_id'),
            'comment_type'      => $this->getParams('comment_item_type'),
            'comment_cat'       => 0,
            'comment_ip'        => USER_IP,
            'comment_ip_type'   => USER_IP_TYPE,
            'comment_hidden'    => 0,
        ];
    }
    private function execute_CommentUpdate() {
        $this->replaceParam('comment_user', $this->userdata['user_id']);
        /**
         * Documentation for Ajax Token and Fields.
         * To do remote calls for token,
         * 1. the openform shall register the remote url full path
         * 2. in your jquery - POST the `form id`
         */
        if ($this->jquery_enabled === TRUE) {
            if (!defined("COMMENTS_JQUERY_SCRIPT")) {
                define("COMMENTS_JQUERY_SCRIPT", TRUE);
                if (!$this->getParams('comment_custom_script')) {
                    $comment_js = str_replace([""], [], $this->buildJavascript());
                    add_to_jquery($comment_js);
                }
            }
        } else {
            // Non Jquery Actions
            if (isset($_GET['comment_reply'])) {
                add_to_jquery("scrollTo('comments_reply_form');");
            }
            /** Delete */
            if (isset($_GET['c_action']) && iMEMBER) {
                if ($_GET['c_action'] == 'delete') {
                    $delete_query = "
                    SELECT tcm.*, tcu.user_name
                    FROM ".DB_COMMENTS." tcm
                    LEFT JOIN ".DB_USERS." tcu ON tcm.comment_name=tcu.user_id
                    WHERE comment_id=:comment_id AND comment_hidden=:comment_hidden
                    ";
                    $delete_param = [
                        ':comment_id'     => intval(stripinput($_GET['comment_id'])),
                        ':comment_hidden' => 0,
                    ];
                    $eresult = dbquery($delete_query, $delete_param);
                    if (dbrows($eresult)) {
                        $edata = dbarray($eresult);
                        $redirect_link = $this->getParams('clink').($this->settings['comments_sorting'] == "ASC" ? "" : "&c_start=0")."#c".$_GET['comment_id'];
                        $child_query = "SELECT comment_id FROM ".DB_COMMENTS." WHERE comment_cat=:comment_cat_id";
                        $child_param = [':comment_cat_id' => intval($_GET['comment_id'])];
                        $result = dbquery($child_query, $child_param);
                        if (dbrows($result)) {
                            while ($child = dbarray($result)) {
                                dbquery("UPDATE ".DB_COMMENTS." SET comment_cat='".$edata['comment_cat']."' WHERE comment_id='".$child['comment_id']."'");
                            }
                        }
                        dbquery("DELETE FROM ".DB_COMMENTS." WHERE comment_id='".$edata['comment_id']."'".(iADMIN ? "" : "AND comment_name='".$this->userdata['user_id']."'"));
                        $func = $this->getParams('comment_delete_callback_function');
                        if (is_callable($func)) {
                            $func($this->getParams());
                        }
                        redirect($redirect_link);
                    }
                }
            }
        }
        /** Update & Save */
        // Ratings Removal Update
        // post comment_type, comment_item_id, remove_ratings_vote;
        if (iMEMBER && $this->getParams('comment_allow_ratings') && !$this->getParams('comment_allow_vote')) {
            if (isset($_POST['remove_ratings_vote'])) {
                $my_id = fusion_get_userdata('user_id');
                $delete_ratings = "DELETE FROM ".DB_RATINGS."
                WHERE rating_item_id='".$this->getParams('comment_item_id')."'
                AND rating_type = '".$this->getParams('comment_item_type')."'
                AND rating_user = '$my_id'";
                $result = dbquery($delete_ratings);
                if ($result) {
                    redirect(self::format_clink($this->getParams('clink')));
                }
            }
        }
        /**
         * Post Comment, Reply Comment
         */
        if ((iMEMBER || $this->settings['guestposts']) && isset($_POST['post_comment'])) {
            if (!iMEMBER && $this->settings['guestposts']) {
                // Process Captchas
                $_CAPTCHA_IS_VALID = FALSE;
                include INCLUDES."captchas/".$this->settings['captcha']."/captcha_check.php";
                if (!$_CAPTCHA_IS_VALID) {
                    \defender::stop();
                    addNotice("danger", $this->locale['u194']);
                }
            }
            $default_comment_id = isset($_POST['comment_id']) && isnum($_POST['comment_id']) ? intval($_POST['comment_id']) : 0;
            $comment_data = [
                'comment_id'      => isset($_GET['comment_id']) && isnum($_GET['comment_id']) ? $_GET['comment_id'] : $default_comment_id,
                'comment_name'    => iMEMBER ? $this->userdata['user_id'] : form_sanitizer($_POST['comment_name'], '', 'comment_name'),
                'comment_subject' => empty($_POST['comment_cat']) && isset($_POST['comment_subject']) ? form_sanitizer($_POST['comment_subject'], '', 'comment_subject') : '',
                'comment_item_id' => $this->getParams('comment_item_id'),
                'comment_type'    => $this->getParams('comment_item_type'),
                'comment_cat'     => form_sanitizer($_POST['comment_cat'], 0, 'comment_cat'),
                'comment_ip'      => USER_IP,
                'comment_ip_type' => USER_IP_TYPE,
                'comment_hidden'  => 0,
            ];
            // there is a conflict. the form above and the form below is same?
            $comment_data['comment_message'] = $comment_data['comment_cat'] ? form_sanitizer($_POST['comment_message_reply'], '', 'comment_message_reply') : form_sanitizer($_POST['comment_message'], '', 'comment_message');
            $ratings_query = "
            SELECT rating_id FROM ".DB_RATINGS." WHERE rating_item_id='".$comment_data['comment_item_id']."'
            AND rating_type='".$comment_data['comment_type']."' AND rating_user='".$comment_data['comment_name']."'
            ";
            $ratings_data = [];
            $ratings_id = dbresult(dbquery($ratings_query), 0);
            if ($this->getParams('comment_allow_ratings') && $this->getParams('comment_allow_vote') && isset($_POST['comment_rating'])) {
                $ratings_data = [
                    'rating_id'        => $ratings_id,
                    'rating_item_id'   => $this->getParams('comment_item_id'),
                    'rating_type'      => $this->getParams('comment_item_type'),
                    'rating_user'      => $comment_data['comment_name'],
                    'rating_vote'      => form_sanitizer($_POST['comment_rating'], 0, 'comment_rating'),
                    'rating_datestamp' => TIME,
                    'rating_ip'        => USER_IP,
                    'rating_ip_type'   => USER_IP_TYPE
                ];
            }
            if (iMEMBER && $comment_data['comment_id']) {
                // Update comment
                if ((iADMIN && checkrights("C")) || (iMEMBER && dbcount("(comment_id)", DB_COMMENTS, "comment_id='".$comment_data['comment_id']."'
                        AND comment_item_id='".$this->getParams('comment_item_id')."'
                        AND comment_type='".$this->getParams('comment_item_type')."'
                        AND comment_name='".$this->userdata['user_id']."'
                        AND comment_hidden='0'")) && \defender::safe()
                ) {
                    $c_name_query = "SELECT comment_name FROM ".DB_COMMENTS." WHERE comment_id='".$comment_data['comment_id']."'";
                    $comment_data['comment_name'] = dbresult(dbquery($c_name_query), 0);
                    dbquery_insert(DB_COMMENTS, $comment_data, 'update');
                    $this->comment_params[self::$key]['post_id'] = $comment_data['comment_id'];
                    $func = $this->getParams('comment_edit_callback_function');
                    if (is_callable($func)) {
                        $func($this->getParams());
                    }
                    if (iMEMBER && $this->getParams('comment_allow_ratings') && $this->getParams('comment_allow_vote')) {
                        dbquery_insert(DB_RATINGS, $ratings_data, ($ratings_data['rating_id'] ? 'update' : 'save'));
                    }
                    if ($this->settings['comments_sorting'] == "ASC") {
                        $c_operator = "<=";
                    } else {
                        $c_operator = ">=";
                    }
                    $c_count = dbcount("(comment_id)", DB_COMMENTS, "comment_id".$c_operator."'".$comment_data['comment_id']."'
                            AND comment_item_id='".$this->getParams('comment_item_id')."'
                            AND comment_type='".$this->getParams('comment_item_type')."'");
                    $c_start = (ceil($c_count / $this->settings['comments_per_page']) - 1) * $this->settings['comments_per_page'];
                    if ($this->jquery_enabled === FALSE && \defender::safe()) {
                        addNotice("success", $this->locale['c114']);
                        $_c = (isset($c_start) && isnum($c_start) ? $c_start : "");
                        $c_link = $this->getParams('clink');
                        redirect(self::format_clink("$c_link&c_start=$_c"));
                    }
                }
            } else {
                $comment_data['comment_datestamp'] = TIME;
                if (\defender::safe()) {
                    $c_start = 0;
                    if ($comment_data['comment_name'] && $comment_data['comment_message']) {
                        require_once INCLUDES."flood_include.php";
                        if (!flood_control("comment_datestamp", DB_COMMENTS, "comment_ip='".USER_IP."'")) {
                            $id = dbquery_insert(DB_COMMENTS, $comment_data, 'save');
                            $this->comment_params[self::$key]['post_id'] = $id;
                            $func = $this->getParams('comment_post_callback_function');
                            if (is_callable($func)) {
                                $func($this->getParams());
                            }
                            if (iMEMBER && fusion_get_settings('ratings_enabled') && $this->getParams('comment_allow_ratings') && $this->getParams('comment_allow_vote')) {
                                dbquery_insert(DB_RATINGS, $ratings_data, ($ratings_data['rating_id'] ? 'update' : 'save'));
                            }
                            if ($this->settings['comments_sorting'] == "ASC") {
                                $c_count = dbcount("(comment_id)", DB_COMMENTS, "comment_item_id='".$this->getParams('comment_item_id')."' AND comment_type='".$this->getParams('comment_item_type')."'");
                                $c_start = (ceil($c_count / $this->settings['comments_per_page']) - 1) * $this->settings['comments_per_page'];
                            }
                            if (!$this->jquery_enabled) {
                                redirect(self::format_clink($this->getParams('clink'))."&c_start=".$c_start."#c".$id);
                            }
                        }
                    }
                }
            }
        }
    }
    // This is singular. We cannot have many multiple ones for every instance.
    // All will post towards the last box on multiple instance.
    private function buildJavascript() {
        return "
        
        ";
    }
    /**
     * Removes comment reply
     *
     * @param $clink
     *
     * @return string
     */
    private static $clink = [];
    private static function format_clink($clink) {
        if (empty(self::$clink[$clink])) {
            $fusion_query = [];
            $url = $url = ((array)parse_url(htmlspecialchars_decode($clink))) + [
                    'path'  => '',
                    'query' => ''
                ];
            if ($url['query']) {
                parse_str($url['query'], $fusion_query); // this is original.
            }
            $fusion_query = array_diff_key($fusion_query, array_flip(["comment_reply"]));
            $prefix = $fusion_query ? '?' : '';
            self::$clink[$clink] = $url['path'].$prefix.http_build_query($fusion_query, NULL, '&');
        }
        return (string)self::$clink[$clink];
    }
    private static $c_start = 0;
    /*
     * Fetches Comment Data
     */
    private function get_Comments() {
        if (fusion_get_settings('comments_enabled')) {
            if ($this->getParams('comment_allow_ratings')) {
                $ratings_query = "
                SELECT
                COUNT(rating_id) 'total',
                IF(avg(rating_vote), avg(rating_vote), 0) 'avg',
                SUM(IF(rating_vote='5', 1, 0)) '5',
                SUM(IF(rating_vote='4', 1, 0)) '4',
                SUM(IF(rating_vote='3', 1, 0)) '3',
                SUM(IF(rating_vote='2', 1, 0)) '2',
                SUM(IF(rating_vote='1', 1, 0)) '1'
                FROM ".DB_RATINGS."
                WHERE rating_type=:ratings_type AND rating_item_id=:ratings_item_id
                ";
                $ratings_bind = [
                    ':ratings_type'    => $this->getParams('comment_item_type'),
                    ':ratings_item_id' => $this->getParams('comment_item_id')
                ];
                $this->c_arr['c_info']['ratings_count'] = dbarray(dbquery($ratings_query, $ratings_bind));
                $this->c_arr['c_info']['ratings_remove_form'] = '';
                if ($this->getParams('comment_allow_ratings') && !$this->getParams('comment_allow_vote')) {
                    $ratings_html = openform('remove_ratings_frm', 'post', $this->getParams('clink'), [
                            'class'   => 'text-right',
                            'form_id' => $this->getParams('comment_key')."-remove_ratings_frm",
                        ]
                    );
                    $ratings_html .= form_hidden('comment_type', '', $this->getParams('comment_item_type'));
                    $ratings_html .= form_hidden('comment_item_id', '', $this->getParams('comment_item_id'));
                    $ratings_html .= form_button('remove_ratings_vote', $this->locale['r102'], 'remove_ratings_vote', ['input_id' => $this->getParams('comment_key')."-remove_ratings_vote", 'class' => 'btn-default btn-rmRatings']);
                    $ratings_html .= closeform();
                    $this->c_arr['c_info']['ratings_remove_form'] = $ratings_html;
                }
            }
            $this->c_arr['c_info']['comments_count'] = format_word(0, $this->locale['fmt_comment']);
            $this->c_arr['c_info']['total_comments'] = 0;
            $c_rows = dbcount("('comment_id')", DB_COMMENTS, "comment_item_id=:comment_item_id AND comment_type=:comment_item_type AND comment_hidden=:comment_hidden",
                [
                    ':comment_item_id'   => $this->getParams('comment_item_id'),
                    ':comment_item_type' => $this->getParams('comment_item_type'),
                    ':comment_hidden'    => 0
                ]
            );
            $this->c_arr['c_info']['total_comments'] = $c_rows;
            $root_comment_rows = dbcount("(comment_id)", DB_COMMENTS, "comment_item_id=:comment_item_id AND comment_type=:comment_item_type AND comment_cat=:zero AND comment_hidden=:zero2",
                [
                    ':comment_item_type' => $this->getParams('comment_item_type'),
                    ':comment_item_id'   => $this->getParams('comment_item_id'),
                    ':zero'              => 0,
                    ':zero2'             => 0,
                ]);
            if ($root_comment_rows) {
                // Pagination control string
                self::$c_start = isset($_GET['c_start_'.$this->getParams('comment_key')]) && isnum($_GET['c_start_'.$this->getParams('comment_key')]) ? $_GET['c_start_'.$this->getParams('comment_key')] : 0;
                // Only applicable if sorting is Ascending. If descending, the default $c_start is always 0 as latest.
                if (fusion_get_settings('comments_sorting') == 'ASC') {
                    $getname = 'c_start_'.$this->getParams('comment_key');
                    if (!isset($_GET[$getname]) && $root_comment_rows > $this->cpp) {
                        self::$c_start = (ceil($root_comment_rows / $this->cpp) - 1) * $this->cpp;
                    }
                }
                $comment_query = "
                    SELECT tcm.* ".($this->getParams('comment_allow_ratings') && fusion_get_settings('ratings_enabled') ? ", tcr.rating_vote 'ratings'" : '')."
                    FROM ".DB_COMMENTS." tcm
                    ".($this->getParams('comment_allow_ratings') && fusion_get_settings('ratings_enabled') ? "LEFT JOIN ".DB_RATINGS." tcr ON tcr.rating_item_id=tcm.comment_item_id AND tcr.rating_type=tcm.comment_type" : '')."
                    WHERE comment_item_id=:comment_item_id AND comment_type=:comment_item_type AND comment_hidden=:comment_hidden AND comment_cat = 0
                    ORDER BY comment_id ASC, comment_datestamp ".$this->settings['comments_sorting'].", comment_cat ASC LIMIT ".self::$c_start.", ".$this->cpp."
                ";
                $comment_bind = [
                    ':comment_item_id'   => $this->getParams('comment_item_id'),
                    ':comment_item_type' => $this->getParams('comment_item_type'),
                    ':comment_hidden'    => 0
                ];
                $query = dbquery($comment_query, $comment_bind);
                if (dbrows($query)) {
                    $i = ($this->settings['comments_sorting'] == "ASC" ? self::$c_start + 1 : $root_comment_rows - self::$c_start);
                    if ($root_comment_rows > $this->cpp) {
                        // The $c_rows is different than
                        $this->c_arr['c_info']['c_makepagenav'] = makepagenav(self::$c_start, $this->cpp, $root_comment_rows, 3, $this->getParams('clink').(stristr($this->getParams('clink'), '?') ? "&" : '?'), "c_start_".$this->getParams('comment_key'));
                    }
                    if (iADMIN && checkrights('C')) {
                        $this->c_arr['c_info']['admin_link'] = "\n";
                        $this->c_arr['c_info']['admin_link'] .= "getParams('comment_item_id')."'>".$this->locale['c106']."";
                    }
                    while ($row = dbarray($query)) {
                        $this->parse_comments_data($row, $i);
                        $this->settings['comments_sorting'] == "ASC" ? $i++ : $i--;
                    }
                    $this->c_arr['c_info']['comments_per_page'] = $this->cpp;
                    $this->c_arr['c_info']['comments_count'] = format_word(number_format($this->c_arr['c_info']['total_comments'], 0), $this->locale['fmt_comment']);
                }
            }
        }
    }
    /*
     * Parse Comment Results
     */
    private function parse_comments_data($row, $i) {
        $can_reply = iMEMBER || fusion_get_settings('guestposts') ? TRUE : FALSE;
        $garray = [];
        if (!isnum($row['comment_name'])) {
            $garray = [
                'user_id'     => 0,
                'user_name'   => $row['comment_name'],
                'user_avatar' => '',
                'user_status' => 0,
            ];
        }
        $row = array_merge_recursive($row, isnum($row['comment_name']) ? fusion_get_user($row['comment_name']) : $garray);
        $actions = [
            'edit_link'   => '',
            'delete_link' => '',
            'edit_dell'   => ''
        ];
        if ((iADMIN && checkrights("C")) || (iMEMBER && $row['comment_name'] == $this->userdata['user_id'] && isset($row['user_name']))) {
            $edit_link = $this->getParams('clink')."&c_action=edit&comment_id=".$row['comment_id']."#edit_comment"; //clean_request('c_action=edit&comment_id='.$row['comment_id'], array('c_action', 'comment_id'),FALSE)."#edit_comment";
            $delete_link = $this->getParams('clink')."&c_action=delete&comment_id=".$row['comment_id']; //clean_request('c_action=delete&comment_id='.$row['comment_id'], array('c_action', 'comment_id'), FALSE);
            $data_api = \defender::serialize($this->getParams());
            $comment_actions = "
                            
                            
                                
                                
                            
                            
                            ";
            $actions = [
                "edit_link"   => ['link' => $edit_link, 'name' => $this->locale['edit']],
                "delete_link" => ['link' => $delete_link, 'name' => $this->locale['delete']],
                "edit_dell"   => $comment_actions
            ];
        }
        // Reply Form
        $reply_form = '';
        if ($this->getParams('comment_allow_reply') && (isset($_GET['comment_reply']) && $_GET['comment_reply'] == $row['comment_id']) && $can_reply
            || $this->getParams('comment_allow_reply') && $this->jquery_enabled
        ) {
            $this->comment_data['comment_cat'] = $row['comment_id'];
            if ($this->jquery_enabled === TRUE) {
                $reply_form .= "";
                $reply_form .= "";
            }
        }
        /** formats $row */
        $row = [
                "comment_id"        => $row['comment_id'],
                "comment_cat"       => $row['comment_cat'],
                "i"                 => $i,
                "user_avatar"       => isnum($row['comment_name']) ? display_avatar($row, '50px', '', FALSE, 'm-t-5') : display_avatar([], '50px', '', FALSE, 'm-t-5'),
                "user"              => [
                    "user_id"     => $row['user_id'],
                    "user_name"   => $row['user_name'],
                    "user_avatar" => $row['user_avatar'],
                    "status"      => $row['user_status'],
                ],
                "reply_link"        => $can_reply == TRUE ? self::format_clink($this->getParams('clink')).'&comment_reply='.$row['comment_id'].'#c'.$row['comment_id'] : '',
                "reply_form"        => $reply_form,
                'ratings'           => isset($row['ratings']) ? $row['ratings'] : '',
                "comment_datestamp" => showdate('longdate', $row['comment_datestamp']),
                "comment_time"      => timer($row['comment_datestamp']),
                "comment_subject"   => $row['comment_subject'],
                "comment_message"   => nl2br(parseubb(parsesmileys($row['comment_message']))),
                "comment_name"      => isnum($row['comment_name']) ? profile_link($row['comment_name'], $row['user_name'], $row['user_status']) : $row['comment_name']
            ] + $actions;
        // can limit and use a show more comments.
        $c_result = dbquery("SELECT * FROM ".DB_COMMENTS." WHERE comment_cat=:comment_cat", [':comment_cat' => $row['comment_id']]);
        if (dbrows($c_result)) {
            $x = 1;
            while ($c_rows = dbarray($c_result)) {
                $this->parse_comments_data($c_rows, $x);
                $this->settings['comments_sorting'] == "ASC" ? $x++ : $x--;
            }
        }
        $id = $row['comment_id'];
        $parent_id = $row['comment_cat'] === NULL ? "0" : $row['comment_cat'];
        $data[$id] = $row;
        $this->c_arr['c_con'][$parent_id][$id] = $row;
    }
}
require_once(__DIR__.'/Comments.view.php');
\n"; $_CAPTCHA_HTML .= "
\n\n"; } $_CAPTCHA_HTML .= "