HEX
Server: Apache
System: Linux p3plzcpnl506847.prod.phx3.secureserver.net 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: slfopp7cb1df (5698090)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: /home/slfopp7cb1df/public_html/conradinvestmentgroup.com/pm/app/Controllers/Tickets.php
<?php

namespace App\Controllers;

class Tickets extends Security_Controller {

    protected $Ticket_templates_model;
    protected $Pin_comments_model;

    function __construct() {
        parent::__construct();
        $this->init_permission_checker("ticket");

        $this->Ticket_templates_model = model('App\Models\Ticket_templates_model');
        $this->Pin_comments_model = model('App\Models\Pin_comments_model');
    }

    private function validate_ticket_access($ticket_id = 0) {
        if (!$this->can_access_tickets($ticket_id)) {
            app_redirect("forbidden");
        }
    }

    private function _validate_tickets_report_access() {
        if (!$this->login_user->is_admin && $this->access_type != "all") {
            app_redirect("forbidden");
        }
    }

    //only admin can delete tickets
    protected function can_delete_tickets() {
        return $this->login_user->is_admin;
    }

    // load ticket list view
    function index($status = "", $ticket_type_id = 0, $client_id = 0, $ticket_id = 0) {
        $this->check_module_availability("module_ticket");
        validate_numeric_value($client_id);
        validate_numeric_value($ticket_id);

        $view_data["custom_field_headers"] = $this->Custom_fields_model->get_custom_field_headers_for_table("tickets", $this->login_user->is_admin, $this->login_user->user_type);
        $view_data["custom_field_filters"] = $this->Custom_fields_model->get_custom_field_filters("tickets", $this->login_user->is_admin, $this->login_user->user_type);

        $view_data['show_project_reference'] = get_setting('project_reference_in_tickets');

        $view_data['status'] = clean_data($status);

        $view_data['ticket_id'] = $ticket_id;

        if ($this->login_user->user_type === "staff") {

            //prepare ticket label filter list
            $view_data['ticket_labels_dropdown'] = json_encode($this->make_labels_dropdown("ticket", "", true));

            $view_data['show_options_column'] = true; //team members can view the options column

            $view_data['assigned_to_dropdown'] = json_encode($this->_get_assiged_to_dropdown());

            $view_data['ticket_types_dropdown'] = json_encode($this->_get_ticket_types_dropdown_list_for_filter($ticket_type_id));

            $view_data['clients_dropdown'] = json_encode($this->_get_clients_dropdown($client_id));

            return $this->template->rander("tickets/tickets_list", $view_data);
        } else {
            if (!$this->can_client_access("ticket")) {
                app_redirect("forbidden");
            }

            $view_data['client_id'] = $this->login_user->client_id;
            $view_data['page_type'] = "full";
            return $this->template->rander("clients/tickets/index", $view_data);
        }
    }

    function compact_view($ticket_id = 0) {
        validate_numeric_value($ticket_id);
        if ($this->login_user->user_type === "client") {
            app_redirect("tickets/view/$ticket_id");
        }
        return $this->index("", "", "", $ticket_id);
    }

    private function _get_assiged_to_dropdown() {
        $assigned_to_dropdown = array(array("id" => "", "text" => "- " . app_lang("assigned_to") . " -"));

        $assigned_to_list = $this->Users_model->get_dropdown_list(array("first_name", "last_name"), "id", array("deleted" => 0, "user_type" => "staff", "status" => "active"));
        foreach ($assigned_to_list as $key => $value) {
            $assigned_to_dropdown[] = array("id" => $key, "text" => $value);
        }
        return $assigned_to_dropdown;
    }

    //load new tickt modal 
    function modal_form() {
        $this->validate_submitted_data(array(
            "id" => "numeric",
            "project_id" => "numeric"
        ));

        $id = $this->request->getPost('id');
        $this->validate_ticket_access($id);

        //client should not be able to edit ticket
        if ($this->login_user->user_type === "client" && $id) {
            app_redirect("forbidden");
        }

        $where = array();
        if ($this->login_user->user_type === "staff" && $this->access_type !== "all" && $this->access_type !== "assigned_only") {
            $where = array("where_in" => array("id" => $this->allowed_ticket_types));
        }

        $ticket_info = $this->Tickets_model->get_one($this->request->getPost("id"));

        $projects = $this->Projects_model->get_dropdown_list(array("title"), "id", array("client_id" => $ticket_info->client_id, "project_type" => "client_project"));
        if ($this->login_user->user_type == "client") {
            $projects = $this->Projects_model->get_dropdown_list(array("title"), "id", array("client_id" => $this->login_user->client_id, "project_type" => "client_project"));
            $ticket_info->client_id = $this->login_user->client_id;
        }
        $suggestion = array(array("id" => "", "text" => "-"));
        foreach ($projects as $key => $value) {
            $suggestion[] = array("id" => $key, "text" => $value);
        }

        $model_info = $this->Tickets_model->get_one($id);
        $project_id = $this->request->getPost('project_id');

        //here has a project id. now set the client from the project
        if ($project_id) {
            $client_id = $this->Projects_model->get_one($project_id)->client_id;
            $model_info->client_id = $client_id;

            $view_data['requested_by_dropdown'] = array("" => "-") + $this->Users_model->get_dropdown_list(array("first_name", "last_name"), "id", array("deleted" => 0, "client_id" => $client_id));
        } else {
            $requested_by_suggestion = array(array("id" => "", "text" => "-"));
            $view_data['requested_by_dropdown'] = $requested_by_suggestion;
        }

        $view_data['projects_suggestion'] = $suggestion;

        $view_data['ticket_types_dropdown'] = $this->Ticket_types_model->get_dropdown_list(array("title"), "id", $where);

        $view_data['model_info'] = $model_info;
        $view_data['client_id'] = $ticket_info->client_id;
        $view_data['clients_dropdown'] = array("" => "-") + $this->Clients_model->get_dropdown_list(array("company_name"), "id", array("is_lead" => 0));
        $view_data['show_project_reference'] = get_setting('project_reference_in_tickets');

        $view_data['project_id'] = $this->request->getPost('project_id');

        $view_data['requested_by_id'] = $ticket_info->requested_by;

        if ($this->login_user->user_type == "client") {
            $view_data['project_id'] = $this->request->getPost('project_id');
        } else {
            $view_data['projects_dropdown'] = $this->Projects_model->get_dropdown_list(array("title"), "id", array("project_type" => "client_project"));
        }

        //prepare assign to list
        $assigned_to_dropdown = array("" => "-") + $this->Users_model->get_dropdown_list(array("first_name", "last_name"), "id", array("deleted" => 0, "user_type" => "staff", "status" => "active"));
        $view_data['assigned_to_dropdown'] = $assigned_to_dropdown;

        //prepare label suggestions
        $view_data['label_suggestions'] = $this->make_labels_dropdown("ticket", $view_data['model_info']->labels);

        $view_data["custom_fields"] = $this->Custom_fields_model->get_combined_details("tickets", $view_data['model_info']->id, $this->login_user->is_admin, $this->login_user->user_type)->getResult();

        return $this->template->view('tickets/modal_form', $view_data);
    }

    //get project suggestion against client
    function get_project_suggestion($client_id = 0) {
        validate_numeric_value($client_id);
        $this->access_only_allowed_members();

        $projects = $this->Projects_model->get_dropdown_list(array("title"), "id", array("client_id" => $client_id, "project_type" => "client_project"));
        $suggestion = array(array("id" => "", "text" => "-"));
        foreach ($projects as $key => $value) {
            $suggestion[] = array("id" => $key, "text" => $value);
        }
        echo json_encode($suggestion);
    }

    // add a new ticket
    function save() {
        $validation_array = array(
            "id" => "numeric",
            "client_id" => "numeric",
            "assigned_to" => "numeric",
            "requested_by_id" => "numeric",
            "ticket_type_id" => "required|numeric"
        );

        $id = $this->request->getPost('id');
        if (!$id) {
            $validation_array["client_id"] = "required|numeric";
        }

        $this->validate_submitted_data($validation_array);
        $this->validate_ticket_access($id);

        $client_id = $this->request->getPost('client_id');

        $this->access_only_allowed_members_or_client_contact($client_id);

        $ticket_type_id = $this->request->getPost('ticket_type_id');
        $assigned_to = $this->request->getPost('assigned_to');

        $requested_by = $this->request->getPost('requested_by_id');

        //if this logged in user is a client then overwrite the client id
        if ($this->login_user->user_type === "client") {
            $client_id = $this->login_user->client_id;
            $assigned_to = 0;
        }

        //if this logged in user is a team member and there has a requested_by client contact, change the created_by field also
        $created_by = $this->login_user->id;
        if ($this->login_user->user_type === "staff" && $requested_by) {
            $created_by = $requested_by;
        }

        $now = get_current_utc_time();

        $labels = $this->request->getPost('labels');
        validate_list_of_numbers($labels);

        $ticket_data = array(
            "title" => $this->request->getPost('title'),
            "client_id" => $client_id,
            "project_id" => $this->request->getPost('project_id') ? $this->request->getPost('project_id') : 0,
            "ticket_type_id" => $ticket_type_id,
            "created_by" => $created_by,
            "created_at" => $now,
            "last_activity_at" => $now,
            "labels" => $labels,
            "assigned_to" => $assigned_to ? $assigned_to : 0,
            "requested_by" => $requested_by ? $requested_by : 0
        );

        if (!$id) {
            $ticket_data["creator_name"] = "";
            $ticket_data["creator_email"] = "";
        }

        $ticket_data = clean_data($ticket_data);

        if ($id) {
            //client can't update ticket
            if ($this->login_user->user_type === "client") {
                app_redirect("forbidden");
            }

            //remove not updateable fields
            unset($ticket_data['client_id']);
            unset($ticket_data['created_by']);
            unset($ticket_data['created_at']);
            unset($ticket_data['last_activity_at']);
        }


        $ticket_id = $this->Tickets_model->ci_save($ticket_data, $id);

        $target_path = get_setting("timeline_file_path");
        $files_data = move_files_from_temp_dir_to_permanent_dir($target_path, "ticket");

        if ($ticket_id) {

            save_custom_fields("tickets", $ticket_id, $this->login_user->is_admin, $this->login_user->user_type);

            //ticket added. now add a comment in this ticket
            if (!$id) {
                $description = decode_ajax_post_data($this->request->getPost('description'));

                $comment_data = array(
                    "description" => $description,
                    "ticket_id" => $ticket_id,
                    "created_by" => $this->login_user->id,
                    "created_at" => $now
                );

                $comment_data = clean_data($comment_data);

                $comment_data["files"] = $files_data; //don't clean serilized data

                $ticket_comment_id = $this->Ticket_comments_model->ci_save($comment_data);

                if ($ticket_comment_id) {
                    log_notification("ticket_created", array("ticket_id" => $ticket_id, "ticket_comment_id" => $ticket_comment_id));
                }

                if ($this->login_user->user_type !== "staff") {
                    //don't add auto reply if it's created by team members
                    add_auto_reply_to_ticket($ticket_id);
                }
            } else if ($assigned_to) {
                log_notification("ticket_assigned", array("ticket_id" => $ticket_id, "to_user_id" => $assigned_to));
            }

            echo json_encode(array("success" => true, "id" => $ticket_id, 'message' => app_lang('record_saved')));
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('error_occurred')));
        }
    }


    // list of tickets, prepared for datatable 
    function list_data($is_widget = 0, $is_mobile = 0) {
        $this->access_only_allowed_members();

        validate_numeric_value($is_widget);
        validate_numeric_value($is_mobile);

        $custom_fields = $this->Custom_fields_model->get_available_fields_for_table("tickets", $this->login_user->is_admin, $this->login_user->user_type);

        $status = $this->request->getPost("status");
        if ($status && is_array($status)) {
            $status =  implode(",", $status);
        } else if (!$status) {
            $status =  "";
        }

        $ticket_label = $this->request->getPost("ticket_label");
        $assigned_to = get_only_numeric_value($this->request->getPost("assigned_to"));
        $ticket_type_id = get_only_numeric_value($this->request->getPost('ticket_type_id'));
        $client_id = get_only_numeric_value($this->request->getPost('client_id'));
        $id = get_only_numeric_value($this->request->getPost('id'));

        $options = array(
            "id" => $id,
            "statuses" => $status,
            "ticket_types" => $this->allowed_ticket_types,
            "ticket_label" => $ticket_label,
            "assigned_to" => $assigned_to,
            "custom_fields" => $custom_fields,
            "created_at" => $this->request->getPost('created_at'),
            "ticket_type_id" => $ticket_type_id,
            "show_assigned_tickets_only_user_id" => $this->show_assigned_tickets_only_user_id(),
            "client_id" => $client_id,
            "custom_field_filter" => $this->prepare_custom_field_filter_values("tickets", $this->login_user->is_admin, $this->login_user->user_type)
        );

        if ($is_widget) {
            $options = array(
                "status" => "open",
                "ticket_types" => $this->allowed_ticket_types,
                "custom_fields" => $custom_fields
            );
        }

        $all_options = append_server_side_filtering_commmon_params($options);

        $result = $this->Tickets_model->get_details($all_options);

        //by this, we can handel the server side or client side from the app table prams.
        if (get_array_value($all_options, "server_side")) {
            $list_data = get_array_value($result, "data");
        } else {
            $list_data = $result->getResult();
            $result = array();
        }

        $result_data = array();
        foreach ($list_data as $data) {
            $result_data[] = $this->_make_row($data, $custom_fields, $is_mobile);
        }

        $result["data"] = $result_data;

        echo json_encode($result);
    }

    // list of tickets of a specific client, prepared for datatable 
    function ticket_list_data_of_client($client_id, $is_widget = 0) {
        validate_numeric_value($client_id);
        $this->access_only_allowed_members_or_client_contact($client_id);

        $custom_fields = $this->Custom_fields_model->get_available_fields_for_table("tickets", $this->login_user->is_admin, $this->login_user->user_type);

        $options = array(
            "client_id" => $client_id,
            "access_type" => $this->access_type,
            "show_assigned_tickets_only_user_id" => $this->show_assigned_tickets_only_user_id(),
            "custom_fields" => $custom_fields,
            "status" => $this->request->getPost('status'),
            "custom_field_filter" => $this->prepare_custom_field_filter_values("tickets", $this->login_user->is_admin, $this->login_user->user_type)
        );

        if ($is_widget) {
            $options = array(
                "client_id" => $client_id,
                "access_type" => $this->access_type,
                "status" => "open",
                "custom_fields" => $custom_fields
            );
        }

        $list_data = $this->Tickets_model->get_details($options)->getResult();
        $result = array();
        foreach ($list_data as $data) {
            $result[] = $this->_make_row($data, $custom_fields);
        }
        echo json_encode(array("data" => $result));
    }

    // return a row of ticket list table 
    private function _row_data($id, $is_mobile = 0) {
        $custom_fields = $this->Custom_fields_model->get_available_fields_for_table("tickets", $this->login_user->is_admin, $this->login_user->user_type);

        $options = array(
            "id" => $id,
            "access_type" => $this->access_type,
            "show_assigned_tickets_only_user_id" => $this->show_assigned_tickets_only_user_id(),
            "custom_fields" => $custom_fields
        );

        $data = $this->Tickets_model->get_details($options)->getRow();

        if ($data) {
            return $this->_make_row($data, $custom_fields, $is_mobile);
        } else {
            return json_encode(array());
        }
    }

    //prepare a row of ticket list table
    private function _make_row($data, $custom_fields, $is_mobile = 0) {
        $ticket_status_class = "bg-danger";
        if ($data->status === "new" || $data->status === "client_replied") {
            $ticket_status_class = "bg-warning";
        } else if ($data->status === "closed") {
            $ticket_status_class = "bg-success";
        }

        if ($data->status === "client_replied" && $this->login_user->user_type === "client") {
            $data->status = "open"; //don't show client_replied status to client
            $ticket_status_class = "bg-danger";
        }

        $ticket_status = "<span class='badge $ticket_status_class'>" . app_lang($data->status) . "</span> ";

        $company_name = $data->company_name ? $data->company_name : ($data->creator_name . " [" . app_lang("unknown_client") . "]");

        if ($is_mobile) {
            $avatar_url = get_avatar();
            $requested_by_name = $company_name;
            if ($data->requested_by) {
                $avatar_url = get_avatar($data->requested_by_avatar);
                $requested_by_name = $data->requested_by_name;
            }

            $avatar = "<span class='avatar avatar-xs'><img src='$avatar_url' alt='...'></span>";

            $title = "<div class='text-default'><span>" . $requested_by_name . "</span>
            <small class='text-off float-end'>" . format_to_relative_time($data->last_activity_at, true, true) . "</small>
            <div class='text-truncate max-w250'>" . $data->title . "</div>
            <div class='text-truncate'>" . "" . "</div>
            </div>";

            $link = js_anchor($title, array("class" => "box-label", "data-action-url" => get_uri("tickets/view/" . $data->id), "data-action" => "load_compact_view",  "data-compact_view_id" => $data->id));


            $title = "<div class='box-wrapper'>
                <div class='box-avatar hover'>" . $avatar . "</div>" .
                $link .
                "</div>";
        } else {
            $title = anchor(get_uri("tickets/view/" . $data->id), $data->title);
        }

        //show labels field to team members only
        $labels = "";
        $ticket_labels = make_labels_view_data($data->labels_list, true);
        if ($ticket_labels) {
            $labels = "<span>" . $ticket_labels . "</span>";
        }

        //show assign to field to team members only
        $assigned_to = "-";
        if ($data->assigned_to && $this->login_user->user_type == "staff") {
            $image_url = get_avatar($data->assigned_to_avatar);
            $assigned_to_user = "<span class='avatar avatar-xs mr10'><img src='$image_url' alt='...'></span> $data->assigned_to_user";
            $assigned_to = get_team_member_profile_link($data->assigned_to, $assigned_to_user);
        }

        $status_color = "#FFC007";
        if ($data->status == "open") {
            $status_color = "#F4325B";
        } else if ($data->status == "closed") {
            $status_color = "#485ABD";
        }

        $row_data = array(
            $status_color,
            $data->id,
            anchor(get_uri("tickets/view/" . $data->id), get_ticket_id($data->id), array("class" => "js-selection-id", "data-id" => $data->id, "title" => "")),
            $title,
            $data->company_name ? anchor(get_uri("clients/view/" . $data->client_id), $data->company_name) : ($data->creator_name . " [" . app_lang("unknown_client") . "]"),
            $data->project_title ? anchor(get_uri("projects/view/" . $data->project_id), $data->project_title) : "-",
            $data->ticket_type ? $data->ticket_type : "-",
            $labels,
            $assigned_to,
            $data->last_activity_at,
            format_to_relative_time($data->last_activity_at, true, false, true),
            $ticket_status
        );

        foreach ($custom_fields as $field) {
            $cf_id = "cfv_" . $field->id;
            $row_data[] = $this->template->view("custom_fields/output_" . $field->field_type, array("value" => $data->$cf_id));
        }

        if ($this->login_user->user_type == "staff") {
            $edit = '<li role="presentation">' . modal_anchor(get_uri("tickets/modal_form"), "<i data-feather='edit' class='icon-16'></i> " . app_lang('edit'), array("title" => app_lang('edit'), "data-post-view" => "details", "data-post-id" => $data->id, "class" => "dropdown-item")) . '</li>';

            //show option to close/open the tickets
            $status = "";
            if ($data->status === "closed") {
                $status = '<li role="presentation">' . js_anchor("<i data-feather='check-circle' class='icon-16'></i> " . app_lang('mark_as_open'), array('title' => app_lang('mark_as_open'), "class" => "dropdown-item", "data-action-url" => get_uri("tickets/save_ticket_status/$data->id/open"), "data-action" => "update")) . '</li>';
            } else {
                $status = '<li role="presentation">' . js_anchor("<i data-feather='check-circle' class='icon-16'></i> " . app_lang('mark_as_closed'), array('title' => app_lang('mark_as_closed'), "class" => "dropdown-item", "data-action-url" => get_uri("tickets/save_ticket_status/$data->id/closed"), "data-action" => "update")) . '</li>';
            }

            $assigned_to = "";
            if ($data->assigned_to === "0") {
                $assigned_to = '<li role="presentation">' . js_anchor("<i data-feather='user' class='icon-16'></i> " . app_lang('assign_to_me'), array('title' => app_lang('assign_myself_in_this_ticket'), "data-action-url" => get_uri("tickets/assign_to_me/$data->id"), "data-action" => "update", "class" => "dropdown-item")) . '</li>';
            }


            //show the delete menu if user has access to delete the tickets
            $delete_ticket = "";
            if ($this->can_delete_tickets()) {
                $delete_ticket = '<li role="presentation">' . js_anchor("<i data-feather='x' class='icon-16'></i>" . app_lang('delete'), array('title' => app_lang('delete'), "class" => "delete dropdown-item", "data-id" => $data->id, "data-action-url" => get_uri("tickets/delete"), "data-action" => "delete-confirmation")) . '</li>';
            }

            $actions = '
                        <span class="dropdown inline-block">
                            <button class="action-option dropdown-toggle mt0 mb0" type="button" data-bs-toggle="dropdown" aria-expanded="true" data-bs-display="static">
                                <i data-feather="more-horizontal" class="icon-16"></i>
                            </button>
                            <ul class="dropdown-menu dropdown-menu-end" role="menu">' . $edit . $status . $assigned_to . $delete_ticket . '</ul>
                        </span>';

            $modal_view = "";
            if (!$is_mobile) {
                $modal_view =  anchor(get_uri("tickets/compact_view/" . $data->id), "<i data-feather='sidebar' class='icon-16'></i>", array("title" => "", "class" => "action-option",));
            }

            $row_data[] = $modal_view . $actions;
        }

        return $row_data;
    }

    // load ticket details view 
    function view($ticket_id = 0) {

        validate_numeric_value($ticket_id);
        if (!$ticket_id) {
            $ticket_id = $this->request->getPost('id');
        }

        $view_type = $this->request->getPost('view_type');

        if ($ticket_id) {
            $this->validate_ticket_access($ticket_id);

            $sort_as_decending = get_setting("show_recent_ticket_comments_at_the_top");

            $options = array("id" => $ticket_id);
            $options["ticket_types"] = $this->allowed_ticket_types;

            $view_data["can_create_tasks"] = false;

            $ticket_info = $this->Tickets_model->get_details($options)->getRow();

            if ($ticket_info) {
                $this->access_only_allowed_members_or_client_contact($ticket_info->client_id);

                $view_data['ticket_info'] = $ticket_info;
                $view_data["view_type"] = $view_type;

                $view_data["show_project_reference"] = get_setting('project_reference_in_tickets');

                $view_data['custom_fields_list'] = $this->Custom_fields_model->get_combined_details("tickets", $ticket_info->id, $this->login_user->is_admin, $this->login_user->user_type)->getResult();

                $can_edit_ticket = false;
                if ($this->login_user->user_type != "client" && $this->can_access_tickets($ticket_id)) {
                    $can_edit_ticket = true;
                }
                $view_data['can_edit_ticket'] = $can_edit_ticket;

                $view_data['ticket_labels'] = make_labels_view_data($ticket_info->labels_list, false, true, "rounded-pill");

                $options = array("status" => "active", "user_type" => "staff");
                $users = $this->Users_model->get_details($options)->getResult();

                $assign_to_dropdown = array(array("id" => "", "text" => "-"));
                foreach ($users as $user) {
                    $assign_to_dropdown[] = array("id" => $user->id, "text" => $user->first_name . " " . $user->last_name);
                }

                //get labels suggestion
                $view_data['label_suggestions'] = $this->make_labels_dropdown("ticket", "");
                //get assign to dropdown
                $view_data['assign_to_dropdown'] = $assign_to_dropdown;

                $view_data["can_create_client"] = false;
                if ($this->login_user->is_admin || (get_array_value($this->login_user->permissions, "client") == "all")) {
                    $view_data["can_create_client"] = true;
                }

                //Don't load all data if view type is ticket meta
                if ($view_type != "ticket_meta") {

                    //For project related tickets, check task cration permission for the project
                    if ($ticket_info->project_id) {
                        $this->init_project_permission_checker($ticket_info->project_id);
                        $view_data["can_create_tasks"] = true; //since the user has permission to manage the tickets.
                    }

                    $comments_options = array(
                        "ticket_id" => $ticket_id,
                        "sort_as_decending" => $sort_as_decending,
                        "login_user_id" => $this->login_user->id
                    );

                    if ($this->login_user->user_type === "client") {
                        $comments_options["is_note"] = 0;
                    }

                    $view_data["sort_as_decending"] = $sort_as_decending;

                    $view_data['comments'] = $this->Ticket_comments_model->get_details($comments_options)->getResult();
                    $view_data['pinned_comments'] = $this->Pin_comments_model->get_details(array("ticket_id" => $ticket_id, "pinned_by" => $this->login_user->id))->getResult();

                    $view_data["custom_field_headers_of_task"] = $this->Custom_fields_model->get_custom_field_headers_for_table("tasks", $this->login_user->is_admin, $this->login_user->user_type);
                }

                if ($view_type == "modal_view") {
                    return $this->template->view("tickets/view", $view_data);
                } else if ($view_type == "compact_view") {
                    echo json_encode(array(
                        "success" => true,
                        "content" => $this->template->view("tickets/view",  $view_data)
                    ));
                } else if ($view_type == "inline_view") {
                    return $this->template->view("tickets/view", $view_data);
                } else if ($view_type == "ticket_meta") {

                    echo json_encode(array(
                        "success" => true,
                        "top_bar" => $this->template->view("tickets/top_bar",  $view_data),
                        "ticket_info" => $this->template->view("tickets/ticket_info",  $view_data),
                    ));
                } else {
                    return $this->template->rander("tickets/view", $view_data);
                }
            } else {
                show_404();
            }
        }
    }

    //delete ticket and sub comments

    function delete() {

        if (!$this->can_delete_tickets()) {
            app_redirect("forbidden");
        }

        $id = $this->request->getPost('id');
        $this->validate_ticket_access($id);

        $this->validate_submitted_data(array(
            "id" => "required|numeric"
        ));

        if ($this->Tickets_model->delete_ticket_and_sub_items($id)) {
            echo json_encode(array("success" => true, 'message' => app_lang('record_deleted')));
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('record_cannot_be_deleted')));
        }
    }

    function save_comment() {

        $this->validate_submitted_data(array(
            "ticket_id" => "required|numeric"
        ));

        $ticket_id = $this->request->getPost('ticket_id');
        $description = decode_ajax_post_data($this->request->getPost('description'));
        $now = get_current_utc_time();
        $this->validate_ticket_access($ticket_id);

        $target_path = get_setting("timeline_file_path");
        $files_data = move_files_from_temp_dir_to_permanent_dir($target_path, "ticket");
        $is_note = $this->request->getPost('is_note');

        $comment_data = array(
            "description" => $description,
            "ticket_id" => $ticket_id,
            "created_by" => $this->login_user->id,
            "created_at" => $now,
            "files" => $files_data,
            "is_note" => $is_note ? $is_note : 0
        );


        $comment_data = clean_data($comment_data);
        $comment_data["files"] = $files_data; //don't clean serialized data

        if (!$description && $files_data == "a:0:{}") {
            echo json_encode(array("success" => true, 'validation_error' => true, 'message' => app_lang("empty_comment_cannot_be_saved")));
            exit();
        }

        $comment_id = $this->Ticket_comments_model->ci_save($comment_data);
        if ($comment_id) {

            //update ticket status and last activity if it's not a note
            if (!$is_note) {
                if ($this->login_user->user_type === "client") {
                    $ticket_data = array(
                        "status" => "client_replied",
                        "last_activity_at" => $now
                    );
                } else {
                    $ticket_data = array(
                        "status" => "open",
                        "last_activity_at" => $now
                    );
                }

                $ticket_data = clean_data($ticket_data);

                $this->Tickets_model->ci_save($ticket_data, $ticket_id);
            }

            $comments_options = array("id" => $comment_id, "login_user_id" => $this->login_user->id);
            $view_data['comment'] = $this->Ticket_comments_model->get_details($comments_options)->getRow();
            $comment_view = $this->template->view("tickets/comment_row", $view_data);
            echo json_encode(array("success" => true, "data" => $comment_view, 'message' => app_lang('comment_submited')));

            if (!$is_note) {
                log_notification("ticket_commented", array("ticket_id" => $ticket_id, "ticket_comment_id" => $comment_id));
            }
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('error_occurred')));
        }
    }

    function save_ticket_status($ticket_id = 0, $status = "closed") {
        validate_numeric_value($ticket_id);
        if ($ticket_id) {
            $this->validate_ticket_access($ticket_id);

            $data = array(
                "status" => $status
            );

            $save_id = $this->Tickets_model->ci_save($data, $ticket_id);
            if ($save_id) {
                if ($status == "open") {
                    log_notification("ticket_reopened", array("ticket_id" => $ticket_id));
                } else if ($status == "closed") {
                    log_notification("ticket_closed", array("ticket_id" => $ticket_id));

                    //save closing time
                    $closed_data = array("closed_at" => get_current_utc_time());
                    $this->Tickets_model->ci_save($closed_data, $ticket_id);
                }

                echo json_encode(array("success" => true, "id" => $ticket_id, "message" => ($status == "closed") ? app_lang('ticket_closed') : app_lang('ticket_reopened')));
            } else {
                echo json_encode(array("success" => false, app_lang('error_occurred')));
            }
        }
    }

    /* download files by zip */

    function download_comment_files($id) {
        validate_numeric_value($id);
        $files = $this->Ticket_comments_model->get_one($id)->files;
        return $this->download_app_files(get_setting("timeline_file_path"), $files);
    }

    function assign_to_me($ticket_id = 0) {
        if ($ticket_id) {
            validate_numeric_value($ticket_id);

            $this->validate_ticket_access($ticket_id);

            $data = array(
                "assigned_to" => $this->login_user->id
            );

            $save_id = $this->Tickets_model->ci_save($data, $ticket_id);
            if ($save_id) {
                echo json_encode(array("success" => true, "data" => $this->_row_data($ticket_id), "id" => $ticket_id, "message" => app_lang("record_saved")));
            } else {
                echo json_encode(array("success" => false, app_lang('error_occurred')));
            }
        }
    }

    //load the ticket templates view of ticket template list
    function ticket_templates() {
        $this->access_only_team_members();
        return $this->template->rander("tickets/templates/index");
    }

    private function can_view_ticket_template($id = 0) {
        if ($id) {
            $template_info = $this->Ticket_templates_model->get_one($id);
            if ($template_info->private && $template_info->created_by !== $this->login_user->id) {
                app_redirect("forbidden");
            }
        }
    }

    private function can_edit_ticket_template($id = 0) {
        if ($id) {
            $template_info = $this->Ticket_templates_model->get_one($id);
            //admin could modify all public templates
            //team member could modify only own templates
            if ($this->login_user->is_admin && (!$template_info->private || $template_info->created_by !== $this->login_user->id)) {
                return true;
            } else if ($template_info->created_by == $this->login_user->id) {
                return true;
            } else {
                app_redirect("forbidden");
            }
        }
    }

    //add or edit form of ticket template form
    function ticket_template_modal_form() {
        $this->access_only_team_members();
        $where = array();
        if ($this->login_user->user_type === "staff" && $this->access_type !== "all" && $this->access_type !== "assigned_only") {
            $where = array("where_in" => array("id" => $this->allowed_ticket_types));
        }

        $view_data['ticket_types_dropdown'] = array("" => "-") + $this->Ticket_types_model->get_dropdown_list(array("title"), "id", $where);

        $this->validate_submitted_data(array(
            "id" => "numeric"
        ));

        $id = $this->request->getPost('id');
        $this->can_edit_ticket_template($id);

        $view_data['model_info'] = $this->Ticket_templates_model->get_one($id);

        return $this->template->view('tickets/templates/modal_form', $view_data);
    }

    // add a new ticket template
    function save_ticket_template() {
        $this->access_only_team_members();
        $this->validate_submitted_data(array(
            "id" => "numeric",
            "title" => "required",
            "description" => "required"
        ));

        $id = $this->request->getPost('id');
        $this->can_edit_ticket_template($id);

        $private = $this->request->getPost('private');

        if (is_null($private)) {
            $private = "";
        }

        $now = get_current_utc_time();

        $ticket_template_data = array(
            "title" => $this->request->getPost('title'),
            "description" => $this->request->getPost('description'),
            "ticket_type_id" => $this->request->getPost('ticket_type_id') ? $this->request->getPost('ticket_type_id') : 0,
            "private" => $private
        );

        if (!$id) {
            $ticket_template_data["created_by"] = $this->login_user->id;
            $ticket_template_data["created_at"] = $now;
        }

        $save_id = $this->Ticket_templates_model->ci_save($ticket_template_data, $id);

        if ($save_id) {
            echo json_encode(array("success" => true, 'id' => $save_id, "data" => $this->_row_data_for_ticket_templates($save_id), 'message' => app_lang('record_saved')));
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('error_occurred')));
        }
    }

    function delete_ticket_template() {
        $id = $this->request->getPost('id');
        $this->can_edit_ticket_template($id);

        $this->validate_submitted_data(array(
            "id" => "required|numeric"
        ));

        if ($this->Ticket_templates_model->delete($id)) {
            echo json_encode(array("success" => true, 'message' => app_lang('record_deleted')));
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('record_cannot_be_deleted')));
        }
    }

    function ticket_template_list_data($view_type = "", $ticket_type_id = 0) {
        validate_numeric_value($ticket_type_id);
        $options = array("created_by" => $this->login_user->id, "ticket_type_id" => $ticket_type_id);
        if ($this->login_user->user_type === "staff" && $this->access_type !== "all" && $this->access_type !== "assigned_only") {
            $options["allowed_ticket_types"] = $this->allowed_ticket_types;
        }

        $list_data = $this->Ticket_templates_model->get_details($options)->getResult();

        $result = array();
        foreach ($list_data as $data) {
            $result[] = $this->_make_row_for_ticket_templates($data, $view_type);
        }

        echo json_encode(array("data" => $result));
    }

    // return a row of ticket template table 
    private function _row_data_for_ticket_templates($id) {
        $options = array(
            "id" => $id
        );

        $data = $this->Ticket_templates_model->get_details($options)->getRow();
        return $this->_make_row_for_ticket_templates($data);
    }

    private function _make_row_for_ticket_templates($data, $view_type = "") {

        if ($view_type == "modal") {
            $title = $data->title;
            $ticket_type = "";
        } else {
            $title = modal_anchor(get_uri("tickets/ticket_template_view/" . $data->id), $data->title, array("class" => "edit", "title" => app_lang('ticket_template'), "data-post-id" => $data->id));
            $ticket_type = $data->ticket_type ? $data->ticket_type : "-";
        }

        $private = "";
        if ($data->private) {
            $private = app_lang("yes");
        } else {
            $private = app_lang("no");
        }

        //only creator and admin can edit/delete templates
        $actions = modal_anchor(get_uri("tickets/ticket_template_view/" . $data->id), "<i data-feather='cloud-lightning' class='icon-16'></i>", array("class" => "edit", "title" => app_lang('template_details'), "data-modal-title" => app_lang('template'), "data-post-id" => $data->id));
        if ($data->created_by == $this->login_user->id || $this->login_user->is_admin) {
            $actions = modal_anchor(get_uri("tickets/ticket_template_modal_form"), "<i data-feather='edit' class='icon-16'></i>", array("class" => "edit", "title" => app_lang('edit_template'), "data-post-id" => $data->id))
                . js_anchor("<i data-feather='x' class='icon-16'></i>", array('title' => app_lang('delete'), "class" => "delete", "data-id" => $data->id, "data-action-url" => get_uri("tickets/delete_ticket_template"), "data-action" => "delete-confirmation"));
        }

        if ($view_type == "modal") {
            return array(
                "<div class='media-body template-row'>
                        <div class='truncate-ellipsis'>
                            <strong class='truncate-ellipsis'><span>$title</span></strong>
                        </div>
                        <div class='truncate-ellipsis js-description'><span>$data->description</span></div>
                    </div></div>"
            );
        } else {
            return array(
                "<div class='truncate-ellipsis'><span>$title</span></div>",
                "<div class='truncate-ellipsis js-description'><span>$data->description</span></div>",
                $ticket_type,
                $private,
                $actions
            );
        }
    }

    function ticket_template_view($id) {
        validate_numeric_value($id);
        $this->can_view_ticket_template($id);
        $view_data['model_info'] = $this->Ticket_templates_model->get_one($id);

        return $this->template->view('tickets/templates/view', $view_data);
    }

    //show a modal to choose a template for comment a ticket
    function insert_template_modal_form() {
        $this->access_only_team_members();
        $view_data['ticket_type_id'] = $this->request->getPost('ticket_type_id');

        return $this->template->view("tickets/templates/insert_template_modal_form", $view_data);
    }

    //add client when there has unknown client
    function add_client_modal_form($ticket_id = 0) {
        if ($ticket_id) {
            validate_numeric_value($ticket_id);
            $this->access_only_allowed_members();

            $view_data['clients_dropdown'] = array("" => "-") + $this->Clients_model->get_dropdown_list(array("company_name"));
            $view_data['ticket_id'] = $ticket_id;

            return $this->template->view("tickets/add_client_modal_form", $view_data);
        }
    }

    function link_to_client() {
        $this->access_only_allowed_members();

        $this->validate_submitted_data(array(
            "client_id" => "required|numeric",
            "ticket_id" => "required|numeric"
        ));

        $ticket_id = $this->request->getPost("ticket_id");
        $this->validate_ticket_access($ticket_id);

        $data = array("client_id" => $this->request->getPost("client_id"));
        $save_id = $this->Tickets_model->ci_save($data, $ticket_id);

        if ($save_id) {
            echo json_encode(array("success" => true, "message" => app_lang("record_saved")));
        } else {
            echo json_encode(array("success" => false, app_lang('error_occurred')));
        }
    }

    /* load tickets settings modal */

    function settings_modal_form() {
        return $this->template->view('tickets/settings/modal_form');
    }

    /* save tickets settings */

    function save_settings() {
        $settings = array("signature");

        foreach ($settings as $setting) {
            $value = $this->request->getPost($setting);
            if (is_null($value)) {
                $value = "";
            }

            $value = clean_data($value);

            $this->Settings_model->save_setting("user_" . $this->login_user->id . "_" . $setting, $value, "user");
        }

        echo json_encode(array("success" => true, 'message' => app_lang('settings_updated')));
    }

    /* prepare client contact dropdown based on this suggestion */

    function get_client_contact_suggestion($client_id = 0) {
        validate_numeric_value($client_id);
        $this->access_only_allowed_members();

        $clients = $this->Users_model->get_dropdown_list(array("first_name", "last_name"), "id", array("deleted" => 0, "client_id" => $client_id));
        $suggestion = array(array("id" => "", "text" => "-"));
        foreach ($clients as $key => $value) {
            $suggestion[] = array("id" => $key, "text" => $value);
        }
        echo json_encode($suggestion);
    }

    private function _get_ticket_types_dropdown_list_for_filter($ticket_type_id = 0) {

        $where = array();
        if ($this->login_user->user_type === "staff" && $this->access_type !== "all" && $this->access_type !== "assigned_only") {
            $where = array("where_in" => array("id" => $this->allowed_ticket_types));
        }

        $ticket_type = $this->Ticket_types_model->get_dropdown_list(array("title"), "id", $where);
        $ticket_type_dropdown = array(array("id" => "", "text" => "- " . app_lang("ticket_type") . " -"));

        foreach ($ticket_type as $id => $name) {
            $selected_status = false;
            if (isset($ticket_type_id) && $ticket_type_id) {
                if ($id == $ticket_type_id) {
                    $selected_status = true;
                } else {
                    $selected_status = false;
                }
            }

            $ticket_type_dropdown[] = array("id" => $id, "text" => $name, "isSelected" => $selected_status);
        }
        return $ticket_type_dropdown;
    }

    /* list of ticket of a specific project, prepared for datatable  */

    function ticket_list_data_of_project($project_id) {
        validate_numeric_value($project_id);

        $this->validate_ticket_access();

        $custom_fields = $this->Custom_fields_model->get_available_fields_for_table("tickets", $this->login_user->is_admin, $this->login_user->user_type);

        $options = array(
            "project_id" => $project_id,
            "status" => "open",
            "custom_fields" => $custom_fields
        );

        $list_data = $this->Tickets_model->get_details($options)->getResult();
        $result = array();
        foreach ($list_data as $data) {
            $result[] = $this->_make_row($data, $custom_fields);
        }
        echo json_encode(array("data" => $result));
    }

    /* batch update modal form */

    function batch_update_modal_form($ticket_ids = "") {
        $this->access_only_allowed_members();
        $view_data["ticket_ids"] = clean_data($ticket_ids);

        $where = array();
        if ($this->login_user->user_type === "staff" && $this->access_type !== "all" && $this->access_type !== "assigned_only") {
            $where = array("where_in" => array("id" => $this->allowed_ticket_types));
        }
        $view_data['ticket_types_dropdown'] = array("" => "-") + $this->Ticket_types_model->get_dropdown_list(array("title"), "id", $where);

        //prepare assign to list
        $assigned_to_dropdown = array("" => "-") + $this->Users_model->get_dropdown_list(array("first_name", "last_name"), "id", array("deleted" => 0, "user_type" => "staff"));
        $view_data['assigned_to_dropdown'] = $assigned_to_dropdown;

        //prepare label suggestions
        $view_data['label_suggestions'] = $this->make_labels_dropdown("ticket", "");

        return $this->template->view("tickets/batch_update/modal_form", $view_data);
    }

    /* save batch update */

    function save_batch_update() {
        $this->access_only_allowed_members();

        $batch_fields = $this->request->getPost("batch_fields");
        if ($batch_fields) {
            $allowed_fields = array("ticket_type_id", "assigned_to", "labels", "status");

            $fields_array = explode('-', $batch_fields);

            $data = array();
            foreach ($fields_array as $field) {
                if (in_array($field, $allowed_fields)) {

                    $value = $this->request->getPost($field);
                    $data[$field] = $value;

                    if ($field == "labels") {
                        validate_list_of_numbers($value);
                    }
                }
            }

            $data = clean_data($data);

            $ticket_ids = $this->request->getPost("ticket_ids");
            if ($ticket_ids) {
                $tickets_ids_array = explode('-', $ticket_ids);

                foreach ($tickets_ids_array as $id) {
                    validate_numeric_value($id);
                    $this->validate_ticket_access($id);
                    $this->Tickets_model->ci_save($data, $id);
                }

                echo json_encode(array("success" => true, 'message' => app_lang('record_saved')));
            }
        } else {
            echo json_encode(array('success' => false, 'message' => app_lang('no_field_has_selected')));
            return false;
        }
    }

    function delete_comment($id = 0) {
        if (!$id) {
            exit();
        }

        validate_numeric_value($id);

        $comment_info = $this->Ticket_comments_model->get_one($id);

        //client can't delete the comment
        if ($this->login_user->user_type === "client") {
            app_redirect("forbidden");
        }

        //delete the comment and files
        if ($this->Ticket_comments_model->delete($id) && $comment_info->files) {

            //delete the files
            $file_path = get_setting("timeline_file_path");
            $files = unserialize($comment_info->files);

            foreach ($files as $file) {
                delete_app_files($file_path, array($file));
            }
        }
    }

    //load merge tickt modal 
    function merge_ticket_modal_form() {
        $this->validate_submitted_data(array(
            "ticket_id" => "numeric"
        ));

        $ticket_id = $this->request->getPost('ticket_id');
        $this->validate_ticket_access($ticket_id);

        $ticket_info = $this->Tickets_model->get_one($ticket_id);

        $options = $options = array(
            "status" => "open",
            "ticket_types" => $this->allowed_ticket_types,
            "exclude_ticket_id" => $ticket_id
        );

        if (!$ticket_info->client_id) {
            $options["creator_email"] = $ticket_info->creator_email;
        } else {
            $options["client_id"] = $ticket_info->client_id;
        }

        $tickets = $this->Tickets_model->get_details($options)->getResult();

        $ticket_dropdown = array();
        foreach ($tickets as $ticket) {
            $ticket_dropdown[] = array("id" => $ticket->id, "text" => $ticket->title);
        }

        $view_data['tickets_dropdown'] = $ticket_dropdown;
        $view_data['model_info'] = $ticket_info;

        return $this->template->view('tickets/merge_ticket_modal_form', $view_data);
    }

    function save_merge_ticket() {
        $ticket_id = $this->request->getPost('ticket_id');
        $this->validate_ticket_access($ticket_id);

        //client should not be able to merge ticket
        if ($this->login_user->user_type === "client") {
            app_redirect("forbidden");
        }

        $this->validate_submitted_data(array(
            "ticket_id" => "required|numeric",
            "merge_with_ticket_id" => "required|numeric",
        ));

        $merge_with_ticket_id = $this->request->getPost('merge_with_ticket_id');
        $now = get_current_utc_time();
        $ticket_data = array(
            "merged_with_ticket_id" => $ticket_id,
            "last_activity_at" => $now
        );

        $save_id = $this->Tickets_model->ci_save($ticket_data, $merge_with_ticket_id);

        if ($save_id) {
            $comments = $this->Ticket_comments_model->get_all_where(array("ticket_id" => $merge_with_ticket_id))->getResult();
            foreach ($comments as $comment) {
                $comment_data["ticket_id"] = $ticket_id;

                $this->Ticket_comments_model->ci_save($comment_data, $comment->id);
            }

            $merged_ticket_data["status"] = "closed";
            $this->Tickets_model->ci_save($merged_ticket_data, $merge_with_ticket_id);

            echo json_encode(array("success" => true, 'id' => $ticket_id, 'message' => app_lang('record_saved')));
        } else {
            echo json_encode(array("success" => false, 'message' => app_lang('error_occurred')));
        }
    }

    function tickets_chart_report() {
        $this->_validate_tickets_report_access();

        $view_data['ticket_labels_dropdown'] = json_encode($this->make_labels_dropdown("ticket", "", true));
        $view_data['assigned_to_dropdown'] = json_encode($this->_get_assiged_to_dropdown());
        $view_data['ticket_types_dropdown'] = json_encode($this->_get_ticket_types_dropdown_list_for_filter());

        return $this->template->rander("tickets/reports/chart_report_container", $view_data);
    }

    function tickets_chart_report_data() {
        $this->_validate_tickets_report_access();

        $start_date = $this->request->getPost("start_date");
        $options = array(
            "start_date" => $start_date,
            "end_date" => $this->request->getPost("end_date"),
            "ticket_type_id" => $this->request->getPost("ticket_type_id"),
            "assigned_to" => $this->request->getPost("assigned_to"),
            "ticket_label" => $this->request->getPost("ticket_label")
        );

        $view_data["month"] = strtolower(date("F", strtotime($start_date)));
        $days_of_month = date("t", strtotime($start_date));

        $open_data_array = array();
        $closed_data_array = array();
        $labels = array();
        $open_tickets_array = array();
        $closed_tickets_array = array();

        $options["group_by"] = "created_date";
        $options["status"] = "open";
        $open_tickets_list = $this->Tickets_model->get_ticket_statistics($options)->getResult();

        for ($i = 1; $i <= $days_of_month; $i++) {
            $open_tickets_array[$i] = 0;
            $closed_tickets_array[$i] = 0;
        }

        foreach ($open_tickets_list as $value) {
            $open_tickets_array[$value->day * 1] = $value->total ? $value->total : 0;
        }

        foreach ($open_tickets_array as $value) {
            $open_data_array[] = $value;
        }


        $options["group_by"] = "created_date";
        $options["status"] = "closed";
        $closed_tickets_list = $this->Tickets_model->get_ticket_statistics($options)->getResult();

        foreach ($closed_tickets_list as $value) {
            $closed_tickets_array[$value->day * 1] = $value->total ? $value->total : 0;
        }

        foreach ($closed_tickets_array as $value) {
            $closed_data_array[] = $value;
        }


        for ($i = 1; $i <= $days_of_month; $i++) {
            $labels[] = $i;
        }

        $view_data["labels"] = json_encode($labels);
        $view_data["open_data"] = json_encode($open_data_array);
        $view_data["closed_data"] = json_encode($closed_data_array);

        return $this->template->view("tickets/reports/chart_report_view", $view_data);
    }

    private function _get_clients_dropdown($client_id = 0) {
        $clients_dropdown = array(array("id" => "", "text" => "- " . app_lang("client") . " -"));

        $clients_list = $this->Clients_model->get_dropdown_list(array("company_name"), "id", array("is_lead" => 0));
        foreach ($clients_list as $key => $value) {
            $selected_status = false;
            if (isset($client_id) && $client_id) {
                if ($key == $client_id) {
                    $selected_status = true;
                } else {
                    $selected_status = false;
                }
            }

            $clients_dropdown[] = array("id" => $key, "text" => $value, "isSelected" => $selected_status);
        }
        return $clients_dropdown;
    }

    // pin/unpin comments
    function pin_comment($comment_id = 0, $ticket_id = 0) {
        if ($comment_id) {
            validate_numeric_value($comment_id);

            $data = array(
                "ticket_comment_id" => $comment_id,
                "pinned_by" => $this->login_user->id
            );

            $existing = $this->Pin_comments_model->get_one_where(array_merge($data, array("deleted" => 0)));

            $save_id = "";
            if ($existing->id) {
                //pinned already, unpin now
                $save_id = $this->Pin_comments_model->delete($existing->id);
            } else {
                //not pinned, pin now
                $data["created_at"] = get_current_utc_time();
                $save_id = $this->Pin_comments_model->ci_save($data);
            }

            if ($save_id) {
                $pinned_comments = $this->Pin_comments_model->get_details(array("id" => $save_id, "ticket_id" => $ticket_id, "pinned_by" => $this->login_user->id))->getResult();

                $save_data = $this->template->view("lib/pin_comments/comments_list", array("pinned_comments" => $pinned_comments));

                echo json_encode(array("success" => true, "data" => $save_data, "status" => "pinned"));
            } else {
                echo json_encode(array("success" => false));
            }
        }
    }

    function update_ticket_info($id = 0, $data_field = "") {
        if (!$id) {
            return false;
        }

        validate_numeric_value($id);
        $this->validate_ticket_access($id);

        //client should not be able to edit ticket
        if ($this->login_user->user_type === "client" && $id) {
            app_redirect("forbidden");
        }

        $ticket_info = $this->Tickets_model->get_one($id);
        $value = $this->request->getPost('value');

        if ($data_field == "labels") {
            validate_list_of_numbers($value);
            $data = array(
                $data_field => $value
            );
        } else {
            $data = array(
                $data_field => $value
            );
        }

        $data = clean_data($data);

        $save_id = $this->Tickets_model->ci_save($data, $id);
        if (!$save_id) {
            echo json_encode(array("success" => false, app_lang('error_occurred')));
            return false;
        }

        $success_array = array("success" => true, 'id' => $save_id, "message" => app_lang('record_saved'));

        echo json_encode($success_array);
    }
}

/* End of file tickets.php */
/* Location: ./app/controllers/tickets.php */